You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by eh...@apache.org on 2006/10/16 21:48:23 UTC

svn commit: r464642 - in /incubator/wicket/trunk/wicket/src/main/java/wicket: Application.java IDestroyer.java IInitializer.java Initializer.java jmx/Initializer.java protocol/http/WebApplication.java protocol/http/WicketFilter.java util/lang/Objects.java

Author: ehillenius
Date: Mon Oct 16 12:48:22 2006
New Revision: 464642

URL: http://svn.apache.org/viewvc?view=rev&rev=464642
Log:
Implemented optional interface for initializers: IDestroyer that may be implemented by initializers to clear up stuff when the application is shut down.
Implemented destroy for JMX so that it deregisters the registrations it is responsible for
Tweaked logging, and introduced logStarted that may be used to print a customized 'application started' message

Added:
    incubator/wicket/trunk/wicket/src/main/java/wicket/IDestroyer.java
Modified:
    incubator/wicket/trunk/wicket/src/main/java/wicket/Application.java
    incubator/wicket/trunk/wicket/src/main/java/wicket/IInitializer.java
    incubator/wicket/trunk/wicket/src/main/java/wicket/Initializer.java
    incubator/wicket/trunk/wicket/src/main/java/wicket/jmx/Initializer.java
    incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebApplication.java
    incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WicketFilter.java
    incubator/wicket/trunk/wicket/src/main/java/wicket/util/lang/Objects.java

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/Application.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/Application.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/Application.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/Application.java Mon Oct 16 12:48:22 2006
@@ -22,8 +22,10 @@
 import java.io.InputStream;
 import java.io.Serializable;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -56,7 +58,7 @@
 import wicket.settings.IApplicationSettings.UnexpectedExceptionDisplay;
 import wicket.util.file.IResourceFinder;
 import wicket.util.lang.Classes;
-import wicket.util.string.Strings;
+import wicket.util.lang.Objects;
 import wicket.util.time.Duration;
 
 /**
@@ -193,6 +195,9 @@
 	/** Record what the configuration is, so that we can query for it later. */
 	private String configurationType;
 
+	/** list of initializers. */
+	private List<IInitializer> initializers = new ArrayList<IInitializer>();
+
 	/** Markup cache for this application */
 	private final MarkupCache markupCache;
 
@@ -327,7 +332,6 @@
 		// should counter act each other for all properties.
 		if (DEVELOPMENT.equalsIgnoreCase(configurationType))
 		{
-			log.info("You are in DEVELOPMENT mode");
 			getResourceSettings().setResourcePollFrequency(Duration.ONE_SECOND);
 			getDebugSettings().setComponentUseCheck(true);
 			getDebugSettings().setSerializeSessionAttributes(true);
@@ -559,10 +563,10 @@
 	 */
 	public final void initializeComponents()
 	{
-		// Load any wicket components we can find
+		// Load any wicket properties files we can find
 		try
 		{
-			// Load components used by all applications
+			// Load properties files used by all libraries
 			final Enumeration resources = getClass().getClassLoader().getResources(
 					"wicket.properties");
 			while (resources.hasMoreElements())
@@ -574,7 +578,7 @@
 					final Properties properties = new Properties();
 					in = url.openStream();
 					properties.load(in);
-					initializeComponents(properties);
+					load(properties);
 				}
 				finally
 				{
@@ -589,6 +593,9 @@
 		{
 			throw new WicketRuntimeException("Unable to load initializers file", e);
 		}
+
+		// now call any initializers we read
+		callInitializers();
 	}
 
 	/**
@@ -675,7 +682,7 @@
 	 */
 	protected void destroy()
 	{
-
+		callDestroyers();
 	}
 
 	/**
@@ -702,7 +709,6 @@
 		applicationKeyToApplication.remove(getApplicationKey());
 	}
 
-
 	/**
 	 * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT OVERRIDE OR
 	 * CALL.
@@ -736,6 +742,23 @@
 		}
 	}
 
+
+	/**
+	 * Log that this application is started.
+	 */
+	protected void logStarted()
+	{
+		String version = getFrameworkSettings().getVersion();
+		StringBuffer b = new StringBuffer();
+		b.append("[").append(getName()).append("] Started Wicket ");
+		if (!"n/a".equals(version))
+		{
+			b.append("version ").append(version).append(" ");
+		}
+		b.append("in ").append(getConfigurationType()).append(" mode");
+		log.info(b.toString());
+	}
+
 	/**
 	 * Creates a new session facade. Is called once per application, and is
 	 * typically not something clients reimplement.
@@ -761,6 +784,49 @@
 	}
 
 	/**
+	 * Construct and add initializer from the provided class name.
+	 * 
+	 * @param className
+	 */
+	private final void addInitializer(String className)
+	{
+		IInitializer initializer = (IInitializer)Objects.newInstance(className);
+		if (initializer != null)
+		{
+			initializers.add(initializer);
+		}
+	}
+
+	/**
+	 * @param properties
+	 *            Properties map with names of any library destroyers in it
+	 */
+	private final void callDestroyers()
+	{
+		for (IInitializer initializer : initializers)
+		{
+			if (initializer instanceof IDestroyer)
+			{
+				log.info("[" + getName() + "] destroy: " + initializer);
+				((IDestroyer)initializer).destroy(this);
+			}
+		}
+	}
+
+	/**
+	 * @param properties
+	 *            Properties map with names of any library destroyers in it
+	 */
+	private final void callInitializers()
+	{
+		for (IInitializer initializer : initializers)
+		{
+			log.info("[" + getName() + "] init: " + initializer);
+			initializer.init(this);
+		}
+	}
+
+	/**
 	 * This method is still here for backwards compatibility with 1.1 source
 	 * code. The getXXXSettings() methods are now preferred. This method will be
 	 * removed post 1.2 version.
@@ -793,42 +859,12 @@
 	}
 
 	/**
-	 * Instantiate initializer with the given class name.
-	 * 
-	 * @param className
-	 *            The name of the initializer class
-	 */
-	private final void initialize(final String className)
-	{
-		if (!Strings.isEmpty(className))
-		{
-			try
-			{
-				Class c = getApplicationSettings().getClassResolver().resolveClass(className);
-				((IInitializer)c.newInstance()).init(this);
-			}
-			catch (ClassCastException e)
-			{
-				throw new WicketRuntimeException("Unable to initialize " + className, e);
-			}
-			catch (InstantiationException e)
-			{
-				throw new WicketRuntimeException("Unable to initialize " + className, e);
-			}
-			catch (IllegalAccessException e)
-			{
-				throw new WicketRuntimeException("Unable to initialize " + className, e);
-			}
-		}
-	}
-
-	/**
 	 * @param properties
 	 *            Properties map with names of any library initializers in it
 	 */
-	private final void initializeComponents(final Properties properties)
+	private final void load(final Properties properties)
 	{
-		initialize(properties.getProperty("initializer"));
-		initialize(properties.getProperty(getName() + "-initializer"));
+		addInitializer(properties.getProperty("initializer"));
+		addInitializer(properties.getProperty(getName() + "-initializer"));
 	}
 }

Added: incubator/wicket/trunk/wicket/src/main/java/wicket/IDestroyer.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/IDestroyer.java?view=auto&rev=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/IDestroyer.java (added)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/IDestroyer.java Mon Oct 16 12:48:22 2006
@@ -0,0 +1,42 @@
+/*
+ * $Id: IInitializer.java 4597 2006-02-21 22:08:11 +0000 (Tue, 21 Feb 2006)
+ * jdonnerstag $ $Revision: 460927 $ $Date: 2006-02-21 22:08:11 +0000 (Tue, 21 Feb
+ * 2006) $
+ * 
+ * ==============================================================================
+ * Licensed 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 wicket;
+
+/**
+ * Optional interface for {@link IInitializer initializers} that can clean up
+ * stuff initializers created. Initializers simple have to implement this
+ * interface and do their thing in {@link #destroy(Application)}.
+ * <p>
+ * Destroyers can be used to cleanup code when the application unloads. It only
+ * guarantees a best effort of cleaning up. Typically, for web applications,
+ * this is called when the Wicket servlet/ filter is unloaded by the container,
+ * which may depend on the container's implementation and things like the time
+ * out period it uses and whether all threads of the web app were cleared.
+ * </p>
+ * 
+ * @author Eelco Hillenius
+ */
+public interface IDestroyer
+{
+	/**
+	 * @param application
+	 *            The application loading the component
+	 */
+	void destroy(Application application);
+}

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/IInitializer.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/IInitializer.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/IInitializer.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/IInitializer.java Mon Oct 16 12:48:22 2006
@@ -33,6 +33,17 @@
  * You don't have to pre-register {@link PackageResource package resources}, as
  * they can be initialized lazily.
  * </p>
+ * <p>
+ * Initializers can be configured by having a wicket.properties file in the
+ * class path root, with property 'initializer=${initializer class name}'. You
+ * can have one such properties per jar file, but the initializer that property
+ * denotes can delegate to other initializers of that library.
+ * </p>
+ * <p>
+ * If an initializer also implement {@link IDestroyer}, the instance will be
+ * kept for destroying, so that it may clean up whatever it did when
+ * initializing.
+ * </p>
  * 
  * @author Jonathan Locke
  */

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/Initializer.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/Initializer.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/Initializer.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/Initializer.java Mon Oct 16 12:48:22 2006
@@ -29,8 +29,18 @@
  * 
  * @author Jonathan Locke
  */
-public class Initializer implements IInitializer
+public class Initializer implements IInitializer, IDestroyer
 {
+	wicket.jmx.Initializer jmxInitializer = new wicket.jmx.Initializer();
+
+	/**
+	 * @see wicket.IDestroyer#destroy(wicket.Application)
+	 */
+	public void destroy(Application application)
+	{
+		jmxInitializer.destroy(application);
+	}
+
 	/**
 	 * @see wicket.IInitializer#init(wicket.Application)
 	 */
@@ -48,6 +58,14 @@
 		IResourceListener.INTERFACE.register();
 
 		// register JMX beans
-		new wicket.jmx.Initializer().init(application);
+		jmxInitializer.init(application);
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString()
+	{
+		return "Wicket core library initializer";
 	}
 }

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/jmx/Initializer.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/jmx/Initializer.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/jmx/Initializer.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/jmx/Initializer.java Mon Oct 16 12:48:22 2006
@@ -15,8 +15,11 @@
 package wicket.jmx;
 
 import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
@@ -26,6 +29,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import wicket.IDestroyer;
 import wicket.IInitializer;
 import wicket.WicketRuntimeException;
 
@@ -34,11 +38,39 @@
  * 
  * @author eelcohillenius
  */
-public class Initializer implements IInitializer
+public class Initializer implements IInitializer, IDestroyer
 {
 	private static Log log = LogFactory.getLog(Initializer.class);
 
 	/**
+	 * List of registered names
+	 */
+	private List<ObjectName> registered = new ArrayList<ObjectName>();
+
+	/**
+	 * @see wicket.IDestroyer#destroy(wicket.Application)
+	 */
+	public void destroy(wicket.Application application)
+	{
+		MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+		for (ObjectName objectName : registered)
+		{
+			try
+			{
+				mbs.unregisterMBean(objectName);
+			}
+			catch (InstanceNotFoundException e)
+			{
+				log.error(e.getMessage(), e);
+			}
+			catch (MBeanRegistrationException e)
+			{
+				log.error(e.getMessage(), e);
+			}
+		}
+	}
+
+	/**
 	 * @see wicket.IInitializer#init(wicket.Application)
 	 */
 	public void init(wicket.Application application)
@@ -63,30 +95,30 @@
 			domain = tempDomain;
 
 			Application appBean = new Application(application);
-			mbs.registerMBean(appBean, appBeanName);
+			register(mbs, appBean, appBeanName);
 
-			mbs.registerMBean(new ApplicationSettings(application), new ObjectName(domain
+			register(mbs, new ApplicationSettings(application), new ObjectName(domain
 					+ ":type=Application,name=ApplicationSettings"));
-			mbs.registerMBean(new DebugSettings(application), new ObjectName(domain
+			register(mbs, new DebugSettings(application), new ObjectName(domain
 					+ ":type=Application,name=DebugSettings"));
-			mbs.registerMBean(new MarkupSettings(application), new ObjectName(domain
+			register(mbs, new MarkupSettings(application), new ObjectName(domain
 					+ ":type=Application,name=MarkupSettings"));
-			mbs.registerMBean(new ResourceSettings(application), new ObjectName(domain
+			register(mbs, new ResourceSettings(application), new ObjectName(domain
 					+ ":type=Application,name=ResourceSettings"));
-			mbs.registerMBean(new PageSettings(application), new ObjectName(domain
+			register(mbs, new PageSettings(application), new ObjectName(domain
 					+ ":type=Application,name=PageSettings"));
-			mbs.registerMBean(new RequestCycleSettings(application), new ObjectName(domain
+			register(mbs, new RequestCycleSettings(application), new ObjectName(domain
 					+ ":type=Application,name=RequestCycleSettings"));
-			mbs.registerMBean(new SecuritySettings(application), new ObjectName(domain
+			register(mbs, new SecuritySettings(application), new ObjectName(domain
 					+ ":type=Application,name=SecuritySettings"));
-			mbs.registerMBean(new SessionSettings(application), new ObjectName(domain
+			register(mbs, new SessionSettings(application), new ObjectName(domain
 					+ ":type=Application,name=SessionSettings"));
-			mbs.registerMBean(new CookieValuePersisterSettings(application), new ObjectName(domain
+			register(mbs, new CookieValuePersisterSettings(application), new ObjectName(domain
 					+ ":type=Application,name=CookieValuePersisterSettings"));
 
 			RequestLogger sessionsBean = new RequestLogger(application);
 			ObjectName sessionsBeanName = new ObjectName(domain + ":type=RequestLogger");
-			mbs.registerMBean(sessionsBean, sessionsBeanName);
+			register(mbs, sessionsBean, sessionsBeanName);
 		}
 		catch (MalformedObjectNameException e)
 		{
@@ -104,5 +136,34 @@
 		{
 			throw new WicketRuntimeException(e);
 		}
+	}
+
+	/**
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString()
+	{
+		return "Wicket JMX initializer";
+	}
+
+	/**
+	 * Register MBean.
+	 * 
+	 * @param mbs
+	 *            server
+	 * @param o
+	 *            MBean
+	 * @param objectName
+	 *            Object name
+	 * @throws NotCompliantMBeanException
+	 * @throws MBeanRegistrationException
+	 * @throws InstanceAlreadyExistsException
+	 */
+	private void register(MBeanServer mbs, Object o, ObjectName objectName)
+			throws InstanceAlreadyExistsException, MBeanRegistrationException,
+			NotCompliantMBeanException
+	{
+		mbs.registerMBean(o, objectName);
+		registered.add(objectName);
 	}
 }

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebApplication.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebApplication.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebApplication.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WebApplication.java Mon Oct 16 12:48:22 2006
@@ -72,11 +72,11 @@
  * init() method. For example:
  * 
  * <pre>
- *              public void init()
- *              {
- *                  String webXMLParameter = getWicketServlet().getInitParameter(&quot;myWebXMLParameter&quot;);
- *                  URL schedulersConfig = getWicketServlet().getServletContext().getResource(&quot;/WEB-INF/schedulers.xml&quot;);
- *                  ...
+ *               public void init()
+ *               {
+ *                   String webXMLParameter = getWicketServlet().getInitParameter(&quot;myWebXMLParameter&quot;);
+ *                   URL schedulersConfig = getWicketServlet().getServletContext().getResource(&quot;/WEB-INF/schedulers.xml&quot;);
+ *                   ...
  * </pre>
  * 
  * @see WicketServlet
@@ -535,6 +535,15 @@
 			configure(Application.DEVELOPMENT, wicketFilter.getFilterConfig().getInitParameter(
 					"sourceFolder"));
 		}
+	}
+
+	/**
+	 * @see wicket.Application#logStarted()
+	 */
+	@Override
+	protected void logStarted()
+	{
+		super.logStarted();
 	}
 
 	/**

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WicketFilter.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WicketFilter.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WicketFilter.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/protocol/http/WicketFilter.java Mon Oct 16 12:48:22 2006
@@ -52,9 +52,6 @@
  */
 public class WicketFilter implements Filter
 {
-	/** Log. */
-	private static final Log log = LogFactory.getLog(WicketFilter.class);
-
 	/**
 	 * The name of the context parameter that specifies application factory
 	 * class
@@ -67,9 +64,6 @@
 	 */
 	public static final String FILTER_PATH_PARAM = "filterPath";
 
-	/** The URL path prefix expected for (so called) resources (not html pages). */
-	private static final String RESOURCES_PATH_PREFIX = "/resources/";
-
 	/**
 	 * The servlet path holder when the WicketSerlvet is used. So that the
 	 * filter path will be computed with the first request. Note: This variable
@@ -77,6 +71,12 @@
 	 */
 	static final String SERVLET_PATH_HOLDER = "<servlet>";
 
+	/** Log. */
+	private static final Log log = LogFactory.getLog(WicketFilter.class);
+
+	/** The URL path prefix expected for (so called) resources (not html pages). */
+	private static final String RESOURCES_PATH_PREFIX = "/resources/";
+
 	/** See javax.servlet.FilterConfig */
 	private FilterConfig filterConfig;
 
@@ -343,9 +343,8 @@
 			// component.
 			this.webApplication.initializeComponents();
 
-			// Finished
-			log.info("Wicket application " + this.webApplication.getName() + " started [factory="
-					+ factory.getClass().getName() + "]");
+			// Give the application the option to log that it is started
+			this.webApplication.logStarted();
 		}
 		finally
 		{

Modified: incubator/wicket/trunk/wicket/src/main/java/wicket/util/lang/Objects.java
URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/wicket/src/main/java/wicket/util/lang/Objects.java?view=diff&rev=464642&r1=464641&r2=464642
==============================================================================
--- incubator/wicket/trunk/wicket/src/main/java/wicket/util/lang/Objects.java (original)
+++ incubator/wicket/trunk/wicket/src/main/java/wicket/util/lang/Objects.java Mon Oct 16 12:48:22 2006
@@ -46,6 +46,7 @@
 import wicket.settings.IApplicationSettings;
 import wicket.util.collections.MiniMap;
 import wicket.util.io.ByteCountingOutputStream;
+import wicket.util.string.Strings;
 
 /**
  * Object utilities.
@@ -741,7 +742,6 @@
 		return false;
 	}
 
-
 	/**
 	 * Returns the constant from the NumericTypes interface that best expresses
 	 * the type of an operation, which can be either numeric or not, on the two
@@ -810,6 +810,7 @@
 		}
 	}
 
+
 	/**
 	 * Returns a constant from the NumericTypes interface that represents the
 	 * numeric type of the given object.
@@ -1005,6 +1006,40 @@
 	public static MiniMap<Field, Object> mapObject(final Object object)
 	{
 		return mapObject(object, new ArrayList<Object>());
+	}
+
+	/**
+	 * Creates a new instance using the current application's class resolver.
+	 * Returns null if className is null.
+	 * 
+	 * @param className
+	 *            The full class name
+	 * @return The new object instance
+	 */
+	public static Object newInstance(final String className)
+	{
+		if (!Strings.isEmpty(className))
+		{
+			try
+			{
+				Class c = Application.get().getApplicationSettings().getClassResolver()
+						.resolveClass(className);
+				return c.newInstance();
+			}
+			catch (ClassCastException e)
+			{
+				throw new WicketRuntimeException("Unable to create " + className, e);
+			}
+			catch (InstantiationException e)
+			{
+				throw new WicketRuntimeException("Unable to create " + className, e);
+			}
+			catch (IllegalAccessException e)
+			{
+				throw new WicketRuntimeException("Unable to create " + className, e);
+			}
+		}
+		return null;
 	}
 
 	/**