Skip to content

Commit 444fb10

Browse files
committed
added SettingsStore class
1 parent 6d78fb8 commit 444fb10

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
// Copyright (c) 2023, Oracle and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
package com.oracle.weblogic.imagetool.settings;
5+
6+
import java.io.IOException;
7+
import java.io.InputStream;
8+
import java.io.OutputStreamWriter;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.util.Collections;
12+
import java.util.Map;
13+
14+
import com.oracle.weblogic.imagetool.logging.LoggingFacade;
15+
import com.oracle.weblogic.imagetool.logging.LoggingFactory;
16+
import org.yaml.snakeyaml.DumperOptions;
17+
import org.yaml.snakeyaml.Yaml;
18+
import org.yaml.snakeyaml.introspector.Property;
19+
import org.yaml.snakeyaml.introspector.PropertyUtils;
20+
import org.yaml.snakeyaml.nodes.NodeTuple;
21+
import org.yaml.snakeyaml.nodes.Tag;
22+
import org.yaml.snakeyaml.representer.Representer;
23+
24+
public class SettingsStore {
25+
private static final LoggingFacade logger = LoggingFactory.getLogger(SettingsStore.class);
26+
27+
private Path filePath;
28+
29+
public SettingsStore(Path pathToFile) {
30+
filePath = pathToFile;
31+
}
32+
33+
/**
34+
* Utility method to convert the InputStream with YAML into UserSettings.
35+
* @param settings An InputStream with raw YAML text.
36+
* @return The UserSettings containing the parsed values from the InputStream.
37+
*/
38+
private Map<String, Object> load(InputStream settings) {
39+
// While yaml.loadAs() will do about the same thing, I opted to use Map because Map is more forgiving.
40+
// Bad fields or extra data fields not in this version of ImageTool will cause yaml.loadAs to completely fail.
41+
logger.entering();
42+
Yaml yaml = new Yaml();
43+
Map<String, Object> map = yaml.load(settings);
44+
logger.exiting(map);
45+
return map;
46+
}
47+
48+
/**
49+
* Loads the settings from the YAML file and returns the loaded file as a Map.
50+
*/
51+
public Map<String, Object> load() {
52+
logger.entering(filePath);
53+
Map<String, Object> map = Collections.emptyMap();
54+
try (InputStream input = Files.newInputStream(filePath)) {
55+
map = load(input);
56+
} catch (IOException ioe) {
57+
// If exception occurs, map will be empty. parseMap() must handle both empty and populated map.
58+
}
59+
logger.exiting(map);
60+
return map;
61+
}
62+
63+
private static Representer getYamlRepresenter() {
64+
// Created this inline override to suppress the output of null for all unset user settings
65+
Representer representer = new Representer() {
66+
@Override
67+
protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue,
68+
Tag customTag) {
69+
// if value of property is null, ignore it.
70+
if (propertyValue == null) {
71+
return null;
72+
} else {
73+
return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
74+
}
75+
}
76+
};
77+
representer.addClassTag(UserSettingsFile.class, Tag.MAP);
78+
representer.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
79+
80+
PropertyUtils propertyUtils = new PropertyUtils();
81+
propertyUtils.setAllowReadOnlyProperties(true);
82+
representer.setPropertyUtils(propertyUtils);
83+
return representer;
84+
}
85+
86+
/**
87+
* Save all settings to the specified file.
88+
* @throws IOException if an error occurs saving to the filesystem
89+
*/
90+
public void save(Object data) throws IOException {
91+
Path parent = filePath.getParent();
92+
if (parent != null && Files.notExists(parent)) {
93+
Files.createDirectories(parent);
94+
}
95+
96+
try (OutputStreamWriter output = new OutputStreamWriter(Files.newOutputStream(filePath))) {
97+
Yaml yaml = new Yaml(getYamlRepresenter());
98+
yaml.dump(data, output);
99+
} catch (IOException ioe) {
100+
logger.severe("Failed saved user settings: {0}", ioe.getMessage(), ioe);
101+
throw ioe;
102+
}
103+
}
104+
105+
/**
106+
* Get the value for the setting by name from the provided settings map.
107+
* This method is intended to be used for leaf attributes (not folders).
108+
* @param settingName The attribute name of the setting
109+
* @param type The type of the attribute value (for cast)
110+
* @param settings The map of settings from which the attribute is to be retrieved
111+
* @return The value of the requested attribute.
112+
*/
113+
public static <T> T getValue(String settingName, Class<T> type, Map<String, Object> settings) {
114+
if (settings == null) {
115+
return null;
116+
}
117+
118+
Object value = settings.get(settingName);
119+
if (value == null) {
120+
return null;
121+
}
122+
123+
if (type.isInstance(value)) {
124+
return type.cast(value);
125+
}
126+
127+
logger.severe("Setting for {0} could not be loaded. Expected {1}, but found {2}. Invalid value: {3}",
128+
settingName, type, value.getClass(), value.toString());
129+
return null;
130+
}
131+
132+
/**
133+
* Get the folder for the settings by name from the provided settings map.
134+
* For nested maps withing the settings map.
135+
*
136+
* @param folderName The key/name of the map/folder to be returned
137+
* @param settings The settings from which the map/folder is to be retrieved.
138+
* @return A map of settings matching the folder name provided, or empty map if not found.
139+
*/
140+
@SuppressWarnings("unchecked")
141+
public static Map<String, Object> getFolder(String folderName, Map<String, Object> settings) {
142+
if (settings == null) {
143+
return Collections.emptyMap();
144+
}
145+
146+
Object value = settings.get(folderName);
147+
if (value == null) {
148+
return Collections.emptyMap();
149+
}
150+
151+
if (value instanceof Map) {
152+
return (Map<String, Object>) value;
153+
}
154+
155+
//TODO needs to be an exception that will be caught and displayed as a parsing config error.
156+
logger.severe("Setting for {0} could not be loaded. Invalid value: {3}",
157+
folderName, value.toString());
158+
return Collections.emptyMap();
159+
}
160+
161+
/**
162+
* Convert settings object to a YAML string.
163+
* @return formatted YAML text.
164+
*/
165+
public static String asYaml(Object value) {
166+
Yaml yaml = new Yaml(getYamlRepresenter());
167+
return yaml.dump(value);
168+
}
169+
}

0 commit comments

Comments
 (0)