blob: de7175c6aa5a3405d249dc7fe5c307234f67dd47 [file] [log] [blame]
/*
* 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 java.security;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamField;
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.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;
/**
* {@code UnresolvedPermissionCollection} represents a specific {@code
* PermissionCollection} for storing {@link UnresolvedPermission} instances.
* Contained elements are grouped by their target type.
*/
final class UnresolvedPermissionCollection extends PermissionCollection {
private static final long serialVersionUID = -7176153071733132400L;
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("permissions", Hashtable.class), };
// elements of the collection.
private transient Map klasses = new HashMap();
/**
* Adds an unresolved permission to this {@code
* UnresolvedPermissionCollection}.
*
* @param permission
* the permission to be added.
* @throws SecurityException
* if this collection is read only.
* @throws IllegalArgumentException
* if {@code permission} is {@code null} or not an {@code
* UnresolvedPermission}.
*/
public void add(Permission permission) {
if (isReadOnly()) {
throw new SecurityException("collection is read-only");
}
if (permission == null || permission.getClass() != UnresolvedPermission.class) {
throw new IllegalArgumentException("Invalid permission: " + permission);
}
synchronized (klasses) {
String klass = permission.getName();
Collection klassMates = (Collection)klasses.get(klass);
if (klassMates == null) {
klassMates = new HashSet();
klasses.put(klass, klassMates);
}
klassMates.add(permission);
}
}
public Enumeration elements() {
Collection all = new ArrayList();
for (Iterator iter = klasses.values().iterator(); iter.hasNext();) {
all.addAll((Collection)iter.next());
}
return Collections.enumeration(all);
}
/**
* Always returns {@code false}.
*
* @return always {@code false}
* @see UnresolvedPermission#implies(Permission).
*/
public boolean implies(Permission permission) {
return false;
}
/**
* Returns true if this collection contains unresolved permissions
* with the same classname as argument permission.
*/
boolean hasUnresolved(Permission permission) {
return klasses.containsKey(permission.getClass().getName());
}
/**
* Resolves all permissions of the same class as the specified target
* permission and adds them to the specified collection. If passed
* collection is {@code null} and some unresolved permissions were resolved,
* an appropriate new collection is instantiated and used. All resolved
* permissions are removed from this unresolved collection, and collection
* with resolved ones is returned.
*
* @param target
* a kind of permissions to be resolved.
* @param holder
* an existing collection for storing resolved permissions.
* @return a collection containing resolved permissions (if any found)
*/
PermissionCollection resolveCollection(Permission target,
PermissionCollection holder) {
String klass = target.getClass().getName();
if (klasses.containsKey(klass)) {
synchronized (klasses) {
Collection klassMates = (Collection)klasses.get(klass);
for (Iterator iter = klassMates.iterator(); iter.hasNext();) {
UnresolvedPermission element = (UnresolvedPermission)iter
.next();
Permission resolved = element.resolve(target.getClass());
if (resolved != null) {
if (holder == null) {
holder = target.newPermissionCollection();
if (holder == null) {
holder = new PermissionsHash();
}
}
holder.add(resolved);
iter.remove();
}
}
if (klassMates.size() == 0) {
klasses.remove(klass);
}
}
}
return holder;
}
/**
* Output fields via default mechanism.
*/
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
Hashtable permissions = new Hashtable();
for (Iterator iter = klasses.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
permissions.put(key, new Vector(((Collection) entry.getValue())));
}
ObjectOutputStream.PutField fields = out.putFields();
fields.put("permissions", permissions);
out.writeFields();
}
/**
* Reads the object from stream and checks elements grouping for validity.
*/
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
ObjectInputStream.GetField fields = in.readFields();
Map permissions = (Map)fields.get("permissions", null);
klasses = new HashMap();
synchronized (klasses) {
for (Iterator iter = permissions.entrySet().iterator(); iter
.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
Collection values = (Collection) entry.getValue();
for (Iterator iterator = values.iterator(); iterator.hasNext();) {
UnresolvedPermission element =
(UnresolvedPermission) iterator.next();
if (!element.getName().equals(key)) {
throw new InvalidObjectException("collection is corrupted");
}
}
klasses.put(key, new HashSet(values));
}
}
}
}