Author: ekoneil Date: Mon Jul 19 13:44:25 2004 New Revision: 23067 Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java Log: Fixup BundleMap to handle a containsKey(Object) call.
In some JSP 2.0 EL implementations, this is called before Map.get(Object) is called. In such a situation, this was throwing an NPE because the _bundleContext object hadn't be initialized. This fixes the logic of the containsKey(Object) call to be consistent with the Map.get(Object) call. The resource bundle search is now done as follows: BundleContext -- pickup any bundles that have been declared using the <netui-data:declareBundle> tag. default -- pickup the "default" Struts resource bundle <named resource bundle> -- check ServletContext for a resource bundle with a given name BB: self DRT: NetUI pass BVT: NetUI pass CR: Daryl Modified: incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java ============================================================================== --- incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java (original) +++ incubator/beehive/trunk/netui/src/pageflow/org/apache/beehive/netui/script/common/BundleMap.java Mon Jul 19 13:44:25 2004 @@ -20,16 +20,15 @@ // java imports import java.util.Iterator; -import java.util.Set; import java.util.Locale; +import java.util.Set; -import javax.servlet.http.HttpSession; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; import javax.servlet.ServletContext; // internal imports import org.apache.beehive.netui.script.common.BundleContext.BundleNode; - import org.apache.beehive.netui.util.logging.Logger; // external imports @@ -51,12 +50,22 @@ private HttpSession _session = null; private ServletContext _application = null; + /** + * Create a BundleMap object that is used for data binding to resource bundles. + * + * @param request the current [EMAIL PROTECTED] javax.servlet.http.HttpServletRequest} object + * @param application a [EMAIL PROTECTED] javax.servlet.ServletContext} object that facilitates binding to + * resource bundles declared in Struts modules + * @param bundleContext optional [EMAIL PROTECTED] BundleContext} object that describes any existing, data bindable + * resource bundles + */ public BundleMap(HttpServletRequest request, ServletContext application, BundleContext bundleContext) { - assert bundleContext != null; + assert request != null; + assert application != null; _request = request; - _session = request.getSession(); + _session = request.getSession(false); _application = application; _bundleContext = bundleContext; } @@ -69,7 +78,7 @@ public Object get(Object name) { assert name instanceof String; - return createScriptableBundle((String)name, _bundleContext); + return createScriptableBundle((String)name); } public boolean containsKey(Object key) @@ -77,7 +86,19 @@ if(key == null) return false; - return _bundleContext.containsBundle(key.toString()); + assert key instanceof String; + + // this logic needs to match the logic used to perform the "get" call + // it is coded twice so that the containsKey call doesn't do extraneous + // object creation and checks only what it needs to + String name = (String)key; + if(_bundleContext != null && _bundleContext.containsBundle(name)) + return true; + else if(name.equals(BundleContext.DEFAULT_STRUTS_BUNDLE_NAME)) + return getDefaultStrutsModuleBundle() != null; + else if(_application.getAttribute(name) != null) + return getNamedStrutsModuleBundle(name) != null; + else return false; } public Set entrySet() @@ -85,13 +106,13 @@ throw new UnsupportedOperationException("The entrySet method is not supported"); } - private Object createScriptableBundle(String name, BundleContext bundleContext) + private Object createScriptableBundle(String name) { - if(bundleContext != null && bundleContext.containsBundle(name)) + if(_bundleContext != null && _bundleContext.containsBundle(name)) { try { - return new ScriptableBundle(name, bundleContext.getBundle(name)); + return new ScriptableBundle(name, _bundleContext.getBundle(name)); } catch(Exception e) { @@ -102,7 +123,7 @@ } else if(name.equals(BundleContext.DEFAULT_STRUTS_BUNDLE_NAME)) { - MessageResources resources = (MessageResources)_request.getAttribute(Globals.MESSAGES_KEY); + MessageResources resources = getDefaultStrutsModuleBundle(); if(resources != null) { @@ -112,7 +133,7 @@ } else if(_application.getAttribute(name) != null) { - MessageResources resources = (MessageResources)_application.getAttribute(name); + MessageResources resources = getNamedStrutsModuleBundle(name); if(resources != null) { @@ -121,7 +142,7 @@ } } - String bundleList = createBundleList(bundleContext); + String bundleList = createBundleList(); String strutsBundleList = createStrutsBundleList(); String msg = "The bundle named \"" + name + "\" was not found in the list of registered bundles with names " + @@ -131,6 +152,52 @@ throw new RuntimeException(msg); } + /** + * Lookup the "default" resource bundle for the current Struts module. + * + * @return a MessageResources object if a "default" bundle exists. <code>null</code> otherwise + */ + private MessageResources getDefaultStrutsModuleBundle() + { + Object value = _request.getAttribute(Globals.MESSAGES_KEY); + if(value instanceof MessageResources) + return (MessageResources)value; + else + { + if(value != null) + if(_logger.isWarnEnabled()) _logger.warn("Can not resolve the default module bundle." + + " The object resolved from the request is of type " + (value != null ? value.getClass() : "null")); + return null; + } + } + + /** + * Lookup a specific resource bundle for the current Struts module. + * + * @param name the name of the resource bundle to lookup + * @return a MessageResources object if a bundle matching the given name exists. <code>null</code> otherwise. + */ + private MessageResources getNamedStrutsModuleBundle(String name) + { + Object value = _application.getAttribute(name); + if(value instanceof MessageResources) + return (MessageResources)value; + else + { + if(value != null) + if(_logger.isWarnEnabled()) _logger.warn("Can not resolve module bundle with name \"" + name + + "\". The object resolved from ServletContext is of type " + (value != null ? value.getClass() : "null")); + return null; + } + } + + /** + * Utility method that discovers the [EMAIL PROTECTED] java.util.Locale} for the current request. + * + * todo: this code is duped in the codebase and needs to be localized into a utility + * + * @return the [EMAIL PROTECTED] java.util.Locale} to use when doing bundle data binding + */ private final Locale retrieveUserLocale() { String locale = null; @@ -153,13 +220,13 @@ return userLocale; } - private final String createBundleList(BundleContext bundleContext) + private final String createBundleList() { StringBuilder nameList = new StringBuilder(32); nameList.append("["); - if(bundleContext != null) + if(_bundleContext != null) { - Iterator iterator = bundleContext.getBundleNames(); + Iterator iterator = _bundleContext.getBundleNames(); for(int i = 0; iterator.hasNext(); i++) { if(i > 0) nameList.append(", "); @@ -207,6 +274,9 @@ ScriptableBundle(String propertiesName, BundleNode bundle) { + assert _bundle != null; + assert _propertiesName != null; + _bundle = bundle; _propertiesName = propertiesName; }
