2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 Bell Canada.
4 * Modifications Copyright © 2019 Nordix Foundation.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 package org.onap.ccsdk.cds.controllerblueprints.core.utils
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
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
42 class BluePrintArchiveUtils {
45 private val log = LoggerFactory.getLogger(BluePrintArchiveUtils::class.java)
48 * Create a new Zip from a root directory
50 * @param source the base directory
51 * @param destination the output filename
54 fun compress(source: File, destination: File): Boolean {
56 if (!destination.parentFile.exists()) {
57 destination.parentFile.mkdirs()
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)
64 } catch (e: Exception) {
65 log.error("Fail to compress folder($source) to path(${destination.path})", e)
72 * In-memory compress an entire folder.
74 fun compressToBytes(baseDir: Path, compressionLevel: Int = Deflater.NO_COMPRESSION): ByteArray {
75 return compressFolder(baseDir, ByteArrayOutputStream(), compressionLevel = compressionLevel)
80 * Compress an entire folder.
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.
89 private fun <T> compressFolder(
92 pathFilter: Predicate<Path> = Predicates.alwaysTrue(),
93 compressionLevel: Int = Deflater.DEFAULT_COMPRESSION,
94 fixedModificationTime: Long? = null
96 where T : OutputStream {
97 ZipOutputStream(output)
98 .apply { setLevel(compressionLevel) }
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 {
109 zos.putNextEntry(zipEntry)
110 Files.copy(file, zos)
113 return FileVisitResult.CONTINUE
116 @Throws(IOException::class)
117 override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
118 val zipEntry = ZipEntry(baseDir.relativize(dir).toString() + "/")
119 fixedModificationTime?.let {
122 zos.putNextEntry(zipEntry)
124 return FileVisitResult.CONTINUE
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()
139 if (entry.isDirectory)
142 val bufferedIs = BufferedInputStream(zip.getInputStream(entry))
144 destFilePath.outputStream().buffered(1024).use { bos ->
145 bufferedIs.copyTo(bos)
150 val destinationDir = File(targetPath)
151 check(destinationDir.isDirectory && destinationDir.exists()) {
152 throw BluePrintProcessorException("failed to decompress blueprint(${zipFile.absolutePath}) to ($targetPath) ")
155 return destinationDir