KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/BundlePermission.java,v 1.16 2007/02/20 00:06:02 hargrave Exp $
3  *
4  * Copyright (c) OSGi Alliance (2004, 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.Enumeration JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
26 /**
27  * A bundle's authority to require or provide a bundle or to receive or attach
28  * fragments.
29  *
30  * <p>
31  * A bundle symbolic name defines a unique fully qualified name.
32  * <p>
33  * For example:
34  *
35  * <pre>
36  * <code>
37  * org.osgi.example.bundle
38  * </code>
39  * </pre>
40  *
41  * <p>
42  * <code>BundlePermission</code> has four actions: <code>PROVIDE</code>,
43  * <code>REQUIRE</code>,<code>HOST</code>, and <code>FRAGMENT</code>.
44  * The <code>PROVIDE</code> action implies the <code>REQUIRE</code> action.
45  *
46  * @since 1.3
47  * @version $Revision: 1.16 $
48  */

49
50 public final class BundlePermission extends BasicPermission {
51
52     private static final long serialVersionUID = 3257846601685873716L;
53
54     /**
55      * The action string <code>provide</code>.
56      */

57     public final static String JavaDoc PROVIDE = "provide";
58
59     /**
60      * The action string <code>require</code>.
61      */

62     public final static String JavaDoc REQUIRE = "require";
63
64     /**
65      * The action string <code>host</code>.
66      */

67     public final static String JavaDoc HOST = "host";
68
69     /**
70      * The action string <code>fragment</code>.
71      */

72     public final static String JavaDoc FRAGMENT = "fragment";
73
74     private final static int ACTION_PROVIDE = 0x00000001;
75     private final static int ACTION_REQUIRE = 0x00000002;
76     private final static int ACTION_HOST = 0x00000004;
77     private final static int ACTION_FRAGMENT = 0x00000008;
78     private final static int ACTION_ALL = ACTION_PROVIDE
79                                                             | ACTION_REQUIRE
80                                                             | ACTION_HOST
81                                                             | ACTION_FRAGMENT;
82     private final static int ACTION_NONE = 0;
83     /**
84      * The actions mask.
85      */

86     private transient int action_mask = ACTION_NONE;
87
88     /**
89      * The actions in canonical form.
90      *
91      * @serial
92      */

93     private String JavaDoc actions = null;
94
95     /**
96      * Defines the authority to provide and/or require and or specify a host
97      * fragment symbolic name within the OSGi environment.
98      * <p>
99      * Bundle Permissions are granted over all possible versions of a bundle.
100      *
101      * A bundle that needs to provide a bundle must have the appropriate
102      * <code>BundlePermission</code> for the symbolic name; a bundle that
103      * requires a bundle must have the appropriate <code>BundlePermssion</code>
104      * for that symbolic name; a bundle that specifies a fragment host must have
105      * the appropriate <code>BundlePermission</code> for that symbolic name.
106      *
107      * @param symbolicName the bundle symbolic name.
108      * @param actions <code>PROVIDE</code>,<code>REQUIRE</code>,
109      * <code>HOST</code>,<code>FRAGMENT</code> (canonical order).
110      */

111
112     public BundlePermission(String JavaDoc symbolicName, String JavaDoc actions) {
113         this(symbolicName, getMask(actions));
114     }
115
116     /**
117      * Bundle private constructor used by BundlePermissionCollection.
118      *
119      * @param symbolicName the bundle symbolic name
120      * @param mask the action mask
121      */

122     BundlePermission(String JavaDoc symbolicName, int mask) {
123         super(symbolicName);
124         init(mask);
125     }
126
127     /**
128      * Called by constructors and when deserialized.
129      *
130      * @param mask
131      */

132     private void init(int mask) {
133         if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) {
134             throw new IllegalArgumentException JavaDoc("invalid action string");
135         }
136
137         action_mask = mask;
138     }
139
140     /**
141      * Parse action string into action mask.
142      *
143      * @param actions Action string.
144      * @return action mask.
145      */

146     private static int getMask(String JavaDoc actions) {
147         boolean seencomma = false;
148
149         int mask = ACTION_NONE;
150
151         if (actions == null) {
152             return (mask);
153         }
154
155         char[] a = actions.toCharArray();
156
157         int i = a.length - 1;
158         if (i < 0)
159             return (mask);
160
161         while (i != -1) {
162             char c;
163
164             // skip whitespace
165
while ((i != -1)
166                     && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
167                             || c == '\f' || c == '\t'))
168                 i--;
169
170             // check for the known strings
171
int matchlen;
172
173             if (i >= 6 && (a[i - 6] == 'p' || a[i - 6] == 'P')
174                     && (a[i - 5] == 'r' || a[i - 5] == 'R')
175                     && (a[i - 4] == 'o' || a[i - 4] == 'O')
176                     && (a[i - 3] == 'v' || a[i - 3] == 'V')
177                     && (a[i - 2] == 'i' || a[i - 2] == 'I')
178                     && (a[i - 1] == 'd' || a[i - 1] == 'D')
179                     && (a[i] == 'e' || a[i] == 'E')) {
180                 matchlen = 7;
181                 mask |= ACTION_PROVIDE | ACTION_REQUIRE;
182             }
183             else
184                 if (i >= 6 && (a[i - 6] == 'r' || a[i - 6] == 'R')
185                         && (a[i - 5] == 'e' || a[i - 5] == 'E')
186                         && (a[i - 4] == 'q' || a[i - 4] == 'Q')
187                         && (a[i - 3] == 'u' || a[i - 3] == 'U')
188                         && (a[i - 2] == 'i' || a[i - 2] == 'I')
189                         && (a[i - 1] == 'r' || a[i - 1] == 'R')
190                         && (a[i] == 'e' || a[i] == 'E')) {
191                     matchlen = 7;
192                     mask |= ACTION_REQUIRE;
193                 }
194                 else
195                     if (i >= 3 && (a[i - 3] == 'h' || a[i - 3] == 'H')
196                             && (a[i - 2] == 'o' || a[i - 2] == 'O')
197                             && (a[i - 1] == 's' || a[i - 1] == 'S')
198                             && (a[i] == 't' || a[i] == 'T')) {
199                         matchlen = 4;
200                         mask |= ACTION_HOST;
201                     }
202                     else
203                         if (i >= 7 && (a[i - 7] == 'f' || a[i - 7] == 'F')
204                                 && (a[i - 6] == 'r' || a[i - 6] == 'R')
205                                 && (a[i - 5] == 'a' || a[i - 5] == 'A')
206                                 && (a[i - 4] == 'g' || a[i - 4] == 'G')
207                                 && (a[i - 3] == 'm' || a[i - 3] == 'M')
208                                 && (a[i - 2] == 'e' || a[i - 2] == 'E')
209                                 && (a[i - 1] == 'n' || a[i - 1] == 'N')
210                                 && (a[i] == 't' || a[i] == 'T')) {
211                             matchlen = 8;
212                             mask |= ACTION_FRAGMENT;
213                         }
214                         else {
215                             // parse error
216
throw new IllegalArgumentException JavaDoc(
217                                     "invalid permission: " + actions);
218                         }
219
220             // make sure we didn't just match the tail of a word
221
// like "ackbarfrequire". Also, skip to the comma.
222
seencomma = false;
223             while (i >= matchlen && !seencomma) {
224                 switch (a[i - matchlen]) {
225                     case ',' :
226                         seencomma = true;
227                     /* FALLTHROUGH */
228                     case ' ' :
229                     case '\r' :
230                     case '\n' :
231                     case '\f' :
232                     case '\t' :
233                         break;
234                     default :
235                         throw new IllegalArgumentException JavaDoc(
236                                 "invalid permission: " + actions);
237                 }
238                 i--;
239             }
240
241             // point i at the location of the comma minus one (or -1).
242
i -= matchlen;
243         }
244
245         if (seencomma) {
246             throw new IllegalArgumentException JavaDoc("invalid permission: " + actions);
247         }
248
249         return (mask);
250     }
251
252     /**
253      * Determines if the specified permission is implied by this object.
254      *
255      * <p>
256      * This method checks that the symbolic name of the target is implied by the
257      * symbolic name of this object. The list of <code>BundlePermission</code>
258      * actions must either match or allow for the list of the target object to
259      * imply the target <code>BundlePermission</code> action.
260      * <p>
261      * The permission to provide a bundle implies the permission to require the
262      * named symbolic name.
263      *
264      * <pre>
265      * x.y.*,&quot;provide&quot; -&gt; x.y.z,&quot;provide&quot; is true
266      * *,&quot;require&quot; -&gt; x.y, &quot;require&quot; is true
267      * *,&quot;provide&quot; -&gt; x.y, &quot;require&quot; is true
268      * x.y,&quot;provide&quot; -&gt; x.y.z, &quot;provide&quot; is false
269      * </pre>
270      *
271      * @param p The target permission to interrogate.
272      * @return <code>true</code> if the specified
273      * <code>BundlePermission</code> action is implied by this object;
274      * <code>false</code> otherwise.
275      */

276
277     public boolean implies(Permission p) {
278         if (p instanceof BundlePermission) {
279             BundlePermission target = (BundlePermission) p;
280
281             return (((action_mask & target.action_mask) == target.action_mask) && super
282                     .implies(p));
283         }
284
285         return (false);
286     }
287
288     /**
289      * Returns the canonical string representation of the
290      * <code>BundlePermission</code> actions.
291      *
292      * <p>
293      * Always returns present <code>BundlePermission</code> actions in the
294      * following order: <code>PROVIDE</code>,<code>REQUIRE</code>,
295      * <code>HOST</code>,<code>FRAGMENT.
296      * @return Canonical string representation of the <code>BundlePermission</code> actions.
297      */

298
299     public String JavaDoc getActions() {
300         if (actions == null) {
301             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
302             boolean comma = false;
303
304             if ((action_mask & ACTION_PROVIDE) == ACTION_PROVIDE) {
305                 sb.append(PROVIDE);
306                 comma = true;
307             }
308
309             if ((action_mask & ACTION_REQUIRE) == ACTION_REQUIRE) {
310                 if (comma)
311                     sb.append(',');
312                 sb.append(REQUIRE);
313                 comma = true;
314             }
315
316             if ((action_mask & ACTION_HOST) == ACTION_HOST) {
317                 if (comma)
318                     sb.append(',');
319                 sb.append(HOST);
320                 comma = true;
321             }
322
323             if ((action_mask & ACTION_FRAGMENT) == ACTION_FRAGMENT) {
324                 if (comma)
325                     sb.append(',');
326                 sb.append(FRAGMENT);
327             }
328
329             actions = sb.toString();
330         }
331
332         return (actions);
333     }
334
335     /**
336      * Returns a new <code>PermissionCollection</code> object suitable for
337      * storing <code>BundlePermission</code> objects.
338      *
339      * @return A new <code>PermissionCollection</code> object.
340      */

341     public PermissionCollection newPermissionCollection() {
342         return (new BundlePermissionCollection());
343     }
344
345     /**
346      * Determines the equality of two <code>BundlePermission</code> objects.
347      *
348      * This method checks that specified bundle has the same bundle symbolic
349      * name and <code>BundlePermission</code> actions as this
350      * <code>BundlePermission</code> object.
351      *
352      * @param obj The object to test for equality with this
353      * <code>BundlePermission</code> object.
354      * @return <code>true</code> if <code>obj</code> is a
355      * <code>BundlePermission</code>, and has the same bundle
356      * symbolic name and actions as this <code>BundlePermission</code>
357      * object; <code>false</code> otherwise.
358      */

359     public boolean equals(Object JavaDoc obj) {
360         if (obj == this) {
361             return (true);
362         }
363
364         if (!(obj instanceof BundlePermission)) {
365             return (false);
366         }
367
368         BundlePermission p = (BundlePermission) obj;
369
370         return ((action_mask == p.action_mask) && getName().equals(p.getName()));
371     }
372
373     /**
374      * Returns the hash code value for this object.
375      *
376      * @return A hash code value for this object.
377      */

378
379     public int hashCode() {
380         return (getName().hashCode() ^ getActions().hashCode());
381     }
382
383     /**
384      * Returns the current action mask.
385      * <p>
386      * Used by the BundlePermissionCollection class.
387      *
388      * @return Current action mask.
389      */

390     int getMask() {
391         return (action_mask);
392     }
393
394     /**
395      * WriteObject is called to save the state of the
396      * <code>BundlePermission</code> object to a stream. The actions are
397      * serialized, and the superclass takes care of the name.
398      */

399
400     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc s)
401             throws IOException JavaDoc {
402         // Write out the actions. The superclass takes care of the name
403
// call getActions to make sure actions field is initialized
404
if (actions == null)
405             getActions();
406         s.defaultWriteObject();
407     }
408
409     /**
410      * readObject is called to restore the state of the BundlePermission from a
411      * stream.
412      */

413     private synchronized void readObject(java.io.ObjectInputStream JavaDoc s)
414             throws IOException JavaDoc, ClassNotFoundException JavaDoc {
415         // Read in the action, then initialize the rest
416
s.defaultReadObject();
417         init(getMask(actions));
418     }
419 }
420
421 /**
422  * Stores a set of <code>BundlePermission</code> permissions.
423  *
424  * @see java.security.Permission
425  * @see java.security.Permissions
426  * @see java.security.PermissionCollection
427  */

428
429 final class BundlePermissionCollection extends PermissionCollection {
430
431     /**
432      * Comment for <code>serialVersionUID</code>
433      */

434     private static final long serialVersionUID = 3258407326846433079L;
435
436     /**
437      * Table of permissions.
438      *
439      * @serial
440      */

441     private Hashtable JavaDoc permissions;
442
443     /**
444      * Boolean saying if "*" is in the collection.
445      *
446      * @serial
447      */

448     private boolean all_allowed;
449
450     /**
451      * Create an empty BundlePermissions object.
452      *
453      */

454
455     public BundlePermissionCollection() {
456         permissions = new Hashtable JavaDoc();
457         all_allowed = false;
458     }
459
460     /**
461      * Adds a permission to the <code>BundlePermission</code> objects. The key
462      * for the hash is the symbolic name.
463      *
464      * @param permission The <code>BundlePermission</code> object to add.
465      *
466      * @throws IllegalArgumentException If the permission is not a
467      * <code>BundlePermission</code> instance.
468      * @throws SecurityException If this <code>BundlePermissionCollection</code>
469      * object has been marked read-only.
470      */

471
472     public void add(Permission permission) {
473         if (!(permission instanceof BundlePermission))
474             throw new IllegalArgumentException JavaDoc("invalid permission: "
475                     + permission);
476         if (isReadOnly())
477             throw new SecurityException JavaDoc("attempt to add a Permission to a "
478                     + "readonly PermissionCollection");
479
480         BundlePermission bp = (BundlePermission) permission;
481         String JavaDoc name = bp.getName();
482
483         BundlePermission existing = (BundlePermission) permissions.get(name);
484
485         if (existing != null) {
486             int oldMask = existing.getMask();
487             int newMask = bp.getMask();
488             if (oldMask != newMask) {
489                 permissions.put(name, new BundlePermission(name, oldMask
490                         | newMask));
491
492             }
493         }
494         else {
495             permissions.put(name, permission);
496         }
497
498         if (!all_allowed) {
499             if (name.equals("*"))
500                 all_allowed = true;
501         }
502     }
503
504     /**
505      * Determines if the specified permissions implies the permissions expressed
506      * in <code>permission</code>.
507      *
508      * @param permission The Permission object to compare with this
509      * <code>BundlePermission</code> object.
510      *
511      * @return <code>true</code> if <code>permission</code> is a proper
512      * subset of a permission in the set; <code>false</code>
513      * otherwise.
514      */

515
516     public boolean implies(Permission permission) {
517         if (!(permission instanceof BundlePermission))
518             return (false);
519
520         BundlePermission bp = (BundlePermission) permission;
521         BundlePermission x;
522
523         int desired = bp.getMask();
524         int effective = 0;
525
526         // short circuit if the "*" Permission was added
527
if (all_allowed) {
528             x = (BundlePermission) permissions.get("*");
529             if (x != null) {
530                 effective |= x.getMask();
531                 if ((effective & desired) == desired)
532                     return (true);
533             }
534         }
535
536         // strategy:
537
// Check for full match first. Then work our way up the
538
// name looking for matches on a.b.*
539

540         String JavaDoc name = bp.getName();
541
542         x = (BundlePermission) permissions.get(name);
543
544         if (x != null) {
545             // we have a direct hit!
546
effective |= x.getMask();
547             if ((effective & desired) == desired)
548                 return (true);
549         }
550
551         // work our way up the tree...
552
int last, offset;
553
554         offset = name.length() - 1;
555
556         while ((last = name.lastIndexOf(".", offset)) != -1) {
557
558             name = name.substring(0, last + 1) + "*";
559             x = (BundlePermission) permissions.get(name);
560
561             if (x != null) {
562                 effective |= x.getMask();
563                 if ((effective & desired) == desired)
564                     return (true);
565             }
566             offset = last - 1;
567         }
568
569         // we don't have to check for "*" as it was already checked
570
// at the top (all_allowed), so we just return false
571
return (false);
572     }
573
574     /**
575      * Returns an enumeration of all <code>BundlePermission</code> objects in
576      * the container.
577      *
578      * @return Enumeration of all <code>BundlePermission</code> objects.
579      */

580
581     public Enumeration JavaDoc elements() {
582         return (permissions.elements());
583     }
584 }
585
Popular Tags