You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/12/19 06:31:40 UTC

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

Author: hlship
Date: Tue Dec 18 21:31:31 2007
New Revision: 605435

URL: http://svn.apache.org/viewvc?rev=605435&view=rev
Log:
TAPESTRY-1990: More flexibility for specifying timeouts and other time periods in minutes, seconds, etc. rather than milliseconds

Added:
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/IntermediateType.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/TimePeriod.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/TimePeriodTest.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/CookiesImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceCreator.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/IdAllocator.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/TapestryException.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PipelineBuilder.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/UtilMessages.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/util/UtilStrings.properties
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/util/DefenseTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodIteratorTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodSignatureTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/BodyBuilderTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/CookiesImpl.java Tue Dec 18 21:31:31 2007
@@ -14,7 +14,9 @@
 
 package org.apache.tapestry.internal.services;
 
+import org.apache.tapestry.ioc.annotations.IntermediateType;
 import org.apache.tapestry.ioc.annotations.Symbol;
+import org.apache.tapestry.ioc.util.TimePeriod;
 import org.apache.tapestry.services.Cookies;
 import org.apache.tapestry.services.Request;
 
@@ -33,19 +35,25 @@
 
     private final int _defaultMaxAge;
 
+    /**
+     * @param request
+     * @param cookieSource
+     * @param cookieSink
+     * @param defaultMaxAge default cookie expiration time in milliseconds
+     */
     public CookiesImpl(Request request,
 
                        CookieSource cookieSource,
 
                        CookieSink cookieSink,
 
-                       @Symbol("tapestry.default-cookie-max-age")
-                       int defaultMaxAge)
+                       @Symbol("tapestry.default-cookie-max-age") @IntermediateType(TimePeriod.class)
+                       long defaultMaxAge)
     {
         _request = request;
         _cookieSource = cookieSource;
         _cookieSink = cookieSink;
-        _defaultMaxAge = defaultMaxAge;
+        _defaultMaxAge = (int) (defaultMaxAge / 1000l);
     }
 
     public String readCookieValue(String name)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/services/TapestryModule.java Tue Dec 18 21:31:31 2007
@@ -38,6 +38,7 @@
 import org.apache.tapestry.ioc.internal.util.InternalUtils;
 import org.apache.tapestry.ioc.services.*;
 import org.apache.tapestry.ioc.util.StrategyRegistry;
+import org.apache.tapestry.ioc.util.TimePeriod;
 import org.apache.tapestry.json.JSONObject;
 import org.apache.tapestry.runtime.Component;
 import org.apache.tapestry.runtime.ComponentResourcesAware;
@@ -506,10 +507,11 @@
                                          final RequestExceptionHandler exceptionHandler,
 
                                          // @Inject not needed because its a long, not a String
-                                         @Symbol("tapestry.file-check-interval")
+                                         @Symbol("tapestry.file-check-interval") @IntermediateType(TimePeriod.class)
                                          long checkInterval,
 
                                          @Symbol("tapestry.file-check-update-timeout")
+                                         @IntermediateType(TimePeriod.class)
                                          long updateTimeout,
 
                                          LocalizationSetter localizationSetter)
@@ -1527,13 +1529,13 @@
         // Remember this is request-to-request time, presumably it'll take the developer more than
         // one second to make a change, save it, and switch back to the browser.
 
-        configuration.add("tapestry.file-check-interval", "1000"); // 1 second
-        configuration.add("tapestry.file-check-update-timeout", "50"); // 50 milliseconds
+        configuration.add("tapestry.file-check-interval", "1 s");
+        configuration.add("tapestry.file-check-update-timeout", "50 ms");
 
         // This should be overridden for particular applications.
         configuration.add("tapestry.supported-locales", "en");
 
-        configuration.add("tapestry.default-cookie-max-age", "604800"); // One week
+        configuration.add("tapestry.default-cookie-max-age", "7 d");
 
         configuration.add("tapestry.start-page-name", "start");
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/CookiesImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/CookiesImplTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/CookiesImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/CookiesImplTest.java Tue Dec 18 21:31:31 2007
@@ -42,8 +42,8 @@
         {
             Cookie c = (Cookie) obj;
 
-            return equals(getName(), c.getName()) && equals(getValue(), c.getValue())
-                    && equals(getPath(), c.getPath()) && getMaxAge() == c.getMaxAge();
+            return equals(getName(), c.getName()) && equals(getValue(), c.getValue()) && equals(getPath(),
+                                                                                                c.getPath()) && getMaxAge() == c.getMaxAge();
         }
 
         private boolean equals(Object value, Object other)
@@ -99,14 +99,12 @@
 
     public void test_Match()
     {
-        attempt("fred", "flintstone", new String[]
-                {"barney", "rubble", "fred", "flintstone"});
+        attempt("fred", "flintstone", new String[]{"barney", "rubble", "fred", "flintstone"});
     }
 
     public void test_No_Match()
     {
-        attempt("foo", null, new String[]
-                {"bar", "baz"});
+        attempt("foo", null, new String[]{"bar", "baz"});
     }
 
     public void test_Write_Cookie_Domain()
@@ -131,7 +129,7 @@
                 cookies.add(cookie);
             }
 
-        }, 1000);
+        }, 1000l * 1000l);
     }
 
     public void test_Write_Cookie_With_Max_Age()

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/IntermediateType.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/IntermediateType.java?rev=605435&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/IntermediateType.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/annotations/IntermediateType.java Tue Dec 18 21:31:31 2007
@@ -0,0 +1,37 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc.annotations;
+
+import java.lang.annotation.*;
+
+
+/**
+ * Used to guide Tapestry when coercing from a raw type to a field or parameter type, by forcing
+ * Tapestry to coerce to the intermediate type.  This was introduced to allow coercion from
+ * string to a time period (in milliseconds) via {@link org.apache.tapestry.ioc.util.TimePeriod}.
+ *
+ * @see org.apache.tapestry.ioc.annotations.Value
+ * @see org.apache.tapestry.ioc.annotations.Symbol
+ */
+@Target({ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface IntermediateType
+{
+    /**
+     * The intermediate to coerce through.
+     */
+    Class value();
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/OrIdMatcher.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.internal;
 
 import org.apache.tapestry.ioc.IdMatcher;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceCreator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceCreator.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceCreator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/PerThreadServiceCreator.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 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.
+
 /**
  *
  */

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProvider.java Tue Dec 18 21:31:31 2007
@@ -17,6 +17,7 @@
 import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.annotations.IntermediateType;
 import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.ioc.services.Builtin;
 import org.apache.tapestry.ioc.services.SymbolSource;
@@ -31,26 +32,27 @@
 
     private final TypeCoercer _typeCoercer;
 
-    public SymbolObjectProvider(@Builtin
-    SymbolSource symbolSource,
+    public SymbolObjectProvider(@Builtin SymbolSource symbolSource,
 
-                                @Builtin
-                                TypeCoercer typeCoercer)
+                                @Builtin TypeCoercer typeCoercer)
     {
         _symbolSource = symbolSource;
         _typeCoercer = typeCoercer;
     }
 
-    public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider,
-                         ObjectLocator locator)
+    public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider, ObjectLocator locator)
     {
         Symbol annotation = annotationProvider.getAnnotation(Symbol.class);
 
         if (annotation == null) return null;
 
-        String symbolValue = _symbolSource.valueForSymbol(annotation.value());
+        Object value = _symbolSource.valueForSymbol(annotation.value());
 
-        return _typeCoercer.coerce(symbolValue, objectType);
+        IntermediateType it = annotationProvider.getAnnotation(IntermediateType.class);
+
+        if (it != null) value = _typeCoercer.coerce(value, it.value());
+
+        return _typeCoercer.coerce(value, objectType);
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/services/ValueObjectProvider.java Tue Dec 18 21:31:31 2007
@@ -17,6 +17,7 @@
 import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.annotations.IntermediateType;
 import org.apache.tapestry.ioc.annotations.Value;
 import org.apache.tapestry.ioc.services.Builtin;
 import org.apache.tapestry.ioc.services.SymbolSource;
@@ -24,7 +25,9 @@
 
 /**
  * Provides an object when the {@link Value} annotation is present. The string value has symbols
- * expanded, and then is {@link TypeCoercer coerced} to the associated type.
+ * expanded, and then is {@link TypeCoercer coerced} to the associated type.   The value
+ * may first be coerced to an intermediate type if
+ * the {@link IntermediateType} annotation is present.
  */
 public class ValueObjectProvider implements ObjectProvider
 {
@@ -47,7 +50,11 @@
         if (annotation == null) return null;
 
         String value = annotation.value();
-        String expanded = _symbolSource.expandSymbols(value);
+        Object expanded = _symbolSource.expandSymbols(value);
+
+        IntermediateType intermediate = annotationProvider.getAnnotation(IntermediateType.class);
+
+        if (intermediate != null) expanded = _typeCoercer.coerce(expanded, intermediate.value());
 
         return _typeCoercer.coerce(expanded, objectType);
     }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/IdAllocator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/IdAllocator.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/IdAllocator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/IdAllocator.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// Copyright 2004, 2005, 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 2004, 2005, 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.internal.util;
 
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/TapestryException.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/TapestryException.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/TapestryException.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/internal/util/TapestryException.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.internal.util;
 
 import org.apache.tapestry.ioc.Locatable;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PipelineBuilder.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PipelineBuilder.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PipelineBuilder.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/PipelineBuilder.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// Copyright 2006, 2007 The Apache Software Foundation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// 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, 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.services;
 
 import org.slf4j.Logger;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/services/TapestryIOCModule.java Tue Dec 18 21:31:31 2007
@@ -19,6 +19,7 @@
 import org.apache.tapestry.ioc.annotations.Marker;
 import org.apache.tapestry.ioc.annotations.Value;
 import org.apache.tapestry.ioc.internal.services.*;
+import org.apache.tapestry.ioc.util.TimePeriod;
 import org.apache.tapestry.services.MasterObjectProvider;
 
 import java.io.File;
@@ -75,8 +76,8 @@
     /**
      * Contributes the "perthread" scope.
      */
-    public void contributeServiceLifecycleSource(
-            MappedConfiguration<String, ServiceLifecycle> configuration, ObjectLocator locator)
+    public void contributeServiceLifecycleSource(MappedConfiguration<String, ServiceLifecycle> configuration,
+                                                 ObjectLocator locator)
     {
         configuration.add(PERTHREAD_SCOPE, locator.autobuild(PerThreadServiceLifecycle.class));
     }
@@ -88,10 +89,9 @@
      * Contributes "Value", which injects values (not services) triggered by the {@link Value}
      * annotation.
      */
-    public static void contributeMasterObjectProvider(
-            OrderedConfiguration<ObjectProvider> configuration,
+    public static void contributeMasterObjectProvider(OrderedConfiguration<ObjectProvider> configuration,
 
-            ObjectLocator locator)
+                                                      ObjectLocator locator)
     {
         configuration.add("Value", locator.autobuild(ValueObjectProvider.class));
         configuration.add("Symbol", locator.autobuild(SymbolObjectProvider.class));
@@ -128,6 +128,8 @@
      * <li>Null to BigDecimal (zero)</li>
      * <li>Null to BigInteger (zero)</li>
      * <li>String to File</li>
+     * <li>String to {@link org.apache.tapestry.ioc.util.TimePeriod}</li>
+     * <li>{@link org.apache.tapestry.ioc.util.TimePeriod} to Long</li>
      * </ul>
      * <p/>
      * The coercion of String to Long, BigInteger, Double and BigDecimal causes some minor headaches
@@ -386,10 +388,26 @@
                 return new File(input);
             }
         });
+
+        add(configuration, String.class, TimePeriod.class, new Coercion<String, TimePeriod>()
+        {
+            public TimePeriod coerce(String input)
+            {
+                return new TimePeriod(input);
+            }
+        });
+
+        add(configuration, TimePeriod.class, Long.class, new Coercion<TimePeriod, Long>()
+        {
+            public Long coerce(TimePeriod input)
+            {
+                return input.milliseconds();
+            }
+        });
     }
 
-    private static <S, T> void add(Configuration<CoercionTuple> configuration, Class<S> sourceType,
-                                   Class<T> targetType, Coercion<S, T> coercion)
+    private static <S, T> void add(Configuration<CoercionTuple> configuration, Class<S> sourceType, Class<T> targetType,
+                                   Coercion<S, T> coercion)
     {
         CoercionTuple<S, T> tuple = new CoercionTuple<S, T>(sourceType, targetType, coercion);
 
@@ -397,11 +415,9 @@
     }
 
     public static void contributeSymbolSource(OrderedConfiguration<SymbolProvider> configuration,
-                                              @ApplicationDefaults
-                                              SymbolProvider applicationDefaults,
+                                              @ApplicationDefaults SymbolProvider applicationDefaults,
 
-                                              @FactoryDefaults
-                                              SymbolProvider factoryDefaults)
+                                              @FactoryDefaults SymbolProvider factoryDefaults)
     {
         configuration.add("SystemProperties", new SystemPropertiesSymbolProvider());
         configuration.add("ApplicationDefaults", applicationDefaults, "after:SystemProperties");

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/test/IOCTestCase.java Tue Dec 18 21:31:31 2007
@@ -15,6 +15,7 @@
 package org.apache.tapestry.ioc.test;
 
 import org.apache.tapestry.ioc.*;
+import org.apache.tapestry.ioc.annotations.IntermediateType;
 import org.apache.tapestry.ioc.def.ContributionDef;
 import org.apache.tapestry.ioc.def.DecoratorDef;
 import org.apache.tapestry.ioc.def.ModuleDef;
@@ -359,5 +360,15 @@
     protected final MasterObjectProvider mockMasterObjectProvider()
     {
         return newMock(MasterObjectProvider.class);
+    }
+
+    protected final void train_value(IntermediateType it, Class value)
+    {
+        expect(it.value()).andReturn(value);
+    }
+
+    protected final IntermediateType newIntermediateType()
+    {
+        return newMock(IntermediateType.class);
     }
 }

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/TimePeriod.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/TimePeriod.java?rev=605435&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/TimePeriod.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/TimePeriod.java Tue Dec 18 21:31:31 2007
@@ -0,0 +1,151 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc.util;
+
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Used to represent a period of time, specifically as a configuration value. This is often
+ * used to specify timeouts.
+ * <p/>
+ * TimePeriods are parsed from strings.
+ * <p/>
+ * The string specifys a number of terms. The values of all the terms are summed together to form
+ * the total time period. Each term consists of a number followed by a unit.
+ * Units (from largest to smallest) are:
+ * <dl>
+ * <dt>d <dd>day
+ * <dt>h <dd>hour
+ * <dt>m <dd>minute
+ * <dt>s <dd>second
+ * <dt>ms <dd>millisecond
+ * </dl>
+ * <p>  Example: "2 h 30 m". By convention, terms are specified largest to smallest.  A term without a unit is assumed to be milliseconds.  Units are case insensitive ("h" or "H"
+ * are treated the same).
+ */
+public class TimePeriod
+{
+    private static final Map<String, Long> UNITS = CollectionFactory.newCaseInsensitiveMap();
+
+    private static final long MILLISECOND = 1000l;
+
+    static
+    {
+        UNITS.put("ms", 1l);
+        UNITS.put("s", MILLISECOND);
+        UNITS.put("m", 60 * MILLISECOND);
+        UNITS.put("h", 60 * 60 * MILLISECOND);
+        UNITS.put("d", 24 * 60 * 60 * MILLISECOND);
+    }
+
+    private static final Pattern PATTERN = Pattern.compile("\\s*(\\d+)\\s*([a-z]*)", Pattern.CASE_INSENSITIVE);
+
+    private final long _milliseconds;
+
+    /**
+     * Creates a TimePeriod for a string.
+     *
+     * @param input the string specifying the amount of time in the period
+     */
+    public TimePeriod(String input)
+    {
+        _milliseconds = parseMilliseconds(input);
+    }
+
+    public long milliseconds()
+    {
+        return _milliseconds;
+    }
+
+    public long seconds()
+    {
+        return _milliseconds / MILLISECOND;
+    }
+
+    static long parseMilliseconds(String input)
+    {
+        long milliseconds = 0l;
+
+        Matcher matcher = PATTERN.matcher(input);
+
+        matcher.useAnchoringBounds(true);
+
+        // TODO: Notice non matching characters and reject input, including at end
+
+        int lastMatchEnd = -1;
+
+        while (matcher.find())
+        {
+            int start = matcher.start();
+
+            if (lastMatchEnd + 1 < start)
+            {
+                String invalid = input.substring(lastMatchEnd + 1, start);
+                throw new RuntimeException(UtilMessages.invalidTimePeriodInput(invalid, input));
+            }
+
+            lastMatchEnd = matcher.end();
+
+            long count = Long.parseLong(matcher.group(1));
+            String units = matcher.group(2);
+
+            if (units.length() == 0)
+            {
+                milliseconds += count;
+                continue;
+            }
+
+            Long unitValue = UNITS.get(units);
+
+            if (unitValue == null)
+                throw new RuntimeException(UtilMessages.invalidTimePeriodUnit(units, input, UNITS.keySet()));
+
+            milliseconds += count * unitValue;
+        }
+
+        if (lastMatchEnd + 1 < input.length())
+        {
+            String invalid = input.substring(lastMatchEnd + 1);
+            throw new RuntimeException(UtilMessages.invalidTimePeriodInput(invalid, input));
+        }
+
+        return milliseconds;
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.format("TimePeriod[%d ms]", _milliseconds);
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (obj == null) return false;
+
+        if (obj instanceof TimePeriod)
+        {
+            TimePeriod tp = (TimePeriod) obj;
+
+            return _milliseconds == tp._milliseconds;
+        }
+
+        return false;
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/UtilMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/UtilMessages.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/UtilMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/UtilMessages.java Tue Dec 18 21:31:31 2007
@@ -33,15 +33,22 @@
 
     static String noStrategyAdapter(Class inputType, Class adapterType, Collection<String> catalog)
     {
-        return MESSAGES.format(
-                "no-strategy-adapter",
-                inputType.getName(),
-                adapterType.getName(),
-                InternalUtils.joinSorted(catalog));
+        return MESSAGES.format("no-strategy-adapter", inputType.getName(), adapterType.getName(),
+                               InternalUtils.joinSorted(catalog));
     }
 
     static String stackIsEmpty()
     {
         return MESSAGES.get("stack-is-empty");
+    }
+
+    static String invalidTimePeriodUnit(String unit, String input, Collection<String> units)
+    {
+        return MESSAGES.format("invalid-time-period-unit", unit, input, InternalUtils.joinSorted(units));
+    }
+
+    static String invalidTimePeriodInput(String invalid, String input)
+    {
+        return MESSAGES.format("invalid-time-period-input", invalid, input);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/internal/util/UtilStrings.properties Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-# 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 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.
+
 dependency-cycle=Unable to add '%s' as a dependency of '%s', as that forms a dependency cycle ('%<s' depends on itself via '%1$s'). The dependency has been ignored.
 duplicate-orderer=Could not add object with duplicate id '%s'.  The duplicate object has been ignored.
 constraint-format=Could not parse ordering constraint '%s' (for '%s'). The constraint has been ignored.

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/util/UtilStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/util/UtilStrings.properties?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/util/UtilStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/resources/org/apache/tapestry/ioc/util/UtilStrings.properties Tue Dec 18 21:31:31 2007
@@ -14,3 +14,5 @@
 
 no-strategy-adapter=No adapter from type %s to type %s is available (registered types are %s).
 stack-is-empty=Stack is empty.
+invalid-time-period-unit=Unknown time period unit '%s' (in '%s').  Defined units: %s.
+invalid-time-period-input=Unexpected string '%s' (in time period '%s').
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/SymbolObjectProviderTest.java Tue Dec 18 21:31:31 2007
@@ -17,12 +17,15 @@
 import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
 import org.apache.tapestry.ioc.ObjectProvider;
+import org.apache.tapestry.ioc.annotations.IntermediateType;
 import org.apache.tapestry.ioc.annotations.Symbol;
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.ioc.test.IOCTestCase;
 import org.testng.annotations.Test;
 
+import java.math.BigInteger;
+
 public class SymbolObjectProviderTest extends IOCTestCase
 {
     @Test
@@ -51,14 +54,13 @@
         TypeCoercer coercer = mockTypeCoercer();
         AnnotationProvider annotationProvider = mockAnnotationProvider();
         ObjectLocator locator = mockObjectLocator();
-        Symbol annotation = newMock(Symbol.class);
         String symbolName = "example-symbol";
         String symbolValue = "symbol-value";
         Long coercedValue = 123l;
+        Symbol annotation = newSymbol(symbolName);
 
         train_getAnnotation(annotationProvider, Symbol.class, annotation);
-
-        expect(annotation.value()).andReturn(symbolName);
+        train_getAnnotation(annotationProvider, IntermediateType.class, null);
 
         train_valueForSymbol(source, symbolName, symbolValue);
 
@@ -73,8 +75,48 @@
         verify();
     }
 
-    protected final void train_valueForSymbol(SymbolSource source, String symbolName,
-                                              String symbolValue)
+    @Test
+    public void intermediate_type()
+    {
+        SymbolSource source = mockSymbolSource();
+        TypeCoercer coercer = mockTypeCoercer();
+        AnnotationProvider annotationProvider = mockAnnotationProvider();
+        ObjectLocator locator = mockObjectLocator();
+        String symbolName = "example-symbol";
+        String symbolValue = "symbol-value";
+        Long coercedValue = 123l;
+        Symbol annotation = newSymbol(symbolName);
+        IntermediateType it = newIntermediateType();
+        BigInteger intervalue = new BigInteger("123");
+
+        train_getAnnotation(annotationProvider, Symbol.class, annotation);
+        train_getAnnotation(annotationProvider, IntermediateType.class, it);
+
+        train_valueForSymbol(source, symbolName, symbolValue);
+
+        expect(it.value()).andReturn(BigInteger.class);
+
+        train_coerce(coercer, symbolValue, BigInteger.class, intervalue);
+        train_coerce(coercer, intervalue, Long.class, coercedValue);
+
+        replay();
+
+        ObjectProvider provider = new SymbolObjectProvider(source, coercer);
+
+        assertSame(provider.provide(Long.class, annotationProvider, locator), coercedValue);
+
+        verify();
+
+    }
+
+    private Symbol newSymbol(String symbolName)
+    {
+        Symbol annotation = newMock(Symbol.class);
+        expect(annotation.value()).andReturn(symbolName);
+        return annotation;
+    }
+
+    protected final void train_valueForSymbol(SymbolSource source, String symbolName, String symbolValue)
     {
         expect(source.valueForSymbol(symbolName)).andReturn(symbolValue);
     }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java Tue Dec 18 21:31:31 2007
@@ -16,6 +16,7 @@
 
 import org.apache.tapestry.ioc.internal.IOCInternalTestCase;
 import org.apache.tapestry.ioc.services.TypeCoercer;
+import org.apache.tapestry.ioc.util.TimePeriod;
 import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
@@ -139,64 +140,50 @@
         Float floatValue = new Float(31.14);
         byte byte1 = 12, byte2 = 56;
         short short1 = 34, short2 = 98;
-        return new Object[][]
-                {
-                        // There's a lot of these!
-
-                        {this, String.class, toString()},
-                        {55l, Integer.class, 55},
-                        {"", Boolean.class, false},
-                        {"  ", Boolean.class, false},
-                        {"x", Boolean.class, true},
-                        {" z ", Boolean.class, true},
-                        {"false", Boolean.class, false},
-                        {"  False ", Boolean.class, false},
-                        {null, Boolean.class, false},
-                        {new Double(256), Integer.class, new Integer(256)},
-                        {new Double(22.7), Integer.class, new Integer(22)},
-                        {new Integer(0), Boolean.class, false},
-                        {new Long(32838), Boolean.class, true},
-                        {new Integer(127), Byte.class, new Byte("127")},
-                        {new Double(58), Short.class, new Short("58")},
-                        {new Integer(33), Long.class, new Long(33)},
-                        {new Integer(22), Float.class, new Float(22)},
-                        {new Integer(1234), Double.class, new Double(1234)},
-                        {floatValue, Double.class, floatValue.doubleValue()},
-                        {Collections.EMPTY_LIST, Boolean.class, false},
-                        {Collections.singleton(this), Boolean.class, true},
-                        {bigDecimalValue, BigDecimal.class, new BigDecimal(bigDecimalValue)},
-                        {new BigDecimal(bigDecimalValue), Double.class, 1.2345656748352436E49},
-                        {bigIntegerValue, BigInteger.class, new BigInteger(bigIntegerValue)},
-                        {new BigInteger("12345678"), Long.class, 12345678l},
-                        {-12345678l, BigInteger.class, new BigInteger("-12345678")},
-                        {object, List.class, Collections.singletonList(object)},
-                        {null, Iterable.class, null},
-                        {null, List.class, null},
-                        {null, Collection.class, null},
-                        {null, String.class, null},
-                        {new Object[]{"a", 123}, List.class, Arrays.asList("a", 123)},
-                        {new String[]{"a", "b"}, List.class, Arrays.asList("a", "b")},
-                        {new byte[]{byte1, byte2}, List.class, Arrays.asList(byte1, byte2)},
-                        {new short[]{short1, short2}, List.class, Arrays.asList(short1, short2)},
-                        {new int[]{1, 2}, List.class, Arrays.asList(1, 2)},
-                        {new long[]{123L, 321L}, List.class, Arrays.asList(123L, 321L)},
-                        {new float[]{3.4f, 7.777f}, List.class, Arrays.asList(3.4f, 7.777f)},
-                        {new double[]{3.4, 7.777}, List.class, Arrays.asList(3.4, 7.777)},
-                        {new char[]{'a', 'b'}, List.class, Arrays.asList('a', 'b')},
-                        {new boolean[]{true, false}, List.class, Arrays.asList(true, false)},
-
-                        {"foo/bar/baz.txt", File.class, new File("foo/bar/baz.txt")},
-
-                        {null, Long.class, 0l},
-                        {null, Short.class, (short) 0},
-                        {null, Byte.class, (byte) 0},
-                        {null, BigDecimal.class, BigDecimal.ZERO},
-                        {null, Float.class, 0f},
-                        {null, BigInteger.class, BigInteger.ZERO},
+        return new Object[][]{
+                // There's a lot of these!
 
-                        // null to arbitrary object is still null
+                {this, String.class, toString()}, {55l, Integer.class, 55}, {"", Boolean.class, false},
+                {"  ", Boolean.class, false}, {"x", Boolean.class, true}, {" z ", Boolean.class, true},
+                {"false", Boolean.class, false}, {"  False ", Boolean.class, false}, {null, Boolean.class, false},
+                {new Double(256), Integer.class, new Integer(256)}, {new Double(22.7), Integer.class, new Integer(22)},
+                {new Integer(0), Boolean.class, false}, {new Long(32838), Boolean.class, true},
+                {new Integer(127), Byte.class, new Byte("127")}, {new Double(58), Short.class, new Short("58")},
+                {new Integer(33), Long.class, new Long(33)}, {new Integer(22), Float.class, new Float(22)},
+                {new Integer(1234), Double.class, new Double(1234)},
+                {floatValue, Double.class, floatValue.doubleValue()}, {Collections.EMPTY_LIST, Boolean.class, false},
+                {Collections.singleton(this), Boolean.class, true},
+                {bigDecimalValue, BigDecimal.class, new BigDecimal(bigDecimalValue)},
+                {new BigDecimal(bigDecimalValue), Double.class, 1.2345656748352436E49},
+                {bigIntegerValue, BigInteger.class, new BigInteger(bigIntegerValue)},
+                {new BigInteger("12345678"), Long.class, 12345678l},
+                {-12345678l, BigInteger.class, new BigInteger("-12345678")},
+                {object, List.class, Collections.singletonList(object)}, {null, Iterable.class, null},
+                {null, List.class, null}, {null, Collection.class, null}, {null, String.class, null},
+                {new Object[]{"a", 123}, List.class, Arrays.asList("a", 123)},
+                {new String[]{"a", "b"}, List.class, Arrays.asList("a", "b")},
+                {new byte[]{byte1, byte2}, List.class, Arrays.asList(byte1, byte2)},
+                {new short[]{short1, short2}, List.class, Arrays.asList(short1, short2)},
+                {new int[]{1, 2}, List.class, Arrays.asList(1, 2)},
+                {new long[]{123L, 321L}, List.class, Arrays.asList(123L, 321L)},
+                {new float[]{3.4f, 7.777f}, List.class, Arrays.asList(3.4f, 7.777f)},
+                {new double[]{3.4, 7.777}, List.class, Arrays.asList(3.4, 7.777)},
+                {new char[]{'a', 'b'}, List.class, Arrays.asList('a', 'b')},
+                {new boolean[]{true, false}, List.class, Arrays.asList(true, false)},
+
+                {"foo/bar/baz.txt", File.class, new File("foo/bar/baz.txt")},
+
+
+                {new TimePeriod("2 h"), Long.class, 2 * 60 * 60 * 1000l},
+                {"2 h", TimePeriod.class, new TimePeriod("120 m")},
+
+                {null, Long.class, 0l}, {null, Short.class, (short) 0}, {null, Byte.class, (byte) 0},
+                {null, BigDecimal.class, BigDecimal.ZERO}, {null, Float.class, 0f},
+                {null, BigInteger.class, BigInteger.ZERO},
 
-                        {null, XMLReader.class, null}};
+                // null to arbitrary object is still null
+
+                {null, XMLReader.class, null}};
     }
 
     @Test(dataProvider = "explain_inputs")
@@ -208,18 +195,14 @@
     @DataProvider(name = "explain_inputs")
     public Object[][] explain_inputs()
     {
-        return new Object[][]
-                {
-                        {StringBuffer.class, Integer.class,
-                         "Object --> String, String --> Long, Long --> Integer"},
-                        {void.class, Map.class, "null --> null"},
-                        {void.class, Boolean.class, "null --> Boolean"},
-                        {String[].class, List.class, "Object[] --> java.util.List"},
-                        {Float.class, Double.class, "Float --> Double"},
-                        {Double.class, BigDecimal.class,
-                         "Object --> String, String --> java.math.BigDecimal"},
+        return new Object[][]{
+                {StringBuffer.class, Integer.class, "Object --> String, String --> Long, Long --> Integer"},
+                {void.class, Map.class, "null --> null"}, {void.class, Boolean.class, "null --> Boolean"},
+                {String[].class, List.class, "Object[] --> java.util.List"},
+                {Float.class, Double.class, "Float --> Double"},
+                {Double.class, BigDecimal.class, "Object --> String, String --> java.math.BigDecimal"},
 
-                };
+        };
     }
 
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/services/ValueObjectProviderTest.java Tue Dec 18 21:31:31 2007
@@ -16,12 +16,15 @@
 
 import org.apache.tapestry.ioc.AnnotationProvider;
 import org.apache.tapestry.ioc.ObjectLocator;
+import org.apache.tapestry.ioc.annotations.IntermediateType;
 import org.apache.tapestry.ioc.annotations.Value;
 import org.apache.tapestry.ioc.services.SymbolSource;
 import org.apache.tapestry.ioc.services.TypeCoercer;
 import org.apache.tapestry.ioc.test.IOCTestCase;
 import org.testng.annotations.Test;
 
+import java.math.BigDecimal;
+
 public class ValueObjectProviderTest extends IOCTestCase
 {
     @Test
@@ -53,11 +56,11 @@
         String annotationValue = "${foo}";
         String expanded = "Foo";
         Runnable coerced = mockRunnable();
-        Value annotation = newMock(Value.class);
+        Value annotation = newValue(annotationValue);
 
         train_getAnnotation(annotationProvider, Value.class, annotation);
 
-        expect(annotation.value()).andReturn(annotationValue);
+        train_getAnnotation(annotationProvider, IntermediateType.class, null);
 
         train_expandSymbols(symbolSource, annotationValue, expanded);
         train_coerce(coercer, expanded, Runnable.class, coerced);
@@ -70,4 +73,48 @@
 
         verify();
     }
+
+    @Test
+    public void intermediate_type()
+    {
+        SymbolSource symbolSource = mockSymbolSource();
+        TypeCoercer coercer = mockTypeCoercer();
+        AnnotationProvider annotationProvider = mockAnnotationProvider();
+        ObjectLocator locator = mockObjectLocator();
+        String annotationValue = "${foo}";
+        String expanded = "Foo";
+        Runnable coerced = mockRunnable();
+        Value annotation = newValue(annotationValue);
+        IntermediateType it = newIntermediateType();
+        BigDecimal intervalue = new BigDecimal("1234");
+
+        train_getAnnotation(annotationProvider, Value.class, annotation);
+
+        train_getAnnotation(annotationProvider, IntermediateType.class, it);
+
+        train_value(it, BigDecimal.class);
+
+        train_expandSymbols(symbolSource, annotationValue, expanded);
+        train_coerce(coercer, expanded, BigDecimal.class, intervalue);
+        train_coerce(coercer, intervalue, Runnable.class, coerced);
+
+        replay();
+
+        ValueObjectProvider provider = new ValueObjectProvider(symbolSource, coercer);
+
+        assertSame(provider.provide(Runnable.class, annotationProvider, locator), coerced);
+
+        verify();
+    }
+
+    private Value newValue(String value)
+    {
+        Value annotation = newMock(Value.class);
+
+        expect(annotation.value()).andReturn(value);
+
+        return annotation;
+    }
+
+
 }

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/util/DefenseTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/util/DefenseTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/util/DefenseTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/internal/util/DefenseTest.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.internal.util;
 
 import static org.apache.tapestry.ioc.internal.util.Defense.*;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodIteratorTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodIteratorTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodIteratorTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodIteratorTest.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.services;
 
 import org.apache.tapestry.ioc.test.IOCTestCase;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodSignatureTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodSignatureTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodSignatureTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/services/MethodSignatureTest.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.services;
 
 import org.apache.tapestry.ioc.test.IOCTestCase;

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/BodyBuilderTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/BodyBuilderTest.java?rev=605435&r1=605434&r2=605435&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/BodyBuilderTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/BodyBuilderTest.java Tue Dec 18 21:31:31 2007
@@ -1,17 +1,17 @@
-// 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 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package org.apache.tapestry.ioc.util;
 
 import org.apache.tapestry.ioc.test.IOCTestCase;

Added: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/TimePeriodTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/TimePeriodTest.java?rev=605435&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/TimePeriodTest.java (added)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/TimePeriodTest.java Tue Dec 18 21:31:31 2007
@@ -0,0 +1,100 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.ioc.util;
+
+import org.apache.tapestry.ioc.test.TestBase;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class TimePeriodTest extends TestBase
+{
+    @Test
+    public void use_constructor()
+    {
+        TimePeriod p = new TimePeriod("30 s");
+
+        assertEquals(p.seconds(), 30);
+        assertEquals(p.milliseconds(), 30 * 1000);
+
+        assertEquals(p.toString(), "TimePeriod[30000 ms]");
+    }
+
+    @Test
+    public void invalid_units()
+    {
+        try
+        {
+            TimePeriod.parseMilliseconds("30s 500mz");
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(ex.getMessage(),
+                         "Unknown time period unit 'mz' (in '30s 500mz').  Defined units: d, h, m, ms, s.");
+        }
+    }
+
+    @Test
+    public void unrecognized_input()
+    {
+        try
+        {
+            TimePeriod.parseMilliseconds("30s z 500ms");
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(ex.getMessage(), "Unexpected string 'z' (in time period '30s z 500ms').");
+        }
+    }
+
+    @Test
+    public void unrecognized_input_at_end()
+    {
+        try
+        {
+            TimePeriod.parseMilliseconds("30s  500ms xyz");
+            unreachable();
+        }
+        catch (RuntimeException ex)
+        {
+            assertEquals(ex.getMessage(), "Unexpected string 'xyz' (in time period '30s  500ms xyz').");
+        }
+    }
+
+    @Test(dataProvider = "mix_of_units_data")
+    public void mix_of_units(String input, long expected)
+    {
+        assertEquals(TimePeriod.parseMilliseconds(input), expected);
+    }
+
+    @DataProvider(name = "mix_of_units_data")
+    public Object[][] mix_of_units_data()
+    {
+        return new Object[][]{{"54321", 54321},
+
+                              {"30s", 30 * 1000},
+
+                              {"1h 30m", 90 * 60 * 1000},
+
+                              {"2d", 2 * 24 * 60 * 60 * 1000},
+
+                              {"2m", 2 * 60 * 1000},
+
+                              {"23ms", 23}
+
+        };
+    }
+}