package org.appfuse.webapp.taglib;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.Constants;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* <p>This class is designed to put all the public variables in a class to a
* specified scope - designed for exposing a Constants class to Tag
* Libraries.</p>
*
* <p>It is designed to be used as follows:
* <pre><tag:constants /></pre>
* </p>
*
* <p>Optional values are "className" (fully qualified) and "scope".</p>
*
* <p>
* <a href="BaseAction.java.html"><i>View Source</i></a>
* </p>
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
*/
public class ConstantsTag extends TagSupport {
private static final long serialVersionUID = 3258417209566116146L;
private final Log log = LogFactory.getLog(ConstantsTag.class);
/**
* The class to expose the variables from.
*/
private String clazz = Constants.class.getName();
/**
* The scope to be put the variable in.
*/
protected String scope;
/**
* The single variable to expose.
*/
protected String var;
/**
* Main method that does processing and exposes Constants in specified scope
* @return int
* @throws JspException if processing fails
*/
@Override
public int doStartTag() throws JspException {
// Using reflection, get the available field names in the class
Class c = null;
int toScope = PageContext.PAGE_SCOPE;
if (scope != null) {
toScope = getScope(scope);
}
try {
c = Class.forName(clazz);
} catch (ClassNotFoundException cnf) {
log.error("ClassNotFound - maybe a typo?");
throw new JspException(cnf.getMessage());
}
try {
// if var is null, expose all variables
if (var == null) {
Field[] fields = c.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field field : fields) {
pageContext.setAttribute(field.getName(), field.get(this), toScope);
}
} else {
try {
Object value = c.getField(var).get(this);
pageContext.setAttribute(c.getField(var).getName(), value, toScope);
} catch (NoSuchFieldException nsf) {
log.error(nsf.getMessage());
throw new JspException(nsf);
}
}
} catch (IllegalAccessException iae) {
log.error("Illegal Access Exception - maybe a classloader issue?");
throw new JspException(iae);
}
// Continue processing this page
return (SKIP_BODY);
}
public void setClassName(String clazz) {
this.clazz = clazz;
}
public String getClassName() {
return this.clazz;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getScope() {
return (this.scope);
}
public void setVar(String var) {
this.var = var;
}
public String getVar() {
return (this.var);
}
/**
* Release all allocated resources.
*/
public void release() {
super.release();
clazz = null;
scope = Constants.class.getName();
}
/**
* Maps lowercase JSP scope names to their PageContext integer constant
* values.
*/
private static final Map<String, Integer> SCOPES = new HashMap<String, Integer>();
/**
* Initialize the scope names map and the encode variable
*/
static {
SCOPES.put("page", PageContext.PAGE_SCOPE);
SCOPES.put("request", PageContext.REQUEST_SCOPE);
SCOPES.put("session", PageContext.SESSION_SCOPE);
SCOPES.put("application", PageContext.APPLICATION_SCOPE);
}
/**
* Converts the scope name into its corresponding PageContext constant value.
* @param scopeName Can be "page", "request", "session", or "application" in any
* case.
* @return The constant representing the scope (ie. PageContext.REQUEST_SCOPE).
* @throws JspException if the scopeName is not a valid name.
*/
public int getScope(String scopeName) throws JspException {
Integer scope = (Integer) SCOPES.get(scopeName.toLowerCase());
if (scope == null) {
throw new JspException("Scope '" + scopeName + "' not a valid option");
}
return scope;
}
}