blob: cbea15e77f59af6cab002af816cda583e83d9695 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.permadmin;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.*;
import java.util.Enumeration;
import java.util.HashMap;
import org.osgi.service.permissionadmin.PermissionInfo;
public final class PermissionInfoCollection extends PermissionCollection {
private static final long serialVersionUID = 3140511562980923957L;
/* Used to find permission constructors in addPermissions */
static private final Class twoStringClassArray[] = new Class[] {String.class, String.class};
static private final Class oneStringClassArray[] = new Class[] {String.class};
static private final Class noArgClassArray[] = new Class[] {};
static private final Class[][] permClassArrayArgs = new Class[][] {noArgClassArray, oneStringClassArray, twoStringClassArray};
/* @GuardedBy(cachedPermisssionCollections) */
private final HashMap cachedPermissionCollections = new HashMap();
private final boolean hasAllPermission;
private final PermissionInfo[] permInfos;
public PermissionInfoCollection(PermissionInfo[] permInfos) {
this.permInfos = permInfos;
boolean tempAllPermissions = false;
for (int i = 0; i < permInfos.length && !tempAllPermissions; i++)
if (permInfos[i].getType().equals(AllPermission.class.getName()))
tempAllPermissions = true;
this.hasAllPermission = tempAllPermissions;
setReadOnly(); // collections are managed with ConditionalPermissionAdmin
}
public void add(Permission arg0) {
throw new SecurityException();
}
public Enumeration elements() {
// TODO return an empty enumeration for now;
return BundlePermissions.EMPTY_ENUMERATION;
}
public boolean implies(Permission perm) {
if (hasAllPermission)
return true;
Class permClass = perm.getClass();
PermissionCollection collection;
synchronized (cachedPermissionCollections) {
collection = (PermissionCollection) cachedPermissionCollections.get(permClass);
}
// must populate the collection outside of the lock to prevent class loader deadlock
if (collection == null) {
collection = perm.newPermissionCollection();
if (collection == null)
collection = new PermissionsHash();
try {
addPermissions(collection, permClass);
} catch (Exception e) {
throw (SecurityException) new SecurityException("Exception creating permissions: " + e.getClass().getName() + ": " + e.getMessage()).initCause(e); //$NON-NLS-1$ //$NON-NLS-2$
}
synchronized (cachedPermissionCollections) {
// check to see if another thread beat this thread at adding the collection
PermissionCollection exists = (PermissionCollection) cachedPermissionCollections.get(permClass);
if (exists != null)
collection = exists;
else
cachedPermissionCollections.put(permClass, collection);
}
}
return collection.implies(perm);
}
PermissionInfo[] getPermissionInfos() {
return permInfos;
}
private void addPermissions(PermissionCollection collection, Class permClass) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
String permClassName = permClass.getName();
Constructor constructor = null;
int numArgs = -1;
for (int i = permClassArrayArgs.length - 1; i >= 0; i--) {
try {
constructor = permClass.getConstructor(permClassArrayArgs[i]);
numArgs = i;
break;
} catch (NoSuchMethodException e) {
// ignore
}
}
if (constructor == null)
throw new NoSuchMethodException(permClass.getName() + ".<init>()"); //$NON-NLS-1$
/*
* TODO: We need to cache the permission constructors to enhance performance (see bug 118813).
*/
for (int i = 0; i < permInfos.length; i++) {
if (permInfos[i].getType().equals(permClassName)) {
String args[] = new String[numArgs];
if (numArgs > 0)
args[0] = permInfos[i].getName();
if (numArgs > 1)
args[1] = permInfos[i].getActions();
if (permInfos[i].getType().equals("java.io.FilePermission")) { //$NON-NLS-1$
// map FilePermissions for relative names to the bundle's data area
if (!args[0].equals("<<ALL FILES>>")) { //$NON-NLS-1$
File file = new File(args[0]);
if (!file.isAbsolute()) { // relative name
// TODO need to figure out how to do relative FilePermissions from the dataFile
continue;
}
}
}
collection.add((Permission) constructor.newInstance(args));
}
}
}
void clearPermissionCache() {
synchronized (cachedPermissionCollections) {
cachedPermissionCollections.clear();
}
}
}