You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2006/08/12 20:24:19 UTC
svn commit: r431064 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/ main/java/org/apache/tapestry/internal/ioc/
main/java/org/apache/tapestry/internal/ioc/services/
main/java/org/apache/tapestry/internal/pageload/...
Author: hlship
Date: Sat Aug 12 11:24:17 2006
New Revision: 431064
URL: http://svn.apache.org/viewvc?rev=431064&view=rev
Log:
Add support for parameter injection into module class constructors (as a way to cache common services).
Rename ServiceCreator to ObjectCreator.
Change some method signatures to support deferring the creation of the module builder instance until just as needed.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java
- copied, changed from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java
- copied, changed from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ExtraPublicConstructorsModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/PrivateConstructorModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/RecursiveConstructorModule.java
Removed:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/service.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilderTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ModuleImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/OneShortServiceCreatorTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvokerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycleTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/ioc/IntegrationTest.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ComponentResources.java Sat Aug 12 11:24:17 2006
@@ -21,5 +21,9 @@
*/
public interface ComponentResources
{
-
+ /**
+ * Returns the id of the component. The id will be unique within the component's immediate
+ * container. For a page's root component, the value null is returned.
+ */
+ String getId();
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCMessages.java Sat Aug 12 11:24:17 2006
@@ -14,6 +14,7 @@
package org.apache.tapestry.internal.ioc;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
@@ -242,5 +243,27 @@
static String errorBuildingService(String serviceId, ServiceDef serviceDef, Throwable cause)
{
return MESSAGES.format("error-building-service", serviceId, serviceDef, cause);
+ }
+
+ static String noPublicConstructors(String moduleId, Class moduleBuilderClass)
+ {
+ return MESSAGES.format("no-public-constructors", moduleId, moduleBuilderClass.getName());
+ }
+
+ static String tooManyPublicConstructors(String moduleId, Class moduleBuilderClass,
+ Constructor constructor)
+ {
+ return MESSAGES.format("too-many-public-constructors", moduleId, moduleBuilderClass
+ .getName(), constructor);
+ }
+
+ static String recursiveModuleConstructor(String moduleId, Class builderClass,
+ Constructor constructor)
+ {
+ return MESSAGES.format(
+ "recursive-module-constructor",
+ moduleId,
+ builderClass.getName(),
+ constructor);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/IOCUtilities.java Sat Aug 12 11:24:17 2006
@@ -26,7 +26,8 @@
import org.apache.tapestry.ioc.ServiceLocator;
import org.apache.tapestry.ioc.annotations.Inject;
import org.apache.tapestry.ioc.annotations.InjectService;
-import org.apache.tapestry.util.CollectionFactory;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
/**
* Contains static methods used within this package.
@@ -100,6 +101,14 @@
{
Class[] parameterTypes = method.getParameterTypes();
Annotation[][] annotations = method.getParameterAnnotations();
+
+ return calculateParameters(locator, parameterDefaults, parameterTypes, annotations);
+ }
+
+ public static Object[] calculateParameters(ServiceLocator locator,
+ Map<Class, Object> parameterDefaults, Class[] parameterTypes,
+ Annotation[][] parameterAnnotations)
+ {
int parameterCount = parameterTypes.length;
Object[] parameters = new Object[parameterCount];
@@ -108,7 +117,7 @@
{
parameters[i] = calculateParameterValue(
parameterTypes[i],
- annotations[i],
+ parameterAnnotations[i],
locator,
parameterDefaults);
}
@@ -138,7 +147,7 @@
/** Creates a sorted copy of the provided elements, then turns that into a comma separated list. */
public static String joinSorted(Collection<String> elements)
{
- List<String> list = CollectionFactory.newList(elements);
+ List<String> list = newList(elements);
Collections.sort(list);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/InterceptorStackBuilder.java Sat Aug 12 11:24:17 2006
@@ -17,7 +17,7 @@
import java.util.Collections;
import java.util.List;
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
import org.apache.tapestry.ioc.ServiceDecorator;
/**
@@ -26,11 +26,11 @@
*
* @author Howard M. Lewis Ship
*/
-public class InterceptorStackBuilder implements ServiceCreator
+public class InterceptorStackBuilder implements ObjectCreator
{
private final String _serviceId;
- private final ServiceCreator _coreServiceCreator;
+ private final ObjectCreator _coreServiceCreator;
private final Module _module;
@@ -44,16 +44,16 @@
* interceptors
*/
public InterceptorStackBuilder(Module module, String serviceId,
- ServiceCreator coreServiceCreator)
+ ObjectCreator coreServiceCreator)
{
_module = module;
_serviceId = serviceId;
_coreServiceCreator = coreServiceCreator;
}
- public Object createService()
+ public Object createObject()
{
- Object current = _coreServiceCreator.createService();
+ Object current = _coreServiceCreator.createObject();
List<ServiceDecorator> decorators = _module.findDecoratorsForService(_serviceId);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/LifecycleWrappedServiceCreator.java Sat Aug 12 11:24:17 2006
@@ -14,7 +14,7 @@
package org.apache.tapestry.internal.ioc;
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
import org.apache.tapestry.ioc.ServiceLifecycle;
import org.apache.tapestry.ioc.ServiceResources;
@@ -25,16 +25,16 @@
*
* @author Howard M. Lewis Ship
*/
-public class LifecycleWrappedServiceCreator implements ServiceCreator
+public class LifecycleWrappedServiceCreator implements ObjectCreator
{
private final ServiceLifecycle _lifecycle;
private final ServiceResources _resources;
- private final ServiceCreator _creator;
+ private final ObjectCreator _creator;
public LifecycleWrappedServiceCreator(ServiceLifecycle lifecycle, ServiceResources resources,
- ServiceCreator creator)
+ ObjectCreator creator)
{
_lifecycle = lifecycle;
_resources = resources;
@@ -45,7 +45,7 @@
* Passes the resources and the service creator through the
* {@link org.apache.tapestry.ioc.ServiceLifecycle}.
*/
- public Object createService()
+ public Object createObject()
{
return _lifecycle.createService(_resources, _creator);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ModuleImpl.java Sat Aug 12 11:24:17 2006
@@ -14,6 +14,8 @@
package org.apache.tapestry.internal.ioc;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.List;
@@ -22,10 +24,11 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.internal.annotations.SuppressNullCheck;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
import org.apache.tapestry.ioc.ServiceDecorator;
import org.apache.tapestry.ioc.ServiceLifecycle;
+import org.apache.tapestry.ioc.ServiceLocator;
import org.apache.tapestry.ioc.ServiceResources;
import org.apache.tapestry.ioc.def.ContributionDef;
import org.apache.tapestry.ioc.def.DecoratorDef;
@@ -51,14 +54,23 @@
private final ModuleDef _moduleDef;
+ private final Log _log;
+
private Object _moduleBuilder;
private final static String INTERNAL_MODULE_ID = "tapestry.ioc";
- public ModuleImpl(InternalRegistry registry, ModuleDef moduleDef)
+ // Set to true when invoking the module constructor. Used to
+ // detect endless loops caused by irresponsible dependencies into
+ // the constructor.
+
+ private boolean _insideConstructor;
+
+ public ModuleImpl(InternalRegistry registry, ModuleDef moduleDef, Log log)
{
_registry = registry;
_moduleDef = moduleDef;
+ _log = log;
}
/** Keyed on fully qualified service id; values are instantiated services (proxies). */
@@ -114,7 +126,6 @@
return def.isPrivate() && this != module;
}
- /** TODO: Returns an empty list currently. */
public List<ServiceDecorator> findDecoratorsForService(String serviceId)
{
ServiceDef sd = _moduleDef.getServiceDef(serviceId);
@@ -185,12 +196,12 @@
{
ServiceLifecycle lifecycle = _registry.getServiceLifecycle(def.getServiceLifeycle());
- ServiceCreatorResources resources = new ServiceResourcesImpl(_registry, this, def, log);
+ ServiceBuilderResources resources = new ServiceResourcesImpl(_registry, this, def, log);
// Build up a stack of operations that will be needed to instantiate the service
// (by the proxy, at a later date).
- ServiceCreator creator = def.createServiceCreator(getModuleBuilder(), resources);
+ ObjectCreator creator = def.createServiceCreator(resources);
creator = new LifecycleWrappedServiceCreator(lifecycle, resources, creator);
@@ -199,13 +210,11 @@
if (!getModuleId().equals(INTERNAL_MODULE_ID))
creator = new InterceptorStackBuilder(this, serviceId, creator);
- Object service = null;
-
// Add a wrapper that makes sure that it only gets created once.
creator = new OneShotServiceCreator(def, creator);
- service = createProxy(resources, creator);
+ Object service = createProxy(resources, creator);
_services.put(serviceId, service);
@@ -217,37 +226,78 @@
}
}
- private synchronized void ensureModuleBuilderExists()
+ public synchronized Object getModuleBuilder()
{
- if (_moduleBuilder != null)
- return;
+ if (_moduleBuilder == null)
+ _moduleBuilder = instantiateModuleBuilder();
+
+ return _moduleBuilder;
+ }
+ private Object instantiateModuleBuilder()
+ {
Class builderClass = _moduleDef.getBuilderClass();
- // TODO: Support additional constructors (beyond no arguments constructor)?
+ Constructor[] constructors = builderClass.getConstructors();
+
+ if (constructors.length == 0)
+ throw new RuntimeException(IOCMessages.noPublicConstructors(
+ _moduleDef.getModuleId(),
+ builderClass));
+
+ // Use the first one.
+
+ Constructor constructor = constructors[0];
+
+ if (constructors.length > 1)
+ _log.warn(IOCMessages.tooManyPublicConstructors(
+ _moduleDef.getModuleId(),
+ builderClass,
+ constructor));
+
+ if (_insideConstructor)
+ throw new RuntimeException(IOCMessages.recursiveModuleConstructor(_moduleDef
+ .getModuleId(), builderClass, constructor));
+
+ ServiceLocator locator = new ServiceLocatorImpl(_registry, this);
+ Map<Class, Object> parameterDefaults = newMap();
+
+ parameterDefaults.put(Log.class, _log);
+ parameterDefaults.put(String.class, _moduleDef.getModuleId());
+ parameterDefaults.put(ServiceLocator.class, locator);
+
+ Throwable fail = null;
try
{
- _moduleBuilder = builderClass.newInstance();
+ _insideConstructor = true;
+
+ Object[] parameterValues = IOCUtilities.calculateParameters(
+ locator,
+ parameterDefaults,
+ constructor.getParameterTypes(),
+ constructor.getParameterAnnotations());
+
+ return constructor.newInstance(parameterValues);
+ }
+ catch (InvocationTargetException ex)
+ {
+ fail = ex.getTargetException();
}
catch (Exception ex)
{
- throw new RuntimeException(IOCMessages.instantiateBuilderError(builderClass, _moduleDef
- .getModuleId(), ex), ex);
+ fail = ex;
+ }
+ finally
+ {
+ _insideConstructor = false;
}
- }
-
- public Object getModuleBuilder()
- {
- // Pretty sure that in the situations where this method is invoked, the MB will already have
- // been instantiated, but just to be safe.
-
- ensureModuleBuilderExists();
- return _moduleBuilder;
+ throw new RuntimeException(IOCMessages.instantiateBuilderError(builderClass, _moduleDef
+ .getModuleId(), fail), fail);
}
- private Object createProxy(ServiceResources resources, ServiceCreator creator)
+ private Object createProxy(ServiceResources resources, ObjectCreator creator)
{
String serviceId = resources.getServiceId();
Class serviceInterface = resources.getServiceInterface();
@@ -257,7 +307,7 @@
return createProxyInstance(creator, serviceId, serviceInterface, toString);
}
- private Object createProxyInstance(ServiceCreator creator, String serviceId,
+ private Object createProxyInstance(ObjectCreator creator, String serviceId,
Class serviceInterface, String description)
{
Class proxyClass = createProxyClass(serviceId, serviceInterface, description);
@@ -278,11 +328,11 @@
{
ClassFab cf = _registry.newClass(serviceInterface);
- cf.addField("_creator", ServiceCreator.class);
+ cf.addField("_creator", ObjectCreator.class);
cf.addField("_delegate", serviceInterface);
cf.addConstructor(new Class[]
- { ServiceCreator.class }, null, "_creator = $1;");
+ { ObjectCreator.class }, null, "_creator = $1;");
addDelegateGetter(cf, serviceInterface);
@@ -300,7 +350,7 @@
builder.addln("if (_delegate == null)");
builder.begin();
- builder.addln("_delegate = (%s) _creator.createService();", serviceInterface.getName());
+ builder.addln("_delegate = (%s) _creator.createObject();", serviceInterface.getName());
builder.addln("_creator = null;");
builder.end();
@@ -333,4 +383,5 @@
return result;
}
+
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/OneShotServiceCreator.java Sat Aug 12 11:24:17 2006
@@ -14,11 +14,11 @@
package org.apache.tapestry.internal.ioc;
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
import org.apache.tapestry.ioc.def.ServiceDef;
/**
- * Decorator for {@link org.apache.tapestry.ioc.ServiceCreator} that ensures the service is only
+ * Decorator for {@link org.apache.tapestry.ioc.ObjectCreator} that ensures the service is only
* created once. This detects a situation where the service builder for a service directly or
* indirectly invokes methods on the service itself. This would show up as a second call up the
* ServiceCreator stack injected into the proxy.
@@ -28,15 +28,15 @@
*
* @author Howard M. Lewis Ship
*/
-public class OneShotServiceCreator implements ServiceCreator
+public class OneShotServiceCreator implements ObjectCreator
{
private final ServiceDef _serviceDef;
- private final ServiceCreator _delegate;
+ private final ObjectCreator _delegate;
private boolean _locked;
- public OneShotServiceCreator(ServiceDef serviceDef, ServiceCreator delegate)
+ public OneShotServiceCreator(ServiceDef serviceDef, ObjectCreator delegate)
{
_serviceDef = serviceDef;
_delegate = delegate;
@@ -46,14 +46,14 @@
* We could make this method synchronized, but in the context of creating a service for a proxy,
* it will already be synchronized (inside the proxy).
*/
- public Object createService()
+ public Object createObject()
{
if (_locked)
throw new IllegalStateException(IOCMessages.recursiveServiceBuild(_serviceDef));
_locked = true;
- return _delegate.createService();
+ return _delegate.createObject();
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/RegistryImpl.java Sat Aug 12 11:24:17 2006
@@ -64,6 +64,8 @@
*/
static final String CLASS_FACTORY_SERVICE_ID = "tapestry.ioc.ClassFactory";
+ static final String LOG_SOURCE_SERVICE_ID = "tapestry.ioc.LogSource";
+
private final Map<String, Object> _builtinServices = newMap();
private final Map<String, Class> _builtinTypes = newMap();
@@ -102,9 +104,14 @@
for (ModuleDef def : moduleDefs)
{
- Module module = new ModuleImpl(this, def);
+ Log log = _logSource.getLog(def.getModuleId());
+
+ Module module = new ModuleImpl(this, def, log);
+
_modules.put(def.getModuleId(), module);
}
+
+ addBuiltin(LOG_SOURCE_SERVICE_ID, LogSource.class, _logSource);
Log log = _logSource.getLog(RegistryImpl.CLASS_FACTORY_SERVICE_ID);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceBuilderMethodInvoker.java Sat Aug 12 11:24:17 2006
@@ -23,8 +23,8 @@
import java.util.Map;
import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
import org.apache.tapestry.ioc.ServiceResources;
import static org.apache.tapestry.internal.ioc.ConfigurationType.MAPPED;
@@ -34,21 +34,19 @@
import static org.apache.tapestry.util.CollectionFactory.newMap;
/**
- * Basic implementation of {@link org.apache.tapestry.ioc.ServiceCreator} that handles invoking a
+ * Basic implementation of {@link org.apache.tapestry.ioc.ObjectCreator} that handles invoking a
* method on the module builder, and figures out the correct parameters to pass into the annotated
* method.
*
* @author Howard M. Lewis Ship
*/
-public class ServiceBuilderMethodInvoker implements ServiceCreator
+public class ServiceBuilderMethodInvoker implements ObjectCreator
{
- private final Object _moduleBuilder;
-
private final String _serviceId;
private final Map<Class, Object> _parameterDefaults = newMap();
- private final ServiceCreatorResources _resources;
+ private final ServiceBuilderResources _resources;
private final Method _builderMethod;
@@ -63,12 +61,10 @@
PARAMETER_TYPE_TO_CONFIGURATION_TYPE.put(Map.class, MAPPED);
}
- public ServiceBuilderMethodInvoker(Method method, Object moduleBuilder,
- ServiceCreatorResources resources)
+ public ServiceBuilderMethodInvoker(Method method, ServiceBuilderResources resources)
{
_serviceId = resources.getServiceId();
_builderMethod = method;
- _moduleBuilder = moduleBuilder;
_resources = resources;
_log = resources.getServiceLog();
@@ -233,8 +229,12 @@
/**
* Invoked from the proxy to create the actual service implementation.
*/
- public Object createService()
+ public Object createObject()
{
+ // Defer getting (and possibly instantitating) the module builder until the last possible
+ // moment.
+
+ Object moduleBuilder = _resources.getModuleBuilder();
if (_log.isDebugEnabled())
_log.debug(IOCMessages.invokingMethod(_builderMethod));
@@ -249,7 +249,7 @@
_resources,
getParameterDefaultsWithConfigurations());
- result = _builderMethod.invoke(_moduleBuilder, parameters);
+ result = _builderMethod.invoke(moduleBuilder, parameters);
}
catch (InvocationTargetException ite)
{
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceDefImpl.java Sat Aug 12 11:24:17 2006
@@ -17,8 +17,8 @@
import java.lang.reflect.Method;
import org.apache.tapestry.internal.util.InternalUtils;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
import org.apache.tapestry.ioc.def.ServiceDef;
/**
@@ -53,9 +53,9 @@
return _builderMethod;
}
- public ServiceCreator createServiceCreator(Object moduleBuilder, ServiceCreatorResources resources)
+ public ObjectCreator createServiceCreator(ServiceBuilderResources resources)
{
- return new ServiceBuilderMethodInvoker(_builderMethod, moduleBuilder, resources);
+ return new ServiceBuilderMethodInvoker(_builderMethod, resources);
}
public String getServiceId()
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java?rev=431064&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceLocatorImpl.java Sat Aug 12 11:24:17 2006
@@ -0,0 +1,66 @@
+// Copyright 2006 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.tapestry.internal.ioc;
+
+import org.apache.tapestry.ioc.ServiceLocator;
+
+import static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
+
+/**
+ * Base service locator class used when only the module is known (i.e., when instantiating a module
+ * builder class).
+ *
+ * @author Howard M. Lewis Ship
+ */
+public class ServiceLocatorImpl extends Object implements ServiceLocator
+{
+ private final InternalRegistry _registry;
+
+ private final Module _module;
+
+ public ServiceLocatorImpl(InternalRegistry registry, Module module)
+ {
+ _registry = registry;
+ _module = module;
+ }
+
+ public <T> T getService(String serviceId, Class<T> serviceInterface)
+ {
+ return _registry.getService(
+ toQualifiedId(_module.getModuleId(), serviceId),
+ serviceInterface,
+ _module);
+ }
+
+ public <T> T getService(Class<T> serviceInterface)
+ {
+ return _registry.getService(serviceInterface, _module);
+ }
+
+ public <T> T getObject(String reference, Class<T> objectType)
+ {
+ return _registry.getObject(reference, objectType, this);
+ }
+
+ protected InternalRegistry getRegistry()
+ {
+ return _registry;
+ }
+
+ protected Module getModule()
+ {
+ return _module;
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/ServiceResourcesImpl.java Sat Aug 12 11:24:17 2006
@@ -19,27 +19,21 @@
import java.util.Map;
import org.apache.commons.logging.Log;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
import org.apache.tapestry.ioc.def.ServiceDef;
-import static org.apache.tapestry.ioc.IOCUtilities.toQualifiedId;
-
/**
- * Implementation of {@link org.apache.tapestry.ioc.ServiceCreatorResources}. We just have one
+ * Implementation of {@link org.apache.tapestry.ioc.ServiceBuilderResources}. We just have one
* implementation that fills the purposes of methods that need a
* {@link org.apache.tapestry.ioc.ServiceResources} (which includes service decorator methods) as
- * well as methods that need a {@link org.apache.tapestry.ioc.ServiceCreatorResources} (which is
+ * well as methods that need a {@link org.apache.tapestry.ioc.ServiceBuilderResources} (which is
* just service builder methods). Since it is most commonly used for the former, we'll just leave
* the name as ServiceResourcesImpl.
*
* @author Howard M. Lewis Ship
*/
-public class ServiceResourcesImpl implements ServiceCreatorResources
+public class ServiceResourcesImpl extends ServiceLocatorImpl implements ServiceBuilderResources
{
- private final InternalRegistry _registry;
-
- private final Module _module;
-
private final ServiceDef _serviceDef;
private Log _log;
@@ -47,8 +41,7 @@
public ServiceResourcesImpl(InternalRegistry registry, Module module, ServiceDef serviceDef,
Log log)
{
- _registry = registry;
- _module = module;
+ super(registry, module);
_serviceDef = serviceDef;
_log = log;
}
@@ -63,19 +56,6 @@
return _serviceDef.getServiceInterface();
}
- public <T> T getService(String serviceId, Class<T> serviceInterface)
- {
- return _registry.getService(
- toQualifiedId(_module.getModuleId(), serviceId),
- serviceInterface,
- _module);
- }
-
- public <T> T getService(Class<T> serviceInterface)
- {
- return _registry.getService(serviceInterface, _module);
- }
-
public Log getServiceLog()
{
return _log;
@@ -83,22 +63,22 @@
public <T> Collection<T> getUnorderedConfiguration(Class<T> valueType)
{
- return _registry.getUnorderedConfiguration(_serviceDef, valueType);
+ return getRegistry().getUnorderedConfiguration(_serviceDef, valueType);
}
public <T> List<T> getOrderedConfiguration(Class<T> valueType)
{
- return _registry.getOrderedConfiguration(_serviceDef, valueType);
+ return getRegistry().getOrderedConfiguration(_serviceDef, valueType);
}
public <K, V> Map<K, V> getMappedConfiguration(Class<K> keyType, Class<V> valueType)
{
- return _registry.getMappedConfiguration(_serviceDef, keyType, valueType);
+ return getRegistry().getMappedConfiguration(_serviceDef, keyType, valueType);
}
- public <T> T getObject(String reference, Class<T> objectType)
+ public Object getModuleBuilder()
{
- return _registry.getObject(reference, objectType, this);
+ return getModule().getModuleBuilder();
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/SingletonServiceLifecycle.java Sat Aug 12 11:24:17 2006
@@ -14,20 +14,20 @@
package org.apache.tapestry.internal.ioc;
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
import org.apache.tapestry.ioc.ServiceLifecycle;
import org.apache.tapestry.ioc.ServiceResources;
/**
* The basic implementation of a service lifecycle, which simply uses the
- * {@link org.apache.tapestry.ioc.ServiceCreator} to create an instance of the service when asked.
+ * {@link org.apache.tapestry.ioc.ObjectCreator} to create an instance of the service when asked.
*
* @author Howard M. Lewis Ship
*/
public class SingletonServiceLifecycle implements ServiceLifecycle
{
- public Object createService(ServiceResources resources, ServiceCreator creator)
+ public Object createService(ServiceResources resources, ObjectCreator creator)
{
- return creator.createService();
+ return creator.createObject();
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceCreator.java Sat Aug 12 11:24:17 2006
@@ -17,7 +17,7 @@
*/
package org.apache.tapestry.internal.ioc.services;
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
import org.apache.tapestry.ioc.services.ThreadCleanupHub;
import org.apache.tapestry.ioc.services.ThreadCleanupListener;
@@ -27,13 +27,13 @@
* @author Howard M. Lewis Ship
*/
public class PerThreadServiceCreator extends ThreadLocal implements ThreadCleanupListener,
- ServiceCreator
+ ObjectCreator
{
private final ThreadCleanupHub _threadCleanupHub;
- private final ServiceCreator _delegate;
+ private final ObjectCreator _delegate;
- public PerThreadServiceCreator(ThreadCleanupHub threadCleanupHub, ServiceCreator delegate)
+ public PerThreadServiceCreator(ThreadCleanupHub threadCleanupHub, ObjectCreator delegate)
{
_threadCleanupHub = threadCleanupHub;
_delegate = delegate;
@@ -47,10 +47,10 @@
_threadCleanupHub.addThreadCleanupListener(this);
- return _delegate.createService();
+ return _delegate.createObject();
}
- public Object createService()
+ public Object createObject()
{
// Get (or create) the service.
return get();
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/ioc/services/PerThreadServiceLifecycle.java Sat Aug 12 11:24:17 2006
@@ -18,7 +18,7 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
-import org.apache.tapestry.ioc.ServiceCreator;
+import org.apache.tapestry.ioc.ObjectCreator;
import org.apache.tapestry.ioc.ServiceLifecycle;
import org.apache.tapestry.ioc.ServiceResources;
import org.apache.tapestry.ioc.services.ClassFab;
@@ -30,7 +30,7 @@
/**
* Allows a service to exist "per thread" (in each thread). This involves an inner proxy, with a
- * ThreadLocal whose initial value is derived from a {@link org.apache.tapestry.ioc.ServiceCreator}.
+ * ThreadLocal whose initial value is derived from a {@link org.apache.tapestry.ioc.ObjectCreator}.
* Method invocations are delegated to the per-thread service instance. The proxy also implements
* {@link org.apache.tapestry.ioc.services.ThreadCleanupListener} so that it can discard the
* per-thread implementation.
@@ -55,11 +55,11 @@
_classFactory = classFactory;
}
- public Object createService(ServiceResources resources, final ServiceCreator creator)
+ public Object createService(ServiceResources resources, final ObjectCreator creator)
{
Class proxyClass = createProxyClass(resources);
- ServiceCreator perThreadCreator = new PerThreadServiceCreator(_threadCleanupHub, creator);
+ ObjectCreator perThreadCreator = new PerThreadServiceCreator(_threadCleanupHub, creator);
try
{
@@ -83,14 +83,14 @@
ClassFab cf = _classFactory.newClass(serviceInterface);
- cf.addField("_creator", ServiceCreator.class);
+ cf.addField("_creator", ObjectCreator.class);
// Constructor takes a ServiceCreator
cf.addConstructor(new Class[]
- { ServiceCreator.class }, null, "_creator = $1;");
+ { ObjectCreator.class }, null, "_creator = $1;");
- String body = format("return (%s) _creator.createService();", serviceInterface.getName());
+ String body = format("return (%s) _creator.createObject();", serviceInterface.getName());
MethodSignature sig = new MethodSignature(serviceInterface, PER_THREAD_METHOD_NAME, null,
null);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/ComponentTemplateSourceImpl.java Sat Aug 12 11:24:17 2006
@@ -142,5 +142,4 @@
fireInvalidationEvent();
}
}
-
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/pageload/PageLoaderImpl.java Sat Aug 12 11:24:17 2006
@@ -14,19 +14,24 @@
package org.apache.tapestry.internal.pageload;
-import static org.apache.tapestry.util.CollectionFactory.newList;
-
import java.util.List;
import java.util.Locale;
+import org.apache.tapestry.internal.parser.AttributeToken;
+import org.apache.tapestry.internal.parser.ComponentTemplate;
+import org.apache.tapestry.internal.parser.StartComponentToken;
+import org.apache.tapestry.internal.parser.TemplateToken;
import org.apache.tapestry.internal.structure.ComponentPageElement;
import org.apache.tapestry.internal.structure.ComponentPageElementImpl;
+import org.apache.tapestry.internal.structure.MarkupPageElement;
import org.apache.tapestry.internal.structure.Page;
import org.apache.tapestry.internal.structure.PageElement;
import org.apache.tapestry.internal.structure.PageImpl;
import org.apache.tapestry.internal.transform.ComponentInstantiatorSource;
import org.apache.tapestry.internal.transform.Instantiator;
+import static org.apache.tapestry.util.CollectionFactory.newList;
+
/**
* This implementation is not threadsafe.
*
@@ -34,12 +39,21 @@
*/
public class PageLoaderImpl implements PageLoader
{
- private ComponentInstantiatorSource _componentInstantiatorSource;
+ private final ComponentInstantiatorSource _componentInstantiatorSource;
+
+ private final ComponentTemplateSource _templateSource;
private Page _page;
private Locale _locale;
+ public PageLoaderImpl(ComponentInstantiatorSource componentInstantiatorSource,
+ ComponentTemplateSource templateSource)
+ {
+ _componentInstantiatorSource = componentInstantiatorSource;
+ _templateSource = templateSource;
+ }
+
/**
* Stack of elements within the current template, used to determine on which object to invoke
* {@link ComponentPageElement#addToBody(PageElement)}. Each new element (component or
@@ -87,29 +101,179 @@
/** Works the component queue, until exausted. */
private void workComponentQueue()
{
+ while (!_componentQueue.isEmpty())
+ {
+ ComponentPageElement componentElement = pop(_componentQueue);
+ loadTemplateForComponent(componentElement);
+ }
}
- /** For injection. */
- public void setComponentInstantiatorSource(ComponentInstantiatorSource source)
+ private void loadTemplateForComponent(ComponentPageElement loadingComponent)
{
- _componentInstantiatorSource = source;
+ // Have to do something here, like consult the ComponentModelSource and get a
+ // ComponentModel to guide the process. Lots of moving parts.
+
+ ComponentTemplate template = _templateSource.getTemplate("", _locale);
+
+ // Here's the thing. Stuff in this template is part of element's template unless
+ // it is inside another component, in which case, it is part of the component's
+ // body. template is stuff from the component's own template (if any). body
+ // is stuff from its container's template.
+
+ PageElement activePageElement = loadingComponent;
+ ComponentPageElement activeComponent = loadingComponent;
+ List<PageElement> activePageElementStack = newList();
+ List<ComponentPageElement> activeComponentStack = newList();
+
+ boolean directlyInsideSubcomponent = false;
+
+ for (TemplateToken token : template.getTokens())
+ {
+ switch (token.getTokenType())
+ {
+ case CDATA:
+ case TEXT:
+
+ add(loadingComponent, activeComponent, new MarkupPageElement(token));
+ break;
+
+ case START_ELEMENT:
+
+ // We push onto *both* stacks when starting an element or when
+ // starting a component, because we can't differentitate cases
+ // when we hit the end element token.
+
+ PageElement newElement = new MarkupPageElement(token);
+
+ add(loadingComponent, activeComponent, newElement);
+
+ push(activePageElementStack, activePageElement);
+ push(activeComponentStack, activeComponent);
+
+ activePageElement = newElement;
+
+ // Any additional attribute tokens should be directed to
+ // the activePageElement, and not be directed to
+ // the the activeComponent.
+
+ directlyInsideSubcomponent = false;
+
+ break;
+
+ case END_ELEMENT:
+
+ add(loadingComponent, activeComponent, new MarkupPageElement(token));
+
+ activePageElement = pop(activePageElementStack);
+ activeComponent = pop(activeComponentStack);
+
+ break;
+
+ case START_COMPONENT:
+
+ StartComponentToken start = (StartComponentToken) token;
+
+ // For the moment, we're assuming each component will have an id and a FQCN for
+ // the type. This will change pretty soon.
+
+ String id = start.getId();
+
+ // Determining the component name is really not this easy. We may only specify
+ // the id in the template, and rely on the component model to provide us with
+ // the type. And the type in the template may be a local abbreviation that must
+ // be properly expanded to a FQCN before being passed to the
+ // component instantiator source.
+
+ String componentName = start.getType();
+
+ Instantiator instantiator = _componentInstantiatorSource
+ .findInstantiator(componentName);
+
+ // The container for any components is the loading component, regardless of
+ // how the component elements are nested within the loading component's
+ // template.
+
+ ComponentPageElement newComponent = new ComponentPageElementImpl(_page,
+ loadingComponent, id, instantiator);
+
+ // Make sure container knows about the new component.
+
+ loadingComponent.addChild(newComponent);
+
+ // Remember that we have to load this new component and any of its
+ // subcomponents, later.
+
+ push(_componentQueue, newComponent);
+
+ push(activePageElementStack, activePageElement);
+ push(activeComponentStack, activeComponent);
+
+ activePageElement = newComponent;
+ activeComponent = newComponent;
+
+ // If we see any attribute tokens immediately following the start
+ // of a component, they are parameters of the component.
+ // Remember that attribute token can only directly follow
+ // start component or start element tokens -- due to the structure of
+ // XML and SAX, they just can't show up elsewhere.
+
+ directlyInsideSubcomponent = true;
+
+ break;
+
+ case ATTRIBUTE:
+
+ if (directlyInsideSubcomponent)
+ {
+ AttributeToken attribute = (AttributeToken) token;
+ activeComponent.addParameter(attribute);
+ }
+ else
+ {
+ add(loadingComponent, activeComponent, new MarkupPageElement(token));
+ }
+
+ default:
+ throw new IllegalStateException("Just haven't written that stuff yet.");
+ }
+
+ }
+
}
+ private void add(ComponentPageElement loadingComponent, ComponentPageElement activeComponent,
+ PageElement child)
+ {
+ if (loadingComponent == activeComponent)
+ activeComponent.addToTemplate(child);
+ else
+ activeComponent.addToBody(child);
+ }
+
+ /** Peeks at the top element on the stack without changing the stack. */
static <T> T peek(List<T> stack)
{
int size = stack.size();
+ if (size == 0)
+ throw new IllegalStateException("Stack is empty.");
+
return stack.get(size - 1);
}
- static <T> void pop(List<T> stack)
+ /** Pops the top element off the stack and returns it. */
+ static <T> T pop(List<T> stack)
{
int size = stack.size();
- stack.remove(size - 1);
+ if (size == 0)
+ throw new IllegalStateException("Stack is empty.");
+
+ return stack.remove(size - 1);
}
+ /** Pushes a new element onto the top of the stack. */
static <T> void push(List<T> stack, T element)
{
stack.add(element);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElement.java Sat Aug 12 11:24:17 2006
@@ -15,6 +15,7 @@
package org.apache.tapestry.internal.structure;
import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.parser.AttributeToken;
/**
* Extended version of {@link org.apache.tapestry.internal.structure.PageElement} for elements that
@@ -40,8 +41,19 @@
void addToTemplate(PageElement element);
/**
- *
+ * Used during the construction of the page. Adds a page element as part of the body of the
+ * component. The body of a component is defined as the portion of the container's template
+ * directly enclosed by component's start and end elements.
*/
void addToBody(PageElement element);
+ /**
+ * Used during construction of the page to identify a parameter of the component that is bound
+ * via a template attribute. An error is logged if there is a conflict, or if the attribute
+ * doesn't correspond to a parameter of the component.
+ */
+ void addParameter(AttributeToken attribute);
+
+ /** Adds a child component to its container. The child's id must be unique within the container. */
+ void addChild(ComponentPageElement child);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/structure/ComponentPageElementImpl.java Sat Aug 12 11:24:17 2006
@@ -15,10 +15,14 @@
package org.apache.tapestry.internal.structure;
import java.util.List;
+import java.util.Map;
+import org.apache.tapestry.internal.parser.AttributeToken;
import org.apache.tapestry.internal.transform.Instantiator;
import org.apache.tapestry.runtime.ComponentLifecycle;
-import org.apache.tapestry.util.CollectionFactory;
+
+import static org.apache.tapestry.util.CollectionFactory.newList;
+import static org.apache.tapestry.util.CollectionFactory.newMap;
/**
* Implements {@link org.apache.tapestry.internal.structure.PageElement} and
@@ -32,20 +36,31 @@
{
private final Page _page;
+ private final String _id;
+
private List<PageElement> _template;
private List<PageElement> _body;
private final ComponentPageElement _container;
+ // The user-provided class, with runtime code enhancements.
private final ComponentLifecycle _component;
+ private Map<String, ComponentPageElement> _children;
+
+ // This is likely to change shortly to something more involved; we need to introduce the concept
+ // of parameters as well as a component model for the component.
+
+ private final Map<String, AttributeToken> _parameters = newMap();
+
/** Constructor for the root component of a page. */
public ComponentPageElementImpl(Page page, Instantiator instantiator)
{
_page = page;
_container = null;
_component = instantiator.newInstance(this);
+ _id = null;
}
/**
@@ -53,11 +68,12 @@
* the hierarchy.
*/
- public ComponentPageElementImpl(Page page, ComponentPageElement container,
+ public ComponentPageElementImpl(Page page, ComponentPageElement container, String id,
Instantiator instantiator)
{
_page = page;
_container = container;
+ _id = id;
_component = instantiator.newInstance(this);
}
@@ -69,7 +85,7 @@
public void addToBody(PageElement element)
{
if (_body == null)
- _body = CollectionFactory.newList();
+ _body = newList();
_body.add(element);
}
@@ -77,9 +93,33 @@
public void addToTemplate(PageElement element)
{
if (_template == null)
- _template = CollectionFactory.newList();
+ _template = newList();
_template.add(element);
+ }
+
+ public void addParameter(AttributeToken attribute)
+ {
+ // TODO: Check for conflicts, etc.
+
+ _parameters.put(attribute.getName(), attribute);
+ }
+
+ public void addChild(ComponentPageElement child)
+ {
+ if (_children == null)
+ _children = newMap();
+
+ String childId = child.getId();
+
+ // TODO: Check for conflicts!
+
+ _children.put(childId, child);
+ }
+
+ public String getId()
+ {
+ return _id;
}
}
Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java (from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java&r1=428940&r2=431064&rev=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreator.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ObjectCreator.java Sat Aug 12 11:24:17 2006
@@ -15,14 +15,13 @@
package org.apache.tapestry.ioc;
/**
- * Interface used to encapsulate any strategy used to obtain a service implementation (the real
- * service implementation, not a proxy) on demand.
+ * Interface used to encapsulate any strategy used defer the creation of some object until just as
+ * needed.
*
* @author Howard M. Lewis Ship
- * @see org.apache.tapestry.internal.ioc.SingletonServiceLifecycle
*/
-public interface ServiceCreator
+public interface ObjectCreator
{
- /** Create and return the service implementation. */
- Object createService();
+ /** Create and return the object. */
+ Object createObject();
}
Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java (from r428940, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java?p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java&r1=428940&r2=431064&rev=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceCreatorResources.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceBuilderResources.java Sat Aug 12 11:24:17 2006
@@ -24,8 +24,13 @@
*
* @author Howard M. Lewis Ship
*/
-public interface ServiceCreatorResources extends ServiceResources
+public interface ServiceBuilderResources extends ServiceResources
{
+ /**
+ * Returns the module builder instance for the module containing the service to be created.
+ */
+ Object getModuleBuilder();
+
<T> Collection<T> getUnorderedConfiguration(Class<T> valueType);
<T> List<T> getOrderedConfiguration(Class<T> valueType);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/ServiceLifecycle.java Sat Aug 12 11:24:17 2006
@@ -34,5 +34,5 @@
* around the service's builder method.
* @return the service or equivalent service proxy
*/
- Object createService(ServiceResources resources, ServiceCreator creator);
+ Object createService(ServiceResources resources, ObjectCreator creator);
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java Sat Aug 12 11:24:17 2006
@@ -14,8 +14,8 @@
package org.apache.tapestry.ioc.def;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
/**
* Service definition derived, by default, from a service builder method.
@@ -25,15 +25,13 @@
public interface ServiceDef
{
/**
- * Returns a {@link ServiceCreator} that can create the core service implementation.
- *
- * @param moduleBuilder
- * the module builder instance for the module containing the service
+ * Returns an {@link ObjectCreator} that can create the core service implementation.
* @param resources
* used to resolve dependencies of the service, or access its configuration
+ *
* @return an object that can (later) be used to instantiate the service itself
*/
- ServiceCreator createServiceCreator(Object moduleBuilder, ServiceCreatorResources resources);
+ ObjectCreator createServiceCreator(ServiceBuilderResources resources);
/** Returns the fully qualified service id, derived from the method name. */
String getServiceId();
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Sat Aug 12 11:24:17 2006
@@ -39,14 +39,21 @@
@Id("tapestry.ioc")
public final class TapestryIOCModule
{
+ private final ClassFactory _classFactory;
+
+ public TapestryIOCModule(@InjectService("ClassFactory")
+ ClassFactory classFactory)
+ {
+ _classFactory = classFactory;
+ }
+
/**
* The LoggingDecorator service is used to decorate a service implementation so that it logs
* method entry and exit (at level debug).
*/
- public LoggingDecorator buildLoggingDecorator(@InjectService("ClassFactory")
- ClassFactory classFactory)
+ public LoggingDecorator buildLoggingDecorator()
{
- return new LoggingDecoratorImpl(classFactory);
+ return new LoggingDecoratorImpl(_classFactory);
}
/**
@@ -70,22 +77,19 @@
public void contributeServiceLifecycleSource(
MappedConfiguration<String, ServiceLifecycle> configuration,
@InjectService("ThreadCleanupHub")
- ThreadCleanupHub threadCleanupHub, @InjectService("ClassFactory")
- ClassFactory classFactory)
+ ThreadCleanupHub threadCleanupHub)
{
- configuration.add(
- "perthread",
- new PerThreadServiceLifecycle(threadCleanupHub, classFactory));
+ configuration.add("perthread", new PerThreadServiceLifecycle(threadCleanupHub,
+ _classFactory));
}
/**
* A service that implements the chain of command pattern, creating an efficient implementation
* of a chain of command for an arbitrary interface.
*/
- public ChainBuilder buildChainBuilder(@InjectService("ClassFactory")
- ClassFactory classFactory)
+ public ChainBuilder buildChainBuilder()
{
- return new ChainBuilderImpl(classFactory);
+ return new ChainBuilderImpl(_classFactory);
}
/**
@@ -100,31 +104,27 @@
/**
* Builder that creates a shadow, a projection of a property of some other object.
*/
- public PropertyShadowBuilder buildPropertyShadowBuilder(@InjectService("ClassFactory")
- ClassFactory classFactory, @InjectService("PropertyAccess")
+ public PropertyShadowBuilder buildPropertyShadowBuilder(@InjectService("PropertyAccess")
PropertyAccess propertyAccess)
{
- return new PropertyShadowBuilderImpl(classFactory, propertyAccess);
+ return new PropertyShadowBuilderImpl(_classFactory, propertyAccess);
}
/**
* Builder that creates a filter pipeline around a simple service interface.
*/
- public PipelineBuilder buildPipelineBuilder(@InjectService("ClassFactory")
- ClassFactory classFactory, @InjectService("DefaultImplementationBuilder")
+ public PipelineBuilder buildPipelineBuilder(@InjectService("DefaultImplementationBuilder")
DefaultImplementationBuilder builder)
{
- return new PipelineBuilderImpl(classFactory, builder);
+ return new PipelineBuilderImpl(_classFactory, builder);
}
/**
* Builder that creates a default implementation of an interface.
*/
- public DefaultImplementationBuilder buildDefaultImplementationBuilder(
- @InjectService("ClassFactory")
- ClassFactory classFactory)
+ public DefaultImplementationBuilder buildDefaultImplementationBuilder()
{
- return new DefaultImplementationBuilderImpl(classFactory);
+ return new DefaultImplementationBuilderImpl(_classFactory);
}
/**
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java?rev=431064&view=auto
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ComponentNameExpander.java Sat Aug 12 11:24:17 2006
@@ -0,0 +1,27 @@
+// Copyright 2006 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.tapestry.services;
+
+/**
+ * Invoked by the page loader to convert a component name into a fully qualified component class
+ * name.
+ *
+ * @author Howard M. Lewis Ship
+ */
+public interface ComponentNameExpander
+{
+ /** Expands the component name into a fully qualified class name. */
+ String expandComponentName(String componentName);
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Sat Aug 12 11:24:17 2006
@@ -20,6 +20,7 @@
import org.apache.tapestry.internal.InternalModule;
import org.apache.tapestry.internal.services.InfrastructureImpl;
import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
+import org.apache.tapestry.ioc.Configuration;
import org.apache.tapestry.ioc.MappedConfiguration;
import org.apache.tapestry.ioc.ObjectProvider;
import org.apache.tapestry.ioc.annotations.Contribute;
@@ -57,5 +58,30 @@
Infrastructure infrastructure)
{
configuration.add("service", infrastructure.getObjectProvider());
+ }
+
+ public void contributeInfrastructure(Configuration<InfrastructureContribution> configuration,
+ @InjectService("ComponentNameExpander")
+ ComponentNameExpander componentNameExpander)
+ {
+ configuration.add(new InfrastructureContribution("componentNameExpander",
+ componentNameExpander));
+ }
+
+ /**
+ * Builds a provisional implementation that assumes the input name already is a fully qualified
+ * class name.
+ */
+ public ComponentNameExpander buildComponentNameExpander()
+ {
+ return new ComponentNameExpander()
+ {
+
+ public String expandComponentName(String componentName)
+ {
+ return componentName;
+ }
+
+ };
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/BaseTestCase.java Sat Aug 12 11:24:17 2006
@@ -34,8 +34,8 @@
import org.apache.tapestry.ioc.LogSource;
import org.apache.tapestry.ioc.MappedConfiguration;
import org.apache.tapestry.ioc.OrderedConfiguration;
-import org.apache.tapestry.ioc.ServiceCreator;
-import org.apache.tapestry.ioc.ServiceCreatorResources;
+import org.apache.tapestry.ioc.ObjectCreator;
+import org.apache.tapestry.ioc.ServiceBuilderResources;
import org.apache.tapestry.ioc.ServiceDecorator;
import org.apache.tapestry.ioc.ServiceLocator;
import org.apache.tapestry.ioc.ServiceResources;
@@ -202,15 +202,15 @@
setReturnValue(service);
}
- protected final void trainCreateService(ServiceCreator creator, Object service)
+ protected final void trainCreateService(ObjectCreator creator, Object service)
{
- creator.createService();
+ creator.createObject();
setReturnValue(service);
}
- protected final ServiceCreator newServiceCreator()
+ protected final ObjectCreator newServiceCreator()
{
- return newMock(ServiceCreator.class);
+ return newMock(ObjectCreator.class);
}
protected final void trainGetServiceInterface(ServiceResources resources, Class serviceInterface)
@@ -289,9 +289,9 @@
return newMock(ContributionDef.class);
}
- protected final ServiceCreatorResources newServiceCreatorResources()
+ protected final ServiceBuilderResources newServiceCreatorResources()
{
- return newMock(ServiceCreatorResources.class);
+ return newMock(ServiceBuilderResources.class);
}
protected final Module newModule()
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/ioc/IOCStrings.properties Sat Aug 12 11:24:17 2006
@@ -66,4 +66,10 @@
existing contribution (by %s) and has been ignored.
generic-type-not-supported=Generic type '%s' is not supported. Only simple parameterized lists are \
supported.
-error-building-service=Error building service proxy for service '%s' (at %s): %s
\ No newline at end of file
+error-building-service=Error building service proxy for service '%s' (at %s): %s
+no-public-constructors=Module builder for module '%s' (class %s) does not contain any public constructors.
+too-many-public-constructors=Module bulider for module '%s' (class %s) contains more than one public constructor. \
+ The first constructor, %s, is being used. \
+ You should change the class to have only a single public constructor.
+recursive-module-constructor=The constructor for module '%s' (class %s) is recursive: it depends on itself in some way. \
+ The constructor, %s, is in some way is triggering a service builder, decorator or contribution method within the class.
\ No newline at end of file
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/module.apt Sat Aug 12 11:24:17 2006
@@ -69,6 +69,68 @@
errors will occur.
+{Caching Services}
+
+ You will often find yourself in the position of injecting the same services
+ into your service builder or service decorator methods repeatedly. This can be quite
+ a bit of redundant typing. Less code is better code, so as an alternative, you may define a <constructor> for your
+ module that accepts annotated parameters (as with
+ {{{service.html#Injecting Dependencies}service builder injection}}).
+
+ This gives you a chance to store common services in instance variables for later use inside
+ service builder methods.
+
++-----------------------------------------------------------------------------------+
+
+public class MyModule
+{
+ private final JobScheduler _scheduler;
+ private final FileSystem _fileSystem;
+
+ public MyModule(
+ @Inject("service:JobScheduler")
+ JobScheduler scheduler,
+ @Inject("service:FileSystem")
+ FileSystem fileSystem)
+ {
+ _scheduler = scheduler;
+ _fileSystem = fileSystem;
+ }
+
+ public Indexer buildIndexer()
+ {
+ IndexerImpl indexer = new IndexerImpl(_fileSystem);
+
+ _scheduler.scheduleDailyJob(indexer);
+
+ return indexer;
+ }
+}
++-----------------------------------------------------------------------------------+
+
+ In addition to injecting dependencies with the @InjectService and @Inject annotations,
+ you may also inject a number of <module> resources:
+
+ * java.lang.String: the module id
+
+ * org.apache.commons.logging.Log: log for the module
+
+ * {{{../apidocs/org/apache/tapestry/ioc/ServiceLocator.html}ServiceLocator}}: access to other services
+
+ []
+
+ Care should be taken with this approach: in some circustances, you may force a situtation in which
+ the module constructor is dependent on itself. For example, if you invoke a method on any injected services
+ defined within the same module from the module builder's constructor,
+ then the service implementation will be needed. Creating service implementations
+ requires the module builder instance ... that's a recursive reference.
+
+ Another common example would be using @Inject("infrastructure:<property>") when the module being constructed
+ contributes into the tapestry.Infrastructure service's configuration. Here, to resolve the contribution, Tapestry
+ needs an instance of the module builder class even as it is trying to invoke the module builder's constructor.
+
+ Tapestry detects these scenarios and throws a runtime exception to prevent an endless loop.
+
Autoloading modules
When setting up the registry, Tapestry can automatically locate modules packaged into JARs.
@@ -85,7 +147,7 @@
Tapestry-Module-Classes: org.example.mylib.LibModule, org.example.mylib.internal.InternalModule
+-----------------------------------------------------------------------------------+
- If you are using Maven 2, then getting these entries into your JAR's manifest
+ If you are using Maven 2, then getting these entries into your JAR's manifest
is as simple as some configuration in your pom.xml:
+-----------------------------------------------------------------------------------+
@@ -140,17 +202,13 @@
. . .
+----+
+ In general, your should only need to identify a single module in the JAR manifest, and make use of
+ @SubModule to pull in any additional module builder classes.
+
Module Builder Implementation Notes
Module builder classes are designed to be very, very simple to implement.
-
- They must have a no-arguments public constructor.
-
- You should <<not>> attempt to cache services. There is really no way to
- determine in what order methods of the builder class will be invoked. Because
- services are generally instantiated only as needed, methods will be
- invoked in an arbitrary order, and some may never be invoked.
-
+
Again, keep the methods very simple. Use {{{service.html#Injecting Dependencies}parameter injection}}
to gain access to the dependencies you need.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt?rev=431064&r1=431063&r2=431064&view=diff
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/ioc/provider.apt Sat Aug 12 11:24:17 2006
@@ -26,6 +26,42 @@
As outlined above, the service provider interprets the expression as
a service id, either fully qualified or local.
+* infrastructure provider
+
+ The infrastructure provider is a key element in making Tapestry extensible; it adds a layer of
+ indirection between service implementations and their collaborators. Using the infrastructure
+ provider allows applications to identify and override individual services within Tapestry's
+ network of services.
+
+ The <expression> for the infrastructure provider is the name of a property. This property is
+ mapped to a particular service via a <pair> of services. The
+ {{{../apidocs/org/apache/tapestry/services/Infrastructure.html}tapestry.Infrastructure}} service
+ has a mapped configuration of
+ {{{../apidocs/org/apache/tapestry/services/InfrastructureContribution.html}InfrastructureContribution}}s.
+ Each contribution is keyed on the property it provides.
+
+ A second service (<<Caution:>> not yet implemented), tapestry.InfrastructureOverride, exists
+ to support a second, identical configuration. Any properties contributed here override the normal
+ Infrastructure properties.
+
+ In order to override an individual Tapestry service, all that is necessary is to provide
+ a new implementation as a new service, and contribute that service into the configuration for
+ the tapestry.InfrastructureOverride configuration.
+
+ In many cases, the original service can be injected into the new implementation; this must be done
+ using the original service's fully qualified service id.
+
+ The following table identifies the properties that are available via the infrastructure provider
+ by default:
+
+*---------------------+-----------------------------------------------------------------------------------------+
+| <<Property>> | <<Default Service or Implementation>> |
+*---------------------+-----------------------------------------------------------------------------------------+
+| xyz | {{{../apidocs/org/apache/tapestry/ioc/services/ClassFactory.html}ClassFactory}} |
+*---------------------+-----------------------------------------------------------------------------------------+
+Default properties available via the infrastructure object provider
+
+
Defining New Providers
New providers can be specified by contributing to the