home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / security / SecureClassLoader.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  6.3 KB  |  242 lines

  1. /*
  2.  * @(#)SecureClassLoader.java    1.58 98/03/18
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.Hashtable;
  18. import java.util.ArrayList;
  19. import java.net.URL;
  20.  
  21. /** 
  22.  * This class extends ClassLoader with additional support for defining
  23.  * classes with an associated code source and set of signers.
  24.  *
  25.  * @version 1.58, 03/18/98
  26.  * @author  Li Gong 
  27.  * @author  Roland Schemers
  28.  */
  29. public class SecureClassLoader extends ClassLoader {
  30.     // Hashtable that maps CodeSource to ProtectionDomain
  31.     private Hashtable pdcache = new Hashtable();
  32.  
  33.     /**
  34.      * Creates a new SecureClassLoader using the specified parent
  35.      * class loader for delegation.
  36.      *
  37.      * @param parent the parent ClassLoader
  38.      */
  39.     protected SecureClassLoader(ClassLoader parent) {
  40.     super(parent);
  41.     }
  42.  
  43.     /**
  44.      * Creates a new SecureClassLoader using the default parent class
  45.      * loader for delegation.
  46.      */
  47.     protected SecureClassLoader() {
  48.     super();
  49.     }
  50.  
  51.     /**
  52.      * Converts an array of bytes into an instance of class Class,
  53.      * with an optional ProtectionDomain and list of signers. Before the
  54.      * class can be used it must be resolved.
  55.      * @param name the name of the class
  56.      * @param b the class bytes
  57.      * @param off the start offset of the class bytes
  58.      * @param len the length of the class bytes
  59.      * @param protectionDomain the ProtectionDomain of the class
  60.      * @param signers the list of signers, or null if none
  61.      * @return the <code>Class</code> object created from the data,
  62.      *         optional ProtectionDomain, and list of signers
  63.      */
  64.     protected final Class defineClass(String name, byte[] b, int off, int len,
  65.                       ProtectionDomain protectionDomain,
  66.                       Object signers[])
  67.     {
  68.     Class c = defineClass(name, b, off, len);
  69.     if (protectionDomain != null) {
  70.         try {
  71.         AccessController.beginPrivileged();
  72.         c.setProtectionDomain(protectionDomain);
  73.         } finally {
  74.         AccessController.endPrivileged();
  75.         }
  76.     }
  77.     if (signers != null) {
  78.         setSigners(c, signers);
  79.     }
  80.     return c;
  81.     }
  82.  
  83.     /**
  84.      * Converts an array of bytes into an instance of class Class,
  85.      * with an optional CodeSource and list of signers. Before the
  86.      * class can be used it must be resolved.
  87.      * @param name the name of the class
  88.      * @param b the class bytes
  89.      * @param off the start offset of the class bytes
  90.      * @param len the length of the class bytes
  91.      * @param cs the associated CodeSource, or null if none
  92.      * @param signers the list of signers, or null if none
  93.      * @return the <code>Class</code> object created from the data,
  94.      *         optional CodeSource, and list of signers
  95.      */
  96.     protected final Class defineClass(String name, byte[] b, int off, int len,
  97.                       CodeSource cs, Object signers[])
  98.     {
  99.     Class c = defineClass(name, b, off, len);
  100.     if (cs != null) {
  101.         try {
  102.         AccessController.beginPrivileged();
  103.         c.setProtectionDomain(getProtectionDomain(cs));
  104.         } finally {
  105.         AccessController.endPrivileged();
  106.         }
  107.     }
  108.     if (signers != null) {
  109.         setSigners(c, signers);
  110.     }
  111.     return c;
  112.     }
  113.  
  114.     /*
  115.      * Returned cached ProtectionDomain for the specified CodeSource.
  116.      */
  117.     private ProtectionDomain getProtectionDomain(CodeSource cs) {
  118.     if (cs == null)
  119.         return null;
  120.  
  121.     ProtectionDomain pd = (ProtectionDomain)pdcache.get(cs);
  122.     if (pd == null) {
  123.         synchronized (pdcache) {
  124.         pd = (ProtectionDomain)pdcache.get(cs);
  125.         if (pd == null) {
  126.  
  127.             Policy p = Policy.getPolicyNoCheck();
  128.             Permissions perms;
  129.             if (p == null) {
  130.             perms = new Permissions();
  131.             } else {
  132.             perms = p.evaluate(cs);
  133.             }
  134.             pd = new ProtectionDomain(cs, perms);
  135.  
  136.             if (pd != null) {
  137.             pdcache.put(cs, pd);
  138.             }
  139.         }
  140.         }
  141.     }
  142.     return pd;
  143.     }
  144.  
  145.     // used to Cache already created CodeSource's. Saves expensive lookups
  146.     // and multiple calls to new.
  147.     
  148.     static class CodeSourceCache {
  149.     public URL base;
  150.     Object [] ids;
  151.     CodeSource codesource;
  152.  
  153.     boolean equals(URL base, Object [] ids) {
  154.         if (this.base == null) {
  155.             if (base != null) return false;
  156.         } else {
  157.             if (!this.base.equals(base))
  158.             return false;
  159.         }
  160.         if (this.ids == null) {
  161.             if (ids!= null)
  162.             return false;
  163.             else
  164.             return true;
  165.         }
  166.  
  167.         if (ids == null)
  168.             return false;
  169.  
  170.         boolean match;
  171.         
  172.         for (int i = 0; i < ids.length; i++) {
  173.             match = false;
  174.             for (int j = 0; j < this.ids.length; j++) {
  175.             if (ids[i].equals(this.ids[j])) {
  176.                 match = true;
  177.                 break;
  178.             }
  179.             }
  180.             if (!match) return false;
  181.         }
  182.  
  183.         for (int i = 0; i < this.ids.length; i++) {
  184.             match = false;
  185.             for (int j = 0; j < ids.length; j++) {
  186.             if (this.ids[i].equals(ids[j])) {
  187.                 match = true;
  188.                 break;
  189.             }
  190.             }
  191.             if (!match) return false;
  192.         }
  193.         return true;
  194.     }
  195.     }
  196.  
  197.     private ArrayList cscache = null;
  198.  
  199.     /**
  200.      * Returns the CodeSource for the specified URL and list of signers.
  201.      * @param url the URL for the CodeSource
  202.      * @param signers the signers for the CodeSource
  203.      * @return the resulting CodeSource
  204.      */
  205.     protected CodeSource getCodeSource(URL url, Object[] signers) {
  206.     if (cscache == null) 
  207.         cscache = new ArrayList();
  208.     CodeSourceCache csc;
  209.     for (int i = 0; i < cscache.size(); i++) {
  210.         csc = (CodeSourceCache) cscache.get(i);
  211.         if (csc.equals(url, signers)) {
  212.         return csc.codesource;
  213.         }
  214.     }
  215.     csc = new CodeSourceCache();
  216.     csc.base = url;
  217.     PublicKey[] keys = null;
  218.  
  219.     if (signers != null) {
  220.         csc.ids = new Object[signers.length];
  221.         System.arraycopy(signers, 0, csc.ids, 0, signers.length);
  222.  
  223.         ArrayList keysAL = new ArrayList();
  224.         for (int j=0; j < signers.length; j++) {
  225.         if (signers[j] instanceof Identity) {
  226.             PublicKey pk = ((Identity) signers[j]).getPublicKey();
  227.             if (pk != null)
  228.             keysAL.add(pk);
  229.         }
  230.         }
  231.         keys = new PublicKey[keysAL.size()];
  232.         for (int k=0; k< keysAL.size(); k++) {
  233.         keys[k] = (PublicKey) keysAL.get(k);
  234.         }
  235.     }
  236.  
  237.     csc.codesource = new CodeSource(csc.base, keys);
  238.     cscache.add(csc);
  239.     return csc.codesource;
  240.     }
  241. }
  242.