From commitsnelsonholly@example.com Sat Aug 02 13:49:32 2008 Return-Path: <commitsnelsonholly@example.com> Delivered-To: nelsonholly@example.com Received: (qmail 42072 invoked from network); 2 Aug 2008 13:49:32 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (83.161.120.155) by minotaur.apache.org with SMTP; 2 Aug 2008 13:49:32 -0000 Received: (qmail 9873 invoked by uid 500); 2 Aug 2008 13:49:31 -0000 Delivered-To: nelsonholly@example.com Received: (qmail 9843 invoked by uid 500); 2 Aug 2008 13:49:31 -0000 Mailing-List: contact nelsonholly@example.com; run by ezmlm Precedence: bulk List-Help: <mailto:nelsonholly@example.com> List-Unsubscribe: <mailto:nelsonholly@example.com> List-Post: <mailto:nelsonholly@example.com> List-Id: <commits.tapestry.apache.org> Reply-To: nelsonholly@example.com Delivered-To: mailing list nelsonholly@example.com Received: (qmail 9833 invoked by uid 99); 2 Aug 2008 13:49:31 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 02 Aug 2008 06:49:31 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 02 Aug 2008 13:48:43 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 87E492388961; Sat, 2 Aug 2008 06:49:10 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r681975 - in /tapestry/tapestry5/trunk: src/site/ src/site/apt/cookbook/ tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ tapestry-core/src/main/java/org/apache/tapestry5/internal/test/ tapestry-core/src/main/java/org/apa... Date: Sat, 02 Aug 2008 13:49:09 -0000 To: nelsonholly@example.com From: nelsonholly@example.com X-Mailer: svnmailer-1.0.8 Message-Id: <nelsonholly@example.com> X-Virus-Checked: Checked by ClamAV on apache.org Author: hlship Date: Sat Aug 2 06:49:08 2008 New Revision: 681975 URL: http://svn.apache.org/viewvc?rev=681975&view=rev Log: TAPESTRY-2550: Allow Tapestry to bind a service interface to a ServiceBuilder callback to create the service Added: tapestry/tapestry5/trunk/src/site/apt/cookbook/exceptions.apt tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBuilder.java tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ServiceBuilderModule.java Modified: tapestry/tapestry5/trunk/src/site/site.xml tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MarkupWriterFactoryImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageDocumentGeneratorImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/test/TestableMarkupWriterFactoryImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MarkupWriterFactory.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBinder.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/service.apt tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java Added: tapestry/tapestry5/trunk/src/site/apt/cookbook/exceptions.apt URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/cookbook/exceptions.apt?rev=681975&view=auto ============================================================================== --- tapestry/tapestry5/trunk/src/site/apt/cookbook/exceptions.apt (added) +++ tapestry/tapestry5/trunk/src/site/apt/cookbook/exceptions.apt Sat Aug 2 06:49:08 2008 @@ -0,0 +1,279 @@ + --- + Overriding Exception Reporting + --- + +Overriding Exception Reporting + + One of Tapestry's best features is its comprehensive exception reporting. The level of detail is impressive + and useful. + + Of course, one of the first questions anyone asks is "How do I turn it off?" This exception reporting + is very helpful for developers but its easy to see it as terrifying for potential users. Not that you'd have have + runtime exceptions in production, of course, but even so ... + +Version 1: Replacing the Exception Report Page + + Let's start with a page that fires an exception from an event handler method. + + <<Index.tml>> + +---- +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> + <head> + <title>Index</title> + </head> + <body> + <p> + <t:actionlink t:id="fail">click for exception</t:actionlink> + </p> + </body> +</html> +---- + + <<Index.java>> + +---- +package com.example.tapestry2523.pages; + +public class Index +{ + void onActionFromFail() + { + throw new RuntimeException("Failure inside action event handler."); + } +} +---- + + With production mode disabled, clicking the link displays the default exception report page: + +[error1.png] Default exception report + + The easy way to override the exception report is to provide an ExceptionReport page that overrides the one + provided with the framework. + + This is as easy as providing a page named "ExceptionReport". It must implement the + {{{../apidocs/org/apache/tapestry5/services/ExceptionReporter.html}ExceptionReporter}} interface. + + + <<ExceptionReport.tml>> + +---- +<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"> + <head> + <title>Exception</title> + </head> + + <body> + + <p>An exception has occurred: + <strong>${exception.message}</strong> + </p> + + <p> + Click + <t:pagelink page="index">here</t:pagelink> + to restart. + </p> + + </body> + +</html> +---- + + <<ExceptionReport.java>> + +---- +package com.example.tapestry2523.pages; + +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.services.ExceptionReporter; + +public class ExceptionReport implements ExceptionReporter +{ + @Property + private Throwable exception; + + public void reportException(Throwable exception) + { + this.exception = exception; + } +} +---- + + The end result is a customized exception report page. + +[error2.png] Customized Exception Report Page + + +Version 2: Overriding the RequestExceptionHandler + + The previous example will display a link back to the Index page of the application. + Another alternative is to display the error <on> the Index page. This requires a different + approach: overriding the service responsible for reporting request exceptions. + + The service + {{{../apidocs/org/apache/tapestry5/services/RequestExceptionHandler.html}RequestExceptionHandler}} + is responsible for this. + + By replacing the default implementation of this service with our own implementation, we can take + control over exactly what happens when a request exception occurs. + + We'll do this in two steps. First, we'll extend the Index page to serve as an ExceptionReporter. + Second, we'll override the default RequestExceptionHandler to use the Index page instead + of the ExceptionReport page. Of course, this is just one approach. + + <<Index.tml>> (partial) + +---- + <t:if test="message"> + <p> + An unexpected exception has occurred: + <strong>${message}</strong> + </p> + </t:if> +---- + + <<Index.java>> + +---- +public class Index implements ExceptionReporter +{ + @Property + @Persist(PersistenceConstants.FLASH) + private String message; + + public void reportException(Throwable exception) + { + message = exception.getMessage(); + } + + void onActionFromFail() + { + throw new RuntimeException("Failure inside action event handler."); + } +} +---- + + The above defines a new property, message, on the Index page. The @Persist + annotation indicates that values assigned to the field will persist from one + request to another. The use of FLASH for the persistence strategy indicates + that the value will be used until the next time the page renders, then the value + will be discarded. + + The message property is set from the thrown runtime exception. + + The remaining changes take place inside AppModule. + + <<AppModule.java>> (partial) + +---- + public RequestExceptionHandler buildAppRequestExceptionHandler( + final Logger logger, + final ResponseRenderer renderer, + final ComponentSource componentSource) + { + return new RequestExceptionHandler() + { + public void handleRequestException(Throwable exception) throws IOException + { + logger.error("Unexpected runtime exception: " + exception.getMessage(), exception); + + ExceptionReporter index = (ExceptionReporter) componentSource.getPage("Index"); + + index.reportException(exception); + + renderer.renderPageMarkupResponse("Index"); + } + }; + } + + public void contributeAlias( + Configuration<AliasContribution> configuration, + + @InjectService("AppRequestExceptionHandler") + RequestExceptionHandler handler) + { + configuration.add(AliasContribution.create(RequestExceptionHandler.class, handler)); + } +---- + + First we define the new service using a service builder method. This is an alternative + to the bind() method; we define the service, its interface type (the return type of the method) + and the service id (the part that follows "build" is the method name) and provide the implementation + inline. A service builder method must return the service implementation, here implemented as an inner class. + + The Logger resource that is passed into the builder method is the Logger appropriate for the service. + ResponseRenderer and ComponentSource are two services defined by Tapestry. + + With this in place, there are now two different services that implement the RequestExceptionHandler interface: + the default one built into Tapestry (whose service id is "RequestExceptionHandler") and the new one defined + in this module, "AppRequestExceptionHandler"). Without a little more work, Tapestry will be unable to determine + which one to use when an exception does occur. + + The contributeAlias() method makes a contribution to the Alias service's configuration. The Alias service + is used to disambiguate injections when just a service interface is given; one service will become the "Alias", hiding the + existence of the others. + + Here we inject the AppRequestExceptionHandler service and contribute it as the alias for type RequestExceptionHandler. + + This finally brings us to the point where we can see the result: + +[error3.png] Errors show on Index page + + +Version 3: Decorating the RequestExceptionHandler + + A third option is available: we don't define a <new> service, but instead <decorate> the existing + RequestExceptionHandler service. This approach means we don't have to make a contribution to the Alias service. + + Service decoration is a powerful facility of Tapestry that is generally used to "wrap" an existing service in + an interceptor that provides new functionality such as logging, security, transaction management or other cross-cutting + concerns. + + However, there's no requirement that an interceptor for a service actually invoke methods on the service; here + we contribute a new implementation that <replaces> the original: + + <<AppModule.java>> + +---- + public RequestExceptionHandler decorateRequestExceptionHandler( + final Logger logger, + final ResponseRenderer renderer, + final ComponentSource componentSource, + @Symbol(SymbolConstants.PRODUCTION_MODE) + boolean productionMode, + Object service) + { + if (!productionMode) return null; + + return new RequestExceptionHandler() + { + public void handleRequestException(Throwable exception) throws IOException + { + logger.error("Unexpected runtime exception: " + exception.getMessage(), exception); + + ExceptionReporter index = (ExceptionReporter) componentSource.getPage("Index"); + + index.reportException(exception); + + renderer.renderPageMarkupResponse("Index"); + } + }; + } +---- + + As with service builder methods and service configuration method, decorator methods are recognized + by the "decorate" prefix on the method name. As used here, the rest of the method name is used + to identify the service to be decorated (there are other options that allow a decorator to be applied + to many different services). + + A change in this version is that when in development mode (that is, when <not> in production mode) we use + the normal implementation. Returning null from a service decoration method indicates that the decorator + chooses not to decorate. + + The Logger injected here is the Logger for the service being decorated, the default RequestExceptionHandler service. + + Otherwise, we return an interceptor whose implementation is the same as the new service in version #2. + + The end result is that in development mode we get the full exception report, and in production mode we + get an abbreviated message on the application's Index page. Modified: tapestry/tapestry5/trunk/src/site/site.xml URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/site.xml?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/src/site/site.xml (original) +++ tapestry/tapestry5/trunk/src/site/site.xml Sat Aug 2 06:49:08 2008 @@ -69,6 +69,7 @@ <item name="Introduction" href="cookbook/"/> <item name="Supporting Informal Parameters" href="cookbook/informals.html"/> <item name="Default Parameter" href="cookbook/defaultparameter.html"/> + <item name="Exception Reporting" href="cookbook/exceptions.html"/> </menu> <menu name="Tapestry 5 Maven Support"> Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MarkupWriterFactoryImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MarkupWriterFactoryImpl.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MarkupWriterFactoryImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/MarkupWriterFactoryImpl.java Sat Aug 2 06:49:08 2008 @@ -20,14 +20,25 @@ import org.apache.tapestry5.dom.MarkupModel; import org.apache.tapestry5.dom.XMLMarkupModel; import org.apache.tapestry5.internal.InternalConstants; +import org.apache.tapestry5.internal.structure.Page; import org.apache.tapestry5.services.MarkupWriterFactory; public class MarkupWriterFactoryImpl implements MarkupWriterFactory { + private final PageContentTypeAnalyzer analyzer; + + private final RequestPageCache cache; + private final MarkupModel htmlModel = new DefaultMarkupModel(); private final MarkupModel xmlModel = new XMLMarkupModel(); + public MarkupWriterFactoryImpl(PageContentTypeAnalyzer analyzer, RequestPageCache cache) + { + this.analyzer = analyzer; + this.cache = cache; + } + public MarkupWriter newMarkupWriter(ContentType contentType) { boolean isHTML = contentType.getMimeType().equalsIgnoreCase("text/html"); @@ -40,4 +51,13 @@ return new MarkupWriterImpl(model, contentType.getParameter(InternalConstants.CHARSET_CONTENT_TYPE_PARAMETER)); } + public MarkupWriter newMarkupWriter(String pageName) + { + Page page = cache.get(pageName); + + ContentType contentType = analyzer.findContentType(page); + + return newMarkupWriter(contentType); + } + } Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageDocumentGeneratorImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageDocumentGeneratorImpl.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageDocumentGeneratorImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageDocumentGeneratorImpl.java Sat Aug 2 06:49:08 2008 @@ -14,7 +14,6 @@ package org.apache.tapestry5.internal.services; -import org.apache.tapestry5.ContentType; import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.dom.Document; import org.apache.tapestry5.internal.InternalConstants; @@ -31,17 +30,14 @@ private final MarkupWriterFactory markupWriterFactory; - private final PageContentTypeAnalyzer pageContentTypeAnalyzer; - private final Request request; public PageDocumentGeneratorImpl(RequestPageCache pageCache, PageMarkupRenderer markupRenderer, MarkupWriterFactory markupWriterFactory, - PageContentTypeAnalyzer pageContentTypeAnalyzer, Request request) + Request request) { this.markupRenderer = markupRenderer; this.markupWriterFactory = markupWriterFactory; - this.pageContentTypeAnalyzer = pageContentTypeAnalyzer; this.pageCache = pageCache; this.request = request; } @@ -50,9 +46,7 @@ { Page page = pageCache.get(logicalPageName); - ContentType contentType = pageContentTypeAnalyzer.findContentType(page); - - MarkupWriter writer = markupWriterFactory.newMarkupWriter(contentType); + MarkupWriter writer = markupWriterFactory.newMarkupWriter(logicalPageName); // value will almost certainly be null, unless a page that is being rendered to a document // itself decides to render another page to a document. Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/test/TestableMarkupWriterFactoryImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/test/TestableMarkupWriterFactoryImpl.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/test/TestableMarkupWriterFactoryImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/test/TestableMarkupWriterFactoryImpl.java Sat Aug 2 06:49:08 2008 @@ -1,4 +1,4 @@ -// Copyright 2007 The Apache Software Foundation +// Copyright 2007, 2008 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. @@ -43,10 +43,20 @@ public MarkupWriter newMarkupWriter(ContentType contentType) { - MarkupWriter result = delegate.newMarkupWriter(contentType); + return save(delegate.newMarkupWriter(contentType)); + } - lastCreated = result; + public MarkupWriter newMarkupWriter(String pageName) + { + return save(delegate.newMarkupWriter(pageName)); + } - return result; + private MarkupWriter save(MarkupWriter writer) + { + lastCreated = writer; + + return writer; } + + } Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MarkupWriterFactory.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MarkupWriterFactory.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MarkupWriterFactory.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/MarkupWriterFactory.java Sat Aug 2 06:49:08 2008 @@ -1,4 +1,4 @@ -// Copyright 2006, 2007 The Apache Software Foundation +// Copyright 2006, 2007, 2008 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,4 +30,12 @@ * the backs the markup writer. */ MarkupWriter newMarkupWriter(ContentType contentType); + + /** + * Obtains a markup writer that will render the content for the provided logical page name. + * + * @param pageName logical page name + * @return writer configured for the page + */ + MarkupWriter newMarkupWriter(String pageName); } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBinder.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBinder.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBinder.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBinder.java Sat Aug 2 06:49:08 2008 @@ -1,4 +1,4 @@ -// Copyright 2007 The Apache Software Foundation +// Copyright 2007, 2008 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. @@ -31,12 +31,22 @@ * fully on first reference (ignoring its scope, if any) and will not be decorated. * * @param <T> - * @param implementationClass - * @return + * @param implementationClass class to instantiate as the service + * @return binding options, used to specify additional details about the service */ <T> ServiceBindingOptions bind(Class<T> implementationClass); /** + * Alternative implementation that supports a callback to build the service, rather than instantiating a particular + * class. + * + * @param serviceInterface interface implemented by the service + * @param builder constructs the core service implementation + * @return binding options, used to specify additional details about the service + */ + <T> ServiceBindingOptions bind(Class<T> serviceInterface, ServiceBuilder<T> builder); + + /** * Binds the service interface to a service implementation class. The default service name is the unqualified name * of the service interface. The default service scope is "singleton", unless the service implementation class * includes the {@link Scope} annotation. @@ -44,7 +54,7 @@ * @param <T> * @param serviceInterface service interface (used when locating services, and when building proxies) * @param serviceImplementation implementation class that implements the service interface - * @return binding options, used to specify additional details about the service. + * @return binding options, used to specify additional details about the service */ <T> ServiceBindingOptions bind(Class<T> serviceInterface, Class<? extends T> serviceImplementation); Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBuilder.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBuilder.java?rev=681975&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBuilder.java (added) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/ServiceBuilder.java Sat Aug 2 06:49:08 2008 @@ -0,0 +1,29 @@ +// Copyright 2008 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.tapestry5.ioc; + +/** + * A callback used to create a service implementation. + */ +public interface ServiceBuilder<T> +{ + /** + * Construct the service. A non-null object that implements the service interface must be returned. + * + * @param resources used to lookup dependencies or access resources + * @return the core service implementation + */ + T buildService(ServiceResources resources); +} Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImpl.java Sat Aug 2 06:49:08 2008 @@ -247,7 +247,7 @@ // TODO: Validate constraints here? - String[] patterns = match == null ? new String[] { decoratorId } : match.value(); + String[] patterns = match == null ? new String[]{decoratorId} : match.value(); DecoratorDef def = new DecoratorDefImpl(decoratorId, method, patterns, constraints, classFactory); @@ -385,7 +385,7 @@ return; } - ServiceBinderImpl binder = new ServiceBinderImpl(this, classFactory, defaultMarkers); + ServiceBinderImpl binder = new ServiceBinderImpl(this, bindMethod, classFactory, defaultMarkers); bindMethod.invoke(null, binder); Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ServiceBinderImpl.java Sat Aug 2 06:49:08 2008 @@ -1,4 +1,4 @@ -// Copyright 2007 The Apache Software Foundation +// Copyright 2007, 2008 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. @@ -20,6 +20,7 @@ import org.apache.tapestry5.ioc.annotations.Scope; import org.apache.tapestry5.ioc.def.ServiceDef; import org.apache.tapestry5.ioc.internal.util.CollectionFactory; +import org.apache.tapestry5.ioc.internal.util.Defense; import static org.apache.tapestry5.ioc.internal.util.Defense.notBlank; import static org.apache.tapestry5.ioc.internal.util.Defense.notNull; import org.apache.tapestry5.ioc.internal.util.InternalUtils; @@ -28,6 +29,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; +import java.lang.reflect.Method; import java.util.Arrays; import java.util.Set; @@ -35,15 +37,20 @@ { private final OneShotLock lock = new OneShotLock(); + private final Method bindMethod; + private final ServiceDefAccumulator accumulator; private final ClassFactory classFactory; private final Set<Class> defaultMarkers; - public ServiceBinderImpl(ServiceDefAccumulator accumulator, ClassFactory classFactory, Set<Class> defaultMarkers) + public ServiceBinderImpl(ServiceDefAccumulator accumulator, Method bindMethod, + ClassFactory classFactory, + Set<Class> defaultMarkers) { this.accumulator = accumulator; + this.bindMethod = bindMethod; this.classFactory = classFactory; this.defaultMarkers = defaultMarkers; } @@ -52,9 +59,11 @@ private Class serviceInterface; + private Class serviceImplementation; + private final Set<Class> markers = CollectionFactory.newSet(); - private Class serviceImplementation; + private ObjectCreatorSource source; private boolean eagerLoad; @@ -71,20 +80,11 @@ { if (serviceInterface == null) return; - final Constructor constructor = findConstructor(); + // source will be null when the implementation class is provided; non-null when using + // a ServiceBuilder callback - ObjectCreatorSource source = new ObjectCreatorSource() - { - public ObjectCreator constructCreator(ServiceBuilderResources resources) - { - return new ConstructorServiceCreator(resources, getDescription(), constructor); - } - - public String getDescription() - { - return classFactory.getConstructorLocation(constructor).toString(); - } - }; + if (source == null) + source = createObjectCreatorSourceFromImplementationClass(); // Combine service-specific markers with those inherited form the module. Set<Class> markers = CollectionFactory.newSet(defaultMarkers); @@ -96,31 +96,43 @@ serviceId = null; serviceInterface = null; - this.markers.clear(); serviceImplementation = null; + source = null; + this.markers.clear(); eagerLoad = false; scope = null; } - private Constructor findConstructor() + private ObjectCreatorSource createObjectCreatorSourceFromImplementationClass() { - Constructor result = InternalUtils.findAutobuildConstructor(serviceImplementation); + final Constructor constructor = InternalUtils.findAutobuildConstructor(serviceImplementation); - if (result == null) throw new RuntimeException(IOCMessages - .noConstructor(serviceImplementation, serviceId)); + if (constructor == null) + throw new RuntimeException(IOCMessages.noConstructor(serviceImplementation, serviceId)); - return result; + return new ObjectCreatorSource() + { + public ObjectCreator constructCreator(ServiceBuilderResources resources) + { + return new ConstructorServiceCreator(resources, getDescription(), constructor); + } + + public String getDescription() + { + return classFactory.getConstructorLocation(constructor).toString(); + } + }; } public <T> ServiceBindingOptions bind(Class<T> serviceClass) { - if(serviceClass.isInterface()) + if (serviceClass.isInterface()) { try { - Class<T> implementationClass = (Class<T>) Class.forName(serviceClass.getName()+"Impl"); - - if(!implementationClass.isInterface() && serviceClass.isAssignableFrom(implementationClass)) + Class<T> implementationClass = (Class<T>) Class.forName(serviceClass.getName() + "Impl"); + + if (!implementationClass.isInterface() && serviceClass.isAssignableFrom(implementationClass)) { return bind(serviceClass, implementationClass); } @@ -131,9 +143,46 @@ throw new RuntimeException(IOCMessages.noConventionServiceImplementationFound(serviceClass)); } } + return bind(serviceClass, serviceClass); } + public <T> ServiceBindingOptions bind(Class<T> serviceInterface, final ServiceBuilder<T> builder) + { + Defense.notNull(serviceInterface, "serviceInterface"); + Defense.notNull(builder, "builder"); + + lock.check(); + + flush(); + + this.serviceInterface = serviceInterface; + this.scope = IOCConstants.DEFAULT_SCOPE; + + serviceId = serviceInterface.getSimpleName(); + + this.source = new ObjectCreatorSource() + { + public ObjectCreator constructCreator(final ServiceBuilderResources resources) + { + return new ObjectCreator() + { + public Object createObject() + { + return builder.buildService(resources); + } + }; + } + + public String getDescription() + { + return classFactory.getMethodLocation(bindMethod).toString(); + } + }; + + return this; + } + public <T> ServiceBindingOptions bind(Class<T> serviceInterface, Class<? extends T> serviceImplementation) { notNull(serviceInterface, "serviceIterface"); @@ -144,6 +193,7 @@ flush(); this.serviceInterface = serviceInterface; + this.serviceImplementation = serviceImplementation; // Set defaults for the other properties. Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/service.apt URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/service.apt?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/service.apt (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/site/apt/service.apt Sat Aug 2 06:49:08 2008 @@ -109,8 +109,8 @@ addition, inspired by the terseness of the {{{http://code.google.com/p/google-guice/}Guice}} IoC container. - Following the convention over configuration principle the autobuilding of services can be done even less verbose. - If a service interface is passed as a single argument to the bind() method Tapestry will try to find an implementation in the + Following the convention over configuration principle, the autobuilding of services can be even less verbose. + If a service interface is passed as a single argument to the bind() method, Tapestry will try to find an implementation in the same package whose name matches the name of the service interface followed by the suffix <Impl>. +------+ @@ -590,7 +590,15 @@ Here, the alertEmail parameter will recieve the configured alerts email (see {{{symbols.html}the symbols documentation}} for more about this syntax) rather than the service id. - + +Binding ServiceBuilders + + Yet another option is available: instead of binding an interface to a implemention class, + you can bind a service to a + {{{../apidocs/org/apache/tapestry5/ioc/ServiceBuilder.html}ServiceBuilder}}, a callback used + to create the service implementation. This is very useful in very rare circumstances. + + Builtin Services A few services within the Tapestry IOC Module are "builtin"; there is no Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/IntegrationTest.java Sat Aug 2 06:49:08 2008 @@ -401,7 +401,7 @@ r.shutdown(); } - + @Test public void convention_over_configuration_service() { @@ -409,14 +409,14 @@ StringHolder holder = r.getService(StringHolder.class); - + holder.setValue("Bar"); assertEquals(holder.getValue(), "Bar"); r.shutdown(); } - + @Test public void convention_over_configuration_service_impl_not_found() { @@ -424,12 +424,14 @@ { buildRegistry(ConventionModuleImplementationNotFound.class); unreachable(); - }catch (RuntimeException ex) { + } + catch (RuntimeException ex) + { assertMessageContains(ex, - "No service implements the interface "+StringTransformer.class.getName()+". Please provide"); + "No service implements the interface " + StringTransformer.class.getName() + ". Please provide"); } } - + @Test public void convention_over_configuration_service_wrong_impl_found() { @@ -437,9 +439,11 @@ { buildRegistry(ConventionFailureModule.class); unreachable(); - }catch (RuntimeException ex) { + } + catch (RuntimeException ex) + { assertMessageContains(ex, - "No service implements the interface "+Pingable.class.getName()); + "No service implements the interface " + Pingable.class.getName()); } } @@ -822,4 +826,38 @@ r.shutdown(); } + + @Test + public void bind_to_service_builder() + { + Registry r = buildRegistry(ServiceBuilderModule.class); + + Greeter g = r.getService("Greeter", Greeter.class); + + assertEquals(g.getGreeting(), "Greetings from service Greeter."); + + r.shutdown(); + } + + @Test + public void bind_to_service_binder_that_throws_exception() + { + Registry r = buildRegistry(ServiceBuilderModule.class); + + Greeter g = r.getService("BrokenGreeter", Greeter.class); + + try + { + g.getGreeting(); + unreachable(); + } + catch (Exception ex) + { + assertEquals(ex.getMessage(), + "Exception constructing service 'BrokenGreeter': Failure inside ServiceBuilder callback."); + } + + r.shutdown(); + + } } Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ServiceBuilderModule.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ServiceBuilderModule.java?rev=681975&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ServiceBuilderModule.java (added) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/ServiceBuilderModule.java Sat Aug 2 06:49:08 2008 @@ -0,0 +1,47 @@ +// Copyright 2008 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.tapestry5.ioc; + +/** + * Used to test the functionality related to {@link org.apache.tapestry5.ioc.ServiceBinder#bind(Class, + * ServiceBuilder)}. + */ +public class ServiceBuilderModule +{ + public static void bind(ServiceBinder binder) + { + binder.bind(Greeter.class, new ServiceBuilder<Greeter>() + { + public Greeter buildService(ServiceResources resources) + { + return new Greeter() + { + public String getGreeting() + { + return "Greetings from service Greeter."; + } + }; + } + }); + + binder.bind(Greeter.class, new ServiceBuilder<Greeter>() + { + public Greeter buildService(ServiceResources resources) + { + throw new RuntimeException("Failure inside ServiceBuilder callback."); + } + }).withId("BrokenGreeter"); + } +} Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java?rev=681975&r1=681974&r2=681975&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DefaultModuleDefImplTest.java Sat Aug 2 06:49:08 2008 @@ -1,4 +1,4 @@ -// Copyright 2006, 2007 The Apache Software Foundation +// Copyright 2006, 2007, 2008 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. @@ -384,8 +384,8 @@ } catch (RuntimeException ex) { - assertEquals(ex.getMessage(), - "Class org.apache.tapestry5.ioc.internal.RunnableServiceImpl (implementation of service \'Runnable\') does not contain any public constructors."); + assertMessageContains(ex, + "Class org.apache.tapestry5.ioc.internal.RunnableServiceImpl (implementation of service \'Runnable\') does not contain any public constructors."); } verify(); From commitsnelsonholly@example.com Mon Aug 04 23:57:34 2008 Return-Path: <commitsnelsonholly@example.com> Delivered-To: nelsonholly@example.com Received: (qmail 57755 invoked from network); 4 Aug 2008 23:57:34 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (83.161.120.155) by minotaur.apache.org with SMTP; 4 Aug 2008 23:57:34 -0000 Received: (qmail 92991 invoked by uid 500); 4 Aug 2008 23:57:33 -0000 Delivered-To: nelsonholly@example.com Received: (qmail 92980 invoked by uid 500); 4 Aug 2008 23:57:33 -0000 Mailing-List: contact nelsonholly@example.com; run by ezmlm Precedence: bulk List-Help: <mailto:nelsonholly@example.com> List-Unsubscribe: <mailto:nelsonholly@example.com> List-Post: <mailto:nelsonholly@example.com> List-Id: <commits.tapestry.apache.org> Reply-To: nelsonholly@example.com Delivered-To: mailing list nelsonholly@example.com Received: (qmail 92971 invoked by uid 99); 4 Aug 2008 23:57:33 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Aug 2008 16:57:33 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Aug 2008 23:56:45 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 1B30A2388988; Mon, 4 Aug 2008 16:57:13 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r682544 - in /tapestry/tapestry5/trunk/tapestry-ioc/src: main/java/org/apache/tapestry5/ioc/internal/ test/java/org/apache/tapestry5/ioc/internal/ Date: Mon, 04 Aug 2008 23:57:12 -0000 To: nelsonholly@example.com From: nelsonholly@example.com X-Mailer: svnmailer-1.0.8 Message-Id: <nelsonholly@example.com> X-Virus-Checked: Checked by ClamAV on apache.org Author: hlship Date: Mon Aug 4 16:57:12 2008 New Revision: 682544 URL: http://svn.apache.org/viewvc?rev=682544&view=rev Log: TAPESTRY-2410: Service decorator method not invoked for @Match with "*" in middle Removed: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/MatchType.java Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcher.java tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcherTest.java Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcher.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcher.java?rev=682544&r1=682543&r2=682544&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcher.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcher.java Mon Aug 4 16:57:12 2008 @@ -1,4 +1,4 @@ -// Copyright 2006, 2007 The Apache Software Foundation +// Copyright 2006, 2007, 2008 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,82 +14,41 @@ package org.apache.tapestry5.ioc.internal; -import static org.apache.tapestry5.ioc.internal.MatchType.*; +import java.util.regex.Pattern; +/** + * Used when matching identifiers. In the early days of T5 IoC, matching was based on shell-style glob matches (a '*' + * could represent zero or more characters). But that was limiting so now we check to see if the provided pattern looks + * like a glob (just characters and asterisks, for compatibility with older code) and, if not, we assume it is a regular + * expression. + */ public class GlobPatternMatcher { - private String substring; + private final Pattern pattern; - private MatchType type; + private final static Pattern oldStyleGlob = + Pattern.compile("[a-z\\*]+", Pattern.CASE_INSENSITIVE); public GlobPatternMatcher(String pattern) { - analyze(pattern); + this.pattern = compilePattern(pattern); } - private void analyze(String pattern) + private static Pattern compilePattern(String pattern) { - if (pattern.equals("*")) - { - type = ANY; - return; - } - - boolean globPrefix = pattern.startsWith("*"); - boolean globSuffix = pattern.endsWith("*"); - - if (globPrefix && globSuffix) - { - substring = pattern.substring(1, pattern.length() - 1); - type = INFIX; - return; - } - - if (globPrefix) - { - substring = pattern.substring(1); - type = SUFFIX; - return; - } - - if (globSuffix) - { - substring = pattern.substring(0, pattern.length() - 1); - type = PREFIX; - return; - } - - type = MatchType.EXACT; - substring = pattern; + return Pattern.compile(createRegexpFromGlob(pattern), Pattern.CASE_INSENSITIVE); } - public boolean matches(String input) + private static String createRegexpFromGlob(String pattern) { - switch (type) - { - case ANY: - return true; - - case EXACT: - - return input.equalsIgnoreCase(substring); - - case INFIX: - - return input.toLowerCase().contains(substring.toLowerCase()); - - case PREFIX: - - return input.regionMatches(true, 0, substring, 0, substring.length()); + return oldStyleGlob.matcher(pattern).matches() + ? pattern.replace("*", ".*") + : pattern; + } - default: - return input.regionMatches( - true, - input.length() - substring.length(), - substring, - 0, - substring.length()); - } + public boolean matches(String input) + { + return pattern.matcher(input).matches(); } } Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcherTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcherTest.java?rev=682544&r1=682543&r2=682544&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcherTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/GlobPatternMatcherTest.java Mon Aug 4 16:57:12 2008 @@ -1,80 +1,85 @@ -// Copyright 2006 The Apache Software Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - +// Copyright 2006, 2008 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.tapestry5.ioc.internal; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import org.testng.Assert; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -/** - * - */ -public class GlobPatternMatcherTest +public class GlobPatternMatcherTest extends Assert { private boolean globMatch(String input, String pattern) { return new GlobPatternMatcher(pattern).matches(input); } - @Test - public void glob_match_exact() + @DataProvider(name = "matches") + public Object[][] matches() { - assertTrue(globMatch("fred", "fred")); - assertTrue(globMatch("fred", "FRED")); - assertFalse(globMatch("xfred", "fred")); - assertFalse(globMatch("fredx", "fred")); - assertFalse(globMatch("fred", "xfred")); - assertFalse(globMatch("fred", "fredx")); + return new Object[][] + { + {"fred", "fred"}, + {"fred", "FRED"}, + {"fred", "*"}, + {"", "*"}, + {"fred.Barney", "*Barney"}, + {"fred.Barney", "*BARNEY"}, + {"fred.Barney", "fred*"}, + {"fred.Barney", "FRED*"}, + {"fredBarney", "*dB*"}, + {"fredBarney", "*DB*"}, + {"fred.Barney", "*Barney*"}, + {"fred.Barney", "*fred*"}, + {"fred.Barney", "*FRED*"}, + {"MyEntityDAO", ".*dao"}, + {"FredDAO", "(fred|barney)dao"} + }; + } + + @Test(dataProvider = "matches") + public void successful_glob_match(String input, String pattern) + { + assertTrue(globMatch(input, pattern)); } - @Test - public void glob_match_wild() - { - assertTrue(globMatch("fred", "*")); - assertTrue(globMatch("", "*")); - } - @Test - public void glob_match_prefix() - { - assertTrue(globMatch("fred.Barney", "*Barney")); - assertTrue(globMatch("fred.Barney", "*BARNEY")); - assertFalse(globMatch("fred.Barneyx", "*Barney")); - assertFalse(globMatch("fred.Barney", "*Barneyx")); - assertFalse(globMatch("fred.Barney", "*xBarney")); + @DataProvider(name = "mismatches") + public Object[][] mismatches() + { + return new Object[][] + { + {"xfred", "fred"}, + {"fredx", "fred"}, + {"fred", "xfred"}, + {"fred", "fredx"}, + {"fred.Barneyx", "*Barney"}, + {"fred.Barney", "*Barneyx"}, + {"fred.Barney", "*xBarney"}, + {"xfred.Barney", "fred*"}, + {"fred.Barney", "fredx*"}, + {"fred.Barney", "xfred*"}, + {"fred.Barney", "*flint*"}, + {"MyEntityDAL", ".*dao"}, + {"WilmaDAO", "(fred|barney)dao"} + }; } - @Test - public void glob_match_suffix() - { - assertTrue(globMatch("fred.Barney", "fred*")); - assertTrue(globMatch("fred.Barney", "FRED*")); - assertFalse(globMatch("xfred.Barney", "fred*")); - assertFalse(globMatch("fred.Barney", "fredx*")); - assertFalse(globMatch("fred.Barney", "xfred*")); - } - @Test - public void glob_match_infix() + @Test(dataProvider = "mismatches") + public void unsuccessful_glob_match(String input, String pattern) { - assertTrue(globMatch("fred.Barney", "*d.B*")); - assertTrue(globMatch("fred.Barney", "*D.B*")); - assertTrue(globMatch("fred.Barney", "*Barney*")); - assertTrue(globMatch("fred.Barney", "*fred*")); - assertTrue(globMatch("fred.Barney", "*FRED*")); - assertFalse(globMatch("fred.Barney", "*flint*")); + assertFalse(globMatch(input, pattern)); } - } From commitsnelsonholly@example.com Tue Aug 05 00:44:25 2008 Return-Path: <commitsnelsonholly@example.com> Delivered-To: nelsonholly@example.com Received: (qmail 96590 invoked from network); 5 Aug 2008 00:44:24 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (83.161.120.155) by minotaur.apache.org with SMTP; 5 Aug 2008 00:44:24 -0000 Received: (qmail 39255 invoked by uid 500); 5 Aug 2008 00:44:23 -0000 Delivered-To: nelsonholly@example.com Received: (qmail 39221 invoked by uid 500); 5 Aug 2008 00:44:23 -0000 Mailing-List: contact nelsonholly@example.com; run by ezmlm Precedence: bulk List-Help: <mailto:nelsonholly@example.com> List-Unsubscribe: <mailto:nelsonholly@example.com> List-Post: <mailto:nelsonholly@example.com> List-Id: <commits.tapestry.apache.org> Reply-To: nelsonholly@example.com Delivered-To: mailing list nelsonholly@example.com Received: (qmail 39209 invoked by uid 99); 5 Aug 2008 00:44:23 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Aug 2008 17:44:23 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Aug 2008 00:43:35 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 75799238899C; Mon, 4 Aug 2008 17:44:02 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r682554 [2/2] - in /tapestry/tapestry5/trunk: src/site/apt/ src/site/apt/cookbook/ src/site/resources/cookbook/ tapestry-core/src/main/java/org/apache/tapestry5/ tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/ tapestry-core/s... Date: Tue, 05 Aug 2008 00:44:00 -0000 To: nelsonholly@example.com From: nelsonholly@example.com X-Mailer: svnmailer-1.0.8 Message-Id: <nelsonholly@example.com> X-Virus-Checked: Checked by ClamAV on apache.org Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/PropertyEditorTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/PropertyEditorTest.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/PropertyEditorTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/PropertyEditorTest.java Mon Aug 4 17:43:59 2008 @@ -1,4 +1,4 @@ -// Copyright 2007 The Apache Software Foundation +// Copyright 2007, 2008 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,6 +15,7 @@ package org.apache.tapestry5.corelib.components; import org.apache.tapestry5.ComponentResources; +import org.apache.tapestry5.PropertyOverrides; import org.apache.tapestry5.beaneditor.PropertyModel; import org.apache.tapestry5.ioc.Location; import org.apache.tapestry5.ioc.Messages; @@ -33,7 +34,7 @@ public void no_editor_block_available() { PropertyModel model = mockPropertyModel(); - ComponentResources overrides = mockComponentResources(); + PropertyOverrides overrides = mockPropertyOverrides(); ComponentResources resources = mockComponentResources(); BeanBlockSource source = newMock(BeanBlockSource.class); RuntimeException exception = new RuntimeException("Simulated failure."); @@ -48,7 +49,7 @@ expect(model.getId()).andReturn(propertyId); - expect(overrides.getBlockParameter(propertyId)).andReturn(null); + train_getOverrideBlock(overrides, propertyId, null); expect(model.getDataType()).andReturn(dataType); @@ -78,4 +79,5 @@ } } + } Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/AdditionalIntegrationTests.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/AdditionalIntegrationTests.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/AdditionalIntegrationTests.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/AdditionalIntegrationTests.java Mon Aug 4 17:43:59 2008 @@ -48,8 +48,8 @@ { start("BeanDisplay Override Demo"); - assertText("//div[@class='t-beandisplay-value no']", "Nay"); - assertText("//div[@class='t-beandisplay-value yes']", "Yea"); + assertText("//dd[@class='no']", "Nay"); + assertText("//dd[@class='yes']", "Yea"); } /** Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/IntegrationTests.java Mon Aug 4 17:43:59 2008 @@ -1838,9 +1838,9 @@ assertText("activePageName", "music/Details2"); - assertText("//div[@class='t-beandisplay-value title']", "Wake Me Up"); + assertText("//dd[@class='title']", "Wake Me Up"); - assertText("//div[@class='t-beandisplay-value artist']", "Norah Jones"); + assertText("//dd[@class='artist']", "Norah Jones"); } /** @@ -1861,7 +1861,7 @@ clickAndWait(SUBMIT); - assertText("//div[@class='t-beandisplay-value value']", "237"); + assertText("//dd[@class='value']", "237"); } /** Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/AddedGridColumnsDemo.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/AddedGridColumnsDemo.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/AddedGridColumnsDemo.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/AddedGridColumnsDemo.java Mon Aug 4 17:43:59 2008 @@ -14,12 +14,12 @@ package org.apache.tapestry5.integration.app1.pages; -import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.annotations.Component; import org.apache.tapestry5.beaneditor.BeanModel; import org.apache.tapestry5.corelib.components.Grid; import org.apache.tapestry5.integration.app1.data.Track; import org.apache.tapestry5.integration.app1.services.MusicLibrary; +import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.services.BeanModelSource; @@ -27,7 +27,7 @@ public class AddedGridColumnsDemo { - @Component(parameters = { "source=tracks", "row=track", "model=model" }) + @Component(parameters = {"source=tracks", "row=track", "model=model"}) private Grid grid; @Inject @@ -41,10 +41,10 @@ private final BeanModel model; @Inject - private ComponentResources resources; + private Messages messages; { - model = source.create(Track.class, true, resources); + model = source.create(Track.class, true, messages); model.exclude("album", "artist", "genre", "playcount", "rating"); Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SimpleTrackGridDemo.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SimpleTrackGridDemo.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SimpleTrackGridDemo.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SimpleTrackGridDemo.java Mon Aug 4 17:43:59 2008 @@ -1,4 +1,4 @@ -// Copyright 2007 The Apache Software Foundation +// Copyright 2007, 2008 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,11 +14,11 @@ package org.apache.tapestry5.integration.app1.pages; -import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.beaneditor.BeanModel; import org.apache.tapestry5.integration.app1.data.SimpleTrack; import org.apache.tapestry5.integration.app1.data.Track; import org.apache.tapestry5.integration.app1.services.MusicLibrary; +import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.services.BeanModelSource; @@ -33,7 +33,7 @@ private BeanModelSource beanModelSource; @Inject - private ComponentResources resources; + private Messages messages; private SimpleTrack track; @@ -54,6 +54,6 @@ public BeanModel getSimpleTrackModel() { - return beanModelSource.create(SimpleTrack.class, false, resources); + return beanModelSource.create(SimpleTrack.class, false, messages); } } Added: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOverridesImplTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOverridesImplTest.java?rev=682554&view=auto ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOverridesImplTest.java (added) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOverridesImplTest.java Mon Aug 4 17:43:59 2008 @@ -0,0 +1,68 @@ +// Copyright 2008 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.tapestry5.internal; + +import org.apache.tapestry5.Block; +import org.apache.tapestry5.ComponentResources; +import org.apache.tapestry5.PropertyOverrides; +import org.apache.tapestry5.internal.test.InternalBaseTestCase; +import org.apache.tapestry5.ioc.Messages; +import org.testng.annotations.Test; + +public class PropertyOverridesImplTest extends InternalBaseTestCase +{ + @Test + public void block_found() + { + Messages messages = mockMessages(); + ComponentResources resources = mockInternalComponentResources(); + Block block = mockBlock(); + + String name = "alfred"; + + train_getContainerMessages(resources, messages); + + train_getBlockParameter(resources, name, block); + + replay(); + + PropertyOverrides po = new PropertyOverridesImpl(resources); + + assertSame(po.getOverrideBlock(name), block); + + verify(); + } + + @Test + public void block_not_found() + { + Messages messages = mockMessages(); + ComponentResources resources = mockInternalComponentResources(); + + String name = "alfred"; + + train_getContainerMessages(resources, messages); + + train_getBlockParameter(resources, name, null); + + replay(); + + PropertyOverrides po = new PropertyOverridesImpl(resources); + + assertNull(po.getOverrideBlock(name)); + + verify(); + } +} Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/grid/CollectionGridDataSourceTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/grid/CollectionGridDataSourceTest.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/grid/CollectionGridDataSourceTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/grid/CollectionGridDataSourceTest.java Mon Aug 4 17:43:59 2008 @@ -14,7 +14,6 @@ package org.apache.tapestry5.internal.grid; -import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.beaneditor.BeanModel; import org.apache.tapestry5.beaneditor.PropertyModel; import org.apache.tapestry5.grid.ColumnSort; @@ -56,15 +55,13 @@ { BeanModelSource source = getService(BeanModelSource.class); - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - model = source.create(Datum.class, false, resources); + model = source.create(Datum.class, false, messages); verify(); } Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java Mon Aug 4 17:43:59 2008 @@ -14,7 +14,6 @@ package org.apache.tapestry5.internal.services; -import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.PropertyConduit; import org.apache.tapestry5.beaneditor.BeanModel; import org.apache.tapestry5.beaneditor.PropertyModel; @@ -50,15 +49,13 @@ @Test public void default_model_for_bean() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertSame(model.getBeanType(), SimpleBean.class); @@ -107,15 +104,13 @@ @Test public void include_properties() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertSame(model.getBeanType(), SimpleBean.class); @@ -131,13 +126,11 @@ @Test public void add_before() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); PropertyConduit conduit = mockPropertyConduit(); Class propertyType = String.class; - train_getMessages(resources, messages); stub_contains(messages, false); expect(conduit.getPropertyType()).andReturn(propertyType).atLeastOnce(); @@ -145,7 +138,7 @@ replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("firstName", "lastName", "age")); @@ -168,15 +161,13 @@ @Test public void new_instance() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel<SimpleBean> model = source.create(SimpleBean.class, true, resources); + BeanModel<SimpleBean> model = source.create(SimpleBean.class, true, messages); SimpleBean s1 = model.newInstance(); @@ -193,15 +184,13 @@ @Test public void add_before_using_default_conduit() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); model.exclude("firstname"); @@ -222,13 +211,11 @@ @Test public void add_after() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); PropertyConduit conduit = mockPropertyConduit(); Class propertyType = String.class; - train_getMessages(resources, messages); stub_contains(messages, false); expect(conduit.getPropertyType()).andReturn(propertyType).atLeastOnce(); @@ -237,7 +224,7 @@ replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("firstName", "lastName", "age")); @@ -255,19 +242,17 @@ @Test public void filtering_out_read_only_properties() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(ReadOnlyBean.class, true, resources); + BeanModel model = source.create(ReadOnlyBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("value")); - model = source.create(ReadOnlyBean.class, false, resources); + model = source.create(ReadOnlyBean.class, false, messages); assertEquals(model.getPropertyNames(), Arrays.asList("value", "readOnly")); @@ -277,15 +262,13 @@ @Test public void non_text_property() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(EnumBean.class, true, resources); + BeanModel model = source.create(EnumBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("token")); @@ -297,15 +280,13 @@ @Test public void add_duplicate_property_name_is_failure() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); try { @@ -324,15 +305,13 @@ @Test public void unknown_property_name() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); try { @@ -351,15 +330,13 @@ @Test public void unknown_property_id() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); model.add("shrub.foo()", null); @@ -381,15 +358,13 @@ @Test public void get_added_property_by_name() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); PropertyModel pm = model.add("shrub.foo()", null); @@ -401,15 +376,13 @@ @Test public void get_added_property_by_id() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); PropertyModel pm = model.add("shrub.foo()", null); @@ -422,15 +395,13 @@ @Test public void order_via_annotation() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(StoogeBean.class, true, resources); + BeanModel model = source.create(StoogeBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("larry", "moe", "shemp", "curly")); @@ -440,15 +411,13 @@ @Test public void edit_property_label() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources).get("age").label("Decrepitude").model(); + BeanModel model = source.create(SimpleBean.class, true, messages).get("age").label("Decrepitude").model(); assertEquals(model.get("age").getLabel(), "Decrepitude"); @@ -458,10 +427,8 @@ @Test public void label_from_component_messages() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); train_contains(messages, "age-label", true); @@ -469,7 +436,7 @@ replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertEquals(model.get("age").getLabel(), "Decrepitude"); @@ -479,15 +446,13 @@ @Test public void array_type_bean() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(StringArrayBean.class, true, resources); + BeanModel model = source.create(StringArrayBean.class, true, messages); // There's not editor for string arrays yet, so it won't show up normally. @@ -495,7 +460,7 @@ assertSame(propertyModel.getPropertyType(), String[].class); - String[] value = { "foo", "bar" }; + String[] value = {"foo", "bar"}; StringArrayBean bean = new StringArrayBean(); @@ -513,10 +478,8 @@ @Test public void composite_bean() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); train_contains(messages, "simpleage-label", true); @@ -524,7 +487,7 @@ replay(); - BeanModel model = source.create(CompositeBean.class, true, resources); + BeanModel model = source.create(CompositeBean.class, true, messages); // No editor for CompositeBean, so this will be empty. @@ -557,15 +520,13 @@ @Test public void default_properties_exclude_write_only() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(WriteOnlyBean.class, false, resources); + BeanModel model = source.create(WriteOnlyBean.class, false, messages); assertEquals(model.getPropertyNames(), Arrays.asList("readOnly", "readWrite")); @@ -575,15 +536,13 @@ @Test public void add_synthetic_property() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); PropertyModel property = model.add("placeholder", null); @@ -597,15 +556,13 @@ @Test public void exclude_property() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertSame(model.exclude("age"), model); @@ -617,15 +574,13 @@ @Test public void exclude_unknown_property_is_noop() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertSame(model.exclude("frobozz"), model); @@ -637,15 +592,13 @@ @Test public void nonvisual_properties_are_excluded() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(NonVisualBean.class, true, resources); + BeanModel model = source.create(NonVisualBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("name")); @@ -655,15 +608,13 @@ @Test public void reorder() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(SimpleBean.class, true, resources); + BeanModel model = source.create(SimpleBean.class, true, messages); assertSame(model.getBeanType(), SimpleBean.class); @@ -685,15 +636,13 @@ @Test public void reoder_from_annotation() { - ComponentResources resources = mockComponentResources(); Messages messages = mockMessages(); - train_getMessages(resources, messages); stub_contains(messages, false); replay(); - BeanModel model = source.create(PropertyOrderBean.class, true, resources); + BeanModel model = source.create(PropertyOrderBean.class, true, messages); assertEquals(model.getPropertyNames(), Arrays.asList("third", "first", "second")); Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResponseRendererImplTest.java URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResponseRendererImplTest.java?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResponseRendererImplTest.java (original) +++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResponseRendererImplTest.java Mon Aug 4 17:43:59 2008 @@ -20,6 +20,7 @@ import org.apache.tapestry5.internal.test.InternalBaseTestCase; import org.apache.tapestry5.runtime.Component; import org.apache.tapestry5.services.Response; +import org.apache.tapestry5.services.ResponseRenderer; import org.testng.annotations.Test; public class ResponseRendererImplTest extends InternalBaseTestCase From commitsnelsonholly@example.com Tue Aug 05 00:44:36 2008 Return-Path: <commitsnelsonholly@example.com> Delivered-To: nelsonholly@example.com Received: (qmail 96827 invoked from network); 5 Aug 2008 00:44:35 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (83.161.120.155) by minotaur.apache.org with SMTP; 5 Aug 2008 00:44:35 -0000 Received: (qmail 39495 invoked by uid 500); 5 Aug 2008 00:44:34 -0000 Delivered-To: nelsonholly@example.com Received: (qmail 39485 invoked by uid 500); 5 Aug 2008 00:44:34 -0000 Mailing-List: contact nelsonholly@example.com; run by ezmlm Precedence: bulk List-Help: <mailto:nelsonholly@example.com> List-Unsubscribe: <mailto:nelsonholly@example.com> List-Post: <mailto:nelsonholly@example.com> List-Id: <commits.tapestry.apache.org> Reply-To: nelsonholly@example.com Delivered-To: mailing list nelsonholly@example.com Received: (qmail 39476 invoked by uid 99); 5 Aug 2008 00:44:34 -0000 Received: from athena.apache.org (HELO athena.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 04 Aug 2008 17:44:34 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [83.161.120.155] (HELO eris.apache.org) (83.161.120.155) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Aug 2008 00:43:35 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 6BC0B2388988; Mon, 4 Aug 2008 17:44:02 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r682554 [1/2] - in /tapestry/tapestry5/trunk: src/site/apt/ src/site/apt/cookbook/ src/site/resources/cookbook/ tapestry-core/src/main/java/org/apache/tapestry5/ tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/ tapestry-core/s... Date: Tue, 05 Aug 2008 00:44:00 -0000 To: nelsonholly@example.com From: nelsonholly@example.com X-Mailer: svnmailer-1.0.8 Message-Id: <nelsonholly@example.com> X-Virus-Checked: Checked by ClamAV on apache.org Author: hlship Date: Mon Aug 4 17:43:59 2008 New Revision: 682554 URL: http://svn.apache.org/viewvc?rev=682554&view=rev Log: TAPESTRY-2552: Provide easier overrides for Grid, BeanEditor property display & edit blocks Added: tapestry/tapestry5/trunk/src/site/resources/cookbook/ tapestry/tapestry5/trunk/src/site/resources/cookbook/error1.png (with props) tapestry/tapestry5/trunk/src/site/resources/cookbook/error2.png (with props) tapestry/tapestry5/trunk/src/site/resources/cookbook/error3.png (with props) tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/PropertyOverrides.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/PropertyOverridesImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ResponseRenderer.java - copied, changed from r679133, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseRenderer.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/PropertyOverridesImplTest.java Removed: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResponseRenderer.java Modified: tapestry/tapestry5/trunk/src/site/apt/cookbook/index.apt tapestry/tapestry5/trunk/src/site/apt/index.apt tapestry/tapestry5/trunk/src/site/apt/upgrade.apt tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/SymbolConstants.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/base/AbstractPropertyOutput.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanDisplay.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanDisplay.xdoc tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditForm.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/BeanEditor.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/Grid.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridColumns.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/GridRows.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/PropertyEditor.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/mixins/Autocomplete.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ServiceStatus.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BeanModelSourceImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DefaultRequestExceptionHandler.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/ResponseRendererImpl.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/BeanModelSource.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ExceptionReporter.java tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/PageDocumentGenerator.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/TapestryTestCase.java tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/BeanDisplay.tml tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/components/GridRows.tml tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry5/default.css tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/conf.apt tapestry/tapestry5/trunk/tapestry-core/src/site/apt/index.apt tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/BeanEditorTest.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/corelib/components/PropertyEditorTest.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/AdditionalIntegrationTests.java 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/app1/pages/AddedGridColumnsDemo.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/SimpleTrackGridDemo.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/grid/CollectionGridDataSourceTest.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/BeanModelSourceImplTest.java tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ResponseRendererImplTest.java Modified: tapestry/tapestry5/trunk/src/site/apt/cookbook/index.apt URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/cookbook/index.apt?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/src/site/apt/cookbook/index.apt (original) +++ tapestry/tapestry5/trunk/src/site/apt/cookbook/index.apt Mon Aug 4 17:43:59 2008 @@ -4,3 +4,6 @@ The Tapestry Cookbook is a collection of tips and tricks for commonly occuring patterns in Tapestry. + + The cookbook conists of a number of pages; use the standard site navigation (on the left side of the page) + to reach the pages. \ No newline at end of file Modified: tapestry/tapestry5/trunk/src/site/apt/index.apt URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/index.apt?rev=682554&r1=682553&r2=682554&view=diff ============================================================================== --- tapestry/tapestry5/trunk/src/site/apt/index.apt (original) +++ tapestry/tapestry5/trunk/src/site/apt/index.apt Mon Aug 4 17:43:59 2008 @@ -32,28 +32,6 @@ Tapestry is released under the Apache Software Licence 2.0. -Where To Go - - You are currently reading the Tapestry 5 project site. Tapestry itself is broken into several modules: - -*---+---+ -| {{{tapestry-annotations/index.html}tapestry-annotations}} | A few Tapestry annotations that may be used with non-component classes. | -*---+---+ -| {{{tapestry-core/index.html}tapestry-core}} | The core implementation of the Tapestry framework, including all the primary built-in components. | -*---+---+ -| {{{tapestry-hibernate/index.html}tapestry-hibernate}} | Integration with the {{{http://hibernate.org}Hibernate}} Object/Relational Mapping framework. | -*---+---+ -| {{{tapestry-ioc/index.html}tapestry-ioc}} | The Tapestry Inversion of Control Container. | -*---+---+ -| {{{tapestry-spring/index.html}tapestry-spring}} | Integration with {{{http://springframework.org}Spring}}. | -*---+---+ -| {{{tapestry-test/index.html}tapestry-test}} | Tapestry test utilities. | -*---+---+ -| {{{tapestry-upload/index.html}tapestry-upload}} | Tapestry file upload component. | -*---+---+ - - Or, you can start with the {{{screencast.html}screencasts}}, which give you a better idea about how Tapestry fits together. - Roadmap Tapestry is, of course, an open-source project, with all the work coming from unpaid volunteers. That being said, our rough timeline is as follows: @@ -68,8 +46,10 @@ is increasingly stable. Further "stable" with Tapestry usually refers to names of interfaces and methods, not to code quality, which is always very, very high. - * We are now edging towards a release candidate, with most work being documentation, minor bug fixes and modest - enhancements. + * We are now finally edging towards a release candidate, with most work being documentation, minor bug fixes and modest + enhancements. Note that Tapestry team members have been using Tapestry 5 to build production applications, and those + experiences are being applied back to the framework to improve its quality: we're finding rough edges and we're + smoothing them out. [] @@ -102,6 +82,29 @@ | {{{http://code.google.com/p/tapestry5-treegrid/}tapestry5-treegrid}} | Gabriel Landais | Combination tree navigation and data grid, based on sstree. | *--+--+--+ +New And Of Note + + * Work has started on a {{{cookbook}Tapestry Cookbook}}, showing how to tackle common scenarios. + + * Component methods may be marked with the @Log annotation, to enable debug logging of + method entry (with parameters) and exit (with return value, or thrown exception). + + * It is now possible to provide method invocation advice to component methods. This opens up + a very powerful Aspect Oriented Programming approach to Tapestry components. + + * The Exception Report page now identifies the version of the Tapestry framework, and lists + out System properties (including the Java classpath). + + * The {{{tapestry-core/ref/org/apache/tapestry5/corelib/components/Grid.html}Grid}} component can now update itself in place, + using Ajax, when paging or sorting links are clicked. + + * Added a zone parameter to the {{{tapestry-core/ref/org/apache/tapestry5/corelib/components/BeanEditForm.html}BeanEditForm}} + component, to support Ajax updates. + + * The @Cached annotation has been added to allowing the caching of method results. + + [] + What's changed since Tapestry 4? @@ -113,8 +116,7 @@ * Components no longer extend from base classes. * {{{tapestry-core/guide/component-classes.html}Components classes are no longer <abstract>}}. - Components are pure, simple POJOs (<plain old Java - objects>). + Components are pure, simple POJOs (<plain old Java objects>). * Tapestry no longer uses XML page and component specification files. Information that used to be supplied in such files is now supplied directly in the Java class, using Java annotations and naming conventions. @@ -129,56 +131,88
{'source': 'Apache Software Foundation Public Mail Archives'}