bbfcef02e225c79b1f31f002050b51b6f66a61db
[so.git] / adapters / mso-openstack-adapters / src / main / java / org / onap / so / adapters / vnf / CSAR.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.adapters.vnf;
22
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.OutputStream;
29 import java.io.PrintStream;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.zip.ZipEntry;
33 import java.util.zip.ZipOutputStream;
34
35 import org.onap.so.adapters.vdu.VduArtifact;
36 import org.onap.so.adapters.vdu.VduArtifact.ArtifactType;
37 import org.onap.so.adapters.vdu.VduModelInfo;
38 import org.onap.so.adapters.vnf.exceptions.VnfException;
39
40 import com.google.common.io.Files;
41
42 /**
43  * The purpose of this class is to create a CSAR byte array from Vdu inputs for the purpose
44  * of forwarding to a TOSCA orchestrator.
45  * 
46  * @author DeWayne
47  *
48  */
49 public class CSAR {
50         private static final String MANIFEST_FILENAME = "MANIFEST.MF";
51         private VduModelInfo vduModel;
52
53         public CSAR(VduModelInfo model){
54            this.vduModel = model;
55         }
56
57         /**
58          * Creates a byte array representation of a CSAR corresponding to the VduBlueprint arg in the
59          * constructor.  
60          * 
61          * @return
62          * @throws VnfException 
63          */
64         public byte[] create() {
65                 File dir = Files.createTempDir();
66
67                 /**
68                  * Create subdir
69                  */
70                 File metadir = new File(dir.getAbsolutePath() + "/TOSCA-Metadata");
71                 if (!metadir.mkdir()) {
72                         throw new RuntimeException("CSAR TOSCA-Metadata directory create failed");
73                 }
74
75                 /**
76                  * Organize model info for consumption
77                  */
78                 VduArtifact mainTemplate = null;
79                 List<VduArtifact> extraFiles = new ArrayList<>();
80                 for(VduArtifact artifact: vduModel.getArtifacts()) {
81                           if(artifact.getType() == ArtifactType.MAIN_TEMPLATE ) {
82                                  mainTemplate = artifact;
83                           } else{
84                             extraFiles.add(artifact);
85                           }
86                 }
87                 
88                 if (mainTemplate == null) { // make a dummy to avoid null pointers
89                         mainTemplate = new VduArtifact("", new byte[0], null);
90                 }
91
92                 /**
93                  * Write template files
94                  */
95                 try (OutputStream ofs = new FileOutputStream(new File(dir, mainTemplate.getName()));
96                          PrintStream mfstream = new PrintStream(new File(metadir.getAbsolutePath() + '/' + MANIFEST_FILENAME));
97                         ) {
98                         ofs.write(mainTemplate.getContent());
99
100                         /**
101                          * Write other files
102                          */
103                         if (!extraFiles.isEmpty()) {
104                                 for (VduArtifact artifact: extraFiles){
105                                         try (OutputStream out = new FileOutputStream(new File(dir, artifact.getName()));) {
106                                                 out.write(artifact.getContent());
107                                         }
108                                 }
109                         }
110
111
112                         /**
113                          * Create manifest
114                          */
115                         mfstream.println("TOSCA-Meta-File-Version: 1.0");
116                         mfstream.println("CSAR-Version: 1.1");
117                         mfstream.println("Created-by: ONAP");
118                         mfstream.println("Entry-Definitions: " + mainTemplate.getName());
119
120                         /**
121                          * ZIP it up
122                          */
123                         ByteArrayOutputStream zipbytes = new ByteArrayOutputStream();
124                         ZipOutputStream zos = new ZipOutputStream(zipbytes);
125                         compressTree(zos, "", dir, dir);
126                         zos.close();
127                         return zipbytes.toByteArray();
128
129                 } catch (Exception e) {
130                         throw new RuntimeException("Failed to create CSAR: " + e.getMessage());
131                 } finally {
132                         /**
133                          * Clean up tmpdir
134                          */
135                         deleteDirectory(dir);
136                 }
137         }
138
139         /**
140          * Private methods
141          */
142
143         /**
144          * Compresses (ZIPs) a directory tree
145          * 
146          * @param dir
147          * @throws IOException
148          */
149         private void compressTree(ZipOutputStream zos, String path, File basedir, File dir) throws IOException {
150                 if (!dir.isDirectory())
151                         return;
152
153                 for (File f : dir.listFiles()) {
154                         if (f.isDirectory()) {
155                                 String newpath = path + f.getName() + '/';
156                                 ZipEntry entry = new ZipEntry(newpath);
157                                 zos.putNextEntry(entry);
158                                 zos.closeEntry();
159                                 compressTree(zos, newpath, basedir, f);
160                         } else {
161                                 ZipEntry ze = new ZipEntry(
162                                                 f.getAbsolutePath().substring(basedir.getAbsolutePath().length() + 1).replaceAll("\\\\", "/"));
163                                 zos.putNextEntry(ze);
164                                 // read the file and write to ZipOutputStream
165                                 try (FileInputStream fis = new FileInputStream(f);) {
166                                         byte[] buffer = new byte[1024];
167                                         int len;
168                                         while ((len = fis.read(buffer)) > 0) {
169                                                 zos.write(buffer, 0, len);
170                                         }
171                                 }
172                                 zos.closeEntry();
173                         }
174                 }
175         }
176
177         private boolean deleteDirectory(File directory) {
178                 if (directory.exists()) {
179                         File[] files = directory.listFiles();
180                         if (null != files) {
181                                 for (int i = 0; i < files.length; i++) {
182                                         if (files[i].isDirectory()) {
183                                                 deleteDirectory(files[i]);
184                                         } else {
185                                                 files[i].delete();
186                                         }
187                                 }
188                         }
189                 }
190                 return (directory.delete());
191         }
192 }