ad91d45c35bed45c58059addb61a0dc5da908162
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 package org.onap.ccsdk.cds.controllerblueprints.core.utils
19
20 import kotlinx.coroutines.runBlocking
21 import org.apache.commons.io.FileUtils
22 import org.apache.commons.lang3.StringUtils
23 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
24 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
26 import org.onap.ccsdk.cds.controllerblueprints.core.data.ImportDefinition
27 import org.onap.ccsdk.cds.controllerblueprints.core.data.ServiceTemplate
28 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
29 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName
30 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
31 import org.slf4j.LoggerFactory
32 import java.io.File
33 import java.io.FileFilter
34 import java.nio.file.Files
35 import java.nio.file.Path
36 import java.nio.file.Paths
37 import java.nio.file.StandardOpenOption
38
39
40 class BluePrintFileUtils {
41     companion object {
42
43         private val log = LoggerFactory.getLogger(this::class.toString())
44
45         fun createEmptyBluePrint(basePath: String) {
46
47             val blueprintDir = File(basePath)
48             FileUtils.deleteDirectory(blueprintDir)
49
50             Files.createDirectories(blueprintDir.toPath())
51
52             val metaDataDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_METADATA_DIR))
53             Files.createDirectories(metaDataDir.toPath())
54
55             val metaFile = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants
56                     .TOSCA_METADATA_ENTRY_DEFINITION_FILE))
57             Files.write(metaFile.toPath(), getMetaDataContent().toByteArray(), StandardOpenOption.CREATE_NEW)
58
59             val definitionsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR))
60             Files.createDirectories(definitionsDir.toPath())
61
62             val scriptsDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_SCRIPTS_DIR))
63             Files.createDirectories(scriptsDir.toPath())
64
65             val plansDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_PLANS_DIR))
66             Files.createDirectories(plansDir.toPath())
67
68             val templatesDir = File(blueprintDir.absolutePath.plus(File.separator).plus(BluePrintConstants.TOSCA_TEMPLATES_DIR))
69             Files.createDirectories(templatesDir.toPath())
70
71         }
72
73         fun copyBluePrint(sourcePath: String, targetPath: String) {
74             val sourceFile = File(sourcePath)
75             val targetFile = File(targetPath)
76             sourceFile.copyRecursively(targetFile, true)
77         }
78
79         fun deleteBluePrintTypes(basePath: String) {
80             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
81             log.info("deleting definition types under : $definitionPath")
82
83             val definitionDir = File(definitionPath)
84             // Find the Type Definitions
85             val fileFilter = FileFilter { pathname -> pathname.absolutePath.endsWith("_types.json") }
86             // Delete the Type Files
87             definitionDir.listFiles(fileFilter).forEach {
88                 Files.deleteIfExists(it.toPath())
89             }
90         }
91
92         fun writeEnhancedBluePrint(blueprintContext: BluePrintContext) {
93
94             // Write Blueprint Types
95             writeBluePrintTypes(blueprintContext)
96             // Re Populate the Imports
97             populateDefaultImports(blueprintContext)
98             // Rewrite the Entry Definition Files
99             writeEntryDefinitionFile(blueprintContext)
100
101         }
102
103         fun writeBluePrintTypes(blueprintContext: BluePrintContext) {
104
105             val basePath = blueprintContext.rootPath
106             val definitionPath = basePath.plus(File.separator).plus(BluePrintConstants.TOSCA_DEFINITIONS_DIR)
107             val definitionDir = File(definitionPath)
108
109             check(definitionDir.exists()) {
110                 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
111                         "path(${definitionDir.absolutePath})")
112             }
113
114             blueprintContext.serviceTemplate.dataTypes?.let {
115                 val dataTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_DATA_TYPES, it.toSortedMap(), true)
116                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_DATA_TYPES, dataTypesContent)
117             }
118
119             blueprintContext.serviceTemplate.relationshipTypes?.let {
120                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_RELATIONSHIP_TYPES, it.toSortedMap(), true)
121                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_RELATIONSHIP_TYPES, nodeTypesContent)
122             }
123
124             blueprintContext.serviceTemplate.artifactTypes?.let {
125                 val artifactTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_ARTIFACT_TYPES, it.toSortedMap(), true)
126                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_ARTIFACT_TYPES, artifactTypesContent)
127             }
128
129             blueprintContext.serviceTemplate.nodeTypes?.let {
130                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_NODE_TYPES, it.toSortedMap(), true)
131                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_NODE_TYPES, nodeTypesContent)
132             }
133
134             blueprintContext.serviceTemplate.policyTypes?.let {
135                 val nodeTypesContent = JacksonUtils.getWrappedJson(BluePrintConstants.PATH_POLICY_TYPES, it.toSortedMap(), true)
136                 writeTypeFile(definitionDir.absolutePath, BluePrintConstants.PATH_POLICY_TYPES, nodeTypesContent)
137             }
138         }
139
140         private fun populateDefaultImports(blueprintContext: BluePrintContext) {
141             // Get the Default Types
142             val types = arrayListOf(BluePrintConstants.PATH_DATA_TYPES, BluePrintConstants.PATH_RELATIONSHIP_TYPES,
143                     BluePrintConstants.PATH_ARTIFACT_TYPES, BluePrintConstants.PATH_NODE_TYPES,
144                     BluePrintConstants.PATH_POLICY_TYPES)
145
146             // Clean Type Imports
147             cleanImportTypes(blueprintContext.serviceTemplate)
148
149             val imports = mutableListOf<ImportDefinition>()
150             types.forEach { typeName ->
151                 val import = ImportDefinition()
152                 import.file = BluePrintConstants.TOSCA_DEFINITIONS_DIR.plus("/$typeName.json")
153                 imports.add(import)
154             }
155
156             blueprintContext.serviceTemplate.imports = imports
157         }
158
159         fun cleanImportTypes(serviceTemplate: ServiceTemplate) {
160             // Clean the Type imports
161             val toDeleteTypes = serviceTemplate.imports?.filter {
162                 it.file.endsWith("_types.json")
163             }
164
165             if (toDeleteTypes != null && toDeleteTypes.isNotEmpty()) {
166                 serviceTemplate.imports?.removeAll(toDeleteTypes)
167             }
168         }
169
170         /**
171          * Re Generate the Blueprint Service Template Definition file based on BluePrint Context.
172          */
173         private fun writeEntryDefinitionFile(blueprintContext: BluePrintContext) {
174
175             val absoluteEntryDefinitionFile = blueprintContext.rootPath.plus(File.separator).plus(blueprintContext.entryDefinition)
176
177             val serviceTemplate = blueprintContext.serviceTemplate
178
179             // Clone the Service Template
180             val writeServiceTemplate = serviceTemplate.clone()
181             writeServiceTemplate.dataTypes = null
182             writeServiceTemplate.artifactTypes = null
183             writeServiceTemplate.policyTypes = null
184             writeServiceTemplate.relationshipTypes = null
185             writeServiceTemplate.nodeTypes = null
186
187             // Write the Service Template
188             writeDefinitionFile(absoluteEntryDefinitionFile, JacksonUtils.getJson(writeServiceTemplate, true))
189         }
190
191         fun writeDefinitionFile(definitionFileName: String, content: String) = runBlocking {
192             val definitionFile = File(definitionFileName)
193             // Delete the File If exists
194             Files.deleteIfExists(definitionFile.toPath())
195
196             Files.write(definitionFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
197             check(definitionFile.exists()) {
198                 throw BluePrintException(ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write definition file under " +
199                         "path(${definitionFile.absolutePath})")
200             }
201         }
202
203         private fun writeTypeFile(definitionPath: String, type: String, content: String) = runBlocking {
204             val typeFile = File(definitionPath.plus(File.separator).plus("$type.json"))
205
206             Files.write(typeFile.toPath(), content.toByteArray(), StandardOpenOption.CREATE_NEW)
207             check(typeFile.exists()) {
208                 throw BluePrintException(ErrorCode.BLUEPRINT_WRITING_FAIL.value, "couldn't write $type.json file under " +
209                         "path(${typeFile.absolutePath})")
210             }
211         }
212
213         private fun getMetaDataContent(): String {
214             return "TOSCA-Meta-File-Version: 1.0.0" +
215                     "\nCSAR-Version: <VERSION>" +
216                     "\nCreated-By: <AUTHOR NAME>" +
217                     "\nEntry-Definitions: Definitions/<BLUEPRINT_NAME>.json" +
218                     "\nTemplate-Tags: <TAGS>"
219         }
220
221
222         fun getBluePrintFile(fileName: String, targetPath: Path): File {
223             val filePath = targetPath.resolve(fileName).toString()
224             val file = File(filePath)
225             check(file.exists()) {
226                 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get definition file under " +
227                         "path(${file.absolutePath})")
228             }
229             return file
230         }
231
232         fun getCbaStorageDirectory(path: String): Path {
233             check(StringUtils.isNotBlank(path)) {
234                 throw BluePrintException(ErrorCode.BLUEPRINT_PATH_MISSING.value, "couldn't get " +
235                         "Blueprint folder under path($path)")
236             }
237
238             val fileStorageLocation = Paths.get(path).toAbsolutePath().normalize()
239
240             if (!Files.exists(fileStorageLocation))
241                 Files.createDirectories(fileStorageLocation)
242
243             return fileStorageLocation
244         }
245
246         fun compileCacheKey(basePath: String): String {
247             return normalizedPathName(basePath)
248         }
249
250         private fun compileJarFileName(artifactName: String, artifactVersion: String): String {
251             return "$artifactName-$artifactVersion-cba-kts.jar"
252         }
253
254         fun compileJarFilePathName(basePath: String, artifactName: String, artifactVersion: String): String {
255             return normalizedPathName(basePath, BluePrintConstants.TOSCA_SCRIPTS_KOTLIN_DIR,
256                     compileJarFileName(artifactName, artifactVersion))
257         }
258
259         fun compileJarFile(basePath: String, artifactName: String, artifactVersion: String): File {
260             return normalizedFile(compileJarFilePathName(basePath,
261                     artifactName, artifactVersion))
262         }
263
264         fun stripFileExtension(fileName: String): String {
265             val dotIndexe = fileName.lastIndexOf('.')
266
267             // In case dot is in first position, we are dealing with a hidden file rather than an extension
268             return if (dotIndexe > 0) fileName.substring(0, dotIndexe) else fileName
269         }
270
271     }
272 }