1 package org.codehaus.plexus.classworlds.launcher;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import java.io.BufferedReader;
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.InputStreamReader;
25 import java.net.MalformedURLException;
26 import java.net.URL;
27 import java.nio.charset.StandardCharsets;
28 import java.nio.file.Files;
29 import java.nio.file.Paths;
30 import java.util.Properties;
31
32 import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
33 import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
34
35
36
37
38
39
40
41
42
43 public class ConfigurationParser {
44 public static final String MAIN_PREFIX = "main is";
45
46 public static final String SET_PREFIX = "set";
47
48 public static final String IMPORT_PREFIX = "import";
49
50 public static final String LOAD_PREFIX = "load";
51
52
53
54
55 public static final String OPTIONALLY_PREFIX = "optionally";
56
57 protected static final String FROM_SEPARATOR = " from ";
58
59 protected static final String USING_SEPARATOR = " using ";
60
61 protected static final String DEFAULT_SEPARATOR = " default ";
62
63 private final ConfigurationHandler handler;
64
65 private final Properties systemProperties;
66
67 public ConfigurationParser(ConfigurationHandler handler, Properties systemProperties) {
68 this.handler = handler;
69 this.systemProperties = systemProperties;
70 }
71
72
73
74
75
76
77
78
79
80
81 public void parse(InputStream is)
82 throws IOException, ConfigurationException, DuplicateRealmException, NoSuchRealmException {
83 try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
84
85 String line;
86
87 int lineNo = 0;
88
89 boolean mainSet = false;
90
91 String curRealm = null;
92
93 while (true) {
94 line = reader.readLine();
95
96 if (line == null) {
97 break;
98 }
99
100 ++lineNo;
101 line = line.trim();
102
103 if (canIgnore(line)) {
104 continue;
105 }
106
107 char lineFirstChar = line.charAt(0);
108 switch (lineFirstChar) {
109 case 'm': {
110 if (line.startsWith(MAIN_PREFIX)) {
111 if (mainSet) {
112 throw new ConfigurationException("Duplicate main configuration", lineNo, line);
113 }
114
115 int fromLoc = line.indexOf(FROM_SEPARATOR, MAIN_PREFIX.length());
116
117 if (fromLoc < 0) {
118 throw new ConfigurationException("Missing from clause", lineNo, line);
119 }
120
121 String mainClassName = filter(line.substring(MAIN_PREFIX.length(), fromLoc)
122 .trim());
123
124 String mainRealmName = filter(line.substring(fromLoc + FROM_SEPARATOR.length())
125 .trim());
126
127 this.handler.setAppMain(mainClassName, mainRealmName);
128
129 mainSet = true;
130
131 break;
132 }
133 throw new ConfigurationException("Unhandled configuration", lineNo, line);
134 }
135 case 's': {
136 if (line.startsWith(SET_PREFIX)) {
137 String conf = line.substring(SET_PREFIX.length()).trim();
138
139 int usingLoc = conf.indexOf(USING_SEPARATOR);
140
141 String property = null;
142
143 String propertiesFileName = null;
144
145 if (usingLoc >= 0) {
146 property = conf.substring(0, usingLoc).trim();
147
148 propertiesFileName = filter(conf.substring(usingLoc + USING_SEPARATOR.length())
149 .trim());
150
151 conf = propertiesFileName;
152 }
153
154 String defaultValue = null;
155
156 int defaultLoc = conf.indexOf(DEFAULT_SEPARATOR);
157
158 if (defaultLoc >= 0) {
159 defaultValue = filter(conf.substring(defaultLoc + DEFAULT_SEPARATOR.length())
160 .trim());
161
162 if (property == null) {
163 property = conf.substring(0, defaultLoc).trim();
164 } else {
165 propertiesFileName =
166 conf.substring(0, defaultLoc).trim();
167 }
168 }
169
170 String value = systemProperties.getProperty(property);
171
172 if (value != null) {
173 continue;
174 }
175
176 if (propertiesFileName != null) {
177 File propertiesFile = new File(propertiesFileName);
178
179 if (propertiesFile.exists()) {
180 Properties properties = new Properties();
181
182 try (InputStream inputStream =
183 Files.newInputStream(Paths.get(propertiesFileName))) {
184 properties.load(inputStream);
185 value = properties.getProperty(property);
186 } catch (Exception e) {
187
188 }
189 }
190 }
191
192 if (value == null && defaultValue != null) {
193 value = defaultValue;
194 }
195
196 if (value != null) {
197 value = filter(value);
198 systemProperties.setProperty(property, value);
199 }
200
201 break;
202 }
203 throw new ConfigurationException("Unhandled configuration", lineNo, line);
204 }
205 case '[': {
206 int rbrack = line.indexOf("]");
207
208 if (rbrack < 0) {
209 throw new ConfigurationException("Invalid realm specifier", lineNo, line);
210 }
211
212 String realmName = line.substring(1, rbrack);
213
214 handler.addRealm(realmName);
215
216 curRealm = realmName;
217
218 break;
219 }
220 case 'i': {
221 if (line.startsWith(IMPORT_PREFIX)) {
222 if (curRealm == null) {
223 throw new ConfigurationException("Unhandled import", lineNo, line);
224 }
225 int fromLoc = line.indexOf(FROM_SEPARATOR, IMPORT_PREFIX.length());
226
227 if (fromLoc < 0) {
228 throw new ConfigurationException("Missing from clause", lineNo, line);
229 }
230
231 String importSpec = line.substring(IMPORT_PREFIX.length(), fromLoc)
232 .trim();
233
234 String relamName = line.substring(fromLoc + FROM_SEPARATOR.length())
235 .trim();
236
237 handler.addImportFrom(relamName, importSpec);
238
239 break;
240 }
241 throw new ConfigurationException("Unhandled configuration", lineNo, line);
242 }
243 case 'l': {
244 if (line.startsWith(LOAD_PREFIX)) {
245 String constituent =
246 line.substring(LOAD_PREFIX.length()).trim();
247
248 constituent = filter(constituent);
249
250 if (constituent.contains("*")) {
251 loadGlob(constituent, false );
252 } else {
253 File file = new File(constituent);
254
255 if (file.exists()) {
256 handler.addLoadFile(file);
257 } else {
258 try {
259 handler.addLoadURL(new URL(constituent));
260 } catch (MalformedURLException e) {
261 throw new FileNotFoundException(constituent);
262 }
263 }
264 }
265
266 break;
267 }
268 throw new ConfigurationException("Unhandled configuration", lineNo, line);
269 }
270 case 'o': {
271 if (line.startsWith(OPTIONALLY_PREFIX)) {
272 String constituent =
273 line.substring(OPTIONALLY_PREFIX.length()).trim();
274
275 constituent = filter(constituent);
276
277 if (constituent.contains("*")) {
278 loadGlob(constituent, true );
279 } else {
280 File file = new File(constituent);
281
282 if (file.exists()) {
283 handler.addLoadFile(file);
284 } else {
285 try {
286 handler.addLoadURL(new URL(constituent));
287 } catch (MalformedURLException e) {
288
289 }
290 }
291 }
292
293 break;
294 }
295 throw new ConfigurationException("Unhandled configuration", lineNo, line);
296 }
297 default:
298 throw new ConfigurationException("Unhandled configuration", lineNo, line);
299 }
300 }
301 }
302 }
303
304
305
306
307
308
309
310
311
312
313
314
315 @SuppressWarnings("RedundantThrows")
316 protected void loadGlob(String line, boolean optionally)
317 throws MalformedURLException, FileNotFoundException, ConfigurationException {
318 File globFile = new File(line);
319
320 File dir = globFile.getParentFile();
321 if (!dir.exists()) {
322 if (optionally) {
323 return;
324 } else {
325 throw new FileNotFoundException(dir.toString());
326 }
327 }
328
329 String localName = globFile.getName();
330
331 int starLoc = localName.indexOf("*");
332
333 final String prefix = localName.substring(0, starLoc);
334
335 final String suffix = localName.substring(starLoc + 1);
336
337 File[] matches = dir.listFiles((dir1, name) -> name.startsWith(prefix) || name.endsWith(suffix));
338
339 if (matches != null) {
340 for (File match : matches) {
341 handler.addLoadFile(match);
342 }
343 }
344 }
345
346
347
348
349
350
351
352
353
354 protected String filter(String text) throws ConfigurationException {
355 StringBuilder result = new StringBuilder();
356
357 int cur = 0;
358 int textLen = text.length();
359
360 int propStart;
361 int propStop;
362
363 String propName;
364 String propValue;
365
366 while (cur < textLen) {
367 propStart = text.indexOf("${", cur);
368
369 if (propStart < 0) {
370 break;
371 }
372
373 result.append(text, cur, propStart);
374
375 propStop = text.indexOf("}", propStart);
376
377 if (propStop < 0) {
378 throw new ConfigurationException("Unterminated property: " + text.substring(propStart));
379 }
380
381 propName = text.substring(propStart + 2, propStop);
382
383 propValue = systemProperties.getProperty(propName);
384
385
386 if (propName.equals("basedir") && (propValue == null || propValue.isEmpty())) {
387 propValue = (new File("")).getAbsolutePath();
388 }
389
390 if (propValue == null) {
391 throw new ConfigurationException("No such property: " + propName);
392 }
393 result.append(propValue);
394
395 cur = propStop + 1;
396 }
397
398 result.append(text.substring(cur));
399
400 return result.toString();
401 }
402
403
404
405
406
407
408
409
410
411 private boolean canIgnore(String line) {
412 return (line.isEmpty() || line.startsWith("#"));
413 }
414 }