Lines 18-23
Link Here
|
18 |
package org.apache.tools.ant; |
18 |
package org.apache.tools.ant; |
19 |
|
19 |
|
20 |
import java.util.Hashtable; |
20 |
import java.util.Hashtable; |
|
|
21 |
import java.util.Locale; |
22 |
import java.util.Map; |
23 |
import java.util.Iterator; |
24 |
import java.util.Stack; |
21 |
import java.util.Vector; |
25 |
import java.util.Vector; |
22 |
import java.util.Enumeration; |
26 |
import java.util.Enumeration; |
23 |
|
27 |
|
Lines 287-292
Link Here
|
287 |
return sb.toString(); |
291 |
return sb.toString(); |
288 |
} |
292 |
} |
289 |
|
293 |
|
|
|
294 |
private static final int STATE_NORMAL = 0; |
295 |
private static final int STATE_EXPECT_BRACKET = 1; |
296 |
private static final int STATE_EXPECT_NAME = 2; |
297 |
|
298 |
/** |
299 |
* Replaces <code>@{xxx}</code> style constructions in the given value |
300 |
* with the string value of the corresponding data types. |
301 |
* |
302 |
* @param s The string to be scanned for attribute references. |
303 |
* May be <code>null</code>, in which case this |
304 |
* method returns immediately with no effect. |
305 |
* @param attrMapping Mapping (String to String) of attribute names |
306 |
* to their values. |
307 |
* @return the original string with the attributes replaced, or |
308 |
* <code>null</code> if the original string is <code>null</code>. |
309 |
*/ |
310 |
public synchronized String replaceAttributes(String s, Map attrMapping) { |
311 |
if (s == null) { |
312 |
return null; |
313 |
} |
314 |
StringBuffer ret = new StringBuffer(); |
315 |
StringBuffer macroName = null; |
316 |
|
317 |
int state = STATE_NORMAL; |
318 |
for (int i = 0; i < s.length(); ++i) { |
319 |
char ch = s.charAt(i); |
320 |
switch (state) { |
321 |
case STATE_NORMAL: |
322 |
if (ch == '@') { |
323 |
state = STATE_EXPECT_BRACKET; |
324 |
} else { |
325 |
ret.append(ch); |
326 |
} |
327 |
break; |
328 |
case STATE_EXPECT_BRACKET: |
329 |
if (ch == '{') { |
330 |
state = STATE_EXPECT_NAME; |
331 |
macroName = new StringBuffer(); |
332 |
} else if (ch == '@') { |
333 |
state = STATE_NORMAL; |
334 |
ret.append('@'); |
335 |
} else { |
336 |
state = STATE_NORMAL; |
337 |
ret.append('@'); |
338 |
ret.append(ch); |
339 |
} |
340 |
break; |
341 |
case STATE_EXPECT_NAME: |
342 |
if (ch == '}') { |
343 |
state = STATE_NORMAL; |
344 |
String name = macroName.toString().toLowerCase(Locale.US); |
345 |
String value = (String) attrMapping.get(name); |
346 |
if (value == null) { |
347 |
ret.append("@{"); |
348 |
ret.append(name); |
349 |
ret.append("}"); |
350 |
} else { |
351 |
ret.append(value); |
352 |
} |
353 |
macroName = null; |
354 |
} else { |
355 |
macroName.append(ch); |
356 |
} |
357 |
break; |
358 |
default: |
359 |
break; |
360 |
} |
361 |
} |
362 |
switch (state) { |
363 |
case STATE_NORMAL: |
364 |
break; |
365 |
case STATE_EXPECT_BRACKET: |
366 |
ret.append('@'); |
367 |
break; |
368 |
case STATE_EXPECT_NAME: |
369 |
ret.append("@{"); |
370 |
ret.append(macroName.toString()); |
371 |
break; |
372 |
default: |
373 |
break; |
374 |
} |
375 |
|
376 |
return ret.toString(); |
377 |
} |
378 |
|
290 |
// -------------------- Default implementation -------------------- |
379 |
// -------------------- Default implementation -------------------- |
291 |
// Methods used to support the default behavior and provide backward |
380 |
// Methods used to support the default behavior and provide backward |
292 |
// compatibility. Some will be deprecated, you should avoid calling them. |
381 |
// compatibility. Some will be deprecated, you should avoid calling them. |
Lines 411-416
Link Here
|
411 |
properties.put(name, value); |
500 |
properties.put(name, value); |
412 |
} |
501 |
} |
413 |
|
502 |
|
|
|
503 |
/** |
504 |
* Set a new inherited user property, which cannot be overwritten |
505 |
* by set/unset property calls. If a user property with the |
506 |
* same name is already present the value is not overridden. |
507 |
* |
508 |
* @param ns The namespace for the property (currently not used). |
509 |
* @param n Name of property |
510 |
* @param v Value to set |
511 |
*/ |
512 |
public synchronized void setNewInheritedProperty(String ns, |
513 |
String n, String v) { |
514 |
if (getUserProperty(null, n) == null) { |
515 |
setInheritedProperty(null, n, v); |
516 |
} else { |
517 |
project.log("Override ignored for " + n, Project.MSG_VERBOSE); |
518 |
} |
519 |
} |
520 |
|
521 |
/** |
522 |
* Adds a set of unexpanded properties. |
523 |
* <p>The properties are resolved, prefixed, expanded and added with |
524 |
* {@link #setNewProperty(String, String, Object)}.</p> |
525 |
* @param props The unexpanded properties. |
526 |
* @param prefix The prefix to add to each property name |
527 |
* after properties resolved. |
528 |
* <code>null</code> if no prefix. |
529 |
*/ |
530 |
public synchronized void addNewProperties(String ns |
531 |
, Map props, String prefix) { |
532 |
addUnexpandedProperties(ns, props, prefix, false); |
533 |
} |
534 |
|
535 |
/** |
536 |
* Adds a set of unexpanded inherited user properties. |
537 |
* <p>The properties are resolved, prefixed, expanded and added with |
538 |
* {@link #setNewInheritedProperty(String, String, String)}.</p> |
539 |
* @param props The unexpanded inherited user properties. |
540 |
* @param prefix The prefix to add to each property name |
541 |
* after properties resolved. |
542 |
* <code>null</code> if no prefix. |
543 |
*/ |
544 |
public synchronized void addNewInheritedProperties(String ns |
545 |
, Map props, String prefix) { |
546 |
addUnexpandedProperties(ns, props, prefix, true); |
547 |
} |
548 |
|
549 |
/** |
550 |
* Iterate through a map of properties, |
551 |
* resolve them and assign them. |
552 |
* @param props The properties to iterate over. |
553 |
* @param prefix The prefix to add to each name. |
554 |
* @param userProperties Whether to be added as user properties. |
555 |
*/ |
556 |
private void addUnexpandedProperties(String ns |
557 |
, Map props, String prefix, boolean userProperties) { |
558 |
resolveAllProperties(props); |
559 |
Iterator it = props.entrySet().iterator(); |
560 |
while (it.hasNext()) { |
561 |
Map.Entry entry = (Map.Entry)it.next(); |
562 |
String propertyName = (String) entry.getKey(); |
563 |
String propertyValue = (String) entry.getValue(); |
564 |
|
565 |
String v = replaceProperties(null, propertyValue, null); |
566 |
|
567 |
if (prefix != null) { |
568 |
propertyName = prefix + propertyName; |
569 |
} |
570 |
|
571 |
if (userProperties) { |
572 |
setNewInheritedProperty(null, propertyName, v); |
573 |
} else { |
574 |
setNewProperty(null, propertyName, v); |
575 |
} |
576 |
} |
577 |
} |
578 |
|
579 |
/** |
580 |
* Resolve properties inside a properties map. |
581 |
* @param props Map of properties to resolve. |
582 |
*/ |
583 |
private void resolveAllProperties(Map props) throws BuildException { |
584 |
Iterator it = props.entrySet().iterator(); |
585 |
while (it.hasNext()) { |
586 |
Map.Entry entry = (Map.Entry)it.next(); |
587 |
String propertyName = (String) entry.getKey(); |
588 |
Stack referencesSeen = new Stack(); |
589 |
resolve(props, propertyName, referencesSeen); |
590 |
} |
591 |
} |
592 |
|
593 |
/** |
594 |
* Recursively expand the named property using the given |
595 |
* properties map - fail if a circular definition is detected. |
596 |
* |
597 |
* @param props Map of properties to resolve |
598 |
* @param name Name of the property to resolve |
599 |
* @param referencesSeen Stack of all property names that have |
600 |
* been tried to expand before coming here. |
601 |
*/ |
602 |
private void resolve(Map props, String name, Stack referencesSeen) |
603 |
throws BuildException { |
604 |
if (referencesSeen.contains(name)) { |
605 |
throw new BuildException("Property " + name + " was circularly " |
606 |
+ "defined."); |
607 |
} |
608 |
|
609 |
String propertyValue = (String)props.get(name); |
610 |
Vector fragments = new Vector(); |
611 |
Vector propertyRefs = new Vector(); |
612 |
parsePropertyString(propertyValue, fragments, propertyRefs); |
613 |
|
614 |
if (propertyRefs.size() != 0) { |
615 |
referencesSeen.push(name); |
616 |
StringBuffer sb = new StringBuffer(); |
617 |
Enumeration i = fragments.elements(); |
618 |
Enumeration j = propertyRefs.elements(); |
619 |
while (i.hasMoreElements()) { |
620 |
String fragment = (String) i.nextElement(); |
621 |
if (fragment == null) { |
622 |
String propertyName = (String) j.nextElement(); |
623 |
Object o = getProperty(null, propertyName); |
624 |
fragment = (o == null) ? null : o.toString(); |
625 |
if (fragment == null) { |
626 |
if (props.containsKey(propertyName)) { |
627 |
resolve(props, propertyName, referencesSeen); |
628 |
fragment = (String)props.get(propertyName); |
629 |
} else { |
630 |
fragment = "${" + propertyName + "}"; |
631 |
} |
632 |
} |
633 |
} |
634 |
sb.append(fragment); |
635 |
} |
636 |
propertyValue = sb.toString(); |
637 |
props.put(name, propertyValue); |
638 |
referencesSeen.pop(); |
639 |
} |
640 |
} |
641 |
|
414 |
// -------------------- Getting properties -------------------- |
642 |
// -------------------- Getting properties -------------------- |
415 |
|
643 |
|
416 |
/** |
644 |
/** |