2 * Copyright © 2017-2018 AT&T Intellectual Property.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.ccsdk.apps.controllerblueprints.core.utils
19 import com.att.eelf.configuration.EELFLogger
20 import com.att.eelf.configuration.EELFManager
21 import kotlinx.coroutines.runBlocking
22 import org.apache.commons.io.FileUtils
23 import org.apache.commons.lang3.StringUtils
24 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintConstants
25 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
26 import org.onap.ccsdk.apps.controllerblueprints.core.data.ImportDefinition
27 import org.onap.ccsdk.apps.controllerblueprints.core.data.ServiceTemplate
28 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintContext
30 import java.io.FileFilter
31 import java.nio.file.Files
32 import java.nio.file.Path
33 import java.nio.file.Paths
34 import java.nio.file.StandardOpenOption
35 import java.text.MessageFormat
36 import java.time.Instant
37 import java.time.temporal.ChronoUnit
38 import java.time.ZoneId
39 import java.time.format.DateTimeFormatter
43 class BluePrintFileUtils {
46 private val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
48 fun createEmptyBluePrint(basePath: String) {
50 val blueprintDir = File(basePath)
51 FileUtils.deleteDirectory(blueprintDir)
53 Files.createDirectories(blueprintDir.toPath())
55 val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
56 Files.createDirectories(metaDataDir.toPath())
58 val metafile = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_ENTRY_DEFINITION_FILE))
59 Files.write(metafile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
61 val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
62 Files.createDirectories(definitionsDir.toPath())
64 val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
65 Files.createDirectories(scriptsDir.toPath())
67 val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
68 Files.createDirectories(plansDir.toPath())
70 val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
71 Files.createDirectories(templatesDir.toPath())
75 fun copyBluePrint(sourcePath: String, targetPath: String) {
76 val sourceFile = File(sourcePath)
77 val targetFile = File(targetPath)
78 sourceFile.copyRecursively(targetFile, true)
81 fun deleteBluePrintTypes(basePath: String) {
82 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
83 log.info("deleting definition types under : $definitionPath")
85 val definitionDir = File(definitionPath)
86 // Find the Type Definitions
87 val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
88 // Delete the Type Files
89 definitionDir.listFiles(fileFilter).forEach {
90 Files.deleteIfExists(it.toPath())
94 fun populateDefaultImports(blueprintContext: BluePrintContext) {
95 // Get the Default Types
96 val types = arrayListOf(BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_ARTIFACT_TYPES,
97 BluePrintConstants.PATH_NODE_TYPES, BluePrintConstants.PATH_POLICY_TYPES)
100 cleanImportTypes(blueprintContext.serviceTemplate)
102 val imports = mutableListOf<ImportDefinition>()
103 types.forEach { typeName ->
104 val import = ImportDefinition()
105 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
109 blueprintContext.serviceTemplate.imports = imports
112 fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
113 // Clean the Type imports
114 val toDeleteTypes = serviceTemplate.imports?.filter {
115 it.file.endsWith("_types.json")
118 if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
119 serviceTemplate.imports?.removeAll(toDeleteTypes)
123 fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
125 // Write Blueprint Types
126 writeBluePrintTypes(blueprintContext)
127 // Re Populate the Imports
128 populateDefaultImports(blueprintContext)
129 // Rewrite the Entry Definition Files
130 writeEntryDefinitionFile(blueprintContext)
134 fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
136 val basePath = blueprintContext.rootPath
137 val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
138 val definitionDir = File(definitionPath)
140 check(definitionDir.exists()) {
141 throw BluePrintException("couldn't get definition file under path(${definitionDir.absolutePath})")
144 blueprintContext.serviceTemplate.dataTypes?.let {
145 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
146 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
149 blueprintContext.serviceTemplate.artifactTypes?.let {
150 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
151 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
154 blueprintContext.serviceTemplate.nodeTypes?.let {
155 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
156 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
159 blueprintContext.serviceTemplate.policyTypes?.let {
160 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
161 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
165 fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
167 val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
169 val serviceTemplate = blueprintContext.serviceTemplate
171 // Clone the Service Template
172 val writeServiceTemplate = serviceTemplate.clone()
173 writeServiceTemplate.dataTypes = null
174 writeServiceTemplate.artifactTypes = null
175 writeServiceTemplate.policyTypes = null
176 writeServiceTemplate.nodeTypes = null
178 // Write the Serivice Template
179 writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
182 fun writeDefinitionFile(definitionFile: String, content: String) = runBlocking {
183 val definitionFile = File(definitionFile)
184 // Delete the File If exists
185 Files.deleteIfExists(definitionFile.toPath())
187 Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
188 check(definitionFile.exists()) {
189 throw BluePrintException("couldn't write definition file under path(${definitionFile.absolutePath})")
193 private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
194 val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
196 Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
197 check(typeFile.exists()) {
198 throw BluePrintException("couldn't write $type.json file under path(${typeFile.absolutePath})")
202 private fun getMetaDataContent(): String {
203 return "TOSCA-Meta-File-Version: 1.0.0" +
204 "\nCSAR-Version: <VERSION>" +
205 "\nCreated-By: <AUTHOR NAME>" +
206 "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
207 "\nTemplate-Tags: <TAGS>"
210 fun getBluePrintFile(fileName: String, targetPath: Path) : File {
211 val filePath = targetPath.resolve(fileName).toString()
212 val file = File(filePath)
213 check(file.exists()) {
214 throw BluePrintException("couldn't get definition file under path(${file.absolutePath})")
219 fun getCBAGeneratedFileName(fileName: String, prefix: String): String {
220 val DATE_FORMAT = "yyyyMMddHHmmss"
221 val formatter = DateTimeFormatter.ofPattern(DATE_FORMAT)
222 val datePrefix = Instant.now().atZone(ZoneId.systemDefault()).toLocalDateTime().format(formatter)
223 return MessageFormat.format(prefix, datePrefix, fileName)
226 fun getCbaStorageDirectory(path: String): Path {
227 check(StringUtils.isNotBlank(path)) {
228 throw BluePrintException("CBA Path is missing.")
231 val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
233 if (!Files.exists(fileStorageLocation))
234 Files.createDirectories(fileStorageLocation)
236 return fileStorageLocation
239 fun stripFileExtension(fileName: String): String {
240 val dotIndexe = fileName.lastIndexOf('.')
242 // In case dot is in first position, we are dealing with a hidden file rather than an extension
243 return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName