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 2006/12/01 18:49:35 UTC
svn commit: r481321 [1/2] - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/ main/java/org/apache/tapestry/annotations/
main/java/org/apache/tapestry/internal/services/
main/java/org/apache/tapestry/internal/util/ main/jav...
Author: hlship
Date: Fri Dec 1 09:49:32 2006
New Revision: 481321
URL: http://svn.apache.org/viewvc?view=rev&rev=481321
Log:
Add basic Asset support (for context assets).
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Asset.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetInjectWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetSourceImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextAssetFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextResource.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectAnonymousWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectNamedWorker.java
- copied, changed from r480115, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetSource.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/assets.apt
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/images/
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/images/tapestry_banner.gif (with props)
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Img.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/AssetDemo.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetInjectWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetSourceImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextAssetFactoryTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextResourceTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectAnonymousWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectNamedWorkerTest.java
- copied, changed from r480115, tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/transform/pages/FindFieldClass.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/AssetDemo.html
Removed:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectionKey.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InjectWorkerTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/MultiKey.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/inject.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/localization.apt
tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/InternalClassTransformationImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/OnEventWorkerTest.java
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Asset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Asset.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Asset.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/Asset.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,37 @@
+// 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;
+
+import org.apache.tapestry.ioc.Resource;
+
+/**
+ * An Asset is any kind of resource that can be exposed to the client web browser. Although quite
+ * often an Asset is a resource in a web application's context folder, within Tapestry, Assets may
+ * also be resources on the classpath (i.e., packaged inside JARs).
+ * <p>
+ * An Asset's toString() will return the URL for the resource (the same value as
+ * {@link #toClientURL()}).
+ */
+public interface Asset
+{
+ /**
+ * Returns a URL that can be passed, unchanged, to the client in order for it to access the
+ * resource.
+ */
+ String toClientURL();
+
+ /** Returns the underlying Resource for the Asset. */
+ Resource getResource();
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Inject.java Fri Dec 1 09:49:32 2006
@@ -21,8 +21,24 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ComponentResources;
+
/**
- * Allows injection of various objects into a component class.
+ * Allows injection of various objects into a component class. In certain cases, the type of the
+ * field guides the interpretation of the value. For {@link Asset}, the value is the path, relative
+ * to the component's class file, to the resource from which the Asset is obtained.
+ * <p>
+ * In most other cases, the value is an object reference. A common example:
+ *
+ * <pre>
+ * @Inject("infrastructure:request")
+ * private WebRequest _request;
+ * </pre>
+ *
+ * <p>
+ * Finally, for certain specific types (such as {@link ComponentResources}), the value is omitted
+ * entirely, and an object appropriate to the component instance is injected.
*
* @see org.apache.tapestry.services.InjectionProvider
*/
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetInjectWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetInjectWorker.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetInjectWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetInjectWorker.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,116 @@
+// 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.internal.services;
+
+import java.util.List;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.ioc.util.BodyBuilder;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.AssetSource;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.TransformConstants;
+
+/**
+ * Supports injection for fields of type {@link Asset}. This worker must be scheduled
+ * <em>before</em> {@link InjectNamedWorker}.
+ *
+ * @see AssetSource
+ */
+public class AssetInjectWorker implements ComponentClassTransformWorker
+{
+ static final String ASSET_TYPE_NAME = Asset.class.getName();
+
+ private final AssetSource _assetSource;
+
+ public AssetInjectWorker(final AssetSource assetSource)
+ {
+ _assetSource = assetSource;
+ }
+
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ List<String> names = transformation.findFieldsOfType(ASSET_TYPE_NAME);
+
+ String assetSourceFieldName = null;
+ String baseResourceFieldName = null;
+ String resourcesFieldName = null;
+
+ BodyBuilder builder = new BodyBuilder();
+ builder.begin();
+
+ for (String name : names)
+ {
+
+ Inject annotation = transformation.getFieldAnnotation(name, Inject.class);
+
+ // If the field has no annotation, or no value for its annotation, that's probably
+ // a programmer error, but we'll let the later Inject-related workers complain about it.
+
+ if (annotation == null)
+ continue;
+
+ String path = annotation.value();
+
+ if (path.equals(""))
+ continue;
+
+ // This is tricky because we support sublcasses; if we ask the component at runtime for
+ // its Resource (via the ComponentModel), we get the subclass, which will break the link
+ // to any Asset resources from super-classes.
+
+ if (assetSourceFieldName == null)
+ {
+ assetSourceFieldName = transformation.addInjectedField(
+ AssetSource.class,
+ "assetSource",
+ _assetSource);
+ baseResourceFieldName = transformation.addInjectedField(
+ Resource.class,
+ "baseResource",
+ model.getBaseResource());
+ resourcesFieldName = transformation.getResourcesFieldName();
+ }
+
+ builder.addln(
+ "%s = %s.findAsset(%s, \"%s\", %s.getLocale());",
+ name,
+ assetSourceFieldName,
+ baseResourceFieldName,
+ path,
+ resourcesFieldName);
+
+ transformation.makeReadOnly(name);
+
+ // Keep InjectNamedWorker from doing anything to it.
+
+ transformation.claimField(name, annotation);
+ }
+
+ // If no matches
+
+ if (assetSourceFieldName == null)
+ return;
+
+ builder.end();
+
+ transformation.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, builder
+ .toString());
+
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetSourceImpl.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetSourceImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/AssetSourceImpl.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,114 @@
+// 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.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newThreadSafeMap;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.ioc.util.StrategyRegistry;
+import org.apache.tapestry.services.AssetFactory;
+import org.apache.tapestry.services.AssetSource;
+
+/**
+ * Implementation of {@link AssetSource} available as service:tapestry.AssetSource or
+ * infrastructure:assetSource.
+ */
+public class AssetSourceImpl implements AssetSource
+{
+ private final StrategyRegistry<AssetFactory> _registry;
+
+ private final Map<String, Resource> _prefixToRootResource = newMap();
+
+ private final Map<Resource, Asset> _cache = newThreadSafeMap();
+
+ public AssetSourceImpl(Map<String, AssetFactory> configuration)
+ {
+ Map<Class, AssetFactory> byResourceClass = newMap();
+
+ for (Map.Entry<String, AssetFactory> e : configuration.entrySet())
+ {
+ String prefix = e.getKey();
+ AssetFactory factory = e.getValue();
+
+ Resource rootResource = factory.getRootResource();
+
+ byResourceClass.put(rootResource.getClass(), factory);
+
+ _prefixToRootResource.put(prefix, rootResource);
+ }
+
+ _registry = StrategyRegistry.newInstance(AssetFactory.class, byResourceClass);
+ }
+
+ public Asset findAsset(Resource baseResource, String path, Locale locale)
+ {
+ int colonx = path.indexOf(':');
+
+ if (colonx < 0)
+ return findRelativeAsset(baseResource, path, locale);
+
+ String prefix = path.substring(0, colonx);
+
+ Resource rootResource = _prefixToRootResource.get(prefix);
+
+ if (rootResource == null)
+ throw new IllegalArgumentException(ServicesMessages.unknownAssetPrefix(path));
+
+ return findRelativeAsset(rootResource, path.substring(colonx + 1), locale);
+ }
+
+ private Asset findRelativeAsset(Resource baseResource, String path, Locale locale)
+ {
+ Resource unlocalized = baseResource.forFile(path);
+ Resource localized = unlocalized.forLocale(locale);
+
+ if (localized == null)
+ throw new RuntimeException(ServicesMessages.assetDoesNotExist(unlocalized));
+
+ return getAssetForResource(localized);
+ }
+
+ private Asset getAssetForResource(Resource resource)
+ {
+ Asset result = _cache.get(resource);
+
+ if (result == null)
+ {
+ result = createAssetFromResource(resource);
+ _cache.put(resource, result);
+ }
+
+ return result;
+ }
+
+ private Asset createAssetFromResource(Resource resource)
+ {
+ // The class of the resource is derived from the class of the base resource.
+ // So we can then use the class of the resource as a key to locate the correct asset
+ // factory.
+
+ Class resourceClass = resource.getClass();
+
+ AssetFactory factory = _registry.get(resourceClass);
+
+ return factory.createAsset(resource);
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextAssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextAssetFactory.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextAssetFactory.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextAssetFactory.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,74 @@
+// 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.internal.services;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.services.AssetFactory;
+import org.apache.tapestry.services.WebContext;
+import org.apache.tapestry.services.WebRequest;
+
+/**
+ * Implementation of {@link AssetFactory} for assets that are part of the web application context.
+ *
+ * @see ContextResource
+ */
+public class ContextAssetFactory implements AssetFactory
+{
+ private final WebRequest _request;
+
+ private final WebContext _context;
+
+ public ContextAssetFactory(WebRequest request, WebContext context)
+ {
+ _request = request;
+ _context = context;
+ }
+
+ public Asset createAsset(final Resource resource)
+ {
+ final String contextPath = _request.getContextPath() + "/" + resource.getPath();
+
+ return new Asset()
+ {
+ public Resource getResource()
+ {
+ return resource;
+ }
+
+ public String toClientURL()
+ {
+ return contextPath;
+ }
+
+ /**
+ * Returns the client URL, which is essiential to allow informal parameters of type
+ * Asset to generate a proper value.
+ */
+ @Override
+ public String toString()
+ {
+ return toClientURL();
+ }
+ };
+ }
+
+ /** Returns the root {@link ContextResource}. */
+ public Resource getRootResource()
+ {
+ return new ContextResource(_context, "/");
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextResource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextResource.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextResource.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ContextResource.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,85 @@
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
+import java.net.URL;
+
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.ioc.internal.util.AbstractResource;
+import org.apache.tapestry.services.WebContext;
+
+/**
+ * A resource stored with in the web application context.
+ */
+public class ContextResource extends AbstractResource
+{
+ private static final int PRIME = 37;
+
+ private WebContext _context;
+
+ public ContextResource(WebContext context, String path)
+ {
+ super(path);
+
+ notNull(context, "context");
+
+ _context = context;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("context:%s", getPath());
+ }
+
+ @Override
+ protected Resource newResource(String path)
+ {
+ return new ContextResource(_context, path);
+ }
+
+ public URL toURL()
+ {
+ // This is so easy to screw up; ClassLoader.getResource() doesn't want a leading slash,
+ // and HttpServletContext.getResource() does. This is what I mean when I say that
+ // a framework is an accumulation of the combined experience of many users and developers.
+
+ return _context.getResource("/" + getPath());
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return PRIME * _context.hashCode() + getPath().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+
+ final ContextResource other = (ContextResource) obj;
+
+ return _context == other._context && getPath().equals(other.getPath());
+ }
+
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectAnonymousWorker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectAnonymousWorker.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectAnonymousWorker.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectAnonymousWorker.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,71 @@
+// 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.internal.services;
+
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.ioc.ServiceLocator;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+import org.apache.tapestry.services.InjectionProvider;
+
+/**
+ * Performs anonymous injection, for the cases where a field is labled with the {@link Inject}
+ * annotation, but no specific value was provided. This worker must be scheduled <em>after</em>
+ * {@link InjectNamedWorker}.
+ * <p>
+ * The implementation of this worker mostly delegates to a chain of command of
+ * {@link InjectionProvider}s.
+ */
+public class InjectAnonymousWorker implements ComponentClassTransformWorker
+{
+
+ private final ServiceLocator _locator;
+
+ // Really, a chain of command
+
+ private final InjectionProvider _injectionProvider;
+
+ public InjectAnonymousWorker(final ServiceLocator locator,
+ final InjectionProvider injectionProvider)
+ {
+ _locator = locator;
+ _injectionProvider = injectionProvider;
+ }
+
+ public void transform(ClassTransformation transformation, MutableComponentModel model)
+ {
+ for (String fieldName : transformation.findFieldsWithAnnotation(Inject.class))
+ {
+ Inject annotation = transformation.getFieldAnnotation(fieldName, Inject.class);
+
+ String fieldType = transformation.getFieldType(fieldName);
+
+ boolean result = _injectionProvider.provideInjection(
+ fieldName,
+ fieldType,
+ _locator,
+ transformation,
+ model);
+
+ if (!result)
+ throw new RuntimeException(ServicesMessages.noInjectionFound(transformation
+ .getClassName(), fieldName, fieldType));
+
+ transformation.claimField(fieldName, annotation);
+ }
+ }
+
+}
Copied: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectNamedWorker.java (from r480115, tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectNamedWorker.java?view=diff&rev=481321&p1=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java&r1=480115&p2=tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectNamedWorker.java&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectWorker.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InjectNamedWorker.java Fri Dec 1 09:49:32 2006
@@ -21,27 +21,26 @@
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.services.ClassTransformation;
import org.apache.tapestry.services.ComponentClassTransformWorker;
-import org.apache.tapestry.services.InjectionProvider;
/**
- * Worker for the {@link org.apache.tapestry.annotations.Inject} annotation.
+ * Worker for the {@link org.apache.tapestry.annotations.Inject} annotation, but only works with
+ * annotations where the annotation has a value (a name). In some cases, there are specific types
+ * where the meaning of the value for the Inject annoation is different, works for those cases must
+ * be scheduled <em>before</em> this worker, and must be sure to
+ * {@link ClassTransformation#claimField(String, Object) claim the field}.
+ *
+ * @see ObjectProvider
*/
-public class InjectWorker implements ComponentClassTransformWorker
+public class InjectNamedWorker implements ComponentClassTransformWorker
{
private final ObjectProvider _objectProvider;
private final ServiceLocator _locator;
- // Really, a chain of command
-
- private final InjectionProvider _injectionProvider;
-
- public InjectWorker(ObjectProvider objectProvider, ServiceLocator locator,
- InjectionProvider injectionProvider)
+ public InjectNamedWorker(ObjectProvider objectProvider, ServiceLocator locator)
{
_objectProvider = objectProvider;
_locator = locator;
- _injectionProvider = injectionProvider;
}
public void transform(ClassTransformation transformation, MutableComponentModel model)
@@ -52,10 +51,12 @@
String value = annotation.value();
+ // A later worker will tackle this.
+
if (InternalUtils.isBlank(value))
- injectAnnonymous(fieldName, transformation, model);
- else
- injectNamed(fieldName, value, transformation, model);
+ continue;
+
+ injectNamed(fieldName, value, transformation, model);
transformation.claimField(fieldName, annotation);
}
@@ -75,20 +76,4 @@
transformation.injectField(fieldName, inject);
}
- private void injectAnnonymous(String fieldName, ClassTransformation transformation,
- MutableComponentModel model)
- {
- String fieldType = transformation.getFieldType(fieldName);
-
- boolean result = _injectionProvider.provideInjection(
- fieldName,
- fieldType,
- _locator,
- transformation,
- model);
-
- if (!result)
- throw new RuntimeException(ServicesMessages.noInjectionFound(transformation
- .getClassName(), fieldName, fieldType));
- }
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformation.java Fri Dec 1 09:49:32 2006
@@ -12,58 +12,57 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
-import java.util.List;
-
+package org.apache.tapestry.internal.services;
+
+import java.util.List;
+
+import org.apache.tapestry.internal.util.MultiKey;
import org.apache.tapestry.ioc.internal.util.IdAllocator;
-import org.apache.tapestry.services.ClassTransformation;
-import org.apache.tapestry.services.ComponentClassTransformWorker;
-
-/**
- * Extends {@link org.apache.tapestry.services.ClassTransformation} with additional methods that may
- * only be used internally by Tapestry.
- *
- *
- */
-public interface InternalClassTransformation extends ClassTransformation
-{
- /**
- * Returns the name of the protected field that is injected with the
- * {@link org.apache.tapestry.internal.InternalComponentResources}.
- */
- String getResourcesFieldName();
-
- /**
- * Invoked after all {@link ComponentClassTransformWorker}s have had their chance to work over
- * the class. This performs any final operations for the class transformation, which includes
- * coming up with the final constructor method for the class.
- */
- void finish();
-
- /**
- * Called (after {@link #finish()}) to construct an instantiator for the component.
- *
- * @param componentClass
- * the class to be instantiated
- * @return the component's instantiator
- */
- Instantiator createInstantiator(Class componentClass);
-
- /**
- * Returns a copy of the transformation's IdAllocator. Used when creating a child class
- * transformation. May only be invoked on a frozen transformation.
- */
- IdAllocator getIdAllocator();
-
- /**
- * Returns a copy of the list of constructor arguments for this class.
- */
- List<ConstructorArg> getConstructorArgs();
-
- /**
- * Searchs for an existing injection of an object, returning the name of the protected field
- * into which the value was injected.
- */
- String searchForPreviousInjection(InjectionKey key);
-}
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassTransformWorker;
+
+/**
+ * Extends {@link org.apache.tapestry.services.ClassTransformation} with additional methods that may
+ * only be used internally by Tapestry.
+ */
+public interface InternalClassTransformation extends ClassTransformation
+{
+ /**
+ * Returns the name of the protected field that is injected with the
+ * {@link org.apache.tapestry.internal.InternalComponentResources}.
+ */
+ String getResourcesFieldName();
+
+ /**
+ * Invoked after all {@link ComponentClassTransformWorker}s have had their chance to work over
+ * the class. This performs any final operations for the class transformation, which includes
+ * coming up with the final constructor method for the class.
+ */
+ void finish();
+
+ /**
+ * Called (after {@link #finish()}) to construct an instantiator for the component.
+ *
+ * @param componentClass
+ * the class to be instantiated
+ * @return the component's instantiator
+ */
+ Instantiator createInstantiator(Class componentClass);
+
+ /**
+ * Returns a copy of the transformation's IdAllocator. Used when creating a child class
+ * transformation. May only be invoked on a frozen transformation.
+ */
+ IdAllocator getIdAllocator();
+
+ /**
+ * Returns a copy of the list of constructor arguments for this class.
+ */
+ List<ConstructorArg> getConstructorArgs();
+
+ /**
+ * Searchs for an existing injection of an object, returning the name of the protected field
+ * into which the value was injected.
+ */
+ String searchForPreviousInjection(MultiKey key);
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java Fri Dec 1 09:49:32 2006
@@ -46,6 +46,7 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.ComponentResources;
import org.apache.tapestry.internal.InternalComponentResources;
+import org.apache.tapestry.internal.util.MultiKey;
import org.apache.tapestry.ioc.internal.util.CollectionFactory;
import org.apache.tapestry.ioc.internal.util.IdAllocator;
import org.apache.tapestry.ioc.internal.util.InternalUtils;
@@ -73,7 +74,7 @@
private final IdAllocator _idAllocator;
/** Map, keyed on InjectKey, of field name. */
- private final Map<InjectionKey, String> _injectionCache = newMap();
+ private final Map<MultiKey, String> _injectionCache = newMap();
/** Map from a field to the annotation objects for that field. */
private Map<String, List<Annotation>> _fieldAnnotations = newMap();
@@ -520,6 +521,7 @@
public void claimField(String fieldName, Object tag)
{
notBlank(fieldName, "fieldName");
+ notNull(tag, "tag");
failIfFrozen();
@@ -791,6 +793,9 @@
String fieldName = field.getName();
+ if (_claimedFields.containsKey(fieldName))
+ continue;
+
List<Annotation> annotations = findFieldAnnotations(fieldName);
// Check to see if any of the annotations are the right type, if
@@ -811,6 +816,40 @@
return result;
}
+ public List<String> findFieldsOfType(String type)
+ {
+ failIfFrozen();
+
+ List<String> result = newList();
+
+ for (CtField field : _ctClass.getDeclaredFields())
+ {
+ if (!isInstanceField(field))
+ continue;
+
+ String fieldName = field.getName();
+
+ try
+ {
+ if (!field.getType().getName().equals(type))
+ continue;
+ }
+ catch (NotFoundException ex)
+ {
+ throw new RuntimeException(ex);
+ }
+
+ if (_claimedFields.containsKey(fieldName))
+ continue;
+
+ result.add(fieldName);
+ }
+
+ Collections.sort(result);
+
+ return result;
+ }
+
public List<MethodSignature> findMethodsWithAnnotation(
Class<? extends Annotation> annotationClass)
{
@@ -963,7 +1002,7 @@
failIfFrozen();
- InjectionKey key = new InjectionKey(type, value);
+ MultiKey key = new MultiKey(type, value);
String fieldName = searchForPreviousInjection(key);
@@ -1009,7 +1048,7 @@
return fieldName;
}
- public String searchForPreviousInjection(InjectionKey key)
+ public String searchForPreviousInjection(MultiKey key)
{
String result = _injectionCache.get(key);
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Fri Dec 1 09:49:32 2006
@@ -250,4 +250,14 @@
{
return MESSAGES.format("failure-reading-component-message", url, cause);
}
+
+ static String unknownAssetPrefix(String path)
+ {
+ return MESSAGES.format("unknown-asset-prefix", path);
+ }
+
+ static String assetDoesNotExist(Resource resource)
+ {
+ return MESSAGES.format("asset-does-not-exist", resource);
+ }
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/MultiKey.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/MultiKey.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/MultiKey.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/util/MultiKey.java Fri Dec 1 09:49:32 2006
@@ -16,7 +16,10 @@
import java.util.Arrays;
-/** A general purpose key for multiple values. */
+/**
+ * Combines multiple values to form a single composite key. MultiKey can often be used as an
+ * alternative to nested maps.
+ */
public final class MultiKey
{
private static final int PRIME = 31;
@@ -27,7 +30,8 @@
/**
* Creates a new instance from the provided values. It is assumed that the values provided are
- * good map keys themselves (i.e., immutable, and implement equals() and hashCode() ).
+ * good map keys themselves -- immutable, with proper implementations of equals() and
+ * hashCode().
*
* @param values
*/
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetFactory.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetFactory.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetFactory.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,32 @@
+// 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.services;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ioc.Resource;
+
+/**
+ * Used by {@link AssetSource} to create new {@link Asset}s as needed.
+ */
+public interface AssetFactory
+{
+ /**
+ * Returns the Resource reprsenting the root folder of the domain this factory is responsible
+ * for.
+ */
+ Resource getRootResource();
+
+ Asset createAsset(Resource resource);
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetSource.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetSource.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/AssetSource.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,43 @@
+// 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.services;
+
+import java.util.Locale;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ioc.Resource;
+
+/**
+ * Used to find or create an {@link Asset} with a given path.
+ */
+public interface AssetSource
+{
+ /**
+ * Finds the asset. The path may either be a simple file name or a relative path (relative to
+ * the base resource) <em>or</em> it may have a prefix, such as "context:" or "classpath:", in
+ * which case it is treated as a complete path within the indicated domain. The resulting
+ * Resource is then localized (to the provided Locale) and returned as an Asset.
+ * <p>
+ * The AssetSource caches its results, so a single Asset instance may be shared among many
+ * different components.
+ *
+ * @param baseResource
+ * base resource for computing relative paths
+ * @param path
+ * @param locale
+ * @return
+ */
+ Asset findAsset(Resource baseResource, String path, Locale locale);
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java Fri Dec 1 09:49:32 2006
@@ -40,9 +40,8 @@
*/
public interface ClassTransformation
{
-
/**
- * Returns the name of the class being transformed.
+ * Returns the fully qualified class name of the class being transformed.
*/
String getClassName();
@@ -50,8 +49,6 @@
* Returns the name of a new member (field or method). Ensures that the resulting name does not
* conflict with any existing member (declared by the underlying class, or inherited from a base
* class).
- * <p>
- * TODO: This method may be removed (see {@link #addField(int, String, String)})
*
* @param suggested
* the suggested value for the member
@@ -61,9 +58,17 @@
/**
* Generates a list of the names of declared instance fields that have the indicated annotation.
- * Only the names of private instance fields are returned.
+ * Only the names of private instance fields are returned. Any
+ * {@link #claimField(String, Object) claimed} fields are excluded.
*/
List<String> findFieldsWithAnnotation(Class<? extends Annotation> annotationClass);
+
+ /**
+ * Generates a list of the names of declared instance fields that exactly match the specified
+ * type. Only the names of private instance fields are returned. Any
+ * {@link #claimField(String, Object) claimed} fields are excluded.
+ */
+ List<String> findFieldsOfType(String type);
/**
* Finds all methods defined in the class that are marked with the provided annotation.
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Fri Dec 1 09:49:32 2006
@@ -44,6 +44,8 @@
import org.apache.tapestry.internal.bindings.LiteralBindingFactory;
import org.apache.tapestry.internal.bindings.MessageBindingFactory;
import org.apache.tapestry.internal.services.ApplicationGlobalsImpl;
+import org.apache.tapestry.internal.services.AssetInjectWorker;
+import org.apache.tapestry.internal.services.AssetSourceImpl;
import org.apache.tapestry.internal.services.BindingSourceImpl;
import org.apache.tapestry.internal.services.CommonResourcesInjectionProvider;
import org.apache.tapestry.internal.services.ComponentClassFactoryImpl;
@@ -56,14 +58,16 @@
import org.apache.tapestry.internal.services.ComponentResourcesInjectionProvider;
import org.apache.tapestry.internal.services.ComponentSourceImpl;
import org.apache.tapestry.internal.services.ComponentWorker;
+import org.apache.tapestry.internal.services.ContextAssetFactory;
import org.apache.tapestry.internal.services.DefaultInjectionProvider;
import org.apache.tapestry.internal.services.EnvironmentImpl;
import org.apache.tapestry.internal.services.EnvironmentalWorker;
import org.apache.tapestry.internal.services.HeartbeatImpl;
import org.apache.tapestry.internal.services.InfrastructureImpl;
import org.apache.tapestry.internal.services.InfrastructureManagerImpl;
+import org.apache.tapestry.internal.services.InjectAnonymousWorker;
import org.apache.tapestry.internal.services.InjectPageWorker;
-import org.apache.tapestry.internal.services.InjectWorker;
+import org.apache.tapestry.internal.services.InjectNamedWorker;
import org.apache.tapestry.internal.services.InternalModule;
import org.apache.tapestry.internal.services.LinkFactory;
import org.apache.tapestry.internal.services.MarkupWriterImpl;
@@ -403,6 +407,7 @@
add(configuration, locator, ComponentSource.class);
add(configuration, locator, BindingSource.class);
add(configuration, locator, ComponentMessagesSource.class);
+ add(configuration, locator, AssetSource.class);
configuration.add(new InfrastructureContribution("request", request));
configuration.add(new InfrastructureContribution("response", response));
@@ -526,6 +531,8 @@
* <li>Mixin -- adds a mixin as part of a component's implementation</li>
* <li>Environment -- allows fields to contain values extracted from the {@link Environment}
* service</li>
+ * <li>InjectNamed -- used with the {@link Inject} annotation, when a value is supplied</li>
+ * <li>InjectAnnonymous -- used with the {@link Inject} annotation, when no value is supplied</li>
* <li>InjectPage -- adds code to allow access to other pages via the {@link InjectPage} field
* annotation</li>
* <li>SupportsInformalParameters -- checks for the annotation</li>
@@ -541,13 +548,20 @@
InjectionProvider injectionProvider, @InjectService("Environment")
Environment environment, @InjectService("tapestry.ComponentClassResolver")
ComponentClassResolver resolver, @InjectService("tapestry.internal.RequestPageCache")
- RequestPageCache requestPageCache)
+ RequestPageCache requestPageCache, @Inject("infrastructure:assetSource")
+ AssetSource assetSource)
{
// TODO: Proper scheduling of all of this. Since a given field or method should
// only have a single annotation, the order doesn't matter so much, as long as
// UnclaimedField is last.
- configuration.add("Inject", new InjectWorker(objectProvider, locator, injectionProvider));
+ configuration.add("InjectNamed", new InjectNamedWorker(objectProvider, locator));
+ configuration.add(
+ "InjectAnonymous",
+ new InjectAnonymousWorker(locator, injectionProvider),
+ "after:InjectNamed");
+ configuration.add("AssetInject", new AssetInjectWorker(assetSource), "before:InjectNamed");
+
configuration.add("Parameter", new ParameterWorker());
configuration.add("Component", new ComponentWorker(resolver));
configuration.add("Environment", new EnvironmentalWorker(environment));
@@ -744,5 +758,18 @@
updateListenerHub.addUpdateListener(service);
return service;
+ }
+
+ public static AssetSource buildAssetSource(Map<String, AssetFactory> configuration)
+ {
+ return new AssetSourceImpl(configuration);
+ }
+
+ public void contributeAssetSource(MappedConfiguration<String, AssetFactory> configuration)
+ {
+ AssetFactory contextAssetFactory = new ContextAssetFactory(_request, _applicationGlobals
+ .getWebContext());
+
+ configuration.add("context", contextAssetFactory);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TapestryTestCase.java Fri Dec 1 09:49:32 2006
@@ -34,8 +34,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
+import org.apache.tapestry.Asset;
import org.apache.tapestry.ComponentResources;
import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.Inject;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.ioc.Location;
import org.apache.tapestry.ioc.Resource;
@@ -47,12 +49,14 @@
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.model.ParameterModel;
import org.apache.tapestry.runtime.Component;
+import org.apache.tapestry.services.AssetFactory;
import org.apache.tapestry.services.Binding;
import org.apache.tapestry.services.BindingFactory;
import org.apache.tapestry.services.ClassTransformation;
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.InjectionProvider;
import org.apache.tapestry.services.MethodSignature;
+import org.apache.tapestry.services.WebContext;
import org.apache.tapestry.services.WebRequest;
import org.apache.tapestry.services.WebRequestHandler;
import org.apache.tapestry.services.WebResponse;
@@ -412,5 +416,45 @@
protected final void train_getLocale(ThreadLocale threadLocale, Locale locale)
{
expect(threadLocale.getLocale()).andReturn(locale);
+ }
+
+ protected final Asset newAsset()
+ {
+ return newMock(Asset.class);
+ }
+
+ protected final void train_createAsset(AssetFactory factory, Resource resource, Asset asset)
+ {
+ expect(factory.createAsset(resource)).andReturn(asset);
+ }
+
+ protected final void train_getRootResource(AssetFactory factory, Resource rootResource)
+ {
+ expect(factory.getRootResource()).andReturn(rootResource);
+ }
+
+ protected final AssetFactory newAssetFactory()
+ {
+ return newMock(AssetFactory.class);
+ }
+
+ protected final WebContext newWebContext()
+ {
+ return newMock(WebContext.class);
+ }
+
+ protected final void train_getClassName(ClassTransformation transformation, String className)
+ {
+ expect(transformation.getClassName()).andReturn(className).atLeastOnce();
+ }
+
+ protected final void train_value(Inject annotation, String value)
+ {
+ expect(annotation.value()).andReturn(value).atLeastOnce();
+ }
+
+ protected final <T extends Annotation> void train_getMethodAnnotation(ClassTransformation ct, MethodSignature signature, Class<T> annotationClass, T annotation)
+ {
+ expect(ct.getMethodAnnotation(signature, annotationClass)).andReturn(annotation);
}
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Fri Dec 1 09:49:32 2006
@@ -59,4 +59,6 @@
parameter-name-must-be-unique=Parameter names are required to be unique. Parameter '%s' already has the value '%s'.
page-is-dirty=Page %s is dirty, and will be discarded (rather than returned to the page pool).
component-instance-is-not-a-page=Method %s (for component %s) returned component %s, which is not a page component. The page containing the component will render the client response.
-failure-reading-component-messages=Unable to read component message catalog from %s: %s
\ No newline at end of file
+failure-reading-component-messages=Unable to read component message catalog from %s: %s
+unknown-asset-prefix=Unknown prefix for asset path '%s'.
+asset-does-not-exist=Unable to locate asset '%s' (the file does not exist).
\ No newline at end of file
Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/assets.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/assets.apt?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/assets.apt (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/assets.apt Fri Dec 1 09:49:32 2006
@@ -0,0 +1,59 @@
+ ----
+ Assets
+ ----
+
+Assets
+
+ Assets are any kind of file that may be downloaded to a client web browser in addition to the dynamically generated HTML.
+
+ Assets are most often images, stylesheets, and JavaScript libraries.
+
+ Normal assets are stored in the web application's context folder ... stored inside the web application WAR file in the ordinary way.
+
+ Tapestry will also make files stored <on the classpath>, with your Java class files, visible to the web browser. <<Note: not yet implemented.>>
+
+ Assets are exposed to your code as instances of the {{{../apidocs/org/apache/tapestry/Asset.html}Asset}} interface.
+
+Injecting Assets
+
+ Components learn about assets via injection. The
+ {{{inject.html}Inject}} annotation allows Assets to be injected into components as read-only properties.
+
++----+
+ @Inject("context:images/tapestry_banner.gif")
+ private Asset _banner;
++----+
+
+ Assets are located within <domains>; these domains are identified by the prefix on the Inject annotation's value.
+
+ If the prefix is omitted, the value will be interpreted as a path relative to the Java class file itself, within
+ the "classpath:" domain. This is often used when creating component libraries, where the assets used by the components
+ are packaged in the JAR with the components themselves.
+
+Relative Assets
+
+ You can use relative paths with domains (if you omit the prefix):
+
++----+
+ @Inject("../edit.png")
+ private Asset _icon;
++----+
+
+ Since you must omit the prefix, this only makes sense for components packaged in a library for reuse.
+
+Localization of Assets
+
+ Assets are {{{localization.html}localized}}; Tapestry will search for a variation of the file appropriate
+ to the effective locale for the request. In the previous example, a German user of the application may
+ see a file named <<<edit_de.png>>> (if such a file exists).
+
+New Asset Domains
+
+ If you wish to create new domains for assets, for example to allow assets to be stored on the file system or in a database,
+ you may define a new
+ {{{../apidocs/org/apache/tapestry/services/AssetFactory.html}AssetFactory}}
+ and contribute it to the tapestry.AssetSource service configuration.
+
+
+
+
\ No newline at end of file
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/infrastructure.apt Fri Dec 1 09:49:32 2006
@@ -46,6 +46,11 @@
The following table identifies the properties that are available via the infrastructure provider
by default:
+ [assetSource]
+ {{{../apidocs/org/apache/tapestry/services/AssetSource.html}AssetSource}} (tapestry.AssetSource)
+
+ Obtains assets from public and internal resources.
+
[bindingSource]
{{{../apidocs/org/apache/tapestry/services/BindingSource.html}BindingSource}} (tapestry.BindingSource)
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/inject.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/inject.apt?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/inject.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/inject.apt Fri Dec 1 09:49:32 2006
@@ -28,6 +28,11 @@
at runtime (which is very important in terms of being able to test your components).
Attempting to update an injected field will result in a runtime exception.
+* Asset Injection
+
+ When the field type is
+ {{{../apidocs/org/apache/tapestry/Asset.html}Asset}}, the value of the Inject annoation is treated specially, as a path
+ (relative to the component) to an {{{assets.html}asset}}.
* Named Injection
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/localization.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/localization.apt?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/localization.apt (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/localization.apt Fri Dec 1 09:49:32 2006
@@ -123,6 +123,11 @@
Reloading
If you change a property file in a message catalog, you'll see the change immediately, just as with component classes and component templates.
+
+Asset Localization
+
+ When {{{inject.html}injecting assets}}, the injected asset will be localized as well. A search for the closest match for the active locale
+ is made, and the final Asset will reflect that.
Locale Selection
Modified: tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/site.xml Fri Dec 1 09:49:32 2006
@@ -57,6 +57,7 @@
<item name="Component Events" href="guide/event.html"/>
<item name="Component Mixins" href="guide/mixins.html"/>
<item name="Localization" href="guide/localization.html"/>
+ <item name="Assets" href="guide/assets.html"/>
<item name="Type Coercion" href="guide/coercion.html"/>
<item name="Component Rendering" href="guide/rendering.html"/>
<item name="Persistent Data" href="guide/persist.html"/>
@@ -66,11 +67,7 @@
<item name="Request Processing" href="guide/request.html"/>
<item name="DOM" href="guide/dom.html"/>
<item name="Class Reloading" href="guide/reload.html"/>
- </menu>
-
- <menu name="Other">
- <item name="Dev Wiki" href="tap5devwiki.html#MasterIndex"/>
- </menu>
+ </menu>
<menu ref="reports"/>
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/images/tapestry_banner.gif
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/images/tapestry_banner.gif?view=auto&rev=481321
==============================================================================
Binary file - no diff available.
Propchange: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/images/tapestry_banner.gif
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/app1/index.html Fri Dec 1 09:49:32 2006
@@ -48,6 +48,9 @@
<li>
<a href="Localization.html">Localization</a> -- accessing localized messages from the component catalog
</li>
+ <li>
+ <a href="AssetDemo.html">AssetDemo</a> -- declaring an using Assets
+ </li>
</ul>
</p>
</body>
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Fri Dec 1 09:49:32 2006
@@ -320,9 +320,33 @@
assertTextPresent("Page locale: [en]");
}
+ @Test
+ public void app1_assets()
+ {
+ _selenium.open(BASE_URL);
+ clickAndWait("link=AssetDemo");
+
+ assertText("//img[@id='img']/@src", "/images/tapestry_banner.gif");
+ }
+
private void assertText(String locator, String expected)
{
- String actual = _selenium.getText(locator);
+ String actual = null;
+
+ try
+ {
+ actual = _selenium.getText(locator);
+ }
+ catch (RuntimeException ex)
+ {
+ System.err.printf(
+ "Error accessing %s: %s, in:\n\n%s\n\n",
+ locator,
+ ex.getMessage(),
+ _selenium.getHtmlSource());
+
+ throw ex;
+ }
if (actual.equals(expected))
return;
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Img.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Img.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Img.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/components/Img.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,60 @@
+// 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.integration.app1.components;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.ComponentResources;
+import org.apache.tapestry.MarkupWriter;
+import org.apache.tapestry.annotations.AfterRender;
+import org.apache.tapestry.annotations.BeforeRenderBody;
+import org.apache.tapestry.annotations.BeginRender;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Environmental;
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.annotations.Parameter;
+import org.apache.tapestry.services.PageRenderSupport;
+
+@ComponentClass
+public class Img
+{
+ @Environmental
+ private PageRenderSupport _support;
+
+ @Inject
+ private ComponentResources _resources;
+
+ @Parameter(required = true)
+ private Asset _src;
+
+ @BeginRender
+ void begin(MarkupWriter writer)
+ {
+ String clientId = _support.allocateClientId(_resources.getId());
+
+ writer.element("img", "src", _src, "id", clientId);
+ }
+
+ @BeforeRenderBody
+ boolean beforeRenderBody()
+ {
+ return false;
+ }
+
+ @AfterRender
+ void after(MarkupWriter writer)
+ {
+ writer.end();
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/AssetDemo.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/AssetDemo.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/AssetDemo.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/AssetDemo.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,31 @@
+// 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.integration.app1.pages;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.Inject;
+
+@ComponentClass
+public class AssetDemo
+{
+ @Inject("context:images/tapestry_banner.gif")
+ private Asset _icon;
+
+ public Asset getIcon()
+ {
+ return _icon;
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetInjectWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetInjectWorkerTest.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetInjectWorkerTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetInjectWorkerTest.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,111 @@
+// 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.internal.services;
+
+import java.util.Arrays;
+
+import org.apache.tapestry.annotations.Inject;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.model.MutableComponentModel;
+import org.apache.tapestry.services.AssetSource;
+import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.TransformConstants;
+import org.testng.annotations.Test;
+
+public class AssetInjectWorkerTest extends InternalBaseTestCase
+{
+ @Test
+ public void asset_field_without_annotation()
+ {
+ ClassTransformation ct = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+
+ train_findFieldsOfType(ct, AssetInjectWorker.ASSET_TYPE_NAME, "_fred");
+
+ train_getFieldAnnotation(ct, "_fred", Inject.class, null);
+
+ replay();
+
+ new AssetInjectWorker(null).transform(ct, model);
+
+ verify();
+ }
+
+ @Test
+ public void asset_field_annotation_has_blank_value()
+ {
+ ClassTransformation ct = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+ Inject annotation = newMock(Inject.class);
+
+ train_findFieldsOfType(ct, AssetInjectWorker.ASSET_TYPE_NAME, "_fred");
+
+ train_getFieldAnnotation(ct, "_fred", Inject.class, annotation);
+
+ train_value(annotation, "");
+
+ replay();
+
+ new AssetInjectWorker(null).transform(ct, model);
+
+ verify();
+ }
+
+ @Test
+ public void asset_field_with_full_annotation()
+ {
+ ClassTransformation ct = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+ Inject annotation = newMock(Inject.class);
+ AssetSource source = newMock(AssetSource.class);
+ Resource r = newResource();
+
+ train_findFieldsOfType(ct, AssetInjectWorker.ASSET_TYPE_NAME, "_fred");
+
+ train_getFieldAnnotation(ct, "_fred", Inject.class, annotation);
+
+ train_value(annotation, "foo.gif");
+
+ train_addInjectedField(ct, AssetSource.class, "assetSource", source, "as");
+
+ train_getBaseResource(model, r);
+
+ train_addInjectedField(ct, Resource.class, "baseResource", r, "res");
+ train_getResourcesFieldName(ct, "resources");
+
+ ct.makeReadOnly("_fred");
+ ct.claimField("_fred", annotation);
+
+ train_extendMethod(
+ ct,
+ TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE,
+ "{",
+ "_fred = as.findAsset(res, \"foo.gif\", resources.getLocale());",
+ "}");
+
+ replay();
+
+ new AssetInjectWorker(source).transform(ct, model);
+
+ verify();
+ }
+
+ protected final void train_findFieldsOfType(ClassTransformation transformation,
+ String typeName, String... names)
+ {
+ expect(transformation.findFieldsOfType(typeName)).andReturn(Arrays.asList(names));
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetSourceImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetSourceImplTest.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetSourceImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/AssetSourceImplTest.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,149 @@
+// 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.internal.services;
+
+import java.util.Collections;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.ioc.internal.util.ClasspathResource;
+import org.apache.tapestry.services.AssetFactory;
+import org.apache.tapestry.services.AssetSource;
+import org.testng.annotations.Test;
+
+public class AssetSourceImplTest extends InternalBaseTestCase
+{
+ private final Resource _baseResource = new ClasspathResource(
+ "org/apache/tapestry/internal/services/SimpleComponent.class");
+
+ private final Resource _rootResource = new ClasspathResource("/");
+
+ @Test
+ public void relative_asset()
+ {
+ AssetFactory factory = newAssetFactory();
+ Asset asset = newAsset();
+
+ Resource expectedResource = _baseResource.forFile("SimpleComponent_en_GB.properties");
+
+ train_getRootResource(factory, _rootResource);
+
+ train_createAsset(factory, expectedResource, asset);
+
+ Map<String, AssetFactory> configuration = Collections.singletonMap("classpath", factory);
+
+ replay();
+
+ AssetSource source = new AssetSourceImpl(configuration);
+
+ // First try creates it:
+
+ assertSame(source.findAsset(_baseResource, "SimpleComponent.properties", Locale.UK), asset);
+
+ // Second try shows that it is cached
+
+ assertSame(source.findAsset(_baseResource, "SimpleComponent.properties", Locale.UK), asset);
+
+ verify();
+ }
+
+ @Test
+ public void absolute_asset_with_known_prefix()
+ {
+ AssetFactory factory = newAssetFactory();
+ Asset asset = newAsset();
+
+ Resource expectedResource = _rootResource
+ .forFile("org/apache/tapestry/internal/services/SimpleComponent_en_GB.properties");
+
+ train_getRootResource(factory, _rootResource);
+
+ train_createAsset(factory, expectedResource, asset);
+
+ Map<String, AssetFactory> configuration = Collections.singletonMap("classpath", factory);
+
+ replay();
+
+ AssetSource source = new AssetSourceImpl(configuration);
+
+ assertSame(source.findAsset(
+ _baseResource,
+ "classpath:org/apache/tapestry/internal/services/SimpleComponent.properties",
+ Locale.UK), asset);
+
+ // Check that a leading slash is not a problem:
+
+ assertSame(source.findAsset(
+ _baseResource,
+ "classpath:/org/apache/tapestry/internal/services/SimpleComponent.properties",
+ Locale.UK), asset);
+
+ verify();
+ }
+
+ @Test
+ public void unknown_asset_prefix()
+ {
+ Map<String, AssetFactory> configuration = Collections.emptyMap();
+
+ replay();
+
+ AssetSource source = new AssetSourceImpl(configuration);
+
+ try
+ {
+ source.findAsset(
+ _baseResource,
+ "classpath:org/apache/tapestry/internal/services/SimpleComponent.properties",
+ Locale.UK);
+ unreachable();
+ }
+ catch (IllegalArgumentException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "Unknown prefix for asset path 'classpath:org/apache/tapestry/internal/services/SimpleComponent.properties'.");
+ }
+
+ verify();
+ }
+
+ @Test
+ public void missing_resource()
+ {
+ Map<String, AssetFactory> configuration = Collections.emptyMap();
+
+ replay();
+
+ AssetSource source = new AssetSourceImpl(configuration);
+
+ try
+ {
+ source.findAsset(_baseResource, "DoesNotExist.properties", Locale.UK);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertEquals(
+ ex.getMessage(),
+ "Unable to locate asset 'classpath:org/apache/tapestry/internal/services/DoesNotExist.properties' (the file does not exist).");
+ }
+
+ verify();
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java?view=diff&rev=481321&r1=481320&r2=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java Fri Dec 1 09:49:32 2006
@@ -272,9 +272,4 @@
verify();
}
- protected final void train_getClassName(ClassTransformation transformation, String className)
- {
- expect(transformation.getClassName()).andReturn(className);
- }
-
}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextAssetFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextAssetFactoryTest.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextAssetFactoryTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextAssetFactoryTest.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,64 @@
+// 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.internal.services;
+
+import org.apache.tapestry.Asset;
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.services.AssetFactory;
+import org.apache.tapestry.services.WebContext;
+import org.apache.tapestry.services.WebRequest;
+import org.testng.annotations.Test;
+
+public class ContextAssetFactoryTest extends InternalBaseTestCase
+{
+ @Test
+ public void root_resource()
+ {
+ WebContext context = newWebContext();
+ WebRequest request = newWebRequest();
+
+ replay();
+
+ AssetFactory factory = new ContextAssetFactory(request, context);
+
+ assertEquals(factory.getRootResource().toString(), "context:/");
+
+ verify();
+ }
+
+ @Test
+ public void generated_asset()
+ {
+ WebContext context = newWebContext();
+ WebRequest request = newWebRequest();
+
+ train_getContextPath(request, "/context");
+
+ replay();
+
+ AssetFactory factory = new ContextAssetFactory(request, context);
+
+ Resource r = factory.getRootResource().forFile("foo/Bar.txt");
+
+ Asset asset = factory.createAsset(r);
+
+ assertSame(asset.getResource(), r);
+ assertEquals(asset.toClientURL(), "/context/foo/Bar.txt");
+ assertEquals(asset.toString(), asset.toClientURL());
+
+ verify();
+ }
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextResourceTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextResourceTest.java?view=auto&rev=481321
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextResourceTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ContextResourceTest.java Fri Dec 1 09:49:32 2006
@@ -0,0 +1,103 @@
+// 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.internal.services;
+
+import java.net.URL;
+
+import org.apache.tapestry.internal.test.InternalBaseTestCase;
+import org.apache.tapestry.ioc.Resource;
+import org.apache.tapestry.services.WebContext;
+import org.testng.annotations.Test;
+
+public class ContextResourceTest extends InternalBaseTestCase
+{
+ @Test
+ public void get_url() throws Exception
+ {
+ URL url = getClass().getResource("ContextResourceTest.class");
+
+ WebContext context = newWebContext();
+
+ expect(context.getResource("/foo/Bar.txt")).andReturn(url);
+
+ replay();
+
+ Resource r = new ContextResource(context, "foo/Bar.txt");
+
+ assertSame(r.toURL(), url);
+
+ verify();
+ }
+
+ @Test
+ public void to_string()
+ {
+ WebContext context = newWebContext();
+
+ replay();
+
+ Resource r = new ContextResource(context, "foo/Bar.txt");
+
+ assertEquals(r.toString(), "context:foo/Bar.txt");
+
+ verify();
+ }
+
+ @Test
+ public void hash_code()
+ {
+ WebContext context1 = newWebContext();
+ WebContext context2 = newWebContext();
+
+ replay();
+
+ Resource r1 = new ContextResource(context1, "foo");
+ Resource r2 = new ContextResource(context1, "foo");
+ Resource r3 = new ContextResource(context2, "foo");
+ Resource r4 = new ContextResource(context1, "bar");
+
+ assertTrue(r1.hashCode() == r2.hashCode());
+ assertFalse(r1.hashCode() == r3.hashCode());
+ assertFalse(r1.hashCode() == r4.hashCode());
+
+ verify();
+ }
+
+ @Test
+ public void equals()
+ {
+ WebContext context1 = newWebContext();
+ WebContext context2 = newWebContext();
+ Resource r = newResource();
+
+ replay();
+
+ Resource r1 = new ContextResource(context1, "foo");
+ Resource r2 = new ContextResource(context1, "foo");
+ Resource r3 = new ContextResource(context2, "foo");
+ Resource r4 = new ContextResource(context1, "bar");
+
+ assertTrue(r1.equals(r2));
+ assertFalse(r1.equals(r3));
+ assertFalse(r1.equals(r4));
+
+ assertFalse(r1.equals(null));
+ assertTrue(r1.equals(r1));
+
+ assertFalse(r1.equals(r));
+
+ verify();
+ }
+}