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