Hello, I've added a bug related to the use of jar entry time instead of jar file last modified. https://issues.apache.org/jira/browse/TAP5-1114
<https://issues.apache.org/jira/browse/TAP5-1114>Regards, Krishna On Fri, Apr 23, 2010 at 11:18 AM, Krishna Caldas <[email protected]>wrote: > Hello, > > I have a problem with Expires and Last-Modified headers for classpath > resources inside JBoss/Tomcat. > > It has seen here before: > > http://www.mail-archive.com/[email protected]/msg27853.html > > http://markmail.org/message/uwfozi756vfxd264 > > I think its a very important issue given the performance optimization > expected by: > > https://issues.apache.org/jira/browse/TAPESTRY-2159 - YSlow > Recommendation: Version bundled javascript and use far-future expires header > <https://issues.apache.org/jira/browse/TAPESTRY-2159> > I tried to write a test for this: > > ====================================================== > package org.apache.tapestry5.internal.util; > > ... > > public class URLChangeTrackerTest extends TapestryTestCase > { > ... > > @Test > public void lastmodified_of_jar_url_should_not_be_zero() throws > Exception > { > URLChangeTracker t = new URLChangeTracker(converter, true); > URL jarFileURL = new URL("file:" + > this.getClass().getResource("url.jar").getFile()); > URLClassLoader classLoader = new URLClassLoader(new > URL[]{jarFileURL}); > URL url = > classLoader.getResource(classLoader.getResource("url/change/tracker/Foo.txt").toString()); > assertTrue(t.add(url) > 0); > } > ... > > ====================================================== > > This tests PASSED. The error only occurs for URLs supplied by > WebAppClassloader. > Only inside JBoss/Tomcat. > > ====================================================== > package org.apache.tapestry5.ioc.internal.util; > > ... > > public final class ClasspathResource extends AbstractResource > { > > ... > > public synchronized URL toURL() > { > if (!urlResolved) > { > *// For JBoss/Tomcat classLoader is an instance of > org.apache.catalina.loader.WebappClassLoader* > url = classLoader.getResource(getPath()); > urlResolved = true; > } > > return url; > } > ... > > ====================================================== > > The proposed FIX by Geoff makes sense given that we can have distinct > "lastmodified" dates for entries in a JAR. > And it fixes the problem inside JBoss/Tomcat even I think they have a BUG > because JarURLConnection should give the "lastmodified" date of the JAR. > > Follow some detail. > > Regards, > Krishna > > > > ====================================================== > > public class ResourceStreamerImpl implements ResourceStreamer > { > > ... > > public void streamResource(Resource resource) throws IOException > { > ... > > StreamableResource streamble = > resourceCache.getStreamableResource(resource); > * > long lastModified = streamble.getLastModified(); > > response.setDateHeader("Last-Modified", lastModified); > response.setDateHeader("Expires", lastModified + > InternalConstants.TEN_YEARS);* > ... > > ====================================================== > package org.apache.tapestry5.internal.util; > > ... > > public class URLChangeTracker > { > > ... > > public long add(URL url) > { > if (url == null) return 0; > > URL converted = classpathURLConverter.convert(url); > > if (!converted.getProtocol().equals("file")) return > timestampForNonFileURL(converted); > ... > > private long timestampForNonFileURL(URL url) > { > long timestamp; > > try > { > *// Inside JBoss/Tomcat its returning 0 for JarURLConnection* > timestamp = url.openConnection().getLastModified(); > } > catch (IOException ex) > { > throw new RuntimeException(ex); > } > > return applyGranularity(timestamp); > } > > ... > > ====================================================== > package java.net; > > ... > > public abstract class URLConnection { > > ... > > /** > * Returns the value of the <code>last-modified</code> header field. > * The result is the number of milliseconds since January 1, 1970 GMT. > * > * @return the date the resource referenced by this > * <code>URLConnection</code> was last modified, or 0 if not > known. > * @see java.net.URLConnection#getHeaderField(java.lang.String) > */ > public long getLastModified() { > *// No header fields for JarURLConnection (extends this not overidding > this method) inside JBoss/Tomcat.* > return getHeaderFieldDate("last-modified", 0); > } > > ... > > ====================================================== > >
