Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ConfigDeserializer.java
Go to the documentation of this file.
1/*
2 * Autopsy Forensic Browser
3 *
4 * Copyright 2020 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
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 */
19package org.sleuthkit.autopsy.integrationtesting.config;
20
21import com.fasterxml.jackson.databind.JsonNode;
22import com.fasterxml.jackson.databind.ObjectMapper;
23import com.fasterxml.jackson.databind.type.CollectionType;
24import com.google.gson.Gson;
25import com.google.gson.GsonBuilder;
26import com.google.gson.JsonElement;
27import java.io.File;
28import java.io.IOException;
29import java.lang.reflect.Type;
30import java.util.Arrays;
31import java.util.Collection;
32import java.util.Collections;
33import java.util.HashMap;
34import java.util.List;
35import java.util.Map;
36import java.util.logging.Level;
37import org.sleuthkit.autopsy.coreutils.Logger;
38import java.util.stream.Collectors;
39import java.util.stream.IntStream;
40import org.apache.commons.io.FileUtils;
41import org.apache.commons.lang.StringUtils;
42import org.apache.commons.collections.CollectionUtils;
43import org.sleuthkit.autopsy.integrationtesting.PathUtil;
44
48public class ConfigDeserializer {
49
50 private static final String JSON_EXT = "json";
51 private static final Logger logger = Logger.getLogger(ConfigDeserializer.class.getName());
52 private static final ObjectMapper mapper = new ObjectMapper();
53
54 // The following are the keys that must be provided as arguments (prefixed with 'integration-test.')
55 // A config file key must be specifed or at least the test suites path, and output path.
56 // If a config specifying the EnvConfig json exists, specify this path to load it
57 private static final String CONFIG_FILE_KEY = "configFile";
58 // expecting properties are marked as "integration-test.propVal"
59 private static final String INTEGRATION_TEST_NAMESPACE = "integration-test";
60
72 public EnvConfig getEnvConfigFromSysProps() throws IOException, IllegalStateException {
73 String configFileKey = String.join(".", INTEGRATION_TEST_NAMESPACE, CONFIG_FILE_KEY);
74 if (System.getProperty(configFileKey) != null) {
75 // try to load from file if value is present
76 String fileLoc = System.getProperty(configFileKey);
77 File envConfigFile = new File(fileLoc);
78 if (envConfigFile.exists()) {
79 return getEnvConfig(envConfigFile);
80 } else {
81 throw new IllegalStateException(String.format("No file exists at %s", fileLoc));
82 }
83 } else {
84 // otherwise, try to load from properties
85 try {
86 Map<String, Object> integrationProperties = getOrCreate(getSysPropsMap(), INTEGRATION_TEST_NAMESPACE);
87 return validate(null, convertToObj(integrationProperties, EnvConfig.class));
88 } catch (IllegalStateException ex) {
89 throw new IllegalStateException("EnvConfig could not be determined from system property values", ex);
90 }
91 }
92 }
93
102 private Map<String, Object> getSysPropsMap() {
103 Map<String, Object> mapToRet = new HashMap<>();
104
105 for (String key : System.getProperties().stringPropertyNames()) {
106 String value = System.getProperty(key);
107
108 String[] keyPieces = key.split("\\.");
109 Map<String, Object> mapToAddTo = mapToRet;
110 for (int i = 0; i < keyPieces.length - 1; i++) {
111 mapToAddTo = getOrCreate(mapToAddTo, keyPieces[i]);
112 }
113
114 mapToAddTo.put(keyPieces[keyPieces.length - 1], value);
115 }
116
117 return mapToRet;
118 }
119
125 private static class StringObjMap extends HashMap<String, Object> {
126
127 private static final long serialVersionUID = 1L;
128
132 StringObjMap() {
133 }
134
135 }
136
145 private Map<String, Object> getOrCreate(Map<String, Object> parent, String key) {
146 Object child = parent.get(key);
147 if (child instanceof StringObjMap) {
148 return (StringObjMap) child;
149 } else {
150 Map<String, Object> toRet = new StringObjMap();
151 parent.put(key, toRet);
152 return toRet;
153 }
154 }
155
164 public <T> T convertToObj(Map<String, Object> toConvert, Type clazz) {
165 GsonBuilder builder = new GsonBuilder();
166 Gson gson = builder.create();
167 JsonElement jsonElement = gson.toJsonTree(toConvert);
168 return gson.fromJson(jsonElement, clazz);
169 }
170
180 public IntegrationTestConfig getIntegrationTestConfig() throws IOException, IllegalStateException {
182 String testSuiteConfigPath = PathUtil.getAbsolutePath(envConfig.getWorkingDirectory(), envConfig.getRootTestSuitesPath());
183
184 return new IntegrationTestConfig(
185 getTestSuiteConfigs(new File(testSuiteConfigPath)),
186 envConfig
187 );
188 }
189
198 public EnvConfig getEnvConfig(File envConfigFile) throws IOException, IllegalStateException {
199 EnvConfig config = mapper.readValue(envConfigFile, EnvConfig.class);
200 return validate(envConfigFile, config);
201 }
202
212 private EnvConfig validate(File envConfigFile, EnvConfig config) throws IllegalStateException {
213 // set working directory based off of parent of envConfigFile if that parent exists
214 if (config.getWorkingDirectory() == null && envConfigFile != null && envConfigFile.getParentFile() != null) {
215 config.setWorkingDirectory(envConfigFile.getParentFile().getAbsolutePath());
216 }
217
218 // env config should be non-null after validation
219 if (config == null
220 || StringUtils.isBlank(config.getRootCaseOutputPath())
221 || StringUtils.isBlank(config.getRootTestOutputPath())) {
222 throw new IllegalStateException("EnvConfig must have the root case output path and the root test output path set.");
223 }
224
225 return config;
226 }
227
238 public List<TestSuiteConfig> getTestSuiteConfig(File rootDirectory, File configFile) {
239 try {
240 JsonNode root = mapper.readTree(configFile);
241 if (root.isArray()) {
242 // Define a collection type of List<TestSuiteConfig> for the purposes of json deserialization.
243 CollectionType listClass = mapper.getTypeFactory().constructCollectionType(List.class,
244 TestSuiteConfig.class
245 );
246
247 // This suppresses compiler warning for this cast.
248 @SuppressWarnings("unchecked")
249 List<TestSuiteConfig> testSuites = (List<TestSuiteConfig>) mapper.readValue(mapper.treeAsTokens(root), listClass);
250
251 return validate(rootDirectory, configFile, testSuites);
252 } else {
253 return validate(rootDirectory, configFile, Arrays.asList(mapper.treeToValue(root, TestSuiteConfig.class
254 )));
255 }
256 } catch (IOException ex) {
257 logger.log(Level.WARNING, "Unable to read test suite config at " + configFile.getPath(), ex);
258 return Collections.emptyList();
259 }
260 }
261
270 public List<TestSuiteConfig> getTestSuiteConfigs(File fileOrDirectory) {
271 if (fileOrDirectory.isDirectory()) {
272 Collection<File> jsonFiles = FileUtils.listFiles(fileOrDirectory, new String[]{JSON_EXT}, true);
273 return jsonFiles.stream()
274 .flatMap((file) -> getTestSuiteConfig(fileOrDirectory, file).stream())
275 .collect(Collectors.toList());
276 } else if (fileOrDirectory.isFile()) {
277 return getTestSuiteConfig(fileOrDirectory, fileOrDirectory);
278 }
279
280 logger.log(Level.WARNING, "Unable to read file at: {0}", fileOrDirectory);
281 return Collections.emptyList();
282 }
283
295 private List<TestSuiteConfig> validate(File rootDirectory, File file, List<TestSuiteConfig> testSuites) {
296 return IntStream.range(0, testSuites.size())
297 .mapToObj(idx -> validate(rootDirectory, file, idx, testSuites.get(idx)))
298 .filter(c -> c != null)
299 .collect(Collectors.toList());
300 }
301
316 private TestSuiteConfig validate(File rootDirectory, File file, int index, TestSuiteConfig config) {
317 if (config == null
318 || StringUtils.isBlank(config.getName())
319 || config.getCaseTypes() == null
320 || CollectionUtils.isEmpty(config.getDataSources())
321 || config.getIntegrationTests() == null) {
322
323 logger.log(Level.WARNING, String.format("Item in %s at index %d must contain a valid 'name', 'caseTypes', 'dataSources', and 'integrationTests'", file.toString(), index));
324 return null;
325 }
326
327 if (config.getRelativeOutputPath() == null) {
328 // taken from https://stackoverflow.com/questions/204784/how-to-construct-a-relative-path-in-java-from-two-absolute-paths-or-urls
329 String relative = rootDirectory.toURI().relativize(file.toURI()).getPath();
330 if (relative.endsWith("." + JSON_EXT)) {
331 relative = relative.substring(0, relative.length() - ("." + JSON_EXT).length());
332 }
333 config.setRelativeOutputPath(relative);
334 }
335
336 return config;
337 }
338}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static String getAbsolutePath(String workingDirectory, String relPath)
Definition PathUtil.java:40
Map< String, Object > getOrCreate(Map< String, Object > parent, String key)
List< TestSuiteConfig > getTestSuiteConfigs(File fileOrDirectory)
List< TestSuiteConfig > validate(File rootDirectory, File file, List< TestSuiteConfig > testSuites)
TestSuiteConfig validate(File rootDirectory, File file, int index, TestSuiteConfig config)
List< TestSuiteConfig > getTestSuiteConfig(File rootDirectory, File configFile)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.