Thoughts?

/*
* 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();
       }
}

}

Reply via email to