You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/05/15 21:22:59 UTC

svn commit: r538284 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/internal/ tapestry-core/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/src/main/java/org/apache/tapestry/services/ tapestry-core/src...

Author: hlship
Date: Tue May 15 12:22:56 2007
New Revision: 538284

URL: http://svn.apache.org/viewvc?view=rev&rev=538284
Log:
TAPESTRY-1369: There should be a global application-level message catalog for messages common to all pages & components

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/app.properties
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/AppCatalog.properties
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Symbol.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocalizationSetterImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/localization.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Localization.html
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/SimpleComponent.properties
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Value.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/StringLocation.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/StringLocationTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/InternalConstants.java Tue May 15 12:22:56 2007
@@ -14,6 +14,8 @@
 
 package org.apache.tapestry.internal;
 
+import org.apache.tapestry.services.Alias;
+
 public final class InternalConstants
 {
     /**
@@ -22,8 +24,18 @@
      */
     public static final String TAPESTRY_APP_PACKAGE_PARAM = "tapestry.app-package";
 
+    /**
+     * The application mode, generally "servlet", used to select the correct contributions to the
+     * {@link Alias} service.
+     */
     public static final String TAPESTRY_ALIAS_MODE_SYMBOL = "tapestry.alias-mode";
-    
+
+    /**
+     * The name of the application (i.e., the name of the application filter). Used, for example, to
+     * select additional resources related to the application.
+     */
+    public static final String TAPESTRY_APP_NAME_SYMBOL = "tapestry.app-name";
+
     /**
      * The extension used for Tapestry component template files. Template files are well-formed XML
      * files. This is also used as the extension for page render requests (perhaps these will be
@@ -35,12 +47,14 @@
     /** All purpose CSS class name for anything related to Tapestry errors. */
     public static final String TAPESTRY_ERROR_CLASS = "t-error";
 
-    /** The name of the query parameter that stores the page context inside an action request. */
-
+    /**
+     * The name of the query parameter that stores the page activation context inside an action
+     * request.
+     */
     public static final String PAGE_CONTEXT_NAME = "t:ac";
 
     public static final String OBJECT_RENDER_DIV_SECTION = "t-env-data-section";
-    
+
     private InternalConstants()
     {
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryAppInitializer.java Tue May 15 12:22:56 2007
@@ -149,7 +149,12 @@
                         InternalConstants.TAPESTRY_ALIAS_MODE_SYMBOL, _aliasMode),
                 "before:ServletContext");
 
-        builder.add(new SyntheticModuleDef(symbolSourceContribution, aliasModeContribution));
+        ContributionDef appNameContribution = new SyntheticSymbolSourceContributionDef("AppName",
+                new SingleKeySymbolProvider(InternalConstants.TAPESTRY_APP_NAME_SYMBOL, _appName),
+                "before:ServletContext");
+
+        builder.add(new SyntheticModuleDef(symbolSourceContribution, aliasModeContribution,
+                appNameContribution));
     }
 
     private void overrideServices(RegistryBuilder builder)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java Tue May 15 12:22:56 2007
@@ -23,8 +23,9 @@
 import java.util.Map;
 
 import org.apache.tapestry.events.InvalidationListener;
+import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.ioc.annotations.Inject;
-import org.apache.tapestry.ioc.annotations.Value;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.services.ComponentClassResolver;
 import org.apache.tapestry.services.LibraryMapping;
 
@@ -69,7 +70,7 @@
             ClassNameLocator classNameLocator,
 
             @Inject
-            @Value("${tapestry.app-package}")
+            @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM)
             String appRootPackage,
 
             Collection<LibraryMapping> mappings)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImpl.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImpl.java Tue May 15 12:22:56 2007
@@ -28,13 +28,20 @@
 {
     private final MessagesSource _messagesSource;
 
+    private final Resource _rootResource;
+
+    private final String _appCatalog;
+
     private static class ComponentModelBundle implements MessagesBundle
     {
         private final ComponentModel _model;
 
-        public ComponentModelBundle(final ComponentModel model)
+        private final MessagesBundle _rootBundle;
+
+        public ComponentModelBundle(ComponentModel model, MessagesBundle rootBundle)
         {
             _model = model;
+            _rootBundle = rootBundle;
         }
 
         public Resource getBaseResource()
@@ -51,18 +58,22 @@
         {
             ComponentModel parentModel = _model.getParentModel();
 
-            return parentModel != null ? new ComponentModelBundle(parentModel) : null;
-        }
+            if (parentModel == null) return _rootBundle;
 
+            return new ComponentModelBundle(parentModel, _rootBundle);
+        }
     }
 
-    public ComponentMessagesSourceImpl()
+    public ComponentMessagesSourceImpl(Resource rootResource, String appCatalog)
     {
-        this(new URLChangeTracker());
+        this(rootResource, appCatalog, new URLChangeTracker());
     }
 
-    ComponentMessagesSourceImpl(URLChangeTracker tracker)
+    ComponentMessagesSourceImpl(Resource rootResource, String appCatalog, URLChangeTracker tracker)
     {
+        _rootResource = rootResource;
+        _appCatalog = appCatalog;
+
         _messagesSource = new MessagesSourceImpl(tracker);
     }
 
@@ -73,7 +84,30 @@
 
     public Messages getMessages(ComponentModel componentModel, Locale locale)
     {
-        MessagesBundle bundle = new ComponentModelBundle(componentModel);
+        final Resource appCatalogResource = _rootResource.forFile(_appCatalog);
+
+        // If the application catalog exists, set it up as the root, otherwise use null.
+
+        MessagesBundle appCatalogBundle = appCatalogResource.toURL() == null ? null
+                : new MessagesBundle()
+                {
+                    public Resource getBaseResource()
+                    {
+                        return appCatalogResource;
+                    }
+
+                    public Object getId()
+                    {
+                        return _appCatalog;
+                    }
+
+                    public MessagesBundle getParent()
+                    {
+                        return null;
+                    }
+                };
+
+        MessagesBundle bundle = new ComponentModelBundle(componentModel, appCatalogBundle);
 
         return _messagesSource.getMessages(bundle, locale);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java Tue May 15 12:22:56 2007
@@ -16,9 +16,8 @@
 
 import javax.servlet.http.Cookie;
 
-import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.annotations.InjectService;
-import org.apache.tapestry.ioc.annotations.Value;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.services.Cookies;
 
 /**
@@ -43,8 +42,7 @@
     @InjectService("CookieSink")
     CookieSink cookieSink,
 
-    @Inject
-    @Value("${tapestry.default-cookie-max-age}")
+    @Symbol("tapestry.default-cookie-max-age")
     int defaultMaxAge)
     {
         _contextPathSource = contextPathSource;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalModule.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/InternalModule.java Tue May 15 12:22:56 2007
@@ -42,7 +42,7 @@
 import org.apache.tapestry.ioc.ServiceResources;
 import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.annotations.Scope;
-import org.apache.tapestry.ioc.annotations.Value;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.services.ChainBuilder;
 import org.apache.tapestry.ioc.services.ClassFactory;
@@ -586,7 +586,7 @@
             final RequestGlobals requestGlobals,
 
             // @Inject not needed because its a long, not a String
-            @Value("${tapestry.file-check-interval}")
+            @Symbol("tapestry.file-check-interval")
             long checkInterval,
 
             @InjectService("LocalizationSetter")

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocalizationSetterImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocalizationSetterImpl.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocalizationSetterImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LocalizationSetterImpl.java Tue May 15 12:22:56 2007
@@ -14,15 +14,15 @@
 
 package org.apache.tapestry.internal.services;
 
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newConcurrentMap;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
 
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.tapestry.ioc.annotations.Inject;
-import org.apache.tapestry.ioc.annotations.Value;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.ioc.services.ThreadLocale;
 import org.apache.tapestry.services.PersistentLocale;
 
@@ -44,7 +44,7 @@
 
     public LocalizationSetterImpl(PersistentLocale persistentLocale, ThreadLocale threadLocale,
             @Inject
-            @Value("${tapestry.supported-locales}")
+            @Symbol("tapestry.supported-locales")
             String acceptedLocaleNames)
     {
         _persistentLocale = persistentLocale;

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?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- 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 Tue May 15 12:22:56 2007
@@ -42,7 +42,6 @@
 import org.apache.tapestry.annotations.BeforeRenderTemplate;
 import org.apache.tapestry.annotations.BeginRender;
 import org.apache.tapestry.annotations.CleanupRender;
-import org.apache.tapestry.annotations.Inject;
 import org.apache.tapestry.annotations.InjectPage;
 import org.apache.tapestry.annotations.PageAttached;
 import org.apache.tapestry.annotations.PageDetached;
@@ -55,6 +54,7 @@
 import org.apache.tapestry.dom.DefaultMarkupModel;
 import org.apache.tapestry.dom.Document;
 import org.apache.tapestry.grid.GridDataSource;
+import org.apache.tapestry.internal.InternalConstants;
 import org.apache.tapestry.internal.TapestryInternalUtils;
 import org.apache.tapestry.internal.beaneditor.PrimitiveFieldConstraintGenerator;
 import org.apache.tapestry.internal.beaneditor.ValidateAnnotationConstraintGenerator;
@@ -164,8 +164,10 @@
 import org.apache.tapestry.ioc.OrderedConfiguration;
 import org.apache.tapestry.ioc.ServiceBinder;
 import org.apache.tapestry.ioc.ServiceResources;
+import org.apache.tapestry.ioc.annotations.Inject;
 import org.apache.tapestry.ioc.annotations.InjectService;
 import org.apache.tapestry.ioc.annotations.SubModule;
+import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.ioc.annotations.Value;
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.services.ChainBuilder;
@@ -238,8 +240,8 @@
 
     public static Alias build(Log log,
 
-    @org.apache.tapestry.ioc.annotations.Inject
-    @Value("${tapestry.alias-mode}")
+    @Inject
+    @Symbol(InternalConstants.TAPESTRY_ALIAS_MODE_SYMBOL)
     String mode,
 
     @InjectService("AliasOverrides")
@@ -334,7 +336,7 @@
             MappedConfiguration<String, String> configuration,
 
             // @Inject not needed, because this isn't a service builder method
-            @Value("${tapestry.scriptaculous.path}")
+            @Symbol("tapestry.scriptaculous.path")
             String scriptaculousPath)
     {
         configuration.add("tapestry/", "org/apache/tapestry/");
@@ -1129,22 +1131,17 @@
         return _strategyBuilder.build(registry);
     }
 
-    // /**
-    // * The configuration of the model source is a mapping from type to string. The types are
-    // * property types and the values, the strings, represent different type of editors.
-    // */
-    // public BeanModelSource build(TypeCoercer typeCoercer,
-    //
-    // @InjectService("DataTypeAnalyzer")
-    // DataTypeAnalyzer analyzer)
-    // {
-    // return new BeanModelSourceImpl(typeCoercer, _propertyAccess, _propertyConduitSource,
-    // _componentClassFactory, analyzer);
-    // }
+    public static ComponentMessagesSource build(UpdateListenerHub updateListenerHub,
 
-    public static ComponentMessagesSource build(UpdateListenerHub updateListenerHub)
+    @InjectService("ContextAssetFactory")
+    AssetFactory contextAssetFactory,
+
+    @Inject
+    @Value("WEB-INF/${tapestry.app-name}.properties")
+    String appCatalog)
     {
-        ComponentMessagesSourceImpl service = new ComponentMessagesSourceImpl();
+        ComponentMessagesSourceImpl service = new ComponentMessagesSourceImpl(contextAssetFactory
+                .getRootResource(), appCatalog);
 
         updateListenerHub.addUpdateListener(service);
 
@@ -1298,7 +1295,7 @@
 
     ComponentClassResolver componentClassResolver,
 
-    @Value("${tapestry.start-page-name}")
+    @Symbol("tapestry.start-page-name")
     String startPageName)
     {
         // Looks for the root path and renders the start page

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Tue May 15 12:22:56 2007
@@ -535,12 +535,6 @@
         expect(binding.get()).andReturn(value);
     }
 
-    protected final <T extends Annotation> void train_getAnnotation(AnnotationProvider provider,
-            Class<T> annotationClass, T annotation)
-    {
-        expect(provider.getAnnotation(annotationClass)).andReturn(annotation).atLeastOnce();
-    }
-
     protected void train_getAttribute(HttpSession session, String attributeName, Object value)
     {
         expect(session.getAttribute(attributeName)).andReturn(value);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/localization.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/localization.apt?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/localization.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/localization.apt Tue May 15 12:22:56 2007
@@ -37,7 +37,11 @@
   
 Application Message Catalog
 
-  Tapestry 4 supports an application-wide message catalog; this is <<not yet>> in Tapestry 5, but will likely be coming soon.
+  If the file <<<WEB-INF/>>><AppName><<<.properties>>> exists in the context, it will be used as an application-wide message catalog.  The <AppName>
+  is derived from the name of the filter inside the web.xml file.  The search for the file is case sensitive. The properties file may be localized.
+  
+  Individual pages and components
+  can override the values defined in this message catalog.
   
 Localized Component Templates
 

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/app.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/app.properties?view=auto&rev=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/app.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/WEB-INF/app.properties Tue May 15 12:22:56 2007
@@ -0,0 +1,15 @@
+# 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.
+
+app-catalog-status=Application Catalog Working
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Tue May 15 12:22:56 2007
@@ -244,6 +244,7 @@
 
         assertTextPresent("Via injected Messages property: [Accessed via injected Messages]");
         assertTextPresent("Via message: binding prefix: [Accessed via message: binding prefix]");
+        assertTextPresent("From Application Message Catalog: [Application Catalog Working]");
         assertTextPresent("Page locale: [en]");
         clickAndWait("link=French");
         assertTextPresent("Page locale: [fr]");

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImplTest.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/ComponentMessagesSourceImplTest.java Tue May 15 12:22:56 2007
@@ -22,6 +22,7 @@
 import org.apache.tapestry.ioc.Resource;
 import org.apache.tapestry.ioc.internal.util.ClasspathResource;
 import org.apache.tapestry.model.ComponentModel;
+import org.apache.tapestry.services.ComponentMessagesSource;
 import org.testng.annotations.Test;
 
 /**
@@ -37,11 +38,12 @@
 
     private final URLChangeTracker _tracker = new URLChangeTracker();
 
-    private final ComponentMessagesSourceImpl _source = new ComponentMessagesSourceImpl(_tracker);
-
     private final Resource _simpleComponentResource = new ClasspathResource(
             "org/apache/tapestry/internal/services/SimpleComponent.class");
 
+    private final ComponentMessagesSourceImpl _source = new ComponentMessagesSourceImpl(
+            _simpleComponentResource, "AppCatalog.properties", _tracker);
+
     @Test
     public void simple_component()
     {
@@ -110,7 +112,7 @@
 
         verify();
     }
-    
+
     @Test
     public void messages_keys_are_case_insensitive()
     {
@@ -131,7 +133,7 @@
         assertEquals(messages.get("COlor"), "colour");
         assertEquals(messages.get("Framework"), "Tapestry");
 
-        verify();       
+        verify();
     }
 
     @Test
@@ -165,6 +167,8 @@
         assertEquals(messages.get("framework"), "Tapestry");
         assertEquals(messages.get("source"), "SubclassComponent");
         assertEquals(messages.get("metal"), "steel");
+        assertEquals(messages.get("app-catalog-source"), "AppCatalog");
+        assertEquals(messages.get("app-catalog-overridden"), "Overridden by Component");
 
         messages = _source.getMessages(model, Locale.UK);
 
@@ -172,6 +176,43 @@
         assertEquals(messages.get("framework"), "Tapestry");
         assertEquals(messages.get("source"), "SubclassComponent");
         assertEquals(messages.get("metal"), "aluminium");
+
+        verify();
+    }
+
+    @Test
+    public void no_app_catalog()
+    {
+        ComponentModel model = mockComponentModel();
+        ComponentModel parent = mockComponentModel();
+
+        train_getComponentClassName(
+                model,
+                "org.apache.tapestry.internal.services.SubclassComponent");
+
+        train_getBaseResource(model, new ClasspathResource(
+                "org/apache/tapestry/internal/services/SubclassComponent.class"));
+
+        train_getParentModel(model, parent);
+
+        train_getComponentClassName(parent, SIMPLE_COMPONENT_CLASS_NAME);
+
+        train_getBaseResource(parent, _simpleComponentResource);
+
+        train_getParentModel(parent, null);
+
+        replay();
+
+        forceCacheClear();
+
+        ComponentMessagesSource source = new ComponentMessagesSourceImpl(_simpleComponentResource,
+                "NoSuchAppCatalog.properties");
+
+        Messages messages = source.getMessages(model, Locale.ENGLISH);
+
+        assertEquals(messages.get("color"), "color");
+        assertEquals(messages.get("app-catalog-source"), "[[missing key: app-catalog-source]]");
+        assertEquals(messages.get("app-catalog-overridden"), "Overridden by Component");
 
         verify();
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Localization.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Localization.html?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Localization.html (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Localization.html Tue May 15 12:22:56 2007
@@ -10,6 +10,8 @@
 
     <p> Via message: binding prefix: [${message:via-prefix}]</p>
     
+  <p> From Application Message Catalog: [${message:app-catalog-status}]</p>
+    
     <p> Page locale: [${locale}]</p>
     
     <p> Request locale: [${request.locale}]</p>

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/AppCatalog.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/AppCatalog.properties?view=auto&rev=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/AppCatalog.properties (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/AppCatalog.properties Tue May 15 12:22:56 2007
@@ -0,0 +1,16 @@
+# 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.
+
+app-catalog-source=AppCatalog
+app-catalog-overridden=Value from AppCatalog
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/SimpleComponent.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/SimpleComponent.properties?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/SimpleComponent.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/SimpleComponent.properties Tue May 15 12:22:56 2007
@@ -1,4 +1,4 @@
-# Copyright 2006 The Apache Software Foundation
+# Copyright 2006, 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.
@@ -15,3 +15,4 @@
 color=color
 framework=Tapestry
 source=SimpleComponent
+app-catalog-overridden=Overridden by Component
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Symbol.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Symbol.java?view=auto&rev=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Symbol.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Symbol.java Tue May 15 12:22:56 2007
@@ -0,0 +1,38 @@
+// 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.ioc.annotations;
+
+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;
+
+/**
+ * Used to inject a symbol value, via a symbol name. This is used much like {@link Value}
+ * annotation, except that symbols are not expanded ... the entire value is a symbol name. This
+ * allows the annotation to reference a public constant variable.
+ */
+@Target(
+{ PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+public @interface Symbol
+{
+    /** The name of the symbol to inject. */
+    String value();
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Value.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Value.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Value.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/Value.java Tue May 15 12:22:56 2007
@@ -14,6 +14,7 @@
 
 package org.apache.tapestry.ioc.annotations;
 
+import static java.lang.annotation.ElementType.FIELD;
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
@@ -26,12 +27,15 @@
 
 /**
  * Used in conjunction with {@link Inject} to inject a literal value, rather than a service. Symbols
- * in the value are expanded and the resulting string is coerced to the desired type.
+ * in the value are expanded and the resulting string is coerced to the desired type. For IoC, this
+ * annotation is only applied to parameters (on service builder methods, and on service
+ * constructors); for components, it may also be applied to field.
  * 
  * @see SymbolSource
  * @see TypeCoercer
  */
-@Target(PARAMETER)
+@Target(
+{ PARAMETER, FIELD })
 @Retention(RUNTIME)
 @Documented
 public @interface Value

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/StringLocation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/StringLocation.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/StringLocation.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/StringLocation.java Tue May 15 12:22:56 2007
@@ -1,3 +1,17 @@
+// 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.ioc.internal.services;
 
 import org.apache.tapestry.ioc.Location;

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java?view=auto&rev=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java Tue May 15 12:22:56 2007
@@ -0,0 +1,56 @@
+// 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.ioc.internal.services;
+
+import org.apache.tapestry.ioc.AnnotationProvider;
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.annotations.InjectService;
+import org.apache.tapestry.ioc.annotations.Symbol;
+import org.apache.tapestry.ioc.services.SymbolSource;
+import org.apache.tapestry.ioc.services.TypeCoercer;
+
+/**
+ * Performs an injection based on a {@link Symbol} annotation.
+ */
+public class SymbolObjectProvider implements ObjectProvider
+{
+    private final SymbolSource _symbolSource;
+
+    private final TypeCoercer _typeCoercer;
+
+    public SymbolObjectProvider(@InjectService("SymbolSource")
+    SymbolSource symbolSource,
+
+    @InjectService("TypeCoercer")
+    TypeCoercer typeCoercer)
+    {
+        _symbolSource = symbolSource;
+        _typeCoercer = typeCoercer;
+    }
+
+    public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider,
+            ObjectLocator locator)
+    {
+        Symbol annotation = annotationProvider.getAnnotation(Symbol.class);
+
+        if (annotation == null) return null;
+
+        String symbolValue = _symbolSource.valueForSymbol(annotation.value());
+
+        return _typeCoercer.coerce(symbolValue, objectType);
+    }
+
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Tue May 15 12:22:56 2007
@@ -45,6 +45,7 @@
 import org.apache.tapestry.ioc.internal.services.PropertyAccessImpl;
 import org.apache.tapestry.ioc.internal.services.PropertyShadowBuilderImpl;
 import org.apache.tapestry.ioc.internal.services.StrategyBuilderImpl;
+import org.apache.tapestry.ioc.internal.services.SymbolObjectProvider;
 import org.apache.tapestry.ioc.internal.services.SymbolSourceImpl;
 import org.apache.tapestry.ioc.internal.services.SystemPropertiesSymbolProvider;
 import org.apache.tapestry.ioc.internal.services.ThreadLocaleImpl;
@@ -65,7 +66,6 @@
         binder.bind(PropertyShadowBuilder.class, PropertyShadowBuilderImpl.class);
         binder.bind(PipelineBuilder.class, PipelineBuilderImpl.class);
         binder.bind(DefaultImplementationBuilder.class, DefaultImplementationBuilderImpl.class);
-        binder.bind(ObjectProvider.class, ValueObjectProvider.class).withId("ValueObjectProvider");
         binder.bind(ExceptionTracker.class, ExceptionTrackerImpl.class);
         binder.bind(ExceptionAnalyzer.class, ExceptionAnalyzerImpl.class);
         binder.bind(TypeCoercer.class, TypeCoercerImpl.class);
@@ -121,8 +121,7 @@
     public static void contributeMasterObjectProvider(
             OrderedConfiguration<ObjectProvider> configuration,
 
-            @InjectService("ValueObjectProvider")
-            ObjectProvider valueObjectProvider)
+            ObjectLocator locator)
     {
         ObjectProvider defaultProvider = new ObjectProvider()
         {
@@ -135,7 +134,8 @@
         };
 
         configuration.add("DefaultProvider", defaultProvider, "after:*");
-        configuration.add("Value", valueObjectProvider);
+        configuration.add("Value", locator.autobuild(ValueObjectProvider.class));
+        configuration.add("Symbol", locator.autobuild(SymbolObjectProvider.class));
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java Tue May 15 12:22:56 2007
@@ -16,6 +16,7 @@
 
 import static org.easymock.EasyMock.isA;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.Locale;
@@ -354,5 +355,10 @@
     protected final void train_toURL(Resource resource, URL url)
     {
         expect(resource.toURL()).andReturn(url).atLeastOnce();
+    }
+
+    protected final <T extends Annotation> void train_getAnnotation(AnnotationProvider annotationProvider, Class<T> annotationClass, T annotation)
+    {
+        expect(annotationProvider.getAnnotation(annotationClass)).andReturn(annotation);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/StringLocationTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/StringLocationTest.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/StringLocationTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/StringLocationTest.java Tue May 15 12:22:56 2007
@@ -1,3 +1,17 @@
+// 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.ioc.internal.services;
 
 import org.apache.tapestry.ioc.Location;

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java?view=auto&rev=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java Tue May 15 12:22:56 2007
@@ -0,0 +1,81 @@
+// 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.ioc.internal.services;
+
+import org.apache.tapestry.ioc.AnnotationProvider;
+import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.annotations.Symbol;
+import org.apache.tapestry.ioc.services.SymbolSource;
+import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.apache.tapestry.ioc.test.IOCTestCase;
+import org.testng.annotations.Test;
+
+public class SymbolObjectProviderTest extends IOCTestCase
+{
+    @Test
+    public void no_annotation()
+    {
+        SymbolSource source = mockSymbolSource();
+        TypeCoercer coercer = mockTypeCoercer();
+        AnnotationProvider annotationProvider = mockAnnotationProvider();
+        ObjectLocator locator = mockObjectLocator();
+
+        train_getAnnotation(annotationProvider, Symbol.class, null);
+
+        replay();
+
+        ObjectProvider provider = new SymbolObjectProvider(source, coercer);
+
+        assertNull(provider.provide(Long.class, annotationProvider, locator));
+
+        verify();
+    }
+
+    @Test
+    public void annotation_present()
+    {
+        SymbolSource source = mockSymbolSource();
+        TypeCoercer coercer = mockTypeCoercer();
+        AnnotationProvider annotationProvider = mockAnnotationProvider();
+        ObjectLocator locator = mockObjectLocator();
+        Symbol annotation = newMock(Symbol.class);
+        String symbolName = "example-symbol";
+        String symbolValue = "symbol-value";
+        Long coercedValue = 123l;
+
+        train_getAnnotation(annotationProvider, Symbol.class, annotation);
+
+        expect(annotation.value()).andReturn(symbolName);
+
+        train_valueForSymbol(source, symbolName, symbolValue);
+
+        train_coerce(coercer, symbolValue, Long.class, coercedValue);
+
+        replay();
+
+        ObjectProvider provider = new SymbolObjectProvider(source, coercer);
+
+        assertSame(provider.provide(Long.class, annotationProvider, locator), coercedValue);
+
+        verify();
+    }
+
+    protected final void train_valueForSymbol(SymbolSource source, String symbolName,
+            String symbolValue)
+    {
+        expect(source.valueForSymbol(symbolName)).andReturn(symbolValue);
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java?view=diff&rev=538284&r1=538283&r2=538284
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java Tue May 15 12:22:56 2007
@@ -14,8 +14,6 @@
 
 package org.apache.tapestry.ioc.internal.services;
 
-import java.lang.annotation.Annotation;
-
 import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.ioc.annotations.Value;
@@ -71,12 +69,5 @@
         assertSame(provider.provide(Runnable.class, annotationProvider, locator), coerced);
 
         verify();
-    }
-
-    protected final <T extends Annotation> void train_getAnnotation(
-            AnnotationProvider annotationProvider, Class<T> annotationClass, T annotation)
-    {
-        expect(annotationProvider.getAnnotation(annotationClass)).andReturn(annotation)
-                .atLeastOnce();
     }
 }