Author: jkuhnert
Date: Tue Dec 27 16:07:47 2005
New Revision: 359328
URL: http://svn.apache.org/viewcvs?rev=359328&view=rev
Log:
Initial work on adding unprotected asset resources to AssetService, allowing
more dynamic options for third party libraries/css asset includes/etc.
Added:
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcher.java
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcherImpl.java
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/subresource/
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/subresource/sub-resource.txt
Modified:
jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml
jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.services.xml
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/engine/encoders/AssetEncoderTest.java
jakarta/tapestry/trunk/status.xml
Modified:
jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml?rev=359328&r1=359327&r2=359328&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml
(original)
+++ jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml
Tue Dec 27 16:07:47 2005
@@ -137,4 +137,46 @@
<contribution configuration-id="tapestry.Infrastructure">
<property name="assetFactory" object="service:LookupAssetFactory"/>
</contribution>
+
+ <configuration-point id="UnprotectedAssets">
+
+ Maps asset path regexp patterns to assets that won't be required
+ to have md5sum digests, making them visible and accessible to
unauthenticated
+ url requests. Care should be taken contributing here. Most things should
remain
+ protected, like .class files, database configuration files, etc.
+
+ This configuration is mainly intended to help some resources that require
being
+ able to dynamically load content on the browser client-side. One such
resource
+ is the http://dojotoolkit.org javascript library, which loads
javascript/css/other
+ resources dynamically via XmlHttpRequests for resources that haven't been
previously
+ digested.
+
+ <schema>
+ <element name="unprotected-resource">
+ <attribute name="contains" required="true" unique="true">
+ The regexp pattern to match against.
+ </attribute>
+ </element>
+ </schema>
+ </configuration-point>
+
+ <contribution configuration-id="UnprotectedAssets">
+ List of unprotected asset regexps for ResourceMatcher service.
+
+ </contribution>
+
+ <service-point id="UnprotectedResourceMatcher">
+
+ Uses the UnprotectedAssets configuration point to dynamically determine
+ which assets managed by the AssetService should be protected. The default
+ is to protect all resources.
+
+ <invoke-factory>
+ <construct class="ResourceMatcherImpl">
+ <event-listener service-id="tapestry.ResetEventHub"/>
+ <set-configuration configuration-id="UnprotectedAssets"
property="contributions" />
+ </construct>
+ </invoke-factory>
+ </service-point>
+
</module>
Modified:
jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.services.xml
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.services.xml?rev=359328&r1=359327&r2=359328&view=diff
==============================================================================
---
jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.services.xml
(original)
+++
jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.services.xml
Tue Dec 27 16:07:47 2005
@@ -77,6 +77,8 @@
<set-service property="context"
service-id="tapestry.globals.WebContext"/>
<set-object property="response"
value="service:tapestry.globals.WebResponse"/>
<set-service property="digestSource"
service-id="tapestry.asset.ResourceDigestSource"/>
+ <set-service property="unprotectedMatcher"
+ service-id="tapestry.asset.UnprotectedResourceMatcher" />
</construct>
</invoke-factory>
</service-point>
Modified:
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java?rev=359328&r1=359327&r2=359328&view=diff
==============================================================================
---
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java
(original)
+++
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetService.java
Tue Dec 27 16:07:47 2005
@@ -76,6 +76,9 @@
/** @since 4.0 */
private ResourceDigestSource _digestSource;
+ /** @since 4.1 */
+ private ResourceMatcher _unprotectedMatcher;
+
/**
* Defaults MIME types, by extension, used when the servlet container
doesn't provide MIME
* types. ServletExec Debugger, for example, fails to provide these.
@@ -131,7 +134,7 @@
*/
public static final String DIGEST = "digest";
-
+
/**
* Builds a [EMAIL PROTECTED] ILink}for a [EMAIL PROTECTED] PrivateAsset}.
* <p>
@@ -142,19 +145,19 @@
public ILink getLink(boolean post, Object parameter)
{
Defense.isAssignable(parameter, String.class, "parameter");
-
+
String path = (String) parameter;
-
+
String digest = _digestSource.getDigestForResource(path);
-
+
Map parameters = new HashMap();
-
+
parameters.put(ServiceConstants.SERVICE, getName());
parameters.put(PATH, path);
parameters.put(DIGEST, digest);
-
+
// Service is stateless, which is the exception to the rule.
-
+
return _linkFactory.constructLink(this, post, parameters, false);
}
@@ -199,23 +202,23 @@
.md5Mismatch(path));
return;
}
-
+
// If they were vended an asset in the past then it must be up-to
date.
// Asset URIs change if the underlying file is modified.
-
+
if (_request.getHeader("If-Modified-Since") != null)
{
_response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
-
+
URL resourceURL = _classResolver.getResource(path);
-
+
if (resourceURL == null)
throw new
ApplicationRuntimeException(AssetMessages.noSuchResource(path));
-
+
URLConnection resourceConnection = resourceURL.openConnection();
-
+
writeAssetContent(cycle, path, resourceConnection);
}
catch (Throwable ex)
@@ -231,7 +234,7 @@
URLConnection resourceConnection) throws IOException
{
InputStream input = null;
-
+
try
{
// Getting the content type and length is very dependant
@@ -246,13 +249,13 @@
_response.setDateHeader("Last-Modified", _startupTime);
_response.setDateHeader("Expires", _expireTime);
-
+
// Set the content type. If the servlet container doesn't
// provide it, try and guess it by the extension.
-
+
if (contentType == null || contentType.length() == 0)
contentType = getMimeType(resourcePath);
-
+
OutputStream output = _response.getOutputStream(new
ContentType(contentType));
input = new
BufferedInputStream(resourceConnection.getInputStream());
@@ -319,5 +322,11 @@
public void setRequest(WebRequest request)
{
_request = request;
+ }
+
+ /** @since 4.1 */
+ public void setUnprotectedMatcher(ResourceMatcher matcher)
+ {
+ _unprotectedMatcher = matcher;
}
}
Added:
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcher.java
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcher.java?rev=359328&view=auto
==============================================================================
---
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcher.java
(added)
+++
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcher.java
Tue Dec 27 16:07:47 2005
@@ -0,0 +1,38 @@
+// Copyright 2004, 2005 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.asset;
+
+/**
+ * Responsible for determining if the path string of a [EMAIL PROTECTED]
Reasource} -
+ * typically involving [EMAIL PROTECTED] IAsset} resources being examined by
the
+ * [EMAIL PROTECTED] AssetService} - match the configured resource match
strings
+ * of this service.
+ *
+ * <p/>Currently used by [EMAIL PROTECTED] AssetService} to enable having
unprotected
+ * resources based off of regexp patterns.
+ *
+ * @author jkuhnert
+ */
+public interface ResourceMatcher {
+
+ /**
+ * Checks for the existance of a resource pattern that matches the incoming
+ * path string.
+ * @param path The path to a resource
+ * @return True if the path is matched against one of the patterns
configured
+ * for this matcher, false otherwise.
+ */
+
+ public boolean containsResource(String path);
+}
Added:
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcherImpl.java
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcherImpl.java?rev=359328&view=auto
==============================================================================
---
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcherImpl.java
(added)
+++
jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ResourceMatcherImpl.java
Tue Dec 27 16:07:47 2005
@@ -0,0 +1,80 @@
+// Copyright 2004, 2005 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.asset;
+
+import java.util.List;
+
+import org.apache.tapestry.event.ResetEventListener;
+import org.apache.tapestry.util.RegexpMatcher;
+
+
+/**
+ * Implementation of [EMAIL PROTECTED] ResourceMatcher}.
+ *
+ * @author jkuhnert
+ */
+public class ResourceMatcherImpl implements ResetEventListener,
ResourceMatcher {
+
+ /** regexp matcher engine */
+ protected RegexpMatcher matcher;
+ /** Resource match configuration regexp strings */
+ protected List contributions;
+
+ /** no args constructor */
+ public ResourceMatcherImpl() { }
+
+ /**
+ * Invoked by hivemind by default to initialize
+ * service.
+ */
+ public void initializeService()
+ {
+ matcher = new RegexpMatcher();
+ }
+
+ /**
+ * [EMAIL PROTECTED]
+ */
+ public synchronized void resetEventDidOccur()
+ {
+ matcher.clear();
+ }
+
+ /**
+ * [EMAIL PROTECTED]
+ */
+ public boolean containsResource(String path)
+ {
+ if (contributions == null || contributions.size() < 1)
+ return false;
+
+ for (int i = 0; i < contributions.size(); i++) {
+ String pattern = (String)contributions.get(i);
+ if (matcher.contains(pattern, path))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * The set of contributed regexp strings that will positively
+ * match incoming path strings for this matcher.
+ * @param contributions
+ */
+ public void setContributions(List contributions)
+ {
+ this.contributions = contributions;
+ }
+}
Modified:
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java?rev=359328&r1=359327&r2=359328&view=diff
==============================================================================
---
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java
(original)
+++
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java
Tue Dec 27 16:07:47 2005
@@ -142,6 +142,33 @@
verifyControls();
}
+ /**
+ * Tests relative sub-directory paths.
+ */
+ public void testRelativeDirectoryPath()
+ {
+ IEngineService assetService = newService();
+ Location l = newLocation();
+
+ replayControls();
+
+ ClasspathAssetFactory factory = new ClasspathAssetFactory();
+ factory.setClassResolver(getClassResolver());
+ factory.setAssetService(assetService);
+ factory.setLocalizer(new DefaultResourceLocalizer());
+
+ Resource subResource = new ClasspathResource(getClassResolver(),
+ "/org/apache/tapestry/asset/subresource/sub-resource.txt");
+ IAsset asset = factory.createAsset(subResource, l);
+
+ assertTrue(asset instanceof PrivateAsset);
+ assertEquals("/org/apache/tapestry/asset/subresource/sub-resource.txt",
+ asset.getResourceLocation().getPath());
+ assertSame(l, asset.getLocation());
+
+ verifyControls();
+ }
+
private ClasspathResource newBaseResource()
{
return new ClasspathResource(getClassResolver(),
Added:
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java?rev=359328&view=auto
==============================================================================
---
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java
(added)
+++
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestUnprotectedAsset.java
Tue Dec 27 16:07:47 2005
@@ -0,0 +1,116 @@
+// Copyright 2004, 2005 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.asset;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hivemind.impl.DefaultClassResolver;
+import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Pattern;
+import org.apache.oro.text.regex.PatternCompiler;
+import org.apache.oro.text.regex.PatternMatcher;
+import org.apache.oro.text.regex.Perl5Compiler;
+import org.apache.oro.text.regex.Perl5Matcher;
+
+
+/**
+ * Tests for unprotected resource contributions.
+ *
+ * @author jkuhnert
+ */
+public class TestUnprotectedAsset extends HiveMindTestCase {
+
+ PatternCompiler compiler = new Perl5Compiler();
+ PatternMatcher matcher = new Perl5Matcher();
+
+ /**
+ * Tests for regexp patterns describing unprotected resources.
+ */
+ public void testUnProtectedMatch()
+ {
+ Pattern pr = newPattern("org/apache/tapestry/asset/.*.txt");
+
+ assertFalse(matcher.contains("org/apache/tapestry/foobar.png", pr));
+
assertTrue(matcher.contains("org/apache/tapestry/asset/base-resource.txt", pr));
+ assertFalse(matcher.contains("org/apache/tapestry/asset/foobar.png",
pr));
+ }
+
+ /**
+ * Creates [EMAIL PROTECTED] Pattern} objects for regexp matching.
+ * @param pattern
+ * @return
+ */
+ protected Pattern newPattern(String pattern)
+ {
+ Pattern pr = null;
+ try {
+ pr = compiler.compile("org/apache/tapestry/asset/.*.txt",
+ Perl5Compiler.READ_ONLY_MASK |
Perl5Compiler.CASE_INSENSITIVE_MASK
+ | Perl5Compiler.MULTILINE_MASK);
+ } catch (MalformedPatternException e) {
+ unreachable();
+ }
+
+ return pr;
+ }
+
+ /**
+ * Tests and asserts that it doesn't take ~longer~ to work with undigested
+ * resources using patterns than normal digested resources.
+ */
+ public void testResourcePerformanceComparison()
+ {
+ Pattern pr =
newPattern("/org/apache/tapestry/asset/tapestry-in-action.png");
+
+ ResourceDigestSourceImpl s = new ResourceDigestSourceImpl();
+ s.setClassResolver(new DefaultClassResolver());
+
+ assertEquals("a5f4663532ea3efe22084df086482290", s
+
.getDigestForResource("/org/apache/tapestry/asset/tapestry-in-action.png"));
+
+ long currTime = System.currentTimeMillis();
+
s.getDigestForResource("/org/apache/tapestry/asset/tapestry-in-action.png");
+ long drtime = System.currentTimeMillis() - currTime;
+
+ currTime = System.currentTimeMillis();
+ matcher.contains("/org/apache/tapestry/asset/tapestry-in-action.png",
pr);
+ long urtime = System.currentTimeMillis() - currTime;
+
+ assertFalse("Urtime > drtime: " + urtime + " > " + drtime, urtime <
drtime);
+ }
+
+ /**
+ * Tests the implementation of [EMAIL PROTECTED] ResourceMatcher}.
+ */
+ public void testResourceMatcher()
+ {
+ ResourceMatcherImpl rm = new ResourceMatcherImpl();
+ List patterns = new ArrayList();
+ patterns.add("/org/apache/tapestry/asset/.*.txt");
+ patterns.add("/org/apache/tapestry/asset/.*.css");
+ patterns.add("/org/apache/tapestry/asset/.*.js");
+ patterns.add("/org/apache/tapestry/asset/[%$4]rew\\invalidpattern");
+ rm.setContributions(patterns);
+ rm.initializeService();
+
+
assertFalse(rm.containsResource("/org/apache/tapestry/asset/AbstractAsset.class"));
+ assertFalse(rm.containsResource("/org/apache/tapestry/.*.class"));
+
assertTrue(rm.containsResource("/org/apache/tapestry/asset/assetBuilder.js"));
+ assertTrue(rm.containsResource("/org/apache/tapestry/asset/foo.txt"));
+ assertFalse(rm.containsResource("/org/apache/tapestry/asset/foo.TXT"));
+
assertTrue(rm.containsResource("/org/apache/tapestry/asset/subdirectory/foo.css"));
+ }
+}
Added:
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/subresource/sub-resource.txt
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/subresource/sub-resource.txt?rev=359328&view=auto
==============================================================================
---
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/subresource/sub-resource.txt
(added)
+++
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/subresource/sub-resource.txt
Tue Dec 27 16:07:47 2005
@@ -0,0 +1 @@
+sub-resource value
\ No newline at end of file
Modified:
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/engine/encoders/AssetEncoderTest.java
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/engine/encoders/AssetEncoderTest.java?rev=359328&r1=359327&r2=359328&view=diff
==============================================================================
---
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/engine/encoders/AssetEncoderTest.java
(original)
+++
jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/engine/encoders/AssetEncoderTest.java
Tue Dec 27 16:07:47 2005
@@ -31,16 +31,16 @@
public void testWrongService()
{
ServiceEncoding encoding = newEncoding();
-
+
trainGetParameterValue(encoding, ServiceConstants.SERVICE, "foo");
-
+
replayControls();
-
+
new AssetEncoder().encode(encoding);
-
+
verifyControls();
}
-
+
protected void trainGetParameterValue(ServiceEncoding encoding, String
name, String value)
{
encoding.getParameterValue(name);
@@ -67,7 +67,7 @@
verifyControls();
}
-
+
protected void trainGetServletPath(ServiceEncoding encoding, String
servletPath)
{
encoding.getServletPath();
@@ -77,18 +77,18 @@
public void testEncode()
{
ServiceEncoding encoding = newEncoding();
-
+
trainGetParameterValue(encoding, ServiceConstants.SERVICE,
Tapestry.ASSET_SERVICE);
trainGetParameterValue(encoding, AssetService.PATH,
"/foo/bar/Baz.gif");
trainGetParameterValue(encoding, AssetService.DIGEST, "12345");
-
+
encoding.setServletPath("/assets/12345/foo/bar/Baz.gif");
encoding.setParameterValue(AssetService.PATH, null);
encoding.setParameterValue(AssetService.DIGEST, null);
encoding.setParameterValue(ServiceConstants.SERVICE, null);
-
+
replayControls();
-
+
AssetEncoder encoder = new AssetEncoder();
encoder.setPath("/assets");
@@ -100,14 +100,14 @@
public void testDecode()
{
ServiceEncoding encoding = newEncoding();
-
+
trainGetServletPath(encoding, "/assets");
trainGetPathInfo(encoding, "/12345/foo/bar/Baz.gif");
-
+
encoding.setParameterValue(ServiceConstants.SERVICE,
Tapestry.ASSET_SERVICE);
encoding.setParameterValue(AssetService.DIGEST, "12345");
encoding.setParameterValue(AssetService.PATH, "/foo/bar/Baz.gif");
-
+
replayControls();
AssetEncoder encoder = new AssetEncoder();
Modified: jakarta/tapestry/trunk/status.xml
URL:
http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/status.xml?rev=359328&r1=359327&r2=359328&view=diff
==============================================================================
--- jakarta/tapestry/trunk/status.xml (original)
+++ jakarta/tapestry/trunk/status.xml Tue Dec 27 16:07:47 2005
@@ -57,6 +57,9 @@
<changes>
<release version="4.1-alpha-1" date="unreleased">
<action type="update" dev="JK" >Cleaned up warnings/imports showing on
eclipse problem pane.</action>
+ <action type="add" dev="JK" fixes-bug="TAPESTRY-821">ResourceMatcher
service added with configurable regexp pattern
+ hivemind contributions to conditionally allow some resources to not
+ require md5sum digest checks.</action>
</release>
<release version="4.0-rc-2" date="unreleased">
<action type="fix" dev="HLS"
fixes-bug="TAPESTRY-789">DefaultResourceLocalizerTest is under framework/src
not framework/test</action>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]