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 2010/05/11 22:37:49 UTC
svn commit: r943285 [2/3] - in /incubator/river/jtsk/trunk: ./ qa/
qa/harness/trust/ qa/src/com/sun/jini/qa/harness/
qa/src/com/sun/jini/qa/resources/ src/com/sun/jini/tool/
src/net/jini/core/lookup/ src/net/jini/discovery/ src/net/jini/lease/
src/net/...
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/ConcurrentPolicyFile.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/ConcurrentPolicyFile.java?rev=943285&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/ConcurrentPolicyFile.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/ConcurrentPolicyFile.java Tue May 11 20:37:47 2010
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+
+ /**
+ * Default Policy implementation taken from Apache Harmony, refactored for
+ * concurrency.
+ *
+ * @author Alexey V. Varlamov
+ * @author Peter Firmstone
+ * @version $Revision$
+ */
+
+package org.apache.river.imp.security.policy.se;
+
+import java.io.File;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+import org.apache.river.imp.security.policy.util.DefaultPolicyParser;
+import org.apache.river.imp.security.policy.util.PolicyEntry;
+import org.apache.river.imp.security.policy.util.PolicyParser;
+import org.apache.river.imp.security.policy.util.PolicyUtils;
+import org.apache.river.imp.util.ConcurrentWeakIdentityMap;
+
+
+/**
+ * Concurrent Policy implementation based on policy configuration files,
+ * it is intended to provide concurrent implies() for greatly improved
+ * throughput at the expense of memory usage.
+ *
+ * Set the following system properties to use this Policy instead of the
+ * built in Java sun.security.provider.PolicyFile:
+ *
+ * net.jini.security.policy.PolicyFileProvider.basePolicyClass =
+ * org.apache.river.security.concurrent.ConcurrentPolicyFile
+ *
+ *
+ * This
+ * implementation recognizes text files, consisting of clauses with the
+ * following syntax:
+ *
+ * <pre>
+ * keystore "some_keystore_url" [, "keystore_type"];
+ * </pre>
+ <pre>
+ * grant [SignedBy "signer_names"] [, CodeBase "URL"]
+ * [, Principal [principal_class_name] "principal_name"]
+ * [, Principal [principal_class_name] "principal_name"] ... {
+ * permission permission_class_name [ "target_name" ] [, "action"]
+ * [, SignedBy "signer_names"];
+ * permission ...
+ * };
+ *
+ * </pre>
+ *
+ * The <i>keystore </i> clause specifies reference to a keystore, which is a
+ * database of private keys and their associated digital certificates. The
+ * keystore is used to look up the certificates of signers specified in the
+ * <i>grant </i> entries of the file. The policy file can contain any number of
+ * <i>keystore </i> entries which can appear at any ordinal position. However,
+ * only the first successfully loaded keystore is used, others are ignored. The
+ * keystore must be specified if some grant clause refers to a certificate's
+ * alias. <br>
+ * The <i>grant </i> clause associates a CodeSource (consisting of an URL and a
+ * set of certificates) of some executable code with a set of Permissions which
+ * should be granted to the code. So, the CodeSource is defined by values of
+ * <i>CodeBase </i> and <i>SignedBy </i> fields. The <i>CodeBase </i> value must
+ * be in URL format, while <i>SignedBy </i> value is a (comma-separated list of)
+ * alias(es) to keystore certificates. These fields can be omitted to denote any
+ * codebase and any signers (including case of unsigned code), respectively.
+ * <br>
+ * Also, the code may be required to be executed on behalf of some Principals
+ * (in other words, code's ProtectionDomain must have the array of Principals
+ * associated) in order to possess the Permissions. This fact is indicated by
+ * specifying one or more <i>Principal </i> fields in the <i>grant </i> clause.
+ * Each Principal is specified as class/name pair; name and class can be either
+ * concrete value or wildcard <i>* </i>. As a special case, the class value may
+ * be omitted and then the name is treated as an alias to X.509 Certificate, and
+ * the Principal is assumed to be javax.security.auth.x500.X500Principal with a
+ * name of subject's distinguished name from the certificate. <br>
+ * The order between the <i>CodeBase </i>, <i>SignedBy </i>, and <i>Principal
+ * </i> fields does not matter. The policy file can contain any number of grant
+ * clauses. <br>
+ * Each <i>grant </i> clause must contain one or more <i>permission </i> entry.
+ * The permission entry consist of a fully qualified class name along with
+ * optional <i>name </i>, <i>actions </i> and <i>signedby </i> values. Name and
+ * actions are arguments to the corresponding constructor of the permission
+ * class. SignedBy value represents the keystore alias(es) to certificate(s)
+ * used to sign the permission class. That is, this permission entry is
+ * effective (i.e., access control permission will be granted based on this
+ * entry) only if the bytecode implementation of permission class is verified to
+ * be correctly signed by the said alias(es). <br>
+ * <br>
+ * The policy content may be parameterized via property expansion. Namely,
+ * expressions like <i>${key} </i> are replaced by values of corresponding
+ * system properties. Also, the special <i>slash </i> key (i.e. ${/}) is
+ * supported, it is a shortcut to "file.separator" key. Property
+ * expansion is performed anywhere a double quoted string is allowed in the
+ * policy file. However, this feature is controlled by security properties and
+ * should be turned on by setting "policy.expandProperties" property
+ * to <i>true </i>. <br>
+ * If property expansion fails (due to a missing key), a corresponding entry is
+ * ignored. For fields of <i>keystore </i> and <i>grant </i> clauses, the whole
+ * clause is ignored, and for <i>permission </i> entry, only that entry is
+ * ignored. <br>
+ * <br>
+ * The policy also supports generalized expansion in permissions names, of
+ * expressions like <i>${{protocol:data}} </i>. Currently the following
+ * protocols supported:
+ * <dl>
+ * <dt>self
+ * <dd>Denotes substitution to a principal information of the parental Grant
+ * entry. Replaced by a space-separated list of resolved Principals (including
+ * wildcarded), each formatted as <i>class "name" </i>. If parental
+ * Grant entry has no Principals, the permission is ignored.
+ * <dt>alias: <i>name </i>
+ * <dd>Denotes substitution of a KeyStore alias. Namely, if a KeyStore has an
+ * X.509 certificate associated with the specified name, then replaced by
+ * <i>javax.security.auth.x500.X500Principal " <i>DN </i>" </i>
+ * string, where <i>DN </i> is a certificate's subject distinguished name.
+ * </dl>
+ * <br>
+ * <br>
+ * This implementation is thread-safe. The policy caches sets of calculated
+ * permissions for the requested objects (ProtectionDomains and CodeSources) via
+ * WeakHashMap; the cache is cleaned either explicitly during refresh()
+ * invocation, or naturally by garbage-collecting the corresponding objects.
+ *
+ * @see org.apache.harmony.security.PolicyUtils#getPolicyURLs(Properties, String,
+ * String)
+ */
+
+public class ConcurrentPolicyFile extends Policy {
+
+ /**
+ * System property for dynamically added policy location.
+ */
+ public static final String JAVA_SECURITY_POLICY = "java.security.policy"; //$NON-NLS-1$
+
+ /**
+ * Prefix for numbered Policy locations specified in security.properties.
+ */
+ public static final String POLICY_URL_PREFIX = "policy.url."; //$NON-NLS-1$
+
+ // A set of PolicyEntries constituting this Policy.
+ private final ReentrantReadWriteLock rwl;
+ private final ReadLock rl;
+ private final WriteLock wl;
+
+ private Set<PolicyEntry> grants = new HashSet<PolicyEntry>(); // protected by rwl
+
+ // Calculated Permissions cache, organized as
+ // Map{Object->Collection<Permission>}.
+ // The Object is a ProtectionDomain, a CodeSource or
+ // any other permissions-granted entity.
+ private final ConcurrentMap<Object, Collection<Permission>> cache =
+ new ConcurrentWeakIdentityMap<Object, Collection<Permission>>();
+
+ // A specific parser for a particular policy file format.
+ private final PolicyParser parser;
+
+ /**
+ * Default constructor, equivalent to
+ * <code>ConcurrentPolicyFile(new DefaultPolicyParser())</code>.
+ */
+ public ConcurrentPolicyFile() {
+ this(new DefaultPolicyParser());
+ }
+
+ /**
+ * Extension constructor for plugging-in a custom parser.
+ * @param dpr
+ */
+ public ConcurrentPolicyFile(PolicyParser dpr) {
+ parser = dpr;
+ rwl = new ReentrantReadWriteLock();
+ rl = rwl.readLock();
+ wl = rwl.writeLock();
+ refresh();
+ }
+
+ /**
+ * Returns collection of permissions allowed for the domain
+ * 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>.
+ * @param pd ProtectionDomain
+ * @see ProtectionDomain
+ */
+ @Override
+ public PermissionCollection getPermissions(ProtectionDomain pd) {
+ CodeSource cs = pd.getCodeSource();
+ Collection<Permission> pc = cache.get(cs); // saves new object creation.
+ if (pc == null){
+ // Just because the new object is contained within a ConcurrentMap
+ // doesn't mean it doesn't need to be synchronized!
+ pc = Collections.synchronizedSet( new HashSet<Permission>() );
+ Collection<Permission> existed = cache.putIfAbsent(cs, pc);
+ if ( !(existed == null) ){ pc = existed;}
+ }
+ try {
+ rl.lock();
+ Iterator<PolicyEntry> it = grants.iterator();
+ while (it.hasNext()) {
+ PolicyEntry ge = it.next();
+ if (ge.impliesPrincipals(pd == null ? null : pd.getPrincipals())
+ && ge.impliesCodeSource(pd == null ? null : pd.getCodeSource())) {
+ pc.addAll(ge.getPermissions());
+ }
+ }
+ } finally { rl.unlock(); }
+ return PolicyUtils.toPermissionCollection(pc);
+ }
+
+ /**
+ * Returns collection of permissions allowed for the codesource
+ * according to the policy.
+ * The evaluation assumes that current principals are undefined.
+ * @param cs CodeSource
+ * @see CodeSource
+ */
+ @Override
+ public PermissionCollection getPermissions(CodeSource cs) {
+ Collection<Permission> pc = cache.get(cs); // saves new object creation.
+ if (pc == null){
+ // Just because the new object is contained within a ConcurrentMap
+ // doesn't mean it doesn't need to be synchronized!
+ pc = Collections.synchronizedSet( new HashSet<Permission>() );
+ Collection<Permission> existed = cache.putIfAbsent(cs, pc);
+ if ( !(existed == null) ){ pc = existed;}
+ }
+ try {
+ rl.lock();
+ Iterator<PolicyEntry> it = grants.iterator();
+ while (it.hasNext()) {
+ PolicyEntry ge = it.next();
+ if (ge.impliesPrincipals(null)
+ && ge.impliesCodeSource(cs)) {
+ pc.addAll(ge.getPermissions()); // we still hold a reference
+ }
+ }
+ } finally { rl.unlock(); }
+ return PolicyUtils.toPermissionCollection(pc);
+ }
+
+ @Override
+ public boolean implies(ProtectionDomain domain, Permission permission) {
+ PermissionCollection pc = getPermissions(domain);
+ if (pc == null) {
+ return false;
+ }
+ return pc.implies(permission);
+ }
+
+ /**
+ * Gets fresh list of locations and tries to load all of them in sequence;
+ * failed loads are ignored. After processing all locations, old policy
+ * settings are discarded and new ones come into force. <br>
+ *
+ * @see PolicyUtils#getPolicyURLs(Properties, String, String)
+ */
+ @Override
+ public void refresh() {
+ Set<PolicyEntry> fresh = new HashSet<PolicyEntry>();
+ Properties system = new Properties(AccessController
+ .doPrivileged(new PolicyUtils.SystemKit()));
+ system.setProperty("/", File.separator); //$NON-NLS-1$
+ URL[] policyLocations = PolicyUtils.getPolicyURLs(system,
+ JAVA_SECURITY_POLICY,
+ POLICY_URL_PREFIX);
+ for (int i = 0; i < policyLocations.length; i++) {
+ try {
+ //TODO debug log
+ //System.err.println("Parsing policy file: " + policyLocations[i]);
+ Collection<PolicyEntry> pc = parser.parse(policyLocations[i], system);
+ fresh.addAll(pc);
+ } catch (Exception e) {
+ // TODO log warning
+ //System.err.println("Ignoring policy file: "
+ // + policyLocations[i] + ". Reason:\n"+ e);
+ }
+ }
+ try {
+ wl.lock();
+ grants = fresh;
+ cache.clear();
+ }finally {wl.unlock();}
+ }
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/ConcurrentPolicyFile.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/DynamicConcurrentPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/DynamicConcurrentPolicyProvider.java?rev=943285&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/DynamicConcurrentPolicyProvider.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/DynamicConcurrentPolicyProvider.java Tue May 11 20:37:47 2010
@@ -0,0 +1,489 @@
+
+
+package org.apache.river.imp.security.policy.se;
+
+import java.security.AccessController;
+import java.security.AllPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.security.Provider;
+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.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+import net.jini.security.GrantPermission;
+import net.jini.security.policy.DynamicPolicy;
+import net.jini.security.policy.PolicyInitializationException;
+import org.apache.river.api.security.RevokePermission;
+import org.apache.river.imp.security.policy.spi.RevokeableDynamicPolicySpi;
+import org.apache.river.api.security.RevokeablePolicy;
+import org.apache.river.imp.security.policy.util.PolicyEntry;
+import org.apache.river.imp.security.policy.util.PolicyUtils;
+import org.apache.river.imp.util.ConcurrentWeakIdentityMap;
+
+/**
+ * <p>This is a Dynamic Policy Provider that supports concurrent access,
+ * for instances where a Policy provider is used for a distributed network
+ * of computers, or where there is a large number of ProtectionDomains and
+ * hence the opportunity for concurrency exists, concurrency comes with a
+ * cost however, that of increased memory usage.</p>
+ *
+ * <p>Due to the Java 2 Security system's static design, a Policy Provider
+ * can only augment the policy files utilised, that is it can only relax security
+ * by granting additional permissions, this implementation adds an experimental
+ * feature for revoking permissions, however there are some caveats:</p>
+ *
+ * <p>Firstly if the Policy.refresh() method is called, followed by the
+ * ProtectionDomain.toString() method, the ProtectionDomain
+ * merge the permissions, from the policy with those in the ProtectionDomain,
+ * a ProtectionDomain cannot have Permissions
+ * removed, only additional merged. </p>
+ *
+ * <p>So in order to prevent dynamic grants from finding
+ * their way into a ProtectionDomain's private PermissionCollection,
+ * one would have to ensure that no dynamically grantable permissions are
+ * returned via the methods:</p>
+ * <p>
+ * getPermissions(Codesource source) or
+ * getPermissions(ProtectionDomain domain)
+ * </p>
+ * <p>This is different to the behaviour of the existing Jini 2.0
+ * DynamicPolicyProvider implementation where dynamically granted Permissions
+ * are added.
+ *
+ * However when a Policy is checked via implies(ProtectionDomain d, Permission p)
+ * this implementation checks the dynamic grants
+ *
+ * This means that if a DynamicPolicy is utilised as the base Policy class
+ * and if it returns dynamically granted permissions, then those permissions
+ * cannot be revoked.</p>
+ * <p>
+ * It is thus reccommeded that Static policy files only be used for files
+ * where the level of trust is relatively static. This is the only implementation
+ * where a dyanamic grant can be removed. In the case of Proxy trust, a proxy
+ * is no longer trusted when it has lost contact with it's Principal (server)
+ * because the server cannot be asked if it trusts it's proxy and the proxy
+ * cannot be given a thread of control to find it's server because it has
+ * already attained too many Permissions. In this new implementation it should
+ * be possible to revoke AllPermission and grant Permissions dynamically as
+ * trust is gained.</p>
+ * <p>
+ * This may cause some undesireable side effects in existing programs.
+ * </p><p>
+ * There is one final reccommendation and that is adopting / utilising an OSGi
+ * Framework to enable far greater control over dynamic Permissions than this hack
+ * implementation provides.
+ * </p><p>
+ * To make the best utilisation of this Policy provider, set the System property:
+ * </p>,<p>
+ * net.jini.security.policy.PolicyFileProvider.basePolicyClass =
+ * org.apache.river.security.concurrent.ConcurrentPolicyFile
+ * </p>
+ * @author Peter Firmstone
+ * @version 1
+ * @since 2.2
+ * @see ProtectionDomain
+ * @see Policy
+ * @see ConcurrentPolicyFile
+ * @see net.jini.security.policy.PolicyFileProvider
+ * @see ConcurrentPermissionCollection
+ */
+
+public class DynamicConcurrentPolicyProvider implements RevokeableDynamicPolicySpi {
+ private static final ProtectionDomain sysDomain =
+ AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
+ public ProtectionDomain run() { return Object.class.getProtectionDomain(); }
+ });
+
+ // A set of PolicyEntries constituting this Policy.
+ // PolicyEntry is lighter weight than PermissionCollection.
+ private final ReentrantReadWriteLock rwl;
+ private final ReadLock rl;
+ private final WriteLock wl;
+ private final Set<PolicyEntry> dynamicGrants; // protected by rwl
+ private volatile Policy basePolicy; // effectively final looks after its own sync
+ private final ConcurrentMap<ProtectionDomain, PermissionCollection> cache;
+ private volatile boolean basePolicyIsDynamic; // Don't use cache if true.
+ private volatile boolean revokeable;
+ private volatile boolean initialized = false;
+ private Logger logger;
+ private volatile boolean loggable;
+ // do something about some domain permissions for this domain so we can
+ // avoid dead locks due to bug 4911907
+
+
+ public DynamicConcurrentPolicyProvider(){
+ rwl = new ReentrantReadWriteLock();
+ rl = rwl.readLock();
+ wl = rwl.writeLock();
+ dynamicGrants = new HashSet<PolicyEntry>(30);
+ basePolicy = null;
+ cache = new ConcurrentWeakIdentityMap<ProtectionDomain, PermissionCollection>();
+ basePolicyIsDynamic = false;
+ revokeable = true;
+ logger = Logger.getLogger("net.jini.security.policy");
+ loggable = logger.isLoggable(Level.INFO);
+ }
+
+ /**
+ * Idempotent method.
+ * @param basePolicy
+ * @return
+ */
+ public boolean basePolicy(Policy basePolicy) {
+ if (initialized == true) return false;
+ this.basePolicy = basePolicy;
+ return true;
+ }
+
+ /**
+ * Idempotent method.
+ * @throws net.jini.security.policy.PolicyInitializationException
+ */
+ public void initialize() throws PolicyInitializationException {
+ if (basePolicy == null) throw new PolicyInitializationException("Base Policy hasn't " +
+ "been set cannot initialize", new Exception("Failed to initialize"));
+ if (basePolicy instanceof DynamicPolicy) {
+ DynamicPolicy dp = (DynamicPolicy) basePolicy;
+ basePolicyIsDynamic = dp.grantSupported();
+ revokeable = false;
+ if (basePolicy instanceof RevokeablePolicy ) {
+ RevokeablePolicy rp = (RevokeablePolicy) basePolicy;
+ revokeable = rp.revokeSupported();
+ }
+ }
+ initialized = true;
+ }
+
+ /**
+ * Ensures that any classes depended on by this policy provider are
+ * resolved. This is to preclude lazy resolution of such classes during
+ * operation of the provider, which can result in deadlock as described by
+ * bug 4911907.
+ */
+ public void ensureDependenciesResolved() {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ // 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());
+ }
+
+ public void revoke(Class cl, Principal[] principals, Permission[] permissions) {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ if (permissions == null) return;
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RevokePermission());
+ }
+ if (basePolicyIsDynamic){
+ // Revoke not supported unless the base policy supports it.
+ if (revokeable){
+ RevokeablePolicy rp = (RevokeablePolicy) basePolicy;
+ rp.revoke(cl, principals, permissions);
+ }
+ return;
+ }
+ /* The removal begins with removal from the dynamicGrants then the cache
+ * while dynamicGrants is write locked, otherwise it could be added
+ * again due to a concurrent implies during the removal process.
+ * Actually the decision has been made to release the lock as soon as
+ * possible to prevent possible deadlocks, increase concurrency at the
+ * risk of possible positive implies() the the mean time.
+ */
+ ProtectionDomain domain = cl.getProtectionDomain();
+ CodeSource codeSource = domain.getCodeSource();
+ if (principals == null){
+ principals = new Principal[0];
+ }
+ if (principals.length > 0) {
+ principals = principals.clone();
+ checkNullElements(principals);
+ }
+ permissions = permissions.clone();
+ checkNullElements(permissions);
+ Collection<Permission> permToBeRemoved = Arrays.asList(permissions);
+ Collection<Permission> remainingGrants = new HashSet<Permission>();
+ try {
+ wl.lock();
+ Iterator<PolicyEntry> it = dynamicGrants.iterator();
+ while (it.hasNext()) {
+ PolicyEntry ge = it.next();
+ if (ge.impliesPrincipals(domain == null ? null : principals)
+ && ge.impliesProtectionDomain(domain)
+ && ge.impliesCodeSource(domain == null ? null : codeSource)) {
+ remainingGrants.addAll( ge.getPermissions());
+ it.remove();
+ }
+ }
+ if (remainingGrants.isEmpty()) return; // nothing to do.
+ } finally { wl.unlock(); }
+ /* Now we can remove the PermissionDomain from the cache.
+ * The cache will populate itself again correctly when implies() is
+ * called on that PermissionDomain again.
+ */
+ cache.remove(domain.toString());
+ /* We must re-enter the remaining grants if any exist. */
+ remainingGrants.removeAll(permToBeRemoved);
+ PolicyEntry policyEntry = new PolicyEntry(codeSource,
+ Arrays.asList(principals), remainingGrants);
+ try {
+ wl.lock();
+ dynamicGrants.add(policyEntry);
+ } finally { wl.unlock(); }
+ }
+
+ public boolean revokeSupported() {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ return revokeable;
+ }
+
+ public Provider getProvider() {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public String getType() {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ public PermissionCollection getPermissions(CodeSource codesource) {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ return basePolicy.getPermissions(codesource);
+// The following code breaks revoke.
+// Collection<Permission> dynamicallyGrantedPermissions = getGrants(codesource, null);
+// PermissionCollection pc = null;
+// pc = basePolicy.getPermissions(codesource);
+// if (pc == null) pc = new Permissions();
+// Iterator<Permission> dgpi = dynamicallyGrantedPermissions.iterator();
+// while (dgpi.hasNext()){
+// pc.add(dgpi.next());
+// }
+// return pc;
+ }
+
+ public PermissionCollection getPermissions(ProtectionDomain domain) {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ return basePolicy.getPermissions(domain);
+// The following code breaks revoke.
+// CodeSource cs = (domain == null ? null : domain.getCodeSource());
+// Principal[] pals = (domain == null ? null : domain.getPrincipals());
+// Collection<Permission> dynamicallyGrantedPermissions = getGrants(cs, pals);
+// PermissionCollection pc = null;
+// pc = cache.get(domain); // saves new object creation.
+// if (pc == null){
+// pc = basePolicy.getPermissions(domain);
+// //if (pc == null) pc = new ConcurrentPermissions();
+// if (pc == null) pc = new Permissions();
+//// if (!(pc instanceof ConcurrentPermissions)) {
+//// pc = PolicyUtils.toConcurrentPermissions(pc);
+//// }
+// PermissionCollection existed = cache.putIfAbsent(domain, pc);
+// if ( !(existed == null) ){ pc = existed;} //Another thread might have just done it!
+// }
+// Iterator<Permission> dgpi = dynamicallyGrantedPermissions.iterator();
+// while (dgpi.hasNext()){
+// pc.add(dgpi.next());
+// }
+// return pc;
+ }
+
+ public boolean implies(ProtectionDomain domain, Permission permission) {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ // First check the our cache if the basePolicy is not dynamic.
+ if (!basePolicyIsDynamic) {
+ PermissionCollection pc = cache.get(domain);
+ if ( pc != null){
+ if (pc.implies(permission)) return true;
+ }
+ }
+ // Then check the base policy
+ if (basePolicy.implies(domain, permission)) return true;
+ if (basePolicyIsDynamic) return false;
+ if (loggable){
+ logger.log(Level.INFO, domain + permission.toString() +
+ ": Base policy is not dynamic and returned false" );
+ }
+ // If it doesn't then we should check for dynamic grants
+ Principal[] pals = (domain == null ? null : domain.getPrincipals());
+ CodeSource cs = ( domain == null ? null : domain.getCodeSource());
+ Collection<Permission> dynamicallyGrantedPermissions = getGrants(domain, cs, pals);
+ if (loggable) {
+ logger.log(Level.INFO, "Grants: " + dynamicallyGrantedPermissions.toString());
+ }
+ if (dynamicallyGrantedPermissions.isEmpty()) return false;
+ // Operation starts to get expensive
+ PermissionCollection pc = null;
+ pc = cache.get(domain); // saves new object creation.
+ if (pc == null){
+ pc = basePolicy.getPermissions(domain);
+ if (pc == null) pc = new ConcurrentPermissions();
+// if (pc == null) pc = new Permissions();
+ if (!(pc instanceof ConcurrentPermissions)) {
+ pc = PolicyUtils.toConcurrentPermissions(pc);
+ }
+ PermissionCollection existed = cache.putIfAbsent(domain, pc);
+ if ( !(existed == null) ){ pc = existed;} //Another thread might have just done it!
+ }
+ Iterator<Permission> dgpi = dynamicallyGrantedPermissions.iterator();
+ while (dgpi.hasNext()){
+ pc.add(dgpi.next());
+ }
+ // If we get refreshed the cache could be empty, which is more pedantic
+ // however the result may still be true so we'll return it anyway.
+ if (loggable) {
+ logger.log(Level.INFO, "PermissionCollection: " + pc.toString());
+ }
+ return pc.implies(permission);
+ }
+
+ /**
+ * Calling refresh doesn't remove any dynamic grant's, it only clears
+ * the cache and refreshes the underlying Policy, it also removes any
+ * grants for ProtectionDomains that no longer exist.
+ */
+ public void refresh() {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ cache.clear();
+ basePolicy.refresh();
+ // Clean up any void grants.
+ try {
+ wl.lock();
+ Iterator<PolicyEntry> it = dynamicGrants.iterator();
+ while (it.hasNext()){
+ PolicyEntry pe = it.next();
+ if ( pe.isVoid()){
+ it.remove();
+ }
+ }
+ } finally {wl.unlock();}
+
+ }
+
+ public boolean grantSupported() {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ return true;
+ }
+
+ public void grant(Class cl, Principal[] principals, Permission[] permissions) {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ if (permissions == null || permissions.length == 0) {
+ return;
+ }
+ if ( basePolicyIsDynamic ){
+ /* Delegate, otherwise, if base policy is an instance of this class, we
+ * may have multi combinations of permissions that together should
+ * be true but become separated as this implementation will not
+ * return any dynamically granted permissions via getPermissions(
+ * because doing so would mean loosing revoke ability.
+ */
+ DynamicPolicy dp = (DynamicPolicy) basePolicy;
+ dp.grant(cl, principals, permissions);
+ return;
+ }
+ if (principals == null){
+ principals = new Principal[0];
+ }
+ if (principals.length > 0) {
+ principals = principals.clone();
+ checkNullElements(principals);
+ }
+ permissions = permissions.clone();
+ checkNullElements(permissions);
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new GrantPermission(permissions));
+ }
+ Collection<Principal> pal = Arrays.asList(principals);
+ Collection<Permission> perm = Arrays.asList(permissions);
+ ProtectionDomain domain = null;
+ if ( cl != null){
+ domain = getDomain(cl);
+ }
+ PolicyEntry pe = new PolicyEntry(domain, pal, perm);
+ if (loggable){
+ logger.log(Level.INFO, "Granting: " + pe.toString());
+ }
+ try {
+ wl.lock();
+ dynamicGrants.add(pe);
+ } finally {wl.unlock();}
+ }
+
+ // documentation inherited from DynamicPolicy.getGrants
+ public Permission[] getGrants(Class cl, Principal[] principals) {
+ if (initialized == false) throw new RuntimeException("Object not initialized");
+ ProtectionDomain pd = null;
+ CodeSource cs = null;
+ if ( cl != null ) {
+ pd = getDomain(cl);
+ cs = pd.getCodeSource();
+ }
+ // defensive copy array
+ if (principals != null && principals.length > 0) {
+ principals = principals.clone();
+ checkNullElements(principals);
+ }
+ Collection<Permission> cperms = getGrants(pd, cs, principals);
+ Permission[] perms = cperms.toArray(new Permission[cperms.size()]);
+ return perms;
+ }
+
+ private Collection<Permission> getGrants(ProtectionDomain pd,
+ CodeSource cs, Principal[] pals){
+ Collection<Permission> dynamicallyGrantedPermissions = new HashSet<Permission>(20);
+ try {
+ rl.lock();
+ Iterator<PolicyEntry> it = dynamicGrants.iterator();
+ while (it.hasNext()) {
+ PolicyEntry ge = it.next();
+ if ( ge.impliesProtectionDomain(pd)
+ && ge.impliesCodeSource(cs)
+ && ge.impliesPrincipals(pals)) {
+ dynamicallyGrantedPermissions.addAll( ge.getPermissions());
+ }
+ }
+ } finally { rl.unlock(); }
+ return dynamicallyGrantedPermissions;
+ }
+
+ private static void checkNullElements(Object[] array) {
+ int l = array.length;
+ for (int i = 0; i < l; i++) {
+ if (array[i] == null) {
+ throw new NullPointerException();
+ }
+ }
+ }
+
+ private static ProtectionDomain getDomain(final Class cl) {
+ ProtectionDomain pd = AccessController.doPrivileged(
+ new PrivilegedAction<ProtectionDomain>() {
+ public ProtectionDomain run() { return cl.getProtectionDomain(); }
+ });
+ if (pd != sysDomain && pd.getClassLoader() == null) {
+ throw new UnsupportedOperationException(
+ "ungrantable protection domain");
+ }
+ return pd;
+ }
+
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/DynamicConcurrentPolicyProvider.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/MultiReadPermissionCollection.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/MultiReadPermissionCollection.java?rev=943285&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/MultiReadPermissionCollection.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/MultiReadPermissionCollection.java Tue May 11 20:37:47 2010
@@ -0,0 +1,340 @@
+/*
+ * 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.imp.security.policy.se;
+
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.UnresolvedPermission;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+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;
+
+
+/**
+ * MultiReadPermissionCollection is a wrapper class that enables mutliple
+ * reads and RevokablePermissionCollection support. It only supports
+ * a homogenous class PermissionCollection.
+ *
+ * TODO Serialization Correctly
+ * @version 0.2 2009/11/14
+ * @author Peter Firmstone
+ */
+public final class MultiReadPermissionCollection extends PermissionCollection
+ implements RevokeablePermissionCollection, Serializable {
+ private final static long serialVersionUID = 1L;
+ private transient PermissionCollection permCl; // all access protected by rwl
+ private final transient ReadWriteLock rwl;
+ private final transient Lock rl;
+ private final transient Lock wl;
+ private transient int writeCounter; // all access protected by rwl
+ private boolean readOnly; // all access protected by rwl
+ private Permission[] permissions; //never instantiate for ide code completion
+
+ MultiReadPermissionCollection(Permission p){
+ permCl = newPermissionCollection(p);
+ rwl = new ReentrantReadWriteLock();
+ rl = rwl.readLock();
+ wl = rwl.writeLock();
+ writeCounter = 0;
+ readOnly = false;
+ }
+
+ @Override
+ public boolean isReadOnly(){
+ rl.lock();
+ try{
+ return readOnly;
+ }finally {rl.unlock();}
+ }
+
+ @Override
+ public void setReadOnly(){
+ wl.lock();
+ try{
+ readOnly = true;
+ }finally {wl.unlock();}
+ }
+
+
+
+ @Override
+ public String toString(){
+ rl.lock();
+ try {
+ return permCl.toString();
+ } finally { rl.unlock();}
+ }
+
+ @Override
+ public boolean equals(Object obj){
+ if (this == obj) return true;
+ if ( !(obj instanceof MultiReadPermissionCollection)) return false;
+ MultiReadPermissionCollection mrpcObj = (MultiReadPermissionCollection) obj;
+ rl.lock();
+ try {
+ if (permCl.equals(mrpcObj.permCl)) return true;
+ }finally {rl.unlock();}
+ return false;
+ }
+
+ public int hashCode(){
+ rl.lock();
+ try {
+ return permCl.hashCode();
+ }finally {rl.unlock();}
+ }
+
+ @Override
+ public void add(Permission permission) {
+ if (readOnly) {
+ throw new SecurityException("attempt to add a Permission to a readonly Permissions object");
+ }
+ wl.lock();
+ try {
+ permCl.add(permission);
+ writeCounter++;
+ }
+ finally {wl.unlock();}
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ rl.lock();
+ try {return permCl.implies(permission);}
+ finally {rl.unlock();}
+ }
+
+ @Override
+ public Enumeration<Permission> elements() {
+ rl.lock();
+ try {return permCl.elements();}
+ finally {rl.unlock();}
+ }
+
+
+ /* Returns an empty PermissionCollection
+ */
+ private PermissionCollection newPermissionCollection(Permission permission){
+ PermissionCollection pc = permission.newPermissionCollection();
+ if (pc == null){
+ pc = new PermissionHash();
+ }
+ return pc;
+ }
+ /**
+ * Permissions may have some overlap, this method will remove any Permission
+ * objects that imply any of the Permission's supplied.
+ *
+ * If this fails it will be due to the implies method returning true
+ * due to a combination of Permission objects.
+ *
+ * Permission objects must have the same class and type for this implementation.
+ *
+ * @param permissions
+ * @return success
+ */
+ public int revoke(Permission ... permissions) {
+ int count = 0; // false
+ HashSet<Permission> permissionSet = new HashSet<Permission>();
+ rl.lock();
+ try {
+ if (readOnly) {
+ throw new SecurityException("attempt to remove a Permission from a readonly Permissions object");
+ }
+ count = writeCounter;
+ Enumeration<Permission> current = elements();
+ while (current.hasMoreElements()) {
+ permissionSet.add(current.nextElement());
+ }
+ } finally {
+ rl.unlock();
+ }
+ if (permissionSet.size() == 0) {
+ return 1; // true
+ }
+ Iterator<Permission> itr = permissionSet.iterator();
+ PermissionCollection newCollection = null;
+ int size = permissions.length;
+ PER:
+ while (itr.hasNext() ){
+ Permission p = itr.next();
+ if (newCollection == null) {
+ newCollection = p.newPermissionCollection();
+ if (newCollection == null ){
+ newCollection = new PermissionHash();
+ }
+ }
+ for (int i = 0; i < size; i++) {
+ if (p.implies(permissions[i])) {
+ continue PER;
+ }
+ }
+ newCollection.add(p); // if the wrong type is passed in it doesn't matter
+ }
+ /* Check that our modifications have been effective.
+ */
+ for (int i = 0; i < size ; i++){
+ if ( newCollection.implies(permissions[i])) { return -1;} // fail
+ }
+ return updatePermissionCollection(newCollection, count);
+ }
+
+ /**
+ * Idempotent method to remove all Permissions Contained within a
+ * PermissionCollection. Method fails if PermissionCollection is
+ * modified during method execution. This method
+ * creates an empty replacement PermissionCollection.
+ *
+ * This method also resets setReadOnly() to false;
+ *
+ * @param permission
+ */
+ public void revokeAll(Permission permission) {
+ boolean sameClassType = false;
+ int count = 0;
+ rl.lock();
+ try {
+ Enumeration<Permission> current = elements();
+ Permission currentPerm = null;
+ if (current.hasMoreElements()) {
+ currentPerm = current.nextElement();
+ }
+ if (currentPerm == null) { return; } // idempotent, already empty.
+ if (currentPerm.getClass().equals(permission.getClass())){ sameClassType = true;}
+ } finally { rl.unlock(); }
+ PermissionCollection newCollection = permission.newPermissionCollection();
+ if (newCollection == null) { newCollection = new PermissionHash(); }
+ if (sameClassType == true){
+ updatePermissionCollection(newCollection, count);
+ }
+ }
+
+ private int updatePermissionCollection( PermissionCollection pc, int writeCount ){
+ wl.lock();
+ try {
+ if ( writeCount == writeCounter || writeCount == 0 ) {
+ permCl = pc;
+ writeCounter = 0; //Reset the counter
+ if (writeCount == 0) {readOnly = false;}
+ return 1;
+ }
+ } finally {
+ wl.unlock();
+ }
+ return 0;
+ }
+
+ private static class SerializationProxy implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final Permission[] permissions;
+ private final boolean readOnly;
+ SerializationProxy(PermissionCollection pc){
+ ArrayList<Permission> collection = new ArrayList<Permission>();
+ Enumeration<Permission> en = pc.elements();
+ while (en.hasMoreElements()){
+ collection.add(en.nextElement());
+ }
+ permissions = new Permission[collection.size()];
+ collection.toArray(permissions);
+ readOnly = pc.isReadOnly();
+ }
+ }
+
+ private Object writeReplace(){
+ return new SerializationProxy(this);
+ }
+
+ private void readObject(ObjectInputStream stream) throws InvalidObjectException {
+ throw new InvalidObjectException("Proxy required");
+ }
+
+ private Object readResolve() {
+ MultiReadPermissionCollection pc = new MultiReadPermissionCollection(permissions[0]);
+ int length = permissions.length;
+ for ( int i = 0 ; i < length ; i++){
+ pc.add(permissions[i]);
+ }
+ if ( readOnly == true ) {pc.setReadOnly();}
+ return pc;
+ }
+
+ private static final class PermissionHash extends PermissionCollection {
+ // This class is never serialized.
+ private final static long serialVersionUID = 1L;
+ private HashSet<Permission> permSet;
+
+ public PermissionHash(){
+ permSet = new HashSet<Permission>();
+ }
+
+ public boolean equals(Object obj){
+ if (this == obj) return true;
+ if (!(obj instanceof PermissionHash)) return false;
+ PermissionHash phObj = (PermissionHash) obj;
+ if (this.permSet.equals(phObj.permSet)) return true;
+ return false;
+ }
+
+ public int hashCode(){
+ return permSet.hashCode();
+ }
+
+ public String toString(){
+ return permSet.toString();
+ }
+
+ @Override
+ public void add(Permission permission) {
+ permSet.add(permission);
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ // attempt a fast lookup and implies. If that fails
+ // then enumerate through all the permissions.
+ if (permSet.contains(permission)
+ && !(permission instanceof UnresolvedPermission)) {
+ return true;
+ }
+ Iterator<Permission> itr = permSet.iterator();
+ while (itr.hasNext()) {
+ Permission p = itr.next();
+ if (p.implies(permission)) {return true;}
+ }
+ return false;
+ }
+
+ @Override
+ public Enumeration<Permission> elements() {
+ synchronized (this){
+ return Collections.enumeration(permSet);
+ }
+ }
+ }
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/MultiReadPermissionCollection.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolution.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolution.java?rev=943285&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolution.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolution.java Tue May 11 20:37:47 2010
@@ -0,0 +1,206 @@
+/*
+ * 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.imp.security.policy.se;
+
+import java.lang.reflect.Constructor;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.UnresolvedPermission;
+import java.security.cert.Certificate;
+
+/**
+ *
+ * @author Peter Firmstone
+ */
+class PermissionPendingResolution extends Permission {
+ private static final long serialVersionUID = 1L;
+ private transient String type; //Class name of underlying permission
+ private transient String name; //Target name of underlying permission
+ private transient String actions;
+ /* We have our own array copy of certs, prevents unnecessary
+ * array creation every time .getUnresolvedCerts() is called.
+ */
+ private transient Certificate [] targetCerts;
+ private UnresolvedPermission unresolvedPermission;
+
+ PermissionPendingResolution(UnresolvedPermission up){
+ super(up.getUnresolvedType());
+ type = up.getUnresolvedType();
+ name = up.getUnresolvedName();
+ actions = up.getUnresolvedActions();
+ // don't need to defensive copy, UnresolvedPermission already does it.
+ targetCerts = up.getUnresolvedCerts();
+ unresolvedPermission = up;
+ }
+
+ Permission resolve(Class targetType) {
+ // check signers at first
+ if (matchSubset( targetCerts, targetType.getSigners())) {
+ try {
+ return instantiatePermission(targetType, name, actions);
+ } catch (Exception ignore) {
+ //TODO log warning?
+ }
+ }
+ return null;
+ }
+
+ Permission resolve(ClassLoader cl){
+ Class<?> targetType = null;
+ try {
+ targetType = cl.loadClass(type);
+ } catch (ClassNotFoundException e){
+ //TODO log warning?
+ System.err.println(type +" " + name + " " + actions +
+ ": Cannot be resolved due to ClassNotFoundException");
+ e.printStackTrace();
+ } catch (NullPointerException e){
+ //TODO log warning, this should never happen but if it does
+ //the class will not be resolved.
+ System.err.println(type +" " + name + " " + actions +
+ ": Cannot be resolved due to ClassLoader null instance");
+ e.printStackTrace();
+ }
+ if ( targetType == null ) {return null;}
+ return resolve(targetType);
+ }
+
+
+ /**
+ * Code Copied, Courtesey Apache Harmony
+ *
+ * Checks whether the objects from <code>what</code> array are all
+ * presented in <code>where</code> array.
+ *
+ * @param what first array, may be <code>null</code>
+ * @param where second array, may be <code>null</code>
+ * @return <code>true</code> if the first array is <code>null</code>
+ * or if each and every object (ignoring null values)
+ * from the first array has a twin in the second array; <code>false</code> otherwise
+ */
+ boolean matchSubset(Object[] what, Object[] where) {
+ if (what == null) {
+ return true;
+ }
+
+ for (int i = 0; i < what.length; i++) {
+ if (what[i] != null) {
+ if (where == null) {
+ return false;
+ }
+ boolean found = false;
+ for (int j = 0; j < where.length; j++) {
+ if (what[i].equals(where[j])) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // Empty set of arguments to default constructor of a Permission.
+ private static final Class[] NO_ARGS = {};
+
+ // One-arg set of arguments to default constructor of a Permission.
+ private static final Class[] ONE_ARGS = { String.class };
+
+ // Two-args set of arguments to default constructor of a Permission.
+ private static final Class[] TWO_ARGS = { String.class, String.class };
+
+ /**
+ * Code copied, courtsey of Apache Harmony
+ *
+ * Tries to find a suitable constructor and instantiate a new Permission
+ * with specified parameters.
+ *
+ * @param targetType class of expected Permission instance
+ * @param targetName name of expected Permission instance
+ * @param targetActions actions of expected Permission instance
+ * @return a new Permission instance
+ * @throws IllegalArgumentException if no suitable constructor found
+ * @throws Exception any exception thrown by Constructor.newInstance()
+ */
+ Permission instantiatePermission(Class<?> targetType,
+ String targetName, String targetActions) throws Exception {
+
+ // let's guess the best order for trying constructors
+ Class[][] argTypes = null;
+ Object[][] args = null;
+ if (targetActions != null) {
+ argTypes = new Class[][] { TWO_ARGS, ONE_ARGS, NO_ARGS };
+ args = new Object[][] { { targetName, targetActions },
+ { targetName }, {} };
+ } else if (targetName != null) {
+ argTypes = new Class[][] { ONE_ARGS, TWO_ARGS, NO_ARGS };
+ args = new Object[][] { { targetName },
+ { targetName, targetActions }, {} };
+ } else {
+ argTypes = new Class[][] { NO_ARGS, ONE_ARGS, TWO_ARGS };
+ args = new Object[][] { {}, { targetName },
+ { targetName, targetActions } };
+ }
+
+ // finally try to instantiate actual permission
+ for (int i = 0; i < argTypes.length; i++) {
+ try {
+ Constructor<?> ctor = targetType.getConstructor(argTypes[i]);
+ return (Permission)ctor.newInstance(args[i]);
+ }
+ catch (NoSuchMethodException ignore) {}
+ }
+ throw new IllegalArgumentException(type + name + actions);//$NON-NLS-1$
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( obj == this ) {return true;}
+ if ( !(obj instanceof PermissionPendingResolution)) {return false;}
+ PermissionPendingResolution ob = (PermissionPendingResolution) obj;
+ if (this.unresolvedPermission.equals(ob.unresolvedPermission)) {return true;}
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return unresolvedPermission.hashCode();
+ }
+
+ @Override
+ public String getActions() {
+ return "";
+ }
+
+ @Override
+ public PermissionCollection newPermissionCollection(){
+ return new PermissionPendingResolutionCollection();
+ }
+
+ public UnresolvedPermission asUnresolvedPermission(){
+ return unresolvedPermission;
+ }
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolution.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolutionCollection.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolutionCollection.java?rev=943285&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolutionCollection.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolutionCollection.java Tue May 11 20:37:47 2010
@@ -0,0 +1,147 @@
+/*
+ * 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.imp.security.policy.se;
+
+import java.security.AccessController;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ *
+ * @author Peter Firmstone
+ */
+public class PermissionPendingResolutionCollection extends PermissionCollection {
+ private static final long serialVersionUID = 1L;
+ private ConcurrentHashMap<String,Collection<PermissionPendingResolution>> klasses;
+ private AtomicInteger pending;
+ PermissionPendingResolutionCollection(){
+ klasses = new ConcurrentHashMap<String,Collection<PermissionPendingResolution>>(2);
+ pending = new AtomicInteger(0);
+ }
+
+ public int awaitingResolution(){
+ return pending.get();
+ }
+
+
+ public void add(Permission permission) {
+ if (isReadOnly()) {
+ throw new SecurityException("attempt to add a Permission to a readonly Permissions object"); //$NON-NLS-1$
+ }
+ if (permission == null) { throw new IllegalArgumentException("Null Permission");}
+ if ( permission.getClass() != PermissionPendingResolution.class || permission.getClass() != PermissionPendingResolution.class ) {
+ throw new IllegalArgumentException("Not instance of PermissionPendingResolution");
+ }
+ String klass = permission.getName();
+ Collection<PermissionPendingResolution> klassMates = klasses.get(klass);
+ if (klassMates != null){
+ klassMates.add((PermissionPendingResolution) permission);
+ pending.incrementAndGet();
+ return;
+ }
+ Collection<PermissionPendingResolution> klassMatesExists = null;
+ Set<PermissionPendingResolution> pprs = new HashSet<PermissionPendingResolution>();
+ klassMates = Collections.synchronizedSet(pprs);
+ klassMatesExists = klasses.putIfAbsent(klass, klassMates);
+ if (klassMatesExists == null){
+ klassMates.add((PermissionPendingResolution) permission);
+ pending.incrementAndGet();
+ }else{
+ klassMatesExists.add((PermissionPendingResolution) permission);
+ pending.incrementAndGet();
+ }
+ }
+
+ PermissionCollection resolveCollection(Permission target,
+ PermissionCollection holder ){
+ if (pending.get() == 0) { return holder; }
+ String klass = target.getClass().getName();
+ if (klasses.containsKey(klass)) {
+ Collection<PermissionPendingResolution> klassMates = klasses.get(klass);
+ for (Iterator<PermissionPendingResolution> iter = klassMates.iterator(); iter.hasNext();) {
+ 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();
+ }
+ }
+ // there is no possible way of atomic removal of an empty Collection.
+ }
+ return holder;
+ }
+
+ //Should I be performing a privileged action? Or should it run with
+ // the caller thread's privileges?
+ Enumeration<Permission> resolvePermissions(final ProtectionDomain pd){
+ @SuppressWarnings("unchecked")
+ ClassLoader cl = (ClassLoader) AccessController.doPrivileged(
+ new PrivilegedAction(){
+ public Object run(){
+ ClassLoader cL = pd.getClassLoader();
+ if (cL == null){
+ cL = this.getClass().getClassLoader();
+ }
+ return cL;
+ }
+ });
+
+
+ List<Permission> perms = new ArrayList<Permission>();
+ Enumeration enPending = elements();
+ while (enPending.hasMoreElements()){
+ PermissionPendingResolution pendPerm =
+ (PermissionPendingResolution) enPending.nextElement();
+ Permission resolved = pendPerm.resolve(cl);
+ if ( resolved != null ){
+ perms.add(resolved);
+ }
+ }
+ return Collections.enumeration(perms);
+ }
+
+ @Override
+ public boolean implies(Permission permission) {
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Enumeration<Permission> elements() {
+ Collection all = new ArrayList();
+ for (Iterator iter = klasses.values().iterator(); iter.hasNext();) {
+ all.addAll((Collection)iter.next());
+ }
+ return Collections.enumeration(all);
+ }
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/PermissionPendingResolutionCollection.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/RevokeablePermissionCollection.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/RevokeablePermissionCollection.java?rev=943285&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/RevokeablePermissionCollection.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/RevokeablePermissionCollection.java Tue May 11 20:37:47 2010
@@ -0,0 +1,89 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.apache.river.imp.security.policy.se;
+
+import java.security.Permission;
+import java.util.Enumeration;
+
+/**
+ *
+ * @author Peter Firmstone
+ * @see PermissionCollection
+ * @see Permission
+ */
+public interface RevokeablePermissionCollection {
+ /**
+ * This method is slow and to be used only when correctness is perferred
+ * over performance.
+ *
+ * In fact revokeAll() followed by add() is the preferred method.
+ *
+ * However when the new Permission set depends upon the old and there is
+ * a possibility that the old set may be updated with an add during processing
+ * this method will fail and as such not loose a particular required permission.
+ *
+ * Partial success may occur in which case some of the permissions will be
+ * revoked and others not. However only a subset of those permissions that
+ * are requested to be revoked, shall be. This should not be a problem as
+ * the required permissions will still exist in the set and a simple retry
+ * should suffice if the return was 0.
+ *
+ * Attempt to revoke a Permission, if an intervening write occurs an
+ * integer value of 0 is returned, the suggested strategy is to try again,
+ * however if several attempts are likely to fail use revokeAll instead.
+ *
+ * A return value of -1 indicates that the Permission cannot be revoked
+ * from the collection. In this case use revokeAll. It may be possible
+ * to correct this condition by utilising a finer grained permission set.
+ *
+ * A return value of 1 indicates success.
+ *
+ * @param permissions
+ * @return result, 0 for intervening write, -1 failed not possible, 1 for true
+ */
+ public int revoke(Permission ... permissions);
+
+ /**
+ * Due to the overlapping nature of Permission's, attempts to revoke
+ * a permission may fail, in wich case it is best to remove all
+ * permissions related by class and later add the required Permissions.
+ * This method should always succeed.
+ *
+ * This method should only revoke Permission's related to an individual
+ * class type.
+ *
+ * @param permission
+ */
+ public void revokeAll(Permission permission);
+
+ /**
+ * @see PermissionCollection.add(Permission permission)
+ * @param permission
+ */
+ public void add(Permission permission);
+ /**
+ * @see PermissionCollection.elements()
+ * @return
+ */
+ public Enumeration<Permission> elements();
+ /**
+ * @see PermissionCollection.implies()
+ * @param permission
+ * @return
+ */
+ public boolean implies(Permission permission);
+ /**
+ * @see PermissionCollection.isReadOnly()
+ * @return true or false
+ */
+ public boolean isReadOnly();
+ /**
+ * @see PermissionCollection.setReadOnly()
+ */
+ public void setReadOnly();
+ @Override
+ public String toString();
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/concurrent/RevokeablePermissionCollection.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/spi/RevokeableDynamicPolicySpi.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/spi/RevokeableDynamicPolicySpi.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/spi/RevokeableDynamicPolicySpi.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/spi/RevokeableDynamicPolicySpi.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/spi/RevokeableDynamicPolicySpi.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/spi/RevokeableDynamicPolicySpi.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/spi/RevokeableDynamicPolicySpi.java Tue May 11 20:37:47 2010
@@ -3,8 +3,9 @@
* and open the template in the editor.
*/
-package org.apache.river.security.policy.spi;
+package org.apache.river.imp.security.policy.spi;
+import org.apache.river.api.security.RevokeablePolicy;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyParser.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/DefaultPolicyParser.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyParser.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyParser.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/DefaultPolicyParser.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/DefaultPolicyParser.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyParser.java Tue May 11 20:37:47 2010
@@ -20,7 +20,7 @@
* @version $Revision$
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.io.BufferedReader;
import java.io.InputStream;
@@ -46,10 +46,10 @@ import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
-import org.apache.river.security.policy.util.DefaultPolicyScanner.GrantEntry;
-import org.apache.river.security.policy.util.DefaultPolicyScanner.KeystoreEntry;
-import org.apache.river.security.policy.util.DefaultPolicyScanner.PermissionEntry;
-import org.apache.river.security.policy.util.DefaultPolicyScanner.PrincipalEntry;
+import org.apache.river.imp.security.policy.util.DefaultPolicyScanner.GrantEntry;
+import org.apache.river.imp.security.policy.util.DefaultPolicyScanner.KeystoreEntry;
+import org.apache.river.imp.security.policy.util.DefaultPolicyScanner.PermissionEntry;
+import org.apache.river.imp.security.policy.util.DefaultPolicyScanner.PrincipalEntry;
/**
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyScanner.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/DefaultPolicyScanner.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyScanner.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyScanner.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/DefaultPolicyScanner.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/DefaultPolicyScanner.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/DefaultPolicyScanner.java Tue May 11 20:37:47 2010
@@ -20,7 +20,7 @@
* @version $Revision$
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.io.IOException;
import java.io.Reader;
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Messages.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/Messages.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Messages.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Messages.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/Messages.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/Messages.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Messages.java Tue May 11 20:37:47 2010
@@ -21,7 +21,7 @@
* if this tool runs again. Better make changes in the template file.
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.security.AccessController;
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/NullPolicyParser.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/NullPolicyParser.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/NullPolicyParser.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/NullPolicyParser.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/NullPolicyParser.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/NullPolicyParser.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/NullPolicyParser.java Tue May 11 20:37:47 2010
@@ -3,7 +3,7 @@
* and open the template in the editor.
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.net.URL;
import java.util.Collection;
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyEntry.java (from r941176, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyEntry.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyEntry.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyEntry.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyEntry.java&r1=941176&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyEntry.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyEntry.java Tue May 11 20:37:47 2010
@@ -21,13 +21,15 @@
* @version $Revision$
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
+import java.lang.ref.WeakReference;
import java.net.URL;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.Permission;
import java.security.Principal;
+import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -50,6 +52,9 @@ public final class PolicyEntry {
// Store CodeSource
private final CodeSource cs;
+
+ private final WeakReference<ProtectionDomain> domain;
+ private final boolean hasDomain;
// Array of principals
private final List<Principal> principals;
@@ -78,16 +83,72 @@ public final class PolicyEntry {
this.permissions = new HashSet<Permission>(permissions.size());
this.permissions.addAll(permissions);
}
+ domain = null;
+ hasDomain = false;
/* Effectively immutable, this will make any hash this is contained in perform.
* May need to consider Serializable for this class yet, we'll see.
*/
if (this.cs == null){
- hashcode = (principals.hashCode() + this.permissions.hashCode())/2;
+ hashcode = (principals.hashCode() + this.permissions.hashCode()
+ - Boolean.valueOf(hasDomain).hashCode());
} else {
- hashcode = (this.cs.hashCode() + principals.hashCode() + this.permissions.hashCode())/3;
+ hashcode = (this.cs.hashCode() + principals.hashCode()
+ + this.permissions.hashCode()
+ - Boolean.valueOf(hasDomain).hashCode());
}
}
+
+ public PolicyEntry(ProtectionDomain pd, Collection<? extends Principal> prs,
+ Collection<? extends Permission> permissions ){
+ CodeSource cs = null;
+ if (pd != null){
+ cs = pd.getCodeSource();
+ }
+ this.cs = (cs != null) ? normalizeCodeSource(cs) : null;
+ if ( prs == null || prs.isEmpty()) {
+ this.principals = Collections.emptyList(); // Java 1.5
+ }else{
+ this.principals = new ArrayList<Principal>(prs.size());
+ this.principals.addAll(prs);
+ }
+ if (permissions == null || permissions.isEmpty()) {
+ this.permissions = Collections.emptySet(); // Java 1.5
+ }else{
+ this.permissions = new HashSet<Permission>(permissions.size());
+ this.permissions.addAll(permissions);
+ }
+ domain = new WeakReference<ProtectionDomain>(pd);
+ hasDomain = ( pd != null);
+ /* Effectively immutable, this will make any hash this is contained in perform.
+ * May need to consider Serializable for this class yet, we'll see.
+ */
+ if (pd == null){
+ hashcode = (principals.hashCode() + this.permissions.hashCode()
+ - Boolean.valueOf(hasDomain).hashCode());
+ } else {
+ int codeBaseHash = 0;
+ if (cs != null){
+ codeBaseHash = cs.hashCode();
+ }
+ hashcode = (pd.hashCode() + principals.hashCode()
+ + this.permissions.hashCode() + codeBaseHash
+ - Boolean.valueOf(hasDomain).hashCode());
+ }
+ }
+
+ /**
+ * Checks if passed ProtectionDomain matches this PolicyEntry. Null ProtectionDomain of
+ * PolicyEntry implies any ProtectionDomain; non-null ProtectionDomain is
+ * compared with equals();
+ */
+ public boolean impliesProtectionDomain(ProtectionDomain pd) {
+ if (hasDomain == false) return true;
+ if (pd == null) return false;
+ if (domain.get() == null ) return false; // hasDomain already true
+ return pd.equals(domain.get()); // pd not null
+ }
+
/**
* Checks if passed CodeSource matches this PolicyEntry. Null CodeSource of
* PolicyEntry implies any CodeSource; non-null CodeSource forwards to its
@@ -142,7 +203,9 @@ public final class PolicyEntry {
* Returns true if this PolicyEntry defines no Permissions, false otherwise.
*/
public boolean isVoid() {
- return permissions.size() == 0;
+ if (permissions.size() == 0 ) return true;
+ if (hasDomain == true && domain.get() == null) return true;
+ return false;
}
@Override
@@ -150,8 +213,12 @@ public final class PolicyEntry {
if (this == o) return true;
if ( !(o instanceof PolicyEntry)) return false;
PolicyEntry pe = (PolicyEntry) o;
- if ( (cs == pe.cs || cs.equals(pe.cs)) && principals.equals(pe.principals)
- && permissions.equals(pe.permissions) ) return true;
+ if ( hasDomain == pe.hasDomain
+ && (domain == pe.domain || domain.get().equals(pe.domain.get()))
+ && (cs == pe.cs || cs.equals(pe.cs))
+ && principals.equals(pe.principals)
+ && permissions.equals(pe.permissions) )
+ return true;
return false;
}
@@ -159,4 +226,18 @@ public final class PolicyEntry {
public int hashCode(){
return hashcode;
}
+
+ @Override
+ public String toString(){
+ String domainString = ( domain == null || domain.get() == null)
+ ? "" : domain.get().toString();
+ String csString = (cs == null)? "": cs.toString();
+ String prinStr = principals.toString();
+ String permStr = permissions.toString();
+ int size = domainString.length()+ csString.length()
+ + prinStr.length() + permStr.length();
+ StringBuilder sb = new StringBuilder(size);
+ sb.append(domainString).append(csString).append(prinStr).append(permStr);
+ return sb.toString();
+ }
}
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyParser.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyParser.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyParser.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyParser.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyParser.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyParser.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyParser.java Tue May 11 20:37:47 2010
@@ -3,7 +3,7 @@
* and open the template in the editor.
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.net.URL;
import java.util.Collection;
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyUtils.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyUtils.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyUtils.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyUtils.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyUtils.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/PolicyUtils.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/PolicyUtils.java Tue May 11 20:37:47 2010
@@ -21,7 +21,7 @@
* @version $Revision$
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.io.File;
import java.io.InputStream;
@@ -41,8 +41,7 @@ import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
-
-import org.apache.river.security.concurrent.ConcurrentPermissions;
+import org.apache.river.imp.security.policy.se.ConcurrentPermissions;
/**
* This class consist of a number of static methods, which provide a common functionality
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/UnresolvedPrincipal.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/UnresolvedPrincipal.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/UnresolvedPrincipal.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/UnresolvedPrincipal.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/UnresolvedPrincipal.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/UnresolvedPrincipal.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/UnresolvedPrincipal.java Tue May 11 20:37:47 2010
@@ -20,7 +20,7 @@
* @version $Revision$
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
import java.security.Principal;
Copied: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Util.java (from r933907, incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/Util.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Util.java?p2=incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Util.java&p1=incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/Util.java&r1=933907&r2=943285&rev=943285&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/security/policy/util/Util.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/util/Util.java Tue May 11 20:37:47 2010
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.river.security.policy.util;
+package org.apache.river.imp.security.policy.util;
public class Util {