1 package org.abstracthorizon.extend.repository.maven;
2
3 import java.lang.reflect.InvocationTargetException;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Modifier;
6 import java.util.Collection;
7 import java.util.HashMap;
8 import java.util.Map;
9
10 public class SubstitutionTraverser {
11
12 protected static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
13
14 protected static final Class<?>[] STRING_CLASS_ARRAY = new Class[]{String.class};
15
16 protected static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
17
18 @SuppressWarnings("unchecked")
19 public static void substitute(Object object, Map<String, String> substitutions) {
20
21 Class<?> cls = object.getClass();
22 Method[] methods = cls.getMethods();
23 for (Method m : methods) {
24 if (!Modifier.isStatic(m.getModifiers())) {
25 String name = m.getName();
26 if (!name.equals("getClass") && name.startsWith("get") && (name.length() > 3)) {
27 Class<?> returnType = m.getReturnType();
28 if (returnType.equals(String.class)) {
29 try {
30 String value = (String)m.invoke(object, EMPTY_OBJECT_ARRAY);
31 if ((value != null) && (value.indexOf("${") >= 0)) {
32 String newValue = substitute(value, substitutions);
33 Method writeBackMethod = cls.getMethod("s" + name.substring(1), STRING_CLASS_ARRAY);
34 writeBackMethod.invoke(object, new Object[]{newValue});
35 }
36 } catch (IllegalArgumentException ignore) {
37 } catch (IllegalAccessException ignore) {
38 } catch (InvocationTargetException ignore) {
39 } catch (SecurityException ignore) {
40 } catch (NoSuchMethodException ignore) {
41 }
42 } else if (!returnType.isPrimitive()) {
43 try {
44 Object obj = m.invoke(object, EMPTY_OBJECT_ARRAY);
45 if (obj != null) {
46 if (obj instanceof Collection) {
47 for (Object o : (Collection)obj) {
48 substitute(o, substitutions);
49 }
50 } else if (obj.getClass().isArray()) {
51 for (Object o : (Object[])obj) {
52 substitute(o, substitutions);
53 }
54 } else {
55 substitute(obj, substitutions);
56 }
57 }
58 } catch (IllegalArgumentException ignore) {
59 } catch (IllegalAccessException ignore) {
60 } catch (InvocationTargetException ignore) {
61 }
62 }
63 }
64 }
65 }
66 }
67
68 public static String substitute(String value, Map<String, String> substitutions) {
69 int len = value.length();
70 StringBuffer buf = new StringBuffer(len);
71 int i = 0;
72 int ptr = 0;
73 int state = 0;
74 while (i < len) {
75 char c = value.charAt(i);
76 if (state == 0) {
77 if (c == '$') {
78 state = 1;
79 }
80 } else if (state == 1) {
81 if (c == '{') {
82 if (i > 1) {
83 buf.append(value.substring(ptr, i - 1));
84 }
85 ptr = i + 1;
86 state = 2;
87 } else {
88 state = 0;
89 }
90 } else if (state == 2) {
91 if (c == '}') {
92 String key = value.substring(ptr, i);
93 String sub = substitutions.get(key);
94 if (sub != null) {
95 buf.append(sub);
96 } else {
97 buf.append("${").append(key).append('}');
98 }
99 ptr = i + 1;
100 state = 0;
101 }
102 }
103 i++;
104 }
105 if (ptr != i) {
106 if (state == 2) {
107 buf.append("${");
108 }
109 buf.append(value.substring(ptr));
110 }
111 return buf.toString();
112 }
113
114 public static void main(String[] args) throws Exception {
115 Map<String, String> map = new HashMap<String, String>();
116 map.put("pom.version", "0.4.0");
117 test("${pom.version}x", map);
118 test("y${pom.version}x", map);
119 test("y${pom.version}", map);
120 test("y${pom.version", map);
121 test("pom.version}", map);
122 test("pom.version", map);
123 test("y${pom.version}asd${some}", map);
124
125 test("${pom.versionx}x", map);
126 test("y${pom.versionx}x", map);
127 test("y${pom.versionx}", map);
128
129 }
130
131 public static void test(String value, Map<String, String> map) {
132 System.out.println(value + " = '" + substitute(value, map) + "'");
133 }
134 }