2 * Copyright © 2016-2017 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.translator.utils;
19 import java.io.BufferedReader;
21 import java.io.FileInputStream;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
27 import java.net.URISyntaxException;
29 import java.util.Enumeration;
30 import java.util.HashMap;
32 import java.util.function.BiConsumer;
33 import java.util.function.Predicate;
34 import java.util.zip.ZipEntry;
35 import java.util.zip.ZipFile;
37 import org.apache.commons.io.IOUtils;
38 import org.openecomp.sdc.common.errors.CoreException;
39 import org.openecomp.sdc.common.errors.ErrorCategory;
40 import org.openecomp.sdc.common.errors.ErrorCode;
42 public class ResourceWalker {
44 private static final String RESOURCE_FILE_READ_ERROR = "Can't read resource file from class path.";
46 private ResourceWalker() {
50 * Read resources from directory map.
52 * @param resourceDirectoryToStart the resource directory to start
53 * @return the map of file where key is file name and value is its data
54 * @throws Exception the exception
56 public static Map<String, String> readResourcesFromDirectory(String resourceDirectoryToStart)
59 Map<String, String> filesContent = new HashMap<>();
60 traverse(resourceDirectoryToStart, (fileName, stream) -> {
61 try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
62 filesContent.put(fileName, IOUtils.toString(reader));
63 } catch (IOException exception) {
64 throw new CoreException((new ErrorCode.ErrorCodeBuilder())
65 .withMessage(RESOURCE_FILE_READ_ERROR
66 + " File name = " + fileName)
67 .withId("Resource Read Error").withCategory(ErrorCategory.APPLICATION).build(),
74 private static void traverse(String start, BiConsumer<String, InputStream> handler) throws
77 URL url = ResourceWalker.class.getClassLoader().getResource(start);
79 throw new FileNotFoundException("Resource not found: " + start);
82 switch (url.getProtocol().toLowerCase()) {
85 traverseFile(new File(url.getPath()), handler);
89 String path = url.getPath();
90 int resourcePosition = path.lastIndexOf("!/" + start);
91 traverseArchive(path.substring(0, resourcePosition), start, handler);
94 throw new IllegalArgumentException("Unknown protocol");
98 private static void traverseArchive(String file, String resource, BiConsumer<String, InputStream>
100 throws URISyntaxException, IOException {
102 // There is what looks like a bug in Java:
103 // if "abc" is a directory in an archive,
104 // both "abc" and "abc/" will be found successfully.
105 // However, calling isDirectory() will return "true" for "abc/",
106 // but "false" for "abc".
107 try (ZipFile zip = new ZipFile(new URI(file).getPath())) {
109 Predicate<ZipEntry> predicate = buildPredicate(resource);
110 Enumeration<? extends ZipEntry> entries = zip.entries();
111 while (entries.hasMoreElements()) {
112 handleZipEntry(predicate, zip, entries.nextElement(), handler);
117 private static Predicate<ZipEntry> buildPredicate(String resource) {
119 if (resource.endsWith("/")) {
121 zipEntry.getName().startsWith(resource) && !zipEntry.isDirectory();
124 String name = zipEntry.getName();
125 return (name.equals(resource) || name.startsWith(resource + "/"))
126 && !zipEntry.isDirectory() && !name.contains("../");
131 private static void handleZipEntry(Predicate<ZipEntry> predicate, ZipFile zip, ZipEntry zipEntry,
132 BiConsumer<String, InputStream> handler)
135 if (predicate.test(zipEntry)) {
137 try (InputStream input = zip.getInputStream(zipEntry)) {
138 handler.accept(zipEntry.getName(), input);
143 private static void traverseFile(File file, BiConsumer<String, InputStream> handler) throws
146 if (file.isDirectory()) {
147 File[] files = file.listFiles();
149 for (File sub : files) {
150 traverseFile(sub, handler);
154 try (FileInputStream stream = new FileInputStream(file)) {
155 handler.accept(file.getPath(), stream);