You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2006/05/14 11:45:13 UTC

svn commit: r406298 - /cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/StandaloneServiceSelector.java

Author: cziegeler
Date: Sun May 14 02:45:13 2006
New Revision: 406298

URL: http://svn.apache.org/viewcvs?rev=406298&view=rev
Log:
New version which should support single threaded and thread safe components.

Modified:
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/StandaloneServiceSelector.java

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/StandaloneServiceSelector.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/StandaloneServiceSelector.java?rev=406298&r1=406297&r2=406298&view=diff
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/StandaloneServiceSelector.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/StandaloneServiceSelector.java Sun May 14 02:45:13 2006
@@ -16,11 +16,9 @@
  */
 package org.apache.cocoon.components.treeprocessor;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.avalon.framework.activity.Disposable;
@@ -38,11 +36,12 @@
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.core.container.spring.ComponentInfo;
 import org.apache.cocoon.util.ClassUtils;
 
 /**
- * Default component selector for Cocoon's components.
+ * This is the selector used to select/create node builders.
  *
  * @version $Id$
  * @since 2.2
@@ -69,8 +68,11 @@
     /** The application context for components */
     protected Context context;
 
-    /** Used to map roles to ComponentHandlers. */
-    protected final Map componentHandlers = Collections.synchronizedMap(new HashMap());
+    /** Used to map roles to component infos. */
+    protected final Map componentInfos = Collections.synchronizedMap(new HashMap());
+
+    /** All singletons. */
+    protected final Map singletons = Collections.synchronizedMap(new HashMap());
 
     /** Is the Manager disposed or not? */
     protected boolean disposed;
@@ -92,22 +94,21 @@
      * @param componentClass Class of the component for which the handle is
      *                       being requested.
      * @param configuration The configuration for this component.
-     * @param serviceManager The service manager which will be managing the Component.
      *
      * @throws Exception If there were any problems obtaining a ComponentHandler
      */
-    protected ComponentInfo getComponentHandler( final String role,
-                                                    final Class componentClass,
-                                                    final Configuration configuration,
-                                                    final ServiceManager serviceManager)
+    protected ComponentInfo getComponentInfo( final Class componentClass,
+                                              final Configuration configuration)
     throws Exception {
-        ComponentInfo info;
-        info = new ComponentInfo();
+        final ComponentInfo info = new ComponentInfo();
         info.fill(configuration);
-        info.setRole(role);
         info.setConfiguration(configuration);
         info.setComponentClassName(componentClass.getName());
-        info.setModel(ComponentInfo.MODEL_SINGLETON);
+        if ( ThreadSafe.class.isAssignableFrom( componentClass ) ) {
+            info.setModel(ComponentInfo.MODEL_SINGLETON);
+        } else {
+            info.setModel(ComponentInfo.MODEL_PRIMITIVE);
+        }
         return info;
     }
 
@@ -173,16 +174,23 @@
                 "You cannot select a component from a disposed service selector." );
         }
 
-        Object component = this.componentHandlers.get( key );
-
-        // Retrieve the instance of the requested component
-        if( null == component ) {
-            final String message = this.roleName
-                + ": service selector could not find the component for key [" + key + "]";
-            if( this.getLogger().isDebugEnabled() ) {
-                this.getLogger().debug( message );
+        Object component = this.singletons.get(key);
+        if ( component == null ) {
+            final ComponentInfo info = (ComponentInfo)this.componentInfos.get( key );
+
+            // Retrieve the instance of the requested component
+            if( null == info ) {
+                final String message = this.roleName
+                   + ": service selector could not find the component for key [" + key + "]";
+                throw new ServiceException( key, message );
+            }
+            try {
+                component = this.createComponent(info);
+            } catch (ServiceException se) {
+                throw se;
+            } catch (Exception e) {
+                throw new ServiceException(key, "Unable to create new component.", e);
             }
-            throw new ServiceException( key, message );
         }
 
         return component;
@@ -205,7 +213,7 @@
         boolean exists = false;
 
         try {
-            Object component = this.componentHandlers.get( key );
+            Object component = this.componentInfos.get( key );
             exists = (component != null);
         } catch( Throwable t ) {
             // We can safely ignore all exceptions
@@ -218,7 +226,9 @@
      * @see org.apache.avalon.framework.service.ServiceSelector#release(java.lang.Object)
      */
     public void release( final Object component ) {
-        // nothing to do as we only serve singletons
+        if ( !(component instanceof ThreadSafe) ) {
+            ContainerUtil.dispose(component);
+        }
     }
 
     /**
@@ -234,26 +244,23 @@
      */
     public void configure( final Configuration config )
     throws ConfigurationException {
-        this.roleName = getRoleName(config);
+        this.roleName = config.getAttribute("role", null);
 
         // Get default key
-        this.defaultKey = config.getAttribute(this.getDefaultKeyAttributeName(), null);
+        this.defaultKey = config.getAttribute("default", null);
 
-        // Add components
-        String compInstanceName = getComponentInstanceName();
-
-        Configuration[] instances = config.getChildren();
+        final Configuration[] instances = config.getChildren();
 
         for (int i = 0; i < instances.length; i++) {
 
-            Configuration instance = instances[i];
+            final Configuration instance = instances[i];
             String key = instance.getAttribute("name").trim();
 
-            String classAttr = instance.getAttribute(getClassAttributeName(), null);
+            String classAttr = instance.getAttribute("builder", null);
             String className;
 
             // component-instances names explicitly defined
-            if (compInstanceName.equals(instance.getName())) {
+            if ("node".equals(instance.getName())) {
                 className = (classAttr == null) ? null : classAttr.trim();
             } else {
                 className = null;
@@ -263,7 +270,6 @@
                 String message = "Unable to determine class name for component named '" + key +
                     "' at " + instance.getLocation();
 
-                getLogger().error(message);
                 throw new ConfigurationException(message);
             }
 
@@ -272,52 +278,50 @@
     }
 
     /**
+     * Create a new component.
+     */
+    protected Object createComponent(ComponentInfo info)
+    throws Exception {
+        final Object component = ClassUtils.newInstance(info.getComponentClassName());
+        ContainerUtil.enableLogging(component, this.getLogger());
+        ContainerUtil.contextualize(component, this.context);
+        ContainerUtil.service(component, this.serviceManager);
+        ContainerUtil.configure(component, info.getConfiguration());
+        if ( component instanceof Parameterizable ) {
+            ContainerUtil.parameterize(component, Parameters.fromConfiguration(info.getConfiguration()));
+        }
+        ContainerUtil.initialize(component);
+        return component;
+    }
+
+    /**
      * @see org.apache.avalon.framework.activity.Initializable#initialize()
      */
     public void initialize() 
     throws Exception {
         this.initialized = true;
 
-        List keys = new ArrayList( this.componentHandlers.keySet() );
-        final Map components = new HashMap();
-
-        for( int i = 0; i < keys.size(); i++ ) {
-            final Object key = keys.get( i );
-            final ComponentInfo handler =
-                (ComponentInfo)this.componentHandlers.get( key );
-
-            try {
-                Object component = ClassUtils.newInstance(handler.getComponentClassName());
-                ContainerUtil.enableLogging(component, this.getLogger());
-                ContainerUtil.contextualize(component, this.context);
-                ContainerUtil.service(component, this.serviceManager);
-                ContainerUtil.configure(component, handler.getConfiguration());
-                if ( component instanceof Parameterizable ) {
-                    ContainerUtil.parameterize(component, Parameters.fromConfiguration(handler.getConfiguration()));
-                }
-                ContainerUtil.initialize(component);
-                components.put(key, component);
-            } catch( Exception e ) {
-                if( this.getLogger().isDebugEnabled() ) {
-                    this.getLogger().debug( "Caught an exception trying to initialize "
-                        + "of the component handler.", e );
-                }
+        final Iterator i = this.componentInfos.entrySet().iterator();
+        while ( i.hasNext() ) {
+            final Map.Entry entry = (Map.Entry)i.next();
+            final ComponentInfo info = (ComponentInfo)entry.getValue();
+            if ( info.getModel() == ComponentInfo.MODEL_SINGLETON ) {
+                this.singletons.put(entry.getKey(), this.createComponent(info));
             }
         }
-        this.componentHandlers.clear();
-        this.componentHandlers.putAll(components);
     }
 
     /**
      * @see org.apache.avalon.framework.activity.Disposable#dispose()
      */
     public void dispose() {
-        Iterator iter = this.componentHandlers.values().iterator();
+        final Iterator iter = this.singletons.values().iterator();
         while( iter.hasNext() ) {
             final Object current = iter.next();
             ContainerUtil.dispose(current);
         }
-        this.componentHandlers.clear();
+        this.singletons.clear();
+        this.componentInfos.clear();
         this.disposed = true;
     }
 
@@ -336,12 +340,10 @@
         }
 
         try {
-            final ComponentInfo handler = getComponentHandler( null,
-                                                               component,
-                                                               configuration,
-                                                               this.serviceManager);
+            final ComponentInfo handler = getComponentInfo( component,
+                                                            configuration);
 
-            this.componentHandlers.put( key, handler );
+            this.componentInfos.put( key, handler );
 
             if( this.getLogger().isDebugEnabled() ) {
                 this.getLogger().debug(
@@ -358,52 +360,5 @@
 
             throw new ServiceException(key, message, e );
         }
-    }
-
-    /**
-     * Get the name for component-instance elements (i.e. components not defined
-     * by their role shortcut. If <code>null</code>, any element having a 'class'
-     * attribute will be considered as a component instance.
-     * <p>
-     * The default here is to return <code>null</code>, and subclasses can redefine
-     * this method to return particular values.
-     *
-     * @return <code>null</code>, but can be changed by subclasses
-     */
-    protected String getComponentInstanceName() {
-        return "node";
-    }
-
-    /**
-     * Get the name of the attribute giving the class name of a component.
-     * The default here is "class", but this can be overriden in subclasses.
-     *
-     * @return "<code>class</code>", but can be changed by subclasses
-     */
-    protected String getClassAttributeName() {
-        return "builder";
-    }
-
-    /**
-     * Get the name of the attribute giving the default key to use if
-     * none is given. The default here is "default", but this can be
-     * overriden in subclasses. If this method returns <code>null</code>,
-     * no default key can be specified.
-     *
-     * @return "<code>default</code>", but can be changed by subclasses
-     */
-    protected String getDefaultKeyAttributeName() {
-        return "default";
-    }
-
-    /**
-     * Get the role name for this selector. This is called by <code>configure()</code>
-     * to set the value of <code>this.roleName</code>.
-     *
-     * @return the role name, or <code>null<code> if it couldn't be determined.
-     */
-    protected String getRoleName(Configuration config) {
-        // Get the role for this selector
-        return config.getAttribute("role", null);
     }
 }