Return-Path: Delivered-To: apmail-tapestry-commits-archive@locus.apache.org Received: (qmail 72236 invoked from network); 11 Nov 2007 09:28:36 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 11 Nov 2007 09:28:36 -0000 Received: (qmail 37340 invoked by uid 500); 11 Nov 2007 09:28:23 -0000 Delivered-To: apmail-tapestry-commits-archive@tapestry.apache.org Received: (qmail 37317 invoked by uid 500); 11 Nov 2007 09:28:23 -0000 Mailing-List: contact commits-help@tapestry.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@tapestry.apache.org Delivered-To: mailing list commits@tapestry.apache.org Received: (qmail 37308 invoked by uid 99); 11 Nov 2007 09:28:23 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 Nov 2007 01:28:23 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 Nov 2007 09:28:29 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 96DC81A9832; Sun, 11 Nov 2007 01:28:06 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r593862 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/src/main/java/org/apache/tapestry/internal/test/ tapestry-core/src/main/java/org/apache/tapestry/services/ tapestry-ioc... Date: Sun, 11 Nov 2007 09:28:04 -0000 To: commits@tapestry.apache.org From: hlship@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20071111092806.96DC81A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: hlship Date: Sun Nov 11 01:28:03 2007 New Revision: 593862 URL: http://svn.apache.org/viewvc?rev=593862&view=rev Log: TAPESTRY-1900: Allow multiple markers annotations per service Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Core.java Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetObjectProvider.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/TestBase.java tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/cookbook/patterns.apt tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/overview.apt tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImplTest.java tapestry/tapestry5/trunk/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetObjectProvider.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetObjectProvider.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetObjectProvider.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/AssetObjectProvider.java Sun Nov 11 01:28:03 2007 @@ -24,6 +24,7 @@ import org.apache.tapestry.ioc.services.SymbolSource; import org.apache.tapestry.ioc.services.TypeCoercer; import org.apache.tapestry.services.AssetSource; +import org.apache.tapestry.services.Core; /** * Exposes assets (in the current locale). The Inject annotation must be supplemented by a @@ -37,7 +38,7 @@ private final SymbolSource _symbolSource; - public AssetObjectProvider(@Builtin + public AssetObjectProvider(@Core AssetSource source, @Builtin Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/test/TestableMarkupWriterFactoryImpl.java Sun Nov 11 01:28:03 2007 @@ -18,7 +18,7 @@ import org.apache.tapestry.MarkupWriter; import org.apache.tapestry.ioc.annotations.Scope; -import org.apache.tapestry.ioc.services.Builtin; +import org.apache.tapestry.services.Core; import org.apache.tapestry.services.MarkupWriterFactory; @Scope(PERTHREAD_SCOPE) @@ -32,7 +32,7 @@ * Using Builtin to reference to framework-provided version, which this implementation wraps * around. */ - public TestableMarkupWriterFactoryImpl(@Builtin + public TestableMarkupWriterFactoryImpl(@Core MarkupWriterFactory delegate) { _delegate = delegate; Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Core.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Core.java?rev=593862&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Core.java (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/Core.java Sun Nov 11 01:28:03 2007 @@ -0,0 +1,35 @@ +// Copyright 2007 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; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * Marker for services that are provided by the Tapestry core module. + */ +@Target( +{ PARAMETER, FIELD }) +@Retention(RUNTIME) +@Documented +public @interface Core +{ + +} Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Sun Nov 11 01:28:03 2007 @@ -132,7 +132,7 @@ /** * The root module for Tapestry. */ -@Marker(Builtin.class) +@Marker(Core.class) public final class TapestryModule { public static void bind(ServiceBinder binder) @@ -1580,9 +1580,9 @@ public static void contributeTemplateParser(MappedConfiguration config) { - // Any class inside the internal module would do. Or we could move all these + // Any class inside the internal module would do. Or we could move all these // files to o.a.t.services. - + Class c = UpdateListenerHub.class; config.add("-//W3C//DTD XHTML 1.0 Strict//EN", c.getResource("xhtml1-strict.dtd")); config.add("-//W3C//DTD XHTML 1.0 Transitional//EN", c Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/ServiceBindingOptions.java Sun Nov 11 01:28:03 2007 @@ -56,15 +56,16 @@ ServiceBindingOptions eagerLoad(); /** - * Defines the marker interface for the service, used to connect injections by type at the point - * of injection with a particular service implementation, based on the intersection of type and - * marker interface. The containing module will sometimes provide a default marker interface for - * all services within the module, this method allows that default to be overridden (typically a - * different marker annotation, but sometimes to null). + * Defines the marker interface(s) for the service, used to connect injections by type at the + * point of injection with a particular service implementation, based on the intersection of + * type and marker interface. The containing module will sometimes provide a set of default + * marker annotations for all services within the module, this method allows that default to be + * extended. * * @param * @param marker + * one or more markers to add * @return this binding options, for further configuration */ - ServiceBindingOptions withMarker(Class marker); + ServiceBindingOptions withMarker(Class... marker); } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Marker.java Sun Nov 11 01:28:03 2007 @@ -25,7 +25,7 @@ import org.apache.tapestry.ioc.def.ServiceDef; /** - * Used to define a {@linkplain ServiceDef#getMarker() marker annotation} for a service + * Used to define a {@linkplain ServiceDef#getMarkers() marker annotation} for a service * implementation. This allows for injection based on the combination of type and marker interface. * These marker interfaces should not have any values. The mere presence of the marker annotation is * all that is needed. Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/def/ServiceDef.java Sun Nov 11 01:28:03 2007 @@ -14,6 +14,7 @@ package org.apache.tapestry.ioc.def; +import java.util.Set; import org.apache.tapestry.ioc.ObjectCreator; import org.apache.tapestry.ioc.ServiceBuilderResources; @@ -48,7 +49,7 @@ * * @return the annotation, or null if the service has no annotation */ - Class getMarker(); + Set getMarkers(); /** * Returns the service interface associated with this service. This is the interface exposed to Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImpl.java Sun Nov 11 01:28:03 2007 @@ -28,6 +28,8 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.Map; import java.util.Set; @@ -48,6 +50,7 @@ import org.apache.tapestry.ioc.def.DecoratorDef; import org.apache.tapestry.ioc.def.ModuleDef; import org.apache.tapestry.ioc.def.ServiceDef; +import org.apache.tapestry.ioc.internal.util.CollectionFactory; import org.apache.tapestry.ioc.internal.util.InternalUtils; import org.apache.tapestry.ioc.services.ClassFactory; import org.slf4j.Logger; @@ -84,7 +87,7 @@ private final static Map PARAMETER_TYPE_TO_CONFIGURATION_TYPE = newMap(); - private final Class _defaultMarker; + private final Set _defaultMarkers = newSet(); static { @@ -108,7 +111,7 @@ Marker annotation = builderClass.getAnnotation(Marker.class); - _defaultMarker = annotation != null ? annotation.value() : null; + if (annotation != null) _defaultMarkers.addAll(Arrays.asList(annotation.value())); grind(); bind(); @@ -319,22 +322,22 @@ } }; - Class marker = extractMarker(method); + Set markers = newSet(_defaultMarkers); + markers.addAll(extractMarkers(method)); - ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, serviceId, marker, scope, + ServiceDefImpl serviceDef = new ServiceDefImpl(returnType, serviceId, markers, scope, eagerLoad, source); addServiceDef(serviceDef); } - private Class extractMarker(Method method) + private Collection extractMarkers(Method method) { Marker annotation = method.getAnnotation(Marker.class); - // Use the annotation value if present, otherwise use the module's default - // (from the module class's annotation, or null if no annotation there). + if (annotation == null) return Collections.emptyList(); - return annotation == null ? _defaultMarker : annotation.value(); + return CollectionFactory.newList(annotation.value()); } public void addServiceDef(ServiceDef serviceDef) @@ -393,7 +396,7 @@ return; } - ServiceBinderImpl binder = new ServiceBinderImpl(this, _classFactory, _defaultMarker); + ServiceBinderImpl binder = new ServiceBinderImpl(this, _classFactory, _defaultMarkers); bindMethod.invoke(null, binder); Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/RegistryImpl.java Sun Nov 11 01:28:03 2007 @@ -47,6 +47,7 @@ import org.apache.tapestry.ioc.def.ServiceDef; import org.apache.tapestry.ioc.internal.services.RegistryShutdownHubImpl; import org.apache.tapestry.ioc.internal.services.ThreadCleanupHubImpl; +import org.apache.tapestry.ioc.internal.util.CollectionFactory; import org.apache.tapestry.ioc.internal.util.InternalUtils; import org.apache.tapestry.ioc.internal.util.OneShotLock; import org.apache.tapestry.ioc.internal.util.Orderer; @@ -75,6 +76,14 @@ private static final String SERVICE_ACTIVITY_SCOREBOARD_SERVICE_ID = "ServiceActivityScoreboard"; + /** The set of marker annotations for a builtin service. */ + private final static Set BUILTIN = CollectionFactory.newSet(); + + static + { + BUILTIN.add(Builtin.class); + } + /** * Used to obtain the {@link org.apache.tapestry.ioc.services.ClassFactory} service, which is * crucial when creating runtime classes for proxies and the like. @@ -209,9 +218,7 @@ // The service is defined but will not have gone further than that. _tracker.define(serviceDef, Status.DEFINED); - Class marker = serviceDef.getMarker(); - - if (marker != null) + for (Class marker : serviceDef.getMarkers()) InternalUtils.addToMapList(_markerToServiceDef, marker, serviceDef); } @@ -267,9 +274,9 @@ return null; } - public Class getMarker() + public Set getMarkers() { - return Builtin.class; + return BUILTIN; } public String getServiceId() @@ -293,7 +300,8 @@ } }; - InternalUtils.addToMapList(_markerToServiceDef, serviceDef.getMarker(), serviceDef); + for (Class marker : serviceDef.getMarkers()) + InternalUtils.addToMapList(_markerToServiceDef, marker, serviceDef); _tracker.define(serviceDef, Status.BUILTIN); } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceBinderImpl.java Sun Nov 11 01:28:03 2007 @@ -19,6 +19,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.util.Arrays; +import java.util.Set; import org.apache.tapestry.ioc.IOCConstants; import org.apache.tapestry.ioc.ObjectCreator; @@ -29,6 +31,7 @@ import org.apache.tapestry.ioc.annotations.Marker; import org.apache.tapestry.ioc.annotations.Scope; import org.apache.tapestry.ioc.def.ServiceDef; +import org.apache.tapestry.ioc.internal.util.CollectionFactory; import org.apache.tapestry.ioc.internal.util.InternalUtils; import org.apache.tapestry.ioc.internal.util.OneShotLock; import org.apache.tapestry.ioc.services.ClassFactory; @@ -41,21 +44,21 @@ private final ClassFactory _classFactory; - private final Class _defaultMarker; + private final Set _defaultMarkers; public ServiceBinderImpl(ServiceDefAccumulator accumulator, ClassFactory classFactory, - Class defaultMarker) + Set defaultMarkers) { _accumulator = accumulator; _classFactory = classFactory; - _defaultMarker = defaultMarker; + _defaultMarkers = defaultMarkers; } private String _serviceId; private Class _serviceInterface; - private Class _marker; + private final Set _markers = CollectionFactory.newSet(); private Class _serviceImplementation; @@ -89,14 +92,18 @@ } }; - ServiceDef serviceDef = new ServiceDefImpl(_serviceInterface, _serviceId, _marker, _scope, + // Combine service-specific markers with those inherited form the module. + Set markers = CollectionFactory.newSet(_defaultMarkers); + markers.addAll(_markers); + + ServiceDef serviceDef = new ServiceDefImpl(_serviceInterface, _serviceId, markers, _scope, _eagerLoad, source); _accumulator.addServiceDef(serviceDef); _serviceId = null; _serviceInterface = null; - _marker = _defaultMarker; + _markers.clear(); _serviceImplementation = null; _eagerLoad = false; _scope = null; @@ -142,7 +149,7 @@ Marker marker = serviceImplementation.getAnnotation(Marker.class); - _marker = marker != null ? marker.value() : _defaultMarker; + if (marker != null) _markers.addAll(Arrays.asList(marker.value())); return this; } @@ -178,11 +185,11 @@ return this; } - public ServiceBindingOptions withMarker(Class marker) + public ServiceBindingOptions withMarker(Class... marker) { _lock.check(); - _marker = marker; + _markers.addAll(Arrays.asList(marker)); return this; } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/ServiceDefImpl.java Sun Nov 11 01:28:03 2007 @@ -14,7 +14,9 @@ package org.apache.tapestry.ioc.internal; +import java.util.Set; +import org.apache.tapestry.ioc.IOCConstants; import org.apache.tapestry.ioc.ObjectCreator; import org.apache.tapestry.ioc.ServiceBuilderResources; import org.apache.tapestry.ioc.def.ServiceDef; @@ -31,17 +33,33 @@ private final ObjectCreatorSource _source; - private Class _marker; + private final Set _markers; - ServiceDefImpl(Class serviceInterface, String serviceId, Class marker, - String scope, boolean eagerLoad, ObjectCreatorSource source) + /** + * @param serviceInterface + * interface implemented by the service (or the service implementation class, for + * non-proxied services) + * @param serviceId + * unique id for the service + * @param markers + * set of marker annotation classes (will be retained not copied) + * @param scope + * scope of the service (i.e., {@link IOCConstants#DEFAULT_SCOPE}). + * @param eagerLoad + * if true, the service is realized at startup, rather than on-demand + * @param source + * used to create the service implementation when needed + */ + ServiceDefImpl(Class serviceInterface, String serviceId, Set markers, String scope, + boolean eagerLoad, ObjectCreatorSource source) { _serviceInterface = serviceInterface; _serviceId = serviceId; - _marker = marker; _scope = scope; _eagerLoad = eagerLoad; _source = source; + + _markers = markers; } @Override @@ -75,9 +93,9 @@ return _eagerLoad; } - public Class getMarker() + public Set getMarkers() { - return _marker; + return _markers; } } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/TestBase.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/TestBase.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/TestBase.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/TestBase.java Sun Nov 11 01:28:03 2007 @@ -14,6 +14,9 @@ package org.apache.tapestry.ioc.test; +import java.util.Arrays; +import java.util.List; + import org.easymock.EasyMock; import org.easymock.IExpectationSetters; import org.easymock.IMocksControl; @@ -154,5 +157,59 @@ for (String substring : substrings) assertTrue(message.contains(substring)); + } + + /** + * Compares two lists for equality; first all the elements are individually compared for + * equality (if the lists are of unequal length, only elements up to the shorter length are + * compared). Then the length of the lists are compared. This generally gives + * + * @param + * type of objects to compare + * @param actual + * actual values to check + * @param expected + * expected values + */ + protected final void assertListsEquals(List actual, List expected) + { + int count = Math.min(actual.size(), expected.size()); + + for (int i = 0; i < count; i++) + { + assertEquals(actual.get(i), expected.get(i), String.format("Element #%d.", i)); + } + + assertEquals(actual.size(), expected.size(), "List size."); + } + + /** + * Convenience for {@link #assertListsEquals(List, List)}. + * + * @param + * tyoe of objects to compare + * @param actual + * actual values to check + * @param expected + * expected values + */ + protected final void assertListsEquals(List actual, T... expected) + { + assertListsEquals(actual, Arrays.asList(expected)); + } + + /** + * Convenience for {@link #assertListsEquals(List, List)}. + * + * @param + * tyoe of objects to compare + * @param actual + * actual values to check + * @param expected + * expected values + */ + protected final void assertArraysEqual(T[] actual, T... expected) + { + assertListsEquals(Arrays.asList(actual), expected); } } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/cookbook/patterns.apt URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/cookbook/patterns.apt?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/cookbook/patterns.apt (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/cookbook/patterns.apt Sun Nov 11 01:28:03 2007 @@ -17,6 +17,8 @@ Let's look at another example, again from the Tapestry code base. The {{{../../apidocs/org/apache/tapestry/services/InjectionProvider.html}InjectProvider}} interface is used to process the @Inject annotation on the fields of a Tapestry page or component. + Many different instances are combined together to form a + {{{../command.html}chain of command}}. The interface has only a single method (this is far from uncommon): Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/overview.apt URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/overview.apt?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/overview.apt (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/overview.apt Sun Nov 11 01:28:03 2007 @@ -21,7 +21,7 @@ That's an system. Most desktop applications are unmanaged, so it's a very familiar pattern, and easy to get your head around. - By contrast, web application are a environment. You don't write a main(), you don't control startup. You + By contrast, web applications are a environment. You don't write a main(), you don't control startup. You the Servlet API to tell it about your servlet classes to be instantiated, and their lifecycle is totally controlled by the servlet container. @@ -34,7 +34,7 @@ of , values stored inside instance variables, since in a multi-threaded environment, that's no longer the safe place it is in traditional development. Shared objects plus internal state plus multiple threads equals an broken, unpredictable application. - Frameworks such as Tapestry (both the IoC container, and the web framework itself) exists to help. + Frameworks such as Tapestry -- both the IoC container, and the web framework itself -- exist to help. When thinking in terms of IoC, <>. What does that mean? It means small classes and small methods are easier to code than large ones. At one extreme, we have servlets circa 1997 (and Visual Basic before that) with methods a thousand lines long, Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImplTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImplTest.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImplTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/DefaultModuleDefImplTest.java Sun Nov 11 01:28:03 2007 @@ -34,6 +34,7 @@ import org.apache.tapestry.ioc.def.ModuleDef; import org.apache.tapestry.ioc.def.ServiceDef; import org.apache.tapestry.ioc.internal.services.ClassFactoryImpl; +import org.apache.tapestry.ioc.internal.util.CollectionFactory; import org.apache.tapestry.ioc.internal.util.InternalUtils; import org.apache.tapestry.ioc.services.ClassFactory; import org.apache.tapestry.ioc.test.IOCTestCase; @@ -89,7 +90,7 @@ assertTrue(sd.toString().contains(className + ".buildFred()")); assertEquals(sd.getServiceScope(), IOCConstants.DEFAULT_SCOPE); assertEquals(sd.isEagerLoad(), false); - assertNull(sd.getMarker()); + assertTrue(sd.getMarkers().isEmpty()); sd = md.getServiceDef("Wilma"); assertEquals(sd.isEagerLoad(), true); @@ -520,7 +521,7 @@ ServiceDef sd = md.getServiceDef("Greeter"); - assertEquals(sd.getMarker(), BlueMarker.class); + assertListsEquals(CollectionFactory.newList(sd.getMarkers()), BlueMarker.class); verify(); } @@ -536,7 +537,7 @@ ServiceDef sd = md.getServiceDef("RedGreeter"); - assertEquals(sd.getMarker(), RedMarker.class); + assertListsEquals(CollectionFactory.newList(sd.getMarkers()), RedMarker.class); verify(); } @@ -552,11 +553,12 @@ ServiceDef sd = md.getServiceDef("SecondRedGreeter"); - assertEquals(sd.getMarker(), RedMarker.class); + assertListsEquals(CollectionFactory.newList(sd.getMarkers()), RedMarker.class); verify(); } + @SuppressWarnings("unchecked") @Test public void explicit_marker_overrides_marker_annotation() { @@ -568,8 +570,13 @@ ServiceDef sd = md.getServiceDef("SurprisinglyBlueGreeter"); - assertEquals(sd.getMarker(), BlueMarker.class); + // BlueMarker from ServiceBindingOptions, RedMarker from @Marker on class + assertEquals(sd.getMarkers(), CollectionFactory.newSet(RedMarker.class, BlueMarker.class)); verify(); } + + // TODO: We're short on tests that ensure that marker annotations are additive (i.e., module + // marker annotations are + // merged into the set specific to the service). } Modified: tapestry/tapestry5/trunk/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java?rev=593862&r1=593861&r2=593862&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java (original) +++ tapestry/tapestry5/trunk/tapestry-spring/src/main/java/org/apache/tapestry/internal/spring/SpringModuleDef.java Sun Nov 11 01:28:03 2007 @@ -93,10 +93,10 @@ return false; } - /** Returns null, Spring has no concept of a marker annotation. */ - public Class getMarker() + /** Returns an empty set, Spring has no concept of a marker annotation. */ + public Set getMarkers() { - return null; + return Collections.emptySet(); } }; @@ -141,9 +141,9 @@ } /** Returns null. */ - public Class getMarker() + public Set getMarkers() { - return null; + return Collections.emptySet(); } };