1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.polago.deployconf.task.properties;
26
27 import java.io.BufferedWriter;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.io.OutputStreamWriter;
32 import java.util.LinkedHashSet;
33 import java.util.Set;
34
35 import org.jdom2.Element;
36 import org.polago.deployconf.InteractiveConfigurer;
37 import org.polago.deployconf.group.ConfigGroup;
38 import org.polago.deployconf.group.ConfigGroupManager;
39 import org.polago.deployconf.task.AbstractTask;
40 import org.polago.deployconf.task.Task;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44
45
46
47 public class PropertiesTask extends AbstractTask {
48
49 private static Logger logger = LoggerFactory.getLogger(PropertiesTask.class);
50
51
52
53
54 public static final String DOM_ELEMENT_TASK = "properties";
55
56 private static final String DOM_ELEMENT_PROPERTY = "property";
57
58 protected static final String DOM_ELEMENT_NAME = "name";
59
60
61 private static final String ENCODING = "ISO-8859-1";
62
63 private static final String PATH_IGNORE = PropertiesTask.class.getCanonicalName() + "_NO_PATH";;
64
65 private Set<Property> properties;
66
67
68
69
70
71
72 public PropertiesTask(ConfigGroupManager groupManager) {
73 super(groupManager);
74 properties = new LinkedHashSet<Property>();
75 }
76
77
78
79
80 @Override
81 public void deserialize(Element node) throws IOException {
82 String attribute = node.getAttributeValue(DOM_ATTRIBUTE_PATH);
83 if (attribute == null) {
84 attribute = PATH_IGNORE;
85 }
86 setPath(attribute);
87
88 for (Element e : node.getChildren()) {
89 String name = e.getChildTextTrim(DOM_ELEMENT_NAME);
90 if (name.length() == 0) {
91 throw new IllegalStateException("Property name element does not exists");
92 }
93 String description = e.getChildTextTrim(DOM_ELEMENT_DESCRIPTION);
94 if (description.length() == 0) {
95 throw new IllegalStateException("Property description element does not exists");
96 }
97 String defaultValue = e.getChildTextTrim(DOM_ELEMENT_DEFAULT);
98
99 String group = e.getAttributeValue(DOM_ATTRIBUTE_GROUP);
100 String value = null;
101
102 if (group != null) {
103 value = getGroupManager().lookupGroup(group).getProperty(name);
104 }
105
106 if (value == null) {
107 value = e.getChildTextTrim(DOM_ELEMENT_VALUE);
108 if (group != null && value != null) {
109 logger.debug("Populating group {} with value of name {}: {}", group, name, value);
110 getGroupManager().lookupGroup(group).setProperty(name, value);
111 }
112 }
113
114 Property p = new Property(name, description, defaultValue, value);
115
116 if (group != null) {
117 p.setGroup(group);
118 }
119
120 p.setCondition(e.getChildTextTrim(DOM_ELEMENT_CONDITION));
121
122 logger.debug("Deserializing property: {}", p);
123
124 properties.add(p);
125 }
126 }
127
128
129
130
131 @Override
132 public void serialize(Element node) throws IOException {
133 if (!PATH_IGNORE.equals(getPath())) {
134 node.setAttribute(DOM_ATTRIBUTE_PATH, getPath());
135 }
136
137 for (Property p : properties) {
138 logger.debug("Serializing property: {}", p);
139 Element e = createJDOMElement(DOM_ELEMENT_PROPERTY);
140 e.addContent(createJDOMTextElement(DOM_ELEMENT_NAME, p.getName()));
141 e.addContent(createJDOMCDATAElement(DOM_ELEMENT_DESCRIPTION, p.getDescription()));
142 e.addContent(createJDOMTextElement(DOM_ELEMENT_DEFAULT, p.getDefaultValue()));
143 e.addContent(createJDOMTextElement(DOM_ELEMENT_CONDITION, p.getCondition()));
144
145 String group = p.getGroup();
146 if (group != null) {
147 e.setAttribute(DOM_ATTRIBUTE_GROUP, group);
148 } else {
149 e.addContent(createJDOMTextElement(DOM_ELEMENT_VALUE, p.getValue()));
150 }
151
152 node.addContent(e);
153 }
154 }
155
156
157
158
159
160
161 public Set<Property> getProperties() {
162 return properties;
163 }
164
165
166
167
168
169
170 void setProperties(Set<Property> properties) {
171 this.properties = properties;
172 }
173
174
175
176
177 @Override
178 public void merge(Task other) {
179 if (other instanceof PropertiesTask) {
180 PropertiesTask opt = (PropertiesTask) other;
181 properties.retainAll(opt.getProperties());
182
183 for (Property op : opt.getProperties()) {
184 boolean exists = false;
185 for (Property p : properties) {
186 if (p.equals(op)) {
187 exists = true;
188 p.setDescription(op.getDescription());
189 p.setDefaultValue(op.getDefaultValue());
190 p.setGroup(op.getGroup());
191 p.setCondition(op.getCondition());
192 logger.debug("Merging existing Property: {}", p);
193 break;
194 }
195 }
196 if (!exists) {
197 logger.debug("Adding new Property: {}", op);
198 properties.add(op);
199 }
200 }
201 }
202 }
203
204
205
206
207 @Override
208 public boolean isConfigured() throws IOException {
209 for (Property p : properties) {
210 if (evaluateCondition(p.getCondition(), getGroupManager().lookupGroup(p.getGroup()))) {
211 if (p.getValue() == null || p.getValue().length() == 0) {
212 logger.debug("Property is not configured: {}", p);
213 return false;
214 }
215 }
216 }
217
218 return true;
219 }
220
221
222
223
224 @Override
225 public boolean configureInteractively(InteractiveConfigurer configurer, boolean force) throws Exception {
226
227 boolean configured = true;
228
229 for (Property p : properties) {
230 ConfigGroup group = getGroupManager().lookupGroup(p.getGroup());
231 if (evaluateCondition(p.getCondition(), group)
232 && (force || p.getValue() == null || p.getValue().length() == 0)) {
233 configured = configurePropertyInteractively(p, configurer);
234 if (configured) {
235 group.setProperty(p.getName(), p.getValue());
236 } else {
237 return configured;
238 }
239 }
240 }
241
242 return configured;
243 }
244
245
246
247
248 @Override
249 public String getSerializedName() {
250 return DOM_ELEMENT_TASK;
251 }
252
253
254
255
256 @Override
257 public void apply(InputStream source, OutputStream destination) throws Exception {
258
259 if (PATH_IGNORE.equals(getPath())) {
260
261 return;
262 }
263
264 OutputStreamWriter out = new OutputStreamWriter(destination, ENCODING);
265 BufferedWriter writer = new BufferedWriter(out);
266
267 for (Property p : getProperties()) {
268 ConfigGroup group = getGroupManager().lookupGroup(p.getGroup());
269 if (evaluateCondition(p.getCondition(), group)) {
270 writer.newLine();
271 String description = p.getDescription();
272 if (description != null) {
273 writer.append("#");
274 writer.newLine();
275 String[] lines = description.split("[\\r\\n]+");
276 for (String line : lines) {
277 writer.append("# ");
278 writer.append(line.trim());
279 writer.newLine();
280 }
281 writer.append("#");
282 writer.newLine();
283 }
284 writer.append(p.getName());
285 writer.append("=");
286
287 String value = expandPropertyExpression(p.getValue(), group);
288 writer.append(value);
289 writer.newLine();
290 }
291 }
292 writer.flush();
293 }
294
295
296
297
298
299
300
301
302
303 private boolean configurePropertyInteractively(Property p, InteractiveConfigurer configurer) throws IOException {
304
305 boolean result = false;
306
307 logger.debug("Configure interactively: {}", p.getName());
308
309 String defaultValue = p.getValue();
310 if (defaultValue == null || defaultValue.length() == 0) {
311 defaultValue = p.getDefaultValue();
312 }
313
314 String value = configurer.configure(p.getName(), p.getDescription(), defaultValue);
315
316 logger.debug("Configure interactively result for '{}': {}", p.getName(), value);
317
318 if (value != null) {
319 p.setValue(value);
320 result = true;
321 }
322
323 return result;
324 }
325
326
327
328
329 @Override
330 public String toString() {
331 return "PropertiesTask [path=" + getPath() + ", properties=" + properties + "]";
332 }
333
334
335 }