1 package net.sf.jpkgmk.util;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8
9 import net.sf.jpkgmk.DuplicateEntryException;
10 import net.sf.jpkgmk.PackageException;
11 import net.sf.jpkgmk.prototype.PrototypeEntry;
12 import net.sf.jpkgmk.prototype.PrototypeEntryCommandVariable;
13
14 import org.apache.commons.logging.Log;
15 import org.apache.commons.logging.LogFactory;
16
17
18
19
20
21
22
23
24 public class VariableMap implements VariableResolver
25 {
26 private Log log = LogFactory.getLog(VariableMap.class);
27
28 private List<PrototypeEntryCommandVariable> entryVariableList = new ArrayList<PrototypeEntryCommandVariable>();
29
30
31
32
33 public VariableMap()
34 {
35 }
36
37
38
39
40 public String expand(String evaluationString) {
41 return expand(evaluationString, true);
42 }
43
44
45
46
47
48
49
50 String expand(String evaluationString, boolean expandInstallTimeVaribles) {
51
52 if(evaluationString == null) {
53 return null;
54 }
55
56 expandVariables();
57 return expandString(evaluationString, expandInstallTimeVaribles);
58 }
59
60
61
62 private String expandString(String evaluationString, boolean expandInstallTimeVaribles)
63 {
64 String result = evaluationString;
65
66 for (Iterator<PrototypeEntryCommandVariable> iterator = entryVariableList.iterator(); iterator.hasNext();) {
67 PrototypeEntryCommandVariable entry = iterator.next();
68 if(!entry.isBuildVariable() && !expandInstallTimeVaribles) {
69
70 log.debug("Skipping variable '" + entry + "' - is not a build variable");
71 continue;
72 }
73 String key = entry.getKey();
74
75 String value = entry.getExpandedValue() != null ? entry.getExpandedValue() : entry.getValue();
76
77 result = replaceVars(result, "\\$" + key, value);
78 result = replaceVars(result, "\\$\\{" + key + "\\}", value);
79 }
80
81
82 return result;
83 }
84
85 private void expandVariables() {
86 for (Iterator<PrototypeEntryCommandVariable> iterator = entryVariableList.iterator(); iterator.hasNext();) {
87 PrototypeEntryCommandVariable entry = iterator.next();
88 String value = entry.getValue();
89 value = expandString(value, true);
90 entry.setExpandedValue(value);
91 }
92 }
93
94 private String replaceVars(String string, String key, String value) {
95 String groupedRegexBeforeVars = "([.[^\\$]]{1}|^)";
96
97 String patternString = groupedRegexBeforeVars + "(" + key + ")";
98 Pattern pattern = Pattern.compile(patternString);
99
100 try {
101 Matcher matcher = pattern.matcher(string);
102
103
104 matcher.useAnchoringBounds(false);
105
106 StringBuffer sb = new StringBuffer();
107 while(matcher.find()) {
108 String characterBeforeVar = matcher.group(1);
109 matcher.appendReplacement(sb, characterBeforeVar + Matcher.quoteReplacement(value));
110 }
111
112 matcher.appendTail(sb);
113 return sb.toString();
114 }
115 catch(Exception e) {
116 throw new PackageException("Exception while replacing variables in string '" + string + "'. key=" + key + ", value=" + value + ". pattern=" + patternString, e);
117 }
118 }
119
120
121
122
123
124 public int size() {
125 return this.entryVariableList.size();
126 }
127
128 public void registerInVariablesMap(PrototypeEntry entry) {
129
130
131 if(entry instanceof PrototypeEntryCommandVariable) {
132 PrototypeEntryCommandVariable newVarEntry = (PrototypeEntryCommandVariable)entry;
133
134 PrototypeEntryCommandVariable existingEntry = findEntryWithKey(newVarEntry.getKey());
135 if(existingEntry != null) {
136 throw new DuplicateEntryException("The VariableMap already contains an entry with the key '" + newVarEntry.getKey() + "' of the given one: existing='" + existingEntry + "', given='" + entry + "'.");
137 }
138 else {
139 boolean success = entryVariableList.add(newVarEntry);
140 if(!success) {
141 throw new IllegalStateException("Could not add the variable '" + entry + "' to the variable map");
142 }
143 }
144 }
145 else {
146 log.debug("The entry is no variable and will not be added to the variables store. Entry=" + entry);
147 }
148 }
149
150 private PrototypeEntryCommandVariable findEntryWithKey(String key) {
151 for (Iterator<PrototypeEntryCommandVariable> iterator = entryVariableList.iterator(); iterator.hasNext();) {
152 PrototypeEntryCommandVariable varEntry = iterator.next();
153 if(varEntry.getKey().equals(key)) {
154 return varEntry;
155 }
156 }
157 return null;
158 }
159
160 public void unregisterFromVariablesMap(PrototypeEntry entry) {
161
162 if(entry instanceof PrototypeEntryCommandVariable) {
163 PrototypeEntryCommandVariable newVarEntry = (PrototypeEntryCommandVariable)entry;
164 if(!entryVariableList.contains(newVarEntry)) {
165 throw new IllegalArgumentException("The entry '" + newVarEntry + "' was not found in the VariableMap.");
166 }
167 boolean success = entryVariableList.remove(newVarEntry);
168 if(!success) {
169 throw new IllegalStateException("Could not remove entry '" + entry + "' from variable list for a unknown reason.");
170 }
171 }
172 else {
173 log.debug("The entry is no variable and will not be added to the variables store. Entry=" + entry);
174 }
175
176 }
177
178 public void addVariable(String key, String value) {
179 this.entryVariableList.add(new PrototypeEntryCommandVariable(key, value));
180 }
181
182
183
184
185
186
187 public String getVariableValue(String variableName)
188 {
189 return getVariableValue(variableName, false);
190 }
191
192 public String getVariableValue(String variableName, boolean expandVariable)
193 {
194 if (variableName == null) {
195 throw new NullPointerException("The parameter 'variableName' must not be null");
196 }
197 for (Iterator<PrototypeEntryCommandVariable> iterator = entryVariableList.iterator(); iterator.hasNext();) {
198 PrototypeEntryCommandVariable entry = iterator.next();
199 if(entry.getKey().equals(variableName)) {
200 String value = entry.getValue();
201 if(expandVariable) {
202 value = expand(value);
203 }
204 return value;
205 }
206 }
207
208 return null;
209 }
210
211 public static boolean containsVariable(String stringToCheck) {
212 return stringToCheck.contains("$");
213 }
214
215
216 }