Return-Path: Delivered-To: apmail-shale-commits-archive@locus.apache.org Received: (qmail 55010 invoked from network); 11 Nov 2006 04:16:50 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 11 Nov 2006 04:16:50 -0000 Received: (qmail 4169 invoked by uid 500); 11 Nov 2006 04:17:00 -0000 Delivered-To: apmail-shale-commits-archive@shale.apache.org Received: (qmail 4147 invoked by uid 500); 11 Nov 2006 04:17:00 -0000 Mailing-List: contact commits-help@shale.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@shale.apache.org Delivered-To: mailing list commits@shale.apache.org Received: (qmail 4135 invoked by uid 99); 11 Nov 2006 04:17:00 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Nov 2006 20:17:00 -0800 X-ASF-Spam-Status: No, hits=-8.6 required=10.0 tests=ALL_TRUSTED,INFO_TLD,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Nov 2006 20:16:48 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 3C59C1A9846; Fri, 10 Nov 2006 20:16:20 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r473638 - in /shale/framework/trunk/shale-dialog-basic: ./ src/main/java/org/apache/shale/dialog/basic/ src/main/resources/META-INF/ Date: Sat, 11 Nov 2006 04:16:19 -0000 To: commits@shale.apache.org From: craigmcc@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061111041620.3C59C1A9846@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: craigmcc Date: Fri Nov 10 20:16:19 2006 New Revision: 473638 URL: http://svn.apache.org/viewvc?view=rev&rev=473638 Log: Partial fix for cleaning up static resources at application shutdown (SHALE-274) for the basic implementation. This took several changes: * We needed a servlet context listener that can call PropertyUtils.clearDescriptors() and LogFactory.release(). * In order to get this without requiring the user to configure a listener manually in web.xml, create a dummy "tag library" inside the JAR (META-INF/taglib.tld) that serves to declare the listener. * Since we now have an application startup/shutdown instance, migrate the dialog configuration parsing from "first use" in BasicDialogManager to "application startup time" as well. With these changes, we have successfully cleaned up issues that caused the Commons BeanUtils and Commons Logging jars to remain locked after undeployment on a Windows platform. However, there is still something that prevents shale-dialog-basic-xxx.jar itself from being deleted -- and this means there will be a memory leak over multiple application deploys and undeploys. This needs to be investigated and fixed before this issue can be considered as "dealt with" for the basic implementation. The Commons SCXML implementation is going to need the same sort of changes (can be tagged against SHALE-274 as well), but it's likely to have its own set of different issues about leaving the shale-dialog-scxml-xxx.jar file locked. Added: shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java (with props) shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld (with props) Modified: shale/framework/trunk/shale-dialog-basic/ (props changed) shale/framework/trunk/shale-dialog-basic/pom.xml shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogManager.java Propchange: shale/framework/trunk/shale-dialog-basic/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Fri Nov 10 20:16:19 2006 @@ -0,0 +1 @@ +target Modified: shale/framework/trunk/shale-dialog-basic/pom.xml URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/pom.xml?view=diff&rev=473638&r1=473637&r2=473638 ============================================================================== --- shale/framework/trunk/shale-dialog-basic/pom.xml (original) +++ shale/framework/trunk/shale-dialog-basic/pom.xml Fri Nov 10 20:16:19 2006 @@ -40,6 +40,23 @@ + commons-logging + commons-logging + + + + javax.servlet + jsp-api + provided + + + + javax.servlet + servlet-api + provided + + + junit junit test Modified: shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogManager.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogManager.java?view=diff&rev=473638&r1=473637&r2=473638 ============================================================================== --- shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogManager.java (original) +++ shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicDialogManager.java Fri Nov 10 20:16:19 2006 @@ -19,7 +19,6 @@ import java.io.Serializable; import java.net.URL; -import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -31,7 +30,6 @@ import org.apache.shale.dialog.Constants; import org.apache.shale.dialog.DialogContext; import org.apache.shale.dialog.DialogContextManager; -import org.apache.shale.dialog.basic.config.ConfigurationParser; import org.apache.shale.dialog.basic.model.Dialog; /** @@ -54,22 +52,6 @@ /** - *

The default configuration resource we will process (if present), - * even if it is not explicitly configured.

- */ - private static final String DEFAULT_CONFIGURATION_RESOURCE = - "/WEB-INF/dialog-config.xml"; - - - /** - *

Resource name for dialog configuration resource(s) embedded in - * JAR files inside the application.

- */ - private static final String EMBEDDED_CONFIGURATION_RESOURCE = - "META-INF/dialog-config.xml"; - - - /** *

Map of {@link Dialog} configurations, keyed * by dialog name. This value is lazily instantiated, and is also * transient and may need to be regenerated.

@@ -88,7 +70,7 @@ *

Map containing all currently active {@link DialogContext} instances for * the current user.

*/ - private final HashMap map = new HashMap(); + private final Map map = new HashMap(); /** @@ -158,8 +140,7 @@ /** *

Return a Map of the configured {@link Dialog}s, keyed - * by logical dialog name. Upon the first request, the configuration - * resources will be processed.

+ * by logical dialog name.

* * @param context FacesContext for the current request * @return The map of available dialogs, keyed by dialog logical name @@ -174,110 +155,6 @@ // Return the previously configured application scope instance (if any) this.dialogs = (Map) context.getExternalContext().getApplicationMap().get(Globals.DIALOGS); - if (this.dialogs != null) { - return this.dialogs; - } - - // Set up to parse our specified configuration resources and cache the results - boolean didDefault = false; - ConfigurationParser parser = new ConfigurationParser(); - parser.setDialogs(new HashMap()); - - // Parse implicitly specified resources embedded in JAR files - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - if (loader == null) { - loader = this.getClass().getClassLoader(); - } - try { - Enumeration resources = loader.getResources(EMBEDDED_CONFIGURATION_RESOURCE); - while (resources.hasMoreElements()) { - URL resource = (URL) resources.nextElement(); - if (log().isDebugEnabled()) { - log().debug("Parsing configuration resource '" - + resource + "'"); - } - parser.setResource(resource); - parser.parse(); - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new FacesException(e); - } - - // Parse explicitly specified resources - String resources = - context.getExternalContext().getInitParameter(Globals.CONFIGURATION); - if (resources == null) { - resources = ""; - // Because we process the default resource even if it is not - // explicitly listed, we don't want to warn here - } - int comma = 0; - String path = null; - try { - while (true) { - comma = resources.indexOf(","); - if (comma < 0) { - path = resources.trim(); - resources = ""; - } else { - path = resources.substring(0, comma).trim(); - resources = resources.substring(comma + 1); - } - if (path.length() < 1) { - break; - } - URL resource = context.getExternalContext().getResource(path); - if (log().isDebugEnabled()) { - log().debug("Parsing configuration resource '" - + resource + "'"); - } - parser.setResource(resource); - parser.parse(); - if (DEFAULT_CONFIGURATION_RESOURCE.equals(path)) { - didDefault = true; - } - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new FacesException(e); - } - - // Parse the default configuration resource if it exists and has not - // already been parsed - if (!didDefault) { - try { - URL resource = - context.getExternalContext().getResource(DEFAULT_CONFIGURATION_RESOURCE); - if (resource != null) { - if (log().isDebugEnabled()) { - log().debug("Parsing configuration resource '" - + resource + "'"); - } - parser.setResource(resource); - parser.parse(); - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new FacesException(e); - } - } - - // Cache the results both locally and in application scope - this.dialogs = parser.getDialogs(); - - if (this.dialogs.size() == 0) { - if (log().isWarnEnabled()) { - log.warn("No dialog configuration information present. No default configuration found at: " + - DEFAULT_CONFIGURATION_RESOURCE + ". No embedded configuration found at: " + - EMBEDDED_CONFIGURATION_RESOURCE); - } - } - - context.getExternalContext().getApplicationMap().put(Globals.DIALOGS, this.dialogs); return this.dialogs; } Added: shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java?view=auto&rev=473638 ============================================================================== --- shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java (added) +++ shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java Fri Nov 10 20:16:19 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.dialog.basic; + +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import javax.faces.FacesException; +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.shale.dialog.basic.config.ConfigurationParser; + +/** + *

ServletContextListener that loads dialog configuration resources + * at application startup, and cleans up the libraries we depend on at + * application shutdown.

+ */ +public class BasicLifecycleListener implements ServletContextListener { + + + // -------------------------------------------------------- Static Variables + + + /** + *

The default configuration resource we will process (if present), + * even if it is not explicitly configured.

+ */ + private static final String DEFAULT_CONFIGURATION_RESOURCE = + "/WEB-INF/dialog-config.xml"; + + + /** + *

Resource name for dialog configuration resource(s) embedded in + * JAR files inside the application.

+ */ + private static final String EMBEDDED_CONFIGURATION_RESOURCE = + "META-INF/dialog-config.xml"; + + + // ------------------------------------------------------ Instance Variables + + + /** + *

The Log instance we will use for this listener.

+ */ + private Log log = LogFactory.getLog(BasicLifecycleListener.class); + + + // ------------------------------------------ ServletContextListener Methods + + + /** + *

Process an application shutdown event.

+ * + * @param event Shutdown event to be processed + */ + public void contextDestroyed(ServletContextEvent event) { + + if (log.isInfoEnabled()) { + log.info("Finalizing Dialog Basic Implementation"); + } + + // Clean up our cache of dialog configuration information + event.getServletContext().removeAttribute(Globals.DIALOGS); + + // Clean up dependency libraries we have used + PropertyUtils.clearDescriptors(); + LogFactory.release(Thread.currentThread().getContextClassLoader()); + log = null; + + } + + + /** + *

Process an application startup event.

+ * + * @param event Startup event to be processed + */ + public void contextInitialized(ServletContextEvent event) { + + if (log.isInfoEnabled()) { + log.info("Initializing Dialog Basic Implementation"); + } + + // Set up to parse our specified configuration resources and cache the results + boolean didDefault = false; + ConfigurationParser parser = new ConfigurationParser(); + parser.setDialogs(new HashMap()); + + // Parse implicitly specified resources embedded in JAR files + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + if (loader == null) { + loader = this.getClass().getClassLoader(); + } + try { + Enumeration resources = loader.getResources(EMBEDDED_CONFIGURATION_RESOURCE); + while (resources.hasMoreElements()) { + URL resource = (URL) resources.nextElement(); + if (log.isDebugEnabled()) { + log.debug("Parsing configuration resource '" + + resource + "'"); + } + parser.setResource(resource); + parser.parse(); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new FacesException(e); + } + + // Parse explicitly specified resources + String resources = + event.getServletContext().getInitParameter(Globals.CONFIGURATION); + if (resources == null) { + resources = ""; + // Because we process the default resource even if it is not + // explicitly listed, we don't want to warn here + } + int comma = 0; + String path = null; + try { + while (true) { + comma = resources.indexOf(","); + if (comma < 0) { + path = resources.trim(); + resources = ""; + } else { + path = resources.substring(0, comma).trim(); + resources = resources.substring(comma + 1); + } + if (path.length() < 1) { + break; + } + URL resource = event.getServletContext().getResource(path); + if (log.isDebugEnabled()) { + log.debug("Parsing configuration resource '" + + resource + "'"); + } + parser.setResource(resource); + parser.parse(); + if (DEFAULT_CONFIGURATION_RESOURCE.equals(path)) { + didDefault = true; + } + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new FacesException(e); + } + + // Parse the default configuration resource if it exists and has not + // already been parsed + if (!didDefault) { + try { + URL resource = + event.getServletContext().getResource(DEFAULT_CONFIGURATION_RESOURCE); + if (resource != null) { + if (log.isDebugEnabled()) { + log.debug("Parsing configuration resource '" + + resource + "'"); + } + parser.setResource(resource); + parser.parse(); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new FacesException(e); + } + } + + // Cache the results in application scope + Map dialogs = parser.getDialogs(); + if (dialogs.size() == 0) { + if (log.isWarnEnabled()) { + log.warn("No dialog configuration information present. No default configuration found at: " + + DEFAULT_CONFIGURATION_RESOURCE + ". No embedded configuration found at: " + + EMBEDDED_CONFIGURATION_RESOURCE); + } + } + event.getServletContext().setAttribute(Globals.DIALOGS, dialogs); + + } + + +} Propchange: shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: shale/framework/trunk/shale-dialog-basic/src/main/java/org/apache/shale/dialog/basic/BasicLifecycleListener.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Added: shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld URL: http://svn.apache.org/viewvc/shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld?view=auto&rev=473638 ============================================================================== --- shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld (added) +++ shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld Fri Nov 10 20:16:19 2006 @@ -0,0 +1,50 @@ + + + + + + + + + + 1.0 + 1.2 + s + http://shale.apache.org/dialog-basic + Shale Framework Basic Dialog Tag Library + + This tag library contains no live custom tag handlers. It exists + solely to declare the lifecycle context listener without requiring + any entries in the application's WEB-INF/web.xml resource + + + + + + + + org.apache.shale.dialog.basic.BasicLifecycleListener + + + + + + + Propchange: shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld ------------------------------------------------------------------------------ svn:eol-style = native Propchange: shale/framework/trunk/shale-dialog-basic/src/main/resources/META-INF/taglib.tld ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL