Completed most of the functionality for AdminPermission.
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@386461 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.framework/src/main/java/org/osgi/framework/AdminPermission.java b/org.apache.felix.framework/src/main/java/org/osgi/framework/AdminPermission.java
index b640c6a..b854ab1 100644
--- a/org.apache.felix.framework/src/main/java/org/osgi/framework/AdminPermission.java
+++ b/org.apache.felix.framework/src/main/java/org/osgi/framework/AdminPermission.java
@@ -17,10 +17,9 @@
package org.osgi.framework;
import java.security.*;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
+import java.util.*;
-import sun.net.www.MeteredStream;
+import org.apache.felix.framework.FilterImpl;
/**
* <p>
@@ -56,26 +55,48 @@
LIFECYCLE_MASK | LISTENER_MASK | METADATA_MASK |
RESOLVE_MASK | RESOURCE_MASK | STARTLEVEL_MASK;
- private String m_bundleFilter = null;
private String m_actions = null;
private int m_actionMask = 0;
+ // Cached filter for permissions created with a filter when
+ // granting admin permissions.
+ private FilterImpl m_filterImpl = null;
+
+ // Bundle associated with the permission when checking
+ // admin permissions.
+ private Bundle m_bundle = null;
+ // Cached bundle property dictionary when checking
+ // admin permissions.
+ private Dictionary m_bundleDict = null;
+
+ // This constructor is only used when granting an admin permission.
public AdminPermission()
{
this("*", "*");
}
+ // This constructor is only used when checking a granted admin permission.
public AdminPermission(Bundle bundle, String actions)
{
- this(createNameFilter(bundle), actions);
+ this(createName(bundle), actions);
+ m_bundle = bundle;
}
+ // This constructor is only used when granting an admin permission.
public AdminPermission(String filter, String actions)
{
- super((filter == null) ? "*" : filter);
+ super((filter == null) || (filter.equals("*")) ? "(id=*)" : filter);
m_actionMask = parseActions(actions);
}
+ // This constructor is only used by the admin permission collection
+ // when combining admin permissions.
+ private AdminPermission(String filter, int actionMask)
+ {
+ super((filter == null) || (filter.equals("*")) ? "(id=*)" : filter);
+ m_actionMask = actionMask;
+ }
+
public boolean equals(Object obj)
{
if (obj == this)
@@ -90,12 +111,12 @@
AdminPermission p = (AdminPermission) obj;
- return m_bundleFilter.equals(p.m_bundleFilter) && (m_actionMask == p.m_actionMask);
+ return getName().equals(p.getName()) && (m_actionMask == p.m_actionMask);
}
public int hashCode()
{
- return m_bundleFilter.hashCode() ^ getActions().hashCode();
+ return getName().hashCode() ^ getActions().hashCode();
}
public String getActions()
@@ -116,12 +137,27 @@
AdminPermission admin = (AdminPermission) p;
- if (m_actionMask != admin.m_actionMask)
+ // Make sure the action mask is a subset.
+ if ((m_actionMask & admin.m_actionMask) != admin.m_actionMask)
{
return false;
}
- // TODO: SECURITY - Still need check that the "name" filter.
+ // Otherwise, see if this permission's filter matches the
+ // dictionary of the passed in permission.
+ if (m_filterImpl == null)
+ {
+ try
+ {
+ m_filterImpl = new FilterImpl(getName());
+ }
+ catch (InvalidSyntaxException ex)
+ {
+ return false;
+ }
+
+ return m_filterImpl.match(admin.getBundleDictionary());
+ }
return false;
}
@@ -131,6 +167,34 @@
return new AdminPermissionCollection();
}
+ private Dictionary getBundleDictionary()
+ {
+ if (m_bundleDict == null)
+ {
+ // Add bundle properties to dictionary.
+ m_bundleDict = new Hashtable();
+ m_bundleDict.put("id", new Long(m_bundle.getBundleId()));
+ m_bundleDict.put("name", m_bundle.getSymbolicName());
+ // Add location in privileged block since it performs a security check.
+ if (System.getSecurityManager() != null)
+ {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run()
+ {
+ m_bundleDict.put("location", m_bundle.getLocation());
+ return null;
+ }
+ });
+ }
+ else
+ {
+ m_bundleDict.put("location", m_bundle.getLocation());
+ }
+ // TODO: SECURITY - Add bundle signer properties to dictionary.
+ }
+ return m_bundleDict;
+ }
+
private static int parseActions(String actions)
{
if (actions == null)
@@ -247,7 +311,7 @@
return sb.toString();
}
- private static String createNameFilter(Bundle bundle)
+ private static String createName(Bundle bundle)
{
StringBuffer sb = new StringBuffer();
sb.append("(id=");
@@ -258,21 +322,58 @@
final class AdminPermissionCollection extends PermissionCollection
{
+ private HashMap m_map = new HashMap();
+
public void add(Permission permission)
{
- // TODO: SECURITY - AdminPermissionCollection.add()
+ if (!(permission instanceof AdminPermission))
+ {
+ throw new IllegalArgumentException("Invalid permission: " + permission);
+ }
+ else if (isReadOnly())
+ {
+ throw new SecurityException(
+ "Cannot add to read-only permission collection.");
+ }
+
+ AdminPermission admin = (AdminPermission) permission;
+ AdminPermission current = (AdminPermission) m_map.get(admin.getName());
+ if (current != null)
+ {
+ if (admin.m_actionMask != current.m_actionMask)
+ {
+ m_map.put(admin.getName(),
+ new AdminPermission(admin.getName(),
+ admin.m_actionMask | current.m_actionMask));
+ }
+ }
+ else
+ {
+ m_map.put(admin.getName(), admin);
+ }
}
public boolean implies(Permission permission)
{
- // TODO: SECURITY - AdminPermissionCollection.implies()
+ if (!(permission instanceof AdminPermission))
+ {
+ return false;
+ }
+
+ for (Iterator iter = m_map.values().iterator(); iter.hasNext(); )
+ {
+ if (((AdminPermission) iter.next()).implies(permission))
+ {
+ return true;
+ }
+ }
+
return false;
}
public Enumeration elements()
{
- // TODO: SECURITY - AdminPermissionCollection.elements()
- return null;
+ return Collections.enumeration(m_map.values());
}
}
}
\ No newline at end of file