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.nio.file.Files
36 import java.nio.file.Path
37 import java.nio.file.Paths
38 import java.nio.file.StandardOpenOption
40 class BluePrintFileUtils {
43 private val log = LoggerFactory.getLogger(this::class.toString())
45 fun createEmptyBluePrint(basePath: String) {
47 val blueprintDir = File(basePath)
48 FileUtils.deleteDirectory(blueprintDir)
50 Files.createDirectories(blueprintDir.toPath())
52 val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
53 Files.createDirectories(metaDataDir.toPath())
56 blueprintDir.absolutePath.plus(File.separator).plus(
58 .TOSCA_METADATA_ENTRY_DEFINITION_FILE
61 Files.write(metaFile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
63 val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
64 Files.createDirectories(definitionsDir.toPath())
66 val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
67 Files.createDirectories(scriptsDir.toPath())
69 val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
70 Files.createDirectories(plansDir.toPath())
72 val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
73 Files.createDirectories(templatesDir.toPath())
76 fun copyBluePrint(sourcePath: String, targetPath: String) {
77 val sourceFile = File(sourcePath)
78 val targetFile = File(targetPath)
79 sourceFile.copyRecursively(targetFile, true)
82 fun deleteBluePrintTypes(basePath: String) {
83 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
84 log.info("deleting definition types under : $definitionPath")
86 val definitionDir = File(definitionPath)
87 // Find the Type Definitions
88 val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
89 // Delete the Type Files
90 definitionDir.listFiles(fileFilter).forEach {
91 Files.deleteIfExists(it.toPath())
95 fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
97 // Write Blueprint Types
98 writeBluePrintTypes(blueprintContext)
99 // Re Populate the Imports
100 populateDefaultImports(blueprintContext)
101 // Rewrite the Entry Definition Files
102 writeEntryDefinitionFile(blueprintContext)
105 fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
107 val basePath = blueprintContext.rootPath
108 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
109 val definitionDir = File(definitionPath)
111 check(definitionDir.exists()) {
112 throw BluePrintException(
113 ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
114 "path(${definitionDir.absolutePath})"
118 blueprintContext.serviceTemplate.dataTypes?.let {
119 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
120 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
123 blueprintContext.serviceTemplate.relationshipTypes?.let {
124 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
125 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
128 blueprintContext.serviceTemplate.artifactTypes?.let {
129 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
130 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
133 blueprintContext.serviceTemplate.nodeTypes?.let {
134 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
135 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
138 blueprintContext.serviceTemplate.policyTypes?.let {
139 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
140 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
144 private fun populateDefaultImports(blueprintContext: BluePrintContext) {
145 // Get the Default Types
146 val types = arrayListOf(
147 BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_RELATIONSHIP_TYPES,
148 BluePrintConstants.PATH_ARTIFACT_TYPES, BluePrintConstants.PATH_NODE_TYPES,
149 BluePrintConstants.PATH_POLICY_TYPES
152 // Clean Type Imports
153 cleanImportTypes(blueprintContext.serviceTemplate)
155 val imports = mutableListOf<ImportDefinition>()
156 types.forEach { typeName ->
157 val import = ImportDefinition()
158 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
162 blueprintContext.serviceTemplate.imports = imports
165 fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
166 // Clean the Type imports
167 val toDeleteTypes = serviceTemplate.imports?.filter {
168 it.file.endsWith("_types.json")
171 if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
172 serviceTemplate.imports?.removeAll(toDeleteTypes)
177 * Re Generate the Blueprint Service Template Definition file based on BluePrint Context.
179 private fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
181 val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
183 val serviceTemplate = blueprintContext.serviceTemplate
185 // Clone the Service Template
186 val writeServiceTemplate = serviceTemplate.clone()
187 writeServiceTemplate.dataTypes = null
188 writeServiceTemplate.artifactTypes = null
189 writeServiceTemplate.policyTypes = null
190 writeServiceTemplate.relationshipTypes = null
191 writeServiceTemplate.nodeTypes = null
193 // Write the Service Template
194 writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
197 fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
198 val definitionFile = File(definitionFileName)
199 // Delete the File If exists
200 Files.deleteIfExists(definitionFile.toPath())
202 Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
203 check(definitionFile.exists()) {
204 throw BluePrintException(
205 ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write definition file under " +
206 "path(${definitionFile.absolutePath})"
211 private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
212 val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
214 Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
215 check(typeFile.exists()) {
216 throw BluePrintException(
217 ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write $type.json file under " +
218 "path(${typeFile.absolutePath})"
223 private fun getMetaDataContent(): String {
224 return "TOSCA-Meta-File-Version: 1.0.0" +
225 "\nCSAR-Version: <VERSION>" +
226 "\nCreated-By: <AUTHOR NAME>" +
227 "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
228 "\nTemplate-Name: <BLUEPRINT_NAME>" +
229 "\nTemplate-Tags: <BLUEPRINT_VERSION>" +
230 "\nTemplate-Tags: <TAGS>"
233 fun getBluePrintFile(fileName: String, targetPath: Path): File {
234 val filePath = targetPath.resolve(fileName).toString()
235 val file = File(filePath)
236 check(file.exists()) {
237 throw BluePrintException(
238 ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
239 "path(${file.absolutePath})"
245 fun getCbaStorageDirectory(path: String): Path {
246 check(StringUtils.isNotBlank(path)) {
247 throw BluePrintException(
248 ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get " +
249 "Blueprint folder under path($path)"
253 val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
255 if (!Files.exists(fileStorageLocation))
256 Files.createDirectories(fileStorageLocation)
258 return fileStorageLocation
261 fun compileCacheKey(basePath: String): String {
262 return normalizedPathName(basePath)
265 private fun compileJarFileName(artifactName: String, artifactVersion: String): String {
266 return "$artifactName-$artifactVersion-cba-kts.jar"
269 fun compileJarFilePathName(basePath: String, artifactName: String, artifactVersion: String): String {
270 return normalizedPathName(
271 basePath, BluePrintConstants.TOSCA_SCRIPTS_KOTLIN_DIR,
272 compileJarFileName(artifactName, artifactVersion)
276 fun compileJarFile(basePath: String, artifactName: String, artifactVersion: String): File {
277 return normalizedFile(
278 compileJarFilePathName(
280 artifactName, artifactVersion
285 fun stripFileExtension(fileName: String): String {
286 val dotIndexe = fileName.lastIndexOf('.')
288 // In case dot is in first position, we are dealing with a hidden file rather than an extension
289 return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName