6e5f0b477685ccfb5013520de230ac37511b63fb
[sdc.git] /
1 /*
2  * Copyright © 2016-2017 European Support Limited
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.openecomp.sdc.translator.utils;
18
19 import org.apache.commons.io.IOUtils;
20 import org.openecomp.sdc.common.errors.CoreException;
21 import org.openecomp.sdc.common.errors.ErrorCategory;
22 import org.openecomp.sdc.common.errors.ErrorCode;
23 import org.openecomp.sdc.datatypes.error.ErrorLevel;
24 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
25 import org.openecomp.sdc.logging.types.LoggerConstants;
26 import org.openecomp.sdc.logging.types.LoggerErrorCode;
27 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
28 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
29
30 import java.io.BufferedReader;
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.InputStreamReader;
37 import java.net.URI;
38 import java.net.URISyntaxException;
39 import java.net.URL;
40 import java.util.Enumeration;
41 import java.util.HashMap;
42 import java.util.Map;
43 import java.util.function.BiConsumer;
44 import java.util.function.Predicate;
45 import java.util.zip.ZipEntry;
46 import java.util.zip.ZipFile;
47
48 public class ResourceWalker {
49
50   private ResourceWalker() {
51   }
52
53   /**
54    * Read resources from directory map.
55    *
56    * @param resourceDirectoryToStart the resource directory to start
57    * @return the map of file where key is file name and value is its data
58    * @throws Exception the exception
59    */
60   public static Map<String, String> readResourcesFromDirectory(String resourceDirectoryToStart)
61       throws
62       Exception {
63     Map<String, String> filesContent = new HashMap<>();
64     traverse(resourceDirectoryToStart, (fileName, stream) -> {
65       try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
66         filesContent.put(fileName, IOUtils.toString(reader));
67       } catch (IOException exception) {
68         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
69             LoggerTragetServiceName.READ_RESOURCE_FILE, ErrorLevel.ERROR.name(),
70             LoggerErrorCode.DATA_ERROR.getErrorCode(),
71             LoggerErrorDescription.RESOURCE_FILE_READ_ERROR
72                 + " File name = " + fileName);
73         throw new CoreException((new ErrorCode.ErrorCodeBuilder())
74             .withMessage(LoggerErrorDescription.RESOURCE_FILE_READ_ERROR
75                 + " File name = " + fileName)
76             .withId("Resource Read Error").withCategory(ErrorCategory.APPLICATION).build(),
77             exception);
78       }
79     });
80     return filesContent;
81   }
82
83   private static void traverse(String start, BiConsumer<String, InputStream> handler) throws
84       Exception {
85
86     URL url = ResourceWalker.class.getClassLoader().getResource(start);
87     if (url == null) {
88       throw new FileNotFoundException("Resource not found: " + start);
89     }
90
91     switch (url.getProtocol().toLowerCase()) {
92
93       case "file":
94         traverseFile(new File(url.getPath()), handler);
95         break;
96       case "zip":
97       case "jar":
98         String path = url.getPath();
99         int resourcePosition = path.lastIndexOf("!/" + start);
100         traverseArchive(path.substring(0, resourcePosition), start, handler);
101         break;
102       default:
103         throw new IllegalArgumentException("Unknown protocol");
104     }
105   }
106
107   private static void traverseArchive(String file, String resource, BiConsumer<String, InputStream>
108       handler)
109       throws URISyntaxException, IOException {
110
111     // There is what looks like a bug in Java:
112     // if "abc" is a directory in an archive,
113     // both "abc" and "abc/" will be found successfully.
114     // However, calling isDirectory() will return "true" for "abc/",
115     // but "false" for "abc".
116     try (ZipFile zip = new ZipFile(new URI(file).getPath())) {
117
118       Predicate<ZipEntry> predicate = buildPredicate(resource);
119       Enumeration<? extends ZipEntry> entries = zip.entries();
120       while (entries.hasMoreElements()) {
121         handleZipEntry(predicate, zip, entries.nextElement(), handler);
122       }
123     }
124   }
125
126   private static Predicate<ZipEntry> buildPredicate(String resource) {
127
128     if (resource.endsWith("/")) {
129       return zipEntry ->
130           zipEntry.getName().startsWith(resource) && !zipEntry.isDirectory();
131     } else {
132       return zipEntry -> {
133         String name = zipEntry.getName();
134         return (name.equals(resource) || name.startsWith(resource + "/"))
135             && !zipEntry.isDirectory();
136       };
137     }
138   }
139
140   private static void handleZipEntry(Predicate<ZipEntry> predicate, ZipFile zip, ZipEntry zipEntry,
141                                      BiConsumer<String, InputStream> handler)
142       throws IOException {
143
144     if (predicate.test(zipEntry)) {
145
146       try (InputStream input = zip.getInputStream(zipEntry)) {
147         handler.accept(zipEntry.getName(), input);
148       }
149     }
150   }
151
152   private static void traverseFile(File file, BiConsumer<String, InputStream> handler) throws
153       IOException {
154
155     if (file.isDirectory()) {
156       File[] files = file.listFiles();
157       if (files != null) {
158         for (File sub : files) {
159           traverseFile(sub, handler);
160         }
161       }
162     } else {
163       try (FileInputStream stream = new FileInputStream(file)) {
164         handler.accept(file.getPath(), stream);
165       }
166     }
167   }
168 }