KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > osgi > framework > internal > core > ConditionalPermissionSet


1 /*******************************************************************************
2  * Copyright (c) 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.osgi.framework.internal.core;
13
14 import java.security.*;
15 import java.util.*;
16 import org.osgi.service.condpermadmin.Condition;
17 import org.osgi.service.permissionadmin.PermissionInfo;
18
19 /**
20  * This class represents a PermissionCollection tied to a set of Conditions.
21  * Before the permissions are actually used, isNonEmpty should be called.
22  */

23 public class ConditionalPermissionSet extends BundlePermissionCollection {
24     private static final long serialVersionUID = 3258411750729920566L;
25     private ConditionalPermissionInfoImpl cpis[] = ConditionalPermissionAdminImpl.EMPTY_COND_PERM_INFO;
26     private HashMap cachedPermissionCollections = new HashMap();
27     private boolean hasAllPermission = false;
28     private AbstractBundle bundle;
29     /**
30      * These are conditions that need to be satisfied in order to enable the
31      * permissions. If the array is empty, no conditions need to be satisfied.
32      * If <code>neededCondititions</code> is null,
33      */

34     private Condition neededConditions[];
35
36     /*
37      * TODO: we need to validate the cpis[] to make sure they don't go away.
38      * Reset everything if they do. We also need to be able to add CPIs
39      */

40     /**
41      * Construct a new ConditionalPermission set with an initial set of
42      * permissions.
43      */

44     public ConditionalPermissionSet(AbstractBundle bundle, ConditionalPermissionInfoImpl cpis[], Condition neededConditions[]) {
45         this.bundle = bundle;
46         this.cpis = cpis;
47         this.neededConditions = neededConditions;
48         checkForAllPermission();
49     }
50
51     /**
52      * Adds another ConditionalPermissionInfoImpl to this set. <b>Only a
53      * CondtitionalPermissionInfo whose Conditions are immutable and satisfied
54      * may be added. </b>
55      *
56      * @param cpi the ConditionalPermissionInfoImpl to be added to this set.
57      * <b>Only a CondtitionalPermissionInfo whose Conditions are
58      * immutable and satisfied may be added. </b>
59      */

60     void addConditionalPermissionInfo(ConditionalPermissionInfoImpl cpi) {
61         if (neededConditions == null || neededConditions.length > 0)
62             throw new RuntimeException JavaDoc("Cannot add ConditionalPermissionInfoImpl to a non satisfied set"); //$NON-NLS-1$
63
synchronized (cachedPermissionCollections) {
64             // first look for a null slot
65
for (int i = 0; i < cpis.length; i++)
66                 if (cpis[i] == null) { // found an empty slot; use it
67
cpis[i] = cpi;
68                     cachedPermissionCollections.clear();
69                     return;
70                 }
71             ConditionalPermissionInfoImpl newcpis[] = new ConditionalPermissionInfoImpl[cpis.length + 1];
72             System.arraycopy(cpis, 0, newcpis, 0, cpis.length);
73             newcpis[cpis.length] = cpi;
74             cpis = newcpis;
75             /*
76              * TODO: I couldn't decide wether it is better to run through the cached
77              * PermissionCollections and add permissions from this cpi, or to just
78              * clear out and let them get rebuilt ondemand. The ondemand route is
79              * simpler and in the end may be more efficient.
80              */

81             cachedPermissionCollections.clear();
82             checkForAllPermission();
83         }
84     }
85
86     /**
87      * This runs through the PermissionInfos to see if there is an AllPermission in the mix.
88      */

89     private void checkForAllPermission() {
90         if (hasAllPermission) {
91             return;
92         }
93         out: for (int i = 0; i < cpis.length; i++) {
94             if (cpis[i] == null) // check for deletions
95
continue;
96             PermissionInfo perms[] = cpis[i].perms;
97             for (int j = 0; j < perms.length; j++) {
98                 if (perms[j].getType().equals(AllPermission.class.getName())) {
99                     hasAllPermission = true;
100                     break out;
101                 }
102             }
103         }
104     }
105
106     /**
107      * Returns true if at least one of the ConditionalPermissionInfos in this
108      * set is still active. (Not deleted.)
109      *
110      * @return true if there is at least one active ConditionalPermissionInfo.
111      */

112     boolean isNonEmpty() {
113         boolean nonEmpty = false;
114         boolean forceAllPermCheck = false;
115         synchronized (cachedPermissionCollections) {
116             for (int i = 0; i < cpis.length; i++) {
117                 if (cpis[i] != null) {
118                     if (cpis[i].isDeleted()) {
119                         cpis[i] = null;
120                         forceAllPermCheck = true;
121                         /*
122                          * We don't have a way to remove from a collection; we can
123                          * only add. Thus, we must clear out everything. TODO:
124                          * Investigate if it would be more efficient to only clear
125                          * the permission collections of the type stored by the cpi.
126                          */

127                         cachedPermissionCollections.clear();
128                     } else {
129                         nonEmpty = true;
130                     }
131                 }
132             }
133             if (!nonEmpty)
134                 cpis = ConditionalPermissionAdminImpl.EMPTY_COND_PERM_INFO;
135             if (forceAllPermCheck) {
136                 hasAllPermission = false;
137                 checkForAllPermission();
138             }
139         }
140         return nonEmpty;
141     }
142
143     /**
144      * Returns the conditions that need to be satisfied before the permissions
145      * embodied in this set can be used.
146      *
147      * @return the array of conditions that need to be satisfied. If the array
148      * is empty, no conditions need to be satisfied to use the
149      * permissions. If null is returned, these permissions can never be
150      * used.
151      */

152     Condition[] getNeededConditions() {
153         if (neededConditions == null || neededConditions.length == 0)
154             return neededConditions;
155         boolean foundNonNullCondition = false;
156         /* We need to check to see if any conditions became immutable */
157         for (int i = 0; i < neededConditions.length; i++) {
158             Condition cond = neededConditions[i];
159             if (cond == null)
160                 continue;
161             if (!cond.isMutable()) {
162                 if (cond.isSatisfied()) {
163                     neededConditions[i] = null;
164                 } else {
165                     /*
166                      * We now have an immutable unsatisfied condition, this set
167                      * is no longer valid.
168                      */

169                     neededConditions = null;
170                     break;
171                 }
172             } else {
173                 foundNonNullCondition = true;
174             }
175         }
176         if (neededConditions != null && !foundNonNullCondition)
177             neededConditions = ConditionalPermissionAdminImpl.EMPTY_COND;
178         return neededConditions;
179     }
180
181     /**
182      * We don't do anything here since this isn't a real PermissionCollection.
183      *
184      * @param perm ignored.
185      * @see java.security.PermissionCollection#add(java.security.Permission)
186      */

187     public void add(Permission perm) {
188         // do nothing
189
}
190
191     /**
192      * Checks to see if the desired Permission is implied by this collection of
193      * ConditionalPermissionInfos.
194      *
195      * @param perm Permission to check.
196      * @return true if this ConditionPermissionSet implies the passed
197      * Permission.
198      * @see java.security.PermissionCollection#implies(java.security.Permission)
199      */

200     public boolean implies(Permission perm) {
201         if (hasAllPermission)
202             return true;
203         Class JavaDoc permClass = perm.getClass();
204         PermissionCollection collection;
205         synchronized (cachedPermissionCollections) {
206             collection = (PermissionCollection) cachedPermissionCollections.get(permClass);
207             if (collection == null) {
208                 collection = perm.newPermissionCollection();
209                 if (collection == null)
210                     collection = new PermissionsHash();
211                 for (int i = 0; i < cpis.length; i++) {
212                     try {
213                         ConditionalPermissionInfoImpl cpi = cpis[i];
214                         if (cpi != null)
215                             cpi.addPermissions(bundle, collection, permClass);
216                     } catch (Exception JavaDoc e) {
217                         // TODO: we should log this somewhere
218
e.printStackTrace();
219                     }
220                 }
221                 cachedPermissionCollections.put(permClass, collection);
222             }
223         }
224         return collection.implies(perm);
225     }
226
227     /**
228      * We don't do anything here since this isn't a real PermissionCollection.
229      *
230      * @return always returns null.
231      * @see java.security.PermissionCollection#elements()
232      */

233     public Enumeration elements() {
234         return null;
235     }
236
237     /**
238      * This method simply clears the resolved permission table. I think in both the
239      * short-term and the amoritized case, this is more efficient than walking through
240      * and clearing specific entries.
241      */

242     void unresolvePermissions() {
243         synchronized (cachedPermissionCollections) {
244             cachedPermissionCollections.clear();
245         }
246     }
247
248     boolean remove(ConditionalPermissionInfoImpl cpi) {
249         synchronized (cachedPermissionCollections) {
250             for (int i = 0; i < cpis.length; i++)
251                 if (cpis[i] == cpi) {
252                     cpis[i] = null;
253                     cachedPermissionCollections.clear();
254                     return true;
255                 }
256         }
257         return false;
258     }
259 }
260
Popular Tags