2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 Bell Canada.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.onap.ccsdk.cds.controllerblueprints.core.utils
20 import com.att.eelf.configuration.EELFLogger
21 import com.att.eelf.configuration.EELFManager
22 import kotlinx.coroutines.runBlocking
23 import org.apache.commons.io.FileUtils
24 import org.apache.commons.lang3.StringUtils
25 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
26 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
28 import org.onap.ccsdk.cds.controllerblueprints.core.data.ImportDefinition
29 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
30 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
32 import java.io.FileFilter
33 import java.nio.file.Files
34 import java.nio.file.Path
35 import java.nio.file.Paths
36 import java.nio.file.StandardOpenOption
39 class BluePrintFileUtils {
42 private val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
44 fun createEmptyBluePrint(basePath: String) {
46 val blueprintDir = File(basePath)
47 FileUtils.deleteDirectory(blueprintDir)
49 Files.createDirectories(blueprintDir.toPath())
51 val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
52 Files.createDirectories(metaDataDir.toPath())
54 val metaFile = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants
55 .TOSCA_METADATA_ENTRY_DEFINITION_FILE))
56 Files.write(metaFile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
58 val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
59 Files.createDirectories(definitionsDir.toPath())
61 val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
62 Files.createDirectories(scriptsDir.toPath())
64 val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
65 Files.createDirectories(plansDir.toPath())
67 val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
68 Files.createDirectories(templatesDir.toPath())
72 fun copyBluePrint(sourcePath: String, targetPath: String) {
73 val sourceFile = File(sourcePath)
74 val targetFile = File(targetPath)
75 sourceFile.copyRecursively(targetFile, true)
78 fun deleteBluePrintTypes(basePath: String) {
79 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
80 log.info("deleting definition types under : $definitionPath")
82 val definitionDir = File(definitionPath)
83 // Find the Type Definitions
84 val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
85 // Delete the Type Files
86 definitionDir.listFiles(fileFilter).forEach {
87 Files.deleteIfExists(it.toPath())
91 fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
93 // Write Blueprint Types
94 writeBluePrintTypes(blueprintContext)
95 // Re Populate the Imports
96 populateDefaultImports(blueprintContext)
97 // Rewrite the Entry Definition Files
98 writeEntryDefinitionFile(blueprintContext)
102 fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
104 val basePath = blueprintContext.rootPath
105 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
106 val definitionDir = File(definitionPath)
108 check(definitionDir.exists()) {
109 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
110 "path(${definitionDir.absolutePath})")
113 blueprintContext.serviceTemplate.dataTypes?.let {
114 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
115 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
118 blueprintContext.serviceTemplate.relationshipTypes?.let {
119 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
120 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
123 blueprintContext.serviceTemplate.artifactTypes?.let {
124 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
125 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
128 blueprintContext.serviceTemplate.nodeTypes?.let {
129 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
130 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
133 blueprintContext.serviceTemplate.policyTypes?.let {
134 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
135 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
139 private fun populateDefaultImports(blueprintContext: BluePrintContext) {
140 // Get the Default Types
141 val types = arrayListOf(BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_RELATIONSHIP_TYPES,
142 BluePrintConstants.PATH_ARTIFACT_TYPES, BluePrintConstants.PATH_NODE_TYPES,
143 BluePrintConstants.PATH_POLICY_TYPES)
145 // Clean Type Imports
146 cleanImportTypes(blueprintContext.serviceTemplate)
148 val imports = mutableListOf<ImportDefinition>()
149 types.forEach { typeName ->
150 val import = ImportDefinition()
151 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
155 blueprintContext.serviceTemplate.imports = imports
158 fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
159 // Clean the Type imports
160 val toDeleteTypes = serviceTemplate.imports?.filter {
161 it.file.endsWith("_types.json")
164 if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
165 serviceTemplate.imports?.removeAll(toDeleteTypes)
170 * Re Generate the Blueprint Service Template Definition file based on BluePrint Context.
172 private fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
174 val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
176 val serviceTemplate = blueprintContext.serviceTemplate
178 // Clone the Service Template
179 val writeServiceTemplate = serviceTemplate.clone()
180 writeServiceTemplate.dataTypes = null
181 writeServiceTemplate.artifactTypes = null
182 writeServiceTemplate.policyTypes = null
183 writeServiceTemplate.relationshipTypes = null
184 writeServiceTemplate.nodeTypes = null
186 // Write the Service Template
187 writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
190 fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
191 val definitionFile = File(definitionFileName)
192 // Delete the File If exists
193 Files.deleteIfExists(definitionFile.toPath())
195 Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
196 check(definitionFile.exists()) {
197 throw BluePrintException(ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write definition file under " +
198 "path(${definitionFile.absolutePath})")
202 private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
203 val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
205 Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
206 check(typeFile.exists()) {
207 throw BluePrintException(ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write $type.json file under " +
208 "path(${typeFile.absolutePath})")
212 private fun getMetaDataContent(): String {
213 return "TOSCA-Meta-File-Version: 1.0.0" +
214 "\nCSAR-Version: <VERSION>" +
215 "\nCreated-By: <AUTHOR NAME>" +
216 "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
217 "\nTemplate-Tags: <TAGS>"
221 fun getBluePrintFile(fileName: String, targetPath: Path) : File {
222 val filePath = targetPath.resolve(fileName).toString()
223 val file = File(filePath)
224 check(file.exists()) {
225 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
226 "path(${file.absolutePath})")
231 fun getCbaStorageDirectory(path: String): Path {
232 check(StringUtils.isNotBlank(path)) {
233 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get " +
234 "Blueprint folder under path($path)")
237 val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
239 if (!Files.exists(fileStorageLocation))
240 Files.createDirectories(fileStorageLocation)
242 return fileStorageLocation
245 fun stripFileExtension(fileName: String): String {
246 val dotIndexe = fileName.lastIndexOf('.')
248 // In case dot is in first position, we are dealing with a hidden file rather than an extension
249 return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName