KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > security > PermissionCache


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.security;
24
25 import java.security.AccessController JavaDoc;
26 import java.security.CodeSource JavaDoc;
27 import java.security.AllPermission JavaDoc;
28 import java.security.Permission JavaDoc;
29 import java.security.PermissionCollection JavaDoc;
30 import java.security.Permissions JavaDoc;
31 import java.security.Policy JavaDoc;
32 import java.security.PrivilegedExceptionAction JavaDoc;
33 import java.security.PrivilegedActionException JavaDoc;
34 import java.util.Enumeration JavaDoc;
35 import java.util.logging.Level JavaDoc;
36 import java.util.logging.Logger JavaDoc;
37 import java.util.concurrent.locks.Lock JavaDoc;
38 import java.util.concurrent.locks.ReadWriteLock JavaDoc;
39 import java.util.concurrent.locks.ReentrantReadWriteLock JavaDoc;
40
41 import javax.security.jacc.PolicyContext JavaDoc;
42 import com.sun.enterprise.security.CachedPermissionImpl.Epoch;
43
44 import com.sun.logging.LogDomains;
45
46 /**
47  * This class is
48  * @author Ron Monzillo
49  */

50
51 public class PermissionCache extends Object JavaDoc {
52
53     private static Logger JavaDoc _logger =
54     LogDomains.getLogger(LogDomains.SECURITY_LOGGER);
55     private static Policy JavaDoc policy = Policy.getPolicy();
56     private static AllPermission JavaDoc allPermission = new AllPermission JavaDoc();
57
58     private Permissions JavaDoc cache;
59     private CodeSource JavaDoc codesource;
60     private Permission JavaDoc[] protoPerms;
61     private Class JavaDoc[] classes;
62     private String JavaDoc name;
63     private String JavaDoc pcID;
64     private final Integer JavaDoc factoryKey;
65     private volatile int epoch;
66     private volatile boolean loading;
67     private ReadWriteLock JavaDoc rwLock;
68     private Lock JavaDoc rLock;
69     private Lock JavaDoc wLock;
70  
71     // USE OF THIS CONSTRUCTOR WITH IS DISCOURAGED PLEASE USE THE Permission
72
// (object) based CONSTRUCTOR.
73
// @param key - Integer that uniquely identifies the cache at the factory
74
// @param pcID - a string identifying the policy context and which must
75
// be set when getPermissions is called (internally). this value may be
76
// null, in which case the permisions of the default policy context will
77
// be cached.
78
// @param codesource - the codesource argument to be used in the call to
79
// getPermissions. this value may be null.
80
// @param class - a single Class object that identifies the permission
81
// type that will be managed by the cache. This value may be
82
// null. When this argument is not null, only permissions of the
83
// identified type or that resolve to the identified type,
84
// will be managed within the cache. When null is passed to this argument,
85
// permission type will not be a factor in determining the cached
86
// permissions.
87
// @param name - a string corresponding to a value returned by
88
// Permission.getName(). Only permissions whose getName() value
89
// matches the name parameter will be included in the cache. This value
90
// may be null, in which case permission name does not factor into
91
// the permission caching.
92

93     public PermissionCache(Integer JavaDoc key, String JavaDoc pcID, CodeSource JavaDoc codesource,
94                Class JavaDoc clazz, String JavaDoc name){
95     if (codesource == null) {
96         this.codesource =
97         new CodeSource JavaDoc(null,
98                    (java.security.cert.Certificate JavaDoc[])null);
99     } else {
100         this.codesource = codesource;
101     }
102     this.factoryKey = key;
103     this.cache = null;
104     this.pcID = pcID;
105     this.protoPerms = null;
106     if (clazz != null) {
107         this.classes = new Class JavaDoc[] {clazz};
108     } else {
109         this.classes = null;
110     }
111     this.name = name;
112     this.epoch = 1;
113     this.loading = false;
114     this.rwLock = new ReentrantReadWriteLock JavaDoc(true);
115     this.rLock = rwLock.readLock();
116     this.wLock = rwLock.writeLock();
117     }
118   
119     // @param key - Integer that uniquely identifies the cache at the factory
120
// @param pcID - a string identifying the policy context and which must
121
// be set when getPermissions is called (internally). this value may be
122
// null, in which case the permisions of the default policy context will
123
// be cached.
124
// @param codesource - the codesource argument to be used in the call to
125
// getPermissions. this value may be null.
126
// @param perms - an array of permission objects identifying the
127
// permission types that will be managed by the cache. This value may be
128
// null. When this argument is not null, only permissions of the types
129
// passed in the array or that resolve to the types identified in the
130
// will be managed within the cache. When null is passed to this argument,
131
// permission type will not be a factor in determining the cached
132
// permissions.
133
// @param name - a string corresponding to a value returned by
134
// Permission.getName(). Only permissions whose getName() value
135
// matches the name parameter will be included in the cache. This value
136
// may be null, in which case permission name does not factor into
137
// the permission caching.
138

139     public PermissionCache(Integer JavaDoc key, String JavaDoc pcID, CodeSource JavaDoc codesource,
140                Permission JavaDoc[] perms, String JavaDoc name){
141     if (codesource == null) {
142         this.codesource =
143         new CodeSource JavaDoc(null,
144                    (java.security.cert.Certificate JavaDoc[])null);
145     } else {
146         this.codesource = codesource;
147     }
148     this.factoryKey = key;
149     this.cache = null;
150     this.pcID = pcID;
151     this.protoPerms = perms;
152     if (perms != null && perms.length>0) {
153         this.classes = new Class JavaDoc[perms.length];
154         for (int i=0; i<perms.length; i++) {
155         this.classes[i] = perms[i].getClass();
156         }
157     } else {
158         this.classes = null;
159     }
160     this.name = name;
161     this.epoch = 1;
162     this.loading = false;
163     this.rwLock = new ReentrantReadWriteLock JavaDoc(true);
164     this.rLock = rwLock.readLock();
165     this.wLock = rwLock.writeLock();
166     }
167  
168     public Integer JavaDoc getFactoryKey() {
169     return this.factoryKey;
170     }
171
172     private boolean loadCache(Permission JavaDoc p) {
173
174     // test-and-set to guard critical section
175
rLock.lock();
176     if (loading) {
177         rLock.unlock();
178         return false;
179     } else if (cache != null) {
180         // cache is available and must stay locked for use by caller.
181
// readlock must be released by caller
182
return true;
183     } else {
184         rLock.unlock();
185         wLock.lock();
186         if (loading) {
187         // another thread started the load, so we give up the
188
// writelock and return.
189
wLock.unlock();
190         return false;
191         } else {
192         // set the load indicators and release the writelock so that
193
// readers may bypass the cache until it is loaded
194
cache = null;
195         loading = true;
196         wLock.unlock();
197         }
198     }
199     
200     // cache will be null if we proceed past this point
201
// NO LOCKS ARE HELD AT THIS POINT
202
Permissions JavaDoc nextCache = new Permissions JavaDoc();
203
204     boolean setPc = false;
205     String JavaDoc oldpcID = null;
206     try {
207         oldpcID = PolicyContext.getContextID();
208         if (this.pcID != oldpcID &&
209         (this.pcID == null || !this.pcID.equals(oldpcID))) {
210         setPc = true;
211         }
212     } catch (Exception JavaDoc ex) {
213         _logger.log(Level.SEVERE,"JACC: Unexpected security exception on access decision"
214             , ex);
215         return false;
216     }
217
218     PermissionCollection JavaDoc pc = null;
219     try {
220         if (setPc) {
221         setPolicyContextID(this.pcID);
222         }
223         
224         pc = this.policy.getPermissions(this.codesource);
225     } catch(Exception JavaDoc ex) {
226         _logger.log(Level.SEVERE,"JACC: Unexpected security exception on access decision"
227             , ex);
228         return false;
229     } finally {
230         if (setPc) {
231         try {
232             setPolicyContextID(oldpcID);
233         } catch(Exception JavaDoc ex) {
234             _logger.log(Level.SEVERE,"JACC: Unexpected security exception on access decision", ex);
235             return false;
236         }
237         }
238     }
239
240     // force resolution of unresolved permissions
241
// so that we can filter out all but the permissions
242
// that are supposed to be in the cache.
243

244     resolvePermissions(pc,p);
245
246     Enumeration JavaDoc granted = pc.elements();
247     while (granted.hasMoreElements()) {
248         Permission JavaDoc i = (Permission JavaDoc) granted.nextElement();
249         if (i.equals(allPermission)) {
250         nextCache.add(i);
251         } else {
252         boolean classMatch = true;
253         if (this.classes != null) {
254             classMatch = false;
255             Class JavaDoc iClazz = i.getClass();
256             for (int j=0; j<this.classes.length; j++) {
257             if (this.classes[j].equals(iClazz)) {
258                 classMatch = true;
259                 break;
260             }
261             }
262         }
263         if (classMatch) {
264             if (this.name != null) {
265             String JavaDoc name = i.getName();
266             if (name != null && this.name.equals(name)) {
267                 nextCache.add(i);
268             }
269             } else {
270             nextCache.add(i);
271             }
272         }
273         }
274     }
275
276     wLock.lock();
277     cache = nextCache;
278     loading = false;
279     // cache is available and must be (read)locked for use by caller.
280
// get readlock inside writelock. readlock must be released by caller
281
rLock.lock();
282     wLock.unlock();
283     return true;
284     }
285     
286     public boolean checkPermission(Permission JavaDoc p, Epoch epoch) {
287     boolean rvalue = false;
288     if (loadCache(p)) {
289         try {
290         if (epoch.epoch != this.epoch) {
291             epoch.granted = this.cache.implies(p);
292             epoch.epoch = this.epoch;
293         }
294         } finally {
295         rLock.unlock();
296         }
297         rvalue = epoch.granted;
298     }
299     return rvalue;
300      }
301   
302     public boolean checkPermission(Permission JavaDoc p) {
303     boolean rvalue = false;
304     if (loadCache(p)) {
305         try {
306         rvalue = this.cache.implies(p);
307         } finally {
308         rLock.unlock();
309         }
310     }
311     return rvalue;
312     }
313    
314     public synchronized void reset() {
315     wLock.lock();
316     try {
317         if (cache != null) {
318         // since cache is non-null, we know we are NOT loading
319
// setting cache to null will force a (re)load
320
cache = null;
321         epoch = (epoch + 1 == 0) ? 1 : epoch + 1;
322         }
323     } finally {
324         wLock.unlock();
325     }
326     }
327
328     private void setPolicyContextID(final String JavaDoc newID)
329             throws PrivilegedActionException JavaDoc {
330         AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc(){
331             public java.lang.Object JavaDoc run() throws Exception JavaDoc{
332                 PolicyContext.setContextID(newID);
333                 return null;
334             }
335         });
336     }
337
338     // use implies to resolve unresolved permissions
339
private void resolvePermissions(PermissionCollection JavaDoc pc, Permission JavaDoc p) {
340     // each call to implies will resolve permissions of the
341
// argument permission type
342
if (this.protoPerms != null && this.protoPerms.length > 0) {
343         for (int i=0; i<this.protoPerms.length; i++) {
344         pc.implies(this.protoPerms[i]);
345         }
346     } else {
347         pc.implies(p);
348     }
349     }
350 }
351
Popular Tags