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