KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > osgi > framework > AdminPermission


1 /*
2  * $Header: /cvsroot/eclipse/org.eclipse.osgi/osgi/src/org/osgi/framework/AdminPermission.java,v 1.23 2007/02/26 16:37:21 twatson Exp $
3  *
4  * Copyright (c) OSGi Alliance (2000, 2007). All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.osgi.framework;
20
21 import java.io.IOException JavaDoc;
22 import java.security.*;
23 import java.util.*;
24 import org.eclipse.osgi.framework.internal.core.AbstractBundle;
25 import org.eclipse.osgi.framework.internal.core.FilterImpl;
26
27 /**
28  * A bundle's authority to perform specific privileged administrative operations
29  * on or to get sensitive information about a bundle. The actions for this
30  * permission are:
31  *
32  * <pre>
33  * Action Methods
34  * class Bundle.loadClass
35  * execute Bundle.start
36  * Bundle.stop
37  * StartLevel.setBundleStartLevel
38  * extensionLifecycle BundleContext.installBundle for extension bundles
39  * Bundle.update for extension bundles
40  * Bundle.uninstall for extension bundles
41  * lifecycle BundleContext.installBundle
42  * Bundle.update
43  * Bundle.uninstall
44  * listener BundleContext.addBundleListener for SynchronousBundleListener
45  * BundleContext.removeBundleListener for SynchronousBundleListener
46  * metadata Bundle.getHeaders
47  * Bundle.getLocation
48  * resolve PackageAdmin.refreshPackages
49  * PackageAdmin.resolveBundles
50  * resource Bundle.getResource
51  * Bundle.getResources
52  * Bundle.getEntry
53  * Bundle.getEntryPaths
54  * Bundle.findEntries
55  * Bundle resource/entry URL creation
56  * startlevel StartLevel.setStartLevel
57  * StartLevel.setInitialBundleStartLevel
58  * context Bundle.getBundleContext
59  *
60  * </pre>
61  *
62  * <p>
63  * The special action &quot;*&quot; will represent all actions.
64  * <p>
65  * The name of this permission is a filter expression. The filter gives access
66  * to the following parameters:
67  * <ul>
68  * <li>signer - A Distinguished Name chain used to sign a bundle. Wildcards in
69  * a DN are not matched according to the filter string rules, but according to
70  * the rules defined for a DN chain.</li>
71  * <li>location - The location of a bundle.</li>
72  * <li>id - The bundle ID of the designated bundle.</li>
73  * <li>name - The symbolic name of a bundle.</li>
74  * </ul>
75  *
76  * @ThreadSafe
77  * @version $Revision: 1.23 $
78  */

79
80 public final class AdminPermission extends BasicPermission {
81     static final long serialVersionUID = 207051004521261705L;
82
83     /**
84      * The action string <code>class</code> (Value is "class").
85      * @since 1.3
86      */

87     public final static String JavaDoc CLASS = "class";
88     /**
89      * The action string <code>execute</code> (Value is "execute").
90      * @since 1.3
91      */

92     public final static String JavaDoc EXECUTE = "execute";
93     /**
94      * The action string <code>extensionLifecycle</code> (Value is
95      * "extensionLifecycle").
96      * @since 1.3
97      */

98     public final static String JavaDoc EXTENSIONLIFECYCLE = "extensionLifecycle";
99     /**
100      * The action string <code>lifecycle</code> (Value is "lifecycle").
101      * @since 1.3
102      */

103     public final static String JavaDoc LIFECYCLE = "lifecycle";
104     /**
105      * The action string <code>listener</code> (Value is "listener").
106      * @since 1.3
107      */

108     public final static String JavaDoc LISTENER = "listener";
109     /**
110      * The action string <code>metadata</code> (Value is "metadata").
111      * @since 1.3
112      */

113     public final static String JavaDoc METADATA = "metadata";
114     /**
115      * The action string <code>resolve</code> (Value is "resolve").
116      * @since 1.3
117      */

118     public final static String JavaDoc RESOLVE = "resolve";
119     /**
120      * The action string <code>resource</code> (Value is "resource").
121      * @since 1.3
122      */

123     public final static String JavaDoc RESOURCE = "resource";
124     /**
125      * The action string <code>startlevel</code> (Value is "startlevel").
126      * @since 1.3
127      */

128     public final static String JavaDoc STARTLEVEL = "startlevel";
129
130     /**
131      * The action string <code>context</code> (Value is "context").
132      * @since 1.4
133      */

134     public final static String JavaDoc CONTEXT = "context";
135
136     private final static int ACTION_CLASS = 0x00000001;
137     private final static int ACTION_EXECUTE = 0x00000002;
138     private final static int ACTION_LIFECYCLE = 0x00000004;
139     private final static int ACTION_LISTENER = 0x00000008;
140     private final static int ACTION_METADATA = 0x00000010;
141     private final static int ACTION_RESOLVE = 0x00000040;
142     private final static int ACTION_RESOURCE = 0x00000080;
143     private final static int ACTION_STARTLEVEL = 0x00000100;
144     private final static int ACTION_EXTENSIONLIFECYCLE = 0x00000200;
145     private final static int ACTION_CONTEXT = 0x00000400;
146     private final static int ACTION_ALL =
147         ACTION_CLASS |
148         ACTION_EXECUTE |
149         ACTION_LIFECYCLE |
150         ACTION_LISTENER |
151         ACTION_METADATA |
152         ACTION_RESOLVE |
153         ACTION_RESOURCE |
154         ACTION_STARTLEVEL |
155         ACTION_EXTENSIONLIFECYCLE |
156         ACTION_CONTEXT;
157     private final static int ACTION_NONE = 0;
158     
159     /**
160      * Indicates that this AdminPermission refers to all bundles
161      * @serial
162      */

163     private boolean wildcard;
164     
165     /**
166      * An x.500 distinguished name used to match a bundle's signature - only used if
167      * wildcard is false and bundle = null
168      * @serial
169      */

170     private String JavaDoc filter;
171
172     /**
173      * The actions in canonical form.
174      *
175      * @serial
176      */

177     private String JavaDoc actions = null;
178
179     /**
180      * The actions mask.
181      */

182     private transient int action_mask = ACTION_NONE;
183
184     /**
185      * The bundle governed by this AdminPermission - only used if
186      * wildcard is false and filter == null
187      */

188     private transient Bundle bundle;
189
190     /**
191      * If this AdminPermission was constructed with a bundle, this dictionary holds
192      * the properties of that bundle, used to match a filter in implies.
193      * This is not initialized until necessary, and then cached in this object.
194      */

195     private transient Dictionary bundleProperties;
196     
197     /**
198      * If this AdminPermission was constructed with a filter, this dictionary holds
199      * a Filter matching object used to evaluate the filter in implies.
200      * This is not initialized until necessary, and then cached in this object
201      */

202     private transient Filter filterImpl;
203     
204     /**
205      * Creates a new <code>AdminPermission</code> object that matches all
206      * bundles and has all actions. Equivalent to AdminPermission("*","*");
207      */

208     public AdminPermission() {
209         this("*",AdminPermission.ACTION_ALL); //$NON-NLS-1$
210
}
211
212     /**
213      * Create a new AdminPermission.
214      *
215      * This constructor must only be used to create a permission that is going
216      * to be checked.
217      * <p>
218      * Examples:
219      *
220      * <pre>
221      * (signer=\*,o=ACME,c=US)
222      * (&amp;(signer=\*,o=ACME,c=US)(name=com.acme.*)(location=http://www.acme.com/bundles/*))
223      * (id&gt;=1)
224      * </pre>
225      *
226      * <p>
227      * When a signer key is used within the filter expression the signer value
228      * must escape the special filter chars ('*', '(', ')').
229      * <p>
230      * Null arguments are equivalent to "*".
231      *
232      * @param filter A filter expression that can use signer, location, id, and
233      * name keys. A value of &quot;*&quot; or <code>null</code> matches
234      * all bundle.
235      * @param actions <code>class</code>, <code>execute</code>,
236      * <code>extensionLifecycle</code>, <code>lifecycle</code>,
237      * <code>listener</code>, <code>metadata</code>,
238      * <code>resolve</code>, <code>resource</code>,
239      * <code>startlevel</code> or <code>context</code>. A value of "*" or <code>null</code>
240      * indicates all actions
241      */

242     public AdminPermission(String JavaDoc filter, String JavaDoc actions) {
243         //arguments will be null if called from a PermissionInfo defined with
244
//no args
245
this(
246                 (filter == null ? "*" : filter), //$NON-NLS-1$
247
getMask((actions == null ? "*" : actions)) //$NON-NLS-1$
248
);
249     }
250
251     /**
252      * Creates a new <code>AdminPermission</code> object to be used by the
253      * code that must check a <code>Permission</code> object.
254      *
255      * @param bundle A bundle
256      * @param actions <code>class</code>, <code>execute</code>,
257      * <code>extensionLifecycle</code>, <code>lifecycle</code>,
258      * <code>listener</code>, <code>metadata</code>,
259      * <code>resolve</code>, <code>resource</code>,
260      * <code>startlevel</code>, <code>context</code>.
261      * @since 1.3
262      */

263     public AdminPermission(Bundle bundle, String JavaDoc actions) {
264         super(createName(bundle));
265         this.bundle = bundle;
266         this.wildcard = false;
267         this.filter = null;
268         this.action_mask = getMask(actions);
269     }
270
271     /**
272      * Create a permission name from a Bundle
273      *
274      * @param bundle Bundle to use to create permission name.
275      * @return permission name.
276      */

277     private static String JavaDoc createName(Bundle bundle) {
278         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
279         sb.append("(id=");
280         sb.append(bundle.getBundleId());
281         sb.append(")");
282         return sb.toString();
283     }
284
285     /**
286      * Determines the equality of two <code>AdminPermission</code> objects.
287      *
288      * @param obj The object being compared for equality with this object.
289      * @return <code>true</code> if <code>obj</code> is equivalent to this
290      * <code>AdminPermission</code>; <code>false</code> otherwise.
291      */

292     public boolean equals(Object JavaDoc obj) {
293         if (obj == this) {
294             return true;
295         }
296         
297         if (!(obj instanceof AdminPermission)) {
298             return false;
299         }
300         
301         AdminPermission a = (AdminPermission) obj;
302
303         return (action_mask == a.action_mask) &&
304                 (wildcard == a.wildcard) &&
305                 (bundle == null ? a.bundle == null : (a.bundle == null ? false : bundle.getBundleId() == a.bundle.getBundleId())) &&
306                 (filter == null ? a.filter == null : filter.equals(a.filter));
307     }
308
309     /**
310      * Returns the hash code value for this object.
311      *
312      * @return Hash code value for this object.
313      */

314     public int hashCode() {
315         return getName().hashCode() ^ getActions().hashCode();
316     }
317
318     /**
319      * Returns the canonical string representation of the
320      * <code>AdminPermission</code> actions.
321      *
322      * <p>
323      * Always returns present <code>AdminPermission</code> actions in the
324      * following order: <code>class</code>, <code>execute</code>,
325      * <code>extensionLifecycle</code>, <code>lifecycle</code>,
326      * <code>listener</code>, <code>metadata</code>, <code>resolve</code>,
327      * <code>resource</code>, <code>startlevel</code>, <code>context</code>.
328      *
329      * @return Canonical string representation of the
330      * <code>AdminPermission</code> actions.
331      */

332     public String JavaDoc getActions() {
333         if (actions == null) {
334             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
335             
336             if ((action_mask & ACTION_CLASS) == ACTION_CLASS) {
337                 sb.append(CLASS);
338                 sb.append(',');
339             }
340
341             if ((action_mask & ACTION_EXECUTE) == ACTION_EXECUTE) {
342                 sb.append(EXECUTE);
343                 sb.append(',');
344             }
345
346             if ((action_mask & ACTION_EXTENSIONLIFECYCLE) == ACTION_EXTENSIONLIFECYCLE) {
347                 sb.append(EXTENSIONLIFECYCLE);
348                 sb.append(',');
349             }
350
351             if ((action_mask & ACTION_LIFECYCLE) == ACTION_LIFECYCLE) {
352                 sb.append(LIFECYCLE);
353                 sb.append(',');
354             }
355
356             if ((action_mask & ACTION_LISTENER) == ACTION_LISTENER) {
357                 sb.append(LISTENER);
358                 sb.append(',');
359             }
360             
361             if ((action_mask & ACTION_METADATA) == ACTION_METADATA) {
362                 sb.append(METADATA);
363                 sb.append(',');
364             }
365
366             if ((action_mask & ACTION_RESOLVE) == ACTION_RESOLVE) {
367                 sb.append(RESOLVE);
368                 sb.append(',');
369             }
370
371             if ((action_mask & ACTION_RESOURCE) == ACTION_RESOURCE) {
372                 sb.append(RESOURCE);
373                 sb.append(',');
374             }
375
376             if ((action_mask & ACTION_STARTLEVEL) == ACTION_STARTLEVEL) {
377                 sb.append(STARTLEVEL);
378                 sb.append(',');
379             }
380
381             if ((action_mask & ACTION_CONTEXT) == ACTION_CONTEXT) {
382                 sb.append(CONTEXT);
383                 sb.append(',');
384             }
385
386             //remove trailing comma
387
if (sb.length() > 0) {
388                 sb.setLength(sb.length()-1);
389             }
390             
391             actions = sb.toString();
392         }
393         return actions;
394     }
395
396     /**
397      * Determines if the specified permission is implied by this object. This
398      * method throws an exception if the specified permission was not
399      * constructed with a bundle.
400      *
401      * <p>
402      * This method returns <code>true</code> if the specified permission is an
403      * AdminPermission AND
404      * <ul>
405      * <li>this object's filter matches the specified permission's bundle ID,
406      * bundle symbolic name, bundle location and bundle signer distinguished
407      * name chain OR</li>
408      * <li>this object's filter is "*"</li>
409      * </ul>
410      * AND this object's actions include all of the specified permission's
411      * actions.
412      * <p>
413      * Special case: if the specified permission was constructed with "*"
414      * filter, then this method returns <code>true</code> if this object's
415      * filter is "*" and this object's actions include all of the specified
416      * permission's actions
417      *
418      * @param p The permission to interrogate.
419      *
420      * @return <code>true</code> if the specified permission is implied by
421      * this object; <code>false</code> otherwise.
422      * @throws RuntimeException if specified permission was not constructed with
423      * a bundle or "*"
424      */

425     public boolean implies(Permission p) {
426         if (!(p instanceof AdminPermission))
427             return false;
428         AdminPermission target = (AdminPermission)p;
429         //check actions first - much faster
430
if ((action_mask & target.action_mask)!=target.action_mask)
431             return false;
432         //if passed in a filter, puke
433
if (target.filter != null)
434             throw new RuntimeException JavaDoc("Cannot imply a filter"); //$NON-NLS-1$
435
//special case - only wildcard implies wildcard
436
if (target.wildcard)
437             return wildcard;
438
439         //check our name
440
if (filter != null) {
441             //it's a filter
442
Filter filterImpl = getFilterImpl();
443             return filterImpl != null && filterImpl.match(target.getProperties());
444         } else if (wildcard) {
445             //it's "*"
446
return true;
447         } else {
448             //it's a bundle id
449
return bundle.equals(target.bundle);
450         }
451     }
452
453     /**
454      * Returns a new <code>PermissionCollection</code> object suitable for
455      * storing <code>AdminPermission</code>s.
456      *
457      * @return A new <code>PermissionCollection</code> object.
458      */

459     public PermissionCollection newPermissionCollection() {
460         return(new AdminPermissionCollection());
461     }
462
463     /**
464      * Package private constructor used by AdminPermissionCollection.
465      *
466      * @param filter name filter
467      * @param action_mask mask
468      */

469     AdminPermission(String JavaDoc filter, int action_mask) {
470         super(filter);
471         
472         //name must be either * or a filter
473
if (filter.equals("*")) { //$NON-NLS-1$
474
this.wildcard = true;
475             this.filter = null;
476         } else {
477             this.wildcard = false;
478             this.filter = filter;
479         }
480         this.bundle = null;
481         this.action_mask = action_mask;
482     }
483
484     /**
485      * Parse action string into action mask.
486      *
487      * @param actions Action string.
488      * @return action mask.
489      */

490     private static int getMask(String JavaDoc actions) {
491     
492         boolean seencomma = false;
493
494         int mask = ACTION_NONE;
495
496         if (actions == null) {
497             return mask;
498         }
499
500         char[] a = actions.toCharArray();
501
502         int i = a.length - 1;
503         if (i < 0)
504             return mask;
505
506         while (i != -1) {
507             char c;
508
509             // skip whitespace
510
while ((i!=-1) && ((c = a[i]) == ' ' ||
511                     c == '\r' ||
512                     c == '\n' ||
513                     c == '\f' ||
514                     c == '\t'))
515                 i--;
516
517             // check for the known strings
518
int matchlen;
519
520             if (i >= 4 &&
521                     (a[i-4] == 'c' || a[i-4] == 'C') &&
522                     (a[i-3] == 'l' || a[i-3] == 'L') &&
523                     (a[i-2] == 'a' || a[i-2] == 'A') &&
524                     (a[i-1] == 's' || a[i-1] == 'S') &&
525                       (a[i] == 's' || a[i] == 'S'))
526             {
527                 matchlen = 5;
528                 mask |= ACTION_CLASS;
529     
530             } else if (i >= 6 &&
531                     (a[i-6] == 'e' || a[i-6] == 'E') &&
532                     (a[i-5] == 'x' || a[i-5] == 'X') &&
533                     (a[i-4] == 'e' || a[i-4] == 'E') &&
534                     (a[i-3] == 'c' || a[i-3] == 'C') &&
535                     (a[i-2] == 'u' || a[i-2] == 'U') &&
536                     (a[i-1] == 't' || a[i-1] == 'T') &&
537                       (a[i] == 'e' || a[i] == 'E'))
538             {
539                 matchlen = 7;
540                 mask |= ACTION_EXECUTE;
541                 
542             } else if (i >= 17 &&
543                     (a[i-17] == 'e' || a[i-17] == 'E') &&
544                     (a[i-16] == 'x' || a[i-16] == 'X') &&
545                     (a[i-15] == 't' || a[i-15] == 'T') &&
546                     (a[i-14] == 'e' || a[i-14] == 'E') &&
547                     (a[i-13] == 'n' || a[i-13] == 'N') &&
548                     (a[i-12] == 's' || a[i-12] == 'S') &&
549                     (a[i-11] == 'i' || a[i-11] == 'I') &&
550                     (a[i-10] == 'o' || a[i-10] == 'O') &&
551                     (a[i-9] == 'n' || a[i-9] == 'N') &&
552                     (a[i-8] == 'l' || a[i-8] == 'L') &&
553                     (a[i-7] == 'i' || a[i-7] == 'I') &&
554                     (a[i-6] == 'f' || a[i-6] == 'F') &&
555                     (a[i-5] == 'e' || a[i-5] == 'E') &&
556                     (a[i-4] == 'c' || a[i-4] == 'C') &&
557                     (a[i-3] == 'y' || a[i-3] == 'Y') &&
558                     (a[i-2] == 'c' || a[i-2] == 'C') &&
559                     (a[i-1] == 'l' || a[i-1] == 'L') &&
560                       (a[i] == 'e' || a[i] == 'E'))
561             {
562                 matchlen = 18;
563                 mask |= ACTION_EXTENSIONLIFECYCLE;
564
565             } else if (i >= 8 &&
566                     (a[i-8] == 'l' || a[i-8] == 'L') &&
567                     (a[i-7] == 'i' || a[i-7] == 'I') &&
568                     (a[i-6] == 'f' || a[i-6] == 'F') &&
569                     (a[i-5] == 'e' || a[i-5] == 'E') &&
570                     (a[i-4] == 'c' || a[i-4] == 'C') &&
571                     (a[i-3] == 'y' || a[i-3] == 'Y') &&
572                     (a[i-2] == 'c' || a[i-2] == 'C') &&
573                     (a[i-1] == 'l' || a[i-1] == 'L') &&
574                       (a[i] == 'e' || a[i] == 'E'))
575             {
576                 matchlen = 9;
577                 mask |= ACTION_LIFECYCLE;
578                 
579             } else if (i >= 7 &&
580                     (a[i-7] == 'l' || a[i-7] == 'L') &&
581                     (a[i-6] == 'i' || a[i-6] == 'I') &&
582                     (a[i-5] == 's' || a[i-5] == 'S') &&
583                     (a[i-4] == 't' || a[i-4] == 'T') &&
584                     (a[i-3] == 'e' || a[i-3] == 'E') &&
585                     (a[i-2] == 'n' || a[i-2] == 'N') &&
586                     (a[i-1] == 'e' || a[i-1] == 'E') &&
587                       (a[i] == 'r' || a[i] == 'R'))
588             {
589                 matchlen = 8;
590                 mask |= ACTION_LISTENER;
591             
592             } else if (i >= 7 &&
593                     (a[i-7] == 'm' || a[i-7] == 'M') &&
594                     (a[i-6] == 'e' || a[i-6] == 'E') &&
595                     (a[i-5] == 't' || a[i-5] == 'T') &&
596                     (a[i-4] == 'a' || a[i-4] == 'A') &&
597                     (a[i-3] == 'd' || a[i-3] == 'D') &&
598                     (a[i-2] == 'a' || a[i-2] == 'A') &&
599                     (a[i-1] == 't' || a[i-1] == 'T') &&
600                       (a[i] == 'a' || a[i] == 'A'))
601             {
602                 matchlen = 8;
603                 mask |= ACTION_METADATA;
604
605             } else if (i >= 6 &&
606                     (a[i-6] == 'r' || a[i-6] == 'R') &&
607                     (a[i-5] == 'e' || a[i-5] == 'E') &&
608                     (a[i-4] == 's' || a[i-4] == 'S') &&
609                     (a[i-3] == 'o' || a[i-3] == 'O') &&
610                     (a[i-2] == 'l' || a[i-2] == 'L') &&
611                     (a[i-1] == 'v' || a[i-1] == 'V') &&
612                       (a[i] == 'e' || a[i] == 'E'))
613             {
614                 matchlen = 7;
615                 mask |= ACTION_RESOLVE;
616                 
617             } else if (i >= 7 &&
618                         (a[i-7] == 'r' || a[i-7] == 'R') &&
619                         (a[i-6] == 'e' || a[i-6] == 'E') &&
620                         (a[i-5] == 's' || a[i-5] == 'S') &&
621                         (a[i-4] == 'o' || a[i-4] == 'O') &&
622                         (a[i-3] == 'u' || a[i-3] == 'U') &&
623                         (a[i-2] == 'r' || a[i-2] == 'R') &&
624                         (a[i-1] == 'c' || a[i-1] == 'C') &&
625                           (a[i] == 'e' || a[i] == 'E'))
626             {
627                 matchlen = 8;
628                 mask |= ACTION_RESOURCE;
629
630             } else if (i >= 9 &&
631                     (a[i-9] == 's' || a[i-9] == 'S') &&
632                     (a[i-8] == 't' || a[i-8] == 'T') &&
633                     (a[i-7] == 'a' || a[i-7] == 'A') &&
634                     (a[i-6] == 'r' || a[i-6] == 'R') &&
635                     (a[i-5] == 't' || a[i-5] == 'T') &&
636                     (a[i-4] == 'l' || a[i-4] == 'L') &&
637                     (a[i-3] == 'e' || a[i-3] == 'E') &&
638                     (a[i-2] == 'v' || a[i-2] == 'V') &&
639                     (a[i-1] == 'e' || a[i-1] == 'E') &&
640                       (a[i] == 'l' || a[i] == 'L'))
641             {
642                 matchlen = 10;
643                 mask |= ACTION_STARTLEVEL;
644
645             } else if (i >= 6 &&
646                     (a[i-6] == 'c' || a[i-6] == 'C') &&
647                     (a[i-5] == 'o' || a[i-5] == 'O') &&
648                     (a[i-4] == 'n' || a[i-4] == 'N') &&
649                     (a[i-3] == 't' || a[i-3] == 'T') &&
650                     (a[i-2] == 'e' || a[i-2] == 'E') &&
651                     (a[i-1] == 'x' || a[i-1] == 'X') &&
652                       (a[i] == 't' || a[i] == 'T'))
653             {
654                 matchlen = 7;
655                 mask |= ACTION_CONTEXT;
656
657             } else if (i >= 0 &&
658
659                     (a[i] == '*'))
660             {
661                 matchlen = 1;
662                 mask |= ACTION_ALL;
663
664             } else {
665                 // parse error
666
throw new IllegalArgumentException JavaDoc(
667                         "invalid permission: " + actions); //$NON-NLS-1$
668
}
669
670         // make sure we didn't just match the tail of a word
671
// like "ackbarfstartlevel". Also, skip to the comma.
672
seencomma = false;
673         while (i >= matchlen && !seencomma) {
674             switch(a[i-matchlen]) {
675                 case ',':
676                     seencomma = true;
677                     /*FALLTHROUGH*/
678                 case ' ': case '\r': case '\n':
679                 case '\f': case '\t':
680                     break;
681                 default:
682                     throw new IllegalArgumentException JavaDoc(
683                             "invalid permission: " + actions); //$NON-NLS-1$
684
}
685             i--;
686         }
687
688         // point i at the location of the comma minus one (or -1).
689
i -= matchlen;
690     }
691
692     if (seencomma) {
693         throw new IllegalArgumentException JavaDoc("invalid permission: " + //$NON-NLS-1$
694
actions);
695     }
696
697     return mask;
698     }
699      
700     /**
701      * Called by <code><@link AdminPermission#implies(Permission)></code> on an AdminPermission
702      * which was constructed with a Bundle. This method loads a dictionary with the
703      * filter-matchable properties of this bundle. The dictionary is cached so this lookup
704      * only happens once.
705      *
706      * This method should only be called on an AdminPermission which was constructed with a
707      * bundle
708      *
709      * @return a dictionary of properties for this bundle
710      */

711     private Dictionary getProperties() {
712         if (bundleProperties == null) {
713             bundleProperties = new Hashtable();
714
715             AccessController.doPrivileged(new PrivilegedAction() {
716                 public Object JavaDoc run() {
717                     //set Id
718
bundleProperties.put("id",new Long JavaDoc(bundle.getBundleId())); //$NON-NLS-1$
719

720                     //set location
721
bundleProperties.put("location",bundle.getLocation()); //$NON-NLS-1$
722

723                     //set name
724
if (bundle.getSymbolicName() != null)
725                         bundleProperties.put("name",bundle.getSymbolicName()); //$NON-NLS-1$
726

727                     //set signers
728
bundleProperties.put("signer",new SignerWrapper(bundle)); //$NON-NLS-1$
729

730                     return null;
731                 }
732             });
733         }
734         return bundleProperties;
735     }
736
737     private static class SignerWrapper extends Object JavaDoc {
738         private Bundle bundle;
739         private String JavaDoc pattern;
740         public SignerWrapper(String JavaDoc pattern) {
741             this.pattern = pattern;
742         }
743         SignerWrapper(Bundle bundle) {
744             this.bundle = bundle;
745         }
746         
747         public boolean equals(Object JavaDoc o) {
748             if (!(o instanceof SignerWrapper))
749                 return false;
750             SignerWrapper other = (SignerWrapper) o;
751             AbstractBundle matchBundle = (AbstractBundle) (bundle != null ? bundle : other.bundle);
752             String JavaDoc matchPattern = bundle != null ? other.pattern : pattern;
753             return matchBundle.getBundleData().matchDNChain(matchPattern);
754         }
755     }
756     
757     /**
758      * Called by <tt><@link AdminPermission#implies(Permission)></tt> on an AdminPermission
759      * which was constructed with a filter. This method loads a FilterImpl with the
760      * filter specification of this AdminPermission. The filter is cached so this work
761      * only happens once.
762      *
763      * This method should only be called on an AdminPermission which was constructed with a
764      * filter
765      *
766      * @return a filterImpl for this bundle
767      */

768     private Filter getFilterImpl() {
769         if (filterImpl == null) {
770             try {
771                 int pos = filter.indexOf("signer"); //$NON-NLS-1$
772
if (pos != -1){
773                 
774                     //there may be a signer attribute
775
StringBuffer JavaDoc filterBuf = new StringBuffer JavaDoc(filter);
776                     int numAsteriskFound = 0; //use as offset to replace in buffer
777

778                     int walkbackPos; //temp pos
779

780                     //find occurences of (signer= and escape out *'s
781
while (pos != -1) {
782
783                         //walk back and look for '(' to see if this is an attr
784
walkbackPos = pos-1;
785                         
786                         //consume whitespace
787
while(walkbackPos >= 0 && Character.isWhitespace(filter.charAt(walkbackPos))) {
788                             walkbackPos--;
789                         }
790                         if (walkbackPos <0) {
791                             //filter is invalid - FilterImpl will throw error
792
break;
793                         }
794                         
795                         //check to see if we have unescaped '('
796
if (filter.charAt(walkbackPos) != '(' || (walkbackPos > 0 && filter.charAt(walkbackPos-1) == '\\')) {
797                             //'(' was escaped or not there
798
pos = filter.indexOf("signer",pos+6); //$NON-NLS-1$
799
continue;
800                         }
801                         pos+=6; //skip over 'signer'
802

803                         //found signer - consume whitespace before '='
804
while (Character.isWhitespace(filter.charAt(pos))) {
805                             pos++;
806                         }
807
808                         //look for '='
809
if (filter.charAt(pos) != '=') {
810                             //attr was signerx - keep looking
811
pos = filter.indexOf("signer",pos); //$NON-NLS-1$
812
continue;
813                         }
814                         pos++; //skip over '='
815

816                         //found signer value - escape '*'s
817
while (!(filter.charAt(pos) == ')' && filter.charAt(pos-1) != '\\')) {
818                             if (filter.charAt(pos) == '*') {
819                                 filterBuf.insert(pos+numAsteriskFound,'\\');
820                                 numAsteriskFound++;
821                             }
822                             pos++;
823                         }
824
825                         //end of signer value - look for more?
826
pos = filter.indexOf("signer",pos); //$NON-NLS-1$
827
} //end while (pos != -1)
828
filter = filterBuf.toString();
829                 } //end if (pos != -1)
830

831                 filterImpl = new FilterImpl(filter);
832             } catch (InvalidSyntaxException e) {
833                 //we will return null
834
}
835         }
836         return filterImpl;
837     }
838
839     /**
840      * Returns the current action mask.
841      * <p>
842      * Used by the AdminPermissionCollection class.
843      *
844      * @return Current action mask.
845      */

846     int getMask() {
847         return action_mask;
848     }
849
850     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
851         // Write out the actions. The superclass takes care of the name
852
// call getActions to make sure actions field is initialized
853
if (actions == null)
854             getActions();
855         if (filter == null && !wildcard)
856             throw new UnsupportedOperationException JavaDoc("cannot serialize"); //$NON-NLS-1$
857
s.defaultWriteObject();
858     }
859
860     /**
861      * readObject is called to restore the state of this permission from a
862      * stream.
863      */

864     private synchronized void readObject(java.io.ObjectInputStream JavaDoc s) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
865         // Read in the action, then initialize the rest
866
s.defaultReadObject();
867         action_mask = getMask(actions);
868     }
869 }
870
871 /**
872  * Stores a collection of <code>AdminPermission</code>s.
873  */

874 final class AdminPermissionCollection extends PermissionCollection
875 {
876     private static final long serialVersionUID = 3906372644575328048L;
877     /**
878      * Collection of permissions.
879      *
880      * @serial
881      */

882     private Hashtable permissions;
883
884     /**
885      * Create an empty AdminPermissions object.
886      *
887      */

888
889     public AdminPermissionCollection()
890     {
891         permissions = new Hashtable();
892     }
893
894     /**
895      * Adds a permission to the <code>AdminPermission</code> objects. The key for
896      * the hashtable is the name
897      *
898      * @param permission The <code>AdminPermission</code> object to add.
899      *
900      * @exception IllegalArgumentException If the permission is not an
901      * <code>AdminPermission</code> instance.
902      *
903      * @exception SecurityException If this <code>AdminPermissionCollection</code>
904      * object has been marked read-only.
905      */

906     public void add(Permission permission)
907     {
908         if (! (permission instanceof AdminPermission))
909             throw new IllegalArgumentException JavaDoc("invalid permission: "+ //$NON-NLS-1$
910
permission);
911         if (isReadOnly())
912             throw new SecurityException JavaDoc("attempt to add a Permission to a " + //$NON-NLS-1$
913
"readonly AdminCollection"); //$NON-NLS-1$
914
AdminPermission ap = (AdminPermission) permission;
915         AdminPermission existing = (AdminPermission) permissions.get(ap.getName());
916         if (existing != null){
917             int oldMask = existing.getMask();
918             int newMask = ap.getMask();
919         
920             if (oldMask != newMask) {
921                 permissions.put(existing.getName(),
922                         new AdminPermission(existing.getName(), oldMask | newMask));
923             }
924         } else {
925             permissions.put(ap.getName(), ap);
926         }
927     }
928
929
930     /**
931      * Determines if the specified permissions implies the permissions
932      * expressed in <code>permission</code>.
933      *
934      * @param permission The Permission object to compare with the <code>AdminPermission</code>
935      * objects in this collection.
936      *
937      * @return <code>true</code> if <code>permission</code> is implied by an
938      * <code>AdminPermission</code> in this collection, <code>false</code> otherwise.
939      */

940     public boolean implies(Permission permission)
941     {
942         if (!(permission instanceof AdminPermission))
943             return(false);
944
945         AdminPermission target = (AdminPermission) permission;
946         
947         //just iterate one by one
948
Iterator permItr = permissions.values().iterator();
949         
950         while(permItr.hasNext())
951             if (((AdminPermission)permItr.next()).implies(target))
952                 return true;
953         return false;
954     }
955  
956
957     /**
958      * Returns an enumeration of all <code>AdminPermission</code> objects in the
959      * container.
960      *
961      * @return Enumeration of all <code>AdminPermission</code> objects.
962      */

963
964     public Enumeration elements()
965     {
966         return(Collections.enumeration(permissions.values()));
967     }
968 }
969
Popular Tags