|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
Configurator.java | 87.5% | 92.7% | 81.8% | 90.6% |
|
1 |
package org.codehaus.classworlds;
|
|
2 |
|
|
3 |
/*
|
|
4 |
$Id: Configurator.java,v 1.3 2004/09/07 13:17:42 brett Exp $
|
|
5 |
|
|
6 |
Copyright 2002 (C) The Werken Company. All Rights Reserved.
|
|
7 |
|
|
8 |
Redistribution and use of this software and associated documentation
|
|
9 |
("Software"), with or without modification, are permitted provided
|
|
10 |
that the following conditions are met:
|
|
11 |
|
|
12 |
1. Redistributions of source code must retain copyright
|
|
13 |
statements and notices. Redistributions must also contain a
|
|
14 |
copy of this document.
|
|
15 |
|
|
16 |
2. Redistributions in binary form must reproduce the
|
|
17 |
above copyright notice, this list of conditions and the
|
|
18 |
following disclaimer in the documentation and/or other
|
|
19 |
materials provided with the distribution.
|
|
20 |
|
|
21 |
3. The name "classworlds" must not be used to endorse or promote
|
|
22 |
products derived from this Software without prior written
|
|
23 |
permission of The Werken Company. For written permission,
|
|
24 |
please contact bob@werken.com.
|
|
25 |
|
|
26 |
4. Products derived from this Software may not be called "classworlds"
|
|
27 |
nor may "classworlds" appear in their names without prior written
|
|
28 |
permission of The Werken Company. "classworlds" is a registered
|
|
29 |
trademark of The Werken Company.
|
|
30 |
|
|
31 |
5. Due credit should be given to The Werken Company.
|
|
32 |
(http://classworlds.werken.com/).
|
|
33 |
|
|
34 |
THIS SOFTWARE IS PROVIDED BY THE WERKEN COMPANY AND CONTRIBUTORS
|
|
35 |
``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
|
|
36 |
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
37 |
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
38 |
THE WERKEN COMPANY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
39 |
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
40 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
41 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
42 |
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
43 |
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
44 |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
45 |
OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
46 |
|
|
47 |
*/
|
|
48 |
|
|
49 |
import java.io.BufferedReader;
|
|
50 |
import java.io.File;
|
|
51 |
import java.io.FileNotFoundException;
|
|
52 |
import java.io.FilenameFilter;
|
|
53 |
import java.io.IOException;
|
|
54 |
import java.io.InputStream;
|
|
55 |
import java.io.InputStreamReader;
|
|
56 |
import java.io.FileInputStream;
|
|
57 |
import java.net.MalformedURLException;
|
|
58 |
import java.net.URL;
|
|
59 |
import java.util.ArrayList;
|
|
60 |
import java.util.Collections;
|
|
61 |
import java.util.Comparator;
|
|
62 |
import java.util.HashMap;
|
|
63 |
import java.util.Iterator;
|
|
64 |
import java.util.List;
|
|
65 |
import java.util.Map;
|
|
66 |
import java.util.Properties;
|
|
67 |
|
|
68 |
/**
|
|
69 |
* <code>Launcher</code> configurator.
|
|
70 |
*
|
|
71 |
* @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
|
|
72 |
* @author <a href="mailto:jason@zenplex.com">Jason van Zyl</a>
|
|
73 |
* @version $Id: Configurator.java,v 1.3 2004/09/07 13:17:42 brett Exp $
|
|
74 |
*/
|
|
75 |
public class Configurator |
|
76 |
{ |
|
77 |
public static final String MAIN_PREFIX = "main is"; |
|
78 |
|
|
79 |
public static final String SET_PREFIX = "set"; |
|
80 |
|
|
81 |
public static final String IMPORT_PREFIX = "import"; |
|
82 |
|
|
83 |
public static final String LOAD_PREFIX = "load"; |
|
84 |
|
|
85 |
/** Optionally spec prefix. */
|
|
86 |
public static final String OPTIONALLY_PREFIX = "optionally"; |
|
87 |
|
|
88 |
/** The launcher to configure. */
|
|
89 |
private Launcher launcher;
|
|
90 |
|
|
91 |
private ClassWorld world;
|
|
92 |
|
|
93 |
/** Processed Realms. */
|
|
94 |
private Map configuredRealms;
|
|
95 |
|
|
96 |
/** Construct.
|
|
97 |
*
|
|
98 |
* @param launcher The launcher to configure.
|
|
99 |
*/
|
|
100 | 68 |
public Configurator( Launcher launcher )
|
101 |
{ |
|
102 | 68 |
this.launcher = launcher;
|
103 |
|
|
104 | 68 |
configuredRealms = new HashMap();
|
105 |
} |
|
106 |
|
|
107 |
/** Construct.
|
|
108 |
*
|
|
109 |
* @param classWorld The classWorld to configure.
|
|
110 |
*/
|
|
111 | 0 |
public Configurator( ClassWorld world )
|
112 |
{ |
|
113 | 0 |
setClassWorld( world ); |
114 |
} |
|
115 |
|
|
116 |
/** set world.
|
|
117 |
* this setter is provided so you can use the same configurator to configure several "worlds"
|
|
118 |
*
|
|
119 |
* @param classWorld The classWorld to configure.
|
|
120 |
*/
|
|
121 | 0 |
public void setClassWorld( ClassWorld world ) |
122 |
{ |
|
123 | 0 |
this.world = world;
|
124 |
|
|
125 | 0 |
configuredRealms = new HashMap();
|
126 |
} |
|
127 |
|
|
128 |
/**
|
|
129 |
* Configure from a file.
|
|
130 |
*
|
|
131 |
* @param is The config input stream
|
|
132 |
* @throws IOException If an error occurs reading the config file.
|
|
133 |
* @throws MalformedURLException If the config file contains invalid URLs.
|
|
134 |
* @throws ConfigurationException If the config file is corrupt.
|
|
135 |
* @throws DuplicateRealmException If the config file defines two realms with the same id.
|
|
136 |
* @throws NoSuchRealmException If the config file defines a main entry point in
|
|
137 |
* a non-existent realm.
|
|
138 |
*/
|
|
139 | 52 |
public void configure( InputStream is ) |
140 |
throws IOException, MalformedURLException, ConfigurationException, DuplicateRealmException, NoSuchRealmException
|
|
141 |
{ |
|
142 | 52 |
BufferedReader reader = new BufferedReader( new InputStreamReader( is ) ); |
143 |
|
|
144 | 52 |
if ( world == null ) |
145 |
{ |
|
146 | 52 |
world = new ClassWorld();
|
147 |
} |
|
148 |
|
|
149 | 52 |
ClassRealm curRealm = null;
|
150 |
|
|
151 | 52 |
String line = null;
|
152 |
|
|
153 | 52 |
int lineNo = 0;
|
154 |
|
|
155 | 52 |
boolean mainSet = false; |
156 |
|
|
157 | 52 |
while ( true ) |
158 |
{ |
|
159 | 660 |
line = reader.readLine(); |
160 |
|
|
161 | 660 |
if ( line == null ) |
162 |
{ |
|
163 | 42 |
break;
|
164 |
} |
|
165 |
|
|
166 | 618 |
++lineNo; |
167 | 618 |
line = line.trim(); |
168 |
|
|
169 | 618 |
if ( canIgnore( line ) )
|
170 |
{ |
|
171 | 422 |
continue;
|
172 |
} |
|
173 |
|
|
174 | 196 |
if ( line.startsWith( MAIN_PREFIX ) )
|
175 |
{ |
|
176 | 46 |
if ( mainSet )
|
177 |
{ |
|
178 | 2 |
throw new ConfigurationException( "Duplicate main configuration", lineNo, line ); |
179 |
} |
|
180 |
|
|
181 | 44 |
String conf = line.substring( MAIN_PREFIX.length() ).trim(); |
182 |
|
|
183 | 44 |
int fromLoc = conf.indexOf( "from" ); |
184 |
|
|
185 | 44 |
if ( fromLoc < 0 )
|
186 |
{ |
|
187 | 0 |
throw new ConfigurationException( "Missing from clause", lineNo, line ); |
188 |
} |
|
189 |
|
|
190 | 44 |
String mainClassName = conf.substring( 0, fromLoc ).trim(); |
191 |
|
|
192 | 44 |
String mainRealmName = conf.substring( fromLoc + 4 ).trim(); |
193 |
|
|
194 | 44 |
if ( this.launcher != null ) |
195 |
{ |
|
196 | 44 |
this.launcher.setAppMain( mainClassName, mainRealmName );
|
197 |
} |
|
198 |
|
|
199 | 44 |
mainSet = true;
|
200 |
} |
|
201 | 150 |
else if ( line.startsWith( SET_PREFIX ) ) |
202 |
{ |
|
203 | 36 |
String conf = line.substring( SET_PREFIX.length() ).trim(); |
204 |
|
|
205 | 36 |
int usingLoc = conf.indexOf( " using" ) + 1; |
206 |
|
|
207 | 36 |
String property = null;
|
208 | 36 |
String propertiesFileName = null;
|
209 | 36 |
if ( usingLoc > 0 )
|
210 |
{ |
|
211 | 24 |
property = conf.substring( 0, usingLoc ).trim(); |
212 |
|
|
213 | 24 |
propertiesFileName = filter( conf.substring( usingLoc + 5 ).trim() ); |
214 |
|
|
215 | 24 |
conf = propertiesFileName; |
216 |
} |
|
217 |
|
|
218 | 36 |
String defaultValue = null;
|
219 |
|
|
220 | 36 |
int defaultLoc = conf.indexOf( " default" ) + 1; |
221 |
|
|
222 | 36 |
if ( defaultLoc > 0 )
|
223 |
{ |
|
224 | 24 |
defaultValue = conf.substring( defaultLoc + 7 ).trim(); |
225 |
|
|
226 | 24 |
if ( property == null ) |
227 |
{ |
|
228 | 12 |
property = conf.substring( 0, defaultLoc ).trim(); |
229 |
} |
|
230 |
else
|
|
231 |
{ |
|
232 | 12 |
propertiesFileName = conf.substring( 0, defaultLoc ).trim(); |
233 |
} |
|
234 |
} |
|
235 |
|
|
236 | 36 |
String value = System.getProperty( property ); |
237 |
|
|
238 | 36 |
if ( value != null ) |
239 |
{ |
|
240 | 4 |
continue;
|
241 |
} |
|
242 |
|
|
243 | 32 |
if ( propertiesFileName != null ) |
244 |
{ |
|
245 | 22 |
File propertiesFile = new File( propertiesFileName );
|
246 |
|
|
247 | 22 |
if ( propertiesFile.exists() )
|
248 |
{ |
|
249 | 10 |
Properties properties = new Properties();
|
250 |
|
|
251 | 10 |
try
|
252 |
{ |
|
253 | 10 |
properties.load( new FileInputStream( propertiesFileName ) );
|
254 |
|
|
255 | 10 |
value = properties.getProperty( property ); |
256 |
} |
|
257 |
catch ( Exception e )
|
|
258 |
{ |
|
259 |
// do nothing
|
|
260 |
} |
|
261 |
} |
|
262 |
} |
|
263 |
|
|
264 | 32 |
if ( value == null && defaultValue != null ) |
265 |
{ |
|
266 | 22 |
value = defaultValue; |
267 |
} |
|
268 |
|
|
269 | 32 |
if ( value != null ) |
270 |
{ |
|
271 | 26 |
value = filter( value ); |
272 | 26 |
System.setProperty( property, value ); |
273 |
} |
|
274 |
} |
|
275 | 114 |
else if ( line.startsWith( "[" ) ) |
276 |
{ |
|
277 | 62 |
int rbrack = line.indexOf( "]" ); |
278 |
|
|
279 | 62 |
if ( rbrack < 0 )
|
280 |
{ |
|
281 | 2 |
throw new ConfigurationException( "Invalid realm specifier", lineNo, line ); |
282 |
} |
|
283 |
|
|
284 | 60 |
String realmName = line.substring( 1, rbrack ); |
285 |
|
|
286 | 60 |
curRealm = world.newRealm( realmName ); |
287 |
|
|
288 |
// Stash the configured realm for subsequent association processing.
|
|
289 | 58 |
configuredRealms.put( realmName, curRealm ); |
290 |
} |
|
291 | 52 |
else if ( line.startsWith( IMPORT_PREFIX ) ) |
292 |
{ |
|
293 | 6 |
if ( curRealm == null ) |
294 |
{ |
|
295 | 2 |
throw new ConfigurationException( "Unhandled import", lineNo, line ); |
296 |
} |
|
297 |
|
|
298 | 4 |
String conf = line.substring( IMPORT_PREFIX.length() ).trim(); |
299 |
|
|
300 | 4 |
int fromLoc = conf.indexOf( "from" ); |
301 |
|
|
302 | 4 |
if ( fromLoc < 0 )
|
303 |
{ |
|
304 | 0 |
throw new ConfigurationException( "Missing from clause", lineNo, line ); |
305 |
} |
|
306 |
|
|
307 | 4 |
String importSpec = conf.substring( 0, fromLoc ).trim(); |
308 |
|
|
309 | 4 |
String relamName = conf.substring( fromLoc + 4 ).trim(); |
310 |
|
|
311 | 4 |
curRealm.importFrom( relamName, importSpec ); |
312 |
|
|
313 |
} |
|
314 | 46 |
else if ( line.startsWith( LOAD_PREFIX ) ) |
315 |
{ |
|
316 | 40 |
String constituent = line.substring( LOAD_PREFIX.length() ).trim(); |
317 |
|
|
318 | 40 |
constituent = filter( constituent ); |
319 |
|
|
320 | 40 |
if ( constituent.indexOf( "*" ) >= 0 ) |
321 |
{ |
|
322 | 2 |
loadGlob( constituent, curRealm ); |
323 |
} |
|
324 |
else
|
|
325 |
{ |
|
326 | 38 |
File file = new File( constituent );
|
327 |
|
|
328 | 38 |
if ( file.exists() )
|
329 |
{ |
|
330 | 38 |
curRealm.addConstituent( file.toURL() ); |
331 |
} |
|
332 |
else
|
|
333 |
{ |
|
334 | 0 |
try
|
335 |
{ |
|
336 | 0 |
curRealm.addConstituent( new URL( constituent ) );
|
337 |
} |
|
338 |
catch ( MalformedURLException e )
|
|
339 |
{ |
|
340 | 0 |
throw new FileNotFoundException( constituent ); |
341 |
} |
|
342 |
} |
|
343 |
} |
|
344 |
} |
|
345 | 6 |
else if ( line.startsWith( OPTIONALLY_PREFIX ) ) |
346 |
{ |
|
347 | 4 |
String constituent = line.substring( OPTIONALLY_PREFIX.length() ).trim(); |
348 |
|
|
349 | 4 |
constituent = filter( constituent ); |
350 |
|
|
351 | 4 |
if ( constituent.indexOf( "*" ) >= 0 ) |
352 |
{ |
|
353 | 2 |
loadGlob( constituent, curRealm, true );
|
354 |
} |
|
355 |
else
|
|
356 |
{ |
|
357 | 2 |
File file = new File( constituent );
|
358 |
|
|
359 | 2 |
if ( file.exists() )
|
360 |
{ |
|
361 | 2 |
curRealm.addConstituent( file.toURL() ); |
362 |
} |
|
363 |
else
|
|
364 |
{ |
|
365 | 0 |
try
|
366 |
{ |
|
367 | 0 |
curRealm.addConstituent( new URL( constituent ) );
|
368 |
} |
|
369 |
catch (MalformedURLException e)
|
|
370 |
{ |
|
371 |
// swallow
|
|
372 |
} |
|
373 |
} |
|
374 |
} |
|
375 |
} |
|
376 |
else
|
|
377 |
{ |
|
378 | 2 |
throw new ConfigurationException( "Unhandled configuration", lineNo, line ); |
379 |
} |
|
380 |
} |
|
381 |
|
|
382 |
// Associate child realms to their parents.
|
|
383 | 42 |
associateRealms(); |
384 |
|
|
385 | 42 |
if ( this.launcher != null ) this.launcher.setWorld( world ); |
386 |
|
|
387 | 42 |
reader.close(); |
388 |
} |
|
389 |
|
|
390 |
/**
|
|
391 |
* Associate parent realms with their children.
|
|
392 |
*/
|
|
393 | 42 |
protected void associateRealms() |
394 |
{ |
|
395 | 42 |
List sortRealmNames = new ArrayList( configuredRealms.keySet() );
|
396 |
|
|
397 |
// sort by name
|
|
398 | 42 |
Comparator comparator = new Comparator()
|
399 |
{ |
|
400 | 14 |
public int compare( Object o1, Object o2 ) |
401 |
{ |
|
402 | 14 |
String g1 = (String) o1; |
403 | 14 |
String g2 = (String) o2; |
404 | 14 |
return g1.compareTo( g2 );
|
405 |
} |
|
406 |
}; |
|
407 |
|
|
408 | 42 |
Collections.sort( sortRealmNames, comparator ); |
409 |
|
|
410 |
// So now we have something like the following for defined
|
|
411 |
// realms:
|
|
412 |
//
|
|
413 |
// root
|
|
414 |
// root.maven
|
|
415 |
// root.maven.plugin
|
|
416 |
//
|
|
417 |
// Now if the name of a realm is a superset of an existing realm
|
|
418 |
// the we want to make child/parent associations.
|
|
419 |
|
|
420 | 42 |
for ( Iterator i = sortRealmNames.iterator(); i.hasNext(); )
|
421 |
{ |
|
422 | 52 |
String realmName = (String) i.next(); |
423 |
|
|
424 | 52 |
int j = realmName.lastIndexOf( '.' );
|
425 |
|
|
426 | 52 |
if ( j > 0 )
|
427 |
{ |
|
428 | 4 |
String parentRealmName = realmName.substring( 0, j ); |
429 |
|
|
430 | 4 |
ClassRealm parentRealm = (ClassRealm) configuredRealms.get( parentRealmName ); |
431 |
|
|
432 | 4 |
if ( parentRealm != null ) |
433 |
{ |
|
434 | 4 |
ClassRealm realm = (ClassRealm) configuredRealms.get( realmName ); |
435 |
|
|
436 | 4 |
realm.setParent( parentRealm ); |
437 |
} |
|
438 |
} |
|
439 |
} |
|
440 |
} |
|
441 |
|
|
442 |
/**
|
|
443 |
* Load a glob into the specified classloader.
|
|
444 |
*
|
|
445 |
* @param line The path configuration line.
|
|
446 |
* @param realm The realm to populate
|
|
447 |
* @throws MalformedURLException If the line does not represent
|
|
448 |
* a valid path element.
|
|
449 |
* @throws FileNotFoundException If the line does not represent
|
|
450 |
* a valid path element in the filesystem.
|
|
451 |
*/
|
|
452 | 2 |
protected void loadGlob( String line, ClassRealm realm ) |
453 |
throws MalformedURLException, FileNotFoundException
|
|
454 |
{ |
|
455 | 2 |
loadGlob( line, realm, false );
|
456 |
} |
|
457 |
|
|
458 |
/**
|
|
459 |
* Load a glob into the specified classloader.
|
|
460 |
*
|
|
461 |
* @param line The path configuration line.
|
|
462 |
* @param realm The realm to populate
|
|
463 |
* @param optionally Whether the path is optional or required
|
|
464 |
* @throws MalformedURLException If the line does not represent
|
|
465 |
* a valid path element.
|
|
466 |
* @throws FileNotFoundException If the line does not represent
|
|
467 |
* a valid path element in the filesystem.
|
|
468 |
*/
|
|
469 | 4 |
protected void loadGlob( String line, ClassRealm realm, boolean optionally ) |
470 |
throws MalformedURLException, FileNotFoundException
|
|
471 |
{ |
|
472 | 4 |
File globFile = new File( line );
|
473 |
|
|
474 | 4 |
File dir = globFile.getParentFile(); |
475 | 4 |
if ( ! dir.exists() )
|
476 |
{ |
|
477 | 2 |
if ( optionally )
|
478 |
{ |
|
479 | 2 |
return;
|
480 |
} |
|
481 |
else
|
|
482 |
{ |
|
483 | 0 |
throw new FileNotFoundException( dir.toString() ); |
484 |
} |
|
485 |
} |
|
486 |
|
|
487 | 2 |
String localName = globFile.getName(); |
488 |
|
|
489 | 2 |
int starLoc = localName.indexOf( "*" ); |
490 |
|
|
491 | 2 |
final String prefix = localName.substring( 0, starLoc ); |
492 |
|
|
493 | 2 |
final String suffix = localName.substring( starLoc + 1 ); |
494 |
|
|
495 | 2 |
File[] matches = dir.listFiles( new FilenameFilter()
|
496 |
{ |
|
497 | 56 |
public boolean accept( File dir, String name ) |
498 |
{ |
|
499 | 56 |
if ( !name.startsWith( prefix ) )
|
500 |
{ |
|
501 | 0 |
return false; |
502 |
} |
|
503 |
|
|
504 | 56 |
if ( !name.endsWith( suffix ) )
|
505 |
{ |
|
506 | 46 |
return false; |
507 |
} |
|
508 |
|
|
509 | 10 |
return true; |
510 |
} |
|
511 |
} ); |
|
512 |
|
|
513 | 2 |
for ( int i = 0; i < matches.length; ++i ) |
514 |
{ |
|
515 | 10 |
realm.addConstituent( matches[i].toURL() ); |
516 |
} |
|
517 |
} |
|
518 |
|
|
519 |
/**
|
|
520 |
* Filter a string for system properties.
|
|
521 |
*
|
|
522 |
* @param text The text to filter.
|
|
523 |
* @return The filtered text.
|
|
524 |
* @throws ConfigurationException If the property does not
|
|
525 |
* exist or if there is a syntax error.
|
|
526 |
*/
|
|
527 | 108 |
protected String filter( String text )
|
528 |
throws ConfigurationException
|
|
529 |
{ |
|
530 | 108 |
String result = "";
|
531 |
|
|
532 | 108 |
int cur = 0;
|
533 | 108 |
int textLen = text.length();
|
534 |
|
|
535 | 108 |
int propStart = -1;
|
536 | 108 |
int propStop = -1;
|
537 |
|
|
538 | 108 |
String propName = null;
|
539 | 108 |
String propValue = null;
|
540 |
|
|
541 | 108 |
while ( cur < textLen )
|
542 |
{ |
|
543 | 188 |
propStart = text.indexOf( "${", cur );
|
544 |
|
|
545 | 188 |
if ( propStart < 0 )
|
546 |
{ |
|
547 | 100 |
break;
|
548 |
} |
|
549 |
|
|
550 | 88 |
result += text.substring( cur, propStart ); |
551 |
|
|
552 | 88 |
propStop = text.indexOf( "}", propStart );
|
553 |
|
|
554 | 88 |
if ( propStop < 0 )
|
555 |
{ |
|
556 | 2 |
throw new ConfigurationException( "Unterminated property: " + text.substring( propStart ) ); |
557 |
} |
|
558 |
|
|
559 | 86 |
propName = text.substring( propStart + 2, propStop ); |
560 |
|
|
561 | 86 |
propValue = System.getProperty( propName ); |
562 |
|
|
563 | 86 |
if ( propValue == null ) |
564 |
{ |
|
565 | 2 |
throw new ConfigurationException( "No such property: " + propName ); |
566 |
} |
|
567 | 84 |
result += propValue; |
568 |
|
|
569 | 84 |
cur = propStop + 1; |
570 |
} |
|
571 |
|
|
572 | 104 |
result += text.substring( cur ); |
573 |
|
|
574 | 104 |
return result;
|
575 |
} |
|
576 |
|
|
577 |
/**
|
|
578 |
* Determine if a line can be ignored because it is
|
|
579 |
* a comment or simply blank.
|
|
580 |
*
|
|
581 |
* @param line The line to test.
|
|
582 |
* @return <code>true</code> if the line is ignorable,
|
|
583 |
* otherwise <code>false</code>.
|
|
584 |
*/
|
|
585 | 618 |
private boolean canIgnore( String line ) |
586 |
{ |
|
587 | 618 |
return ( line.length() == 0
|
588 |
|| |
|
589 |
line.startsWith( "#" ) );
|
|
590 |
} |
|
591 |
} |
|
592 |
|
|
593 |
|
|