Skip to content

Instantly share code, notes, and snippets.

@Xaerxess
Created September 27, 2012 11:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xaerxess/3793543 to your computer and use it in GitHub Desktop.
Save Xaerxess/3793543 to your computer and use it in GitHub Desktop.
Custom tag used to get static final class fields in JSP (based on Jakarta 'unstandard' custom tag library API)
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.xaerxess;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import org.springframework.util.ClassUtils;
/**
* Utility class for working with Class instances.
*/
final class ClassReflectionUtils {
/**
* Private constructor to prevent instantiation of this class.
*/
private ClassReflectionUtils() {
}
/**
* Creates and returns a map of the names of public static final constants to
* their values, for the specified class.
*
* @param className The fully qualified name of the class for which the
* constants should be determined
*
* @return {@code Map<String, Object>} from constant names to values
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static Map<String, Object> getClassConstants(final String className)
throws ClassNotFoundException, IllegalArgumentException,
IllegalAccessException {
final Map<String, Object> constants = new HashMap<String, Object>();
final Class<?> clazz = ClassUtils.forName(className,
ClassUtils.getDefaultClassLoader());
for (final Field field : clazz.getFields()) {
final int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
&& Modifier.isFinal(modifiers)) {
// null as argument because it's ignored when field is static
final Object value = field.get(null);
if (value != null) {
constants.put(field.getName(), value);
}
}
}
return constants;
}
}
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
<tag>
<name>useConstants</name>
<tag-class>com.github.xaerxess.UseConstantsTag</tag-class>
<body-content>empty</body-content>
<display-name>useConstants</display-name>
<description>
Exposes all of the public constants in a class as a map stored in
a scoped attribute. The scope may be specified, but defaults to page
scope.
</description>
<variable>
<name-from-attribute>var</name-from-attribute>
<variable-class>java.lang.Object</variable-class>
<declare>true</declare>
<scope>AT_BEGIN</scope>
<description>The name of the attribute into which the map will be stored.</description>
</variable>
<attribute>
<name>var</name>
<required>yes</required>
<rtexprvalue>no</rtexprvalue>
<description>Name of the scoped attribute into which the map will be stored.</description>
</attribute>
<attribute>
<name>className</name>
<required>yes</required>
<rtexprvalue>no</rtexprvalue>
<description>Fully qualified name of the class from which constants will be extracted.</description>
</attribute>
<attribute>
<name>scope</name>
<required>no</required>
<rtexprvalue>no</rtexprvalue>
<description>Scope into which to store the map. Default is page scope.</description>
</attribute>
<example>
To expose all of the constants in the Integer class:
<![CDATA[<un:useConstants var="const" className="java.lang.Integer" />]]>
</example>
</tag>
</taglib>
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.xaerxess;
import java.util.Map;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;
import org.springframework.util.Assert;
import org.springframework.web.util.TagUtils;
/**
* Tag that exposes all of the public constants in a class as a map stored in
* a scoped attribute. The scope may be specified, but defaults to page scope.
* <p/>
* Based on abandoned project taglibs-unstandard, specifically
* {@code org.apache.taglibs.unstandard.UseConstantsTag}. Uses Spring's TagUtils
* and ClassUtils instead of utils bundled in taglibs-unstandard, plus it
* supports generics.
*
* @see http://jakarta.apache.org/taglibs/unstandard
*/
public class UseConstantsTag extends TagSupport {
private static final long serialVersionUID = 1L;
/**
* The fully qualified name of the Java class for which constants are to be
* exposed.
*/
private String className;
/**
* The scope in which the exposed map will be stored.
*/
private String scope = TagUtils.SCOPE_PAGE;
/**
* The name of the scoped attribute in which the constants will be stored.
*/
private String var;
/**
* Construct an instance of this class.
*/
public UseConstantsTag() {
}
/**
* Retrieve the name of the class for which constants are to be exposed.
*
* @return The fully qualified class name.
*/
public String getClassName() {
return className;
}
/**
* Set the name of the class for which constants are to be exposed.
*
* @param className The fully qualified class name.
*/
public void setClassName(final String className) {
this.className = className;
}
/**
* Retrieve the scope in which the exposed map will be stored.
*
* @return The name of the scope.
*/
public String getScope() {
return scope;
}
/**
* Set the scope in which the exposed map will be stored.
*
* @param scope The name of the scope.
*/
public void setScope(final String scope) {
Assert.notNull(scope, "Scope cannot be null");
this.scope = scope;
}
/**
* Retrieve the variable name in which the exposed map will be stored.
*
* @return The name of the variable.
*/
public String getVar() {
return var;
}
/**
* Set the variable name in which the exposed map will be stored.
*
* @param var The name of the variable.
*/
public void setVar(final String var) {
this.var = var;
}
/**
* Expose the constants for a class as a scoped attribute.
*
* @return A constant that identifies what the container should do next.
*
* @throws JspException if a fatal error occurs.
*/
@Override
public int doStartTag() throws JspException {
if (className != null && var != null) {
Map<String, Object> constants;
try {
constants = ClassReflectionUtils.getClassConstants(className);
} catch (final ClassNotFoundException e) {
throw new JspTagException("Class not found: " + className, e);
} catch (final IllegalArgumentException e) {
throw new JspTagException("Illegal argument: " + className, e);
} catch (final IllegalAccessException e) {
throw new JspTagException("Illegal access: " + className, e);
}
if (!constants.isEmpty()) {
pageContext.setAttribute(var, constants, TagUtils.getScope(scope));
}
}
return SKIP_BODY;
}
/**
* Free up any resources being used by this tag handler.
*/
@Override
public void release() {
super.release();
className = null;
scope = null;
var = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment