1
2 package org.apache.commons.configuration.plist;
3
4 import java.util.List;
5 import java.util.ArrayList;
6
7 import org.apache.commons.configuration.HierarchicalConfiguration;
8 import org.apache.commons.configuration.HierarchicalConfiguration.Node;
9
10 import org.apache.commons.lang.StringUtils;
11 import org.apache.commons.codec.binary.Hex;
12
13 /***
14 * JavaCC based parser for the PropertyList format.
15 *
16 * @author Emmanuel Bourg
17 * @version $Revision$, $Date: 2005-11-22 21:40:57 +0100 (Tue, 22 Nov 2005) $
18 */
19 class PropertyListParser implements PropertyListParserConstants
20 {
21
22 /***
23 * Remove the quotes at the beginning and at the end of the specified String.
24 */
25 protected String removeQuotes(String s)
26 {
27 if (s == null)
28 {
29 return null;
30 }
31
32 if (s.startsWith("\"") && s.endsWith("\"") && s.length() >= 2)
33 {
34 s = s.substring(1, s.length() - 1);
35 }
36
37 return s;
38 }
39
40 protected String unescapeQuotes(String s)
41 {
42 return StringUtils.replace(s, "//\"", "\"");
43 }
44
45 /***
46 * Remove the white spaces and the data delimiters from the specified
47 * string and parse it as a byte array.
48 */
49 protected byte[] filterData(String s) throws ParseException
50 {
51 if (s == null)
52 {
53 return null;
54 }
55
56
57 if (s.startsWith("<") && s.endsWith(">") && s.length() >= 2)
58 {
59 s = s.substring(1, s.length() - 1);
60 }
61
62
63 s = StringUtils.replaceChars(s, " \t\n\r", "");
64
65
66 if (s.length() % 2 != 0)
67 {
68 s = "0" + s;
69 }
70
71
72 try
73 {
74 return Hex.decodeHex(s.toCharArray());
75 }
76 catch (Exception e)
77 {
78 throw new ParseException(e.getMessage());
79 }
80 }
81
82 final public PropertyListConfiguration parse() throws ParseException
83 {
84 PropertyListConfiguration configuration = null;
85 configuration = Dictionary();
86 jj_consume_token(0);
87
88 return configuration;
89 }
90
91 final public PropertyListConfiguration Dictionary() throws ParseException
92 {
93 PropertyListConfiguration configuration = new PropertyListConfiguration();
94 List children = new ArrayList();
95 Node child = null;
96 jj_consume_token(DICT_BEGIN);
97 label_1:
98 while (true)
99 {
100 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk)
101 {
102 case STRING:
103 case QUOTED_STRING:
104 ;
105 break;
106 default:
107 jj_la1[0] = jj_gen;
108 break label_1;
109 }
110 child = Property();
111 if (child.getValue() instanceof HierarchicalConfiguration)
112 {
113
114 HierarchicalConfiguration conf = (HierarchicalConfiguration) child.getValue();
115 Node root = conf.getRoot();
116 root.setName(child.getName());
117 children.add(root);
118 }
119 else
120 {
121 children.add(child);
122 }
123 }
124 jj_consume_token(DICT_END);
125 for (int i = 0; i < children.size(); i++)
126 {
127 child = (Node) children.get(i);
128 configuration.getRoot().addChild(child);
129 }
130
131 return configuration;
132 }
133
134 final public Node Property() throws ParseException
135 {
136 Node node = new Node();
137 String key = String();
138 node.setName(key);
139 jj_consume_token(EQUAL);
140 Object value = Element();
141 node.setValue(value);
142 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk)
143 {
144 case DICT_SEPARATOR:
145 jj_consume_token(DICT_SEPARATOR);
146 break;
147 default:
148 jj_la1[1] = jj_gen;
149 ;
150 }
151
152 return node;
153 }
154
155 final public Object Element() throws ParseException
156 {
157 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk)
158 {
159 case ARRAY_BEGIN:
160 return Array();
161
162 case DICT_BEGIN:
163 return Dictionary();
164
165 case STRING:
166 case QUOTED_STRING:
167 return String();
168
169 case DATA:
170 return Data();
171
172 default:
173 jj_la1[2] = jj_gen;
174 jj_consume_token(-1);
175 throw new ParseException();
176 }
177 }
178
179 final public List Array() throws ParseException
180 {
181 List list = new ArrayList();
182 Object element = null;
183 jj_consume_token(ARRAY_BEGIN);
184 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk)
185 {
186 case ARRAY_BEGIN:
187 case DICT_BEGIN:
188 case DATA:
189 case STRING:
190 case QUOTED_STRING:
191 element = Element();
192 list.add(element);
193 label_2:
194 while (true)
195 {
196 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk)
197 {
198 case ARRAY_SEPARATOR:
199 ;
200 break;
201 default:
202 jj_la1[3] = jj_gen;
203 break label_2;
204 }
205 jj_consume_token(ARRAY_SEPARATOR);
206 element = Element();
207 list.add(element);
208 }
209 break;
210 default:
211 jj_la1[4] = jj_gen;
212 ;
213 }
214 jj_consume_token(ARRAY_END);
215
216 return list;
217 }
218
219 final public String String() throws ParseException
220 {
221 Token token = null;
222 switch ((jj_ntk == -1) ? jj_ntk() : jj_ntk)
223 {
224 case QUOTED_STRING:
225 token = jj_consume_token(QUOTED_STRING);
226 return unescapeQuotes(removeQuotes(token.image));
227
228 case STRING:
229 token = jj_consume_token(STRING);
230 return token.image;
231
232 default:
233 jj_la1[5] = jj_gen;
234 jj_consume_token(-1);
235 throw new ParseException();
236 }
237 }
238
239 final public byte[] Data() throws ParseException
240 {
241 Token token;
242 token = jj_consume_token(DATA);
243
244 return filterData(token.image);
245 }
246
247 public PropertyListParserTokenManager token_source;
248 SimpleCharStream jj_input_stream;
249 public Token token, jj_nt;
250 private int jj_ntk;
251 private int jj_gen;
252 final private int[] jj_la1 = new int[6];
253 static private int[] jj_la1_0;
254
255 static
256 {
257 jj_la1_0();
258 }
259
260 private static void jj_la1_0()
261 {
262 jj_la1_0 = new int[]{0x180000, 0x400, 0x1c0120, 0x80, 0x1c0120, 0x180000, };
263 }
264
265 public PropertyListParser(java.io.InputStream stream)
266 {
267 jj_input_stream = new SimpleCharStream(stream, 1, 1);
268 token_source = new PropertyListParserTokenManager(jj_input_stream);
269 token = new Token();
270 jj_ntk = -1;
271 jj_gen = 0;
272 for (int i = 0; i < 6; i++) jj_la1[i] = -1;
273 }
274
275 public PropertyListParser(java.io.Reader stream)
276 {
277 jj_input_stream = new SimpleCharStream(stream, 1, 1);
278 token_source = new PropertyListParserTokenManager(jj_input_stream);
279 token = new Token();
280 jj_ntk = -1;
281 jj_gen = 0;
282 for (int i = 0; i < 6; i++) jj_la1[i] = -1;
283 }
284
285 final private Token jj_consume_token(int kind) throws ParseException
286 {
287 Token oldToken;
288 if ((oldToken = token).next != null)
289 token = token.next;
290 else
291 token = token.next = token_source.getNextToken();
292 jj_ntk = -1;
293 if (token.kind == kind)
294 {
295 jj_gen++;
296 return token;
297 }
298 token = oldToken;
299 jj_kind = kind;
300 throw generateParseException();
301 }
302
303 final private int jj_ntk()
304 {
305 if ((jj_nt = token.next) == null)
306 return (jj_ntk = (token.next = token_source.getNextToken()).kind);
307 else
308 return (jj_ntk = jj_nt.kind);
309 }
310
311 private java.util.Vector jj_expentries = new java.util.Vector();
312 private int[] jj_expentry;
313 private int jj_kind = -1;
314
315 public ParseException generateParseException()
316 {
317 jj_expentries.removeAllElements();
318 boolean[] la1tokens = new boolean[22];
319 for (int i = 0; i < 22; i++)
320 {
321 la1tokens[i] = false;
322 }
323 if (jj_kind >= 0)
324 {
325 la1tokens[jj_kind] = true;
326 jj_kind = -1;
327 }
328 for (int i = 0; i < 6; i++)
329 {
330 if (jj_la1[i] == jj_gen)
331 {
332 for (int j = 0; j < 32; j++)
333 {
334 if ((jj_la1_0[i] & (1 << j)) != 0)
335 {
336 la1tokens[j] = true;
337 }
338 }
339 }
340 }
341 for (int i = 0; i < 22; i++)
342 {
343 if (la1tokens[i])
344 {
345 jj_expentry = new int[1];
346 jj_expentry[0] = i;
347 jj_expentries.addElement(jj_expentry);
348 }
349 }
350 int[][] exptokseq = new int[jj_expentries.size()][];
351 for (int i = 0; i < jj_expentries.size(); i++)
352 {
353 exptokseq[i] = (int[]) jj_expentries.elementAt(i);
354 }
355 return new ParseException(token, exptokseq, tokenImage);
356 }
357
358 }