mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			688 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			688 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* PolicyFile.java -- policy file reader
 | |
|    Copyright (C) 2004, 2005, 2006  Free Software Foundation, Inc.
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package gnu.java.security;
 | |
| 
 | |
| import gnu.classpath.debug.Component;
 | |
| import gnu.classpath.debug.SystemLogger;
 | |
| 
 | |
| import gnu.java.lang.CPStringBuilder;
 | |
| import gnu.java.security.action.GetPropertyAction;
 | |
| 
 | |
| import java.io.File;
 | |
| import java.io.IOException;
 | |
| import java.io.InputStreamReader;
 | |
| import java.io.StreamTokenizer;
 | |
| import java.lang.reflect.Constructor;
 | |
| import java.net.MalformedURLException;
 | |
| import java.net.URL;
 | |
| import java.security.AccessController;
 | |
| import java.security.CodeSource;
 | |
| import java.security.KeyStore;
 | |
| import java.security.KeyStoreException;
 | |
| import java.security.Permission;
 | |
| import java.security.PermissionCollection;
 | |
| import java.security.Permissions;
 | |
| import java.security.Policy;
 | |
| import java.security.Principal;
 | |
| import java.security.PrivilegedActionException;
 | |
| import java.security.PrivilegedExceptionAction;
 | |
| import java.security.Security;
 | |
| import java.security.UnresolvedPermission;
 | |
| import java.security.cert.Certificate;
 | |
| import java.security.cert.X509Certificate;
 | |
| import java.util.Enumeration;
 | |
| import java.util.HashMap;
 | |
| import java.util.Iterator;
 | |
| import java.util.LinkedList;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| import java.util.StringTokenizer;
 | |
| import java.util.logging.Logger;
 | |
| 
 | |
| /**
 | |
|  * An implementation of a {@link java.security.Policy} object whose
 | |
|  * permissions are specified by a <em>policy file</em>.
 | |
|  *
 | |
|  * <p>The approximate syntax of policy files is:</p>
 | |
|  *
 | |
|  * <pre>
 | |
|  * policyFile ::= keystoreOrGrantEntries ;
 | |
|  *
 | |
|  * keystoreOrGrantEntries ::= keystoreOrGrantEntry |
 | |
|  *                            keystoreOrGrantEntries keystoreOrGrantEntry |
 | |
|  *                            EMPTY ;
 | |
|  *
 | |
|  * keystoreOrGrantEntry ::= keystoreEntry | grantEntry ;
 | |
|  *
 | |
|  * keystoreEntry ::= "keystore" keystoreUrl ';' |
 | |
|  *                   "keystore" keystoreUrl ',' keystoreAlgorithm ';' ;
 | |
|  *
 | |
|  * keystoreUrl ::= URL ;
 | |
|  * keystoreAlgorithm ::= STRING ;
 | |
|  *
 | |
|  * grantEntry ::= "grant" domainParameters '{' permissions '}' ';'
 | |
|  *
 | |
|  * domainParameters ::= domainParameter |
 | |
|  *                      domainParameter ',' domainParameters ;
 | |
|  *
 | |
|  * domainParameter ::= "signedBy" signerNames |
 | |
|  *                     "codeBase" codeBaseUrl |
 | |
|  *                     "principal" principalClassName principalName |
 | |
|  *                     "principal" principalName ;
 | |
|  *
 | |
|  * signerNames ::= quotedString ;
 | |
|  * codeBaseUrl ::= URL ;
 | |
|  * principalClassName ::= STRING ;
 | |
|  * principalName ::= quotedString ;
 | |
|  *
 | |
|  * quotedString ::= quoteChar STRING quoteChar ;
 | |
|  * quoteChar ::= '"' | '\'';
 | |
|  *
 | |
|  * permissions ::= permission | permissions permission ;
 | |
|  *
 | |
|  * permission ::= "permission" permissionClassName permissionTarget permissionAction |
 | |
|  *                "permission" permissionClassName permissionTarget |
 | |
|  *                "permission" permissionClassName;
 | |
|  * </pre>
 | |
|  *
 | |
|  * <p>Comments are either form of Java comments. Keystore entries only
 | |
|  * affect subsequent grant entries, so if a grant entry preceeds a
 | |
|  * keystore entry, that grant entry is not affected by that keystore
 | |
|  * entry. Certian instances of <code>${property-name}</code> will be
 | |
|  * replaced with <code>System.getProperty("property-name")</code> in
 | |
|  * quoted strings.</p>
 | |
|  *
 | |
|  * <p>This class will load the following files when created or
 | |
|  * refreshed, in order:</p>
 | |
|  *
 | |
|  * <ol>
 | |
|  * <li>The file <code>${java.home}/lib/security/java.policy</code>.</li>
 | |
|  * <li>All URLs specified by security properties
 | |
|  * <code>"policy.file.<i>n</i>"</code>, for increasing <i>n</i>
 | |
|  * starting from 1. The sequence stops at the first undefined
 | |
|  * property, so you must set <code>"policy.file.1"</code> if you also
 | |
|  * set <code>"policy.file.2"</code>, and so on.</li>
 | |
|  * <li>The URL specified by the property
 | |
|  * <code>"java.security.policy"</code>.</li>
 | |
|  * </ol>
 | |
|  *
 | |
|  * @author Casey Marshall (csm@gnu.org)
 | |
|  * @see java.security.Policy
 | |
|  */
 | |
| public final class PolicyFile extends Policy
 | |
| {
 | |
| 
 | |
|   // Constants and fields.
 | |
|   // -------------------------------------------------------------------------
 | |
| 
 | |
|   protected static final Logger logger = SystemLogger.SYSTEM;
 | |
|   // Added to cut redundant AccessController.doPrivileged calls
 | |
|   private static GetPropertyAction prop = new GetPropertyAction("file.separator");
 | |
|   private static final String fs = (String) AccessController.doPrivileged(prop);
 | |
| 
 | |
|   private static final String DEFAULT_POLICY =
 | |
|     (String) AccessController.doPrivileged(prop.setParameters("java.home"))
 | |
|     + fs + "lib" + fs + "security" + fs + "java.policy";
 | |
|   private static final String DEFAULT_USER_POLICY =
 | |
|     (String) AccessController.doPrivileged(prop.setParameters("user.home")) +
 | |
|     fs + ".java.policy";
 | |
| 
 | |
|   private final Map cs2pc;
 | |
| 
 | |
|   // Constructors.
 | |
|   // -------------------------------------------------------------------------
 | |
| 
 | |
|   public PolicyFile()
 | |
|   {
 | |
|     cs2pc = new HashMap();
 | |
|     refresh();
 | |
|   }
 | |
| 
 | |
|   // Instance methods.
 | |
|   // -------------------------------------------------------------------------
 | |
| 
 | |
|   public PermissionCollection getPermissions(CodeSource codeSource)
 | |
|   {
 | |
|     Permissions perms = new Permissions();
 | |
|     for (Iterator it = cs2pc.entrySet().iterator(); it.hasNext(); )
 | |
|       {
 | |
|         Map.Entry e = (Map.Entry) it.next();
 | |
|         CodeSource cs = (CodeSource) e.getKey();
 | |
|         if (cs.implies(codeSource))
 | |
|           {
 | |
|             logger.log (Component.POLICY, "{0} -> {1}", new Object[]
 | |
|               { cs, codeSource });
 | |
|             PermissionCollection pc = (PermissionCollection) e.getValue();
 | |
|             for (Enumeration ee = pc.elements(); ee.hasMoreElements(); )
 | |
|               {
 | |
|                 perms.add((Permission) ee.nextElement());
 | |
|               }
 | |
|           }
 | |
|         else
 | |
|           logger.log (Component.POLICY, "{0} !-> {1}", new Object[]
 | |
|             { cs, codeSource });
 | |
|       }
 | |
|     logger.log (Component.POLICY, "returning permissions {0} for {1}",
 | |
|                 new Object[] { perms, codeSource });
 | |
|     return perms;
 | |
|   }
 | |
| 
 | |
|   public void refresh()
 | |
|   {
 | |
|     cs2pc.clear();
 | |
|     final List policyFiles = new LinkedList();
 | |
|     try
 | |
|       {
 | |
|         policyFiles.add (new File (DEFAULT_POLICY).toURL());
 | |
|         policyFiles.add (new File (DEFAULT_USER_POLICY).toURL ());
 | |
| 
 | |
|         AccessController.doPrivileged(
 | |
|           new PrivilegedExceptionAction()
 | |
|           {
 | |
|             public Object run() throws Exception
 | |
|             {
 | |
|               String allow = Security.getProperty ("policy.allowSystemProperty");
 | |
|               if (allow == null || Boolean.getBoolean (allow))
 | |
|                 {
 | |
|                   String s = System.getProperty ("java.security.policy");
 | |
|                   logger.log (Component.POLICY, "java.security.policy={0}", s);
 | |
|                   if (s != null)
 | |
|                     {
 | |
|                       boolean only = s.startsWith ("=");
 | |
|                       if (only)
 | |
|                         s = s.substring (1);
 | |
|                       policyFiles.clear ();
 | |
|                       policyFiles.add (new URL (s));
 | |
|                       if (only)
 | |
|                         return null;
 | |
|                     }
 | |
|                 }
 | |
|               for (int i = 1; ; i++)
 | |
|                 {
 | |
|                   String pname = "policy.url." + i;
 | |
|                   String s = Security.getProperty (pname);
 | |
|                   logger.log (Component.POLICY, "{0}={1}", new Object []
 | |
|                     { pname, s });
 | |
|                   if (s == null)
 | |
|                     break;
 | |
|                   policyFiles.add (new URL (s));
 | |
|                 }
 | |
|               return null;
 | |
|             }
 | |
|           });
 | |
|       }
 | |
|     catch (PrivilegedActionException pae)
 | |
|       {
 | |
|         logger.log (Component.POLICY, "reading policy properties", pae);
 | |
|       }
 | |
|     catch (MalformedURLException mue)
 | |
|       {
 | |
|         logger.log (Component.POLICY, "setting default policies", mue);
 | |
|       }
 | |
| 
 | |
|     logger.log (Component.POLICY, "building policy from URLs {0}",
 | |
|                 policyFiles);
 | |
|     for (Iterator it = policyFiles.iterator(); it.hasNext(); )
 | |
|       {
 | |
|         try
 | |
|           {
 | |
|             URL url = (URL) it.next();
 | |
|             parse(url);
 | |
|           }
 | |
|         catch (IOException ioe)
 | |
|           {
 | |
|             logger.log (Component.POLICY, "reading policy", ioe);
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   public String toString()
 | |
|   {
 | |
|     return super.toString() + " [ " + cs2pc.toString() + " ]";
 | |
|   }
 | |
| 
 | |
|   // Own methods.
 | |
|   // -------------------------------------------------------------------------
 | |
| 
 | |
|   private static final int STATE_BEGIN = 0;
 | |
|   private static final int STATE_GRANT = 1;
 | |
|   private static final int STATE_PERMS = 2;
 | |
| 
 | |
|   /**
 | |
|    * Parse a policy file, incorporating the permission definitions
 | |
|    * described therein.
 | |
|    *
 | |
|    * @param url The URL of the policy file to read.
 | |
|    * @throws IOException if an I/O error occurs, or if the policy file
 | |
|    * cannot be parsed.
 | |
|    */
 | |
|   private void parse(final URL url) throws IOException
 | |
|   {
 | |
|     logger.log (Component.POLICY, "reading policy file from {0}", url);
 | |
|     final StreamTokenizer in = new StreamTokenizer(new InputStreamReader(url.openStream()));
 | |
|     in.resetSyntax();
 | |
|     in.slashSlashComments(true);
 | |
|     in.slashStarComments(true);
 | |
|     in.wordChars('A', 'Z');
 | |
|     in.wordChars('a', 'z');
 | |
|     in.wordChars('0', '9');
 | |
|     in.wordChars('.', '.');
 | |
|     in.wordChars('_', '_');
 | |
|     in.wordChars('$', '$');
 | |
|     in.whitespaceChars(' ', ' ');
 | |
|     in.whitespaceChars('\t', '\t');
 | |
|     in.whitespaceChars('\f', '\f');
 | |
|     in.whitespaceChars('\n', '\n');
 | |
|     in.whitespaceChars('\r', '\r');
 | |
|     in.quoteChar('\'');
 | |
|     in.quoteChar('"');
 | |
| 
 | |
|     int tok;
 | |
|     int state = STATE_BEGIN;
 | |
|     List keystores = new LinkedList();
 | |
|     URL currentBase = null;
 | |
|     List currentCerts = new LinkedList();
 | |
|     Permissions currentPerms = new Permissions();
 | |
|     while ((tok = in.nextToken()) != StreamTokenizer.TT_EOF)
 | |
|       {
 | |
|         switch (tok)
 | |
|           {
 | |
|           case '{':
 | |
|             if (state != STATE_GRANT)
 | |
|               error(url, in, "spurious '{'");
 | |
|             state = STATE_PERMS;
 | |
|             tok = in.nextToken();
 | |
|             break;
 | |
|           case '}':
 | |
|             if (state != STATE_PERMS)
 | |
|               error(url, in, "spurious '}'");
 | |
|             state = STATE_BEGIN;
 | |
|             currentPerms.setReadOnly();
 | |
|             Certificate[] c = null;
 | |
|             if (!currentCerts.isEmpty())
 | |
|               c = (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()]);
 | |
|             cs2pc.put(new CodeSource(currentBase, c), currentPerms);
 | |
|             currentCerts.clear();
 | |
|             currentPerms = new Permissions();
 | |
|             currentBase = null;
 | |
|             tok = in.nextToken();
 | |
|             if (tok != ';')
 | |
|               in.pushBack();
 | |
|             continue;
 | |
|           }
 | |
|         if (tok != StreamTokenizer.TT_WORD)
 | |
|           {
 | |
|             error(url, in, "expecting word token");
 | |
|           }
 | |
| 
 | |
|         // keystore "<keystore-path>" [',' "<keystore-type>"] ';'
 | |
|         if (in.sval.equalsIgnoreCase("keystore"))
 | |
|           {
 | |
|             String alg = KeyStore.getDefaultType();
 | |
|             tok = in.nextToken();
 | |
|             if (tok != '"' && tok != '\'')
 | |
|               error(url, in, "expecting key store URL");
 | |
|             String store = in.sval;
 | |
|             tok = in.nextToken();
 | |
|             if (tok == ',')
 | |
|               {
 | |
|                 tok = in.nextToken();
 | |
|                 if (tok != '"' && tok != '\'')
 | |
|                   error(url, in, "expecting key store type");
 | |
|                 alg = in.sval;
 | |
|                 tok = in.nextToken();
 | |
|               }
 | |
|             if (tok != ';')
 | |
|               error(url, in, "expecting semicolon");
 | |
|             try
 | |
|               {
 | |
|                 KeyStore keystore = KeyStore.getInstance(alg);
 | |
|                 keystore.load(new URL(url, store).openStream(), null);
 | |
|                 keystores.add(keystore);
 | |
|               }
 | |
|             catch (Exception x)
 | |
|               {
 | |
|                 error(url, in, x.toString());
 | |
|               }
 | |
|           }
 | |
|         else if (in.sval.equalsIgnoreCase("grant"))
 | |
|           {
 | |
|             if (state != STATE_BEGIN)
 | |
|               error(url, in, "extraneous grant keyword");
 | |
|             state = STATE_GRANT;
 | |
|           }
 | |
|         else if (in.sval.equalsIgnoreCase("signedBy"))
 | |
|           {
 | |
|             if (state != STATE_GRANT && state != STATE_PERMS)
 | |
|               error(url, in, "spurious 'signedBy'");
 | |
|             if (keystores.isEmpty())
 | |
|               error(url, in, "'signedBy' with no keystores");
 | |
|             tok = in.nextToken();
 | |
|             if (tok != '"' && tok != '\'')
 | |
|               error(url, in, "expecting signedBy name");
 | |
|             StringTokenizer st = new StringTokenizer(in.sval, ",");
 | |
|             while (st.hasMoreTokens())
 | |
|               {
 | |
|                 String alias = st.nextToken();
 | |
|                 for (Iterator it = keystores.iterator(); it.hasNext(); )
 | |
|                   {
 | |
|                     KeyStore keystore = (KeyStore) it.next();
 | |
|                     try
 | |
|                       {
 | |
|                         if (keystore.isCertificateEntry(alias))
 | |
|                           currentCerts.add(keystore.getCertificate(alias));
 | |
|                       }
 | |
|                     catch (KeyStoreException kse)
 | |
|                       {
 | |
|                         error(url, in, kse.toString());
 | |
|                       }
 | |
|                   }
 | |
|               }
 | |
|             tok = in.nextToken();
 | |
|             if (tok != ',')
 | |
|               {
 | |
|                 if (state != STATE_GRANT)
 | |
|                   error(url, in, "spurious ','");
 | |
|                 in.pushBack();
 | |
|               }
 | |
|           }
 | |
|         else if (in.sval.equalsIgnoreCase("codeBase"))
 | |
|           {
 | |
|             if (state != STATE_GRANT)
 | |
|               error(url, in, "spurious 'codeBase'");
 | |
|             tok = in.nextToken();
 | |
|             if (tok != '"' && tok != '\'')
 | |
|               error(url, in, "expecting code base URL");
 | |
|             String base = expand(in.sval);
 | |
|             if (File.separatorChar != '/')
 | |
|               base = base.replace(File.separatorChar, '/');
 | |
|             try
 | |
|               {
 | |
|                 currentBase = new URL(base);
 | |
|               }
 | |
|             catch (MalformedURLException mue)
 | |
|               {
 | |
|                 error(url, in, mue.toString());
 | |
|               }
 | |
|             tok = in.nextToken();
 | |
|             if (tok != ',')
 | |
|               in.pushBack();
 | |
|           }
 | |
|         else if (in.sval.equalsIgnoreCase("principal"))
 | |
|           {
 | |
|             if (state != STATE_GRANT)
 | |
|               error(url, in, "spurious 'principal'");
 | |
|             tok = in.nextToken();
 | |
|             if (tok == StreamTokenizer.TT_WORD)
 | |
|               {
 | |
|                 tok = in.nextToken();
 | |
|                 if (tok != '"' && tok != '\'')
 | |
|                   error(url, in, "expecting principal name");
 | |
|                 String name = in.sval;
 | |
|                 Principal p = null;
 | |
|                 try
 | |
|                   {
 | |
|                     Class pclass = Class.forName(in.sval);
 | |
|                     Constructor c =
 | |
|                       pclass.getConstructor(new Class[] { String.class });
 | |
|                     p = (Principal) c.newInstance(new Object[] { name });
 | |
|                   }
 | |
|                 catch (Exception x)
 | |
|                   {
 | |
|                     error(url, in, x.toString());
 | |
|                   }
 | |
|                 for (Iterator it = keystores.iterator(); it.hasNext(); )
 | |
|                   {
 | |
|                     KeyStore ks = (KeyStore) it.next();
 | |
|                     try
 | |
|                       {
 | |
|                         for (Enumeration e = ks.aliases(); e.hasMoreElements(); )
 | |
|                           {
 | |
|                             String alias = (String) e.nextElement();
 | |
|                             if (ks.isCertificateEntry(alias))
 | |
|                               {
 | |
|                                 Certificate cert = ks.getCertificate(alias);
 | |
|                                 if (!(cert instanceof X509Certificate))
 | |
|                                   continue;
 | |
|                                 if (p.equals(((X509Certificate) cert).getSubjectDN()) ||
 | |
|                                     p.equals(((X509Certificate) cert).getSubjectX500Principal()))
 | |
|                                   currentCerts.add(cert);
 | |
|                               }
 | |
|                           }
 | |
|                       }
 | |
|                     catch (KeyStoreException kse)
 | |
|                       {
 | |
|                         error(url, in, kse.toString());
 | |
|                       }
 | |
|                   }
 | |
|               }
 | |
|             else if (tok == '"' || tok == '\'')
 | |
|               {
 | |
|                 String alias = in.sval;
 | |
|                 for (Iterator it = keystores.iterator(); it.hasNext(); )
 | |
|                   {
 | |
|                     KeyStore ks = (KeyStore) it.next();
 | |
|                     try
 | |
|                       {
 | |
|                         if (ks.isCertificateEntry(alias))
 | |
|                           currentCerts.add(ks.getCertificate(alias));
 | |
|                       }
 | |
|                     catch (KeyStoreException kse)
 | |
|                       {
 | |
|                         error(url, in, kse.toString());
 | |
|                       }
 | |
|                   }
 | |
|               }
 | |
|             else
 | |
|               error(url, in, "expecting principal");
 | |
|             tok = in.nextToken();
 | |
|             if (tok != ',')
 | |
|               in.pushBack();
 | |
|           }
 | |
|         else if (in.sval.equalsIgnoreCase("permission"))
 | |
|           {
 | |
|             if (state != STATE_PERMS)
 | |
|               error(url, in, "spurious 'permission'");
 | |
|             tok = in.nextToken();
 | |
|             if (tok != StreamTokenizer.TT_WORD)
 | |
|               error(url, in, "expecting permission class name");
 | |
|             String className = in.sval;
 | |
|             Class clazz = null;
 | |
|             try
 | |
|               {
 | |
|                 clazz = Class.forName(className);
 | |
|               }
 | |
|             catch (ClassNotFoundException cnfe)
 | |
|               {
 | |
|               }
 | |
|             tok = in.nextToken();
 | |
|             if (tok == ';')
 | |
|               {
 | |
|                 if (clazz == null)
 | |
|                   {
 | |
|                     currentPerms.add(new UnresolvedPermission(className,
 | |
|                       null, null, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()])));
 | |
|                     continue;
 | |
|                   }
 | |
|                 try
 | |
|                   {
 | |
|                     currentPerms.add((Permission) clazz.newInstance());
 | |
|                   }
 | |
|                 catch (Exception x)
 | |
|                   {
 | |
|                     error(url, in, x.toString());
 | |
|                   }
 | |
|                 continue;
 | |
|               }
 | |
|             if (tok != '"' && tok != '\'')
 | |
|               error(url, in, "expecting permission target");
 | |
|             String target = expand(in.sval);
 | |
|             tok = in.nextToken();
 | |
|             if (tok == ';')
 | |
|               {
 | |
|                 if (clazz == null)
 | |
|                   {
 | |
|                     currentPerms.add(new UnresolvedPermission(className,
 | |
|                       target, null, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()])));
 | |
|                     continue;
 | |
|                   }
 | |
|                 try
 | |
|                   {
 | |
|                     Constructor c =
 | |
|                       clazz.getConstructor(new Class[] { String.class });
 | |
|                     currentPerms.add((Permission) c.newInstance(
 | |
|                       new Object[] { target }));
 | |
|                   }
 | |
|                 catch (Exception x)
 | |
|                   {
 | |
|                     error(url, in, x.toString());
 | |
|                   }
 | |
|                 continue;
 | |
|               }
 | |
|             if (tok != ',')
 | |
|               error(url, in, "expecting ','");
 | |
|             tok = in.nextToken();
 | |
|             if (tok == StreamTokenizer.TT_WORD)
 | |
|               {
 | |
|                 if (!in.sval.equalsIgnoreCase("signedBy"))
 | |
|                   error(url, in, "expecting 'signedBy'");
 | |
|                 try
 | |
|                   {
 | |
|                     Constructor c =
 | |
|                       clazz.getConstructor(new Class[] { String.class });
 | |
|                     currentPerms.add((Permission) c.newInstance(
 | |
|                       new Object[] { target }));
 | |
|                   }
 | |
|                 catch (Exception x)
 | |
|                   {
 | |
|                     error(url, in, x.toString());
 | |
|                   }
 | |
|                 in.pushBack();
 | |
|                 continue;
 | |
|               }
 | |
|             if (tok != '"' && tok != '\'')
 | |
|               error(url, in, "expecting permission action");
 | |
|             String action = in.sval;
 | |
|             if (clazz == null)
 | |
|               {
 | |
|                 currentPerms.add(new UnresolvedPermission(className,
 | |
|                   target, action, (Certificate[]) currentCerts.toArray(new Certificate[currentCerts.size()])));
 | |
|                 continue;
 | |
|               }
 | |
|             else
 | |
|               {
 | |
|                 try
 | |
|                   {
 | |
|                     Constructor c = clazz.getConstructor(
 | |
|                       new Class[] { String.class, String.class });
 | |
|                     currentPerms.add((Permission) c.newInstance(
 | |
|                       new Object[] { target, action }));
 | |
|                   }
 | |
|                 catch (Exception x)
 | |
|                   {
 | |
|                     error(url, in, x.toString());
 | |
|                   }
 | |
|               }
 | |
|             tok = in.nextToken();
 | |
|             if (tok != ';' && tok != ',')
 | |
|               error(url, in, "expecting ';' or ','");
 | |
|           }
 | |
|       }
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Expand all instances of <code>"${property-name}"</code> into
 | |
|    * <code>System.getProperty("property-name")</code>.
 | |
|    */
 | |
|   private static String expand(final String s)
 | |
|   {
 | |
|     final CPStringBuilder result = new CPStringBuilder();
 | |
|     final CPStringBuilder prop = new CPStringBuilder();
 | |
|     int state = 0;
 | |
|     for (int i = 0; i < s.length(); i++)
 | |
|       {
 | |
|         switch (state)
 | |
|           {
 | |
|           case 0:
 | |
|             if (s.charAt(i) == '$')
 | |
|               state = 1;
 | |
|             else
 | |
|               result.append(s.charAt(i));
 | |
|             break;
 | |
|           case 1:
 | |
|             if (s.charAt(i) == '{')
 | |
|               state = 2;
 | |
|             else
 | |
|               {
 | |
|                 state = 0;
 | |
|                 result.append('$').append(s.charAt(i));
 | |
|               }
 | |
|             break;
 | |
|           case 2:
 | |
|             if (s.charAt(i) == '}')
 | |
|               {
 | |
|                 String p = prop.toString();
 | |
|                 if (p.equals("/"))
 | |
|                   p = "file.separator";
 | |
|                 p = System.getProperty(p);
 | |
|                 if (p == null)
 | |
|                   p = "";
 | |
|                 result.append(p);
 | |
|                 prop.setLength(0);
 | |
|                 state = 0;
 | |
|               }
 | |
|             else
 | |
|               prop.append(s.charAt(i));
 | |
|             break;
 | |
|           }
 | |
|       }
 | |
|     if (state != 0)
 | |
|       result.append('$').append('{').append(prop);
 | |
|     return result.toString();
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * I miss macros.
 | |
|    */
 | |
|   private static void error(URL base, StreamTokenizer in, String msg)
 | |
|     throws IOException
 | |
|   {
 | |
|     throw new IOException(base+":"+in.lineno()+": "+msg);
 | |
|   }
 | |
| }
 |