Author: cziegeler Date: Thu Nov 4 02:24:21 2004 New Revision: 56583 Added: cocoon/trunk/src/core/java/org/apache/cocoon/components/ServiceInfo.java Modified: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java cocoon/trunk/src/samples/org/apache/cocoon/samples/parentcm/Configurator.java Log: Add class for meta information and move all avalon stuff into component factory
Added: cocoon/trunk/src/core/java/org/apache/cocoon/components/ServiceInfo.java ============================================================================== --- (empty file) +++ cocoon/trunk/src/core/java/org/apache/cocoon/components/ServiceInfo.java Thu Nov 4 02:24:21 2004 @@ -0,0 +1,185 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * 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 org.apache.cocoon.components; + +import java.lang.reflect.Method; + +import org.apache.avalon.framework.configuration.Configuration; + +/** + * Meta-information about a service + * + * @version CVS $Id: LifecycleHelper.java 55255 2004-10-21 19:41:15Z cziegeler $ + */ +public class ServiceInfo { + + public static final int MODEL_PRIMITIVE = 0; + public static final int MODEL_SINGLETON = 1; + public static final int MODEL_POOLED = 2; + + private int model; + private String initMethodName; + private String destroyMethodName; + private String poolInMethodName; + private String poolOutMethodName; + private Class serviceClass; + private Method initMethod; + private Method destroyMethod; + private Method poolInMethod; + private Method poolOutMethod; + private Configuration configuration; + + public ServiceInfo() { + this.model = MODEL_PRIMITIVE; + } + + /** + * @return Returns the model. + */ + public int getModel() { + return model; + } + + /** + * @param model The model to set. + */ + public void setModel(int model) { + this.model = model; + } + + /** + * @return Returns the destroyMethod. + */ + public String getDestroyMethodName() { + return destroyMethodName; + } + + /** + * @param destroyMethod The destroyMethod to set. + */ + public void setDestroyMethodName(String destroyMethod) { + this.destroyMethodName = destroyMethod; + } + + /** + * @return Returns the initMethod. + */ + public String getInitMethodName() { + return initMethodName; + } + + /** + * @param initMethod The initMethod to set. + */ + public void setInitMethodName(String initMethod) { + this.initMethodName = initMethod; + } + + /** + * @return Returns the poolInMethodName + */ + public String getPoolInMethodName() { + return this.poolInMethodName; + } + + /** + * @param poolMethod The poolInMethod name to set. + */ + public void setPoolInMethodName(String poolMethod) { + this.poolInMethodName = poolMethod; + } + + /** + * @return Returns the poolOutMethodName + */ + public String getPoolOutMethodName() { + return this.poolOutMethodName; + } + + /** + * @param poolMethod The poolOutMethod name to set. + */ + public void setPoolOutMethodName(String poolMethod) { + this.poolOutMethodName = poolMethod; + } + + /** + * @return Returns the destroyMethod. + */ + public Method getDestroyMethod() throws Exception { + if ( this.destroyMethod == null && this.destroyMethodName != null ) { + this.destroyMethod = this.serviceClass.getMethod(this.destroyMethodName, null); + } + return destroyMethod; + } + + /** + * @return Returns the initMethod. + */ + public Method getInitMethod() throws Exception { + if ( this.initMethod == null && this.initMethodName != null ) { + this.initMethod = this.serviceClass.getMethod(this.initMethodName, null); + } + return initMethod; + } + + /** + * @return Returns the poolInMethod. + */ + public Method getPoolInMethod() throws Exception { + if ( this.poolInMethod == null && this.poolInMethodName != null ) { + this.poolInMethod = this.serviceClass.getMethod(this.poolInMethodName, null); + } + return poolInMethod; + } + + /** + * @return Returns the poolInMethod. + */ + public Method getPoolOutMethod() throws Exception { + if ( this.poolOutMethod == null && this.poolOutMethodName != null ) { + this.poolOutMethod = this.serviceClass.getMethod(this.poolOutMethodName, null); + } + return poolOutMethod; + } + + /** + * @return Returns the serviceClass. + */ + public Class getServiceClass() { + return serviceClass; + } + + /** + * @param serviceClass The serviceClass to set. + */ + public void setServiceClass(Class serviceClass) { + this.serviceClass = serviceClass; + } + + /** + * @return Returns the configuration. + */ + public Configuration getConfiguration() { + return configuration; + } + /** + * @param configuration The configuration to set. + */ + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } +} Modified: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java ============================================================================== --- cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java (original) +++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/AbstractComponentHandler.java Thu Nov 4 02:24:21 2004 @@ -25,6 +25,7 @@ import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.thread.SingleThreaded; import org.apache.avalon.framework.thread.ThreadSafe; +import org.apache.cocoon.components.ServiceInfo; /** * This class acts like a Factory to instantiate the correct version @@ -72,16 +73,29 @@ throws Exception { int numInterfaces = 0; + final ServiceInfo info = new ServiceInfo(); + info.setServiceClass(componentClass); + info.setConfiguration(configuration); + + // Early check for Composable + if ( Composable.class.isAssignableFrom( componentClass ) ) { + throw new Exception("Interface Composable is not supported anymore. Please change class " + + componentClass.getName() + " to use Serviceable instead."); + } + if( SingleThreaded.class.isAssignableFrom( componentClass ) ) { numInterfaces++; + info.setModel(ServiceInfo.MODEL_PRIMITIVE); } if( ThreadSafe.class.isAssignableFrom( componentClass ) ) { numInterfaces++; + info.setModel(ServiceInfo.MODEL_SINGLETON); } if( Poolable.class.isAssignableFrom( componentClass ) ) { numInterfaces++; + info.setModel(ServiceInfo.MODEL_POOLED); } if( numInterfaces > 1 ) { @@ -90,27 +104,30 @@ + "SingleThreaded, ThreadSafe, or Poolable" ); } - // Early check for Composable - if ( Composable.class.isAssignableFrom( componentClass ) ) { - throw new Exception("Interface Composable is not supported anymore. Please change class " - + componentClass.getName() + " to use Serviceable instead."); + if ( numInterfaces == 0 ) { + // test configuration + final String model = configuration.getAttribute("model", null); + if ( "pooled".equals(model) ) { + info.setModel(ServiceInfo.MODEL_POOLED); + } else if ( "singleton".equals(model) ) { + info.setModel(ServiceInfo.MODEL_SINGLETON); + } } // Create the factory to use to create the instances of the Component. ComponentFactory factory = new ComponentFactory( - componentClass, - configuration, serviceManager, context, logger, loggerManager, - roleManager); + roleManager, + info); AbstractComponentHandler handler; - if( Poolable.class.isAssignableFrom( componentClass ) ) { + if( info.getModel() == ServiceInfo.MODEL_POOLED ) { handler = new PoolableComponentHandler( logger, factory, configuration ); - } else if( ThreadSafe.class.isAssignableFrom( componentClass ) ) { + } else if( info.getModel() == ServiceInfo.MODEL_SINGLETON ) { handler = new ThreadSafeComponentHandler( logger, factory ); } else { // This is a SingleThreaded component Modified: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java ============================================================================== --- cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java (original) +++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/ComponentFactory.java Thu Nov 4 02:24:21 2004 @@ -16,8 +16,10 @@ */ package org.apache.cocoon.core.container; +import java.lang.reflect.Method; + import org.apache.avalon.excalibur.logger.LoggerManager; -import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.container.ContainerUtil; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.logger.LogEnabled; @@ -25,6 +27,7 @@ import org.apache.avalon.framework.parameters.Parameterizable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.avalon.framework.service.ServiceManager; +import org.apache.cocoon.components.ServiceInfo; /** * Factory for Avalon based components. @@ -33,11 +36,8 @@ */ public class ComponentFactory { - /** The class which this <code>ComponentFactory</code> - * should create. - */ - private final Class componentClass; - + private final ServiceInfo serviceInfo; + /** The Context for the component */ private final Context context; @@ -46,10 +46,6 @@ */ private final ServiceManager serviceManager; - /** The configuration for this component. - */ - private final Configuration configuration; - /** The parameters for this component */ private Parameters parameters; @@ -69,20 +65,18 @@ * @param context the <code>Context</code> to pass to <code>Contexutalizable</code>s. * */ - public ComponentFactory( final Class componentClass, - final Configuration configuration, - final ServiceManager serviceManager, + public ComponentFactory( final ServiceManager serviceManager, final Context context, final Logger logger, final LoggerManager loggerManager, - final RoleManager roleManager) { - this.componentClass = componentClass; - this.configuration = configuration; + final RoleManager roleManager, + final ServiceInfo info) { this.serviceManager = serviceManager; this.context = context; this.logger = logger; this.loggerManager = loggerManager; this.roleManager = roleManager; + this.serviceInfo = info; } /** @@ -90,18 +84,18 @@ */ public Object newInstance() throws Exception { - final Object component = this.componentClass.newInstance(); + final Object component = this.serviceInfo.getServiceClass().newInstance(); if( this.logger.isDebugEnabled() ) { this.logger.debug( "ComponentFactory creating new instance of " + - this.componentClass.getName() + "." ); + this.serviceInfo.getServiceClass().getName() + "." ); } if ( component instanceof LogEnabled ) { - if( null == this.configuration ) { + if( this.serviceInfo.getConfiguration() != null ) { ContainerUtil.enableLogging( component, this.logger ); } else { - final String logger = this.configuration.getAttribute( "logger", null ); + final String logger = this.serviceInfo.getConfiguration().getAttribute( "logger", null ); if( null == logger ) { this.logger.debug( "no logger attribute available, using standard logger" ); ContainerUtil.enableLogging( component, this.logger ); @@ -120,24 +114,29 @@ ((CocoonServiceSelector)component).setRoleManager(this.roleManager); } - ContainerUtil.configure( component, this.configuration ); + ContainerUtil.configure( component, this.serviceInfo.getConfiguration() ); if( component instanceof Parameterizable ) { if ( this.parameters == null ) { - this.parameters = Parameters.fromConfiguration( this.configuration ); + this.parameters = Parameters.fromConfiguration( this.serviceInfo.getConfiguration() ); } ContainerUtil.parameterize( component, this.parameters ); } ContainerUtil.initialize( component ); + final Method method = this.serviceInfo.getInitMethod(); + if ( method != null ) { + method.invoke(component, null); + } + ContainerUtil.start( component ); return component; } public Class getCreatedClass() { - return this.componentClass; + return this.serviceInfo.getServiceClass(); } /** @@ -147,11 +146,41 @@ throws Exception { if( this.logger.isDebugEnabled() ) { this.logger.debug( "ComponentFactory decommissioning instance of " + - this.componentClass.getName() + "." ); + this.serviceInfo.getServiceClass().getName() + "." ); } ContainerUtil.stop( component ); ContainerUtil.dispose( component ); + + final Method method = this.serviceInfo.getDestroyMethod(); + if ( method != null ) { + method.invoke(component, null); + } } + /** + * Handle service specific methods for getting it out of the pool + */ + public void exitingPool( final Object component ) + throws Exception { + final Method method = this.serviceInfo.getPoolOutMethod(); + if ( method != null ) { + method.invoke(component, null); + } + } + + /** + * Handle service specific methods for putting it into the pool + */ + public void enteringPool( final Object component ) + throws Exception { + // Handle Recyclable objects + if( component instanceof Recyclable ) { + ( (Recyclable)component ).recycle(); + } + final Method method = this.serviceInfo.getPoolInMethod(); + if ( method != null ) { + method.invoke(component, null); + } + } } Modified: cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java ============================================================================== --- cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java (original) +++ cocoon/trunk/src/core/java/org/apache/cocoon/core/container/PoolableComponentHandler.java Thu Nov 4 02:24:21 2004 @@ -19,7 +19,6 @@ import java.util.Iterator; import java.util.LinkedList; -import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.configuration.Configuration; import org.apache.avalon.framework.logger.Logger; @@ -114,7 +113,7 @@ synchronized( this.semaphore ) { // Remove objects in the ready list. for( Iterator iter = this.ready.iterator(); iter.hasNext(); ) { - Object poolable = (Object)iter.next(); + Object poolable = iter.next(); iter.remove(); this.readySize--; this.permanentlyRemovePoolable( poolable ); @@ -169,6 +168,8 @@ } } + this.factory.exitingPool(poolable); + if( this.logger.isDebugEnabled() ) { this.logger.debug( "Got a " + poolable.getClass().getName() + " from the pool." ); } @@ -182,14 +183,14 @@ * @param poolable Poolable to return to the pool. */ protected void doPut( final Object poolable ) { - // Handle Recyclable objects - if( poolable instanceof Recyclable ) { - ( (Recyclable)poolable ).recycle(); + try { + this.factory.enteringPool(poolable); + } catch (Exception ignore) { + this.logger.warn("Exception during putting component back into the pool.", ignore); } synchronized( this.semaphore ) { - if( this.size <= this.max ) - { + if( this.size <= this.max ) { if( this.disposed ) { // The pool has already been disposed. if( this.logger.isDebugEnabled() ) { Modified: cocoon/trunk/src/samples/org/apache/cocoon/samples/parentcm/Configurator.java ============================================================================== --- cocoon/trunk/src/samples/org/apache/cocoon/samples/parentcm/Configurator.java (original) +++ cocoon/trunk/src/samples/org/apache/cocoon/samples/parentcm/Configurator.java Thu Nov 4 02:24:21 2004 @@ -48,9 +48,9 @@ // DefaultConfiguration config = new DefaultConfiguration("roles", ""); DefaultConfiguration timeComponent = new DefaultConfiguration("role", "roles"); - timeComponent.addAttribute("name", Time.ROLE); - timeComponent.addAttribute("default-class", TimeComponent.class.getName()); - timeComponent.addAttribute("shorthand", "samples-parentcm-time"); + timeComponent.setAttribute("name", Time.ROLE); + timeComponent.setAttribute("default-class", TimeComponent.class.getName()); + timeComponent.setAttribute("shorthand", "samples-parentcm-time"); config.addChild(timeComponent); //