Author: mck
Date: Sun Mar 30 13:57:47 2014
New Revision: 1583141
URL: http://svn.apache.org/r1583141
Log:
TILES-571 – Please make the significance of underscore (_) in tiles definition
filename more obvious
SPR-11491 – Doc: Tiles 3 and underscores in definition names
<quote>
… it looks like there is an issue with PostfixedApplicationResource.
This issue comes from
SpringWildcardServletTilesApplicationContext#getResources(String) ->
URLApplicationResource(String, URL) constructor -> super
PostfixedApplicationResource(String localePath) constructor. When there is an
underscore, the string after the last underscore is identified as the locale.
But clearly it's not a locale and one should be able to load
/WEB-INF/base_tiles.xml.
</quote>
Along with improving the documentation the following code changes have been made
• if the resource name contains "_" and after it there is no supported locale
language code then the whole resource name is treated as a non-localized path.
This situation prints a warning like
> No supported matching language for locale "zz". Using
/my/path_zz.html as a non-localized resource path.
• if the resource name contains "_" and after it there is a supported locale
language code but the locale constructed isn't valid/supported then the closest
supported locale is used.
This situation prints a warning like
>
For resource /my/path_en_ZZ.html the closest supported matching locale to
"en_ZZ" is "en". Using /my/path.html as resource path.
Modified:
tiles/framework/branches/TILES_3_0_X/src/site/apt/config-reference.apt
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java
Modified: tiles/framework/branches/TILES_3_0_X/src/site/apt/config-reference.apt
URL:
http://svn.apache.org/viewvc/tiles/framework/branches/TILES_3_0_X/src/site/apt/config-reference.apt?rev=1583141&r1=1583140&r2=1583141&view=diff
==============================================================================
--- tiles/framework/branches/TILES_3_0_X/src/site/apt/config-reference.apt
(original)
+++ tiles/framework/branches/TILES_3_0_X/src/site/apt/config-reference.apt Sun
Mar 30 13:57:47 2014
@@ -143,9 +143,14 @@ Configuring Tiles internals
The reason to use a custom Tiles application context could be:
- * supporting a platform not supported yet;
+ * supporting a platform not supported yet;
- * providing custom behaviour, such as loading resources in a different
manner.
+ * providing custom behaviour, such as loading resources in a different
manner.
+
+
+ When loading resources (by
{{{/tiles-request/apidocs/org/apache/tiles/request/locale/PostfixedApplicationResource.html}default}})
+ an underscore in the name of a file is used to indicate locale information.
+ See the documentation for
{{{/framework/tutorial/advanced/l10n.html}localization}}.
* Custom {TilesContainerFactory}
@@ -160,41 +165,41 @@ Configuring Tiles internals
{{{./apidocs/org/apache/tiles/factory/BasicTilesContainerFactory.html}Javadoc
documentation of BasicTilesContainerFactory}}
documents all the methods that can be overridden to use your own
configuration.
-
+
** Changing the path for the Tiles Definitions file
The <<<BasicTilesContainerFactory>>> loads the "/WEB-INF/tiles.xml" file;
the <<<CompleteAutoloadTilesContainerFactory>>>
loads all the files named "tiles*.xml" under /WEB-INF and under every
META-INF in any part of the classpath.
-
+
If this behaviour doesn't suits you, you can override the method
<<<getSources>>> and retrieve whatever resource you
prefer. Just specify the path for the default locale; Tiles will extrapolate
and load the localized files as needed.
* Custom components
These components can be used by overriding the appropriate <<<create>>>
method in a custom TilesContainerFactory.
-
+
** Custom {LocaleResolver}
-
+
The default implementation is
{{{./apidocs/org/apache/tiles/locale/impl/DefaultLocaleResolver.html}DefaultLocaleResolver}}.
** Custom {DefinitionDAO}
The default implementation is
{{{./apidocs/org/apache/tiles/definition/dao/ResolvingLocaleUrlDefinitionDAO.html}ResolvingLocaleUrlDefinitionDAO}}.
-
+
** Custom {AttributeEvaluatorFactory}
The default implementation is
{{{./apidocs/org/apache/tiles/evaluator/BasicAttributeEvaluatorFactory.html}BasicAttributeEvaluatorFactory}}.
-
+
It can be used with a number of AttributeEvaluators like:
-
- * the
{{{./apidocs/org/apache/tiles/evaluator/impl/DirectAttributeEvaluator.html}DirectAttributeEvaluator}},
- * the
{{{./apidocs/org/apache/tiles/el/ELAttributeEvaluator.html}ELAttributeEvaluator}},
+ * the
{{{./apidocs/org/apache/tiles/evaluator/impl/DirectAttributeEvaluator.html}DirectAttributeEvaluator}},
+
+ * the
{{{./apidocs/org/apache/tiles/el/ELAttributeEvaluator.html}ELAttributeEvaluator}},
+
+ * the
{{{./apidocs/org/apache/tiles/mvel/MVELAttributeEvaluator.html}MVELAttributeEvaluator}},
- * the
{{{./apidocs/org/apache/tiles/mvel/MVELAttributeEvaluator.html}MVELAttributeEvaluator}},
+ * the
{{{./apidocs/org/apache/tiles/ognl/OGNLAttributeEvaluator.html}OGNLAttributeEvaluator}}.
- * the
{{{./apidocs/org/apache/tiles/ognl/OGNLAttributeEvaluator.html}OGNLAttributeEvaluator}}.
-
Please see
{{{./xref/org/apache/tiles/extras/complete/CompleteAutoloadTilesContainerFactory.html}CompleteAutoloadTilesContainerFactory}}
for an example of how to configure those.
@@ -214,20 +219,20 @@ Configuring Tiles internals
The default implementation is
{{{./apidocs/org/apache/tiles/definition/pattern/BasicPatternDefinitionResolver.html}BasicPatternDefinitionResolver}},
that implements the <wildcard> syntax.
-
- <<<CompleteAutoloadTilesContainerFactory>>> defines a
<<<PrefixedPatternDefinitionResolver>>> to enable the use of
+
+ <<<CompleteAutoloadTilesContainerFactory>>> defines a
<<<PrefixedPatternDefinitionResolver>>> to enable the use of
both the <wildcard> syntax and the <regexp> syntax, with appropriate
prefixes.
* Registering {Renderers}
Custom
{{{/tiles-request/apidocs/org/apache/tiles/request/render/Renderer.html}Renderers}}
can be registered by overriding the methods
<<<registerAttributeRenderers>>> and <<<createDefaultAttributeRenderer>>>.
-
+
<<<BasicTilesContainerFactory>>> registers 3 renderers: <<<string>>>,
<<<template>>>, and <<<definition>>>, in order to
render plain strings, JSPs and tiles definitions.
-
- <<<CompleteAutoloadTilesContainerFactory>>> registers 5 renderers:
<<<string>>>, <<<template>>>, <<<freemarker>>>,
- <<<velocity>>> and <<<definition>>>, in order to render plain strings, JSPs,
freemarker and velocity templates
+
+ <<<CompleteAutoloadTilesContainerFactory>>> registers 5 renderers:
<<<string>>>, <<<template>>>, <<<freemarker>>>,
+ <<<velocity>>> and <<<definition>>>, in order to render plain strings, JSPs,
freemarker and velocity templates
and tiles definitions.
* Changing the {definition files}
@@ -245,6 +250,6 @@ protected List<ApplicationResource> getS
-----------
Please note that when using <<<CompleteAutoloadTilesContainerFactory>>>,
- the <<<ApplicationContext>>> loads the resources via spring, and supports
+ the <<<ApplicationContext>>> loads the resources via spring, and supports
{{{http://static.springsource.org/spring/docs/2.5.x/reference/resources.html#resources-resource-strings}the
spring syntax}} for locating resources.
Modified:
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java
URL:
http://svn.apache.org/viewvc/tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java?rev=1583141&r1=1583140&r2=1583141&view=diff
==============================================================================
---
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java
(original)
+++
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java
Sun Mar 30 13:57:47 2014
@@ -21,14 +21,18 @@
package org.apache.tiles.request.locale;
+import java.util.Arrays;
+import java.util.IllformedLocaleException;
+import java.util.List;
import java.util.Locale;
-
import org.apache.tiles.request.ApplicationResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* An ApplicationResource whose localization is managed by postfixing the file
name.
* The various localizations are file sitting next to each other, with the
locale identified in the postfix.
- *
+ *
* For instance:
* <pre>
* /WEB-INF/tiles.xml
@@ -36,13 +40,15 @@ import org.apache.tiles.request.Applicat
* /WEB-INF/tiles_it.xml
* /WEB-INF/tiles_it_IT.xml
* </pre>
- *
+ *
* Two PostfixedApplicationResources are equals if they share the same
localized path and the same class.
- *
+ *
* @version $Rev$ $Date$
*/
public abstract class PostfixedApplicationResource implements
ApplicationResource {
+ private static final Logger LOG =
LoggerFactory.getLogger(PostfixedApplicationResource.class);
+
/** The path without its suffix and its locale postfix. */
private String pathPrefix;
/** The suffix. */
@@ -69,18 +75,18 @@ public abstract class PostfixedApplicati
} else {
pathPrefix = localePath.substring(0, prefixIndex);
String localeString = localePath.substring(prefixIndex + 1,
suffixIndex);
- int countryIndex = localeString.indexOf('_');
- if (countryIndex < 0) {
- locale = new Locale(localeString);
- } else {
- int variantIndex = localeString.indexOf('_', countryIndex + 1);
- if (variantIndex < 0) {
- locale = new Locale(localeString.substring(0,
countryIndex),
- localeString.substring(countryIndex + 1));
- } else {
- locale = new Locale(localeString.substring(0,
countryIndex), localeString.substring(
- countryIndex + 1, variantIndex),
localeString.substring(variantIndex + 1));
- }
+ Locale found = localeFrom(localeString);
+ locale = validateLocale(found);
+ if (Locale.ROOT.equals(locale)) {
+ pathPrefix = suffixIndex < 0 ? localePath :
localePath.substring(0, suffixIndex);
+
+ LOG.warn("No supported matching language for locale \"" +
localeString + "\". Using "
+ + getPath() + " as a non-localized resource path. see
TILES-571");
+
+ } else if
(!localeString.equalsIgnoreCase(getPostfix(locale).substring(1))) {
+ LOG.warn("For resource " + localePath
+ + " the closest supported matching locale to \"" +
localeString + "\" is \"" + locale
+ + "\". Using " + getPath() + " as resource path. see
TILES-571");
}
}
}
@@ -193,4 +199,45 @@ public abstract class PostfixedApplicati
return false;
return true;
}
+
+ private static Locale localeFrom(String localeString) {
+ Locale.Builder builder = new Locale.Builder();
+ try {
+ int countryIndex = localeString.indexOf('_');
+ if (countryIndex < 0) {
+ builder.setLanguage(localeString);
+ } else {
+ int variantIndex = localeString.indexOf('_', countryIndex + 1);
+ builder.setLanguage(localeString.substring(0, countryIndex));
+ if (variantIndex < 0) {
+ builder.setRegion(localeString.substring(countryIndex +
1));
+ } else {
+ builder.setRegion(localeString.substring(countryIndex + 1,
variantIndex));
+ builder.setVariant(localeString.substring(variantIndex +
1));
+ }
+ }
+ } catch (IllformedLocaleException ex) {
+ LOG.debug(localeString + " is an ill-formed locale", ex);
+ }
+ return builder.build();
+ }
+
+ private static Locale validateLocale(Locale locale) {
+ List<Locale> availableLocales =
Arrays.asList(Locale.getAvailableLocales());
+
+ Locale withoutVariant = locale.getVariant().isEmpty()
+ ? locale
+ : new Locale(locale.getLanguage(), locale.getCountry());
+
+ Locale result = locale;
+ if (!availableLocales.contains(withoutVariant)) {
+ if (!result.getCountry().isEmpty()) {
+ result = new Locale(result.getLanguage());
+ }
+ if (!availableLocales.contains(result)) {
+ result = Locale.ROOT;
+ }
+ }
+ return result;
+ }
}
Modified:
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java
URL:
http://svn.apache.org/viewvc/tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java?rev=1583141&r1=1583140&r2=1583141&view=diff
==============================================================================
---
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java
(original)
+++
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java
Sun Mar 30 13:57:47 2014
@@ -53,9 +53,9 @@ public class PostfixedApplicationResourc
public long getLastModified() throws IOException {
return 0;
}
-
+
};
-
+
/**
* Test getLocalePath(String path, Locale locale).
*/
@@ -68,7 +68,7 @@ public class PostfixedApplicationResourc
assertEquals("/my/path_it_IT.html",
resource.getLocalePath(Locale.ITALY));
assertEquals("/my/path_en_GB_scotland.html",
resource.getLocalePath(new Locale("en", "GB", "scotland")));
}
-
+
@Test
public void testBuildFromString() {
TestApplicationResource resource = new
TestApplicationResource("/my/path_en_GB_scotland.html");
@@ -87,8 +87,32 @@ public class PostfixedApplicationResourc
assertEquals("/my/path.html", resource.getLocalePath());
assertEquals("/my/path.html", resource.getPath());
assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_zz.html");
+ assertEquals("/my/path_zz.html", resource.getLocalePath());
+ assertEquals("/my/path_zz.html", resource.getPath());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_en_ZZ.html");
+ assertEquals("/my/path_en.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(new Locale("en"), resource.getLocale());
+ resource = new TestApplicationResource("/my/path_tiles.html");
+ assertEquals("/my/path_tiles.html", resource.getLocalePath());
+ assertEquals("/my/path_tiles.html", resource.getPath());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new
TestApplicationResource("/my/path_longwordthatbreaksISO639.html");
+ assertEquals("/my/path_longwordthatbreaksISO639.html",
resource.getLocalePath());
+ assertEquals("/my/path_longwordthatbreaksISO639.html",
resource.getPath());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_en_tiles.html");
+ assertEquals("/my/path_en.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(new Locale("en"), resource.getLocale());
+ resource = new
TestApplicationResource("/my/path_en_longwordthatbreaksISO3166.html");
+ assertEquals("/my/path_en.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(new Locale("en"), resource.getLocale());
}
-
+
@Test
public void testBuildFromStringAndLocale() {
TestApplicationResource resource = new
TestApplicationResource("/my/path.html", new Locale("en", "GB", "scotland"));
Modified:
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java
URL:
http://svn.apache.org/viewvc/tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java?rev=1583141&r1=1583140&r2=1583141&view=diff
==============================================================================
---
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java
(original)
+++
tiles/request/branches/TREQ_1_0_X/tiles-request-api/src/test/java/org/apache/tiles/request/locale/URLApplicationResourceTest.java
Sun Mar 30 13:57:47 2014
@@ -97,6 +97,42 @@ public class URLApplicationResourceTest
assertEquals("file:/", resource.getURL().toString());
assertEquals("/", resource.getFile().toString());
assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_zz.html", new
URL("file:///"));
+ assertEquals("/my/path_zz.html", resource.getLocalePath());
+ assertEquals("/my/path_zz.html", resource.getPath());
+ assertEquals("file:/", resource.getURL().toString());
+ assertEquals("/", resource.getFile().toString());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_en_ZZ.html", new
URL("file:///"));
+ assertEquals("/my/path_en.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals("file:/", resource.getURL().toString());
+ assertEquals("/", resource.getFile().toString());
+ assertEquals(new Locale("en"), resource.getLocale());
+ resource = new TestApplicationResource("/my/path_tiles.html", new
URL("file:///"));
+ assertEquals("/my/path_tiles.html", resource.getLocalePath());
+ assertEquals("/my/path_tiles.html", resource.getPath());
+ assertEquals("file:/", resource.getURL().toString());
+ assertEquals("/", resource.getFile().toString());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new
TestApplicationResource("/my/path_longwordthatbreaksISO639.html", new
URL("file:///"));
+ assertEquals("/my/path_longwordthatbreaksISO639.html",
resource.getLocalePath());
+ assertEquals("/my/path_longwordthatbreaksISO639.html",
resource.getPath());
+ assertEquals("file:/", resource.getURL().toString());
+ assertEquals("/", resource.getFile().toString());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_en_tiles.html", new
URL("file:///"));
+ assertEquals("/my/path_en.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals("file:/", resource.getURL().toString());
+ assertEquals("/", resource.getFile().toString());
+ assertEquals(new Locale("en"), resource.getLocale());
+ resource = new
TestApplicationResource("/my/path_en_longwordthatbreaksISO3166.html", new
URL("file:///"));
+ assertEquals("/my/path_en.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals("file:/", resource.getURL().toString());
+ assertEquals("/", resource.getFile().toString());
+ assertEquals(new Locale("en"), resource.getLocale());
}
@Test