Remote Script Executor Component
[ccsdk/cds.git] / ms / controllerblueprints / modules / blueprint-core / src / main / kotlin / org / onap / ccsdk / cds / controllerblueprints / core / utils / BluePrintArchiveUtils.kt
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  * Modifications Copyright © 2019 Nordix Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 package org.onap.ccsdk.cds.controllerblueprints.core.utils
20
21 import com.google.common.base.Predicates
22 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
23 import org.slf4j.LoggerFactory
24 import java.io.BufferedInputStream
25 import java.io.ByteArrayOutputStream
26 import java.io.File
27 import java.io.FileOutputStream
28 import java.io.IOException
29 import java.io.OutputStream
30 import java.nio.charset.Charset
31 import java.nio.file.FileVisitResult
32 import java.nio.file.Files
33 import java.nio.file.Path
34 import java.nio.file.SimpleFileVisitor
35 import java.nio.file.attribute.BasicFileAttributes
36 import java.util.function.Predicate
37 import java.util.zip.Deflater
38 import java.util.zip.ZipEntry
39 import java.util.zip.ZipFile
40 import java.util.zip.ZipOutputStream
41
42 class BluePrintArchiveUtils {
43
44     companion object {
45         private val log = LoggerFactory.getLogger(BluePrintArchiveUtils::class.java)
46
47         /**
48          * Create a new Zip from a root directory
49          *
50          * @param source the base directory
51          * @param destination the output filename
52          * @return True if OK
53          */
54         fun compress(source: File, destination: File): Boolean {
55             try {
56                 if (!destination.parentFile.exists()) {
57                     destination.parentFile.mkdirs()
58                 }
59                 destination.createNewFile()
60                 val ignoreZipFiles = Predicate<Path> { path -> !path.endsWith(".zip") && !path.endsWith(".ZIP") }
61                 FileOutputStream(destination).use { out ->
62                     compressFolder(source.toPath(), out, pathFilter = ignoreZipFiles)
63                 }
64             } catch (e: Exception) {
65                 log.error("Fail to compress folder($source) to path(${destination.path})", e)
66                 return false
67             }
68             return true
69         }
70
71         /**
72          * In-memory compress an entire folder.
73          */
74         fun compressToBytes(baseDir: Path, compressionLevel: Int = Deflater.NO_COMPRESSION): ByteArray {
75             return compressFolder(baseDir, ByteArrayOutputStream(), compressionLevel = compressionLevel)
76                 .toByteArray()
77         }
78
79         /**
80          * Compress an entire folder.
81          *
82          * @param baseDir path of base folder to be packaged.
83          * @param output the output stream
84          * @param pathFilter filter to ignore files based on its path.
85          * @param compressionLevel the wanted compression level.
86          * @param fixedModificationTime to force every entry to have this modification time.
87          * Useful for reproducible operations, like tests, for example.
88          */
89         private fun <T> compressFolder(
90             baseDir: Path,
91             output: T,
92             pathFilter: Predicate<Path> = Predicates.alwaysTrue(),
93             compressionLevel: Int = Deflater.DEFAULT_COMPRESSION,
94             fixedModificationTime: Long? = null
95         ): T
96                 where T : OutputStream {
97             ZipOutputStream(output)
98                 .apply { setLevel(compressionLevel) }
99                 .use { zos ->
100                     Files.walkFileTree(baseDir, object : SimpleFileVisitor<Path>() {
101                         @Throws(IOException::class)
102                         override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
103                             if (pathFilter.test(file)) {
104                                 val zipEntry = ZipEntry(baseDir.relativize(file).toString())
105                                 fixedModificationTime?.let {
106                                     zipEntry.time = it
107                                 }
108                                 zipEntry.time = 0
109                                 zos.putNextEntry(zipEntry)
110                                 Files.copy(file, zos)
111                                 zos.closeEntry()
112                             }
113                             return FileVisitResult.CONTINUE
114                         }
115
116                         @Throws(IOException::class)
117                         override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
118                             val zipEntry = ZipEntry(baseDir.relativize(dir).toString() + "/")
119                             fixedModificationTime?.let {
120                                 zipEntry.time = it
121                             }
122                             zos.putNextEntry(zipEntry)
123                             zos.closeEntry()
124                             return FileVisitResult.CONTINUE
125                         }
126                     })
127                 }
128             return output
129         }
130
131         fun deCompress(zipFile: File, targetPath: String): File {
132             val zip = ZipFile(zipFile, Charset.defaultCharset())
133             val enumeration = zip.entries()
134             while (enumeration.hasMoreElements()) {
135                 val entry = enumeration.nextElement()
136                 val destFilePath = File(targetPath, entry.name)
137                 destFilePath.parentFile.mkdirs()
138
139                 if (entry.isDirectory)
140                     continue
141
142                 val bufferedIs = BufferedInputStream(zip.getInputStream(entry))
143                 bufferedIs.use {
144                     destFilePath.outputStream().buffered(1024).use { bos ->
145                         bufferedIs.copyTo(bos)
146                     }
147                 }
148             }
149
150             val destinationDir = File(targetPath)
151             check(destinationDir.isDirectory && destinationDir.exists()) {
152                 throw BluePrintProcessorException("failed to decompress blueprint(${zipFile.absolutePath}) to ($targetPath) ")
153             }
154
155             return destinationDir
156         }
157     }
158 }