2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 Bell Canada.
4 * Modifications Copyright © 2019 IBM.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org.onap.ccsdk.cds.controllerblueprints.core.utils
21 import kotlinx.coroutines.runBlocking
22 import org.apache.commons.io.FileUtils
23 import org.apache.commons.lang3.StringUtils
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.ImportDefinition
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
29 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
30 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
31 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
32 import org.slf4j.LoggerFactory
34 import java.io.FileFilter
35 import java.io.FileNotFoundException
37 import java.net.URLClassLoader
38 import java.nio.file.Files
39 import java.nio.file.NotDirectoryException
40 import java.nio.file.Path
41 import java.nio.file.Paths
42 import java.nio.file.StandardOpenOption
44 class BluePrintFileUtils {
47 const val COMPILED_JAR_SUFFIX = "cba-kts.jar"
49 private val log = LoggerFactory.getLogger(this::class.toString())
51 fun createEmptyBluePrint(basePath: String) {
53 val blueprintDir = File(basePath)
54 FileUtils.deleteDirectory(blueprintDir)
56 Files.createDirectories(blueprintDir.toPath())
58 val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
59 Files.createDirectories(metaDataDir.toPath())
62 blueprintDir.absolutePath.plus(File.separator).plus(
64 .TOSCA_METADATA_ENTRY_DEFINITION_FILE
67 Files.write(metaFile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
69 val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
70 Files.createDirectories(definitionsDir.toPath())
72 val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
73 Files.createDirectories(scriptsDir.toPath())
75 val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
76 Files.createDirectories(plansDir.toPath())
78 val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
79 Files.createDirectories(templatesDir.toPath())
82 fun copyBluePrint(sourcePath: String, targetPath: String) {
83 val sourceFile = File(sourcePath)
84 val targetFile = File(targetPath)
85 sourceFile.copyRecursively(targetFile, true)
88 fun deleteBluePrintTypes(basePath: String) {
89 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
90 log.info("deleting definition types under : $definitionPath")
92 val definitionDir = File(definitionPath)
93 // Find the Type Definitions
94 val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
95 // Delete the Type Files
96 definitionDir.listFiles(fileFilter).forEach {
97 Files.deleteIfExists(it.toPath())
101 fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
103 // Write Blueprint Types
104 writeBluePrintTypes(blueprintContext)
105 // Re Populate the Imports
106 populateDefaultImports(blueprintContext)
107 // Rewrite the Entry Definition Files
108 writeEntryDefinitionFile(blueprintContext)
111 fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
113 val basePath = blueprintContext.rootPath
114 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
115 val definitionDir = File(definitionPath)
117 check(definitionDir.exists()) {
118 throw BluePrintException(
119 ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
120 "path(${definitionDir.absolutePath})"
124 blueprintContext.serviceTemplate.dataTypes?.let {
125 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
126 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
129 blueprintContext.serviceTemplate.relationshipTypes?.let {
130 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
131 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
134 blueprintContext.serviceTemplate.artifactTypes?.let {
135 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
136 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
139 blueprintContext.serviceTemplate.nodeTypes?.let {
140 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
141 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
144 blueprintContext.serviceTemplate.policyTypes?.let {
145 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
146 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
150 private fun populateDefaultImports(blueprintContext: BluePrintContext) {
151 // Get the Default Types
152 val types = arrayListOf(
153 BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_RELATIONSHIP_TYPES,
154 BluePrintConstants.PATH_ARTIFACT_TYPES, BluePrintConstants.PATH_NODE_TYPES,
155 BluePrintConstants.PATH_POLICY_TYPES
158 // Clean Type Imports
159 cleanImportTypes(blueprintContext.serviceTemplate)
161 val imports = mutableListOf<ImportDefinition>()
162 types.forEach { typeName ->
163 val import = ImportDefinition()
164 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
168 blueprintContext.serviceTemplate.imports = imports
171 fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
172 // Clean the Type imports
173 val toDeleteTypes = serviceTemplate.imports?.filter {
174 it.file.endsWith("_types.json")
177 if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
178 serviceTemplate.imports?.removeAll(toDeleteTypes)
183 * Re Generate the Blueprint Service Template Definition file based on BluePrint Context.
185 private fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
187 val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
189 val serviceTemplate = blueprintContext.serviceTemplate
191 // Clone the Service Template
192 val writeServiceTemplate = serviceTemplate.clone()
193 writeServiceTemplate.dataTypes = null
194 writeServiceTemplate.artifactTypes = null
195 writeServiceTemplate.policyTypes = null
196 writeServiceTemplate.relationshipTypes = null
197 writeServiceTemplate.nodeTypes = null
199 // Write the Service Template
200 writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
203 fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
204 val definitionFile = File(definitionFileName)
205 // Delete the File If exists
206 Files.deleteIfExists(definitionFile.toPath())
208 Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
209 check(definitionFile.exists()) {
210 throw BluePrintException(
211 ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write definition file under " +
212 "path(${definitionFile.absolutePath})"
217 private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
218 val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
220 Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
221 check(typeFile.exists()) {
222 throw BluePrintException(
223 ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write $type.json file under " +
224 "path(${typeFile.absolutePath})"
229 private fun getMetaDataContent(): String {
230 return "TOSCA-Meta-File-Version: 1.0.0" +
231 "\nCSAR-Version: <VERSION>" +
232 "\nCreated-By: <AUTHOR NAME>" +
233 "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
234 "\nTemplate-Name: <BLUEPRINT_NAME>" +
235 "\nTemplate-Version: <BLUEPRINT_VERSION>" +
236 "\nTemplate-Type: <BLUEPRINT_TYPE>" +
237 "\nTemplate-Tags: <TAGS>"
240 fun getBluePrintFile(fileName: String, targetPath: Path): File {
241 val filePath = targetPath.resolve(fileName).toString()
242 val file = File(filePath)
243 check(file.exists()) {
244 throw BluePrintException(
245 ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
246 "path(${file.absolutePath})"
252 fun getCbaStorageDirectory(path: String): Path {
253 check(StringUtils.isNotBlank(path)) {
254 throw BluePrintException(
255 ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get " +
256 "Blueprint folder under path($path)"
260 val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
262 if (!Files.exists(fileStorageLocation))
263 Files.createDirectories(fileStorageLocation)
265 return fileStorageLocation
268 fun compileCacheKey(basePath: String): String {
269 return normalizedPathName(basePath)
272 private fun compileJarFileName(artifactName: String, artifactVersion: String): String {
273 return "$artifactName-$artifactVersion-$COMPILED_JAR_SUFFIX"
276 fun compileJarFilePathName(basePath: String, artifactName: String, artifactVersion: String): String {
277 return normalizedPathName(
278 basePath, BluePrintConstants.TOSCA_SCRIPTS_KOTLIN_DIR,
279 compileJarFileName(artifactName, artifactVersion)
283 fun compileJarFile(basePath: String, artifactName: String, artifactVersion: String): File {
284 return normalizedFile(
285 compileJarFilePathName(
287 artifactName, artifactVersion
292 fun stripFileExtension(fileName: String): String {
293 val dotIndexe = fileName.lastIndexOf('.')
295 // In case dot is in first position, we are dealing with a hidden file rather than an extension
296 return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName
299 fun getURLClassLoaderFromDirectory(directory: File): URLClassLoader {
300 if (!directory.exists()) {
301 throw FileNotFoundException(directory.absolutePath)
302 } else if (!directory.isDirectory) {
303 throw NotDirectoryException(directory.absolutePath)
306 val urls = arrayListOf<URL>()
307 directory.walkTopDown()
308 .filter { it.name.endsWith(COMPILED_JAR_SUFFIX) }
310 log.debug("Adding (${it.absolutePath}) to classLoader (${directory.absolutePath})")
312 urls.add(it.toURI().toURL())
314 return URLClassLoader(urls.toTypedArray(), this.javaClass.classLoader)
317 fun getURLClassLoaderFromDirectory(path: String): URLClassLoader {
318 val directory = normalizedFile(path)
319 return getURLClassLoaderFromDirectory(directory)