NIHVIVO-3523 Rewrite the PermissionRegistry to be immutable, and to distribute BrokenPermissions when someone asks for a Permission that doesn't exist.

This commit is contained in:
j2blake 2011-12-19 21:19:58 +00:00
parent 9d89fc291c
commit 7d7503fc22
7 changed files with 153 additions and 41 deletions

View file

@ -0,0 +1,55 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
/**
* This is what the PermissionRegistry hands out if you ask for a Permission
* that it doesn't know about. Nothing is authorized by this Permission.
*/
public class BrokenPermission implements Permission {
private final String uri;
private final String localName;
private final String namespace;
public BrokenPermission(String uri) {
this.uri = uri;
int namespaceBreak = uri.lastIndexOf("#");
if (namespaceBreak == -1) {
namespaceBreak = uri.lastIndexOf("/");
}
int localNameStart = namespaceBreak + 1;
this.namespace = uri.substring(0, localNameStart);
this.localName = uri.substring(localNameStart);
}
@Override
public String getUri() {
return uri;
}
@Override
public String getLocalName() {
return localName;
}
@Override
public String getNamespace() {
return namespace;
}
@Override
public boolean isAuthorized(RequestedAction whatToAuth) {
return false;
}
@Override
public String toString() {
return "BrokenPermission[" + uri + "]";
}
}

View file

@ -37,7 +37,7 @@ public interface Permission {
@Override
public String getUri() {
return "java://" + Permission.class.getName() + "#NOT_AUTHORIZED";
return "java:" + Permission.class.getName() + "#NOT_AUTHORIZED";
}
@Override
@ -47,7 +47,7 @@ public interface Permission {
@Override
public String getNamespace() {
return "java://" + Permission.class.getName();
return "java:" + Permission.class.getName();
}
@Override

View file

@ -2,16 +2,24 @@
package edu.cornell.mannlib.vitro.webapp.auth.permissions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
* Holds a map of known Permission objects by URI. Resides in the
* An immutable collection of Permission objects, keyed by URI. Resides in the
* ServletContext.
*
* This is not thread-safe, so all Permissions should be added during context
@ -23,9 +31,35 @@ public class PermissionRegistry {
private static final String ATTRIBUTE_NAME = PermissionRegistry.class
.getName();
/**
* Has the registry been created yet?
*/
public static boolean isRegistryCreated(ServletContext ctx) {
return ctx.getAttribute(ATTRIBUTE_NAME) instanceof PermissionRegistry;
}
/**
* Get the registry from the context. If the context doesn't contain a
* registry yet, create one.
* Create the registry and store it in the context.
*/
public static void createRegistry(ServletContext ctx,
Collection<? extends Permission> permissions) {
if (ctx == null) {
throw new NullPointerException("ctx may not be null.");
}
if (permissions == null) {
throw new NullPointerException("permissions may not be null.");
}
if (ctx.getAttribute(ATTRIBUTE_NAME) != null) {
throw new IllegalStateException(
"PermissionRegistry has already been set.");
}
PermissionRegistry registry = new PermissionRegistry(permissions);
ctx.setAttribute(ATTRIBUTE_NAME, registry);
}
/**
* Get the registry from the context. If there isn't one, throw an exception.
*/
public static PermissionRegistry getRegistry(ServletContext ctx) {
if (ctx == null) {
@ -33,46 +67,34 @@ public class PermissionRegistry {
}
Object o = ctx.getAttribute(ATTRIBUTE_NAME);
if (o instanceof PermissionRegistry) {
return (PermissionRegistry) o;
}
if (o != null) {
log.error("Error: PermissionRegistry was set to an "
if (o == null) {
throw new IllegalStateException(
"PermissionRegistry has not been set.");
} else if (!(o instanceof PermissionRegistry)) {
throw new IllegalStateException("PermissionRegistry was set to an "
+ "invalid object: " + o);
}
PermissionRegistry registry = new PermissionRegistry();
ctx.setAttribute(ATTRIBUTE_NAME, registry);
return registry;
return (PermissionRegistry) o;
}
private final Map<String, Permission> permissionsMap = new HashMap<String, Permission>();
private final Map<String, Permission> permissionsMap;
private PermissionRegistry() {
// nothing to initialize;
public PermissionRegistry(Collection<? extends Permission> permissions) {
Map<String, Permission> map = new HashMap<String, Permission>();
for (Permission p : permissions) {
String uri = p.getUri();
if (map.containsKey(uri)) {
throw new IllegalStateException("A Permission is already "
+ "registered with this URI: '" + uri + "'.");
}
map.put(uri, p);
}
this.permissionsMap = Collections.unmodifiableMap(map);
}
/**
* Add a Permission to the registry. If a Permission with the same URI is
* already present, throw an IllegalStateException.
*/
public void addPermission(Permission p) {
if (p == null) {
throw new NullPointerException("p may not be null.");
}
String uri = p.getUri();
if (isPermission(uri)) {
throw new IllegalStateException(
"A Permission is already registered with this URI: '" + uri
+ "'.");
}
permissionsMap.put(uri, p);
}
/**
* Is there already a Permission registered with this URI?
* Is there a Permission registered with this URI?
*/
public boolean isPermission(String uri) {
return permissionsMap.containsKey(uri);
@ -80,14 +102,47 @@ public class PermissionRegistry {
/**
* Get the permission that is registered with this URI. If there is no such
* Permission, return a dummy Permission that always denies authorization.
* Permission, return a BrokenPermission that always denies authorization.
*
* If you want to know whether an actual Permission has been registered at
* this URI, call isPermission() instead.
*/
public Permission getPermission(String uri) {
Permission p = permissionsMap.get(uri);
return (p == null) ? Permission.NOT_AUTHORIZED : p;
if (p == null) {
log.warn("No Permission is registered for '" + uri + "'");
return new BrokenPermission(uri);
}
return p;
}
// ----------------------------------------------------------------------
// Setup class
// ----------------------------------------------------------------------
public static class Setup implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
try {
List<Permission> permissions = new ArrayList<Permission>();
permissions.addAll(SimplePermission.getAllInstances());
PermissionRegistry.createRegistry(ctx, permissions);
ss.info(this, "Created the PermissionRegistry with "
+ permissions.size() + " permissions.");
} catch (Exception e) {
ss.fatal(this, "Failed to initialize the PermissionRegistry.",
e);
}
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
sce.getServletContext().removeAttribute(ATTRIBUTE_NAME);
}
}
}

View file

@ -22,7 +22,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAct
public class SimplePermission implements Permission {
private static final Log log = LogFactory.getLog(SimplePermission.class);
private static final String NAMESPACE = "java://"
private static final String NAMESPACE = "java:"
+ SimplePermission.class.getName() + "#";
private static final Map<String, SimplePermission> allInstances = new HashMap<String, SimplePermission>();

View file

@ -20,7 +20,7 @@ public class SimpleRequestedAction extends RequestedAction {
@Override
public String getURI() {
return "java://" + this.getClass().getName() + "#" + localName;
return "java:" + this.getClass().getName() + "#" + localName;
}
@Override

View file

@ -3,7 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces;
public class RequestActionConstants {
public static String actionNamespace = "java://";
public static String actionNamespace = "java:";
public static String SOME_URI = "?SOME_URI";
public static String SOME_LITERAL = "?SOME_LITERAL";