| /******************************************************************************* |
| * Copyright (c) 2005 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.framework.internal.core; |
| |
| import java.io.File; |
| import java.io.Serializable; |
| import java.lang.reflect.*; |
| import java.security.*; |
| import java.util.ArrayList; |
| import org.osgi.framework.Bundle; |
| import org.osgi.service.condpermadmin.*; |
| import org.osgi.service.permissionadmin.PermissionInfo; |
| |
| /** |
| * |
| * This is a runtime embodiment of the data stored in ConditionalPermissionInfo. |
| * It has methods to facilitate the management of Conditions and Permissions at |
| * runtime. |
| */ |
| public class ConditionalPermissionInfoImpl implements ConditionalPermissionInfo, Serializable { |
| private static final long serialVersionUID = 3258130245704825139L; |
| /** |
| * The permissions enabled by the associated Conditions. |
| */ |
| PermissionInfo perms[]; |
| /** |
| * The conditions that must be satisfied to enable the corresponding |
| * permissions. |
| */ |
| ConditionInfo conds[]; |
| |
| /** |
| * The name of the ConditionalPermissionInfo |
| */ |
| private String name; |
| |
| /** |
| * When true, this object has been deleted and any information retrieved |
| * from it should be discarded. |
| */ |
| private boolean deleted = false; |
| |
| /** |
| * When true, this object has been deleted and any information retrieved |
| * from it should be discarded. |
| */ |
| boolean isDeleted() { |
| return deleted; |
| } |
| |
| public ConditionalPermissionInfoImpl(String encoded) { |
| decode(encoded); |
| } |
| |
| public ConditionalPermissionInfoImpl(String name, ConditionInfo conds[], PermissionInfo perms[]) { |
| this.name = name; |
| this.conds = conds; |
| this.perms = perms; |
| } |
| |
| private void decode(String encoded) { |
| int start = encoded.indexOf('{'); |
| int end = encoded.lastIndexOf('}'); |
| if (start < 0 || end < start) |
| throw new IllegalArgumentException(encoded); |
| if (start != 0) |
| name = encoded.substring(0, start); |
| char[] chars = encoded.substring(start + 1, end).toCharArray(); |
| ArrayList condList = new ArrayList(); |
| ArrayList permList = new ArrayList(); |
| int pos = 0; |
| while (pos < chars.length) { |
| while (pos < chars.length && chars[pos] != '[' && chars[pos] != '(') |
| pos++; |
| if (pos == chars.length) |
| break; // no perms or conds left |
| int startPos = pos; |
| char endChar = chars[startPos] == '[' ? ']' : ')'; |
| while (chars[pos] != endChar) { |
| if (chars[pos] == '"') { |
| pos++; |
| while (chars[pos] != '"') { |
| if (chars[pos] == '\\') |
| pos++; |
| pos++; |
| } |
| } |
| pos++; |
| } |
| int endPos = pos; |
| String token = new String(chars, startPos, endPos - startPos + 1); |
| if (endChar == ']') |
| condList.add(new ConditionInfo(token)); |
| else |
| permList.add(new PermissionInfo(token)); |
| pos++; |
| } |
| conds = (ConditionInfo[]) condList.toArray(new ConditionInfo[condList.size()]); |
| perms = (PermissionInfo[]) permList.toArray(new PermissionInfo[permList.size()]); |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * @see org.osgi.service.condpermadmin.ConditionalPermissionInfo#getConditionInfos() |
| */ |
| public ConditionInfo[] getConditionInfos() { |
| if (conds == null) |
| return null; |
| ConditionInfo[] results = new ConditionInfo[conds.length]; |
| System.arraycopy(conds, 0, results, 0, conds.length); |
| return results; |
| } |
| |
| /* 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}; |
| /* Used to find condition constructors getConditions */ |
| static private final Class[] condClassArray = new Class[] {Bundle.class, ConditionInfo.class}; |
| |
| /** |
| * Adds the permissions of the given type (if any) that are part of this |
| * ConditionalPermissionInfo to the specified collection. The Permission |
| * instances are constructed using the specified permClass. |
| * |
| * @param collection the collection to add to. |
| * @param permClass the class to use to construct Permission instances. |
| * @return the number of Permissions added. |
| * @throws NoSuchMethodException |
| * @throws SecurityException |
| * @throws InvocationTargetException |
| * @throws IllegalAccessException |
| * @throws InstantiationException |
| * @throws IllegalArgumentException |
| */ |
| int addPermissions(AbstractBundle bundle, PermissionCollection collection, Class permClass) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, 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$ |
| int count = 0; |
| /* |
| * TODO: We need to cache the permission constructors to enhance performance (see bug 118813). |
| */ |
| for (int i = 0; i < perms.length; i++) { |
| if (perms[i].getType().equals(permClassName)) { |
| count++; |
| String args[] = new String[numArgs]; |
| if (numArgs > 0) |
| args[0] = perms[i].getName(); |
| if (numArgs > 1) |
| args[1] = perms[i].getActions(); |
| if (perms[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 |
| if (bundle == null) // default permissions |
| continue; // no relative file permissions |
| File target = bundle.framework.getDataFile(bundle, args[0]); |
| if (target == null) // no bundle data file area |
| continue; // no relative file permissions |
| args[0] = target.getPath(); |
| } |
| } |
| } |
| collection.add((Permission) constructor.newInstance(args)); |
| } |
| } |
| return count; |
| } |
| |
| /** |
| * Returns the Condition objects associated with this ConditionalPermissionInfo. |
| * |
| * @param bundle the bundle to be used to construct the Conditions. |
| * |
| * @return the array of Conditions that must be satisfied before permissions |
| * in the ConditionPermissionInfoImpl can be used. |
| */ |
| Condition[] getConditions(Bundle bundle) { |
| Condition conditions[] = new Condition[conds.length]; |
| for (int i = 0; i < conds.length; i++) { |
| /* |
| * TODO: I think we can pre-get the Constructors in our own |
| * constructor |
| */ |
| Class clazz; |
| try { |
| clazz = Class.forName(conds[i].getType()); |
| } catch (ClassNotFoundException e) { |
| /* If the class isn't there, we fail */ |
| return null; |
| } |
| Constructor constructor = null; |
| Method method = null; |
| try { |
| method = clazz.getMethod("getCondition", condClassArray); //$NON-NLS-1$ |
| if ((method.getModifiers() & Modifier.STATIC) == 0) |
| method = null; |
| } catch (NoSuchMethodException e) { |
| // This is a normal case |
| } |
| if (method == null) |
| try { |
| constructor = clazz.getConstructor(condClassArray); |
| } catch (NoSuchMethodException e) { |
| // TODO should post a FrameworkEvent of type error here |
| conditions[i] = Condition.FALSE; |
| continue; |
| } |
| |
| Object args[] = {bundle, conds[i]}; |
| try { |
| if (method != null) |
| conditions[i] = (Condition) method.invoke(null, args); |
| else |
| conditions[i] = (Condition) constructor.newInstance(args); |
| } catch (Throwable t) { |
| // TODO should post a FrameworkEvent of type error here |
| conditions[i] = Condition.FALSE; |
| } |
| } |
| return conditions; |
| } |
| |
| /** |
| * @see org.osgi.service.condpermadmin.ConditionalPermissionInfo#getPermissionInfos() |
| */ |
| public PermissionInfo[] getPermissionInfos() { |
| if (perms == null) |
| return null; |
| PermissionInfo[] results = new PermissionInfo[perms.length]; |
| System.arraycopy(perms, 0, results, 0, perms.length); |
| return results; |
| } |
| |
| /** |
| * |
| * @see org.osgi.service.condpermadmin.ConditionalPermissionInfo#delete() |
| */ |
| public void delete() { |
| SecurityManager sm = System.getSecurityManager(); |
| if (sm != null) |
| sm.checkPermission(new AllPermission()); |
| deleted = true; |
| condAdmin.deleteConditionalPermissionInfo(this); |
| } |
| |
| private static ConditionalPermissionAdminImpl condAdmin; |
| |
| static void setConditionalPermissionAdminImpl(ConditionalPermissionAdminImpl condAdmin) { |
| ConditionalPermissionInfoImpl.condAdmin = condAdmin; |
| } |
| |
| public String toString() { |
| StringBuffer result = new StringBuffer(); |
| if (name != null) |
| result.append(name); |
| ConditionInfo[] curConds = getConditionInfos(); |
| PermissionInfo[] curPerms = getPermissionInfos(); |
| result.append('{').append(' '); |
| if (curConds != null) |
| for (int i = 0; i < curConds.length; i++) |
| result.append(curConds[i].getEncoded()).append(' '); |
| if (curPerms != null) |
| for (int i = 0; i < curPerms.length; i++) |
| result.append(curPerms[i].getEncoded()).append(' '); |
| result.append('}'); |
| return result.toString(); |
| } |
| } |