BeanUtils upgrade to 1.9.x
[sdc.git] / openecomp-be / lib / openecomp-common-lib / src / main / java / org / openecomp / sdc / common / utils / CommonUtil.java
1 /*
2  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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  * ============LICENSE_END=========================================================
16  * Modifications copyright (c) 2019 Nokia
17  * ================================================================================
18  */
19
20 package org.openecomp.sdc.common.utils;
21
22 import com.google.common.collect.Multimap;
23
24 import org.apache.commons.collections4.CollectionUtils;
25 import org.apache.commons.io.FilenameUtils;
26 import org.apache.commons.lang3.tuple.ImmutablePair;
27 import org.apache.commons.lang3.tuple.Pair;
28 import org.openecomp.core.utilities.file.FileContentHandler;
29 import org.openecomp.core.utilities.file.FileUtils;
30 import org.openecomp.core.utilities.orchestration.OnboardingTypesEnum;
31 import org.openecomp.sdc.common.errors.CoreException;
32 import org.openecomp.sdc.common.errors.ErrorCategory;
33 import org.openecomp.sdc.common.errors.ErrorCode;
34 import org.openecomp.sdc.common.errors.Messages;
35
36 import java.io.ByteArrayInputStream;
37 import java.io.File;
38 import java.io.IOException;
39 import java.lang.reflect.Field;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.HashSet;
43 import java.util.List;
44 import java.util.Map;
45 import java.util.Objects;
46 import java.util.Optional;
47 import java.util.Set;
48 import java.util.zip.ZipEntry;
49 import java.util.zip.ZipException;
50 import java.util.zip.ZipInputStream;
51
52 public class CommonUtil {
53   static final String DEFAULT = "default";
54   static final String _DEFAULT = "_default";
55
56   private CommonUtil() {
57     // prevent instantiation
58   }
59
60   public static FileContentHandler validateAndUploadFileContent(OnboardingTypesEnum type,
61                                                                 byte[] uploadedFileData)
62       throws IOException {
63     return getFileContentMapFromOrchestrationCandidateZipAndValidateNoFolders(type,
64         uploadedFileData);
65   }
66
67   /**
68    * Gets files out of the zip AND validates zip is flat (no folders)
69    *
70    * @param uploadFileData zip file
71    * @return FileContentHandler if input is valid and has no folders
72    */
73   private static FileContentHandler getFileContentMapFromOrchestrationCandidateZipAndValidateNoFolders(
74       OnboardingTypesEnum type, byte[] uploadFileData)
75       throws IOException {
76     Pair<FileContentHandler, List<String>> pair =
77         getFileContentMapFromOrchestrationCandidateZip(uploadFileData);
78
79     if (isFileOriginFromZip(type.toString())) {
80       validateNoFolders(pair.getRight());
81     }
82
83     return pair.getLeft();
84   }
85
86   public static Pair<FileContentHandler, List<String>> getFileContentMapFromOrchestrationCandidateZip(
87       byte[] uploadFileData)
88       throws IOException {
89     ZipEntry zipEntry;
90     List<String> folderList = new ArrayList<>();
91     FileContentHandler mapFileContent = new FileContentHandler();
92     try (ByteArrayInputStream in = new ByteArrayInputStream(uploadFileData);
93          ZipInputStream inputZipStream = new ZipInputStream(in)) {
94       byte[] fileByteContent;
95       String currentEntryName;
96
97       while ((zipEntry = inputZipStream.getNextEntry()) != null) {
98         assertEntryNotVulnerable(zipEntry);
99         currentEntryName = zipEntry.getName();
100         fileByteContent = FileUtils.toByteArray(inputZipStream);
101
102         int index = lastIndexFileSeparatorIndex(currentEntryName);
103         if (index != -1) {
104           folderList.add(currentEntryName);
105         }
106         if (isFile(currentEntryName)) {
107           mapFileContent.addFile(currentEntryName, fileByteContent);
108         }
109       }
110
111     } catch (RuntimeException exception) {
112       throw new IOException(exception);
113     }
114
115     return new ImmutablePair<>(mapFileContent, folderList);
116   }
117
118   private static void assertEntryNotVulnerable(ZipEntry entry) throws ZipException {
119     if (entry.getName().contains("../")) {
120       throw new ZipException("Path traversal attempt discovered.");
121     }
122   }
123
124   private static boolean isFile(String currentEntryName) {
125     return !(currentEntryName.endsWith("\\") || currentEntryName.endsWith("/"));
126   }
127
128   private static void validateNoFolders(List<String> folderList) {
129     if (CollectionUtils.isNotEmpty(folderList)) {
130       throw new CoreException((new ErrorCode.ErrorCodeBuilder())
131           .withMessage(Messages.ZIP_SHOULD_NOT_CONTAIN_FOLDERS.getErrorMessage())
132           .withId(Messages.ZIP_SHOULD_NOT_CONTAIN_FOLDERS.getErrorMessage())
133           .withCategory(ErrorCategory.APPLICATION).build());
134     }
135   }
136
137   private static int lastIndexFileSeparatorIndex(String filePath) {
138     int length = filePath.length() - 1;
139
140     for (int i = length; i >= 0; i--) {
141       char currChar = filePath.charAt(i);
142       if (currChar == '/' || currChar == File.separatorChar || currChar == File.pathSeparatorChar) {
143         return i;
144       }
145     }
146     // if we've reached to the start of the string and didn't find file separator - return -1
147     return -1;
148   }
149
150   private static boolean validateFilesExtensions(Set<String> allowedExtensions, FileContentHandler
151       files) {
152     for (String fileName : files.getFileList()) {
153       if (!allowedExtensions.contains(FilenameUtils.getExtension(fileName))) {
154         return false;
155       }
156     }
157     return true;
158   }
159
160   public static boolean validateAllFilesYml(FileContentHandler files) {
161     Set<String> allowedExtensions = new HashSet<>(Arrays.asList("yml", "yaml"));
162     return validateFilesExtensions(allowedExtensions, files);
163   }
164
165   public static boolean isFileOriginFromZip(String fileOrigin) {
166     return Objects.nonNull(fileOrigin)
167         && fileOrigin.equalsIgnoreCase(OnboardingTypesEnum.ZIP.toString());
168   }
169
170   public static Set<String> getClassFieldNames(Class<? extends Object> classType) {
171     Set<String> fieldNames = new HashSet<>();
172     Arrays.stream(classType.getDeclaredFields()).forEach(field -> fieldNames.add(field.getName()));
173
174     return fieldNames;
175   }
176
177   public static <T> Optional<T> createObjectUsingSetters(Object objectCandidate,
178                                                          Class<T> classToCreate)
179       throws Exception {
180     return org.onap.sdc.tosca.services.CommonUtil.createObjectUsingSetters(objectCandidate, classToCreate);
181   }
182
183   private static boolean isComplexClass(Field field) {
184     return !field.getType().equals(Map.class)
185         && !field.getType().equals(String.class)
186         && !field.getType().equals(Integer.class)
187         && !field.getType().equals(Float.class)
188         && !field.getType().equals(Double.class)
189         && !field.getType().equals(Set.class)
190         && !field.getType().equals(Object.class)
191         && !field.getType().equals(List.class);
192   }
193
194   public static Map<String, Object> getObjectAsMap(Object obj) {
195     return org.onap.sdc.tosca.services.CommonUtil.getObjectAsMap(obj);
196   }
197
198     public static <K, V> boolean isMultimapEmpty(Multimap<K, V> obj) {
199         return Objects.isNull(obj) || obj.isEmpty();
200     }
201 }