Repository: tapestry-5 Updated Branches: refs/heads/master 3b8fe942b -> 64ef39cf2
TAP5-2083: Failing to load asset / stylesheet with @Import annotation in subclassed component Fixes use of @Import and @Inject @Path in a base class vs. a subclass (as long as the assets are stored in META-INF/assets). Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/64ef39cf Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/64ef39cf Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/64ef39cf Branch: refs/heads/master Commit: 64ef39cf2a2eacf94f70487a704254cc34733116 Parents: 3b8fe94 Author: Howard M. Lewis Ship <hls...@apache.org> Authored: Mon Jun 30 15:48:16 2014 -0700 Committer: Howard M. Lewis Ship <hls...@apache.org> Committed: Mon Jun 30 15:48:27 2014 -0700 ---------------------------------------------------------------------- 54_RELEASE_NOTES.md | 6 ++++++ .../internal/bindings/AssetBindingFactory.java | 4 +--- .../internal/services/AssetInjectionProvider.java | 8 +++++--- .../internal/services/AssetSourceImpl.java | 6 ++---- .../tapestry5/internal/transform/ImportWorker.java | 14 +++++++------- .../org/apache/tapestry5/services/AssetSource.java | 14 +++++++++++--- .../integration/app1/AtImportTests.groovy | 9 ++++++++- .../integration/app1/pages/LogoSubclass.java | 7 +++++++ .../integration/locallib/alpha/pages/Logo.groovy | 13 +++++++++++++ .../tapestry5/integration/app1/pages/Index.java | 1 + .../META-INF/assets/lib/alpha/feature.jpg | Bin 0 -> 25956 bytes .../META-INF/assets/lib/alpha/show-logo.js | 1 + .../integration/locallib/alpha/pages/Logo.tml | 12 ++++++++++++ 13 files changed, 74 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/54_RELEASE_NOTES.md ---------------------------------------------------------------------- diff --git a/54_RELEASE_NOTES.md b/54_RELEASE_NOTES.md index eda173b..4c80c5d 100644 --- a/54_RELEASE_NOTES.md +++ b/54_RELEASE_NOTES.md @@ -71,6 +71,12 @@ Tapestry 5.4 introduces a new module, tapestry-webresources, which provides supp CoffeeScript into JavaScript, Less into CSS, and for minimizing CSS and JavaScript. All processing takes place at runtime. +Tapestry now properly handles the case for a base class referencing assets that is subclassed into a +different library (or subclasses from a library to the application). As long as the new location, under +`META-INF/assets`, is used, then Tapestry will locate the base class asset inside the subfolder +corresponding the the base class' library. In prior releases, the resolution was against the +subclass' library, which would fail. + ## FormGroup Mixin This new mixin for Field components adds the outer `<div class="form-group">` and `<label>` elements for a Field http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBindingFactory.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBindingFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBindingFactory.java index df5207f..c0f532e 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBindingFactory.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/bindings/AssetBindingFactory.java @@ -1,5 +1,3 @@ -// Copyright 2007, 2008, 2009 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 @@ -43,7 +41,7 @@ public class AssetBindingFactory implements BindingFactory // sub-class gets instantiated, because relative path for the asset should be relative to the // base class, but will instead by relative to the subclass. - Asset asset = source.getComponentAsset(container, expression); + Asset asset = source.getComponentAsset(container, expression, container.getComponentModel().getLibraryName()); return new AssetBinding(location, description, asset); } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetInjectionProvider.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetInjectionProvider.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetInjectionProvider.java index 2dd0742..d429da0 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetInjectionProvider.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetInjectionProvider.java @@ -1,5 +1,3 @@ -// Copyright 2007, 2008, 2010, 2011 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 @@ -49,6 +47,7 @@ public class AssetInjectionProvider implements InjectionProvider2 } final String assetPath = path.value(); + final String libraryName = componentModel.getLibraryName(); ComputedValue<Asset> computedAsset = new ComputedValue<Asset>() { @@ -56,7 +55,10 @@ public class AssetInjectionProvider implements InjectionProvider2 { ComponentResources resources = context.get(ComponentResources.class); - return assetSource.getComponentAsset(resources, assetPath); + // Note how this works: the resources represents the actual instantiated class, and the libraryName + // comes from the componentModel, potentially, the componentModel of a base class (which may have + // a different library name than the subclass). + return assetSource.getComponentAsset(resources, assetPath, libraryName); } }; http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java index 140b32b..42e339b 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java @@ -1,5 +1,3 @@ -// Copyright 2006-2014 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 @@ -143,7 +141,7 @@ public class AssetSourceImpl extends LockSupport implements AssetSource return getUnlocalizedAsset(symbolSource.expandSymbols(path)); } - public Asset getComponentAsset(final ComponentResources resources, final String path) + public Asset getComponentAsset(final ComponentResources resources, final String path, final String libraryName) { assert resources != null; @@ -207,7 +205,7 @@ public class AssetSourceImpl extends LockSupport implements AssetSource // represented in the URL. // Ends with trailing slash: - String metaRoot = "META-INF/assets/" + toPathPrefix(resources.getComponentModel().getLibraryName()); + String metaRoot = "META-INF/assets/" + toPathPrefix(libraryName); String trimmedRestOfPath = restOfPath.startsWith("/") ? restOfPath.substring(1) : restOfPath; http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ImportWorker.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ImportWorker.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ImportWorker.java index debd1e4..17bddc4 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ImportWorker.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/transform/ImportWorker.java @@ -1,5 +1,3 @@ -// Copyright 2010-2012 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 @@ -114,6 +112,8 @@ public class ImportWorker implements ComponentClassTransformWorker2 { importStacks(method, annotation.stack()); + String libraryName = model.getLibraryName(); + importLibraries(componentClass, model, method, annotation.library()); importStylesheets(componentClass, model, method, annotation.stylesheet()); @@ -227,7 +227,7 @@ public class ImportWorker implements ComponentClassTransformWorker2 PlasticField assetListField = componentClass.introduceField(Asset[].class, "importedAssets_" + method.getDescription().methodName); - initializeAssetsFromPaths(expandedPaths, assetListField); + initializeAssetsFromPaths(expandedPaths, assetListField, model.getLibraryName()); addMethodAssetOperationAdvice(method, assetListField.getHandle(), operation); } @@ -237,7 +237,7 @@ public class ImportWorker implements ComponentClassTransformWorker2 return F.flow(paths).map(expandSymbols).toArray(String.class); } - private void initializeAssetsFromPaths(final String[] expandedPaths, PlasticField assetsField) + private void initializeAssetsFromPaths(final String[] expandedPaths, PlasticField assetsField, final String libraryName) { assetsField.injectComputed(new ComputedValue<Asset[]>() { @@ -245,18 +245,18 @@ public class ImportWorker implements ComponentClassTransformWorker2 { ComponentResources resources = context.get(ComponentResources.class); - return convertPathsToAssetArray(resources, expandedPaths); + return convertPathsToAssetArray(resources, expandedPaths, libraryName); } }); } - private Asset[] convertPathsToAssetArray(final ComponentResources resources, String[] assetPaths) + private Asset[] convertPathsToAssetArray(final ComponentResources resources, String[] assetPaths, final String libraryName) { return F.flow(assetPaths).map(new Mapper<String, Asset>() { public Asset map(String assetPath) { - return assetSource.getComponentAsset(resources, assetPath); + return assetSource.getComponentAsset(resources, assetPath, libraryName); } }).toArray(Asset.class); } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java index d28711e..111b2f9 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetSource.java @@ -1,5 +1,3 @@ -// Copyright 2006-2013 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 @@ -131,6 +129,12 @@ public interface AssetSource * This is the preferred location in 5.4, with compatibility for 5.3 that allows assets to be stored on the classpath * alongside Java classes and server-only resources such as templates and message catalogs. * + * <p/> + * When resolving a resource in a component that is subclass, the point of injection is the class which contains + * the injecting annotation (e.g., {@link org.apache.tapestry5.ioc.annotations.Inject} with {@link org.apache.tapestry5.annotations.Path}, + * or {@link org.apache.tapestry5.annotations.Import}). In other words, the library name for the library containing the class, + * rather than the library name of the instantiated subclass (which can be different). + * * @param resources * resources, used to identify starting location of asset (if path does not include a asset prefix). * @param path @@ -138,10 +142,14 @@ public interface AssetSource * component's library asset folder (the 5.4 and beyond way), or the to the component's Java class file (the 5.3 and earlier * way, still supported until at least 5.5). * Symbols in the path are {@linkplain org.apache.tapestry5.ioc.services.SymbolSource#expandSymbols(String) expanded}. + * @param libraryName + * The name of the library containing the component, as per {@link org.apache.tapestry5.model.ComponentModel#getLibraryName()}. + * For a subclass, the libraryName must reflect the name of the library for the parent class that forms the basis of + * injection. * @return the Asset * @throws RuntimeException * if Asset can not be found * @since 5.4 */ - Asset getComponentAsset(ComponentResources resources, String path); + Asset getComponentAsset(ComponentResources resources, String path, final String libraryName); } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AtImportTests.groovy ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AtImportTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AtImportTests.groovy index 8199f8e..8810110 100644 --- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AtImportTests.groovy +++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/AtImportTests.groovy @@ -17,7 +17,7 @@ class AtImportTests extends GroovyTapestryCoreTestCase final String locatorTemplate = "//link[contains(@href, 'via-import.css')]/preceding-sibling::link[contains(@href, '%s.css')]" - open("/AtImportWithoutStackButWithStylesheet") + open "/AtImportWithoutStackButWithStylesheet" assert isElementPresent(String.format(locatorTemplate, "bootstrap")) assert isElementPresent(String.format(locatorTemplate, "tapestry")) @@ -27,4 +27,11 @@ class AtImportTests extends GroovyTapestryCoreTestCase } + @Test + void import_and_asset_injection_in_base_class_finds_resources_there() { + openLinks "Base class Assets in sub-classes" + + assertText "//h1", "Alpha Library: Logo Demo" + } + } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/LogoSubclass.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/LogoSubclass.java b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/LogoSubclass.java new file mode 100644 index 0000000..96e3345 --- /dev/null +++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/LogoSubclass.java @@ -0,0 +1,7 @@ +package org.apache.tapestry5.integration.app1.pages; + +import org.apache.tapestry5.integration.locallib.alpha.pages.Logo; + +public class LogoSubclass extends Logo +{ +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.groovy ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.groovy new file mode 100644 index 0000000..9f4e9ba --- /dev/null +++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.groovy @@ -0,0 +1,13 @@ +package org.apache.tapestry5.integration.locallib.alpha.pages + +import org.apache.tapestry5.Asset +import org.apache.tapestry5.annotations.Import +import org.apache.tapestry5.annotations.Path +import org.apache.tapestry5.ioc.annotations.Inject + +@Import(library="show-logo.js") +class Logo { + + @Inject @Path("feature.jpg") + Asset featureImage; +} http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java index 2d9876c..42a4ffa 100644 --- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java +++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java @@ -56,6 +56,7 @@ public class Index private static final List<Item> ITEMS = CollectionFactory .newList( + new Item("LogoSubclass", "Base class Assets in sub-classes", "Assets are resolved for the parent class if that's where the annotations are."), new Item("MissingRequiredARP", "Missing Query Parameter for @ActivationRequestParameter", "Activating a page with a required @ActivationRequestParameter, but no matching query parameter, is an error."), http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/feature.jpg ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/feature.jpg b/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/feature.jpg new file mode 100644 index 0000000..6775c47 Binary files /dev/null and b/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/feature.jpg differ http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/show-logo.js ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/show-logo.js b/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/show-logo.js new file mode 100644 index 0000000..b174e0f --- /dev/null +++ b/tapestry-core/src/test/resources/META-INF/assets/lib/alpha/show-logo.js @@ -0,0 +1 @@ +document.getElementById("t5logo").setAttribute("style", null); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/64ef39cf/tapestry-core/src/test/resources/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.tml ---------------------------------------------------------------------- diff --git a/tapestry-core/src/test/resources/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.tml b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.tml new file mode 100644 index 0000000..93ca922 --- /dev/null +++ b/tapestry-core/src/test/resources/org/apache/tapestry5/integration/locallib/alpha/pages/Logo.tml @@ -0,0 +1,12 @@ +<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"> + + <h1>Alpha Library: Logo Demo</h1> + + <img id="t5logo" style="display:none;" src="${asset:tapestry.png}"/> + + <br/> + + <img src="${featureImage}"/> + +</html> +