KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > UnresolvedPermission


1 /*
2  * @(#)UnresolvedPermission.java 1.29 04/02/03
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7  
8 package java.security;
9
10 import java.io.IOException JavaDoc;
11 import java.io.ByteArrayInputStream JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.Enumeration JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Vector JavaDoc;
16 import java.lang.reflect.*;
17 import java.security.cert.*;
18
19 /**
20  * The UnresolvedPermission class is used to hold Permissions that
21  * were "unresolved" when the Policy was initialized.
22  * An unresolved permission is one whose actual Permission class
23  * does not yet exist at the time the Policy is initialized (see below).
24  *
25  * <p>The policy for a Java runtime (specifying
26  * which permissions are available for code from various principals)
27  * is represented by a Policy object.
28  * Whenever a Policy is initialized or refreshed, Permission objects of
29  * appropriate classes are created for all permissions
30  * allowed by the Policy.
31  *
32  * <p>Many permission class types
33  * referenced by the policy configuration are ones that exist
34  * locally (i.e., ones that can be found on CLASSPATH).
35  * Objects for such permissions can be instantiated during
36  * Policy initialization. For example, it is always possible
37  * to instantiate a java.io.FilePermission, since the
38  * FilePermission class is found on the CLASSPATH.
39  *
40  * <p>Other permission classes may not yet exist during Policy
41  * initialization. For example, a referenced permission class may
42  * be in a JAR file that will later be loaded.
43  * For each such class, an UnresolvedPermission is instantiated.
44  * Thus, an UnresolvedPermission is essentially a "placeholder"
45  * containing information about the permission.
46  *
47  * <p>Later, when code calls AccessController.checkPermission
48  * on a permission of a type that was previously unresolved,
49  * but whose class has since been loaded, previously-unresolved
50  * permissions of that type are "resolved". That is,
51  * for each such UnresolvedPermission, a new object of
52  * the appropriate class type is instantiated, based on the
53  * information in the UnresolvedPermission.
54  *
55  * <p> To instantiate the new class, UnresolvedPermission assumes
56  * the class provides a zero, one, and/or two-argument constructor.
57  * The zero-argument constructor would be used to instantiate
58  * a permission without a name and without actions.
59  * A one-arg constructor is assumed to take a <code>String</code>
60  * name as input, and a two-arg constructor is assumed to take a
61  * <code>String</code> name and <code>String</code> actions
62  * as input. UnresolvedPermission may invoke a
63  * constructor with a <code>null</code> name and/or actions.
64  * If an appropriate permission constructor is not available,
65  * the UnresolvedPermission is ignored and the relevant permission
66  * will not be granted to executing code.
67  *
68  * <p> The newly created permission object replaces the
69  * UnresolvedPermission, which is removed.
70  *
71  * <p> Note that the <code>getName</code> method for an
72  * <code>UnresolvedPermission</code> returns the
73  * <code>type</code> (class name) for the underlying permission
74  * that has not been resolved.
75  *
76  * @see java.security.Permission
77  * @see java.security.Permissions
78  * @see java.security.PermissionCollection
79  * @see java.security.Policy
80  *
81  * @version 1.29 04/02/03
82  *
83  * @author Roland Schemers
84  */

85
86 public final class UnresolvedPermission extends Permission JavaDoc
87 implements java.io.Serializable JavaDoc
88 {
89
90     private static final long serialVersionUID = -4821973115467008846L;
91
92     private static final sun.security.util.Debug debug =
93     sun.security.util.Debug.getInstance
94     ("policy,access", "UnresolvedPermission");
95
96     /**
97      * The class name of the Permission class that will be
98      * created when this unresolved permission is resolved.
99      *
100      * @serial
101      */

102     private String JavaDoc type;
103
104     /**
105      * The permission name.
106      *
107      * @serial
108      */

109     private String JavaDoc name;
110
111     /**
112      * The actions of the permission.
113      *
114      * @serial
115      */

116     private String JavaDoc actions;
117
118     private transient java.security.cert.Certificate JavaDoc certs[];
119
120     /**
121      * Creates a new UnresolvedPermission containing the permission
122      * information needed later to actually create a Permission of the
123      * specified class, when the permission is resolved.
124      *
125      * @param type the class name of the Permission class that will be
126      * created when this unresolved permission is resolved.
127      * @param name the name of the permission.
128      * @param actions the actions of the permission.
129      * @param certs the certificates the permission's class was signed with.
130      * This is a list of certificate chains, where each chain is composed of a
131      * signer certificate and optionally its supporting certificate chain.
132      * Each chain is ordered bottom-to-top (i.e., with the signer certificate
133      * first and the (root) certificate authority last). The signer
134      * certificates are copied from the array. Subsequent changes to
135      * the array will not affect this UnsolvedPermission.
136      */

137     public UnresolvedPermission(String JavaDoc type,
138                 String JavaDoc name,
139                 String JavaDoc actions,
140                 java.security.cert.Certificate JavaDoc certs[])
141     {
142     super(type);
143
144     if (type == null)
145         throw new NullPointerException JavaDoc("type can't be null");
146
147     this.type = type;
148     this.name = name;
149     this.actions = actions;
150     if (certs != null) {
151         // Extract the signer certs from the list of certificates.
152
for (int i=0; i<certs.length; i++) {
153         if (!(certs[i] instanceof X509Certificate)) {
154             // there is no concept of signer certs, so we store the
155
// entire cert array
156
this.certs =
157             (java.security.cert.Certificate JavaDoc[])certs.clone();
158             break;
159         }
160         }
161
162         if (this.certs == null) {
163         // Go through the list of certs and see if all the certs are
164
// signer certs.
165
int i = 0;
166         int count = 0;
167         while (i < certs.length) {
168             count++;
169             while (((i+1) < certs.length) &&
170                ((X509Certificate)certs[i]).getIssuerDN().equals(
171                        ((X509Certificate)certs[i+1]).getSubjectDN())) {
172             i++;
173             }
174             i++;
175         }
176         if (count == certs.length) {
177             // All the certs are signer certs, so we store the entire
178
// array
179
this.certs =
180             (java.security.cert.Certificate JavaDoc[])certs.clone();
181         }
182
183         if (this.certs == null) {
184             // extract the signer certs
185
ArrayList JavaDoc signerCerts = new ArrayList JavaDoc();
186             i = 0;
187             while (i < certs.length) {
188             signerCerts.add(certs[i]);
189             while (((i+1) < certs.length) &&
190                 ((X509Certificate)certs[i]).getIssuerDN().equals(
191                           ((X509Certificate)certs[i+1]).getSubjectDN())) {
192                 i++;
193             }
194             i++;
195             }
196             this.certs =
197             new java.security.cert.Certificate JavaDoc[signerCerts.size()];
198             signerCerts.toArray(this.certs);
199         }
200         }
201     }
202     }
203
204
205     private static final Class JavaDoc[] PARAMS0 = { };
206     private static final Class JavaDoc[] PARAMS1 = { String JavaDoc.class };
207     private static final Class JavaDoc[] PARAMS2 = { String JavaDoc.class, String JavaDoc.class };
208
209     /**
210      * try and resolve this permission using the class loader of the permission
211      * that was passed in.
212      */

213     Permission JavaDoc resolve(Permission JavaDoc p, java.security.cert.Certificate JavaDoc certs[]) {
214     if (this.certs != null) {
215         // if p wasn't signed, we don't have a match
216
if (certs == null) {
217         return null;
218         }
219
220         // all certs in this.certs must be present in certs
221
boolean match;
222         for (int i = 0; i < this.certs.length; i++) {
223         match = false;
224         for (int j = 0; j < certs.length; j++) {
225             if (this.certs[i].equals(certs[j])) {
226             match = true;
227             break;
228             }
229         }
230         if (!match) return null;
231         }
232     }
233     try {
234         Class JavaDoc pc = p.getClass();
235         
236         if (name == null && actions == null) {
237             try {
238                 Constructor c = pc.getConstructor(PARAMS0);
239                 return (Permission JavaDoc)c.newInstance(new Object JavaDoc[] {});
240         } catch (NoSuchMethodException JavaDoc ne) {
241             try {
242                 Constructor c = pc.getConstructor(PARAMS1);
243                         return (Permission JavaDoc) c.newInstance(
244                   new Object JavaDoc[] { name});
245             } catch (NoSuchMethodException JavaDoc ne1) {
246                 Constructor c = pc.getConstructor(PARAMS2);
247                 return (Permission JavaDoc) c.newInstance(
248                   new Object JavaDoc[] { name, actions });
249             }
250         }
251         } else {
252             if (name != null && actions == null) {
253                 try {
254                     Constructor c = pc.getConstructor(PARAMS1);
255                         return (Permission JavaDoc) c.newInstance(
256                   new Object JavaDoc[] { name});
257             } catch (NoSuchMethodException JavaDoc ne) {
258                 Constructor c = pc.getConstructor(PARAMS2);
259                     return (Permission JavaDoc) c.newInstance(
260                   new Object JavaDoc[] { name, actions });
261             }
262             } else {
263                     Constructor c = pc.getConstructor(PARAMS2);
264                     return (Permission JavaDoc) c.newInstance(
265                   new Object JavaDoc[] { name, actions });
266             }
267         }
268     } catch (NoSuchMethodException JavaDoc nsme) {
269         if (debug != null ) {
270         debug.println("NoSuchMethodException:\n could not find " +
271             "proper constructor for " + type);
272         nsme.printStackTrace();
273         }
274         return null;
275     } catch (Exception JavaDoc e) {
276         if (debug != null ) {
277         debug.println("unable to instantiate " + name);
278         e.printStackTrace();
279         }
280         return null;
281     }
282     }
283
284     /**
285      * This method always returns false for unresolved permissions.
286      * That is, an UnresolvedPermission is never considered to
287      * imply another permission.
288      *
289      * @param p the permission to check against.
290      *
291      * @return false.
292      */

293     public boolean implies(Permission JavaDoc p) {
294     return false;
295     }
296
297     /**
298      * Checks two UnresolvedPermission objects for equality.
299      * Checks that <i>obj</i> is an UnresolvedPermission, and has
300      * the same type (class) name, permission name, actions, and
301      * certificates as this object.
302      *
303      * <p> To determine certificate equality, this method only compares
304      * actual signer certificates. Supporting certificate chains
305      * are not taken into consideration by this method.
306      *
307      * @param obj the object we are testing for equality with this object.
308      *
309      * @return true if obj is an UnresolvedPermission, and has the same
310      * type (class) name, permission name, actions, and
311      * certificates as this object.
312      */

313     public boolean equals(Object JavaDoc obj) {
314     if (obj == this)
315         return true;
316
317     if (! (obj instanceof UnresolvedPermission JavaDoc))
318         return false;
319     UnresolvedPermission JavaDoc that = (UnresolvedPermission JavaDoc) obj;
320
321     // check type
322
if (!this.type.equals(that.type)) {
323         return false;
324     }
325
326     // check name
327
if (this.name == null) {
328         if (that.name != null) {
329         return false;
330         }
331     } else if (!this.name.equals(that.name)) {
332         return false;
333     }
334
335     // check actions
336
if (this.actions == null) {
337         if (that.actions != null) {
338         return false;
339         }
340     } else {
341         if (!this.actions.equals(that.actions)) {
342         return false;
343         }
344     }
345
346     // check certs
347
if ((this.certs == null && that.certs != null) ||
348         (this.certs != null && that.certs == null) ||
349         (this.certs != null && that.certs != null &&
350         this.certs.length != that.certs.length)) {
351         return false;
352     }
353         
354     int i,j;
355     boolean match;
356
357     for (i = 0; this.certs != null && i < this.certs.length; i++) {
358         match = false;
359         for (j = 0; j < that.certs.length; j++) {
360         if (this.certs[i].equals(that.certs[j])) {
361             match = true;
362             break;
363         }
364         }
365         if (!match) return false;
366     }
367
368     for (i = 0; that.certs != null && i < that.certs.length; i++) {
369         match = false;
370         for (j = 0; j < this.certs.length; j++) {
371         if (that.certs[i].equals(this.certs[j])) {
372             match = true;
373             break;
374         }
375         }
376         if (!match) return false;
377     }
378     return true;
379     }
380
381     /**
382      * Returns the hash code value for this object.
383      *
384      * @return a hash code value for this object.
385      */

386
387     public int hashCode() {
388     int hash = type.hashCode();
389     if (name != null)
390         hash ^= name.hashCode();
391     if (actions != null)
392         hash ^= actions.hashCode();
393     return hash;
394     }
395
396     /**
397      * Returns the canonical string representation of the actions,
398      * which currently is the empty string "", since there are no actions for
399      * an UnresolvedPermission. That is, the actions for the
400      * permission that will be created when this UnresolvedPermission
401      * is resolved may be non-null, but an UnresolvedPermission
402      * itself is never considered to have any actions.
403      *
404      * @return the empty string "".
405      */

406     public String JavaDoc getActions()
407     {
408     return "";
409     }
410
411     /**
412      * Get the type (class name) of the underlying permission that
413      * has not been resolved.
414      *
415      * @return the type (class name) of the underlying permission that
416      * has not been resolved
417      *
418      * @since 1.5
419      */

420     public String JavaDoc getUnresolvedType() {
421     return type;
422     }
423
424     /**
425      * Get the target name of the underlying permission that
426      * has not been resolved.
427      *
428      * @return the target name of the underlying permission that
429      * has not been resolved, or <code>null</code>,
430      * if there is no targe name
431      *
432      * @since 1.5
433      */

434     public String JavaDoc getUnresolvedName() {
435     return name;
436     }
437
438     /**
439      * Get the actions for the underlying permission that
440      * has not been resolved.
441      *
442      * @return the actions for the underlying permission that
443      * has not been resolved, or <code>null</code>
444      * if there are no actions
445      *
446      * @since 1.5
447      */

448     public String JavaDoc getUnresolvedActions() {
449     return actions;
450     }
451
452     /**
453      * Get the signer certificates (without any supporting chain)
454      * for the underlying permission that has not been resolved.
455      *
456      * @return the signer certificates for the underlying permission that
457      * has not been resolved, or null, if there are no signer certificates.
458      * Returns a new array each time this method is called.
459      *
460      * @since 1.5
461      */

462     public java.security.cert.Certificate JavaDoc[] getUnresolvedCerts() {
463         return (certs == null) ? null :
464                  (java.security.cert.Certificate JavaDoc[])certs.clone();
465     }
466
467     /**
468      * Returns a string describing this UnresolvedPermission. The convention
469      * is to specify the class name, the permission name, and the actions, in
470      * the following format: '(unresolved "ClassName" "name" "actions")'.
471      *
472      * @return information about this UnresolvedPermission.
473      */

474     public String JavaDoc toString() {
475     return "(unresolved " + type + " " + name + " " + actions + ")";
476     }
477
478     /**
479      * Returns a new PermissionCollection object for storing
480      * UnresolvedPermission objects.
481      * <p>
482      * @return a new PermissionCollection object suitable for
483      * storing UnresolvedPermissions.
484      */

485
486     public PermissionCollection JavaDoc newPermissionCollection() {
487     return new UnresolvedPermissionCollection JavaDoc();
488     }
489
490     /**
491      * Writes this object out to a stream (i.e., serializes it).
492      *
493      * @serialData An initial <code>String</code> denoting the
494      * <code>type</code> is followed by a <code>String</code> denoting the
495      * <code>name</code> is followed by a <code>String</code> denoting the
496      * <code>actions</code> is followed by an <code>int</code> indicating the
497      * number of certificates to follow
498      * (a value of "zero" denotes that there are no certificates associated
499      * with this object).
500      * Each certificate is written out starting with a <code>String</code>
501      * denoting the certificate type, followed by an
502      * <code>int</code> specifying the length of the certificate encoding,
503      * followed by the certificate encoding itself which is written out as an
504      * array of bytes.
505      */

506     private synchronized void writeObject(java.io.ObjectOutputStream JavaDoc oos)
507         throws IOException JavaDoc
508     {
509     oos.defaultWriteObject();
510
511     if (certs==null || certs.length==0) {
512         oos.writeInt(0);
513     } else {
514         // write out the total number of certs
515
oos.writeInt(certs.length);
516         // write out each cert, including its type
517
for (int i=0; i < certs.length; i++) {
518         java.security.cert.Certificate JavaDoc cert = certs[i];
519         try {
520             oos.writeUTF(cert.getType());
521             byte[] encoded = cert.getEncoded();
522             oos.writeInt(encoded.length);
523             oos.write(encoded);
524         } catch (CertificateEncodingException cee) {
525             throw new IOException JavaDoc(cee.getMessage());
526         }
527         }
528     }
529     }
530
531     /**
532      * Restores this object from a stream (i.e., deserializes it).
533      */

534     private synchronized void readObject(java.io.ObjectInputStream JavaDoc ois)
535     throws IOException JavaDoc, ClassNotFoundException JavaDoc
536     {
537     CertificateFactory cf;
538     Hashtable JavaDoc cfs=null;
539
540     ois.defaultReadObject();
541
542     if (type == null)
543         throw new NullPointerException JavaDoc("type can't be null");
544
545     // process any new-style certs in the stream (if present)
546
int size = ois.readInt();
547     if (size > 0) {
548         // we know of 3 different cert types: X.509, PGP, SDSI, which
549
// could all be present in the stream at the same time
550
cfs = new Hashtable JavaDoc(3);
551         this.certs = new java.security.cert.Certificate JavaDoc[size];
552     }
553
554     for (int i=0; i<size; i++) {
555         // read the certificate type, and instantiate a certificate
556
// factory of that type (reuse existing factory if possible)
557
String JavaDoc certType = ois.readUTF();
558         if (cfs.containsKey(certType)) {
559         // reuse certificate factory
560
cf = (CertificateFactory)cfs.get(certType);
561         } else {
562         // create new certificate factory
563
try {
564             cf = CertificateFactory.getInstance(certType);
565         } catch (CertificateException ce) {
566             throw new ClassNotFoundException JavaDoc
567             ("Certificate factory for "+certType+" not found");
568         }
569         // store the certificate factory so we can reuse it later
570
cfs.put(certType, cf);
571         }
572         // parse the certificate
573
byte[] encoded=null;
574         try {
575         encoded = new byte[ois.readInt()];
576         } catch (OutOfMemoryError JavaDoc oome) {
577         throw new IOException JavaDoc("Certificate too big");
578         }
579         ois.readFully(encoded);
580         ByteArrayInputStream JavaDoc bais = new ByteArrayInputStream JavaDoc(encoded);
581         try {
582         this.certs[i] = cf.generateCertificate(bais);
583         } catch (CertificateException ce) {
584         throw new IOException JavaDoc(ce.getMessage());
585         }
586         bais.close();
587     }
588     }
589 }
590
Popular Tags