You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2007/06/16 23:37:13 UTC

svn commit: r547988 - in /tapestry/tapestry4/trunk: tapestry-framework/src/descriptor/META-INF/ tapestry-framework/src/java/org/apache/tapestry/asset/ tapestry-framework/src/java/org/apache/tapestry/services/ tapestry-framework/src/java/org/apache/tape...

Author: jkuhnert
Date: Sat Jun 16 14:37:12 2007
New Revision: 547988

URL: http://svn.apache.org/viewvc?view=rev&rev=547988
Log:
TAPESTRY-1578.  AssetService was manually parsing out the date header fields instead of using the "built in" getDateHeader() API provided by the servlet container.

Removed:
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/asset/PoolableDateFormatFactory.java
Modified:
    tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.request.xml
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/asset/AssetService.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/WebRequestServicerFilter.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/EngineFactoryImpl.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebRequest.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebResponse.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebRequest.java
    tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebResponse.java
    tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/asset/TestAssetService.java
    tapestry/tapestry4/trunk/tapestry-portlet/src/java/org/apache/tapestry/portlet/PortletWebRequest.java

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.request.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.request.xml?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.request.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/descriptor/META-INF/tapestry.request.xml Sat Jun 16 14:37:12 2007
@@ -16,234 +16,232 @@
 -->
 
 <module id="tapestry.request" version="4.0.0" package="org.apache.tapestry.services">
-  
-  Services and configurations for the Tapestry request processing pipeline.
-  It is expected that the IEngine interface will eventually "dissolve" into
-  a collection of loosely bound services.
-  
-  <service-point id="EnginePool" interface="ObjectPool">
-    
-    Contains engine instances, keyed on locale, ready for use in the current request.
-    
-    <invoke-factory>
-      <construct class="impl.ObjectPoolImpl">
-        <event-listener service-id="tapestry.ResetEventHub"/>
-        <event-listener service-id="tapestry.describe.ReportStatusHub"/>
-      </construct>
-    </invoke-factory> 
-  </service-point>  
-  
-  <service-point id="RequestLocaleManager">
-    
-    Encapsulates the logic for extracting the locale for the current request.
-    
-    <invoke-factory model="pooled">
-      <construct class="impl.RequestLocaleManagerImpl">
-        <set-service property="request" service-id="tapestry.globals.WebRequest"/>
-        <set-object property="cookieSource" value="infrastructure:cookieSource"/>
-        <set-service property="threadLocale" service-id="hivemind.ThreadLocale"/>
-        <set-object property="acceptedLocales" value="app-property:org.apache.tapestry.accepted-locales"/>
-      </construct>
-    </invoke-factory>
-  </service-point>  
-  
-  <contribution configuration-id="hivemind.FactoryDefaults">
-    <default symbol="org.apache.tapestry.accepted-locales" value=""/>
-    <!-- One week, in seconds -->
-    <default symbol="org.apache.tapestry.default-cookie-max-age" value="604800"/>
-  </contribution>
-  
-  <service-point id="CookieSource">
-    
-    Allows access to incoming HTTP cookie values for the active (per-thread) request.
-    
-    <invoke-factory>
-      <construct class="impl.CookieSourceImpl">
-        <set-service property="request" service-id="tapestry.globals.HttpServletRequest"/>
-        <set-service property="response" service-id="tapestry.globals.HttpServletResponse"/>
-        <set property="defaultMaxAge" value="${org.apache.tapestry.default-cookie-max-age}"/>
-      </construct>
-    </invoke-factory>
-  </service-point>  
-  
-  <service-point id="EngineManager">
-    Obtains an IEngine implementation for the current request, either from a pool of
-    such engine instance, from a factory, or from the HttpSession.
-    
-    <invoke-factory>
-      <construct class="impl.EngineManagerImpl">
-        <set-service property="enginePool" service-id="EnginePool"/>
-        <set-service property="engineFactory" service-id="EngineFactory"/>
-        <set-service property="localeManager" service-id="RequestLocaleManager"/>
-      </construct>
-    </invoke-factory>
-  </service-point>  
-  
-  <service-point id="EngineFactory">
-    
-    Responsible for creating new instances of IEngine as needed.
-    
-    <invoke-factory>
-      <construct class="impl.EngineFactoryImpl">
-        <set-object property="applicationSpecification" value="infrastructure:applicationSpecification"/>
-        <set-object property="defaultEngineClassName" value="global-property:org.apache.tapestry.engine-class"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>  
-  
-  <configuration-point id="ServletRequestServicerPipeline" schema-id="hivemind.lib.Pipeline">
-    
-    A pipeline for processing an incoming servlet request.
-    
-  </configuration-point> 
-  
-  <service-point id="ServletRequestServicer">
-    
-    A pipeline for handling each request.
-    
-    <invoke-factory service-id="hivemind.lib.PipelineFactory">
-      <create-pipeline filter-interface="ServletRequestServicerFilter"
-        configuration-id="ServletRequestServicerPipeline"/>
-    </invoke-factory>    
-  </service-point>     
-  
-  <contribution configuration-id="ServletRequestServicerPipeline">
-    <filter name="DecodedRequestInjector" object="service:DecodedRequestInjector"/>
-	  <filter name="SetupRequestEncoding" object="service:SetupRequestEncoding"/>
-    <terminator object="service:WebRequestServicerPipelineBridge"/>
-  </contribution> 
-  
-  <service-point id="WebRequestServicerPipelineBridge" interface="ServletRequestServicer">
-    <invoke-factory>
-		  <construct class="impl.WebRequestServicerPipelineBridge">
-			  <set-service property="webRequestServicer" service-id="WebRequestServicer"/>
-			  <set-service property="requestGlobals" service-id="tapestry.globals.RequestGlobals"/>
-		  </construct>
-	  </invoke-factory>
-  </service-point>  
-  
-  <configuration-point id="WebRequestServicerPipeline" schema-id="hivemind.lib.Pipeline">
-		
-	A pipeline, invoked by the ServletRequestPipeline, that will process the request
-	using the generic WebRequest and WebResponse objects.
-	
-  </configuration-point>   
-  
-  <service-point id="WebRequestServicer">
-    
-	A secondary pipeline for handling each requests wrapped in the WebRequest abstraction
-	layer.
-    
-    <invoke-factory service-id="hivemind.lib.PipelineFactory">
-      <create-pipeline filter-interface="WebRequestServicerFilter"
-        configuration-id="WebRequestServicerPipeline"/>
-    </invoke-factory>    
-  </service-point>    
-  
-  <contribution configuration-id="WebRequestServicerPipeline">
-     <terminator object="service:InvokeEngineTerminator"/>
-  </contribution>  
-    
-  <service-point id="InvokeEngineTerminator" interface="WebRequestServicer">
-    
-    Terminator service for the WebRequestServicerPipeline. This locates an IEngine instance that
-    can take control of the remainder of the request.
-    
-    <invoke-factory>
-      <construct class="impl.InvokeEngineTerminator">
-        <set-service property="engineManager" service-id="EngineManager"/>
-        <set-service property="infrastructure" service-id="tapestry.Infrastructure"/>	
-      </construct>
-    </invoke-factory>
-  </service-point> 
-    
-  <service-point id="DecodedRequestInjector" interface="ServletRequestServicerFilter">
-    
-    Filter contributed into the ServletRequestServicerPipeline whose responsibility is
-    to provide a modified HttpServletRequest that reflects the results of
-    an IRequestDecoder (provided as the org.apache.tapestry.request-decoder
-    application extension).  If the extension exists, then a different HttpServletRequest
-    is substituted.
-    
-    <invoke-factory>
-      <construct class="org.apache.tapestry.request.DecodedRequestInjector">
-        <set-object property="applicationSpecification" value="infrastructure:applicationSpecification"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>
-  
-  <service-point id="ResponseRenderer">
-    Renders the active page as the response.
-    
-    <invoke-factory>
-      <construct class="impl.ResponseRendererImpl" />
-    </invoke-factory>
-  </service-point>
-  
-  <contribution configuration-id="tapestry.Infrastructure">
-    <property name="responseRenderer" object="service:ResponseRenderer"/>
-    <property name="requestCycleFactory" object="service:RequestCycleFactory"/>
-    <property name="cookieSource" object="service:CookieSource"/>
-  </contribution>
-  
-  <service-point id="AbsoluteURLBuilder">
-    
-    Uses HttpServletRequest information to build complete URLs, suitable for use when
-    sending client-side redirects.
-    
-    <invoke-factory>
-      <construct class="impl.AbsoluteURLBuilderImpl">
-        <set-object property="request" value="infrastructure:request"/>
-      </construct>
-    </invoke-factory>
-    
-  </service-point>
-  
-  <service-point id="RequestCycleFactory">
-    
-    Creates new IRequestCycle instances.
-    
-    <invoke-factory>
-      <construct class="impl.RequestCycleFactoryImpl">
-        <set-object property="encoders"
-                    value="service-property:tapestry.url.LinkFactory:serviceEncoders"/>
-        <set-service property="strategySource" service-id="tapestry.persist.PropertyPersistenceStrategySource"/>       
-        <set-service property="infrastructure" service-id="tapestry.Infrastructure"/>
-		<set-service property="absoluteURLBuilder" service-id="AbsoluteURLBuilder"/>
-		<set-service property="requestGlobals" service-id="tapestry.globals.RequestGlobals"/>  
-        <set-service property="responseDelegateFactory" service-id="tapestry.services.ResponseDelegateFactory" />  
-      </construct>
-    </invoke-factory>
-    
-  </service-point>  
-  
-  <service-point id="SetupRequestEncoding" interface="ServletRequestServicerFilter">
-	
-	Sets the output encoding for the request.
-	
-	<invoke-factory>
-		<construct class="impl.SetupRequestEncoding">
-			<set-object property="outputEncoding"	value="app-property:org.apache.tapestry.output-encoding"/>
-		</construct>
-	</invoke-factory>
-  </service-point>
-  
-  <service-point id="DisableCachingFilter" interface="WebRequestServicerFilter">
-	
-	Uses the ResetEventHub  to reset any cached data at the end of the request.
-	Only used during development, not in production.
-	
-	  <invoke-factory>
-		  <construct class="impl.DisableCachingFilter">
-			  <set-object property="resetEventHub" value="infrastructure:resetEventHub"/>
-		  </construct>
-	  </invoke-factory>
-  </service-point>
-  
-  <contribution configuration-id="WebRequestServicerPipeline" if="property org.apache.tapestry.disable-caching">
-    <filter name="DisableCachingFilter" object="service:DisableCachingFilter"/>
-  </contribution>
-  
+
+    Services and configurations for the Tapestry request processing pipeline.
+    It is expected that the IEngine interface will eventually "dissolve" into
+    a collection of loosely bound services.
+
+    <service-point id="EnginePool" interface="ObjectPool">
+
+        Contains engine instances, keyed on locale, ready for use in the current request.
+
+        <invoke-factory>
+            <construct class="impl.ObjectPoolImpl">
+                <event-listener service-id="tapestry.ResetEventHub"/>
+                <event-listener service-id="tapestry.describe.ReportStatusHub"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="RequestLocaleManager">
+
+        Encapsulates the logic for extracting the locale for the current request.
+
+        <invoke-factory model="pooled">
+            <construct class="impl.RequestLocaleManagerImpl">
+                <set-service property="request" service-id="tapestry.globals.WebRequest"/>
+                <set-object property="cookieSource" value="infrastructure:cookieSource"/>
+                <set-service property="threadLocale" service-id="hivemind.ThreadLocale"/>
+                <set-object property="acceptedLocales" value="app-property:org.apache.tapestry.accepted-locales"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <contribution configuration-id="hivemind.FactoryDefaults">
+        <default symbol="org.apache.tapestry.accepted-locales" value=""/>
+        <!-- One week, in seconds -->
+        <default symbol="org.apache.tapestry.default-cookie-max-age" value="604800"/>
+    </contribution>
+
+    <service-point id="CookieSource">
+
+        Allows access to incoming HTTP cookie values for the active (per-thread) request.
+
+        <invoke-factory>
+            <construct class="impl.CookieSourceImpl">
+                <set-service property="request" service-id="tapestry.globals.HttpServletRequest"/>
+                <set-service property="response" service-id="tapestry.globals.HttpServletResponse"/>
+                <set property="defaultMaxAge" value="${org.apache.tapestry.default-cookie-max-age}"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="EngineManager">
+        Obtains an IEngine implementation for the current request, either from a pool of
+        such engine instance, from a factory, or from the HttpSession.
+
+        <invoke-factory>
+            <construct class="impl.EngineManagerImpl">
+                <set-service property="enginePool" service-id="EnginePool"/>
+                <set-service property="engineFactory" service-id="EngineFactory"/>
+                <set-service property="localeManager" service-id="RequestLocaleManager"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="EngineFactory">
+
+        Responsible for creating new instances of IEngine as needed.
+
+        <invoke-factory>
+            <construct class="impl.EngineFactoryImpl">
+                <set-object property="applicationSpecification" value="infrastructure:applicationSpecification"/>
+                <set-object property="defaultEngineClassName" value="global-property:org.apache.tapestry.engine-class"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <configuration-point id="ServletRequestServicerPipeline" schema-id="hivemind.lib.Pipeline">
+
+        A pipeline for processing an incoming servlet request.
+
+    </configuration-point>
+
+    <service-point id="ServletRequestServicer">
+
+        A pipeline for handling each request.
+
+        <invoke-factory service-id="hivemind.lib.PipelineFactory">
+            <create-pipeline filter-interface="ServletRequestServicerFilter" configuration-id="ServletRequestServicerPipeline"/>
+        </invoke-factory>
+    </service-point>
+
+    <contribution configuration-id="ServletRequestServicerPipeline">
+        <filter name="DecodedRequestInjector" object="service:DecodedRequestInjector"/>
+        <filter name="SetupRequestEncoding" object="service:SetupRequestEncoding"/>
+        <terminator object="service:WebRequestServicerPipelineBridge"/>
+    </contribution>
+
+    <service-point id="WebRequestServicerPipelineBridge" interface="ServletRequestServicer">
+        <invoke-factory>
+            <construct class="impl.WebRequestServicerPipelineBridge">
+                <set-service property="webRequestServicer" service-id="WebRequestServicer"/>
+                <set-service property="requestGlobals" service-id="tapestry.globals.RequestGlobals"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <configuration-point id="WebRequestServicerPipeline" schema-id="hivemind.lib.Pipeline">
+
+        A pipeline, invoked by the ServletRequestPipeline, that will process the request
+        using the generic WebRequest and WebResponse objects.
+
+    </configuration-point>
+
+    <service-point id="WebRequestServicer">
+
+        A secondary pipeline for handling each requests wrapped in the WebRequest abstraction
+        layer.
+
+        <invoke-factory service-id="hivemind.lib.PipelineFactory">
+            <create-pipeline filter-interface="WebRequestServicerFilter" configuration-id="WebRequestServicerPipeline"/>
+        </invoke-factory>
+    </service-point>
+
+    <contribution configuration-id="WebRequestServicerPipeline">
+        <terminator object="service:InvokeEngineTerminator"/>
+    </contribution>
+
+    <service-point id="InvokeEngineTerminator" interface="WebRequestServicer">
+
+        Terminator service for the WebRequestServicerPipeline. This locates an IEngine instance that
+        can take control of the remainder of the request.
+
+        <invoke-factory>
+            <construct class="impl.InvokeEngineTerminator">
+                <set-service property="engineManager" service-id="EngineManager"/>
+                <set-service property="infrastructure" service-id="tapestry.Infrastructure"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="DecodedRequestInjector" interface="ServletRequestServicerFilter">
+
+        Filter contributed into the ServletRequestServicerPipeline whose responsibility is
+        to provide a modified HttpServletRequest that reflects the results of
+        an IRequestDecoder (provided as the org.apache.tapestry.request-decoder
+        application extension).  If the extension exists, then a different HttpServletRequest
+        is substituted.
+
+        <invoke-factory>
+            <construct class="org.apache.tapestry.request.DecodedRequestInjector">
+                <set-object property="applicationSpecification" value="infrastructure:applicationSpecification"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="ResponseRenderer">
+        Renders the active page as the response.
+
+        <invoke-factory>
+            <construct class="impl.ResponseRendererImpl" />
+        </invoke-factory>
+    </service-point>
+
+    <contribution configuration-id="tapestry.Infrastructure">
+        <property name="responseRenderer" object="service:ResponseRenderer"/>
+        <property name="requestCycleFactory" object="service:RequestCycleFactory"/>
+        <property name="cookieSource" object="service:CookieSource"/>
+    </contribution>
+
+    <service-point id="AbsoluteURLBuilder">
+
+        Uses HttpServletRequest information to build complete URLs, suitable for use when
+        sending client-side redirects.
+
+        <invoke-factory>
+            <construct class="impl.AbsoluteURLBuilderImpl">
+                <set-object property="request" value="infrastructure:request"/>
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="RequestCycleFactory">
+
+        Creates new IRequestCycle instances.
+
+        <invoke-factory>
+            <construct class="impl.RequestCycleFactoryImpl">
+                <set-object property="encoders"
+                            value="service-property:tapestry.url.LinkFactory:serviceEncoders"/>
+                <set-service property="strategySource" service-id="tapestry.persist.PropertyPersistenceStrategySource"/>
+                <set-service property="infrastructure" service-id="tapestry.Infrastructure"/>
+                <set-service property="absoluteURLBuilder" service-id="AbsoluteURLBuilder"/>
+                <set-service property="requestGlobals" service-id="tapestry.globals.RequestGlobals"/>
+                <set-service property="responseDelegateFactory" service-id="tapestry.services.ResponseDelegateFactory" />
+            </construct>
+        </invoke-factory>
+
+    </service-point>
+
+    <service-point id="SetupRequestEncoding" interface="ServletRequestServicerFilter">
+
+        Sets the output encoding for the request.
+
+        <invoke-factory>
+            <construct class="impl.SetupRequestEncoding">
+                <set-object property="outputEncoding"	value="app-property:org.apache.tapestry.output-encoding"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <service-point id="DisableCachingFilter" interface="WebRequestServicerFilter">
+
+        Uses the ResetEventHub  to reset any cached data at the end of the request.
+        Only used during development, not in production.
+
+        <invoke-factory>
+            <construct class="impl.DisableCachingFilter">
+                <set-object property="resetEventHub" value="infrastructure:resetEventHub"/>
+            </construct>
+        </invoke-factory>
+    </service-point>
+
+    <contribution configuration-id="WebRequestServicerPipeline" if="property org.apache.tapestry.disable-caching">
+        <filter name="DisableCachingFilter" object="service:DisableCachingFilter"/>
+    </contribution>
+
 </module>

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/asset/AssetService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/asset/AssetService.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/asset/AssetService.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/asset/AssetService.java Sat Jun 16 14:37:12 2007
@@ -17,8 +17,6 @@
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
-import org.apache.commons.pool.ObjectPool;
-import org.apache.commons.pool.impl.StackObjectPool;
 import org.apache.hivemind.ClassResolver;
 import org.apache.hivemind.util.Defense;
 import org.apache.tapestry.IRequestCycle;
@@ -41,9 +39,7 @@
 import java.io.OutputStream;
 import java.net.URL;
 import java.net.URLConnection;
-import java.text.DateFormat;
 import java.util.HashMap;
-import java.util.Locale;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.zip.GZIPOutputStream;
@@ -80,12 +76,7 @@
      */
 
     public static final String DIGEST = "digest";
-    
-    /**
-     * Pool of date format objects. (pooled because DateFormat isn't thread safe )
-     */
-    static final ObjectPool CACHED_FORMAT_POOL = new StackObjectPool(new PoolableDateFormatFactory("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH));
-    
+
     /**
      * Defaults MIME types, by extension, used when the servlet container doesn't provide MIME
      * types. ServletExec Debugger, for example, fails to provide these.
@@ -168,7 +159,6 @@
         Defense.isAssignable(parameter, String.class, "parameter");
 
         String path = (String) parameter;
-        
         String digest = null;
         
         if(!_unprotectedMatcher.containsResource(path))
@@ -199,7 +189,8 @@
         if (result == null)
         {
             int dotx = path.lastIndexOf('.');
-            if (dotx > -1) {
+            if (dotx > -1)
+            {
                 String key = path.substring(dotx + 1).toLowerCase();
                 result = (String) _mimeTypes.get(key);
             }
@@ -306,40 +297,34 @@
     {
         // even if it doesn't exist in header the value will be -1, 
         // which means we need to write out the contents of the resource
-        
-        String header = _request.getHeader("If-Modified-Since");
-        long modify = -1;
-        
-        if (_log.isDebugEnabled())
-            _log.debug("cachedResource(" + resourceURL.getURL() + ") modified-since header is: " + header);
-        
-        DateFormat format = null;
-        
-        try {
 
-            if (header != null)
-            {
-                format = (DateFormat) CACHED_FORMAT_POOL.borrowObject();
-
-                modify = format.parse(header).getTime();
-            }
+        long modifiedSince = _request.getDateHeader("If-Modified-Since");
 
-        } catch (Exception e) { e.printStackTrace(); }
-        finally
-        {    
-            if (format != null) 
-                try { CACHED_FORMAT_POOL.returnObject(format); } catch (Throwable t) { t.printStackTrace(); }
-        }
+        if (modifiedSince <= 0)
+            return false;
+        
+        if (_log.isDebugEnabled())
+            _log.debug("cachedResource(" + resourceURL.getURL() + ") modified-since header is: " + modifiedSince);
         
-        if (resourceURL.getLastModified() > modify)
+        if (resourceURL.getLastModified() > modifiedSince)
             return false;
         
         _response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
         
         return true;
     }
-    
-    /** @since 2.2 */
+
+    /**
+     * Writes the asset specified by <code>resourceConnection</code> out to the response stream.
+     *
+     * @param cycle
+     *          The current request.
+     * @param resourcePath
+     *          The path of the resource.
+     * @param resourceConnection
+     *          A connection for the resource.
+     * @throws IOException On error.
+     */
 
     private void writeAssetContent(IRequestCycle cycle, String resourcePath, URLConnection resourceConnection)
             throws IOException
@@ -396,35 +381,35 @@
             
             // check cache first
             
-            if (_cache.get(resourcePath) != null) {
-                
+            if (_cache.get(resourcePath) != null)
+            {    
                 cache = (CachedAsset)_cache.get(resourcePath);
                 
                 if (cache.getLastModified() < resourceConnection.getLastModified())
                     cache.clear(resourceConnection.getLastModified());
                 
                 data = cache.getData();
-            } else {
-                
+            } else
+            {    
                 cache = new CachedAsset(resourcePath, resourceConnection.getLastModified(), null, null);
                 
                 _cache.put(resourcePath, cache);
             }
             
-            if (data == null) {
-                
+            if (data == null)
+            {
                 input = resourceConnection.getInputStream();
                 data = IOUtils.toByteArray(input);
-                
+
                 cache.setData(data);
             }
             
             // compress javascript responses when possible
             
-            if (GzipUtil.shouldCompressContentType(contentType) && GzipUtil.isGzipCapable(_request)) {
-                
-                if (cache.getGzipData() == null) {
-                    
+            if (GzipUtil.shouldCompressContentType(contentType) && GzipUtil.isGzipCapable(_request))
+            {    
+                if (cache.getGzipData() == null)
+                {    
                     ByteArrayOutputStream bo = new ByteArrayOutputStream();
                     GZIPOutputStream gzip = new GZIPOutputStream(bo);
                     
@@ -433,10 +418,8 @@
                     
                     data = bo.toByteArray();
                     cache.setGzipData(data);
-                } else {
-                    
+                } else
                     data = cache.getGzipData();
-                }
                 
                 _response.setHeader("Content-Encoding", "gzip");
             }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/WebRequestServicerFilter.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/WebRequestServicerFilter.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/WebRequestServicerFilter.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/WebRequestServicerFilter.java Sat Jun 16 14:37:12 2007
@@ -14,11 +14,11 @@
 
 package org.apache.tapestry.services;
 
-import java.io.IOException;
-
 import org.apache.tapestry.web.WebRequest;
 import org.apache.tapestry.web.WebResponse;
 
+import java.io.IOException;
+
 /**
  * Filter interface for {@link org.apache.tapestry.services.WebRequestServicer}.
  * 
@@ -28,7 +28,6 @@
 public interface WebRequestServicerFilter
 {
 
-    void service(WebRequest request, WebResponse response,
-            WebRequestServicer servicer)
+    void service(WebRequest request, WebResponse response, WebRequestServicer servicer)
         throws IOException;
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/EngineFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/EngineFactoryImpl.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/EngineFactoryImpl.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/services/impl/EngineFactoryImpl.java Sat Jun 16 14:37:12 2007
@@ -14,8 +14,6 @@
 
 package org.apache.tapestry.services.impl;
 
-import java.util.Locale;
-
 import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.ClassResolver;
 import org.apache.hivemind.ErrorLog;
@@ -24,6 +22,8 @@
 import org.apache.tapestry.services.EngineFactory;
 import org.apache.tapestry.spec.IApplicationSpecification;
 
+import java.util.Locale;
+
 /**
  * Standard implementation of {@link org.apache.tapestry.services.EngineFactory} service. This
  * should do for most purposes, since a major focus of Tapestry 4.0 is to no longer require
@@ -77,9 +77,7 @@
             }
             catch (Exception ex)
             {
-                throw new ApplicationRuntimeException(ImplMessages.errorInstantiatingEngine(
-                        _engineClass,
-                        ex), ex);
+                throw new ApplicationRuntimeException(ImplMessages.errorInstantiatingEngine(_engineClass, ex), ex);
             }
         }
     }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebRequest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebRequest.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebRequest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebRequest.java Sat Jun 16 14:37:12 2007
@@ -204,6 +204,16 @@
         return _servletRequest.getHeader(name);
     }
 
+    public long getDateHeader(String name)
+    {
+        return _servletRequest.getDateHeader(name);
+    }
+
+    public int getIntHeader(String name)
+    {
+        return _servletRequest.getIntHeader(name);
+    }
+
     public String getRemoteUser()
     {
         return _servletRequest.getRemoteUser();

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebResponse.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebResponse.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebResponse.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/ServletWebResponse.java Sat Jun 16 14:37:12 2007
@@ -53,6 +53,13 @@
 
     /**
      * Alternate constructor used by some tests.
+     *
+     * @param response
+     *          The wrapped response.
+     * @param log
+     *          Logger.
+     * @param tomcatPatch
+     *          Whether or not to apply tomcat workaround.
      */
     ServletWebResponse(HttpServletResponse response, Log log, boolean tomcatPatch)
     {

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebRequest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebRequest.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebRequest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebRequest.java Sat Jun 16 14:37:12 2007
@@ -178,6 +178,55 @@
     String getHeader(String name);
 
     /**
+     * Returns the value of the specified request header
+     * as a <code>long</code> value that represents a
+     * <code>Date</code> object. Use this method with
+     * headers that contain dates, such as
+     * <code>If-Modified-Since</code>.
+     *
+     * <p>The date is returned as
+     * the number of milliseconds since January 1, 1970 GMT.
+     * The header name is case insensitive.
+     *
+     * <p>If the request did not have a header of the
+     * specified name, this method returns -1. If the header
+     * can't be converted to a date, the method throws
+     * an <code>IllegalArgumentException</code>.
+     *
+     * @param name a <code>String</code> specifying the
+     * name of the header
+     *
+     * @return a <code>long</code> value representing the
+     * date specified in the header expressed as the number
+     * of milliseconds since January 1, 1970 GMT, or -1 if
+     * the named header was not included with the reqest
+     *
+     * @exception IllegalArgumentException If the header value
+     * can't be converted to a date
+     */
+    long getDateHeader(String name);
+
+    /**
+     * Returns the value of the specified request header
+     * as an <code>int</code>. If the request does not have a header
+     * of the specified name, this method returns -1. If the
+     * header cannot be converted to an integer, this method
+     * throws a <code>NumberFormatException</code>.
+     *
+     * <p>The header name is case insensitive.
+     *
+     * @param name a <code>String</code> specifying the name
+     * of a request header
+     *
+     * @return an integer expressing the value of the request header or -1
+     * if the request doesn't have a header of this name
+     *
+     * @exception NumberFormatException If the header value can't be
+     * converted to an <code>int</code>
+     */
+    int getIntHeader(String name);
+
+    /**
      * Returns the login of the user making this request, if the user has been authenticated, or
      * null if the user has not been authenticated.
      * 

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebResponse.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebResponse.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebResponse.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/java/org/apache/tapestry/web/WebResponse.java Sat Jun 16 14:37:12 2007
@@ -14,12 +14,12 @@
 
 package org.apache.tapestry.web;
 
+import org.apache.tapestry.util.ContentType;
+
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
 
-import org.apache.tapestry.util.ContentType;
-
 /**
  * Controls the response to the client, and specifically allows for creating the output stream (or
  * print writer) to which content is sent. This is essentially a generic version of
@@ -35,24 +35,40 @@
     /**
      * Returns a output stream to which output should be sent. This method should only be invoked
      * once on a response.
-     * 
+     *
+     * @param contentType
+     *          The encoding type that this outputstream will write content as.
      * @return the output stream, configured for the given type.
+     *
+     * @throws IOException On io error.
      */
 
-    OutputStream getOutputStream(ContentType contentType) throws IOException;
+    OutputStream getOutputStream(ContentType contentType)
+      throws IOException;
 
     /**
      * Returns a {@link PrintWriter} to which output should be sent. This method should be invoked
      * once on a response. A second call is expected to be so that an exception page can be
      * rendered, and the underlying request data is reset.
+     *
+     * @param contentType
+     *          The type of content encoding the writer is for.
+     * @return A new {@link PrintWriter} instance.
+     *
+     * @throws IOException On io error.
      */
 
-    PrintWriter getPrintWriter(ContentType contentType) throws IOException;
+    PrintWriter getPrintWriter(ContentType contentType)
+      throws IOException;
 
     /**
      * Encodes a URL, which adds information to the URL needed to ensure that the request triggered
      * by the URL will be associated with the current session (if any). In most cases, the string is
      * returned unchanged.
+     *
+     * @param url
+     *          The URL to encode.
+     * @return The url encoded.
      */
 
     String encodeURL(String url);
@@ -64,12 +80,20 @@
 
     void reset();
 
+    /**
+     * Sets the response content length header.
+     *
+     * @param contentLength
+     *          The total content length this response will write. 
+     */
     void setContentLength(int contentLength);
 
     /**
      * Returns a value to be prefixed or suffixed with any client-side JavaScript elements
      * (variables and function names) to ensure that they are unique with the context of the entire
      * page. For servlets, this is the empty string.
+     *
+     * @return The namespace that this requests resources should be pre-pended with.
      */
 
     String getNamespace();
@@ -107,12 +131,21 @@
 
     /**
      * Sets the status code for this response.
+     *
+     * @param status
+     *          The HTTP status code to set on the return header.
      */
     void setStatus(int status);
 
     /**
      * Sends an error response.
+     *
+     * @param statusCode
+     *          The error status code to set on the header.
+     * @param message
+     *          The message to give as the reason for error.
+     *
+     * @throws IOException on io error.
      */
-
     void sendError(int statusCode, String message) throws IOException;
 }

Modified: tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/asset/TestAssetService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/asset/TestAssetService.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/asset/TestAssetService.java (original)
+++ tapestry/tapestry4/trunk/tapestry-framework/src/test/org/apache/tapestry/asset/TestAssetService.java Sat Jun 16 14:37:12 2007
@@ -29,7 +29,6 @@
 import javax.servlet.http.HttpServletResponse;
 import java.io.ByteArrayOutputStream;
 import java.net.URLConnection;
-import java.text.DateFormat;
 
 
 /**
@@ -48,42 +47,14 @@
         AssetService service = new AssetService();
         service.setRequest(request);
         service.setLog(LogFactory.getLog("test"));
-        
-        URLConnection url = org.easymock.classextension.EasyMock.createMock(URLConnection.class);
-        
-        expect(request.getHeader("If-Modified-Since")).andReturn(null);
-        expect(url.getLastModified()).andReturn(System.currentTimeMillis());
-        
-        replay();
-        org.easymock.classextension.EasyMock.replay(url);
-        
-        assertFalse(service.cachedResource(url));
-        
-        verify();
-        org.easymock.classextension.EasyMock.verify(url);
-    }
-    
-    public void test_Cached_Resource_Malformed_Modified()
-    {
-        WebRequest request = newMock(WebRequest.class);
-        checkOrder(request, false);
-        
-        AssetService service = new AssetService();
-        service.setRequest(request);
-        service.setLog(LogFactory.getLog("test"));
-        
-        URLConnection url = org.easymock.classextension.EasyMock.createMock(URLConnection.class);
-        
-        expect(request.getHeader("If-Modified-Since")).andReturn("Woopedy woopedy");
-        expect(url.getLastModified()).andReturn(System.currentTimeMillis());
+
+        expect(request.getDateHeader("If-Modified-Since")).andReturn(-1l);
         
         replay();
-        org.easymock.classextension.EasyMock.replay(url);
-        
-        assertFalse(service.cachedResource(url));
+
+        assertFalse(service.cachedResource(null));
         
         verify();
-        org.easymock.classextension.EasyMock.verify(url);
     }
     
     public void test_Cached_Resource_Stale()
@@ -96,8 +67,10 @@
         service.setLog(LogFactory.getLog("test"));
         
         URLConnection url = org.easymock.classextension.EasyMock.createMock(URLConnection.class);
-        
-        expect(request.getHeader("If-Modified-Since")).andReturn("Sat, 29 Oct 1994 19:43:31 GMT");
+
+        long modifiedSince = System.currentTimeMillis() - 1000;
+
+        expect(request.getDateHeader("If-Modified-Since")).andReturn(modifiedSince);
         expect(url.getLastModified()).andReturn(System.currentTimeMillis());
         
         replay();
@@ -122,21 +95,12 @@
         service.setLog(LogFactory.getLog("test"));
         
         URLConnection url = org.easymock.classextension.EasyMock.createMock(URLConnection.class);
-        
-        DateFormat format = null;
-        
-        try {
-            
-            format = (DateFormat) AssetService.CACHED_FORMAT_POOL.borrowObject();
-            
-            expect(request.getHeader("If-Modified-Since")).andReturn("Sat, 29 Oct 1994 19:43:31 GMT");
-            expect(url.getLastModified()).andReturn(format.parse("Sat, 1 Dec 1991 19:43:31 GMT").getTime());
-            
-        } finally {
-            if (format != null) {
-                try { AssetService.CACHED_FORMAT_POOL.returnObject(format); } catch (Throwable t) {}
-            }
-        }
+
+        long lastModified = System.currentTimeMillis() - 4000;
+        long modifiedSince = System.currentTimeMillis();
+
+        expect(request.getDateHeader("If-Modified-Since")).andReturn(modifiedSince);
+        expect(url.getLastModified()).andReturn(lastModified);
         
         response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
         
@@ -175,7 +139,7 @@
 
         expect(matcher.containsResource("/org/apache/tapestry/asset/tapestry-in-action.png")).andReturn(true);
 
-        expect(request.getHeader("If-Modified-Since")).andReturn(null);
+        expect(request.getDateHeader("If-Modified-Since")).andReturn(-1L);
         expect(context.getMimeType("/org/apache/tapestry/asset/tapestry-in-action.png")).andReturn("image/png");
 
         response.setDateHeader("Last-Modified", url.getLastModified());

Modified: tapestry/tapestry4/trunk/tapestry-portlet/src/java/org/apache/tapestry/portlet/PortletWebRequest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-portlet/src/java/org/apache/tapestry/portlet/PortletWebRequest.java?view=diff&rev=547988&r1=547987&r2=547988
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-portlet/src/java/org/apache/tapestry/portlet/PortletWebRequest.java (original)
+++ tapestry/tapestry4/trunk/tapestry-portlet/src/java/org/apache/tapestry/portlet/PortletWebRequest.java Sat Jun 16 14:37:12 2007
@@ -161,6 +161,20 @@
         return null;
     }
 
+    public long getDateHeader(String name)
+    {
+        unsupported("getDateHeader");
+
+        return -1;
+    }
+
+    public int getIntHeader(String name)
+    {
+        unsupported("getIntHeader");
+
+        return -1;
+    }
+
     public String getRemoteUser()
     {
         return _portletRequest.getRemoteUser();