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 2009/02/17 16:25:17 UTC

svn commit: r745118 [1/2] - in /tapestry/tapestry5/trunk: src/site/apt/guide/ tapestry-core/src/main/java/org/apache/tapestry5/ tapestry-core/src/main/java/org/apache/tapestry5/internal/ tapestry-core/src/main/java/org/apache/tapestry5/internal/model/ ...

Author: hlship
Date: Tue Feb 17 15:25:11 2009
New Revision: 745118

URL: http://svn.apache.org/viewvc?rev=745118&view=rev
Log:
TAP5-516: When rendering a PageLink, it should not be necessary to load the target page instance just to see if there's a page activation context

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSource.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BadMixinIdDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/DupeMixinDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/UnsupportedParameterBlockDemo.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/BadMixinIdDemo.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/DupeMixinDemo.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/UnsupportedParameterBlockDemo.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/TestConstants.java
Modified:
    tapestry/tapestry5/trunk/src/site/apt/guide/conf.apt
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryAppInitializer.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ActionRenderResponseGeneratorImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSource.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MetaDataLocatorImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollector.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollectorImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCache.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManager.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManagerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageActivationContextWorker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MetaDataLocator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/PageTester.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Index.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/PageTesterTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/ASOTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/ActionLinkTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/AssetTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/DTDTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/FormTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/HeadTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/IfTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/LocaleTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/LoopTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/PrefixMethodTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/SubmitTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/TemplateInContextTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/pagelevel/UnlessTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/LinkSourceImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/MetaDataLocatorImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PageActivationContextCollectorImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/RequestSecurityManagerImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/test/InternalBaseTestCase.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/log4j.properties

Modified: tapestry/tapestry5/trunk/src/site/apt/guide/conf.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/guide/conf.apt?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/guide/conf.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/guide/conf.apt Tue Feb 17 15:25:11 2009
@@ -103,11 +103,16 @@
   Many of these symbols have an associated constant in the class
   {{{../apidocs/org/apache/tapestry5/SymbolConstants.html}SymbolConstants}}.
 
+  [tapestry.app-catalog]
+    The location of the global application message
+    catalog, the default is context:WEB-INF/<app-name>.properties.
+
   [tapestry.application-version]
     The version of the application, which is incorporated into URLs for context and classpath assets. Assets
     may be {{{compress.html}compressed}}, and will have far-future expiration headers; they will be aggresively
     cached by the client web browser. You should change the application version on each new deployment of the
-    application to force clients to re-download changed versions of files.  If you do not specify
+    application (that is, any time assets in the context change),
+    to force clients to re-download changed versions of files.  If you do not specify
     an application version, a <random> one will be assigned on every deployment (which is good for development
     but very bad for production).
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java Tue Feb 17 15:25:11 2009
@@ -33,7 +33,7 @@
      * is returned from <code>toString()</code>.
      * <p/>
      * Tapestry's built-in asset types (context and classpath) always incorporate a version number as part of the path,
-     * and alternate implementation are encouraged to do so as well. In addition, Tapestry ensures that context and
+     * and alternate implementations are encouraged to do so as well. In addition, Tapestry ensures that context and
      * classpath assets have a far-future expires header (to ensure aggresive caching by the client).
      * <p/>
      */

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/InternalSymbols.java Tue Feb 17 15:25:11 2009
@@ -27,4 +27,12 @@
      * resources related to the application.
      */
     public static final String APP_NAME = "tapestry.app-name";
+
+    /**
+     * The application package converted to a path ('.' becomes '/'). Useful for finding resources on the classpath
+     * relevant to the application.
+     *
+     * @since 5.1.0.0
+     */
+    public static final String APP_PACKAGE_PATH = "tapestry.app-package-path";
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryAppInitializer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryAppInitializer.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryAppInitializer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/TapestryAppInitializer.java Tue Feb 17 15:25:11 2009
@@ -109,7 +109,7 @@
 
         // Add a synthetic module that contributes symbol sources.
 
-        addSyntheticSymbolSourceModule();
+        addSyntheticSymbolSourceModule(appPackage);
     }
 
     /**
@@ -128,25 +128,32 @@
         builder.add(moduleClasses);
     }
 
-    private void addSyntheticSymbolSourceModule()
+    private void addSyntheticSymbolSourceModule(String appPackage)
     {
-        ContributionDef symbolSourceContribution = new SyntheticSymbolSourceContributionDef("ServletContext",
-                                                                                            appProvider,
-                                                                                            "before:ApplicationDefaults");
-
-        ContributionDef aliasModeContribution = new SyntheticSymbolSourceContributionDef("AliasMode",
-                                                                                         new SingleKeySymbolProvider(
-                                                                                                 InternalSymbols.ALIAS_MODE,
-                                                                                                 aliasMode),
-                                                                                         "before:ServletContext");
-
-        ContributionDef appNameContribution = new SyntheticSymbolSourceContributionDef("AppName",
-                                                                                       new SingleKeySymbolProvider(
-                                                                                               InternalSymbols.APP_NAME,
-                                                                                               appName),
-                                                                                       "before:ServletContext");
+        ContributionDef appPathContribution =
+                new SyntheticSymbolSourceContributionDef("AppPath",
+                                                         new SingleKeySymbolProvider(
+                                                                 InternalSymbols.APP_PACKAGE_PATH,
+                                                                 appPackage.replace('.', '/')));
+
+        ContributionDef symbolSourceContribution =
+                new SyntheticSymbolSourceContributionDef("ServletContext",
+                                                         appProvider,
+                                                         "before:ApplicationDefaults");
+
+        ContributionDef aliasModeContribution =
+                new SyntheticSymbolSourceContributionDef("AliasMode",
+                                                         new SingleKeySymbolProvider(InternalSymbols.ALIAS_MODE,
+                                                                                     aliasMode),
+                                                         "before:ServletContext");
+
+        ContributionDef appNameContribution =
+                new SyntheticSymbolSourceContributionDef("AppName",
+                                                         new SingleKeySymbolProvider(InternalSymbols.APP_NAME, appName),
+                                                         "before:ServletContext");
 
-        builder.add(new SyntheticModuleDef(symbolSourceContribution, aliasModeContribution, appNameContribution));
+        builder.add(new SyntheticModuleDef(symbolSourceContribution, aliasModeContribution, appNameContribution,
+                                           appPathContribution));
     }
 
     public Registry createRegistry()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/model/MutableComponentModelImpl.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -62,6 +62,8 @@
 
     private Set<Class> handledRenderPhases;
 
+    private Map<String, Boolean> handledEvents;
+
     public MutableComponentModelImpl(String componentClassName, Logger logger, Resource baseResource,
                                      ComponentModel parentModel)
     {
@@ -284,6 +286,14 @@
         handledRenderPhases.add(renderPhase);
     }
 
+    public void addEventHandler(String eventType)
+    {
+        if (handledEvents == null)
+            handledEvents = CollectionFactory.newCaseInsensitiveMap();
+
+        handledEvents.put(eventType, true);
+    }
+
     public String getMeta(String key)
     {
         String result = InternalUtils.get(metaData, key);
@@ -305,4 +315,13 @@
 
         return result;
     }
+
+    public boolean handlesEvent(String eventType)
+    {
+        if (InternalUtils.get(handledEvents, eventType) != null) return true;
+
+        return parentModel == null
+               ? false
+               : parentModel.handlesEvent(eventType);
+    }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/ComponentAssemblerImpl.java Tue Feb 17 15:25:11 2009
@@ -252,46 +252,59 @@
                                                               EmbeddedComponentModel embeddedModel, String mixins,
                                                               Location location)
     {
-        EmbeddedComponentAssemblerImpl embedded = new EmbeddedComponentAssemblerImpl(assemblerSource,
-                                                                                     instantiatorSource,
-                                                                                     componentClassResolver,
-                                                                                     componentClassName,
-                                                                                     locale, embeddedModel,
-                                                                                     mixins,
-                                                                                     location);
+        try
+        {
+            EmbeddedComponentAssemblerImpl embedded = new EmbeddedComponentAssemblerImpl(assemblerSource,
+                                                                                         instantiatorSource,
+                                                                                         componentClassResolver,
+                                                                                         componentClassName,
+                                                                                         locale, embeddedModel,
+                                                                                         mixins,
+                                                                                         location);
 
-        if (embeddedIdToAssembler == null)
-            embeddedIdToAssembler = CollectionFactory.newMap();
 
-        embeddedIdToAssembler.put(embeddedId, embedded);
+            if (embeddedIdToAssembler == null)
+                embeddedIdToAssembler = CollectionFactory.newMap();
 
-        if (embeddedModel != null)
-        {
-            for (String publishedParameterName : embeddedModel.getPublishedParameters())
+            embeddedIdToAssembler.put(embeddedId, embedded);
+
+            if (embeddedModel != null)
             {
-                if (publishedParameterToEmbeddedId == null)
-                    publishedParameterToEmbeddedId = CollectionFactory.newCaseInsensitiveMap();
+                for (String publishedParameterName : embeddedModel.getPublishedParameters())
+                {
+                    if (publishedParameterToEmbeddedId == null)
+                        publishedParameterToEmbeddedId = CollectionFactory.newCaseInsensitiveMap();
 
-                String existingEmbeddedId = publishedParameterToEmbeddedId.get(publishedParameterName);
+                    String existingEmbeddedId = publishedParameterToEmbeddedId.get(publishedParameterName);
 
-                if (existingEmbeddedId != null)
-                {
-                    String message = String.format(
-                            "Parameter '%s' of embedded component '%s' can not be published as a parameter of component %s, as it has previously been published by embedded component '%s'.",
-                            publishedParameterName,
-                            embeddedId,
-                            instantiator.getModel().getComponentClassName(),
-                            existingEmbeddedId);
+                    if (existingEmbeddedId != null)
+                    {
+                        String message = String.format(
+                                "Parameter '%s' of embedded component '%s' can not be published as a parameter of component %s, as it has previously been published by embedded component '%s'.",
+                                publishedParameterName,
+                                embeddedId,
+                                instantiator.getModel().getComponentClassName(),
+                                existingEmbeddedId);
+
+                        throw new TapestryException(message, location, null);
+                    }
 
-                    throw new TapestryException(message, location, null);
+                    publishedParameterToEmbeddedId.put(publishedParameterName, embeddedId);
                 }
 
-                publishedParameterToEmbeddedId.put(publishedParameterName, embeddedId);
             }
 
+            return embedded;
         }
+        catch (Exception ex)
+        {
+            String message = String.format("Failure creating embedded component '%s' of %s: %s",
+                                           embeddedId,
+                                           instantiator.getModel().getComponentClassName(),
+                                           InternalUtils.toMessage(ex));
 
-        return embedded;
+            throw new TapestryException(message, location, ex);
+        }
     }
 
     public ParameterBinder getBinder(final String parameterName)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/pageload/PageLoaderImpl.java Tue Feb 17 15:25:11 2009
@@ -75,10 +75,7 @@
 
             Key key = (Key) o;
 
-            if (!className.equals(key.className))
-                return false;
-
-            return locale.equals(key.locale);
+            return className.equals(key.className) && locale.equals(key.locale);
         }
 
         @Override
@@ -86,12 +83,6 @@
         {
             return 31 * className.hashCode() + locale.hashCode();
         }
-
-        @Override
-        public String toString()
-        {
-            return String.format("Key[%s, %s]", className, locale);
-        }
     }
 
     private static final PageAssemblyAction POP_EMBEDDED_COMPONENT_ACTION = new PageAssemblyAction()
@@ -417,7 +408,7 @@
                 if (binder == null)
                 {
                     String message = String.format(
-                            "Component %s does not include a parameter '%s' (and does not support informal parameters).",
+                            "Component %s does not include a formal parameter '%s' (and does not support informal parameters).",
                             element.getCompleteId(),
                             parameterName);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ActionRenderResponseGeneratorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ActionRenderResponseGeneratorImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ActionRenderResponseGeneratorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ActionRenderResponseGeneratorImpl.java Tue Feb 17 15:25:11 2009
@@ -38,7 +38,7 @@
 
     public void generateResponse(Page page) throws IOException
     {
-        Link link = linkSource.createPageRenderLink(page, false);
+        Link link = linkSource.createPageRenderLink(page.getName(), false);
 
         response.sendRedirect(link);
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java Tue Feb 17 15:25:11 2009
@@ -75,42 +75,54 @@
 
     public Asset getContextAsset(String path, Locale locale)
     {
-        Defense.notBlank(path, "path");
+        return getAsset(prefixToRootResource.get(CONTEXT), path, locale);
+    }
 
-        Resource rootResource = prefixToRootResource.get(CONTEXT);
+    public Asset getAsset(Resource baseResource, String path, Locale locale)
+    {
+        return getAssetInLocale(baseResource, path, defaulted(locale));
+    }
 
-        return findRelativeAsset(rootResource, path, locale);
+    public Resource resourceForPath(String path)
+    {
+        return getUnlocalizedResource(null, path);
     }
 
-    public Asset getAsset(Resource baseResource, String path, Locale locale)
+    private Asset getAssetInLocale(Resource baseResource, String path, Locale locale)
     {
-        Defense.notBlank(path, "path");
+        return getLocalizedAssetFromResource(getUnlocalizedResource(baseResource, path), locale);
+    }
 
-        if (baseResource == null) baseResource = prefixToRootResource.get(CLASSPATH);
+    private Resource getUnlocalizedResource(Resource baseResource, String path)
+    {
+        Defense.notBlank(path, "path");
 
         int colonx = path.indexOf(':');
 
-        if (colonx < 0) return findRelativeAsset(baseResource, path, locale);
+        if (colonx < 0)
+        {
+            Resource root = baseResource != null ? baseResource : prefixToRootResource.get(CLASSPATH);
+
+            return root.forFile(path);
+        }
 
         String prefix = path.substring(0, colonx);
 
-        Resource rootResource = prefixToRootResource.get(prefix);
+        Resource root = prefixToRootResource.get(prefix);
 
-        if (rootResource == null)
+        if (root == null)
             throw new IllegalArgumentException(ServicesMessages.unknownAssetPrefix(path));
 
-        return findRelativeAsset(rootResource, path.substring(colonx + 1), locale);
-    }
 
-    private Asset findRelativeAsset(Resource baseResource, String path, Locale locale)
-    {
-        Resource unlocalized = baseResource.forFile(path);
+        return root.forFile(path.substring(colonx + 1));
+    }
 
-        Locale effectiveLocale = locale != null
-                                 ? locale
-                                 : threadLocale.getLocale();
 
-        Resource localized = unlocalized.forLocale(effectiveLocale);
+    private Asset getLocalizedAssetFromResource(Resource unlocalized, Locale locale)
+    {
+        Resource localized = locale == null
+                             ? unlocalized
+                             : unlocalized.forLocale(locale);
 
         if (localized == null)
             throw new RuntimeException(ServicesMessages.assetDoesNotExist(unlocalized));
@@ -131,6 +143,11 @@
         return result;
     }
 
+    private Locale defaulted(Locale locale)
+    {
+        return locale != null ? locale : threadLocale.getLocale();
+    }
+
     private Asset createAssetFromResource(Resource resource)
     {
         // The class of the resource is derived from the class of the base resource.

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentMessagesSourceImpl.java Tue Feb 17 15:25:11 2009
@@ -14,9 +14,11 @@
 
 package org.apache.tapestry5.internal.services;
 
+import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.internal.util.URLChangeTracker;
 import org.apache.tapestry5.ioc.Messages;
 import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
 import org.apache.tapestry5.model.ComponentModel;
 import org.apache.tapestry5.services.InvalidationEventHub;
@@ -28,9 +30,7 @@
 {
     private final MessagesSource messagesSource;
 
-    private final Resource rootResource;
-
-    private final String appCatalog;
+    private final Resource appCatalogResource;
 
     private static class ComponentModelBundle implements MessagesBundle
     {
@@ -64,15 +64,18 @@
         }
     }
 
-    public ComponentMessagesSourceImpl(Resource rootResource, String appCatalog, ClasspathURLConverter classpathURLConverter)
+    public ComponentMessagesSourceImpl(
+            @Symbol(SymbolConstants.APPLICATION_CATALOG)
+            Resource appCatalogResource,
+
+            ClasspathURLConverter classpathURLConverter)
     {
-        this(rootResource, appCatalog, new URLChangeTracker(classpathURLConverter));
+        this(appCatalogResource, new URLChangeTracker(classpathURLConverter));
     }
 
-    ComponentMessagesSourceImpl(Resource rootResource, String appCatalog, URLChangeTracker tracker)
+    ComponentMessagesSourceImpl(Resource appCatalogResource, URLChangeTracker tracker)
     {
-        this.rootResource = rootResource;
-        this.appCatalog = appCatalog;
+        this.appCatalogResource = appCatalogResource;
 
         messagesSource = new MessagesSourceImpl(tracker);
     }
@@ -84,12 +87,19 @@
 
     public Messages getMessages(ComponentModel componentModel, Locale locale)
     {
-        final Resource appCatalogResource = rootResource.forFile(appCatalog);
-
         // If the application catalog exists, set it up as the root, otherwise use null.
 
         MessagesBundle appCatalogBundle = !appCatalogResource.exists() ? null
-                                                                       : new MessagesBundle()
+                                                                       : rootBundle();
+
+        MessagesBundle bundle = new ComponentModelBundle(componentModel, appCatalogBundle);
+
+        return messagesSource.getMessages(bundle, locale);
+    }
+
+    private MessagesBundle rootBundle()
+    {
+        return new MessagesBundle()
         {
             public Resource getBaseResource()
             {
@@ -98,7 +108,7 @@
 
             public Object getId()
             {
-                return appCatalog;
+                return appCatalogResource.getPath();
             }
 
             public MessagesBundle getParent()
@@ -106,10 +116,6 @@
                 return null;
             }
         };
-
-        MessagesBundle bundle = new ComponentModelBundle(componentModel, appCatalogBundle);
-
-        return messagesSource.getMessages(bundle, locale);
     }
 
     public InvalidationEventHub getInvalidationEventHub()

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSource.java?rev=745118&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSource.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSource.java Tue Feb 17 15:25:11 2009
@@ -0,0 +1,45 @@
+// Copyright 2009 ${ORG}
+//
+// 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.tapestry5.internal.services;
+
+import org.apache.tapestry5.model.ComponentModel;
+
+/**
+ * Access to component models (as provided via {@link org.apache.tapestry5.internal.services.ComponentInstantiatorSource}).
+ * <p/>
+ * <p>This is a good candidate to move into the public services package.
+ *
+ * @since 5.1.0.0
+ */
+public interface ComponentModelSource
+{
+    /**
+     * Returns the model for a particular component class name.
+     *
+     * @param componentClassName name of component class
+     * @return model for component
+     * @throws IllegalArgumentException if component class name does not match a known component
+     */
+    ComponentModel getModel(String componentClassName);
+
+    /**
+     * Returns the model for a page.  The page name is resolved to a component class name.
+     *
+     * @param pageName name of page
+     * @return the model for the page
+     * @throws IllegalArgumentException if the page name is not a known page name
+     */
+    ComponentModel getPageModel(String pageName);
+}

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java?rev=745118&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentModelSourceImpl.java Tue Feb 17 15:25:11 2009
@@ -0,0 +1,41 @@
+// Copyright 2009 ${ORG}
+//
+// 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.tapestry5.internal.services;
+
+import org.apache.tapestry5.model.ComponentModel;
+import org.apache.tapestry5.services.ComponentClassResolver;
+
+public class ComponentModelSourceImpl implements ComponentModelSource
+{
+    private final ComponentClassResolver resolver;
+
+    private final ComponentInstantiatorSource source;
+
+    public ComponentModelSourceImpl(ComponentClassResolver resolver, ComponentInstantiatorSource source)
+    {
+        this.resolver = resolver;
+        this.source = source;
+    }
+
+    public ComponentModel getModel(String componentClassName)
+    {
+        return source.getInstantiator(componentClassName).getModel();
+    }
+
+    public ComponentModel getPageModel(String pageName)
+    {
+        return getModel(resolver.resolvePageNameToClassName(pageName));
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/InternalModule.java Tue Feb 17 15:25:11 2009
@@ -18,6 +18,7 @@
 import org.apache.tapestry5.internal.pageload.PageLoaderImpl;
 import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSource;
 import org.apache.tapestry5.internal.structure.ComponentPageElementResourcesSourceImpl;
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
 import org.apache.tapestry5.ioc.ObjectLocator;
 import org.apache.tapestry5.ioc.ScopeConstants;
 import org.apache.tapestry5.ioc.ServiceBinder;
@@ -40,10 +41,17 @@
 
     private final RequestGlobals requestGlobals;
 
-    public InternalModule(UpdateListenerHub updateListenerHub, RequestGlobals requestGlobals)
+    private final InvalidationEventHub classesInvalidationEventHub;
+
+    public InternalModule(UpdateListenerHub updateListenerHub,
+                          RequestGlobals requestGlobals,
+
+                          @ComponentClasses
+                          InvalidationEventHub classesInvalidationEventHub)
     {
         this.updateListenerHub = updateListenerHub;
         this.requestGlobals = requestGlobals;
+        this.classesInvalidationEventHub = classesInvalidationEventHub;
     }
 
 
@@ -69,9 +77,9 @@
         binder.bind(RequestSecurityManager.class, RequestSecurityManagerImpl.class);
         binder.bind(InternalRequestGlobals.class, InternalRequestGlobalsImpl.class);
         binder.bind(EndOfRequestEventHub.class);
-        binder.bind(PageActivationContextCollector.class);
         binder.bind(ResponseCompressionAnalyzer.class, ResponseCompressionAnalyzerImpl.class);
         binder.bind(LinkFactory.class, LinkFactoryImpl.class);
+        binder.bind(ComponentModelSource.class);
     }
 
     /**
@@ -107,19 +115,8 @@
     }
 
 
-    public ComponentMessagesSource buildComponentMessagesSource(
-            @ContextProvider
-            AssetFactory contextAssetFactory,
-
-            @Inject
-            @Symbol(SymbolConstants.APPLICATION_CATALOG)
-            String appCatalog,
-
-            ClasspathURLConverter classpathURLConverter)
+    public ComponentMessagesSource buildComponentMessagesSource(@Autobuild ComponentMessagesSourceImpl service)
     {
-        ComponentMessagesSourceImpl service = new ComponentMessagesSourceImpl(contextAssetFactory
-                .getRootResource(), appCatalog, classpathURLConverter);
-
         updateListenerHub.addUpdateListener(service);
 
         return service;
@@ -153,9 +150,6 @@
 
     public PageLoader buildPageLoader(@Autobuild PageLoaderImpl service,
 
-                                      @ComponentClasses
-                                      InvalidationEventHub classesHub,
-
                                       @ComponentTemplates
                                       InvalidationEventHub templatesHub,
 
@@ -164,7 +158,7 @@
     {
         // TODO: We could combine these three using chain-of-command.
 
-        classesHub.addInvalidationListener(service);
+        classesInvalidationEventHub.addInvalidationListener(service);
         templatesHub.addInvalidationListener(service);
         messagesHub.addInvalidationListener(service);
 
@@ -174,9 +168,6 @@
 
     public PagePool buildPagePool(@Autobuild PagePoolImpl service,
 
-                                  @ComponentClasses
-                                  InvalidationEventHub classesHub,
-
                                   @ComponentTemplates
                                   InvalidationEventHub templatesHub,
 
@@ -185,7 +176,7 @@
     {
         // This covers invalidations due to changes to classes
 
-        classesHub.addInvalidationListener(service);
+        classesInvalidationEventHub.addInvalidationListener(service);
 
         // This covers invalidation due to changes to message catalogs (properties files)
 
@@ -202,10 +193,9 @@
         return service;
     }
 
-    public static ComponentClassCache buildComponentClassCache(@Autobuild ComponentClassCacheImpl service,
-                                                               @ComponentClasses InvalidationEventHub hub)
+    public ComponentClassCache buildComponentClassCache(@Autobuild ComponentClassCacheImpl service)
     {
-        hub.addInvalidationListener(service);
+        classesInvalidationEventHub.addInvalidationListener(service);
 
         return service;
     }
@@ -261,4 +251,18 @@
         return builder.build(componentInstantiatorSource, "classSource", CtClassSource.class);
     }
 
+    @Match("PageLoader")
+    public static void adviseWithLogging(LoggingAdvisor advisor, Logger logger, MethodAdviceReceiver receiver)
+    {
+        advisor.addLoggingAdvice(logger, receiver);
+    }
+
+    public PageActivationContextCollector buildPageActivationContextCollector(
+            @Autobuild PageActivationContextCollectorImpl service)
+    {
+        classesInvalidationEventHub.addInvalidationListener(service);
+
+        return service;
+    }
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkFactoryImpl.java Tue Feb 17 15:25:11 2009
@@ -14,12 +14,11 @@
 
 package org.apache.tapestry5.internal.services;
 
-import org.apache.tapestry5.Link;
 import org.apache.tapestry5.EventConstants;
 import org.apache.tapestry5.EventContext;
-import org.apache.tapestry5.ioc.internal.util.InternalUtils;
-import org.apache.tapestry5.internal.structure.Page;
+import org.apache.tapestry5.Link;
 import org.apache.tapestry5.internal.InternalConstants;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.services.*;
 
 import java.util.Locale;
@@ -36,8 +35,6 @@
 
     private final PersistentLocale persistentLocale;
 
-    private final RequestPageCache requestPageCache;
-
     private final ContextValueEncoder valueEncoder;
 
     private final URLEncoder urlEncoder;
@@ -48,7 +45,6 @@
 
     public LinkFactoryImpl(Request request, Response response, RequestSecurityManager requestSecurityManager,
                            RequestPathOptimizer optimizer, PersistentLocale persistentLocale,
-                           RequestPageCache requestPageCache,
                            ContextValueEncoder valueEncoder, URLEncoder urlEncoder)
     {
         this.request = request;
@@ -56,7 +52,6 @@
         this.requestSecurityManager = requestSecurityManager;
         this.optimizer = optimizer;
         this.persistentLocale = persistentLocale;
-        this.requestPageCache = requestPageCache;
         this.valueEncoder = valueEncoder;
         this.urlEncoder = urlEncoder;
     }
@@ -71,12 +66,10 @@
         String containingPageName = parameters.getContainingPageName();
         String eventType = parameters.getEventType();
 
-        Page activePage = requestPageCache.get(activePageName);
-
         String nestedComponentId = parameters.getNestedComponentId();
         boolean hasComponentId = InternalUtils.isNonBlank(nestedComponentId);
 
-        String baseURL = requestSecurityManager.getBaseURL(activePage);
+        String baseURL = requestSecurityManager.getBaseURL(activePageName);
 
         if (baseURL != null)
             builder.append(baseURL);
@@ -140,10 +133,7 @@
 
         String activePageName = parameters.getLogicalPageName();
 
-        Page activePage = requestPageCache.get(activePageName);
-
-
-        String baseURL = requestSecurityManager.getBaseURL(activePage);
+        String baseURL = requestSecurityManager.getBaseURL(activePageName);
 
         if (baseURL != null)
             builder.append(baseURL);

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSource.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSource.java Tue Feb 17 15:25:11 2009
@@ -49,24 +49,13 @@
      * activation context. This is accomplished by triggering a "passivate" event on the targetted page. If the override
      * parameter is true, this will not occur (even when the activation context is empty).
      *
-     * @param page              the page to which a link should be created
-     * @param override          if true, then the provided activation context is always used even if empty
-     * @param activationContext the activation context for the page
+     * @param pageName              name of the page to which a link should be created
+     * @param override              if true, then the provided activation context is always used even if empty
+     * @param pageActivationContext the activation context for the page
      * @return a link
      * @see org.apache.tapestry5.ComponentResources#createPageLink(String, boolean, Object[])
      */
-    Link createPageRenderLink(Page page, boolean override, Object... activationContext);
-
-    /**
-     * As with {@link #createPageRenderLink(Page, boolean, Object[])}, but the page is specified by logical name, rather
-     * than as an instance.  Note: renamed from createPageLink() in 5.1.
-     *
-     * @param logicalPageName the logical name of the page to generate a link to
-     * @param override        if true, then the provided activation context is always used even if empty
-     * @param context         activation context for the page
-     * @return a link
-     */
-    Link createPageRenderLink(String logicalPageName, boolean override, Object... context);
+    Link createPageRenderLink(String pageName, boolean override, Object... pageActivationContext);
 
     /**
      * Returns the hub, used to register and de-register {@link org.apache.tapestry5.services.LinkCreationListener}s.

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSourceImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/LinkSourceImpl.java Tue Feb 17 15:25:11 2009
@@ -19,10 +19,7 @@
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.Defense;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
-import org.apache.tapestry5.services.ComponentEventRequestParameters;
-import org.apache.tapestry5.services.LinkCreationHub;
-import org.apache.tapestry5.services.LinkCreationListener;
-import org.apache.tapestry5.services.PageRenderRequestParameters;
+import org.apache.tapestry5.services.*;
 
 import java.util.List;
 
@@ -40,17 +37,20 @@
 
     private final TypeCoercer typeCoercer;
 
+    private final ComponentClassResolver resolver;
+
     public LinkSourceImpl(
             RequestPageCache pageCache,
             PageRenderQueue pageRenderQueue,
             PageActivationContextCollector contextCollector,
-            LinkFactory linkFactory, TypeCoercer typeCoercer)
+            LinkFactory linkFactory, TypeCoercer typeCoercer, ComponentClassResolver resolver)
     {
         this.pageCache = pageCache;
         this.pageRenderQueue = pageRenderQueue;
         this.contextCollector = contextCollector;
         this.linkFactory = linkFactory;
         this.typeCoercer = typeCoercer;
+        this.resolver = resolver;
     }
 
     public Link createComponentEventLink(Page page, String nestedId, String eventType, boolean forForm,
@@ -65,11 +65,13 @@
         if (activePage == null)
             activePage = page;
 
-        Object[] pageActivationContext = contextCollector.collectPageActivationContext(activePage);
+        String activePageName = activePage.getName();
+
+        Object[] pageActivationContext = contextCollector.collectPageActivationContext(activePageName);
 
         ComponentEventRequestParameters parameters
                 = new ComponentEventRequestParameters(
-                activePage.getName(),
+                activePageName,
                 page.getName(),
                 toBlank(nestedId),
                 eventType,
@@ -90,20 +92,19 @@
         return input == null ? "" : input;
     }
 
-    public Link createPageRenderLink(Page page, boolean override, Object... pageActivationContext)
+    public Link createPageRenderLink(String pageName, boolean override, Object... pageActivationContext)
     {
-        Defense.notNull(page, "page");
-
-        String pageName = page.getName();
+        // Resolve the page name to its canonical format (the best version for URLs). This also validates
+        // the page name.
 
-        // When override is true, we use the activation context even if empty.
+        String canonical = resolver.canonicalizePageName(pageName);
 
         Object[] context = (override || pageActivationContext.length != 0)
                            ? pageActivationContext
-                           : contextCollector.collectPageActivationContext(page);
+                           : contextCollector.collectPageActivationContext(canonical);
 
         PageRenderRequestParameters parameters =
-                new PageRenderRequestParameters(pageName,
+                new PageRenderRequestParameters(canonical,
                                                 new ArrayEventContext(typeCoercer, context));
 
         Link link = linkFactory.createPageRenderLink(parameters);
@@ -114,14 +115,6 @@
         return link;
     }
 
-    public Link createPageRenderLink(String logicalPageName, boolean override, Object... context)
-    {
-        // This verifies that the page name is valid.
-        Page page = pageCache.get(logicalPageName);
-
-        return createPageRenderLink(page, override, context);
-    }
-
     public LinkCreationHub getLinkCreationHub()
     {
         return this;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MetaDataLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MetaDataLocatorImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MetaDataLocatorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MetaDataLocatorImpl.java Tue Feb 17 15:25:11 2009
@@ -29,14 +29,24 @@
 
     private final TypeCoercer typeCoercer;
 
+    private final ComponentModelSource modelSource;
+
     private final Map<String, Map<String, String>> defaultsByFolder = CollectionFactory.newCaseInsensitiveMap();
 
     private final Map<String, String> cache = CollectionFactory.newConcurrentMap();
 
-    public MetaDataLocatorImpl(SymbolSource symbolSource, TypeCoercer typeCoercer, Map<String, String> configuration)
+    private interface ValueLocator
+    {
+        String valueForKey(String key);
+    }
+
+    public MetaDataLocatorImpl(SymbolSource symbolSource, TypeCoercer typeCoercer, ComponentModelSource modelSource,
+                               Map<String, String> configuration
+    )
     {
         this.symbolSource = symbolSource;
         this.typeCoercer = typeCoercer;
+        this.modelSource = modelSource;
 
         loadDefaults(configuration);
     }
@@ -70,20 +80,43 @@
         }
     }
 
-    public <T> T findMeta(String key, ComponentResources resources, Class<T> expectedType)
+    public <T> T findMeta(String key, final ComponentResources resources, Class<T> expectedType)
     {
-        String value = getSymbolExpandedValueFromCache(key, resources);
+        String value = getSymbolExpandedValueFromCache(key,
+                                                       resources.getCompleteId() + "/" + key,
+                                                       new ValueLocator()
+                                                       {
+                                                           public String valueForKey(String key)
+                                                           {
+                                                               return locate(key, resources);
+                                                           }
+                                                       });
 
         return typeCoercer.coerce(value, expectedType);
     }
 
-    private String getSymbolExpandedValueFromCache(String key, ComponentResources resources)
+    public <T> T findMeta(String key, final String pageName, Class<T> expectedType)
     {
-        String cacheKey = resources.getCompleteId() + "/" + key;
 
-        if (cache.containsKey(cacheKey)) return cache.get(cacheKey);
+        String value = getSymbolExpandedValueFromCache(key,
+                                                       pageName + "/" + key,
+                                                       new ValueLocator()
+                                                       {
+                                                           public String valueForKey(String key)
+                                                           {
+                                                               return modelSource.getPageModel(pageName).getMeta(key);
+                                                           }
+                                                       });
+
+        return typeCoercer.coerce(value, expectedType);
+    }
+
+    private String getSymbolExpandedValueFromCache(String key, String cacheKey, ValueLocator valueLocator)
+    {
+        if (cache.containsKey(cacheKey))
+            return cache.get(cacheKey);
 
-        String value = locate(key, resources);
+        String value = valueLocator.valueForKey(key);
 
         if (value == null)
         {
@@ -111,20 +144,20 @@
 
             ComponentResources next = cursor.getContainerResources();
 
-            if (next == null) return locateInDefaults(key, cursor);
+            if (next == null) return locateInDefaults(key, cursor.getPageName());
 
             cursor = next;
         }
     }
 
-    private String locateInDefaults(String key, ComponentResources pageResources)
+    private String locateInDefaults(String key, String pageName)
     {
 
         // We're going to peel this apart, slash by slash. Thus for
         // "mylib/myfolder/mysubfolder/MyPage" we'll be checking: "mylib/myfolder/mysubfolder",
         // then "mylib/myfolder", then "mylib", then "".
 
-        String path = pageResources.getPageName();
+        String path = pageName;
 
         while (true)
         {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollector.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollector.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollector.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollector.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-//  Copyright 2008 The Apache Software Foundation
+//  Copyright 2008, 2009 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.
@@ -14,8 +14,6 @@
 
 package org.apache.tapestry5.internal.services;
 
-import org.apache.tapestry5.internal.structure.Page;
-
 /**
  * Fires the {@link org.apache.tapestry5.EventConstants#PASSIVATE} event on a page, and collects the result, converting
  * it to an array of objects.
@@ -26,8 +24,8 @@
      * Fires the passivate event and collects the response, which is coerced to an object array. A page that does not
      * have an event handler for the passivate event will return an empty array.
      *
-     * @param page to collect context from
+     * @param pageName to collect context from ; this should be the canonical page name
      * @return the activation context, or an empty array of the page does not provide a context
      */
-    Object[] collectPageActivationContext(Page page);
+    Object[] collectPageActivationContext(String pageName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollectorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollectorImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollectorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageActivationContextCollectorImpl.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-//  Copyright 2008 The Apache Software Foundation
+//  Copyright 2008, 2009 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.
@@ -19,21 +19,64 @@
 import org.apache.tapestry5.internal.structure.ComponentPageElement;
 import org.apache.tapestry5.internal.structure.Page;
 import org.apache.tapestry5.internal.util.Holder;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.services.TypeCoercer;
+import org.apache.tapestry5.model.ComponentModel;
+import org.apache.tapestry5.services.InvalidationListener;
 
-public class PageActivationContextCollectorImpl implements PageActivationContextCollector
+import java.util.Map;
+
+public class PageActivationContextCollectorImpl implements PageActivationContextCollector, InvalidationListener
 {
     private final Object[] EMPTY = new Object[0];
 
     private final TypeCoercer typeCoercer;
 
-    public PageActivationContextCollectorImpl(TypeCoercer typeCoercer)
+    private final ComponentModelSource modelSource;
+
+    private final RequestPageCache requestPageCache;
+
+    /**
+     * Keyed on *canonical* page name, value indicates whether the page has a passivate event handler.
+     */
+    private final Map<String, Boolean> cache = CollectionFactory.newConcurrentMap();
+
+    public PageActivationContextCollectorImpl(TypeCoercer typeCoercer, RequestPageCache requestPageCache,
+                                              ComponentModelSource modelSource)
     {
         this.typeCoercer = typeCoercer;
+        this.requestPageCache = requestPageCache;
+        this.modelSource = modelSource;
     }
 
-    public Object[] collectPageActivationContext(Page page)
+    public void objectWasInvalidated()
     {
+        cache.clear();
+    }
+
+    public Object[] collectPageActivationContext(String pageName)
+    {
+        Boolean hasHandler = cache.get(pageName);
+
+        if (hasHandler == null)
+        {
+            ComponentModel model = modelSource.getPageModel(pageName);
+
+            hasHandler = model.handlesEvent(EventConstants.PASSIVATE);
+
+            cache.put(pageName, hasHandler);
+        }
+
+        // If no handler for the event, then no need to fire the event (and more importantly,
+        // no need to obtain a page instance!)
+
+        if (!hasHandler)
+            return EMPTY;
+
+        // Get or create a page instance and trigger the event.
+
+        Page page = requestPageCache.get(pageName);
+
         ComponentPageElement element = page.getRootElement();
 
         final Holder<Object[]> holder = Holder.create();

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCache.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCache.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCache.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCache.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -30,10 +30,10 @@
      * is used to obtain the page (from the page pool).  Note that under certain circumstances, a page may have multiple
      * names (even beyond simple case-insensitivity), and RequestPageCache caches correctly.
      *
-     * @param logicalPageName the name of the page to retrieve (this is the logical page name, not the fully qualified
-     *                        class name)
+     * @param pageName the name of the page to retrieve (this is the logical page name, not the fully qualified class
+     *                 name)
      * @return a page instance reserved for this request
      * @throws IllegalArgumentException if the name can not be resolved to a page instance
      */
-    Page get(String logicalPageName);
+    Page get(String pageName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -38,11 +38,11 @@
         this.resolver = resolver;
     }
 
-    public Page get(String logicalPageName)
+    public Page get(String pageName)
     {
-        Defense.notNull(logicalPageName, "logicalPageName");
+        Defense.notNull(pageName, "pageName");
 
-        String canonicalName = resolver.canonicalizePageName(logicalPageName);
+        String canonicalName = resolver.canonicalizePageName(pageName);
 
         Page page = cache.get(canonicalName);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManager.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManager.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManager.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManager.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 2009 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.
@@ -14,8 +14,6 @@
 
 package org.apache.tapestry5.internal.services;
 
-import org.apache.tapestry5.internal.structure.Page;
-
 import java.io.IOException;
 
 /**
@@ -40,9 +38,9 @@
      * Determines if the page security does not match the request's security. If so, returns a base URL (to which the
      * context path and servlet path may be appended).
      *
-     * @param page for the security check
+     * @param pageName for the security check
      * @return a base URL when switching security levels, or null if the page's security matches the request security
      * @see org.apache.tapestry5.services.BaseURLSource#getBaseURL(boolean)
      */
-    String getBaseURL(Page page);
+    String getBaseURL(String pageName);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManagerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManagerImpl.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManagerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestSecurityManagerImpl.java Tue Feb 17 15:25:11 2009
@@ -16,7 +16,6 @@
 
 import org.apache.tapestry5.Link;
 import org.apache.tapestry5.MetaDataConstants;
-import org.apache.tapestry5.internal.structure.Page;
 import org.apache.tapestry5.services.BaseURLSource;
 import org.apache.tapestry5.services.MetaDataLocator;
 import org.apache.tapestry5.services.Request;
@@ -36,48 +35,41 @@
 
     private final BaseURLSource baseURLSource;
 
-    private final RequestPageCache requestPageCache;
-
     public RequestSecurityManagerImpl(Request request, Response response, LinkSource linkSource,
-                                      MetaDataLocator locator, BaseURLSource baseURLSource,
-                                      RequestPageCache requestPageCache)
+                                      MetaDataLocator locator, BaseURLSource baseURLSource)
     {
         this.request = request;
         this.response = response;
         this.linkSource = linkSource;
         this.locator = locator;
         this.baseURLSource = baseURLSource;
-        this.requestPageCache = requestPageCache;
     }
 
     public boolean checkForInsecureRequest(String pageName) throws IOException
     {
-        // We don't (at this time) redirect from secure to insecure, just form insecure to secure.
+        // We don't (at this time) redirect from secure to insecure, just from insecure to secure.
 
         if (request.isSecure()) return false;
 
-        Page page = requestPageCache.get(pageName);
-
-        if (!isSecure(page)) return false;
+        if (!isSecure(pageName)) return false;
 
         // Page is secure but request is not, so redirect.
 
-        Link link = linkSource.createPageRenderLink(page, false);
+        Link link = linkSource.createPageRenderLink(pageName, false);
 
         response.sendRedirect(link);
 
         return true;
     }
 
-    private boolean isSecure(Page page)
+    private boolean isSecure(String pageName)
     {
-        return locator.findMeta(MetaDataConstants.SECURE_PAGE,
-                                page.getRootComponent().getComponentResources(), Boolean.class);
+        return locator.findMeta(MetaDataConstants.SECURE_PAGE, pageName, Boolean.class);
     }
 
-    public String getBaseURL(Page page)
+    public String getBaseURL(String pageName)
     {
-        boolean securePage = isSecure(page);
+        boolean securePage = isSecure(pageName);
 
         if (securePage == request.isSecure()) return null;
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/OnEventWorker.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -73,7 +73,7 @@
         builder.begin();
 
         for (TransformMethodSignature method : methods)
-            addCodeForMethod(builder, method, transformation);
+            addCodeForMethod(builder, method, transformation, model);
 
         builder.end(); // try
 
@@ -92,7 +92,7 @@
 
 
     private void addCodeForMethod(BodyBuilder builder, TransformMethodSignature method,
-                                  ClassTransformation transformation)
+                                  ClassTransformation transformation, MutableComponentModel model)
     {
         // $1 is the event
 
@@ -129,6 +129,10 @@
         else builder.addln(");");
 
         builder.end();
+
+        // Indicate that the eventType is handled.
+
+        model.addEventHandler(eventType);
     }
 
     private String extractComponentId(TransformMethodSignature method, OnEvent annotation)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageActivationContextWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageActivationContextWorker.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageActivationContextWorker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/PageActivationContextWorker.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2008 The Apache Software Foundation
+// Copyright 2008, 2009 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.
@@ -24,7 +24,9 @@
 import java.util.List;
 
 /**
- * Provides the page activation context handlers.
+ * Provides the page activation context handlers.  This worker must be scheduled before {@link
+ * org.apache.tapestry5.internal.transform.OnEventWorker} in order for the added event handler methods to be properly
+ * picked up and processed.
  *
  * @see org.apache.tapestry5.annotations.PageActivationContext
  */
@@ -49,7 +51,7 @@
                 TransformMethodSignature activate
                         = new TransformMethodSignature(Modifier.PROTECTED | Modifier.FINAL, "void",
                                                        "onActivate",
-                                                       new String[]{fieldType}, null);
+                                                       new String[] { fieldType }, null);
                 transformation.addTransformedMethod(activate, fieldName + " = $1;");
             }
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/ComponentModel.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -154,6 +154,17 @@
      * org.apache.tapestry5.annotations.AfterRender}, etc.).
      *
      * @return set of classes
+     * @since 5.0.19, 5.1.0.0
      */
     Set<Class> getHandledRenderPhases();
+
+    /**
+     * Determines if the component has an event handler for the indicated event name (case insensitive). This includes
+     * handles in the component class itself, or its super-classes, but does not include event handles supplied by
+     * implementation or instance mixins.
+     *
+     * @param eventType name of event to check (case insensitive)
+     * @return true if event handler present
+     */
+    boolean handlesEvent(String eventType);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/model/MutableComponentModel.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -91,7 +91,15 @@
      *
      * @param renderPhase annotation class corresponding to the render phase
      * @see ComponentModel#getHandledRenderPhases()
-     * @since 5.0.19
+     * @since 5.0.19, 5.1.0.0
      */
     void addRenderPhase(Class renderPhase);
+
+    /**
+     * Identifies that the component includes an event handler for the indicated event type.
+     *
+     * @param eventType of handled event
+     * @since 5.1.0.0
+     */
+    void addEventHandler(String eventType);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java Tue Feb 17 15:25:11 2009
@@ -26,7 +26,7 @@
  * <p/>
  * Assets are defined with a domain, and the domain is indicated by a prefix.  The two builtin domains are "context:"
  * (for files inside the web application context) and "classpath:" for files stored on the classpath (typically, inside
- * a JAR, such as a component library).
+ * a JAR, such as a component library). Other domains can be defined via contributions to the AssetSource service.
  * <p/>
  * Since 5.1.0.0, is is preferred that {@link org.apache.tapestry5.services.AssetFactory#createAsset(org.apache.tapestry5.ioc.Resource)}
  * return an instance of {@link org.apache.tapestry5.Asset2}.
@@ -51,11 +51,22 @@
     Asset getAsset(Resource baseResource, String path, Locale locale);
 
     /**
+     * Finds the asset, either on the classpath or (if prefixed), within the indicated domain. The result is not
+     * localized. The underlying Asset may not exist.
+     *
+     * @param path to the resource to provide as an Asset
+     * @return Resource for the path (the Resource may not exist)
+     * @since 5.1.0.0
+     */
+    Resource resourceForPath(String path);
+
+    /**
      * Convienience for finding assets on the classpath.
      *
      * @param path   path to the base resource, relative to classpath root
      * @param locale to localize the resource to
      * @return the asset
+     * @throws RuntimeException if the asset can not be found
      */
     Asset getClasspathAsset(String path, Locale locale);
 
@@ -65,6 +76,7 @@
      * @param path   path relative to the base resource (the context root)
      * @param locale to localize the resource to, or null for the locale for the current request
      * @return the asset
+     * @throws RuntimeException if the asset can not be found
      * @since 5.1.0.0
      */
     Asset getContextAsset(String path, Locale locale);
@@ -72,8 +84,9 @@
     /**
      * Obtains a classpath alias in the current locale (as defined by the {@link ThreadLocale} service).
      *
-     * @param path
+     * @param path relative to the classpath root
      * @return the asset
+     * @throws RuntimeException if the asset can not be found
      */
     Asset getClasspathAsset(String path);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java Tue Feb 17 15:25:11 2009
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009 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.
@@ -39,11 +39,11 @@
      * Converts a logical page name (such as might be encoded into a URL) into a fully qualified class name. The case of
      * the page name is irrelevant.
      *
-     * @param logicalPageName logical page name
+     * @param pageName page name
      * @return fully qualified class name for the page
      * @throws IllegalArgumentException if the name does not match a known page class
      */
-    String resolvePageNameToClassName(String logicalPageName);
+    String resolvePageNameToClassName(String pageName);
 
     /**
      * For a particular path, determines if the path is a logical page name. The check is case insensitive.
@@ -54,13 +54,13 @@
     boolean isPageName(String pageName);
 
     /**
-     * Returns a list of all logical page names, in sorted order.
+     * Returns a list of all  page names, in sorted order.
      */
     List<String> getPageNames();
 
     /**
-     * Converts a fully qualified page class name into a logical class name (often, for inclusion as part of the URI).
-     * This value may later be passed to {@link #resolvePageNameToClassName(String)}.
+     * Converts a fully qualified page class name into a page name (often, for inclusion as part of the URI). This value
+     * may later be passed to {@link #resolvePageNameToClassName(String)}.
      *
      * @param pageClassName fully qualified name of a page class
      * @return equivalent logical page name
@@ -69,8 +69,8 @@
     String resolvePageClassNameToPageName(String pageClassName);
 
     /**
-     * Returns the canonical form of a logical page name. The canonical form uses character case matching the underlying
-     * class name.
+     * Returns the canonical form of a page name. The canonical form uses character case matching the underlying class
+     * name.
      *
      * @throws IllegalArgumentException if the page name does not match a logical page name
      */

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MetaDataLocator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MetaDataLocator.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MetaDataLocator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MetaDataLocator.java Tue Feb 17 15:25:11 2009
@@ -44,4 +44,16 @@
      *                          or as a symbol
      */
     <T> T findMeta(String key, ComponentResources resources, Class<T> expectedType);
+
+    /**
+     * Searches for the value for the corresponding key for a particular page name (the page will <em>not</em> be
+     * loaded).  The value, if located, will have symbols expanded, and will be type coerced to the desired type.
+     *
+     * @param key      the key used to locate the meta data (case insensitive)
+     * @param pageName the name of the page to search
+     * @return the value if found
+     * @throws RuntimeException if the value for the key is not present as meta data of the page, as an override, or as
+     *                          a symbol
+     */
+    <T> T findMeta(String key, String pageName, Class<T> expectedType);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java Tue Feb 17 15:25:11 2009
@@ -804,9 +804,17 @@
      * org.apache.tapestry5.corelib.data.BlankOption} <li> {@link org.apache.tapestry5.ComponentResources} to {@link
      * org.apache.tapestry5.PropertyOverrides} <li>String to {@link org.apache.tapestry5.Renderable} <li>{@link
      * org.apache.tapestry5.Renderable} to {@link org.apache.tapestry5.Block} <li>String to {@link java.text.DateFormat}
-     * <li>{@link org.apache.tapestry5.PrimaryKeyEncoder} to {@link org.apache.tapestry5.ValueEncoder}</ul>
+     * <li>{@link org.apache.tapestry5.PrimaryKeyEncoder} to {@link org.apache.tapestry5.ValueEncoder} <li>String to
+     * {@link org.apache.tapestry5.ioc.Resource} (via {@link org.apache.tapestry5.services.AssetSource#resourceForPath(String)})
+     * </ul>
      */
-    public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration, @Builtin TypeCoercer coercer)
+    public static void contributeTypeCoercer(Configuration<CoercionTuple> configuration,
+
+                                             @Builtin
+                                             TypeCoercer coercer,
+
+                                             @Core
+                                             final AssetSource assetSource)
     {
         add(configuration, ComponentResources.class, PropertyOverrides.class,
             new Coercion<ComponentResources, PropertyOverrides>()
@@ -910,6 +918,15 @@
             }
         });
 
+
+        add(configuration, String.class, Resource.class, new Coercion<String, Resource>()
+        {
+            public Resource coerce(String input)
+            {
+                return assetSource.resourceForPath(input);
+            }
+        });
+
         add(configuration, PrimaryKeyEncoder.class, ValueEncoder.class, new PrimaryKeyEncoder2ValueEncoder(coercer));
     }
 
@@ -1975,7 +1992,7 @@
         configuration.add(SymbolConstants.CHARSET, "UTF-8");
 
         configuration.add(SymbolConstants.APPLICATION_CATALOG,
-                          "WEB-INF/${" + InternalSymbols.APP_NAME + "}.properties");
+                          "context:WEB-INF/${" + InternalSymbols.APP_NAME + "}.properties");
 
         configuration.add(SymbolConstants.EXCEPTION_REPORT_PAGE, "ExceptionReport");
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/PageTester.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/PageTester.java?rev=745118&r1=745117&r2=745118&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/PageTester.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/test/PageTester.java Tue Feb 17 15:25:11 2009
@@ -88,6 +88,10 @@
      */
     public PageTester(String appPackage, String appName, String contextPath, Class... moduleClasses)
     {
+        Defense.notBlank(appPackage, "appPackage");
+        Defense.notBlank(appName, "appName");
+        Defense.notBlank(contextPath, "contextPath");
+
         SymbolProvider provider = new SingleKeySymbolProvider(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM, appPackage);
 
         TapestryAppInitializer initializer = new TapestryAppInitializer(logger, provider, appName,

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BadMixinIdDemo.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BadMixinIdDemo.tml?rev=745118&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BadMixinIdDemo.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/BadMixinIdDemo.tml Tue Feb 17 15:25:11 2009
@@ -0,0 +1,6 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"
+          xmlns:p="tapestry:parameter">
+
+    <t:form unknownmixinid.foo="bar"/>
+
+</t:border>
\ No newline at end of file