/* JndiVariableResolver.java {{IS_NOTE Purpose: Description: History: Mon Dec 1 2007, Created by jeffliu }}IS_NOTE Copyright (C) 2006 Potix Corporation. All Rights Reserved. {{IS_RIGHT }}IS_RIGHT */ package org.zkoss.zkplus.jndi; import java.util.HashMap; import java.util.Map; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zkoss.lang.Objects; import org.zkoss.util.Maps; import org.zkoss.xel.VariableResolver; import org.zkoss.xel.XelException; /** * JndiVariableResolver, a jndi variableResolver * @author Jeff * */ public class JndiVariableResolver implements VariableResolver { private static final Logger log = LoggerFactory.getLogger(JndiVariableResolver.class); private String _jndiPrepend = null; private Map<String, Object> _jndiMapping = new HashMap<String, Object>(); /** * This constructor take arguments to initialize JNDI names. * <ul> * <li>prepend - The prepended part of JNDI name</li> * <li>mapping - The key-value pairs for JNDI name and its corresponding variable name</li> * </ul> * * The variable will be resolved in following priority * <ol> * <li>java:comp/env</li> * <li>java:comp</li> * <li>java:</li> * <li>The variable will be look up as a sessionBean with prepend.</li> * <li>The key-value pairs which is defined by mapping</li> * </ol> * </p> * * <p> * For example: * </p> * <p> * By default, session beans will bind to JNDI in the form ejbName/remote for remote interfaces and ejbName/local in the case of local interfaces. When the EJBs are deployed in an .ear file, the default jndi binding will be prepended by the name of the .ear file. * As a result, if the ear file name is foo.ear, prepend is: foo * </p> * </br> * <p> * If you define your own jndi binding, the string should be in key-value pairs format as</br> * "a=custom/MySession,b=custom/MySession2,emf=java:/EntityManagerFactory" * </p> * * @param prepend prepended part of JNDI name * @param mapping key-value pairs for JNDI name and its corresponding variable name */ public JndiVariableResolver(String prepend, String mapping) { _jndiMapping = new HashMap<String, Object>(); Maps.parse(_jndiMapping, mapping, ',', '='); _jndiPrepend = prepend; } public JndiVariableResolver() { //Do Nothing } /** * Get object from JNDI binding * @param var JNDI binding name * @return bean of context */ public Object resolveVariable(String var) throws XelException { Object variable = null; /* * First, find the variable, var in JNDI key-value map. If * not found, look for the variable as a sessionBean */ variable = jndiLookup("java:comp/env/" + var); if (variable == null) { variable = jndiLookup("java:comp/" + var); } if (variable == null) { variable = jndiLookup("java:/" + var); } if (variable == null) { variable = defaultBean(var); } if (!_jndiMapping.isEmpty() && variable == null) { Object jndiPattern = _jndiMapping.get(var); if (jndiPattern != null) { variable = jndiLookup(jndiPattern.toString()); } } return variable; } private Object defaultBean(String name) { Object variable = null; variable = jndiLookup(_jndiPrepend + "/" + name + "/local"); //If not found in local, lookup remote if (variable == null) { variable = jndiLookup(_jndiPrepend + "/" + name + "/remote"); } return variable; } private Object jndiLookup(String jndiPattern) { Object obj = null; try { Context ctx = new InitialContext(); obj = ctx.lookup(jndiPattern); } catch (NamingException ex) { //Not found, logging if (log.isDebugEnabled()) { log.debug("JNDI binding not found: " + ex); } } return obj; } public int hashCode() { return Objects.hashCode(_jndiMapping) + Objects.hashCode(_jndiPrepend); } public boolean equals(Object obj) { return this == obj || (obj instanceof JndiVariableResolver && Objects.equals(_jndiMapping, ((JndiVariableResolver) obj)._jndiMapping) && Objects.equals(_jndiPrepend, ((JndiVariableResolver) obj)._jndiPrepend)); } }