You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2011/12/19 20:42:38 UTC
svn commit: r1220916 [1/2] - in /river/jtsk/skunk/peterConcurrentPolicy:
qa/src/com/sun/jini/test/spec/jeri/https/ src/net/jini/security/
src/net/jini/security/policy/ src/org/apache/river/api/delegates/
src/org/apache/river/api/security/ src/org/apach...
Author: peter_firmstone
Date: Mon Dec 19 19:42:37 2011
New Revision: 1220916
URL: http://svn.apache.org/viewvc?rev=1220916&view=rev
Log:
River-323 Stable concurrent DynamicPolicyProvider and ConcurrentPolicyFile with policy parser and other changes including DelegateSecurityManager with an executor to parallelise ProtectionDomain checks.
Added:
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/DynamicPermissionCollection.java (with props)
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionComparator.java (with props)
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionStringEqualityWrapper.java (with props)
river/jtsk/skunk/peterConcurrentPolicy/test/src/net/jini/security/DynamicPermissionCollectionTest.java
- copied, changed from r1213147, river/jtsk/skunk/peterConcurrentPolicy/test/src/net/jini/security/MultiReadPermissionCollectionTest.java
Modified:
river/jtsk/skunk/peterConcurrentPolicy/qa/src/com/sun/jini/test/spec/jeri/https/HttpsRobustnessTest.td
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/ConcurrentPermissions.java
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/GrantPermission.java
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionPendingResolutionCollection.java
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java
river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/PolicyFileProvider.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilderImp.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/ProtectionDomainGrant.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/NullPolicyParser.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyParser.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java
river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/Segment.java
river/jtsk/skunk/peterConcurrentPolicy/test/src/net/jini/security/ConcurrentPermissionsTest.java
river/jtsk/skunk/peterConcurrentPolicy/test/src/net/jini/security/GrantPermissionTest.java
river/jtsk/skunk/peterConcurrentPolicy/test/src/net/jini/security/MultiReadPermissionCollectionTest.java
river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/api/security/DelegateCombinerSecurityManagerTest.java
river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/impl/security/policy/util/DefaultPolicyParserTest.java
river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/impl/security/policy/util/SegmentTest.java
Modified: river/jtsk/skunk/peterConcurrentPolicy/qa/src/com/sun/jini/test/spec/jeri/https/HttpsRobustnessTest.td
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/qa/src/com/sun/jini/test/spec/jeri/https/HttpsRobustnessTest.td?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/qa/src/com/sun/jini/test/spec/jeri/https/HttpsRobustnessTest.td (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/qa/src/com/sun/jini/test/spec/jeri/https/HttpsRobustnessTest.td Mon Dec 19 19:42:37 2011
@@ -3,10 +3,10 @@ testCategories=jeri,jeri_spec
testConfiguration=<url: HttpsServerEndpointTest.config>
com.sun.jini.qa.harness.runkitserver=false
com.sun.jini.qa.harness.runjiniserver=false
-testjvmargs=\
--Xdebug,\
--Xrunjdwp:transport=dt_socket+,address=8000+,server=y+,suspend=y,\
-${testjvmargs}
+#testjvmargs=\
+#-Xdebug,\
+#-Xrunjdwp:transport=dt_socket+,address=8000+,server=y+,suspend=y,\
+#${testjvmargs}
#-Djava.security.debug=access:failure,\
#-Dnet.jini.security.policy.PolicyFileProvider.basePolicyClass=net.jini.security.policy.ConcurrentPolicyFile,\
#-Djava.security.manager=com.sun.jini.tool.ProfilingSecurityManager,\
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/ConcurrentPermissions.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/ConcurrentPermissions.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/ConcurrentPermissions.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/ConcurrentPermissions.java Mon Dec 19 19:42:37 2011
@@ -24,10 +24,14 @@ import java.security.Permission;
import java.security.PermissionCollection;
import java.security.UnresolvedPermission;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -103,17 +107,18 @@ implements Serializable {
unresolved.add(new PermissionPendingResolution((UnresolvedPermission)permission));
}
// this get saves unnecessary object creation.
- PermissionCollection pc = permsMap.get(permission.getClass());
+ Class clas = permission.getClass();
+ PermissionCollection pc = permsMap.get(clas);
if (pc == null){
- pc = new MultiReadPermissionCollection(permission);
+ pc = new DynamicPermissionCollection(null, clas);
PermissionCollection existed =
- permsMap.putIfAbsent(permission.getClass(), pc);
+ permsMap.putIfAbsent(clas, pc);
if (existed != null) {
pc = existed;
}
}
pc.add(permission);
- }
+ }
/**
* Returns true if Permission is implied for this PermissionDomain.
@@ -127,13 +132,14 @@ implements Serializable {
public boolean implies(Permission permission) {
if (permission == null){return false;}
if (allPermission == true){return true;}
- if (permission instanceof UnresolvedPermission){return false;}
- PermissionCollection pc = permsMap.get(permission.getClass()); // To stop unnecessary object creation
+ if (permission instanceof UnresolvedPermission){return false;}
+ Class clas = permission.getClass();
+ PermissionCollection pc = permsMap.get(clas); // To stop unnecessary object creation
if (pc != null && pc.implies(permission)) { return true;}
if (unresolved.awaitingResolution() == 0 ) { return false; }
if (pc == null){
- pc = new MultiReadPermissionCollection(permission); // once added it cannot be removed atomically.
- PermissionCollection existed = permsMap.putIfAbsent(permission.getClass(), pc);
+ pc = new DynamicPermissionCollection(null, clas); // once added it cannot be removed atomically.
+ PermissionCollection existed = permsMap.putIfAbsent(clas, pc);
if (existed != null) pc = existed;
}
unresolved.resolveCollection(permission, pc);
Added: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/DynamicPermissionCollection.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/DynamicPermissionCollection.java?rev=1220916&view=auto
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/DynamicPermissionCollection.java (added)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/DynamicPermissionCollection.java Mon Dec 19 19:42:37 2011
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.jini.security;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import org.apache.river.impl.util.CollectionsConcurrent;
+
+/**
+ * This homogenous PermissionCollection is designed to overcome some shortfalls with existing
+ * PermissionCollection's that block for potentially long durations
+ * on implies(), like SocketPermissionCollection.
+ *
+ * @author peter
+ */
+final class DynamicPermissionCollection extends PermissionCollection {
+ private static final long serialVersionUID = 1L;
+
+ private final Collection<Permission> perms;
+ private final Class cl;
+ private final Comparator<Permission> comp;
+
+ DynamicPermissionCollection(Comparator<Permission> c, Class cl){
+ perms = CollectionsConcurrent.multiReadCollection(new ArrayList<Permission>());
+ this.cl = cl;
+ comp = c;
+ }
+
+ private DynamicPermissionCollection(Class cl, Comparator<Permission> c){
+ this.cl = cl;
+ comp = c;
+ Collection<Permission> col = new ArrayList<Permission>();
+ perms = CollectionsConcurrent.multiReadCollection(col);
+ }
+
+ @Override
+ public void add(Permission permission) {
+ if ( ! cl.isInstance(permission))
+ throw new IllegalArgumentException("invalid permission: "+ permission);
+ if (isReadOnly()) throw new SecurityException("PermissionCollection is read only");
+ perms.add(permission);
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ if ( ! cl.isInstance(permission)) return false;
+ Permission [] p = perms.toArray(new Permission[0]); //perms.size() may change
+ if (comp != null){
+ Arrays.sort(p, comp);
+ }
+ PermissionCollection pc = permission.newPermissionCollection();
+ int l = p.length;
+ if (pc != null) {
+ for ( int i = 0; i < l ; i++ ){
+ pc.add(p[i]);
+ }
+ return pc.implies(permission);
+ }
+ for ( int i = 0; i < l ; i++ ){
+ if (p[i].implies(permission)) return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Enumeration<Permission> elements() {
+ return Collections.enumeration(perms);
+ }
+
+ private Collection<Permission> getPermissions(){
+ return perms;
+ }
+
+ private void readObject(ObjectInputStream stream) throws
+ InvalidObjectException, IOException, ClassNotFoundException {
+ throw new InvalidObjectException("Serialization Proxy required");
+ }
+
+ private Object writeReplace(){
+ PermissionCollection pc =
+ new SerializationProxy(cl, comp, this);
+ if (isReadOnly()) pc.setReadOnly();
+ return pc;
+ }
+
+ /**
+ * A serialization proxy has been provided to allow the fields in DynamicPermissionCollection
+ * to be final.
+ *
+ * The serialization proxy extends PermissionCollection for cases where
+ * it may contain a Permission that refers to it, eg a DelegatePermission.
+ * To fix the readResolve bug.
+ *
+ * This has been provided to implement Serialization, it is better to
+ * avoid serializing a PermissionCollection.
+ */
+ private final static class SerializationProxy extends PermissionCollection {
+ private static final long serialVersionUID = 1L;
+ private Permission[] permissions;
+ private Class clazz;
+ private Comparator<Permission> comp;
+ private transient DynamicPermissionCollection resolved;
+ SerializationProxy(Class cl, Comparator<Permission> c, DynamicPermissionCollection pc){
+ permissions = null;
+ clazz = cl;
+ comp = c;
+ resolved = pc;
+ }
+
+ private Object readResolve() {
+ PermissionCollection pc =
+ new DynamicPermissionCollection(clazz, comp);
+ int length = permissions.length;
+ for ( int i = 0 ; i < length ; i++){
+ pc.add(permissions[i]);
+ }
+ if (isReadOnly()) pc.setReadOnly();
+ return pc;
+ }
+
+ private void writeObject(ObjectOutputStream s) throws IOException{
+ permissions = resolved.getPermissions().toArray(new Permission[0]);
+ s.defaultWriteObject();
+ }
+
+ private void readObject(ObjectInputStream stream) throws
+ InvalidObjectException, IOException, ClassNotFoundException {
+ stream.defaultReadObject();
+ }
+
+ @Override
+ public void add(Permission permission) {
+ if ( resolved != null ){
+ resolved.add(permission);
+ return;
+ }
+ throw new IllegalStateException("unresolved after serialization");
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ if ( resolved != null ){
+ return resolved.implies(permission);
+ }
+ throw new IllegalStateException("unresolved after serialization");
+ }
+
+ @Override
+ public Enumeration<Permission> elements() {
+ if ( resolved != null ){
+ return resolved.elements();
+ }
+ throw new IllegalStateException("unresolved after serialization");
+ }
+
+ @Override
+ public void setReadOnly(){
+ super.setReadOnly();
+ resolved.setReadOnly();
+ }
+
+ }
+
+}
Propchange: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/DynamicPermissionCollection.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/GrantPermission.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/GrantPermission.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/GrantPermission.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/GrantPermission.java Mon Dec 19 19:42:37 2011
@@ -774,10 +774,10 @@ public final class GrantPermission exten
throw new SecurityException(
"can't add to read-only PermissionCollection");
}
- if (!perms.contains(p)){
+// if (!perms.contains(p)){
perms.add(p);
implier.add((GrantPermission) p);
- }
+// }
}
public synchronized Enumeration elements() {
Added: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionComparator.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionComparator.java?rev=1220916&view=auto
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionComparator.java (added)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionComparator.java Mon Dec 19 19:42:37 2011
@@ -0,0 +1,18 @@
+
+package net.jini.security;
+
+import java.security.Permission;
+import java.util.Comparator;
+
+/**
+ *
+ * @author peter
+ */
+public class PermissionComparator implements Comparator<Permission> {
+
+ @Override
+ public int compare(Permission o1, Permission o2) {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+}
Propchange: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionComparator.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionPendingResolutionCollection.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionPendingResolutionCollection.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionPendingResolutionCollection.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionPendingResolutionCollection.java Mon Dec 19 19:42:37 2011
@@ -78,8 +78,8 @@ class PermissionPendingResolutionCollect
}
}
- PermissionCollection resolveCollection(Permission target,
- PermissionCollection holder ){
+ PermissionCollection resolveCollection(Permission target, PermissionCollection holder ){
+ if (target == null || holder == null) throw new NullPointerException("target or holder cannot be null");
if (pending.get() == 0) { return holder; }
String klass = target.getClass().getName();
Collection<PermissionPendingResolution> klassMates = klasses.remove(klass);
@@ -88,9 +88,6 @@ class PermissionPendingResolutionCollect
PermissionPendingResolution element = iter.next();
Permission resolved = element.resolve(target.getClass());
if (resolved != null) {
- if (holder == null) {
- holder = new MultiReadPermissionCollection(target);
- }
holder.add(resolved);
iter.remove();
pending.decrementAndGet();
Added: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionStringEqualityWrapper.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionStringEqualityWrapper.java?rev=1220916&view=auto
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionStringEqualityWrapper.java (added)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionStringEqualityWrapper.java Mon Dec 19 19:42:37 2011
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.jini.security;
+
+import java.security.Permission;
+
+/**
+ * The only purpose of this class is to encapsulate an existing Permission that
+ * doesn't implement equals and hashCode efficiently
+ * @author peter
+ */
+public class PermissionStringEqualityWrapper extends Permission {
+ private static final long serialVersionUID = 1L;
+
+ private final Permission encapsulated;
+
+ PermissionStringEqualityWrapper(Permission p){
+ super("PermissionEqualityWrapper: " + p.toString());
+ encapsulated = p;
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( this == obj ) return true;
+ if ( obj == null ) return false;
+ if (encapsulated.toString().equals(obj.toString())) return true;
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return encapsulated.toString().hashCode();
+ }
+
+ @Override
+ public String getActions() {
+ return encapsulated.getActions();
+ }
+
+}
Propchange: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/PermissionStringEqualityWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java Mon Dec 19 19:42:37 2011
@@ -29,9 +29,11 @@ package net.jini.security.policy;
import java.io.File;
import java.lang.ref.Reference;
import java.net.URL;
+import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.CodeSource;
+import java.security.Guard;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
@@ -39,6 +41,7 @@ import java.security.Policy;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
+import java.security.SecurityPermission;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
@@ -51,6 +54,8 @@ import java.util.concurrent.ConcurrentMa
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import net.jini.security.ConcurrentPermissions;
import org.apache.river.api.security.PermissionGrant;
import org.apache.river.impl.security.policy.util.DefaultPolicyParser;
@@ -197,6 +202,9 @@ public class ConcurrentPolicyFile extend
// A specific parser for a particular policy file format.
private final PolicyParser parser;
+ private static final Guard guard =
+ new SecurityPermission("getPolicy");
+
/**
* Default constructor, equivalent to
* <code>ConcurrentPolicyFile(new DefaultPolicyParser())</code>.
@@ -210,6 +218,7 @@ public class ConcurrentPolicyFile extend
* @param dpr
*/
protected ConcurrentPolicyFile(PolicyParser dpr) throws PolicyInitializationException {
+ guard.checkGuard(null);
parser = dpr;
ReadWriteLock rwl = new ReentrantReadWriteLock();
rl = rwl.readLock();
@@ -229,8 +238,10 @@ public class ConcurrentPolicyFile extend
initialize();
ensureDependenciesResolved();
} catch (SecurityException e){
+ throw e;
+ } catch (Exception e){
throw new PolicyInitializationException("PolicyInitialization failed", e);
- }
+ }
}
private void ensureDependenciesResolved() {
@@ -247,6 +258,9 @@ public class ConcurrentPolicyFile extend
* according to the policy. The evaluated characteristics of the
* domain are it's codesource and principals; they are assumed
* to be <code>null</code> if the domain is <code>null</code>.
+ *
+ * Each PermissionCollection returned is a unique instance.
+ *
* @param pd ProtectionDomain
* @see ProtectionDomain
*/
@@ -264,10 +278,10 @@ public class ConcurrentPolicyFile extend
*/
rl.lock();
try {
- PermissionCollection perms =
- pd != null ? impliesCache.get(pd): null;
- if (perms != null) return perms;
- perms = new ConcurrentPermissions();
+// PermissionCollection perms =
+// pd != null ? impliesCache.get(pd): null;
+// if (perms != null) return perms;
+ PermissionCollection perms = new ConcurrentPermissions();
Iterator<PermissionGrant> it = grants.iterator();
while (it.hasNext()){
PermissionGrant ge = it.next();
@@ -290,7 +304,7 @@ public class ConcurrentPolicyFile extend
}
}
}
- if (pd != null) impliesCache.put(pd, perms); //Overwrite older.
+// if (pd != null) impliesCache.put(pd, perms); //Overwrite older.
return perms;
}finally{
rl.unlock();
@@ -339,7 +353,16 @@ public class ConcurrentPolicyFile extend
@Override
public boolean implies(ProtectionDomain domain, Permission permission) {
if (permission == null) throw new NullPointerException("permission not allowed to be null");
- PermissionCollection pc = getPermissions(domain);
+ PermissionCollection pc =
+ domain != null ? impliesCache.get(domain): null;
+ if (pc == null){
+ pc = getPermissions(domain);
+ if (domain != null){
+ PermissionCollection existed = impliesCache.putIfAbsent(domain, pc);
+ // Don't bother replacing pc with existed, we're not mutating
+ // so it doesn't matter.
+ }
+ }
return pc.implies(permission);
}
@@ -355,12 +378,14 @@ public class ConcurrentPolicyFile extend
if ( !wl.tryLock() ) return; // If another thread has the lock, policy is undergoing an update.
try {
initialize();
+ } catch (Exception ex) {
+ ex.printStackTrace(System.err);
} finally {
wl.unlock();
}
}
- private void initialize(){
+ private void initialize() throws Exception{
try {
Set<PermissionGrant> fresh = AccessController.doPrivileged(
new PrivilegedExceptionAction<Set<PermissionGrant>>(){
@@ -384,8 +409,10 @@ public class ConcurrentPolicyFile extend
// It's best to let a SecurityException bubble up
// in case there is a problem with our policy configuration
// or implementation.
- if ( e instanceof SecurityException ) throw (SecurityException) e;
- e.printStackTrace(System.out);
+ if ( e instanceof SecurityException ) {
+ e.printStackTrace(System.out);
+ throw (SecurityException) e;
+ }
// ignore.
}
}
@@ -401,7 +428,9 @@ public class ConcurrentPolicyFile extend
cache.clear(); // Clear the cache.
impliesCache.clear();
}catch (PrivilegedActionException e){
- e.printStackTrace(System.err);
+ Throwable t = e.getCause();
+ if ( t instanceof Exception ) throw (Exception) t;
+ throw e;
}
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java Mon Dec 19 19:42:37 2011
@@ -162,7 +162,8 @@ public class DynamicPolicyProvider exten
private static final String basePolicyClassProperty =
"net.jini.security.policy.DynamicPolicyProvider.basePolicyClass";
private static final String defaultBasePolicyClass =
- "net.jini.security.policy.PolicyFileProvider";
+ "net.jini.security.policy.ConcurrentPolicyFile";
+// "net.jini.security.policy.PolicyFileProvider";
private static final ProtectionDomain sysDomain =
AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
@@ -457,7 +458,7 @@ Put the policy providers and all referen
* container.
*
* I've since found PolicyPermission's to be unnecessary, the
- * ProtectionDomain only merges the permissions for toString()
+ * ProtectionDomain only temporarily merges the permissions for toString()
* not policy decisions.
*
* TODO: Remove PolicyPermission's
@@ -519,45 +520,47 @@ Put the policy providers and all referen
// First check our cache if the basePolicy is not dynamic.
PermissionCollection pc = domain != null? cache.get(domain): null;
if ( pc != null ) {
- if (pc.implies(permission)) return true;
- } else {
- /* 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 will cause a ConcurrentModificationException.
- */
- 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 underlying policy
- * performs the merge.
- *
- * 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.asConcurrent(bpc);
- PermissionCollection existed =
- domain != null ? cache.putIfAbsent(domain, pc): null;
- if ( existed != null ){
- pc = existed;
- }
- expandUmbrella(pc); // We need to avoid using PolicyFileProvider as grants from it are not revokable.
- if ( pc.implies(permission)) return true;
- }
+ if (pc.implies(permission)) return true;
+ }
+ /* 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 will cause a ConcurrentModificationException.
+ */
+ 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 underlying policy
+ * performs the merge.
+ *
+ * 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.asConcurrent(bpc);
+ /* Don't place it in the cache half finished or check it yet since
+ * mutations are blocking */
+// PermissionCollection existed =
+// domain != null ? cache.putIfAbsent(domain, pc): null;
+// if ( existed != null ){
+// pc = existed;
+// }
+// expandUmbrella(pc); // We need to avoid using PolicyFileProvider as grants from it are not revokable.
+// if ( pc.implies(permission)) return true;
+
// Once we get to here pc is definitely not null and we have the
// copy referenced in the cache.
// if (loggable){
@@ -585,10 +588,10 @@ Put the policy providers and all referen
// if (loggable) {
// logger.log(Level.FINEST, "Grants: " + dynamicallyGrantedPermissions.toString());
// }
- if (dynamicallyGrantedPermissions.isEmpty()) {
- // We have no dynamic grants
- return false;
- }
+// if (dynamicallyGrantedPermissions.isEmpty()) {
+// // We have no dynamic grants
+// return false;
+// }
Iterator<Permission> dgpi = dynamicallyGrantedPermissions.iterator();
while (dgpi.hasNext()){
pc.add(dgpi.next());
@@ -598,10 +601,15 @@ Put the policy providers and all referen
// if (loggable) {
// logger.log(Level.FINEST, "PermissionCollection: " + pc.toString());
// }
- // We have added dynamic grants, lets expand them
- // But UmbrellaGrant's are to enable easy dynamic GrantPermission's?
+ // We have added dynamic grants, lets expand any UmbrellaGrant's
expandUmbrella(pc);
- return pc.implies(permission);
+ if ( pc.implies(permission) ){
+ // The cache is replaced rather than updated, to avoid umbrella grants
+ // causing GrantPermission recursion.
+ if (domain != null ) cache.replace(domain, pc);
+ return true;
+ }
+ return false;
}
/**
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/PolicyFileProvider.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/PolicyFileProvider.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/PolicyFileProvider.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/PolicyFileProvider.java Mon Dec 19 19:42:37 2011
@@ -26,6 +26,8 @@ import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.security.Security;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
@@ -276,7 +278,8 @@ public class PolicyFileProvider extends
static void expandUmbrella(PermissionCollection pc) {
if (pc.implies(umbrella)) {
- Set<Permission> perms = new HashSet<Permission>(120);
+ // Don't use Set, avoid calling equals and hashCode on SocketPermission.
+ Collection<Permission> perms = new ArrayList<Permission>(120);
Enumeration<Permission> e = pc.elements();
while (e.hasMoreElements()){
Permission p = e.nextElement();
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java Mon Dec 19 19:42:37 2011
@@ -96,7 +96,10 @@ public final class DelegatePermission ex
Ref.WEAK, Ref.SOFT
);
/**
- * Factory method to obtain a DelegatePermission
+ * Factory method to obtain a DelegatePermission, this is essential to
+ * overcome broken equals contract in some jvm Permission implementations
+ * like SocketPermission and allow caching.
+ *
* @param p Permission to be represented.
* @return DelegatePermission
*/
@@ -113,14 +116,14 @@ public final class DelegatePermission ex
}
private final Permission permission;
- private final transient int hashCode;
+// private final transient int hashCode;
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;
+// int hash = 5;
+// hash = 41 * hash + (this.permission != null ? this.permission.hashCode() : 0);
+// hashCode = hash;
}
public void checkGuard(Object object) throws SecurityException {
@@ -129,6 +132,7 @@ public final class DelegatePermission ex
}
@Override
+ // This is implemented but never called.
public boolean implies(Permission permission) {
if (permission == null) return false;
if (!(permission instanceof DelegatePermission)) return false;
@@ -140,19 +144,24 @@ public final class DelegatePermission ex
return permission;
}
+ // Don't override equals so all Delegates can be used in Collections
+ // including those containing SocketPermission.
@Override
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());
- }
+ return obj == this;
+// 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() {
- return hashCode;
+// return hashCode;
+ // Not in constructor so we don't let this escape.
+ return System.identityHashCode(this);
}
@Override
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java Mon Dec 19 19:42:37 2011
@@ -104,10 +104,13 @@ class CodeSourceSetGrant extends Certifi
// sun.security.provider.PolicyFile compatibility for null CodeSource.
// see com.sun.jini.test.spec.policyprovider.dynamicPolicyProvider.GrantPrincipal test.
if ( codeSource == null ) return false;
- if ( cs == null || nullCS.equals(cs)) return true;
+ if ( cs == null || cs.isEmpty()) return true;
+ codeSource = normalizeCodeSource(codeSource);
Iterator<CodeSource> it = cs.iterator();
while (it.hasNext()){
- if (it.next().implies(normalizeCodeSource(codeSource))) return true;
+ CodeSource c = it.next();
+ if (c == null ) return true;
+ if (c.implies(codeSource)) return true;
}
return false;
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java Mon Dec 19 19:42:37 2011
@@ -18,8 +18,7 @@
package org.apache.river.api.security;
-import java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
+import java.net.SocketPermission;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.DomainCombiner;
@@ -31,9 +30,18 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import org.apache.river.api.delegates.DelegatePermission;
import org.apache.river.impl.util.CollectionsConcurrent;
import org.apache.river.impl.util.RC;
@@ -56,6 +64,7 @@ extends SecurityManager implements Deleg
private final ConcurrentMap<AccessControlContext, Set<Permission>> checked;
private final Guard g;
private final Action action;
+ private final ExecutorService executor;
public DelegateCombinerSecurityManager(){
super();
@@ -71,6 +80,10 @@ extends SecurityManager implements Deleg
checked = RC.concurrentMap(refmap, Ref.SOFT, Ref.STRONG);
g = new RevokePermission();
action = new Action();
+ double blocking_coefficient = 0.8; // 0 CPU intensive to 0.9 IO intensive
+ int numberOfCores = Runtime.getRuntime().availableProcessors();
+ int poolSize = (int) (numberOfCores / ( 1 - blocking_coefficient));
+ executor = Executors.newFixedThreadPool(poolSize);
}
@Override
@@ -97,7 +110,6 @@ extends SecurityManager implements Deleg
// we have sufficient privilege.
delegateContext = AccessController.doPrivileged(
new PrivilegedAction<AccessControlContext>(){
-
public AccessControlContext run() {
return new AccessControlContext(finalExecutionContext, dc);
}
@@ -119,6 +131,8 @@ extends SecurityManager implements Deleg
// Normal execution, same as SecurityManager.
executionContext.checkPermission(perm);
// If we get to here, no exceptions were thrown, we have permission.
+ // Don't cache SocketPermission.
+ if (perm instanceof SocketPermission) return;
checkedPerms.add(perm);
}
@@ -164,13 +178,8 @@ extends SecurityManager implements Deleg
}
private class DelegateDomainCombiner implements DomainCombiner {
- // Cache the DelegateProtectionDomain's we don't want to
- // create any more than abolutely necessary.
- private final ConcurrentMap<ProtectionDomain,DelegateProtectionDomain> cache;
+
private DelegateDomainCombiner (){
- ConcurrentMap<Referrer<ProtectionDomain>,Referrer<DelegateProtectionDomain>> internal =
- new ConcurrentHashMap<Referrer<ProtectionDomain>,Referrer<DelegateProtectionDomain>>(120);
- cache = RC.concurrentMap(internal, Ref.WEAK_IDENTITY, Ref.STRONG);
}
public ProtectionDomain[] combine(ProtectionDomain[] currentDomains, ProtectionDomain[] assignedDomains) {
@@ -178,7 +187,7 @@ extends SecurityManager implements Deleg
* are from the Context that the SecurityManager has been asked
* to check.
*
- * This code wraps each ProtectionDomain in a DelegateProtectionDomain
+ * This code wraps assignedDomains in a DelegateProtectionDomain
* to ensure we check for the DelegatePermission or it's candidate
* Permission.
*
@@ -186,23 +195,13 @@ extends SecurityManager implements Deleg
* we just created moments earlier, but with the context returned
* by this DomainCombiner.
*/
- int l = assignedDomains.length;
- // I don't believe it's safe to re-use the existing array yet.
+ // I don't believe it's safe to modify the existing array.
// I think it's the same context array from the original AccessControlContext
// we've duplicated, so modifing it would risk contaminating the
// call stack context.
- DelegateProtectionDomain[] delegated = new DelegateProtectionDomain[l];
- for ( int i = 0; i < l ;i++ ){
- delegated[i] = cache.get(assignedDomains[i]);
- if (delegated[i] == null){
- delegated[i] = new DelegateProtectionDomain(assignedDomains[i]);
- DelegateProtectionDomain existed =
- cache.putIfAbsent(assignedDomains[i], delegated[i]);
- if (existed != null){
- delegated[i] = existed;
- }
- }
- }
+ // No defensive copying is performed.
+ DelegateProtectionDomain[] delegated = new DelegateProtectionDomain[1];
+ delegated[0] = new DelegateProtectionDomain(assignedDomains);
return delegated;
}
}
@@ -212,50 +211,109 @@ extends SecurityManager implements Deleg
* a permission check. The policy will never see it.
*/
private class DelegateProtectionDomain extends ProtectionDomain {
- // weakly reference the pd, so it doesn't prevent the cache key
- // from being garbage collected.
- private final WeakReference<ProtectionDomain> pd;
+ // Context from AccessControlContext.
+ private final ProtectionDomain[] context;
- DelegateProtectionDomain(ProtectionDomain pd){
+ DelegateProtectionDomain(ProtectionDomain[] context){
// Use static domain so we don't strong reference to ClassLoader
// which has a strong reference to ProtectionDomain.
- super(pd.getCodeSource(),pd.getPermissions());
- this.pd = new WeakReference<ProtectionDomain>(pd);
+ super(null, null);
+ this.context = context;
}
@Override
public boolean implies(Permission perm) {
- ProtectionDomain pd = this.pd.get();
- if (pd != null){
- if (pd.implies(perm)) {
+ Thread currentThread = Thread.currentThread();
+ int l = context.length;
+ CountDownLatch latch = new CountDownLatch(l);
+ List<Future<Boolean>> resultList = null;
+ Collection<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>(l);
+ for ( int i = 0; i < l; i++ ){
+ tasks.add(new PermissionCheck(context[i], perm, latch, currentThread));
+ }
+ try {
+ // We can change either call to add a timeout.
+ resultList = executor.invokeAll(tasks);
+ latch.await();
+ Iterator<Future<Boolean>> it = resultList.iterator();
+ try {
+ while (it.hasNext()){
+ Boolean result = it.next().get();
+ if (result.equals(Boolean.FALSE)) {
+ return false;
+ }
+ }
return true;
+ } catch (ExecutionException ex) {
+ // This should never happen, unless a runtime exception occurs.
+ Logger.getLogger(DelegateCombinerSecurityManager.class.getName()).log(Level.SEVERE, null, ex);
}
- if (perm instanceof DelegatePermission ){
- Permission candidate = ((DelegatePermission)perm).getPermission();
- if (pd.implies(candidate)){
- return true;
- }
+ } catch (InterruptedException ex) {
+ // This is normal, it just means one task returned false.
+ // Swallow the interrupt, because it will likely be caused by
+ // a negative result, in which case a SecurityException will
+ // be thrown anyway.
+ Iterator<Future<Boolean>> it = resultList.iterator();
+ while (it.hasNext()){
+ it.next().cancel(true);
}
+ Logger.getLogger(DelegateCombinerSecurityManager.class.getName()).log(Level.FINEST, null, ex);
}
return false;
}
@Override
public String toString(){
- // When pd.toString() is called, it will merge the policy permissions
- // with those in pd if non static, which means the Permissions will no longer
- // be correct in the superclass. This won't affect implies, since it
- // calls the policy anyway, where the permissions have been combined
- // by the policy.
- // It will affect getPermissions() however this won't be used.
-// StringBuilder sb = new StringBuilder(200);
-// return sb.append("DelegateProtectionDomain\n").append(pd.toString()).toString();
- // I don't think the output should be any different from standard.
- ProtectionDomain pd = this.pd.get();
- if (pd != null){
- return pd.toString();
+ /* Unfortunately we don't know exactly which domain has failed
+ * in fact, multiple domains may fail the permission check since
+ * they are executed concurrently, for that reason, we'll print
+ * all failed domains on the stack.
+ */
+ StringBuilder sb = new StringBuilder(800);
+ sb.append("DomainCombinerSecurityManager full stack: \n");
+ int l = context.length;
+ for (int i = 0; i < l; i++ ){
+ sb.append(context[i].toString());
+ }
+ return sb.toString();
+ }
+
+ }
+
+ /**
+ * Immutable callable task, discarded immediately after use.
+ */
+ private class PermissionCheck implements Callable<Boolean> {
+ private final ProtectionDomain pd;
+ private final Permission p;
+ private final CountDownLatch latch;
+ private final Thread caller;
+
+ PermissionCheck(ProtectionDomain pd, Permission p, CountDownLatch c, Thread caller){
+ if (pd == null || p == null) throw new NullPointerException();
+ this.pd = pd;
+ this.p = p;
+ latch = c;
+ this.caller = caller;
+ }
+
+ public Boolean call() throws Exception {
+ Boolean result = Boolean.FALSE;
+ if (pd.implies(p)) result = Boolean.TRUE;
+ if (p instanceof DelegatePermission ){
+ Permission candidate = ((DelegatePermission)p).getPermission();
+ if (pd.implies(candidate)){
+ result = Boolean.TRUE;
+ }
+ }
+ // If we need to check for any Permission that we have substituted
+ // for a standard jvm permission, getPermissions and convert,
+ // then test here for static ProtectionDomain's.
+ if (Boolean.FALSE.equals(result)) {
+ caller.interrupt();
}
- return "";
+ latch.countDown();
+ return result;
}
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilderImp.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilderImp.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilderImp.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilderImp.java Mon Dec 19 19:42:37 2011
@@ -180,7 +180,7 @@ class PermissionGrantBuilderImp extends
return new ClassLoaderGrant(domain, principals, permissions );
case CODESOURCE:
if (hasMultipleCodeSources) {
- if (csources == null && multipleCodeSources != null) csources =
+ if (multipleCodeSources != null) csources =
multipleCodeSources.toArray(new CodeSource[multipleCodeSources.size()]);
return new CodeSourceSetGrant(csources, principals, permissions, inverse);
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/ProtectionDomainGrant.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/ProtectionDomainGrant.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/ProtectionDomainGrant.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/ProtectionDomainGrant.java Mon Dec 19 19:42:37 2011
@@ -128,7 +128,11 @@ class ProtectionDomainGrant extends Prin
if (domain == null ) return true; // Dynamic grant compatibility
if (cl == null) return false;
if (domain.get() == null ) return false; // is void.
- return domain.get().getClassLoader().equals(cl); // pd not null
+ ClassLoader thisloader = domain.get().getClassLoader(); // pd not null
+ if (thisloader != null){
+ return thisloader.equals(cl);
+ }
+ return false; // System loader if null.
}
// This is here for revoke and for new ProtectionDomain's created by the
// DomainCombiner such as those in the SubjectDomainCombiner.
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java Mon Dec 19 19:42:37 2011
@@ -23,6 +23,7 @@
package org.apache.river.impl.security.policy.util;
import java.io.BufferedReader;
+import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
@@ -38,13 +39,17 @@ import java.security.Permission;
import java.security.Principal;
import java.security.UnresolvedPermission;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
+import java.util.SortedSet;
import java.util.StringTokenizer;
+import java.util.TreeSet;
import org.apache.river.api.security.PermissionGrant;
import org.apache.river.api.security.PermissionGrantBuilder;
@@ -52,6 +57,7 @@ import org.apache.river.impl.security.po
import org.apache.river.impl.security.policy.util.DefaultPolicyScanner.KeystoreEntry;
import org.apache.river.impl.security.policy.util.DefaultPolicyScanner.PermissionEntry;
import org.apache.river.impl.security.policy.util.DefaultPolicyScanner.PrincipalEntry;
+import org.apache.river.impl.security.policy.util.PolicyUtils.ExpansionFailedException;
/**
@@ -132,8 +138,7 @@ public class DefaultPolicyParser impleme
Collection<PermissionGrant> result = new HashSet<PermissionGrant>();
for (Iterator<GrantEntry> iter = grantEntries.iterator(); iter.hasNext();) {
- DefaultPolicyScanner.GrantEntry ge = iter
- .next();
+ DefaultPolicyScanner.GrantEntry ge = iter.next();
try {
PermissionGrant pe = resolveGrant(ge, ks, system, resolve);
if (!pe.isVoid()) {
@@ -145,7 +150,7 @@ public class DefaultPolicyParser impleme
e.printStackTrace(System.out);
}
}
-
+
return result;
}
@@ -192,14 +197,27 @@ public class DefaultPolicyParser impleme
* CodeSource.
*/
URL codebase = null;
+ List<URL> codebases = new ArrayList<URL>();
Certificate[] signers = null;
- Set<Principal>principals = new HashSet<Principal>();
- Set<Permission>permissions = new HashSet<Permission>();
- if (ge.getCodebase(null) != null) {
- codebase = new URL(resolve ? PolicyUtils.expandURL(ge.getCodebase(system),
- system) : ge.getCodebase(null));
+ Set<Principal> principals = new HashSet<Principal>();
+ Set<Permission> permissions = new HashSet<Permission>();
+ String cb = ge.getCodebase(null);
+ if ( cb != null ) {
+ if ( resolve ) {
+ try {
+ Collection<String> cbstr = expandURLs(cb, system);
+ Iterator<String> it = cbstr.iterator();
+ while (it.hasNext()){
+ codebases.add(new URL(it.next()));
+ }
+ } catch (ExpansionFailedException e) {
+ codebase = new URL(cb);
+ }
+ } else {
+ codebase = new URL(cb);
+ }
}
- if (ge.getSigners() != null) {
+ if ( ge.getSigners() != null) {
if (resolve) {
ge.setSigners(PolicyUtils.expand(ge.getSigners(), system));
}
@@ -234,12 +252,48 @@ public class DefaultPolicyParser impleme
}
}
PermissionGrantBuilder pgb = PermissionGrantBuilder.newBuilder();
- return pgb.codeSource(new CodeSource(codebase, signers))
- .principals(principals.toArray(new Principal[principals.size()]))
- .permissions(permissions.toArray(new Permission[permissions.size()]))
- .context(PermissionGrantBuilder.CODESOURCE)
- .build();
+ if ( codebase != null ) {
+ pgb.codeSource(new CodeSource(codebase, signers));
+ } else if (codebases.size() == 1) {
+ pgb.codeSource(new CodeSource(codebases.get(0), signers));
+ } else if (codebases.size() > 1 ){
+ pgb.multipleCodeSources();
+ Iterator<URL> iter = codebases.iterator();
+ while (iter.hasNext()){
+ pgb.codeSource(new CodeSource(iter.next(), signers));
+ }
+ }
+ return pgb
+ .principals(principals.toArray(new Principal[principals.size()]))
+ .permissions(permissions.toArray(new Permission[permissions.size()]))
+ .context(PermissionGrantBuilder.CODESOURCE)
+ .build();
+ }
+
+ Segment segment(String s, Properties p) throws ExpansionFailedException{
+ final String ARRAY_START_MARK = "${{";
+ final String ARRAY_END_MARK = "}}";
+ final String ARRAY_SEPARATOR = ":";
+ final String START_MARK = "${"; //$NON-NLS-1$
+ final String END_MARK = "}"; //$NON-NLS-1$
+ Segment primary = new Segment(s, null);
+ primary.divideAndReplace(ARRAY_START_MARK, ARRAY_END_MARK,
+ ARRAY_SEPARATOR, p);
+ primary.divideAndReplace(START_MARK, END_MARK, null, p);
+ // Repeat twice for nested properties
+ primary.divideAndReplace(START_MARK, END_MARK, null, p);
+ primary.divideAndReplace(START_MARK, END_MARK, null, p);
+ return primary;
}
+
+ Collection<String> expandURLs(String s, Properties p) throws ExpansionFailedException{
+ Segment seg = segment(s,p);
+ Collection<String> urls = new ArrayList<String>();
+ while ( seg.hasNext() ){
+ urls.add(seg.next().replace(File.separatorChar, '/'));
+ }
+ return urls;
+ }
/**
* Translates PermissionEntry token to Permission object.
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java Mon Dec 19 19:42:37 2011
@@ -27,16 +27,9 @@ import java.io.Reader;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Properties;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.river.impl.security.policy.util.PolicyUtils.ExpansionFailedException;
@@ -79,7 +72,7 @@ import org.apache.river.impl.security.po
* @see org.apache.harmony.security.fortress.DefaultPolicyParser
*/
public class DefaultPolicyScanner {
-
+
/**
* Specific exception class to signal policy file syntax error.
*
@@ -405,228 +398,12 @@ public class DefaultPolicyScanner {
composeStatus(st)));
}
- private SortedSet<Segment> segment(String s, Properties p) throws ExpansionFailedException{
- final String ARRAY_START_MARK = "${{";
- final String ARRAY_END_MARK = "}}";
- final String ARRAY_SEPARATOR = ":";
- final String START_MARK = "${"; //$NON-NLS-1$
- final String END_MARK = "}"; //$NON-NLS-1$
- SortedSet<Segment> stringSegments = new TreeSet<Segment>();
- Segment primary = new Segment(s, null);
- Collection<Segment> segments
- = primary.divideAndReplace(ARRAY_START_MARK, ARRAY_END_MARK,
- ARRAY_SEPARATOR, p);
- Iterator<Segment> i = segments.iterator();
- while (i.hasNext()){
- stringSegments.addAll(i.next().divideAndReplace(
- START_MARK, END_MARK, null, p));
- }
- return stringSegments;
- }
-
- protected final Collection<String> expandPolicyProperties(String s, Properties p){
- Collection<StringBuilder> cache = new ArrayList<StringBuilder>();
- final String ARRAY_START_MARK = "${{";
- final String ARRAY_END_MARK = "}}";
- final String ARRAY_SEPARATOR = ":";
- final String START_MARK = "${"; //$NON-NLS-1$
- final String END_MARK = "}"; //$NON-NLS-1$
- // Check for array's first, for every array, we must clone and create
- // a new string, with the array substituted. If there are multiple
- // arrays, then we must clone for each.
- // It would be more efficient to use a pattern match to avoid
- // mutiple processing.
- Collection<Key> keys = getKeys(p, s, ARRAY_START_MARK, ARRAY_END_MARK);
- Iterator<Key> i = keys.iterator();
- int uniqueStrings = 1;
- while (i.hasNext()){
- Key k = i.next();
- while (k != null){
- short valueCount = k.valueCount(ARRAY_SEPARATOR);
- uniqueStrings = valueCount * uniqueStrings;
- }
- }
- if ( uniqueStrings < 0 ) throw new IllegalStateException("integer overflow");
- Collection<String> result = new ArrayList<String>(uniqueStrings);
- // Now we must replace each key with a value such that we have
- // X unique stings where:
- // X = key1.valueCount() * key2.valueCount() ... * keyn.valueCount()
- Key[] keyArray = keys.toArray(new Key[keys.size()]);
- StringBuilder sb = new StringBuilder(); // Key builder
- int lastKey = keyArray.length;
- for ( int u = 0; u < uniqueStrings ; u++ ){
- if ( lastKey > 1){
- for ( int k = 0; k < lastKey; k++ ){
- if (keyArray[k] == null) continue;
- // Key builder (for building keys) we use for matching.
- sb.append(ARRAY_START_MARK)
- .append(keyArray[k].toString())
- .append(ARRAY_END_MARK);
- String primaryKey = sb.toString();
- sb.delete(0, sb.length()); // Clear the builder for next use.
- Collection<String> values =
- keyArray[k].expandValues(ARRAY_SEPARATOR);
- String[] value = values.toArray(new String[values.size()]);
- int lastValue = value.length;
- for ( int v = 0; v < lastValue; v++ ){
- if (value[v] == null) continue;
- // Now replace all keys in the string with a value.
- // for the primary key's value, do this until we have
- // exhausted the other key's values.
- // Add each new string to the cache.
- StringBuilder line = new StringBuilder(64 + s.length()); //extra space for values.
- boolean primaryKeyIsReplaced = false;
- line.append(s);
- for ( int kN = 0; kN < lastKey; kN++){
- if ( kN == k || keyArray[kN] == null ) continue; // ignore self.
- sb.append(ARRAY_START_MARK)
- .append(keyArray[kN].toString())
- .append(ARRAY_END_MARK);
- String secondaryKey = sb.toString();
- sb.delete(0, sb.length()); // Clear the builder for next use.
- // We are now ready to create our unique string.
- // each key value must be combined with each
- // value from each other key.
- Iterator<String> kNvalues = keyArray[kN]
- .expandValues(ARRAY_SEPARATOR).iterator();
- while (kNvalues.hasNext()){
- // In all honesty, we have a problem now if
- // there is more than one identical key, how
- // do we ensure we replace only the correct
- // position in the string?
- // Ans: Replace them in order of occurance in the
- // key array.
- if (k < kN){ // replace k first.
- // We must create a new line for every
- // value. the above iterator won't work.
- } else { // replace kN first.
-
- }
- }
- }
- }
- }
- }
- }
- return result;
- }
- protected static Collection<String> expandStringValues(String value, String separator){
- Collection<String> result = new ArrayList<String>();
- StringBuilder b = new StringBuilder(value);
- int sep = b.indexOf(separator);
- final int start = 0;
- while (sep > 0){
- String sub = b.substring(start, sep + 1);
- b.delete(start, sep +1);
- sep = b.indexOf(separator);
- result.add(sub);
- }
- return result;
- }
-
- protected final Collection<Key> getKeys(Properties p, String keys,
- String START_MARK, String END_MARK)
- {
- Collection<Key> result = new ArrayList<Key>();
- final int START_OFFSET = START_MARK.length();
- final int END_OFFSET = END_MARK.length();
- int start = keys.indexOf(START_MARK);
- while (start >= 0){
- int end = keys.indexOf(END_MARK, start);
- if (end >= 0) {
- String key = (keys.substring(start + START_OFFSET, end));
- result.add(new Key(p,key));
- start = keys.indexOf(START_MARK, end + END_OFFSET);
- }
- }
- return result;
- }
-
-
-// protected final String getNextKey(String s, String START_MARK,
-// String END_MARK, int from)
-// {
-// final int START_OFFSET = START_MARK.length();
-// int start = s.indexOf(START_MARK, from);
-// if (start >= 0){
-// int end = s.indexOf(END_MARK , start + START_OFFSET);
-// if (end >= 0) {
-// String key = s.substring(start + START_OFFSET, end);
-// return key;
-// }
-// }
-// return "";
-// }
- /*
- * A string is made up of string segments and key's, if we create an array
- * which has string segments and keys represented by array elements, we
- * can use a string builder for every possible combination and simply build
- * each possible combination. Also by finding the array key's first,
- * we can then find simpler key's that don't contain arrays in the segment
- * and replace those immediately.
- *
- * The array key's
- */
- public final static class Key {
-
- public static final Key nullKey = new Key();
- private final String key;
- private final String value;
- private Collection<String> values;
- private String separator;
-
- public Key(Properties p, String key){
- this.key = key;
- String v = p.getProperty(key);
- value = v == null ? "" : v;
- values = null;
- separator = null;
- }
-
- private Key(){
- key = "";
- value = "";
- }
-
- public final String getValue(){
- return value;
- }
-
- public short valueCount(String separator){
- short result;
- if (values != null
- && this.separator != null
- && this.separator.equals(separator)
- ) result = (short) values.size();
- values = expandStringValues(value, separator);
- result = (short) values.size();
- if (result < 0) throw new IllegalStateException("short overflow");
- return result;
- }
-
- public Collection<String> expandValues(String separator){
- if (values != null
- && this.separator != null
- && this.separator.equals(separator)
- ) return values;
- values = expandStringValues(value, separator);
- return values;
- }
-
- @Override
- public final String toString(){
- return key;
- }
-
- public final boolean isNull(){
- if (key.isEmpty()) return true;
- return false;
- }
- }
+
+
/**
* Compound token representing <i>keystore </i> clause. See policy format
@@ -646,6 +423,17 @@ public class DefaultPolicyScanner {
* The typename part of keystore clause.
*/
public String type;
+
+ public String toString(){
+ String newline = "\n";
+ int l = url == null? 0 : url.length();
+ l = l + type == null? 0 : type.length();
+ l = l + 4;
+ StringBuffer sb = new StringBuffer(l);
+ if ( url != null ) sb.append(url).append(newline);
+ if ( type != null ) sb.append(type).append(newline);
+ return sb.toString();
+ }
}
/**
@@ -683,6 +471,17 @@ public class DefaultPolicyScanner {
* Collection of PermissionEntries of grant clause.
*/
private Collection<PermissionEntry> permissions;
+
+ public String toString(){
+ String newline = "\n";
+ StringBuffer sb = new StringBuffer(400);
+ if (signers != null ) sb.append(signers).append(newline);
+ if (codebase != null ) sb.append(codebase).append(newline);
+ if (codebases != null ) sb.append(codebases).append(newline);
+ if (principals != null ) sb.append(principals).append(newline);
+ if (permissions != null ) sb.append(permissions).append(newline);
+ return sb.toString();
+ }
/**
* Adds specified element to the <code>principals</code> collection.
@@ -717,7 +516,8 @@ public class DefaultPolicyScanner {
try {
return PolicyUtils.expand(codebase, system);
} catch (ExpansionFailedException ex) {
- Logger.getLogger(DefaultPolicyScanner.class.getName()).log(Level.SEVERE, null, ex);
+// Logger.getLogger(DefaultPolicyScanner.class.getName()).log(Level.SEVERE, null, ex);
+ ex.printStackTrace(System.err);
return codebase;
}
}
@@ -731,16 +531,6 @@ public class DefaultPolicyScanner {
}
/**
- * Check this first? Or just get this and iterate?
- * @return the codebases
- */
- public Collection<String> getCodebases(Properties system) {
-
-
- return codebases;
- }
-
- /**
* @return the principals
*/
public Collection<PrincipalEntry> getPrincipals(Properties system) {
@@ -796,6 +586,17 @@ public class DefaultPolicyScanner {
* The name part of principal clause.
*/
public String name;
+
+ public String toString(){
+ String newline = "\n";
+ int l = klass == null? 0 : klass.length();
+ l = l + name == null? 0 : name.length();
+ l = l + 4;
+ StringBuffer sb = new StringBuffer(l);
+ if ( klass != null ) sb.append(klass).append(newline);
+ if ( name != null ) sb.append(name).append(newline);
+ return sb.toString();
+ }
}
/**
@@ -828,5 +629,20 @@ public class DefaultPolicyScanner {
* of certificate aliases.
*/
public String signers;
+
+ public String toString(){
+ String endline = "\n";
+ int l = klass == null ? 0 : klass.length();
+ l = l + name == null? 0 : name.length();
+ l = l + actions == null? 0 : actions.length();
+ l = l + signers == null? 0 : signers.length();
+ l = l + 8;
+ StringBuffer sb = new StringBuffer(l);
+ if ( klass != null ) sb.append(klass).append(endline);
+ if ( name != null ) sb.append(name).append(endline);
+ if ( actions != null ) sb.append(actions).append(endline);
+ if ( signers != null ) sb.append(signers).append(endline);
+ return sb.toString();
+ }
}
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/NullPolicyParser.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/NullPolicyParser.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/NullPolicyParser.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/NullPolicyParser.java Mon Dec 19 19:42:37 2011
@@ -1,6 +1,20 @@
/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
*/
package org.apache.river.impl.security.policy.util;
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyParser.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyParser.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyParser.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyParser.java Mon Dec 19 19:42:37 2011
@@ -24,7 +24,8 @@ import java.util.Properties;
import org.apache.river.api.security.PermissionGrant;
/**
- * Based on the Apache Harmony interface of the same name.
+ * Based on the Apache Harmony interface of the same name, although not compatible.
+ *
* @author Peter Firmstone
*/
public interface PolicyParser {
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java?rev=1220916&r1=1220915&r2=1220916&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java Mon Dec 19 19:42:37 2011
@@ -484,6 +484,7 @@ public class PolicyUtils {
*/
public static PermissionCollection
asConcurrent(PermissionCollection perms) {
+ if (perms instanceof ConcurrentPermissions ) return perms;
PermissionCollection pc = new ConcurrentPermissions();
if ( perms != null){
Enumeration<Permission> iter = perms.elements();