2be9f19ca00ee431c2198f84c6dd4cb22e2d4a9f
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package org.onap.ccsdk.apps.controllerblueprints.core.utils
18
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
29 import java.io.File
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
40
41
42
43 class BluePrintFileUtils {
44     companion object {
45
46         private val log: EELFLogger = EELFManager.getInstance().getLogger(this::class.toString())
47
48         fun createEmptyBluePrint(basePath: String) {
49
50             val blueprintDir = File(basePath)
51             FileUtils.deleteDirectory(blueprintDir)
52
53             Files.createDirectories(blueprintDir.toPath())
54
55             val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
56             Files.createDirectories(metaDataDir.toPath())
57
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)
60
61             val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
62             Files.createDirectories(definitionsDir.toPath())
63
64             val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
65             Files.createDirectories(scriptsDir.toPath())
66
67             val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
68             Files.createDirectories(plansDir.toPath())
69
70             val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
71             Files.createDirectories(templatesDir.toPath())
72
73         }
74
75         fun copyBluePrint(sourcePath: String, targetPath: String) {
76             val sourceFile = File(sourcePath)
77             val targetFile = File(targetPath)
78             sourceFile.copyRecursively(targetFile, true)
79         }
80
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")
84
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())
91             }
92         }
93
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)
98
99             // Clean Type Imports
100             cleanImportTypes(blueprintContext.serviceTemplate)
101
102             val imports = mutableListOf<ImportDefinition>()
103             types.forEach { typeName ->
104                 val import = ImportDefinition()
105                 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
106                 imports.add(import)
107             }
108
109             blueprintContext.serviceTemplate.imports = imports
110         }
111
112         fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
113             // Clean the Type imports
114             val toDeleteTypes = serviceTemplate.imports?.filter {
115                 it.file.endsWith("_types.json")
116             }
117
118             if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
119                 serviceTemplate.imports?.removeAll(toDeleteTypes)
120             }
121         }
122
123         fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
124
125             // Write Blueprint Types
126             writeBluePrintTypes(blueprintContext)
127             // Re Populate the Imports
128             populateDefaultImports(blueprintContext)
129             // Rewrite the Entry Definition Files
130             writeEntryDefinitionFile(blueprintContext)
131
132         }
133
134         fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
135
136             val basePath = blueprintContext.rootPath
137             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
138             val definitionDir = File(definitionPath)
139
140             check(definitionDir.exists()) {
141                 throw BluePrintException("couldn't get definition file under path(${definitionDir.absolutePath})")
142             }
143
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)
147             }
148
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)
152             }
153
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)
157             }
158
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)
162             }
163         }
164
165         fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
166
167             val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
168
169             val serviceTemplate = blueprintContext.serviceTemplate
170
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
177
178             // Write the Serivice Template
179             writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
180         }
181
182         fun writeDefinitionFile(definitionFile: String, content: String) = runBlocking {
183             val definitionFile = File(definitionFile)
184             // Delete the File If exists
185             Files.deleteIfExists(definitionFile.toPath())
186
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})")
190             }
191         }
192
193         private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
194             val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
195
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})")
199             }
200         }
201
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>"
208         }
209        
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})")
215             }
216             return file
217         }
218
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)
224         }
225
226         fun getCbaStorageDirectory(path: String): Path {
227             check(StringUtils.isNotBlank(path)) {
228                 throw BluePrintException("CBA Path is missing.")
229             }
230
231             val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
232
233             if (!Files.exists(fileStorageLocation))
234                 Files.createDirectories(fileStorageLocation)
235
236             return fileStorageLocation
237         }
238
239         fun stripFileExtension(fileName: String): String {
240             val dotIndexe = fileName.lastIndexOf('.')
241
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
244         }
245
246     }
247 }