diff --git a/webapp/config/tlds/VitroUtils.tld b/webapp/config/tlds/VitroUtils.tld index 401185a7f..1b4cc369b 100644 --- a/webapp/config/tlds/VitroUtils.tld +++ b/webapp/config/tlds/VitroUtils.tld @@ -65,14 +65,14 @@ directed to the home page, which will display an "insufficient authorization" message. - The requested actions are specified as a comma delimited list of names (with - optional spaces). These names must match against the map of classes in - JspPolicyHelper, or an error will be logged and the authorization will fail. + The requested actions are specified as a comma delimited list of class names. + These must be RequestedAction classes, each with a no-argument public + constructor. edu.cornell.mannlib.vitro.webapp.web.jsptags.RequiresAuthorizationFor empty - actions + classNames true true diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java index 9fc8d7a84..5d780452c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/jsptags/RequiresAuthorizationFor.java @@ -3,9 +3,8 @@ package edu.cornell.mannlib.vitro.webapp.web.jsptags; import java.util.Collection; -import java.util.HashMap; +import java.util.Collections; import java.util.HashSet; -import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -19,33 +18,24 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.LoginStatusBean; import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction; -import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages; import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet; /** * Confirm that the user is authorized to perform each of the RequestedActions. * - * The user specifies the actions as a comma delimited list of names (with - * optional spaces). These names are matched against the map of recognized - * names. If no match is found, an error is logged and the authorization fails. + * The user specifies the actions as a comma delimited list of class names (with + * optional spaces). The classes named must be extensions of RequestedAction + * (usually implementations of UsePagesRequestedAction), and each class must + * have a no-argument public constructor. */ public class RequiresAuthorizationFor extends BodyTagSupport { private static final Log log = LogFactory .getLog(RequiresAuthorizationFor.class); - /** - * These are the only action names that we recognize. - */ - private static final Map actionMap = new HashMap(); - static { - actionMap.put("UseAdvancedDataToolsPages", - new UseAdvancedDataToolsPages()); - } + String classNamesString = ""; - String actionNames = ""; - - public void setActions(String actionNames) { - this.actionNames = actionNames; + public void setClassNames(String classNamesString) { + this.classNamesString = classNamesString; } /** @@ -67,7 +57,7 @@ public class RequiresAuthorizationFor extends BodyTagSupport { * are authorized for those actions. */ private boolean isAuthorized() { - Collection actions = parseActionNames(); + Collection actions = instantiateActions(); if (actions == null) { return false; } @@ -76,25 +66,66 @@ public class RequiresAuthorizationFor extends BodyTagSupport { } /** - * Parse the string and pull the corresponding actions from the map. If we - * can't do that, complain and return null. + * Break the string into class names. Confirm that each class is + * RequestedAction or a subclass of it. Create an instance of each class. + * + * If we can't do all of that, complain and return null. */ - private Collection parseActionNames() { - Set actions = new HashSet(); + private Set instantiateActions() { + Set classNames = parseClassNames(); + if (classNames.isEmpty()) { + return Collections.emptySet(); + } - for (String part : actionNames.split("[\\s],[\\s]")) { - String key = part.trim(); - if (key.isEmpty()) { - continue; + Set> actionClasses = loadClassesAndCheckTypes(classNames); + if (actionClasses == null) { + return null; + } + + return getInstancesFromClasses(actionClasses); + } + + private Set parseClassNames() { + Set names = new HashSet(); + for (String part : classNamesString.split("[\\s],[\\s]")) { + String name = part.trim(); + if (!name.isEmpty()) { + names.add(name); } + } + return names; + } - if (actionMap.containsKey(key)) { - log.debug("checking authorization for '" + key + "'"); - actions.add(actionMap.get(key)); - } else { - log.error("JSP requested authorization for unknown action: '" - + key + "'"); + private Set> loadClassesAndCheckTypes( + Set classNames) { + Set> classes = new HashSet>(); + for (String className : classNames) { + try { + Class clazz = Class.forName(className); + classes.add(clazz.asSubclass(RequestedAction.class)); + } catch (ClassNotFoundException e) { + log.error("Can't load action class: '" + className + "'"); return null; + } catch (ClassCastException e) { + log.error("Action class is not a subclass of RequestedAction: '" + + className + "'"); + return null; + } + } + return classes; + } + + private Set getInstancesFromClasses( + Set> actionClasses) { + Set actions = new HashSet(); + for (Class actionClass : actionClasses) { + try { + RequestedAction action = actionClass.newInstance(); + actions.add(action); + } catch (Exception e) { + log.error("Failed to create an instance of '" + + actionClass.getName() + + "'. Does it have a public zero-argument constructor?"); } } return actions;