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.apps.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.apps.controllerblueprints.core.BluePrintConstants
26 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
27 import org.onap.ccsdk.apps.controllerblueprints.core.data.ImportDefinition
28 import org.onap.ccsdk.apps.controllerblueprints.core.data.ServiceTemplate
29 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintContext
31 import java.io.FileFilter
32 import java.nio.file.Files
33 import java.nio.file.Path
34 import java.nio.file.Paths
35 import java.nio.file.StandardOpenOption
36 import java.text.MessageFormat
37 import java.time.Instant
38 import java.time.temporal.ChronoUnit
39 import java.time.ZoneId
40 import java.time.format.DateTimeFormatter
44 class BluePrintFileUtils {
47 private val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
49 fun createEmptyBluePrint(basePath: String) {
51 val blueprintDir = File(basePath)
52 FileUtils.deleteDirectory(blueprintDir)
54 Files.createDirectories(blueprintDir.toPath())
56 val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
57 Files.createDirectories(metaDataDir.toPath())
59 val metafile = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_ENTRY_DEFINITION_FILE))
60 Files.write(metafile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
62 val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
63 Files.createDirectories(definitionsDir.toPath())
65 val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
66 Files.createDirectories(scriptsDir.toPath())
68 val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
69 Files.createDirectories(plansDir.toPath())
71 val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
72 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 populateDefaultImports(blueprintContext: BluePrintContext) {
96 // Get the Default Types
97 val types = arrayListOf(BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_ARTIFACT_TYPES,
98 BluePrintConstants.PATH_NODE_TYPES, BluePrintConstants.PATH_POLICY_TYPES)
100 // Clean Type Imports
101 cleanImportTypes(blueprintContext.serviceTemplate)
103 val imports = mutableListOf<ImportDefinition>()
104 types.forEach { typeName ->
105 val import = ImportDefinition()
106 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
110 blueprintContext.serviceTemplate.imports = imports
113 fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
114 // Clean the Type imports
115 val toDeleteTypes = serviceTemplate.imports?.filter {
116 it.file.endsWith("_types.json")
119 if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
120 serviceTemplate.imports?.removeAll(toDeleteTypes)
124 fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
126 // Write Blueprint Types
127 writeBluePrintTypes(blueprintContext)
128 // Re Populate the Imports
129 populateDefaultImports(blueprintContext)
130 // Rewrite the Entry Definition Files
131 writeEntryDefinitionFile(blueprintContext)
135 fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
137 val basePath = blueprintContext.rootPath
138 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
139 val definitionDir = File(definitionPath)
141 check(definitionDir.exists()) {
142 throw BluePrintException("couldn't get definition file under path(${definitionDir.absolutePath})")
145 blueprintContext.serviceTemplate.dataTypes?.let {
146 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
147 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
150 blueprintContext.serviceTemplate.artifactTypes?.let {
151 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
152 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
155 blueprintContext.serviceTemplate.nodeTypes?.let {
156 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
157 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
160 blueprintContext.serviceTemplate.policyTypes?.let {
161 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
162 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
166 fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
168 val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
170 val serviceTemplate = blueprintContext.serviceTemplate
172 // Clone the Service Template
173 val writeServiceTemplate = serviceTemplate.clone()
174 writeServiceTemplate.dataTypes = null
175 writeServiceTemplate.artifactTypes = null
176 writeServiceTemplate.policyTypes = null
177 writeServiceTemplate.nodeTypes = null
179 // Write the Serivice Template
180 writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
183 fun writeDefinitionFile(definitionFile: String, content: String) = runBlocking {
184 val definitionFile = File(definitionFile)
185 // Delete the File If exists
186 Files.deleteIfExists(definitionFile.toPath())
188 Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
189 check(definitionFile.exists()) {
190 throw BluePrintException("couldn't write definition file under path(${definitionFile.absolutePath})")
194 private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
195 val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
197 Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
198 check(typeFile.exists()) {
199 throw BluePrintException("couldn't write $type.json file under path(${typeFile.absolutePath})")
203 private fun getMetaDataContent(): String {
204 return "TOSCA-Meta-File-Version: 1.0.0" +
205 "\nCSAR-Version: <VERSION>" +
206 "\nCreated-By: <AUTHOR NAME>" +
207 "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
208 "\nTemplate-Tags: <TAGS>"
211 fun getBluePrintFile(fileName: String, targetPath: Path) : File {
212 val filePath = targetPath.resolve(fileName).toString()
213 val file = File(filePath)
214 check(file.exists()) {
215 throw BluePrintException("couldn't get definition file under path(${file.absolutePath})")
220 fun getCBAGeneratedFileName(fileName: String, prefix: String): String {
221 val DATE_FORMAT = "yyyyMMddHHmmss"
222 val formatter = DateTimeFormatter.ofPattern(DATE_FORMAT)
223 val datePrefix = Instant.now().atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter)
224 return MessageFormat.format(prefix, datePrefix, fileName)
227 fun getCbaStorageDirectory(path: String): Path {
228 check(StringUtils.isNotBlank(path)) {
229 throw BluePrintException("CBA Path is missing.")
232 val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
234 if (!Files.exists(fileStorageLocation))
235 Files.createDirectories(fileStorageLocation)
237 return fileStorageLocation
240 fun stripFileExtension(fileName: String): String {
241 val dotIndexe = fileName.lastIndexOf('.')
243 // In case dot is in first position, we are dealing with a hidden file rather than an extension
244 return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName