1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.eclipse.jetty.policy.loader;
23
24
25 import java.io.IOException;
26 import java.io.Reader;
27 import java.io.StreamTokenizer;
28 import java.util.Collection;
29 import java.util.HashSet;
30 import java.util.List;
31
32 import org.eclipse.jetty.policy.entry.GrantEntry;
33 import org.eclipse.jetty.policy.entry.KeystoreEntry;
34 import org.eclipse.jetty.policy.entry.PermissionEntry;
35 import org.eclipse.jetty.policy.entry.PrincipalEntry;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public class PolicyFileScanner
73 {
74
75
76
77
78 public static class InvalidFormatException
79 extends Exception
80 {
81
82
83
84
85 private static final long serialVersionUID = 5789786270390222184L;
86
87
88
89
90 public InvalidFormatException( String arg0 )
91 {
92 super( arg0 );
93 }
94 }
95
96
97
98
99 protected StreamTokenizer configure( StreamTokenizer st )
100 {
101 st.slashSlashComments( true );
102 st.slashStarComments( true );
103 st.wordChars( '_', '_' );
104 st.wordChars( '$', '$' );
105 return st;
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119 public void scanStream( Reader r, Collection<GrantEntry> grantEntries, List<KeystoreEntry> keystoreEntries )
120 throws IOException, InvalidFormatException
121 {
122 StreamTokenizer st = configure( new StreamTokenizer( r ) );
123
124 parsing: while ( true )
125 {
126 switch ( st.nextToken() )
127 {
128 case StreamTokenizer.TT_EOF:
129 break parsing;
130
131 case StreamTokenizer.TT_WORD:
132 if ( Util.equalsIgnoreCase( "keystore", st.sval ) ) {
133 keystoreEntries.add( readKeystoreNode( st ) );
134 }
135 else if ( Util.equalsIgnoreCase( "grant", st.sval ) ) {
136 grantEntries.add( readGrantNode( st ) );
137 }
138 else
139 {
140 handleUnexpectedToken( st, "Expected entries are : \"grant\" or \"keystore\"" );
141
142 }
143 break;
144
145 case ';':
146 break;
147
148 default:
149 handleUnexpectedToken( st );
150 break;
151 }
152 }
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 protected KeystoreEntry readKeystoreNode( StreamTokenizer st )
169 throws IOException, InvalidFormatException
170 {
171 KeystoreEntry ke = new KeystoreEntry();
172 if ( st.nextToken() == '"' )
173 {
174 ke.setUrl( st.sval );
175 if ( ( st.nextToken() == '"' ) || ( ( st.ttype == ',' ) && ( st.nextToken() == '"' ) ) )
176 {
177 ke.setType( st.sval );
178 }
179 else
180 {
181 st.pushBack();
182 }
183 }
184 else
185 {
186 handleUnexpectedToken( st, "Expected syntax is : keystore \"url\"[, \"type\"]" );
187
188 }
189 return ke;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211 protected GrantEntry readGrantNode( StreamTokenizer st )
212 throws IOException, InvalidFormatException
213 {
214 GrantEntry ge = new GrantEntry();
215 parsing: while ( true )
216 {
217 switch ( st.nextToken() )
218 {
219
220 case StreamTokenizer.TT_WORD:
221 if ( Util.equalsIgnoreCase( "signedby", st.sval ) ) {
222 if ( st.nextToken() == '"' )
223 {
224 ge.setSigners( st.sval );
225 }
226 else
227 {
228 handleUnexpectedToken( st, "Expected syntax is : signedby \"name1,...,nameN\"" );
229 }
230 }
231 else if ( Util.equalsIgnoreCase( "codebase", st.sval ) ) {
232 if ( st.nextToken() == '"' )
233 {
234 ge.setCodebase( st.sval );
235 }
236 else
237 {
238 handleUnexpectedToken( st, "Expected syntax is : codebase \"url\"" );
239 }
240 }
241 else if ( Util.equalsIgnoreCase( "principal", st.sval ) ) {
242 ge.addPrincipal( readPrincipalNode( st ) );
243 }
244 else
245 {
246 handleUnexpectedToken( st );
247 }
248 break;
249
250 case ',':
251 break;
252
253 case '{':
254 ge.setPermissions( readPermissionEntries( st ) );
255 break parsing;
256
257 default:
258 st.pushBack();
259 break parsing;
260 }
261 }
262
263 return ge;
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 protected PrincipalEntry readPrincipalNode( StreamTokenizer st )
282 throws IOException, InvalidFormatException
283 {
284 PrincipalEntry pe = new PrincipalEntry();
285 if ( st.nextToken() == StreamTokenizer.TT_WORD )
286 {
287 pe.setKlass( st.sval );
288 st.nextToken();
289 }
290 else if ( st.ttype == '*' )
291 {
292 pe.setKlass( PrincipalEntry.WILDCARD );
293 st.nextToken();
294 }
295 if ( st.ttype == '"' )
296 {
297 pe.setName( st.sval );
298 }
299 else if ( st.ttype == '*' )
300 {
301 pe.setName( PrincipalEntry.WILDCARD );
302 }
303 else
304 {
305 handleUnexpectedToken( st, "Expected syntax is : principal [class_name] \"principal_name\"" );
306 }
307 return pe;
308 }
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 protected Collection<PermissionEntry> readPermissionEntries( StreamTokenizer st )
328 throws IOException, InvalidFormatException
329 {
330 Collection<PermissionEntry> permissions = new HashSet<PermissionEntry>();
331 parsing: while ( true )
332 {
333 switch ( st.nextToken() )
334 {
335
336 case StreamTokenizer.TT_WORD:
337 if ( Util.equalsIgnoreCase( "permission", st.sval ) ) {
338 PermissionEntry pe = new PermissionEntry();
339 if ( st.nextToken() == StreamTokenizer.TT_WORD )
340 {
341 pe.setKlass( st.sval );
342 if ( st.nextToken() == '"' )
343 {
344 pe.setName( st.sval );
345 st.nextToken();
346 }
347 if ( st.ttype == ',' )
348 {
349 st.nextToken();
350 }
351 if ( st.ttype == '"' )
352 {
353 pe.setActions( st.sval );
354 if ( st.nextToken() == ',' )
355 {
356 st.nextToken();
357 }
358 }
359 if ( st.ttype == StreamTokenizer.TT_WORD && Util.equalsIgnoreCase( "signedby", st.sval ) ) {
360 if ( st.nextToken() == '"' )
361 {
362 pe.setSigners( st.sval );
363 }
364 else
365 {
366 handleUnexpectedToken( st );
367 }
368 }
369 else
370 {
371 st.pushBack();
372 }
373 permissions.add( pe );
374 continue parsing;
375 }
376 }
377 handleUnexpectedToken(
378 st,
379 "Expected syntax is : permission permission_class_name [\"target_name\"] [, \"action_list\"] [, signedby \"name1,...,nameN\"]" );
380 break;
381
382 case ';':
383 break;
384
385 case '}':
386 break parsing;
387
388 default:
389 handleUnexpectedToken( st );
390 break;
391 }
392 }
393
394 return permissions;
395 }
396
397
398
399
400 protected String composeStatus( StreamTokenizer st )
401 {
402 return st.toString();
403 }
404
405
406
407
408
409
410
411
412 protected final void handleUnexpectedToken( StreamTokenizer st, String message )
413 throws InvalidFormatException
414 {
415 throw new InvalidFormatException( "Unexpected token encountered: " + composeStatus( st ) + ". " + message );
416 }
417
418
419
420
421
422
423 protected final void handleUnexpectedToken( StreamTokenizer st )
424 throws InvalidFormatException
425 {
426 throw new InvalidFormatException( "Unexpected token encountered: " + composeStatus( st ) );
427 }
428
429
430 private static class Util
431 {
432 public static String toUpperCase( String s )
433 {
434 int len = s.length();
435 StringBuilder buffer = new StringBuilder( len );
436 for ( int i = 0; i < len; i++ )
437 {
438 char c = s.charAt( i );
439 if ( 'a' <= c && c <= 'z' )
440 {
441 buffer.append( (char) ( c - ( 'a' - 'A' ) ) );
442 }
443 else
444 {
445 buffer.append( c );
446 }
447 }
448 return buffer.toString();
449 }
450
451 public static boolean equalsIgnoreCase( String s1, String s2 )
452 {
453 s1 = toUpperCase( s1 );
454 s2 = toUpperCase( s2 );
455 return s1.equals( s2 );
456 }
457 }
458
459 }