KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/PackagePermission.java,v 1.14 2006/06/16 16:31:18 hargrave Exp $
3  *
4  * Copyright (c) OSGi Alliance (2000, 2006). 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.Enumeration JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
26 /**
27  * A bundle's authority to import or export a package.
28  *
29  * <p>
30  * A package is a dot-separated string that defines a fully qualified Java
31  * package.
32  * <p>
33  * For example:
34  *
35  * <pre>
36  * <code>
37  * org.osgi.service.http
38  * </code>
39  * </pre>
40  *
41  * <p>
42  * <code>PackagePermission</code> has two actions: <code>EXPORT</code> and
43  * <code>IMPORT</code>. The <code>EXPORT</code> action implies the
44  * <code>IMPORT</code> action.
45  *
46  * @version $Revision: 1.14 $
47  */

48
49 public final class PackagePermission extends BasicPermission {
50     static final long serialVersionUID = -5107705877071099135L;
51     /**
52      * The action string <code>export</code>.
53      */

54     public final static String JavaDoc EXPORT = "export";
55
56     /**
57      * The action string <code>import</code>.
58      */

59     public final static String JavaDoc IMPORT = "import";
60
61     private final static int ACTION_EXPORT = 0x00000001;
62     private final static int ACTION_IMPORT = 0x00000002;
63     private final static int ACTION_ALL = ACTION_EXPORT
64                                                             | ACTION_IMPORT;
65     private final static int ACTION_NONE = 0;
66     /**
67      * The actions mask.
68      */

69     private transient int action_mask = ACTION_NONE;
70
71     /**
72      * The actions in canonical form.
73      *
74      * @serial
75      */

76     private String JavaDoc actions = null;
77
78     /**
79      * Defines the authority to import and/or export a package within the OSGi
80      * environment.
81      * <p>
82      * The name is specified as a normal Java package name: a dot-separated
83      * string. Wildcards may be used. For example:
84      *
85      * <pre>
86      * org.osgi.service.http
87      * javax.servlet.*
88      * *
89      * </pre>
90      *
91      * <p>
92      * Package Permissions are granted over all possible versions of a package.
93      *
94      * A bundle that needs to export a package must have the appropriate
95      * <code>PackagePermission</code> for that package; similarly, a bundle
96      * that needs to import a package must have the appropriate
97      * <code>PackagePermssion</code> for that package.
98      * <p>
99      * Permission is granted for both classes and resources.
100      *
101      * @param name Package name.
102      * @param actions <code>EXPORT</code>,<code>IMPORT</code> (canonical
103      * order).
104      */

105
106     public PackagePermission(String JavaDoc name, String JavaDoc actions) {
107         this(name, getMask(actions));
108     }
109
110     /**
111      * Package private constructor used by PackagePermissionCollection.
112      *
113      * @param name class name
114      * @param mask action mask
115      */

116     PackagePermission(String JavaDoc name, int mask) {
117         super(name);
118         init(mask);
119     }
120
121     /**
122      * Called by constructors and when deserialized.
123      *
124      * @param mask action mask
125      */

126     private void init(int mask) {
127         if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
128             throw new IllegalArgumentException JavaDoc("invalid action string");
129         }
130
131         action_mask = mask;
132     }
133
134     /**
135      * Parse action string into action mask.
136      *
137      * @param actions Action string.
138      * @return action mask.
139      */

140     private static int getMask(String JavaDoc actions) {
141         boolean seencomma = false;
142
143         int mask = ACTION_NONE;
144
145         if (actions == null) {
146             return (mask);
147         }
148
149         char[] a = actions.toCharArray();
150
151         int i = a.length - 1;
152         if (i < 0)
153             return (mask);
154
155         while (i != -1) {
156             char c;
157
158             // skip whitespace
159
while ((i != -1)
160                     && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
161                             || c == '\f' || c == '\t'))
162                 i--;
163
164             // check for the known strings
165
int matchlen;
166
167             if (i >= 5 && (a[i - 5] == 'i' || a[i - 5] == 'I')
168                     && (a[i - 4] == 'm' || a[i - 4] == 'M')
169                     && (a[i - 3] == 'p' || a[i - 3] == 'P')
170                     && (a[i - 2] == 'o' || a[i - 2] == 'O')
171                     && (a[i - 1] == 'r' || a[i - 1] == 'R')
172                     && (a[i] == 't' || a[i] == 'T')) {
173                 matchlen = 6;
174                 mask |= ACTION_IMPORT;
175
176             }
177             else
178                 if (i >= 5 && (a[i - 5] == 'e' || a[i - 5] == 'E')
179                         && (a[i - 4] == 'x' || a[i - 4] == 'X')
180                         && (a[i - 3] == 'p' || a[i - 3] == 'P')
181                         && (a[i - 2] == 'o' || a[i - 2] == 'O')
182                         && (a[i - 1] == 'r' || a[i - 1] == 'R')
183                         && (a[i] == 't' || a[i] == 'T')) {
184                     matchlen = 6;
185                     mask |= ACTION_EXPORT | ACTION_IMPORT;
186
187                 }
188                 else {
189                     // parse error
190
throw new IllegalArgumentException JavaDoc("invalid permission: "
191                             + actions);
192                 }
193
194             // make sure we didn't just match the tail of a word
195
// like "ackbarfimport". Also, skip to the comma.
196
seencomma = false;
197             while (i >= matchlen && !seencomma) {
198                 switch (a[i - matchlen]) {
199                     case ',' :
200                         seencomma = true;
201                     /* FALLTHROUGH */
202                     case ' ' :
203                     case '\r' :
204                     case '\n' :
205                     case '\f' :
206                     case '\t' :
207                         break;
208                     default :
209                         throw new IllegalArgumentException JavaDoc(
210                                 "invalid permission: " + actions);
211                 }
212                 i--;
213             }
214
215             // point i at the location of the comma minus one (or -1).
216
i -= matchlen;
217         }
218
219         if (seencomma) {
220             throw new IllegalArgumentException JavaDoc("invalid permission: " + actions);
221         }
222
223         return (mask);
224     }
225
226     /**
227      * Determines if the specified permission is implied by this object.
228      *
229      * <p>
230      * This method checks that the package name of the target is implied by the
231      * package name of this object. The list of <code>PackagePermission</code>
232      * actions must either match or allow for the list of the target object to
233      * imply the target <code>PackagePermission</code> action.
234      * <p>
235      * The permission to export a package implies the permission to import the
236      * named package.
237      *
238      * <pre>
239      * x.y.*,&quot;export&quot; -&gt; x.y.z,&quot;export&quot; is true
240      * *,&quot;import&quot; -&gt; x.y, &quot;import&quot; is true
241      * *,&quot;export&quot; -&gt; x.y, &quot;import&quot; is true
242      * x.y,&quot;export&quot; -&gt; x.y.z, &quot;export&quot; is false
243      * </pre>
244      *
245      * @param p The target permission to interrogate.
246      * @return <code>true</code> if the specified
247      * <code>PackagePermission</code> action is implied by this
248      * object; <code>false</code> otherwise.
249      */

250
251     public boolean implies(Permission p) {
252         if (p instanceof PackagePermission) {
253             PackagePermission target = (PackagePermission) p;
254
255             return (((action_mask & target.action_mask) == target.action_mask) && super
256                     .implies(p));
257         }
258
259         return (false);
260     }
261
262     /**
263      * Returns the canonical string representation of the
264      * <code>PackagePermission</code> actions.
265      *
266      * <p>
267      * Always returns present <code>PackagePermission</code> actions in the
268      * following order: <code>EXPORT</code>,<code>IMPORT</code>.
269      *
270      * @return Canonical string representation of the
271      * <code>PackagePermission</code> actions.
272      */

273
274     public String JavaDoc getActions() {
275         if (actions == null) {
276             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
277             boolean comma = false;
278
279             if ((action_mask & ACTION_EXPORT) == ACTION_EXPORT) {
280                 sb.append(EXPORT);
281                 comma = true;
282             }
283
284             if ((action_mask & ACTION_IMPORT) == ACTION_IMPORT) {
285                 if (comma)
286                     sb.append(',');
287                 sb.append(IMPORT);
288             }
289
290             actions = sb.toString();
291         }
292
293         return (actions);
294     }
295
296     /**
297      * Returns a new <code>PermissionCollection</code> object suitable for
298      * storing <code>PackagePermission</code> objects.
299      *
300      * @return A new <code>PermissionCollection</code> object.
301      */

302     public PermissionCollection newPermissionCollection() {
303         return (new PackagePermissionCollection());
304     }
305
306     /**
307      * Determines the equality of two <code>PackagePermission</code> objects.
308      *
309      * This method checks that specified package has the same package name and
310      * <code>PackagePermission</code> actions as this
311      * <code>PackagePermission</code> object.
312      *
313      * @param obj The object to test for equality with this
314      * <code>PackagePermission</code> object.
315      * @return <code>true</code> if <code>obj</code> is a
316      * <code>PackagePermission</code>, and has the same package name
317      * and actions as this <code>PackagePermission</code> object;
318      * <code>false</code> otherwise.
319      */

320     public boolean equals(Object JavaDoc obj) {
321         if (obj == this) {
322             return (true);
323         }
324
325         if (!(obj instanceof PackagePermission)) {
326             return (false);
327         }
328
329         PackagePermission p = (PackagePermission) obj;
330
331         return ((action_mask == p.action_mask) && getName().equals(p.getName()));
332     }
333
334     /**
335      * Returns the hash code value for this object.
336      *
337      * @return A hash code value for this object.
338      */

339
340     public int hashCode() {
341         return (getName().hashCode() ^ getActions().hashCode());
342     }
343
344     /**
345      * Returns the current action mask.
346      * <p>
347      * Used by the PackagePermissionCollection class.
348      *
349      * @return Current action mask.
350      */

351     int getMask() {
352         return (action_mask);
353     }
354
355     /**
356      * WriteObject is called to save the state of this permission object to a
357      * stream. The actions are serialized, and the superclass takes care of the
358      * name.
359      */

360
361     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc s)
362             throws IOException JavaDoc {
363         // Write out the actions. The superclass takes care of the name
364
// call getActions to make sure actions field is initialized
365
if (actions == null)
366             getActions();
367         s.defaultWriteObject();
368     }
369
370     /**
371      * readObject is called to restore the state of this permission from a
372      * stream.
373      */

374     private synchronized void readObject(java.io.ObjectInputStream JavaDoc s)
375             throws IOException JavaDoc, ClassNotFoundException JavaDoc {
376         // Read in the action, then initialize the rest
377
s.defaultReadObject();
378         init(getMask(actions));
379     }
380 }
381
382 /**
383  * Stores a set of <code>PackagePermission</code> permissions.
384  *
385  * @see java.security.Permission
386  * @see java.security.Permissions
387  * @see java.security.PermissionCollection
388  */

389
390 final class PackagePermissionCollection extends PermissionCollection {
391     static final long serialVersionUID = -3350758995234427603L;
392     /**
393      * Table of permissions.
394      *
395      * @serial
396      */

397     private Hashtable JavaDoc permissions;
398
399     /**
400      * Boolean saying if "*" is in the collection.
401      *
402      * @serial
403      */

404     private boolean all_allowed;
405
406     /**
407      * Create an empty PackagePermissions object.
408      */

409
410     public PackagePermissionCollection() {
411         permissions = new Hashtable JavaDoc();
412         all_allowed = false;
413     }
414
415     /**
416      * Adds a permission to the <code>PackagePermission</code> objects. The
417      * key for the hash is the name.
418      *
419      * @param permission The <code>PackagePermission</code> object to add.
420      *
421      * @throws IllegalArgumentException If the permission is not a
422      * <code>PackagePermission</code> instance.
423      *
424      * @throws SecurityException If this
425      * <code>PackagePermissionCollection</code> object has been marked
426      * read-only.
427      */

428
429     public void add(Permission permission) {
430         if (!(permission instanceof PackagePermission))
431             throw new IllegalArgumentException JavaDoc("invalid permission: "
432                     + permission);
433         if (isReadOnly())
434             throw new SecurityException JavaDoc("attempt to add a Permission to a "
435                     + "readonly PermissionCollection");
436
437         PackagePermission pp = (PackagePermission) permission;
438         String JavaDoc name = pp.getName();
439
440         PackagePermission existing = (PackagePermission) permissions.get(name);
441
442         if (existing != null) {
443             int oldMask = existing.getMask();
444             int newMask = pp.getMask();
445             if (oldMask != newMask) {
446                 permissions.put(name, new PackagePermission(name, oldMask
447                         | newMask));
448
449             }
450         }
451         else {
452             permissions.put(name, permission);
453         }
454
455         if (!all_allowed) {
456             if (name.equals("*"))
457                 all_allowed = true;
458         }
459     }
460
461     /**
462      * Determines if the specified permissions implies the permissions expressed
463      * in <code>permission</code>.
464      *
465      * @param permission The Permission object to compare with this
466      * <code>PackagePermission</code> object.
467      *
468      * @return <code>true</code> if <code>permission</code> is a proper
469      * subset of a permission in the set; <code>false</code>
470      * otherwise.
471      */

472
473     public boolean implies(Permission permission) {
474         if (!(permission instanceof PackagePermission))
475             return (false);
476
477         PackagePermission pp = (PackagePermission) permission;
478         PackagePermission x;
479
480         int desired = pp.getMask();
481         int effective = 0;
482
483         // short circuit if the "*" Permission was added
484
if (all_allowed) {
485             x = (PackagePermission) permissions.get("*");
486             if (x != null) {
487                 effective |= x.getMask();
488                 if ((effective & desired) == desired)
489                     return (true);
490             }
491         }
492
493         // strategy:
494
// Check for full match first. Then work our way up the
495
// name looking for matches on a.b.*
496

497         String JavaDoc name = pp.getName();
498
499         x = (PackagePermission) permissions.get(name);
500
501         if (x != null) {
502             // we have a direct hit!
503
effective |= x.getMask();
504             if ((effective & desired) == desired)
505                 return (true);
506         }
507
508         // work our way up the tree...
509
int last, offset;
510
511         offset = name.length() - 1;
512
513         while ((last = name.lastIndexOf(".", offset)) != -1) {
514
515             name = name.substring(0, last + 1) + "*";
516             x = (PackagePermission) permissions.get(name);
517
518             if (x != null) {
519                 effective |= x.getMask();
520                 if ((effective & desired) == desired)
521                     return (true);
522             }
523             offset = last - 1;
524         }
525
526         // we don't have to check for "*" as it was already checked
527
// at the top (all_allowed), so we just return false
528
return (false);
529     }
530
531     /**
532      * Returns an enumeration of all <code>PackagePermission</code> objects in
533      * the container.
534      *
535      * @return Enumeration of all <code>PackagePermission</code> objects.
536      */

537
538     public Enumeration JavaDoc elements() {
539         return (permissions.elements());
540     }
541 }
542
Popular Tags