import java.io.IOException; import java.io.Writer; import java.util.HashMap; import javax.servlet.http.HttpSession; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.MethodInvocationException; import org.apache.velocity.runtime.directive.Directive; import org.apache.velocity.runtime.directive.DirectiveConstants; import org.apache.velocity.runtime.RuntimeServices; import org.apache.velocity.context.InternalContextAdapter; import org.apache.velocity.runtime.parser.node.Node; /** * Example of a velocity directive which can be used to load a JavaBean into a velocity context * so that it can be accessed in a template.
* Note: this needs to be added to the properties of the velocity engine before it is initialised using: *
 * ve.setProperty("userdirective", ?UseBeanDirective?);
 * 
* @author Jason R Briggs */ public class UseBeanDirective extends Directive { private static final String APPLICATION_SCOPE = "application"; private static final String EMPTY = ""; private static final String PAGE_SCOPE = "page"; private static final String QUOTES = "\"'"; private static final String SESSION_SCOPE = "session"; private static final String USEBEAN = "usebean"; private static final int APPLICATION = 1; private static final int SESSION = 2; private static final int PAGE = 3; private static HashMap beanClasses = new HashMap(); private static HashMap beanNames = new HashMap(); private static HashMap appScopeBeans = new HashMap(); public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException { int count = node.jjtGetNumChildren(); String name = node.jjtGetChild(0).getFirstToken().toString(); String className = node.jjtGetChild(1).getFirstToken().toString(); int scope; String tmp; if (count >= 3) { tmp = node.jjtGetChild(2).getFirstToken().toString(); } else { tmp = EMPTY; } // set the scope variable if (tmp.equals(APPLICATION_SCOPE)) { scope = APPLICATION; } else if (tmp.equals(SESSION_SCOPE)) { scope = SESSION; } else { scope = PAGE; } // cache the classnames, so we don't try to load the classes every time if (!beanClasses.containsKey(className)) { synchronized (beanClasses) { if (!beanClasses.containsKey(className)) { try { String cn = remove(className, QUOTES); Class c = Class.forName(cn); beanClasses.put(className, c); } catch (Exception e) { e.printStackTrace(); throw new MethodInvocationException(e.getMessage(), e, getName()); } } } } HttpSession session = null; try { Object obj = null; // if application scope, we use a hashmap to store the beans if (scope == APPLICATION && appScopeBeans.containsKey(name)) { obj = appScopeBeans.get(name); } // if session scope, try to get the bean from the user's session // (note: stored in the velocity context) else if (scope == SESSION) { session = (HttpSession)context.get(SESSION_SCOPE); obj = session.getAttribute(name); } // if we haven't managed to get an object by now, we'll // just instantiate it using the class if (obj == null) { Class c = (Class)beanClasses.get(className); obj = c.newInstance(); } // put the object into the context context.put(name, obj); // depending upon the scope, put it in the cache of app beans // or into the session if (scope == APPLICATION && !appScopeBeans.containsKey(name)) { appScopeBeans.put(name, obj); } else if (scope == SESSION) { session.setAttribute(name, obj); } } catch (Exception e) { throw new MethodInvocationException(e.getMessage(), e, getName()); } return true; } public int getType() { return DirectiveConstants.LINE; } public String getName() { return USEBEAN; } private static final String remove(String s, String chars) { if (s == null) { return EMPTY; } else { StringBuffer sb = new StringBuffer(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (chars.indexOf(c) < 0) { sb.append(c); } } return sb.toString(); } } }