You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@turbine.apache.org by tv...@apache.org on 2011/11/10 03:31:47 UTC
svn commit: r1200102 - in /turbine/core/trunk: conf/test/ src/changes/
src/java/org/apache/turbine/services/
src/test/org/apache/turbine/services/avaloncomponent/
Author: tv
Date: Thu Nov 10 02:31:47 2011
New Revision: 1200102
URL: http://svn.apache.org/viewvc?rev=1200102&view=rev
Log:
Services that implement TurbineServiceProvider are inited early by default. Adjusted tests. Fixes TRB-72
Modified:
turbine/core/trunk/conf/test/TestFulcrumComponents.properties
turbine/core/trunk/src/changes/changes.xml
turbine/core/trunk/src/java/org/apache/turbine/services/BaseServiceBroker.java
turbine/core/trunk/src/test/org/apache/turbine/services/avaloncomponent/TurbineAvalonComponentServiceTest.java
Modified: turbine/core/trunk/conf/test/TestFulcrumComponents.properties
URL: http://svn.apache.org/viewvc/turbine/core/trunk/conf/test/TestFulcrumComponents.properties?rev=1200102&r1=1200101&r2=1200102&view=diff
==============================================================================
--- turbine/core/trunk/conf/test/TestFulcrumComponents.properties (original)
+++ turbine/core/trunk/conf/test/TestFulcrumComponents.properties Thu Nov 10 02:31:47 2011
@@ -128,5 +128,4 @@ tool.request.l10n=org.apache.turbine.ser
services.AvalonComponentService.componentConfiguration = conf/test/fulcrumComponentConfiguration.xml
services.AvalonComponentService.componentRoles = conf/test/fulcrumRoleConfiguration.xml
-services.AvalonComponentService.earlyInit=true
services.AvalonComponentService.lookup = org.apache.fulcrum.cache.GlobalCacheService
Modified: turbine/core/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/changes/changes.xml?rev=1200102&r1=1200101&r2=1200102&view=diff
==============================================================================
--- turbine/core/trunk/src/changes/changes.xml (original)
+++ turbine/core/trunk/src/changes/changes.xml Thu Nov 10 02:31:47 2011
@@ -25,6 +25,9 @@
<body>
<release version="4.0-M2" date="in Subversion">
+ <action type="update" dev="tv" issue="TRB-72">
+ Services that implement TurbineServiceProvider are inited early by default
+ </action>
<action type="update" dev="tv">
Switch from String keys to Class keys for AssemblerBrokerService
</action>
Modified: turbine/core/trunk/src/java/org/apache/turbine/services/BaseServiceBroker.java
URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/java/org/apache/turbine/services/BaseServiceBroker.java?rev=1200102&r1=1200101&r2=1200102&view=diff
==============================================================================
--- turbine/core/trunk/src/java/org/apache/turbine/services/BaseServiceBroker.java (original)
+++ turbine/core/trunk/src/java/org/apache/turbine/services/BaseServiceBroker.java Thu Nov 10 02:31:47 2011
@@ -24,8 +24,11 @@ import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
-import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
@@ -37,7 +40,7 @@ import org.apache.commons.logging.LogFac
*
* <ul>
* <li>Maintaining service name to class name mapping, allowing
- * plugable service implementations.</li>
+ * pluggable service implementations.</li>
* <li>Providing <code>Services</code> with a configuration based on
* system wide configuration mechanism.</li>
* </ul>
@@ -56,14 +59,14 @@ import org.apache.commons.logging.LogFac
public abstract class BaseServiceBroker implements ServiceBroker
{
/**
- * Mapping of Service names to class names.
+ * Mapping of Service names to class names, keep order.
*/
- private Configuration mapping = new BaseConfiguration();
+ private final Map<String, Class<?>> mapping = new LinkedHashMap<String, Class<?>>();
/**
* A repository of Service instances.
*/
- private Hashtable<String, Service> services = new Hashtable<String, Service>();
+ private final Hashtable<String, Service> services = new Hashtable<String, Service>();
/**
* Configuration for the services broker.
@@ -95,7 +98,7 @@ public abstract class BaseServiceBroker
* the requirement of having init(Object) all
* together.
*/
- private Hashtable<String, Object> serviceObjects = new Hashtable<String, Object>();
+ private final Hashtable<String, Object> serviceObjects = new Hashtable<String, Object>();
/** Logging */
private static Log log = LogFactory.getLog(BaseServiceBroker.class);
@@ -109,10 +112,10 @@ public abstract class BaseServiceBroker
/**
* mapping from service names to instances of TurbineServiceProviders
*/
- private Hashtable<String, Service> serviceProviderInstanceMap = new Hashtable<String, Service>();
+ private final Hashtable<String, Service> serviceProviderInstanceMap = new Hashtable<String, Service>();
/**
- * Default constructor, protected as to only be useable by subclasses.
+ * Default constructor, protected as to only be usable by subclasses.
*
* This constructor does nothing.
*/
@@ -191,6 +194,33 @@ public abstract class BaseServiceBroker
}
/**
+ * Check recursively if the given checkIfc interface is among the implemented
+ * interfaces
+ *
+ * @param checkIfc interface to check for
+ * @param interfaces interfaces to scan
+ * @return true if the interface is implemented
+ */
+ private boolean checkForInterface(Class<?> checkIfc, Class<?>[] interfaces)
+ {
+ for (Class<?> ifc : interfaces)
+ {
+ if (ifc == checkIfc)
+ {
+ return true;
+ }
+
+ Class<?>[] subInterfaces = ifc.getInterfaces();
+ if (checkForInterface(checkIfc, subInterfaces))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
* Creates a mapping between Service names and class names.
*
* The mapping is built according to settings present in
@@ -205,21 +235,19 @@ public abstract class BaseServiceBroker
* <br>
*
* Generic ServiceBroker provides no Services.
+ * @throws InitializationException if a service class could not be found
*/
@SuppressWarnings("unchecked")
- protected void initMapping()
+ protected void initMapping() throws InitializationException
{
+ // we need to temporarily store the earlyInit flags to avoid
+ // ConcurrentModificationExceptions
+ Map<String, String> earlyInitFlags = new LinkedHashMap<String, String>();
+
/*
* These keys returned in an order that corresponds
* to the order the services are listed in
* the TR.props.
- *
- * When the mapping is created we use a Configuration
- * object to ensure that the we retain the order
- * in which the order the keys are returned.
- *
- * There's no point in retrieving an ordered set
- * of keys if they aren't kept in order :-)
*/
for (Iterator<String> keys = configuration.getKeys(); keys.hasNext();)
{
@@ -235,18 +263,53 @@ public abstract class BaseServiceBroker
if (!mapping.containsKey(serviceKey))
{
- mapping.setProperty(serviceKey,
- configuration.getString(key));
+ String className = configuration.getString(key);
+ try
+ {
+ Class<?> clazz = Class.forName(className);
+ mapping.put(serviceKey, clazz);
+
+ // detect TurbineServiceProviders
+ if (checkForInterface(TurbineServiceProvider.class, clazz.getInterfaces()))
+ {
+ log.info("Found a TurbineServiceProvider: " + serviceKey + " - initializing it early");
+ earlyInitFlags.put(SERVICE_PREFIX + serviceKey + ".earlyInit", "true");
+ }
+ }
+ // those two errors must be passed to the VM
+ catch (ThreadDeath t)
+ {
+ throw t;
+ }
+ catch (OutOfMemoryError t)
+ {
+ throw t;
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new InitializationException("Class " + className +
+ " is unavailable. Check your jars and classes.", e);
+ }
+ catch (NoClassDefFoundError e)
+ {
+ throw new InitializationException("Class " + className +
+ " is unavailable. Check your jars and classes.", e);
+ }
}
}
}
+
+ for (Map.Entry<String, String> entry : earlyInitFlags.entrySet())
+ {
+ configuration.setProperty(entry.getKey(), entry.getValue());
+ }
}
/**
* Determines whether a service is registered in the configured
* <code>TurbineResources.properties</code>.
*
- * @param serviceName The name of the service whose existance to check.
+ * @param serviceName The name of the service whose existence to check.
* @return Registration predicate for the desired services.
*/
public boolean isRegistered(String serviceName)
@@ -259,10 +322,9 @@ public abstract class BaseServiceBroker
*
* @return An Iterator of service names.
*/
- @SuppressWarnings("unchecked")
public Iterator<String> getServiceNames()
{
- return mapping.getKeys();
+ return mapping.keySet().iterator();
}
/**
@@ -272,10 +334,18 @@ public abstract class BaseServiceBroker
* @param prefix The prefix against which to test.
* @return An Iterator of service names which match the prefix.
*/
- @SuppressWarnings("unchecked")
public Iterator<String> getServiceNames(String prefix)
{
- return mapping.getKeys(prefix);
+ Set<String> keys = new LinkedHashSet<String>(mapping.keySet());
+ for(Iterator<String> key = keys.iterator(); key.hasNext();)
+ {
+ if (!key.next().startsWith(prefix))
+ {
+ key.remove();
+ }
+ }
+
+ return keys.iterator();
}
/**
@@ -531,76 +601,46 @@ public abstract class BaseServiceBroker
if (service == null)
{
-
- String className=null;
if (!this.isLocalService(name))
{
throw new InstantiationException(
"ServiceBroker: unknown service " + name
+ " requested");
}
+
try
{
- className = mapping.getString(name);
- service = services.get(className);
+ Class<?> clazz = mapping.get(name);
- if (service == null)
+ try
{
- try
- {
- service = (Service) Class.forName(className).newInstance();
+ service = (Service) clazz.newInstance();
- // check if the newly created service is also a
- // service provider - if so then remember it
- if (service instanceof TurbineServiceProvider)
- {
- this.serviceProviderInstanceMap.put(name,service);
- }
-
- }
- // those two errors must be passed to the VM
- catch (ThreadDeath t)
- {
- throw t;
- }
- catch (OutOfMemoryError t)
- {
- throw t;
- }
- catch (Throwable t)
+ // check if the newly created service is also a
+ // service provider - if so then remember it
+ if (service instanceof TurbineServiceProvider)
{
- // Used to indicate error condition.
- String msg = null;
-
- if (t instanceof NoClassDefFoundError)
- {
- msg = "A class referenced by " + className +
- " is unavailable. Check your jars and classes.";
- }
- else if (t instanceof ClassNotFoundException)
- {
- msg = "Class " + className +
- " is unavailable. Check your jars and classes.";
- }
- else if (t instanceof ClassCastException)
- {
- msg = "Class " + className +
- " doesn't implement the Service interface";
- }
- else
- {
- msg = "Failed to instantiate " + className;
- }
-
- throw new InstantiationException(msg, t);
+ this.serviceProviderInstanceMap.put(name,service);
}
}
- }
- catch (ClassCastException e)
- {
- throw new InstantiationException("ServiceBroker: Class "
- + className
- + " does not implement Service interface.", e);
+ // those two errors must be passed to the VM
+ catch (ClassCastException e)
+ {
+ throw new InstantiationException("Class " + clazz +
+ " doesn't implement the Service interface", e);
+ }
+ catch (ThreadDeath t)
+ {
+ throw t;
+ }
+ catch (OutOfMemoryError t)
+ {
+ throw t;
+ }
+ catch (Throwable t)
+ {
+ throw new InstantiationException("Failed to instantiate " + clazz, t);
+ }
}
catch (InstantiationException e)
{
Modified: turbine/core/trunk/src/test/org/apache/turbine/services/avaloncomponent/TurbineAvalonComponentServiceTest.java
URL: http://svn.apache.org/viewvc/turbine/core/trunk/src/test/org/apache/turbine/services/avaloncomponent/TurbineAvalonComponentServiceTest.java?rev=1200102&r1=1200101&r2=1200102&view=diff
==============================================================================
--- turbine/core/trunk/src/test/org/apache/turbine/services/avaloncomponent/TurbineAvalonComponentServiceTest.java (original)
+++ turbine/core/trunk/src/test/org/apache/turbine/services/avaloncomponent/TurbineAvalonComponentServiceTest.java Thu Nov 10 02:31:47 2011
@@ -23,7 +23,6 @@ package org.apache.turbine.services.aval
import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
-
import org.apache.turbine.services.ServiceManager;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.test.BaseTestCase;
@@ -58,10 +57,9 @@ public class TurbineAvalonComponentServi
Configuration cfg = new BaseConfiguration();
- // decide here wether to start ECM or YAAFI
+ // decide here whether to start ECM or YAAFI
// cfg.setProperty(PREFIX + "classname", TurbineAvalonComponentService.class.getName());
cfg.setProperty(PREFIX + "classname", TurbineYaafiComponentService.class.getName());
- cfg.setProperty(PREFIX + "earlyInit", "true");
// we want to configure the service to load test TEST configuration files
cfg.setProperty(PREFIX + "componentConfiguration",