Author: craigmcc
Date: Wed Nov 22 20:23:00 2006
New Revision: 478459
URL: http://svn.apache.org/viewvc?view=rev&rev=478459
Log:
Refactor validator resource configuration into a ServletContextListener that
is called at startup time, for the following reasons:
* Architectural similarity to other Shale modules
* Ability to "fail fast" on invalid configuration resource names
* Ability to clean up the Commons BeanUtils and Commons Logging
modules that can otherwise result in memory leaks and/or locked
JAR files on Windows platforms.
SHALE-340
Added:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java
(with props)
Modified:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/CommonsValidator.java
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/Globals.java
shale/framework/trunk/shale-validator/src/main/resources/META-INF/taglib.tld
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/CommonsValidatorTestCase.java
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/ValidatorDefaultTestCase.java
Modified:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/CommonsValidator.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/CommonsValidator.java?view=diff&rev=478459&r1=478458&r2=478459
==============================================================================
---
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/CommonsValidator.java
(original)
+++
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/CommonsValidator.java
Wed Nov 22 20:23:00 2006
@@ -17,6 +17,7 @@
package org.apache.shale.validator;
+import com.sun.org.apache.bcel.internal.classfile.ConstantString;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
@@ -453,64 +454,18 @@
}
- /**
- * This method lazily configures validator resources by reading either
- * the default <code>validalidator-rules.xml</code> file in
- * shale-core.jar or the list of resources configured using the init
- * param <code>org.apache.shale.validator.VALIDATOR_RULES</code>.
- *
- * @return validator resources loaded from the configuration file.
- */
+ /**
+ * <p>Return the validator resources that were configured and cached
+ * at application startup time.</p>
+ */
private static ValidatorResources getValidatorResources() {
- final String VALIDATOR_RESOURCES_KEY =
- "org.apache.shale.validator.resources";
+
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext external = context.getExternalContext();
Map applicationMap = external.getApplicationMap();
- ValidatorResources validatorResources
- = (ValidatorResources) applicationMap.get(VALIDATOR_RESOURCES_KEY);
- if (validatorResources == null) {
- try {
- String pathnames =
external.getInitParameter(Globals.VALIDATOR_RULES);
- if (pathnames == null || pathnames.length() <= 0) {
- pathnames = Globals.DEFAULT_VALIDATOR_RULES;
- }
- StringTokenizer st = new StringTokenizer(pathnames, ",");
- List urlList = new ArrayList();
- while (st.hasMoreTokens()) {
- String validatorRules = st.nextToken().trim();
- log.info(messages.getMessage("commonsValidator.loadresource",
- new Object[] {validatorRules}));
- URL input = external.getResource(validatorRules);
- if (input == null) {
- input = CommonsValidator.class.getResource(validatorRules);
- }
- if (input != null) {
- urlList.add(input);
- } else {
- log.warn(messages.
- getMessage("commonsValidator.skipresource",
- new Object[] {validatorRules}));
- }
- }
- int urlSize = urlList.size();
- String[] urlArray = new String[urlSize];
- for (int urlIndex = 0; urlIndex < urlSize; urlIndex++) {
- URL url = (URL) urlList.get(urlIndex);
- urlArray[urlIndex] = url.toExternalForm();
- }
- validatorResources = new ValidatorResources(urlArray);
- applicationMap.put(VALIDATOR_RESOURCES_KEY, validatorResources);
- } catch (IOException ex) {
- log.error(messages.getMessage("commonsValidator.loaderror"), ex);
- return null;
- } catch (SAXException ex) {
- log.error(messages.getMessage("commonsValidator.loaderror"), ex);
- return null;
- }
- }
+ return (ValidatorResources)
+
context.getExternalContext().getApplicationMap().get(Globals.VALIDATOR_RESOURCES);
- return validatorResources;
}
Modified:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/Globals.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/Globals.java?view=diff&rev=478459&r1=478458&r2=478459
==============================================================================
---
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/Globals.java
(original)
+++
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/Globals.java
Wed Nov 22 20:23:00 2006
@@ -18,19 +18,12 @@
package org.apache.shale.validator;
/**
- * <p>Manifest constants that are global to the Validator Support
+ * <p>Manifest constants that are global to the Validator Integration
* implementation.</p>
*/
public class Globals {
- /**
- * <p>Context initialization parameter used to specify a comma delimited
- * list of context relative resource paths to resources containing our
- * validator configuration information.</p>
- */
- public static final String VALIDATOR_RULES =
- "org.apache.shale.validator.VALIDATOR_RULES";
/**
* <p>Location of the default Validator configuration file.
@@ -40,5 +33,23 @@
*/
public static final String DEFAULT_VALIDATOR_RULES =
"/org/apache/shale/validator/validator-rules.xml";
+
+
+ /**
+ * <p>Application scope attribute under which we store the Commons
+ * Validator resources that have been configured.</p>
+ */
+ public static final String VALIDATOR_RESOURCES =
+ "org.apache.shale.validator.RESOURCES";
+
+
+ /**
+ * <p>Context initialization parameter used to specify a comma delimited
+ * list of context relative resource paths to resources containing our
+ * validator configuration information.</p>
+ */
+ public static final String VALIDATOR_RULES =
+ "org.apache.shale.validator.VALIDATOR_RULES";
+
}
Added:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java?view=auto&rev=478459
==============================================================================
---
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java
(added)
+++
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java
Wed Nov 22 20:23:00 2006
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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 org.apache.shale.validator.faces;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import javax.faces.FacesException;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.validator.ValidatorResources;
+import org.apache.shale.validator.Globals;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>ServletContextListener that loads validator configuration resources
+ * at application startup, and cleans up the libraries we depend on at
+ * application shutdown.</p>
+ */
+public class ValidatorLifecycleListener implements ServletContextListener {
+
+
+ // -------------------------------------------------------- Static
Variables
+
+
+ // ------------------------------------------------------ Instance
Variables
+
+
+ /**
+ * <p>The <code>Log</code> instance we will use for this listener.</p>
+ */
+ private Log log = LogFactory.getLog(ValidatorLifecycleListener.class);
+
+
+ // ------------------------------------------ ServletContextListener
Methods
+
+
+ /**
+ * <p>Process an application shutdown event.</p>
+ *
+ * @param event Shutdown event to be processed
+ */
+ public void contextDestroyed(ServletContextEvent event) {
+
+ if (log.isInfoEnabled()) {
+ log.info("Finalizing Validator Integration");
+ }
+
+ // Clean up our cache of dialog configuration information
+ event.getServletContext().removeAttribute(Globals.VALIDATOR_RESOURCES);
+
+ // Clean up dependency libraries we have used
+ PropertyUtils.clearDescriptors(); // Used by Commons Validator via
Digester
+ LogFactory.release(Thread.currentThread().getContextClassLoader());
+ log = null;
+
+ }
+
+
+ /**
+ * <p>Process an application startup event.</p>
+ *
+ * @param event Startup event to be processed
+ */
+ public void contextInitialized(ServletContextEvent event) {
+
+ if (log.isInfoEnabled()) {
+ log.info("Initializing Validator Integration");
+ }
+
+ // Configure and cache the validator resources for this application
+ ServletContext context = event.getServletContext();
+ ValidatorResources resources = null;
+ try {
+ resources = validatorResources(context);
+ } catch (IllegalArgumentException e) {
+ throw e;
+ } catch (IOException e) {
+ throw new FacesException(e);
+ } catch (SAXException e) {
+ throw new FacesException(e);
+ }
+ context.setAttribute(Globals.VALIDATOR_RESOURCES, resources);
+
+ }
+
+
+ // --------------------------------------------------------- Private
Methods
+
+
+ /**
+ * <p>Configure the validator resources to be used by this application,
+ * by reading the list of resources configured on the context init
+ * parameter named by <code>Globals.VALIDATOR_RULES</code> (if any),
+ * followed by reading the default resource named by
+ * <code>Globals.DEFAULT_VALIDATOR_RULES</code> (if it has not already
+ * been processed).</p>
+ *
+ * @param context <code>ServletContext</code> for this application
+ *
+ * @exception IllegalArgumentException if a specified resource cannot
+ * be located, or if a malformed URL is constructed from the
+ * specified resource name
+ * @exception IOException if an input/output error occurs while
+ * processing the specified configuration resources
+ * @exception SAXException if an XML parsing error occurs while
+ * processing the specified configuration resources
+ */
+ private ValidatorResources validatorResources(ServletContext context)
+ throws IOException, SAXException {
+
+ // Process the explicitly configured resources (if any)
+ List urls = new ArrayList();
+ URL url = null;
+ boolean didDefault = false;
+ String pathnames = context.getInitParameter(Globals.VALIDATOR_RULES);
+ if (pathnames != null) {
+ pathnames = pathnames.trim();
+ while (pathnames.length() > 0) {
+
+ // Identify the next resource pathname to be processed
+ int comma = pathnames.indexOf(',');
+ String pathname = null;
+ if (comma >= 0) {
+ pathname = pathnames.substring(0, comma).trim();
+ pathnames = pathnames.substring(comma + 1);
+ } else {
+ pathname = pathnames.trim();
+ pathnames = "";
+ }
+ if (pathname.length() < 1) {
+ break;
+ }
+
+ // Add the corresponding URL to our list
+ try {
+ url = context.getResource(pathname);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(pathname, e);
+ }
+ if (url == null) {
+ url =
ValidatorLifecycleListener.class.getResource(pathname);
+ }
+ if (url == null) {
+ throw new IllegalArgumentException(pathname);
+ }
+ urls.add(url);
+ if (Globals.DEFAULT_VALIDATOR_RULES.equals(pathname)) {
+ didDefault = true;
+ }
+
+ }
+ }
+
+ // Process the default configuration resources (if not already loaded)
+ if (!didDefault) {
+ try {
+ url = context.getResource(Globals.DEFAULT_VALIDATOR_RULES);
+ } catch (MalformedURLException e) {
+ throw new
IllegalArgumentException(Globals.DEFAULT_VALIDATOR_RULES, e);
+ }
+ if (url == null) {
+ url =
ValidatorLifecycleListener.class.getResource(Globals.DEFAULT_VALIDATOR_RULES);
+ }
+ if (url == null) {
+ throw new
IllegalArgumentException(Globals.DEFAULT_VALIDATOR_RULES);
+ }
+ urls.add(url);
+ }
+
+ // Until <http://issues.apache.org/jira/browse/VALIDATOR-209>
+ // is addressed, we must convert the URLs we have gathered back into
+ // Strings and hope no information is lost in the process
+ String[] array = new String[urls.size()];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = ((URL) urls.get(i)).toExternalForm();
+ }
+
+ // Construct and return a new ValidatorResources instance
+ return new ValidatorResources(array);
+
+ }
+
+
+}
Propchange:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
shale/framework/trunk/shale-validator/src/main/java/org/apache/shale/validator/faces/ValidatorLifecycleListener.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Modified:
shale/framework/trunk/shale-validator/src/main/resources/META-INF/taglib.tld
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/main/resources/META-INF/taglib.tld?view=diff&rev=478459&r1=478458&r2=478459
==============================================================================
---
shale/framework/trunk/shale-validator/src/main/resources/META-INF/taglib.tld
(original)
+++
shale/framework/trunk/shale-validator/src/main/resources/META-INF/taglib.tld
Wed Nov 22 20:23:00 2006
@@ -35,6 +35,14 @@
</description>
+ <!-- ===================== Servlet Listeners =============================
-->
+
+
+ <listener>
+
<listener-class>org.apache.shale.validator.faces.ValidatorLifecycleListener</listener-class>
+ </listener>
+
+
<!-- ================= JSF Component Tags ================================
-->
Modified:
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/CommonsValidatorTestCase.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/CommonsValidatorTestCase.java?view=diff&rev=478459&r1=478458&r2=478459
==============================================================================
---
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/CommonsValidatorTestCase.java
(original)
+++
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/CommonsValidatorTestCase.java
Wed Nov 22 20:23:00 2006
@@ -30,12 +30,14 @@
import javax.faces.component.html.HtmlForm;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.ResponseWriter;
+import javax.servlet.ServletContextEvent;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.validator.ValidatorAction;
+import org.apache.shale.validator.faces.ValidatorLifecycleListener;
import org.apache.shale.validator.faces.ValidatorScript;
import org.apache.shale.test.base.AbstractJsfTestCase;
import org.apache.shale.util.Messages;
@@ -90,7 +92,6 @@
}
-
// ------------------------------------------------------------
Constructors
@@ -100,6 +101,13 @@
}
+ // ------------------------------------------------------ Instance
Variables
+
+
+ // ValidatorLifecycleListener used to load configuration resources
+ ValidatorLifecycleListener listener = null;
+
+
// ---------------------------------------------------- Overall Test
Methods
@@ -111,7 +119,8 @@
(Globals.VALIDATOR_RULES,
Globals.DEFAULT_VALIDATOR_RULES +
", /org/apache/shale/validator/custom-rules.xml");
-
+ listener = new ValidatorLifecycleListener();
+ listener.contextInitialized(new ServletContextEvent(servletContext));
loadComponents();
loadConverters();
@@ -131,6 +140,9 @@
// Tear down instance variables required by this test case.
protected void tearDown() throws Exception {
+
+ listener.contextDestroyed(new ServletContextEvent(servletContext));
+ listener = null;
super.tearDown();
Modified:
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/ValidatorDefaultTestCase.java
URL:
http://svn.apache.org/viewvc/shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/ValidatorDefaultTestCase.java?view=diff&rev=478459&r1=478458&r2=478459
==============================================================================
---
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/ValidatorDefaultTestCase.java
(original)
+++
shale/framework/trunk/shale-validator/src/test/java/org/apache/shale/validator/ValidatorDefaultTestCase.java
Wed Nov 22 20:23:00 2006
@@ -17,10 +17,12 @@
package org.apache.shale.validator;
+import javax.servlet.ServletContextEvent;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.validator.ValidatorAction;
import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.validator.faces.ValidatorLifecycleListener;
/**
* <p>Test case for <code>CommonsValidator</code>.</p>
@@ -45,6 +47,13 @@
super.setUp();
+ servletContext.addInitParameter
+ (Globals.VALIDATOR_RULES,
+ Globals.DEFAULT_VALIDATOR_RULES +
+ ", /org/apache/shale/validator/custom-rules.xml");
+ listener = new ValidatorLifecycleListener();
+ listener.contextInitialized(new ServletContextEvent(servletContext));
+
}
@@ -59,12 +68,19 @@
// Tear down instance variables required by this test case.
protected void tearDown() throws Exception {
+ listener.contextDestroyed(new ServletContextEvent(servletContext));
+ listener = null;
+
super.tearDown();
}
// ------------------------------------------------------ Instance
Variables
+
+
+ // ValidatorLifecycleListener used to load configuration resources
+ ValidatorLifecycleListener listener = null;
// ------------------------------------------------------------ Test
Methods