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,
120 "couldn't get definition file under " +
121 "path(${definitionDir.absolutePath})"
125 blueprintContext.serviceTemplate.dataTypes?.let {
126 val dataTypesContent = JacksonUtils.getWrappedJson(BlueprintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
127 writeTypeFile(definitionDir.absolutePath, BlueprintConstants.PATH_DATA_TYPES, dataTypesContent)
130 blueprintContext.serviceTemplate.relationshipTypes?.let {
131 val nodeTypesContent = JacksonUtils.getWrappedJson(BlueprintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
132 writeTypeFile(definitionDir.absolutePath, BlueprintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
135 blueprintContext.serviceTemplate.artifactTypes?.let {
136 val artifactTypesContent = JacksonUtils.getWrappedJson(BlueprintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
137 writeTypeFile(definitionDir.absolutePath, BlueprintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
140 blueprintContext.serviceTemplate.nodeTypes?.let {
141 val nodeTypesContent = JacksonUtils.getWrappedJson(BlueprintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
142 writeTypeFile(definitionDir.absolutePath, BlueprintConstants.PATH_NODE_TYPES, nodeTypesContent)
145 blueprintContext.serviceTemplate.policyTypes?.let {
146 val nodeTypesContent = JacksonUtils.getWrappedJson(BlueprintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
147 writeTypeFile(definitionDir.absolutePath, BlueprintConstants.PATH_POLICY_TYPES, nodeTypesContent)
151 private fun populateDefaultImports(blueprintContext: BlueprintContext) {
152 // Get the Default Types
153 val types = arrayListOf(
154 BlueprintConstants.PATH_DATA_TYPES, BlueprintConstants.PATH_RELATIONSHIP_TYPES,
155 BlueprintConstants.PATH_ARTIFACT_TYPES, BlueprintConstants.PATH_NODE_TYPES,
156 BlueprintConstants.PATH_POLICY_TYPES
159 // Clean Type Imports
160 cleanImportTypes(blueprintContext.serviceTemplate)
162 val imports = mutableListOf<ImportDefinition>()
163 types.forEach { typeName ->
164 val import = ImportDefinition()
165 import.file = BlueprintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
169 blueprintContext.serviceTemplate.imports = imports
172 fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
173 // Clean the Type imports
174 val toDeleteTypes = serviceTemplate.imports?.filter {
175 it.file.endsWith("_types.json")
178 if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
179 serviceTemplate.imports?.removeAll(toDeleteTypes)
184 * Re Generate the Blueprint Service Template Definition file based on Blueprint Context.
186 private fun writeEntryDefinitionFile(blueprintContext: BlueprintContext) {
188 val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
190 val serviceTemplate = blueprintContext.serviceTemplate
192 // Clone the Service Template
193 val writeServiceTemplate = serviceTemplate.clone()
194 writeServiceTemplate.dataTypes = null
195 writeServiceTemplate.artifactTypes = null
196 writeServiceTemplate.policyTypes = null
197 writeServiceTemplate.relationshipTypes = null
198 writeServiceTemplate.nodeTypes = null
200 // Write the Service Template
201 writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
204 fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
205 val definitionFile = File(definitionFileName)
206 // Delete the File If exists
207 Files.deleteIfExists(definitionFile.toPath())
209 Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
210 check(definitionFile.exists()) {
211 throw BlueprintException(
212 ErrorCode.BLUEPRINT_WRITING_FAIL.value,
213 "couldn't write definition file under " +
214 "path(${definitionFile.absolutePath})"
219 private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
220 val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
222 Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
223 check(typeFile.exists()) {
224 throw BlueprintException(
225 ErrorCode.BLUEPRINT_WRITING_FAIL.value,
226 "couldn't write $type.json file under " +
227 "path(${typeFile.absolutePath})"
232 private fun getMetaDataContent(): String {
233 return "TOSCA-Meta-File-Version: 1.0.0" +
234 "\nCSAR-Version: <VERSION>" +
235 "\nCreated-By: <AUTHOR NAME>" +
236 "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
237 "\nTemplate-Name: <BLUEPRINT_NAME>" +
238 "\nTemplate-Version: <BLUEPRINT_VERSION>" +
239 "\nTemplate-Type: <BLUEPRINT_TYPE>" +
240 "\nTemplate-Tags: <TAGS>"
243 fun getBlueprintFile(fileName: String, targetPath: Path): File {
244 val filePath = targetPath.resolve(fileName).toString()
245 val file = File(filePath)
246 check(file.exists()) {
247 throw BlueprintException(
248 ErrorCode.BLUEPRINT_PATH_MISSING.value,
249 "couldn't get definition file under " +
250 "path(${file.absolutePath})"
256 fun getCbaStorageDirectory(path: String): Path {
257 check(StringUtils.isNotBlank(path)) {
258 throw BlueprintException(
259 ErrorCode.BLUEPRINT_PATH_MISSING.value,
261 "Blueprint folder under path($path)"
265 val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
267 if (!Files.exists(fileStorageLocation))
268 Files.createDirectories(fileStorageLocation)
270 return fileStorageLocation
273 fun compileCacheKey(basePath: String): String {
274 return normalizedPathName(basePath)
277 private fun compileJarFileName(artifactName: String, artifactVersion: String): String {
278 return "$artifactName-$artifactVersion-$COMPILED_JAR_SUFFIX"
281 fun compileJarFilePathName(basePath: String, artifactName: String, artifactVersion: String): String {
282 return normalizedPathName(
283 basePath, BlueprintConstants.TOSCA_SCRIPTS_KOTLIN_DIR,
284 compileJarFileName(artifactName, artifactVersion)
288 fun compileJarFile(basePath: String, artifactName: String, artifactVersion: String): File {
289 return normalizedFile(
290 compileJarFilePathName(
292 artifactName, artifactVersion
297 fun stripFileExtension(fileName: String): String {
298 val dotIndexe = fileName.lastIndexOf('.')
300 // In case dot is in first position, we are dealing with a hidden file rather than an extension
301 return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName
304 fun getURLClassLoaderFromDirectory(directory: File): URLClassLoader {
305 if (!directory.exists()) {
306 throw FileNotFoundException(directory.absolutePath)
307 } else if (!directory.isDirectory) {
308 throw NotDirectoryException(directory.absolutePath)
311 val urls = arrayListOf<URL>()
312 directory.walkTopDown()
313 .filter { it.name.endsWith(COMPILED_JAR_SUFFIX) }
315 log.debug("Adding (${it.absolutePath}) to classLoader (${directory.absolutePath})")
317 urls.add(it.toURI().toURL())
319 return URLClassLoader(urls.toTypedArray(), this.javaClass.classLoader)
322 fun getURLClassLoaderFromDirectory(path: String): URLClassLoader {
323 val directory = normalizedFile(path)
324 return getURLClassLoaderFromDirectory(directory)