KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * $Header: /cvshome/build/org.osgi.framework/src/org/osgi/framework/ServicePermission.java,v 1.15 2007/02/20 00:06:02 hargrave 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.Enumeration JavaDoc;
24 import java.util.Hashtable JavaDoc;
25
26 /**
27  * A bundle's authority to register or get a service.
28  * <ul>
29  * <li>The <code>ServicePermission.REGISTER</code> action allows a bundle to
30  * register a service on the specified names.
31  * <li>The <code>ServicePermission.GET</code> action allows a bundle to
32  * detect a service and get it.
33  * </ul>
34  * Permission to get a service is required in order to detect events regarding
35  * the service. Untrusted bundles should not be able to detect the presence of
36  * certain services unless they have the appropriate
37  * <code>ServicePermission</code> to get the specific service.
38  *
39  * @version $Revision: 1.15 $
40  */

41
42 final public class ServicePermission extends BasicPermission {
43     static final long serialVersionUID = -7662148639076511574L;
44     /**
45      * The action string <code>get</code> (Value is "get").
46      */

47     public final static String JavaDoc GET = "get";
48     /**
49      * The action string <code>register</code> (Value is "register").
50      */

51     public final static String JavaDoc REGISTER = "register";
52
53     private final static int ACTION_GET = 0x00000001;
54     private final static int ACTION_REGISTER = 0x00000002;
55     private final static int ACTION_ALL = ACTION_GET
56                                                             | ACTION_REGISTER;
57     private final static int ACTION_NONE = 0;
58     /**
59      * The actions mask.
60      */

61     private transient int action_mask = ACTION_NONE;
62
63     /**
64      * The actions in canonical form.
65      *
66      * @serial
67      */

68     private String JavaDoc actions = null;
69
70     /**
71      * Create a new ServicePermission.
72      *
73      * <p>
74      * The name of the service is specified as a fully qualified class name.
75      *
76      * <pre>
77      * ClassName ::= &lt;class name&gt; | &lt;class name ending in &quot;.*&quot;&gt;
78      * </pre>
79      *
80      * Examples:
81      *
82      * <pre>
83      * org.osgi.service.http.HttpService
84      * org.osgi.service.http.*
85      * org.osgi.service.snmp.*
86      * </pre>
87      *
88      * <p>
89      * There are two possible actions: <code>get</code> and
90      * <code>register</code>. The <code>get</code> permission allows the
91      * owner of this permission to obtain a service with this name. The
92      * <code>register</code> permission allows the bundle to register a
93      * service under that name.
94      *
95      * @param name class name
96      * @param actions <code>get</code>,<code>register</code> (canonical
97      * order)
98      */

99
100     public ServicePermission(String JavaDoc name, String JavaDoc actions) {
101         this(name, getMask(actions));
102     }
103
104     /**
105      * Package private constructor used by ServicePermissionCollection.
106      *
107      * @param name class name
108      * @param mask action mask
109      */

110     ServicePermission(String JavaDoc name, int mask) {
111         super(name);
112
113         init(mask);
114     }
115
116     /**
117      * Called by constructors and when deserialized.
118      *
119      * @param mask action mask
120      */

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

135     private static int getMask(String JavaDoc actions) {
136         boolean seencomma = false;
137
138         int mask = ACTION_NONE;
139
140         if (actions == null) {
141             return mask;
142         }
143
144         char[] a = actions.toCharArray();
145
146         int i = a.length - 1;
147         if (i < 0)
148             return mask;
149
150         while (i != -1) {
151             char c;
152
153             // skip whitespace
154
while ((i != -1)
155                     && ((c = a[i]) == ' ' || c == '\r' || c == '\n'
156                             || c == '\f' || c == '\t'))
157                 i--;
158
159             // check for the known strings
160
int matchlen;
161
162             if (i >= 2 && (a[i - 2] == 'g' || a[i - 2] == 'G')
163                     && (a[i - 1] == 'e' || a[i - 1] == 'E')
164                     && (a[i] == 't' || a[i] == 'T')) {
165                 matchlen = 3;
166                 mask |= ACTION_GET;
167
168             }
169             else
170                 if (i >= 7 && (a[i - 7] == 'r' || a[i - 7] == 'R')
171                         && (a[i - 6] == 'e' || a[i - 6] == 'E')
172                         && (a[i - 5] == 'g' || a[i - 5] == 'G')
173                         && (a[i - 4] == 'i' || a[i - 4] == 'I')
174                         && (a[i - 3] == 's' || a[i - 3] == 'S')
175                         && (a[i - 2] == 't' || a[i - 2] == 'T')
176                         && (a[i - 1] == 'e' || a[i - 1] == 'E')
177                         && (a[i] == 'r' || a[i] == 'R')) {
178                     matchlen = 8;
179                     mask |= ACTION_REGISTER;
180
181                 }
182                 else {
183                     // parse error
184
throw new IllegalArgumentException JavaDoc("invalid permission: "
185                             + actions);
186                 }
187
188             // make sure we didn't just match the tail of a word
189
// like "ackbarfregister". Also, skip to the comma.
190
seencomma = false;
191             while (i >= matchlen && !seencomma) {
192                 switch (a[i - matchlen]) {
193                     case ',' :
194                         seencomma = true;
195                     /* FALLTHROUGH */
196                     case ' ' :
197                     case '\r' :
198                     case '\n' :
199                     case '\f' :
200                     case '\t' :
201                         break;
202                     default :
203                         throw new IllegalArgumentException JavaDoc(
204                                 "invalid permission: " + actions);
205                 }
206                 i--;
207             }
208
209             // point i at the location of the comma minus one (or -1).
210
i -= matchlen;
211         }
212
213         if (seencomma) {
214             throw new IllegalArgumentException JavaDoc("invalid permission: " + actions);
215         }
216
217         return mask;
218     }
219
220     /**
221      * Determines if a <code>ServicePermission</code> object "implies" the
222      * specified permission.
223      *
224      * @param p The target permission to check.
225      * @return <code>true</code> if the specified permission is implied by
226      * this object; <code>false</code> otherwise.
227      */

228
229     public boolean implies(Permission p) {
230         if (p instanceof ServicePermission) {
231             ServicePermission target = (ServicePermission) p;
232
233             return (((action_mask & target.action_mask) == target.action_mask) && super
234                     .implies(p));
235         }
236
237         return (false);
238     }
239
240     /**
241      * Returns the canonical string representation of the actions. Always
242      * returns present actions in the following order: <code>get</code>,
243      * <code>register</code>.
244      *
245      * @return The canonical string representation of the actions.
246      */

247     public String JavaDoc getActions() {
248         if (actions == null) {
249             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
250             boolean comma = false;
251
252             if ((action_mask & ACTION_GET) == ACTION_GET) {
253                 sb.append(GET);
254                 comma = true;
255             }
256
257             if ((action_mask & ACTION_REGISTER) == ACTION_REGISTER) {
258                 if (comma)
259                     sb.append(',');
260                 sb.append(REGISTER);
261             }
262
263             actions = sb.toString();
264         }
265
266         return (actions);
267     }
268
269     /**
270      * Returns a new <code>PermissionCollection</code> object for storing
271      * <code>ServicePermission<code> objects.
272      *
273      * @return A new <code>PermissionCollection</code> object suitable for storing
274      * <code>ServicePermission</code> objects.
275      */

276     public PermissionCollection newPermissionCollection() {
277         return (new ServicePermissionCollection());
278     }
279
280     /**
281      * Determines the equalty of two ServicePermission objects.
282      *
283      * Checks that specified object has the same class name and action as this
284      * <code>ServicePermission</code>.
285      *
286      * @param obj The object to test for equality.
287      * @return true if obj is a <code>ServicePermission</code>, and has the
288      * same class name and actions as this
289      * <code>ServicePermission</code> object; <code>false</code>
290      * otherwise.
291      */

292     public boolean equals(Object JavaDoc obj) {
293         if (obj == this) {
294             return (true);
295         }
296
297         if (!(obj instanceof ServicePermission)) {
298             return (false);
299         }
300
301         ServicePermission p = (ServicePermission) obj;
302
303         return ((action_mask == p.action_mask) && getName().equals(p.getName()));
304     }
305
306     /**
307      * Returns the hash code value for this object.
308      *
309      * @return Hash code value for this object.
310      */

311
312     public int hashCode() {
313         return (getName().hashCode() ^ getActions().hashCode());
314     }
315
316     /**
317      * Returns the current action mask. Used by the ServicePermissionCollection
318      * object.
319      *
320      * @return The actions mask.
321      */

322     int getMask() {
323         return (action_mask);
324     }
325
326     /**
327      * WriteObject is called to save the state of this permission to a stream.
328      * The actions are serialized, and the superclass takes care of the name.
329      */

330
331     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc s)
332             throws IOException JavaDoc {
333         // Write out the actions. The superclass takes care of the name
334
// call getActions to make sure actions field is initialized
335
if (actions == null)
336             getActions();
337         s.defaultWriteObject();
338     }
339
340     /**
341      * readObject is called to restore the state of this permission from a
342      * stream.
343      */

344     private synchronized void readObject(java.io.ObjectInputStream JavaDoc s)
345             throws IOException JavaDoc, ClassNotFoundException JavaDoc {
346         // Read in the action, then initialize the rest
347
s.defaultReadObject();
348         init(getMask(actions));
349     }
350 }
351
352 /**
353  * Stores a set of ServicePermission permissions.
354  *
355  * @see java.security.Permission
356  * @see java.security.Permissions
357  * @see java.security.PermissionCollection
358  */

359
360 final class ServicePermissionCollection extends PermissionCollection {
361     static final long serialVersionUID = 662615640374640621L;
362     /**
363      * Table of permissions.
364      *
365      * @serial
366      */

367     private Hashtable JavaDoc permissions;
368
369     /**
370      * Boolean saying if "*" is in the collection.
371      *
372      * @serial
373      */

374     private boolean all_allowed;
375
376     /**
377      * Creates an empty ServicePermissions object.
378      */

379
380     public ServicePermissionCollection() {
381         permissions = new Hashtable JavaDoc();
382         all_allowed = false;
383     }
384
385     /**
386      * Adds a permission to the <code>ServicePermission</code> objects using
387      * the key for the hash as the name.
388      *
389      * @param permission The Permission object to add.
390      *
391      * @throws IllegalArgumentException If the permission is not a
392      * ServicePermission object.
393      * @throws SecurityException If this
394      * <code>ServicePermissionCollection</code> object has been marked
395      * read-only.
396      */

397
398     public void add(Permission permission) {
399         if (!(permission instanceof ServicePermission))
400             throw new IllegalArgumentException JavaDoc("invalid permission: "
401                     + permission);
402         if (isReadOnly())
403             throw new SecurityException JavaDoc("attempt to add a Permission to a "
404                     + "readonly PermissionCollection");
405
406         ServicePermission sp = (ServicePermission) permission;
407         String JavaDoc name = sp.getName();
408
409         ServicePermission existing = (ServicePermission) permissions.get(name);
410
411         if (existing != null) {
412             int oldMask = existing.getMask();
413             int newMask = sp.getMask();
414             if (oldMask != newMask) {
415                 permissions.put(name, new ServicePermission(name, oldMask
416                         | newMask));
417             }
418         }
419         else {
420             permissions.put(name, permission);
421         }
422
423         if (!all_allowed) {
424             if (name.equals("*"))
425                 all_allowed = true;
426         }
427     }
428
429     /**
430      * Determines if a set of permissions implies the permissions expressed in
431      * <code>permission</code>.
432      *
433      * @param permission The Permission object to compare.
434      *
435      * @return <code>true</code> if <code>permission</code> is a proper
436      * subset of a permission in the set; <code>false</code>
437      * otherwise.
438      */

439
440     public boolean implies(Permission permission) {
441         if (!(permission instanceof ServicePermission))
442             return (false);
443
444         ServicePermission sp = (ServicePermission) permission;
445         ServicePermission x;
446
447         int desired = sp.getMask();
448         int effective = 0;
449
450         // short circuit if the "*" Permission was added
451
if (all_allowed) {
452             x = (ServicePermission) permissions.get("*");
453             if (x != null) {
454                 effective |= x.getMask();
455                 if ((effective & desired) == desired)
456                     return (true);
457             }
458         }
459
460         // strategy:
461
// Check for full match first. Then work our way up the
462
// name looking for matches on a.b.*
463

464         String JavaDoc name = sp.getName();
465
466         x = (ServicePermission) permissions.get(name);
467
468         if (x != null) {
469             // we have a direct hit!
470
effective |= x.getMask();
471             if ((effective & desired) == desired)
472                 return (true);
473         }
474
475         // work our way up the tree...
476
int last, offset;
477
478         offset = name.length() - 1;
479
480         while ((last = name.lastIndexOf(".", offset)) != -1) {
481
482             name = name.substring(0, last + 1) + "*";
483             x = (ServicePermission) permissions.get(name);
484
485             if (x != null) {
486                 effective |= x.getMask();
487                 if ((effective & desired) == desired)
488                     return (true);
489             }
490             offset = last - 1;
491         }
492
493         // we don't have to check for "*" as it was already checked
494
// at the top (all_allowed), so we just return false
495
return (false);
496     }
497
498     /**
499      * Returns an enumeration of all the <code>ServicePermission</code>
500      * objects in the container.
501      *
502      * @return Enumeration of all the ServicePermission objects.
503      */

504
505     public Enumeration JavaDoc elements() {
506         return (permissions.elements());
507     }
508 }
509
Popular Tags