river-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From peter_firmst...@apache.org
Subject svn commit: r1002846 - in /incubator/river/jtsk/skunk/pepe: ./ src/org/apache/river/api/delegates/ src/org/apache/river/api/security/ src/org/apache/river/imp/security/policy/se/ src/org/apache/river/imp/security/policy/util/
Date Wed, 29 Sep 2010 21:14:40 GMT
Author: peter_firmstone
Date: Wed Sep 29 21:14:40 2010
New Revision: 1002846

URL: http://svn.apache.org/viewvc?rev=1002846&view=rev
Log:
Add FileOutputStream delegate

Modified:
    incubator/river/jtsk/skunk/pepe/build.xml
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileInputStream.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileOutputStream.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/InternetSecurityManager.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/util/PolicyUtils.java

Modified: incubator/river/jtsk/skunk/pepe/build.xml
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/build.xml?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/build.xml (original)
+++ incubator/river/jtsk/skunk/pepe/build.xml Wed Sep 29 21:14:40 2010
@@ -849,8 +849,14 @@
             <arg value="-files"/>
             <arg value="org.apache.river.imp.security.policy.se.ConcurrentPolicyFile"/>
             <arg value="org.apache.river.imp.security.policy.se.DynamicConcurrentPolicyProvider"/>
+	    <arg value="org.apache.river.api.security.DelegatePermission"/>
+	    <arg value="org.apache.river.api.security.InternetSecurityManager"/>
             <arg line="-in org.apache.river"/>
-            <arg line="-out org.apache.river.api"/>
+            <arg line="-skip org.apache.river.api.security.RevokeableDynamicPolicy"/>
+	    <arg line="-skip org.apache.river.api.security.Denied"/>
+	    <arg line="-skip org.apache.river.api.security.PermissionGrant"/>
+	    <arg line="-skip org.apache.river.api.security.PermissionGrantBuilder"/>
+	    <arg line="-skip org.apache.river.api.security.RevokePermission"/>
             <arg line="-out org.apache.river.imp.security.policy.spi"/>
         </classdep>
         <delete file="${lib-ext.dir}/concurrent-policy-util.jar" quiet="true"/>

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileInputStream.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileInputStream.java?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileInputStream.java
(original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileInputStream.java
Wed Sep 29 21:14:40 2010
@@ -43,7 +43,7 @@ public class FileInputStream extends jav
     private final java.io.FileInputStream in;
     public FileInputStream(final String name) throws FileNotFoundException {
 	Permission p = new FilePermission(name, SecurityConstants.FILE_READ_ACTION);
-	g = new DelegatePermission(p);
+	g = DelegatePermission.get(p);
 	java.io.FileInputStream input = null;
 	try {	    
 	    // Permission check is delayed.
@@ -62,7 +62,7 @@ public class FileInputStream extends jav
     public FileInputStream(final File file) throws FileNotFoundException {
 	Permission p = new FilePermission(file.getPath(), 
 		SecurityConstants.FILE_READ_ACTION);
-	g = new DelegatePermission(p);
+	g = DelegatePermission.get(p);
 	java.io.FileInputStream input = null;
 	try {
 	    input = AccessController.doPrivileged(
@@ -78,7 +78,7 @@ public class FileInputStream extends jav
     }
     
     public FileInputStream(final FileDescriptor fdObj) {
-	g = new DelegatePermission(new RuntimePermission("readFileDescriptor"));
+	g = DelegatePermission.get(new RuntimePermission("readFileDescriptor"));
 	in = AccessController.doPrivileged(new PrivilegedAction<java.io.FileInputStream>()
{
 	    public java.io.FileInputStream run() {
 		return new java.io.FileInputStream(fdObj);

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileOutputStream.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileOutputStream.java?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileOutputStream.java
(original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/delegates/FileOutputStream.java
Wed Sep 29 21:14:40 2010
@@ -37,7 +37,7 @@ import sun.security.util.SecurityConstan
 
 /**
  * <p>This is a simple FileOutputStream delegate to replace a java.io.FileOutputStream
- * in code that is downloaded and trust is not assurred.
+ * in code that is downloaded where trust is not assurred.
  * </p><p>
  * The client must have a DelegatePermission representing a FilePermission, or
  * a FilePermission, the
@@ -58,7 +58,7 @@ public class FileOutputStream extends Ou
     public FileOutputStream(final String name, final boolean append) 
 	    throws FileNotFoundException {
 	Permission p = new FilePermission(name, SecurityConstants.FILE_READ_ACTION);
-	g = new DelegatePermission(p);
+	g = DelegatePermission.get(p);
 	java.io.FileOutputStream output = null;
 	try {
 	    // Permission check is delayed.    
@@ -83,7 +83,7 @@ public class FileOutputStream extends Ou
     public FileOutputStream(final File file, final boolean append) throws FileNotFoundException
{
 	Permission p = new FilePermission(file.getPath(),
 		SecurityConstants.FILE_READ_ACTION);
-	g = new DelegatePermission(p);
+	g = DelegatePermission.get(p);
 	java.io.FileOutputStream output = null;
 	try {
 	    output = AccessController.doPrivileged(
@@ -104,7 +104,7 @@ public class FileOutputStream extends Ou
     }
 	
     public FileOutputStream(final FileDescriptor fdObj) {
-	g = new DelegatePermission(new RuntimePermission("readFileDescriptor"));
+	g = DelegatePermission.get(new RuntimePermission("readFileDescriptor"));
 	out = AccessController.doPrivileged(new PrivilegedAction<java.io.FileOutputStream>()
{
 	    public java.io.FileOutputStream run() {
 		return new java.io.FileOutputStream(fdObj);

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java
(original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java
Wed Sep 29 21:14:40 2010
@@ -18,6 +18,9 @@
 
 package org.apache.river.api.security;
 
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
@@ -25,6 +28,8 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.river.imp.util.ConcurrentWeakMap;
 
 /**
  * A DelegatePermission represents any another Permission, called the candidate.
@@ -33,8 +38,8 @@ import java.util.Set;
  * calls.
  * 
  * A Security Delegate does not have an interface that identifies it as a Delegate,
- * it is a wrapper class that has the interface or class type identical to 
- * the object it encapsulates, to discuise it from clients.
+ * it is a wrapper class that has the interface or class type, identical, where 
+ * practical, to the object it encapsulates, to discuise it from clients.
  * 
  * Security Delegates enable sensitive objects to be used by code that isn't
  * fully trusted and may want to monitor, such as a 
@@ -45,7 +50,7 @@ import java.util.Set;
  * 
  * A DelegatePermission never implies it's candidate, however if a 
  * ProtectionDomain has the Permission the delegate represents, then the 
- * AccessControlDelegate, which a Security Delegate must utilise,
+ * InternetSecurityManager, which a Security Delegate must utilise,
  * must ensure that it is also checked.
  * 
  * The DelegatePermissionCollection returned by newPermissionCollection() is not
@@ -56,19 +61,52 @@ import java.util.Set;
  * in this case, existing PermissionCollection implementatations don't cleanly
  * protect their internal state with synchronization, since the Enumeration
  * returned by elements() will throw a ConcurrentModificationException if in a 
- * loop when Permission's are being added to a PermissionCollection.
+ * loop when Permission's are being added to a PermissionCollection.  In this
+ * case external synchronization must be used.
  * 
  * PermissionCollection's are used mostly read only.
  * 
+ * Serialization has been implemented so the implementation is not
+ * tied to the serialized form, instead serialization proxy's are used.
+ * 
  * @author Peter Firmstone
  */
-public class DelegatePermission extends Permission{
+public final class DelegatePermission extends Permission{
     private static final long serialVersionUID = 1L;
+    /* Object Pool ensures that equals performs very well in collections for 
+     * optimum AccessControlContext result caching and minimises memory 
+     * consumption.
+     */
+    private static final ConcurrentMap<Permission,DelegatePermission> instances 
+	    = new ConcurrentWeakMap<Permission,DelegatePermission>();
+    /**
+     * Factory method to obtain a DelegatePermission
+     * @param p Permission to be represented.
+     * @return DelegatePermission
+     */
+    public static Permission get(Permission p){
+	DelegatePermission del = instances.get(p);
+	if ( del == null ){
+	    del = new DelegatePermission(p);
+	    DelegatePermission existed = instances.putIfAbsent(p, del);
+	    if ( existed != null ){
+		del = existed;
+	    }
+	}
+	return del;
+    }
+    
     private final Permission permission;
+    private final transient int hashCode;
+    /* The following null reference is for IDE code completion only */
+    private transient Permission perm = null;
     
-    public DelegatePermission(Permission p){
+    private DelegatePermission(Permission p){
 	super(p.getClass().toString() + " " + p.getName());
 	permission = p;
+	int hash = 5;
+	hash = 41 * hash + (this.permission != null ? this.permission.hashCode() : 0);
+	hashCode = hash;
     }
 
     @Override
@@ -87,15 +125,15 @@ public class DelegatePermission extends 
     public boolean equals(Object obj) {
 	if (obj == this) return true;
 	if (obj == null) return false;
+	if ( obj.hashCode() != hashCode ) return false;
 	if (!(obj instanceof DelegatePermission)) return false;
+	if ( obj.getClass() != this.getClass() ) return false;
 	return permission.equals(((DelegatePermission) permission).getPermission());
     }
 
     @Override
     public int hashCode() {
-	int hash = 5;
-	hash = 41 * hash + (this.permission != null ? this.permission.hashCode() : 0);
-	return hash;
+	return hashCode;
     }
 
     @Override
@@ -108,10 +146,40 @@ public class DelegatePermission extends 
 	return new DelegatePermissionCollection();
     }
     
+    /* Serialization Proxy */
+    private static class SerializationProxy implements Serializable {
+	private static final long serialVersionUID = 1L;
+	private Permission perm;
+	
+	SerializationProxy(Permission p){
+	    perm = p;
+	}
+	
+    }
+    
+    /* Serialization */
+    
+    private Object writeReplace() {
+	return new SerializationProxy(permission);
+    }
+    
+    private void readObject(ObjectInputStream in) throws InvalidObjectException{
+	throw new InvalidObjectException("Proxy required");
+    }
+    
+    private Object readResolve() {
+	// perm is the field from the Serialization proxy.
+	return get(perm);
+    }
+    
+    /* PermissionCollection */
+    
     private static class DelegatePermissionCollection extends PermissionCollection {
 	private static final long serialVersionUID = 1L;
-	private final PermissionCollection candidates;
+	private final transient PermissionCollection candidates;
 	private final Set<Permission> delegates;
+	/* IDE code completion for serialization proxy */
+	private transient Permission[] perms = null;
 	
 	DelegatePermissionCollection(){
 	    candidates = new Permissions();
@@ -143,6 +211,37 @@ public class DelegatePermission extends 
 	    return Collections.enumeration(delegates);
 	}
 	
+	/* Serialization Proxy */
+	 private static class CollectionSerializationProxy implements Serializable {
+	    private static final long serialVersionUID = 1L;
+	    private Permission[] perms;
+
+	    CollectionSerializationProxy(Set<Permission> p){
+		perms = p.toArray(new Permission[p.size()]);
+	    }
+
+	}
+
+	/* Serialization */
+
+	private Object writeReplace() {
+	    return new CollectionSerializationProxy(delegates);
+	}
+
+	private void readObject(ObjectInputStream in) throws InvalidObjectException{
+	    throw new InvalidObjectException("Proxy required");
+	}
+
+	private Object readResolve() {
+	    // perms is the field from the Serialization proxy.
+	    DelegatePermissionCollection dpc = new DelegatePermissionCollection();
+	    int l = perms.length;
+	    for (int i = 0; i < l; i++ ){
+		dpc.add(perms[i]);
+	    }
+	    return dpc;
+	}
+	
     }
 
 }

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/InternetSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/InternetSecurityManager.java?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/InternetSecurityManager.java
(original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/InternetSecurityManager.java
Wed Sep 29 21:14:40 2010
@@ -58,7 +58,7 @@ import org.apache.river.imp.util.Concurr
  */
 public class InternetSecurityManager extends SecurityManager {
 
-    private final ConcurrentMap<AccessControlContext,DelegateContextCheck> checks;
+    private final ConcurrentMap<AccessControlContext,ExecutionContextChecks> checks;
     private final ReadWriteLock revokeLock;
     private final Lock rl; // This lock is held briefly by callers of begin and end.
     private final Lock wl; // This lock is held by revocation.
@@ -89,7 +89,7 @@ public class InternetSecurityManager ext
 	/* This checks adequate permission is held */
 	super();
 	/* Previous checks */
-	checks = new ConcurrentSoftMap<AccessControlContext,DelegateContextCheck>(40);
+	checks = new ConcurrentSoftMap<AccessControlContext,ExecutionContextChecks>(40);
 	/* This lock guards revocation, although if Permission has already
 	 * been removed from the policy then this lock isn't really necessary
 	 */ 
@@ -110,9 +110,9 @@ public class InternetSecurityManager ext
 		permClasses.add(itp.next().getClass());
 	    }
 	    // Remove Permission's and AccessControlContexts from the checked cache.
-	    Iterator<DelegateContextCheck> checkIt = checks.values().iterator();
+	    Iterator<ExecutionContextChecks> checkIt = checks.values().iterator();
 	    while (checkIt.hasNext()){
-		DelegateContextCheck c = checkIt.next();
+		ExecutionContextChecks c = checkIt.next();
 		Iterator<Class> it = permClasses.iterator();
 		while (it.hasNext()){
 		    c.removePermission(it.next());
@@ -140,10 +140,10 @@ public class InternetSecurityManager ext
 	try {
 	    // checkedCache - the permission check, fast for repeated calls.    
 	    //Set<AccessControlContext> checked = checkedCache.get(perm);
-	    DelegateContextCheck checked = checks.get(executionContext);
+	    ExecutionContextChecks checked = checks.get(executionContext);
 	    if (checked == null ){
-		checked = new DelegateContextCheck(executionContext);
-		DelegateContextCheck existed = 
+		checked = new ExecutionContextChecks(executionContext);
+		ExecutionContextChecks existed = 
 			checks.putIfAbsent(executionContext, checked);
 		if (existed != null){
 		    checked = existed;
@@ -155,13 +155,13 @@ public class InternetSecurityManager ext
 	}
     }
     
-    private static class DelegateContextCheck {
+    private static class ExecutionContextChecks {
 	private final AccessControlContext acc;
 	private final ConcurrentMap<Class,Set<Permission>> passed;
 	// The context is only consulted directly for DelegatePermission
 	private final ProtectionDomain[] context;
 	
-	DelegateContextCheck(final AccessControlContext acc){
+	ExecutionContextChecks(final AccessControlContext acc){
 	    this.acc = acc;
 	    passed = new ConcurrentHashMap<Class,Set<Permission>>();
 	    /* If context is null for whatever reason, then the AccessControlContext

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
(original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
Wed Sep 29 21:14:40 2010
@@ -175,11 +175,6 @@ public class DynamicConcurrentPolicyProv
         revokeable = true;
         logger = Logger.getLogger("net.jini.security.policy");
         loggable = logger.isLoggable(Level.FINEST);
-//        drwl = new ReentrantReadWriteLock();
-//        drl = drwl.readLock();
-//        dwl = drwl.writeLock();
-//        denied = new HashSet<Denied>(30);
-//        checkDenied = false;
 	grantLock = new Object();
 	SecurityManager s = System.getSecurityManager();
 	if (s == null) {
@@ -235,14 +230,8 @@ public class DynamicConcurrentPolicyProv
         // Investigate bug 4911907, do we need to do anything more here? Is this sufficient.
         if (sysDomain == null ) System.out.println("System Domain is null");
         implies(sysDomain, new AllPermission());
-        //PermissionCollection pc = getPermissions(sysDomain);
-        //pc = PolicyUtils.toConcurrentPermissionsCopy(pc);
-        //cache.putIfAbsent(sysDomain, pc);
         ProtectionDomain own = this.getClass().getProtectionDomain();
         implies(own, new AllPermission());
-        //PermissionCollection mypc = getPermissions(own);
-        //mypc = PolicyUtils.toConcurrentPermissionsCopy(mypc);
-        //cache.putIfAbsent(own, mypc);
         new GrantPermission(new UmbrellaGrantPermission());
     }
 
@@ -263,11 +252,21 @@ public class DynamicConcurrentPolicyProv
 
     public PermissionCollection getPermissions(CodeSource codesource) {
         if (initialized == false) throw new RuntimeException("Object not initialized");
+	/* It is extremely important that dynamic grant's are not returned,
+	 * to prevent them becoming part of the static permissions held
+	 * by a ProtectionDomain.  In this case during construction of a
+	 * ProtectionDomain.  Static Permissions are irrevocable.
+	 */ 
         return basePolicy.getPermissions(codesource); 
     }
 
     public PermissionCollection getPermissions(ProtectionDomain domain) {
         if (initialized == false) throw new RuntimeException("Object not initialized");
+	/* It is extremely important that dynamic grant's are not returned,
+	 * to prevent them becoming part of the static permissions held
+	 * by a ProtectionDomain. In this case during the merge operation
+	 * performed by the ProtectionDomain.
+	 */
         return basePolicy.getPermissions(domain);
     }
     
@@ -297,19 +296,35 @@ public class DynamicConcurrentPolicyProv
         if ( pc != null ) {
             if (pc.implies(permission)) return true;           
         } else {
-	    /* We should not be calling implies on the base Policy, if
+	    /* Do not call implies on the base Policy, if
 	     * there are UnresolvedPermission's that are undergoing resolution
 	     * while another Permission within that collection is already
-	     * resolved, the Enumeration may cause a ConcurrentModificationException.
+	     * resolved, the Enumeration will cause a ConcurrentModificationException.
 	     */ 
-            PermissionCollection bpc = basePolicy.getPermissions(domain);
-           /* Don't use the underlying policy permission collection otherwise
-            * we can leak grants in to the underlying policy from our cache,
-            * this could then be merged into the PermissionDomain's permission
-            * cache negating the possiblity of revoking the permission.  This
-            * PolicyUtils method defensively copies or creates new if null.
-            */
-            pc = PolicyUtils.toConcurrentPermissionsCopy(bpc);
+	    PermissionCollection bpc = basePolicy.getPermissions(domain);
+	    /* Be mindful of static Permissions held by the 
+	     * ProtectionDomain, a Permission may be implied by the 
+	     * the combination of Permission's in the ProtectionDomain and 
+	     * the base policy, but not by either individually.
+	     * The ProtectionDomain merge is only perfomed if
+	     * ProtectionDomain.toString() is called, since this is not
+	     * guaranteed and is also expensive, the merge is performed
+	     * here.
+	     * 
+	     * Furthermore it is commonly understood that when
+	     * ProtectionDomain.implies(Permission) is called, it first checks
+	     * it's own private Permissions, then calls Policy.implies, however
+	     * this is incorrect, the Policy is checked first.
+	     */ 
+	    PermissionCollection pdpc = domain.getPermissions();
+	    PermissionCollection[] p = { pdpc, bpc };
+	   /* Don't use the underlying policy permission collection otherwise
+	    * we can leak grants in to the underlying policy from our cache,
+	    * this could then be merged into the PermissionDomain's permission
+	    * cache negating the possiblity of revoking the permission.  This
+	    * PolicyUtils method defensively copies or creates new if null.
+	    */
+            pc = PolicyUtils.mergePermissions(p);
             PermissionCollection existed = cache.putIfAbsent(domain, pc); 
             if ( existed != null ){
                 pc = existed;

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/util/PolicyUtils.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/util/PolicyUtils.java?rev=1002846&r1=1002845&r2=1002846&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/util/PolicyUtils.java
(original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/util/PolicyUtils.java
Wed Sep 29 21:14:40 2010
@@ -553,8 +553,8 @@ public class PolicyUtils {
     }
     
     /** 
-     * Copies a common-purpose homegeneous or heterogeneous PermissionCollection 
-     * to a hetergeneous PermissionCollection based on ConcurrentPermissions.
+     * Merges common-purpose homegeneous or heterogeneous PermissionCollection's 
+     * into a hetergeneous PermissionCollection based on ConcurrentPermissions.
      *
      * @param perms a PermissionCollection containing arbitrary permissions. Null
      * is permitted.
@@ -563,15 +563,18 @@ public class PolicyUtils {
      * is returned if parameter is null.
      */
     public static PermissionCollection 
-            toConcurrentPermissionsCopy(PermissionCollection perms) {
+            mergePermissions(PermissionCollection[] perms) {
         PermissionCollection pc = new ConcurrentPermissions();
-        if (perms != null) {
-            Enumeration<Permission> iter = perms.elements();
-            while ( iter.hasMoreElements() ) {
-                Permission element = iter.nextElement();
-                pc.add(element);
-            }
-        }
+	int l = perms.length;
+	for (int i = 0; i < l; i++ ){
+	    if (perms[i] != null) {
+		Enumeration<Permission> iter = perms[i].elements();
+		while ( iter.hasMoreElements() ) {
+		    Permission element = iter.nextElement();
+		    pc.add(element);
+		}
+	    }
+	}
         return pc;
     }
 



Mime
View raw message