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