You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by jd...@apache.org on 2010/09/08 08:40:03 UTC

svn commit: r993630 - in /wicket/trunk: wicket-util/src/main/java/org/apache/wicket/util/resource/ wicket/src/main/java/org/apache/wicket/markup/ wicket/src/main/java/org/apache/wicket/request/mapper/ wicket/src/main/java/org/apache/wicket/request/reso...

Author: jdonnerstag
Date: Wed Sep  8 06:40:02 2010
New Revision: 993630

URL: http://svn.apache.org/viewvc?rev=993630&view=rev
Log:
started refactoring ResourceNameIterator and ResourceStream to make the locale, style etc. available for which the resource was found. Will eventually allow to remove duplicate code e.g. in PackageResource.

Added:
    wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/ResourceUtils.java
Modified:
    wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/AbstractResourceStream.java
    wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/IResourceStream.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupResourceStream.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapper.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/request/resource/ResourceReference.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ExtensionResourceNameIterator.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/LocaleResourceNameIterator.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceNameIterator.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceStreamLocator.java
    wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java
    wicket/trunk/wicket/src/test/java/org/apache/wicket/util/resource/ResourceTest.java

Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/AbstractResourceStream.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/AbstractResourceStream.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/AbstractResourceStream.java (original)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/AbstractResourceStream.java Wed Sep  8 06:40:02 2010
@@ -39,6 +39,8 @@ public abstract class AbstractResourceSt
 	/** Charset for resource */
 	private Charset charset;
 	private Locale locale;
+	private String style;
+	private String variation;
 
 	/**
 	 * Sets the character set used for reading this resource.
@@ -117,6 +119,38 @@ public abstract class AbstractResourceSt
 	}
 
 	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#getStyle()
+	 */
+	public String getStyle()
+	{
+		return style;
+	}
+
+	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#getVariation()
+	 */
+	public String getVariation()
+	{
+		return variation;
+	}
+
+	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#setStyle(java.lang.String)
+	 */
+	public void setStyle(String style)
+	{
+		this.style = style;
+	}
+
+	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#setVariation(java.lang.String)
+	 */
+	public void setVariation(String variation)
+	{
+		this.variation = variation;
+	}
+
+	/**
 	 * @see org.apache.wicket.util.resource.IResourceStream#length()
 	 */
 	public long length()

Modified: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/IResourceStream.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/IResourceStream.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/IResourceStream.java (original)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/IResourceStream.java Wed Sep  8 06:40:02 2010
@@ -88,4 +88,32 @@ public interface IResourceStream extends
 	 *            The Locale where this stream did resolve to.
 	 */
 	void setLocale(Locale locale);
+
+	/**
+	 * @return The Style where this stream did resolve to
+	 */
+	String getStyle();
+
+	/**
+	 * This method shouldn't be used for the outside, It is used by the Loaders to set the resolved
+	 * Style.
+	 * 
+	 * @param style
+	 *            The style where this stream did resolve to.
+	 */
+	void setStyle(String style);
+
+	/**
+	 * @return The Variation where this stream did resolve to
+	 */
+	String getVariation();
+
+	/**
+	 * This method shouldn't be used for the outside, It is used by the Loaders to set the resolved
+	 * variation.
+	 * 
+	 * @param variation
+	 *            The Variation where this stream did resolve to.
+	 */
+	void setVariation(String variation);
 }

Added: wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/ResourceUtils.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/ResourceUtils.java?rev=993630&view=auto
==============================================================================
--- wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/ResourceUtils.java (added)
+++ wicket/trunk/wicket-util/src/main/java/org/apache/wicket/util/resource/ResourceUtils.java Wed Sep  8 06:40:02 2010
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.wicket.util.resource;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.wicket.util.collections.ConcurrentHashSet;
+import org.apache.wicket.util.string.Strings;
+
+/**
+ * 
+ * @author Juergen Donnerstag
+ */
+public class ResourceUtils
+{
+	private static final Pattern LOCALE_PATTERN = Pattern.compile("_([a-z]{2})(_([A-Z]{2})(_([^_]+))?)?$");
+
+	private final static Set<String> isoCountries = new ConcurrentHashSet<String>(
+		Arrays.asList(Locale.getISOCountries()));
+
+	private final static Set<String> isoLanguages = new ConcurrentHashSet<String>(
+		Arrays.asList(Locale.getISOLanguages()));
+
+	/**
+	 * Construct.
+	 */
+	private ResourceUtils()
+	{
+	}
+
+	/**
+	 * Extract the locale from the filename
+	 * 
+	 * @param path
+	 *            The file path
+	 * @return The updated path, without the locale
+	 */
+	public static PathLocale getLocaleFromFilename(String path)
+	{
+		String extension = "";
+		int pos = path.indexOf('.');
+		if (pos != -1)
+		{
+			extension = path.substring(pos);
+			path = path.substring(0, pos);
+		}
+
+		String filename = Strings.lastPathComponent(path, '/');
+		Matcher matcher = LOCALE_PATTERN.matcher(filename);
+		if (matcher.find())
+		{
+			String language = matcher.group(1);
+			String country = matcher.group(3);
+			String variant = matcher.group(5);
+
+			// did we find a language?
+			if (language != null)
+			{
+				if (isoLanguages.contains(language) == false)
+				{
+					language = null;
+					country = null;
+					variant = null;
+				}
+			}
+
+			// did we find a country?
+			if ((language != null) && (country != null))
+			{
+				if (isoCountries.contains(country) == false)
+				{
+					country = null;
+					variant = null;
+				}
+			}
+
+			if (language != null)
+			{
+				pos = path.length() - filename.length() + matcher.start();
+				String basePath = path.substring(0, pos) + extension;
+
+				Locale locale = new Locale(language, country != null ? country : "",
+					variant != null ? variant : "");
+
+				return new PathLocale(basePath, locale);
+			}
+		} // else skip the whole thing... probably user specific underscores used
+
+		return new PathLocale(path, null);
+	}
+
+	/**
+	 * 
+	 */
+	public static class PathLocale
+	{
+		/** */
+		public final String path;
+
+		/** */
+		public final Locale locale;
+
+		/**
+		 * @param path
+		 * @param locale
+		 */
+		public PathLocale(final String path, final Locale locale)
+		{
+			this.path = path;
+			this.locale = locale;
+		}
+	}
+}

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupResourceStream.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupResourceStream.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupResourceStream.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/markup/MarkupResourceStream.java Wed Sep  8 06:40:02 2010
@@ -347,6 +347,38 @@ public class MarkupResourceStream implem
 	}
 
 	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#getStyle()
+	 */
+	public String getStyle()
+	{
+		return resourceStream.getStyle();
+	}
+
+	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#getVariation()
+	 */
+	public String getVariation()
+	{
+		return resourceStream.getVariation();
+	}
+
+	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#setStyle(java.lang.String)
+	 */
+	public void setStyle(String style)
+	{
+		resourceStream.setStyle(style);
+	}
+
+	/**
+	 * @see org.apache.wicket.util.resource.IResourceStream#setVariation(java.lang.String)
+	 */
+	public void setVariation(String variation)
+	{
+		resourceStream.setVariation(variation);
+	}
+
+	/**
 	 * 
 	 * @see java.lang.Object#toString()
 	 */

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapper.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapper.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapper.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/request/mapper/BasicResourceReferenceMapper.java Wed Sep  8 06:40:02 2010
@@ -185,6 +185,7 @@ class BasicResourceReferenceMapper exten
 		{
 			ResourceReferenceRequestHandler referenceRequestHandler = (ResourceReferenceRequestHandler)requestHandler;
 			ResourceReference reference = referenceRequestHandler.getResourceReference();
+
 			Url url = new Url();
 
 			List<String> segments = url.getSegments();

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/request/resource/ResourceReference.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/request/resource/ResourceReference.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/request/resource/ResourceReference.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/request/resource/ResourceReference.java Wed Sep  8 06:40:02 2010
@@ -293,6 +293,15 @@ public abstract class ResourceReference 
 		{
 			return Objects.hashCode(getLocale(), getStyle(), getVariation());
 		}
+
+		/**
+		 * @see java.lang.Object#toString()
+		 */
+		@Override
+		public String toString()
+		{
+			return "locale: " + locale + "; style: " + style + "; variation: " + variation;
+		}
 	}
 
 	/**

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ExtensionResourceNameIterator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ExtensionResourceNameIterator.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ExtensionResourceNameIterator.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ExtensionResourceNameIterator.java Wed Sep  8 06:40:02 2010
@@ -22,34 +22,13 @@ import org.apache.wicket.util.string.Str
 
 
 /**
- * Contains the logic to build the various combinations of file path, style, variation and locale
- * required while searching for Wicket resources. The full filename will be built like:
- * &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;.
- * <p>
- * Resource matches will be attempted in the following order:
- * <ol>
- * <li>1. &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
- * <li>2. &lt;path&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
- * <li>3. &lt;path&gt;_&lt;style&gt;.&lt;extension&gt;</li>
- * <li>4. &lt;path&gt;.&lt;extension&gt;</li>
- * </ol>
- * <p>
- * Locales may contain a language, a country and a region or variant. Combinations of these
- * components will be attempted in the following order:
- * <ol>
- * <li>locale.toString() see javadoc for Locale for more details</li>
- * <li>&lt;language&gt;_&lt;country&gt;</li>
- * <li>&lt;language&gt;</li>
- * </ol>
+ * Iterate over a list of 'comma' separated strings. If an empty string is provided, hasNext() will
+ * successfully return once with next() returning an empty string ("").
  * 
  * @author Juergen Donnerstag
- * @author Jonathan Locke
  */
 public class ExtensionResourceNameIterator implements Iterator<String>
 {
-	/** The base path */
-	private final String path;
-
 	private final String[] extensions;
 
 	private int index;
@@ -57,37 +36,20 @@ public class ExtensionResourceNameIterat
 	/**
 	 * Construct.
 	 * 
-	 * @param path
 	 * @param extension
+	 * @param separatorChar
 	 */
-	public ExtensionResourceNameIterator(String path, final String extension)
+	public ExtensionResourceNameIterator(final String extension, final char separatorChar)
 	{
-		if ((extension == null) && (path.indexOf('.') != -1))
-		{
-			// Get the extension from the path provided
-			extensions = new String[] { "." + Strings.lastPathComponent(path, '.') };
-			path = Strings.beforeLastPathComponent(path, '.');
-		}
-		else if (extension != null)
+		// Extension can be a comma separated list
+		String[] extensions = Strings.split(extension, separatorChar);
+		if (extensions.length == 0)
 		{
-			// Extension can be a comma separated list
-			extensions = Strings.split(extension, ',');
-			for (int i = extensions.length - 1; i >= 0; i--)
-			{
-				extensions[i] = extensions[i].trim();
-				if (!extensions[i].startsWith("."))
-				{
-					extensions[i] = "." + extensions[i];
-				}
-			}
-		}
-		else
-		{
-			extensions = new String[1];
-			extensions[0] = ".";
+			// Fail safe: hasNext() needs to return at least once with true.
+			extensions = new String[] { "" };
 		}
+		this.extensions = extensions;
 
-		this.path = path;
 		index = 0;
 	}
 
@@ -101,15 +63,25 @@ public class ExtensionResourceNameIterat
 	}
 
 	/**
-	 * 
-	 * @see java.util.Iterator#next()
+	 * @return The next filename extension. A leading '.' will be removed.
 	 */
 	public String next()
 	{
-		return path + extensions[index++];
+		String rtn = extensions[index++].trim();
+		return rtn.startsWith(".") ? rtn.substring(1) : rtn;
+	}
+
+	/**
+	 * @return Assuming you've called next() already, it'll return the very same value.
+	 */
+	public final String getExtension()
+	{
+		String rtn = extensions[index - 1].trim();
+		return rtn.startsWith(".") ? rtn.substring(1) : rtn;
 	}
 
 	/**
+	 * Noop.
 	 * 
 	 * @see java.util.Iterator#remove()
 	 */

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/LocaleResourceNameIterator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/LocaleResourceNameIterator.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/LocaleResourceNameIterator.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/LocaleResourceNameIterator.java Wed Sep  8 06:40:02 2010
@@ -23,34 +23,14 @@ import org.apache.wicket.util.string.Str
 
 
 /**
- * Contains the logic to build the various combinations of file path, style, variation and locale
- * required while searching for Wicket resources. The full filename will be built like:
- * &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;.
- * <p>
- * Resource matches will be attempted in the following order:
- * <ol>
- * <li>1. &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
- * <li>2. &lt;path&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
- * <li>3. &lt;path&gt;_&lt;style&gt;.&lt;extension&gt;</li>
- * <li>4. &lt;path&gt;.&lt;extension&gt;</li>
- * </ol>
- * <p>
- * Locales may contain a language, a country and a region or variant. Combinations of these
- * components will be attempted in the following order:
- * <ol>
- * <li>locale.toString() see javadoc for Locale for more details</li>
- * <li>&lt;language&gt;_&lt;country&gt;</li>
- * <li>&lt;language&gt;</li>
- * </ol>
+ * Given a Locale it'll iterate over all possible combinations of the attrs making up the Locale.
+ * Starting the Locale provided to more 'weaker' combinations. The latest one will be no Locale in
+ * which case an empty string will be returned.
  * 
  * @author Juergen Donnerstag
- * @author Jonathan Locke
  */
 public class LocaleResourceNameIterator implements Iterator<String>
 {
-	/** The base path */
-	private final String path;
-
 	/** The locale (see Session) */
 	private final Locale locale;
 
@@ -60,24 +40,13 @@ public class LocaleResourceNameIterator 
 	private final boolean strict;
 
 	/**
-	 * While iterating the various combinations, it will always contain the current combination used
-	 * to create the path
-	 */
-	private Locale currentLocale;
-
-	/** Internal: used to compare with previous path to avoid duplicates */
-	private String currentPath;
-
-	/**
 	 * Construct.
 	 * 
-	 * @param path
 	 * @param locale
 	 * @param strict
 	 */
-	public LocaleResourceNameIterator(final String path, final Locale locale, boolean strict)
+	public LocaleResourceNameIterator(final Locale locale, boolean strict)
 	{
-		this.path = path;
 		this.locale = locale;
 		this.strict = strict;
 	}
@@ -87,7 +56,20 @@ public class LocaleResourceNameIterator 
 	 */
 	public Locale getLocale()
 	{
-		return currentLocale;
+		if (state == 1)
+		{
+			// Language, country, variation
+			return locale;
+		}
+		else if (state == 2)
+		{
+			return new Locale(locale.getLanguage(), locale.getCountry());
+		}
+		else if (state == 3)
+		{
+			return new Locale(locale.getLanguage());
+		}
+		return null;
 	}
 
 	/**
@@ -106,7 +88,6 @@ public class LocaleResourceNameIterator 
 	}
 
 	/**
-	 * 
 	 * @see java.util.Iterator#next()
 	 */
 	public String next()
@@ -114,16 +95,14 @@ public class LocaleResourceNameIterator 
 		if (locale == null)
 		{
 			state = 999;
-			return path;
+			return "";
 		}
 
 		// 1. Apply Locale default toString() implementation. See Locale.
 		if (state == 0)
 		{
 			state++;
-			currentLocale = locale;
-			currentPath = path + '_' + locale.toString();
-			return currentPath;
+			return '_' + locale.toString();
 		}
 
 		// Get language and country, either of which may be the empty string
@@ -137,9 +116,8 @@ public class LocaleResourceNameIterator 
 
 			if (!Strings.isEmpty(language) && !Strings.isEmpty(country))
 			{
-				currentLocale = new Locale(language, country);
-				String newPath = path + '_' + language + '_' + country;
-				if (currentPath.equals(newPath) == false)
+				String newPath = '_' + language + '_' + country;
+				if (locale.toString().equals(newPath) == false)
 				{
 					return newPath;
 				}
@@ -153,16 +131,13 @@ public class LocaleResourceNameIterator 
 
 			if (!Strings.isEmpty(language))
 			{
-				currentLocale = new Locale(language);
-				return path + '_' + language;
+				return '_' + language;
 			}
 		}
 
 		// 4. The path only; without locale
 		state++;
-
-		currentLocale = null;
-		return path;
+		return "";
 	}
 
 	/**

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceNameIterator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceNameIterator.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceNameIterator.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceNameIterator.java Wed Sep  8 06:40:02 2010
@@ -16,21 +16,17 @@
  */
 package org.apache.wicket.util.resource.locator;
 
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.Locale;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.wicket.WicketRuntimeException;
-import org.apache.wicket.util.collections.ConcurrentHashSet;
 import org.apache.wicket.util.string.Strings;
 
 /**
- * Contains the logic to locate a resource based on a path, a style (see
- * {@link org.apache.wicket.Session}), a locale and a extension strings. The full filename will be
- * built like: &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;.
+ * Contains the logic to locate a resource based on a path, style (see
+ * {@link org.apache.wicket.Session}), variation, locale and extension strings. The full filename
+ * will be built like:
+ * &lt;path&gt;_&lt;variation&gt;_&lt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;.
  * <p>
  * Resource matches will be attempted in the following order:
  * <ol>
@@ -54,35 +50,30 @@ import org.apache.wicket.util.string.Str
  */
 public class ResourceNameIterator implements Iterator<String>
 {
-	private static final Pattern LOCALE_PATTERN = Pattern.compile("_([a-z]{2})(_([A-Z]{2})(_([^_]+))?)?$");
+	// The base path without extension, style, locale etc.
+	private final String path;
+
+	// The extensions (comma separated) to search for the resource file
+	private final String extensions;
 
 	// The locale to search for the resource file
 	private final Locale locale;
 
-	// The extensions (comma separated) to search for the resource file
-	private final String extensions;
+	// Do not test any combinations. Just return the full path based on the locale, style etc.
+	// provided. Only iterate over the extensions provided.
+	private final boolean strict;
 
 	// The various iterators used to locate the resource file
-	private final Iterator<String> styleIterator;
+	private final StyleAndVariationResourceNameIterator styleIterator;
 	private LocaleResourceNameIterator localeIterator;
-	private Iterator<String> extenstionsIterator;
-
-	// The latest exact Locale used
-	private Locale currentLocale;
-
-	private final static Set<String> isoCountries = new ConcurrentHashSet<String>(
-		Arrays.asList(Locale.getISOCountries()));
-
-	private final static Set<String> isoLanguages = new ConcurrentHashSet<String>(
-		Arrays.asList(Locale.getISOLanguages()));
-
-	private final boolean strict;
+	private ExtensionResourceNameIterator extensionsIterator;
 
 	/**
 	 * Construct.
 	 * 
 	 * @param path
-	 *            The path of the resource without extension
+	 *            The path of the resource. In case the parameter 'extensions' is null, the path
+	 *            will be checked and if a filename extension is present, it'll be used instead.
 	 * @param style
 	 *            A theme or style (see {@link org.apache.wicket.Session})
 	 * @param variation
@@ -91,88 +82,66 @@ public class ResourceNameIterator implem
 	 *            The Locale to apply
 	 * @param extensions
 	 *            the filname's extensions (comma separated)
-	 * 
 	 * @param strict
-	 *            whether other combinations should be tried
+	 *            If false, weaker combinations of style, locale, etc. are tested as well
 	 */
-	public ResourceNameIterator(String path, final String style, final String variation,
+	public ResourceNameIterator(final String path, final String style, final String variation,
 		final Locale locale, final String extensions, boolean strict)
 	{
 		this.locale = locale;
-		if ((extensions == null) && (path.indexOf('.') != -1))
+		if ((extensions == null) && (path != null) && (path.indexOf('.') != -1))
 		{
 			this.extensions = Strings.afterLast(path, '.');
-			path = Strings.beforeLast(path, '.');
+			this.path = Strings.beforeLast(path, '.');
 		}
 		else
 		{
 			this.extensions = extensions;
+			this.path = path;
 		}
 
-		path = getLocaleFromFilename(path);
-
-		styleIterator = new StyleAndVariationResourceNameIterator(path, style, variation);
+		styleIterator = newStyleAndVariationResourceNameIterator(style, variation);
 		this.strict = strict;
 	}
 
 	/**
-	 * Extract the locale from the filename in case where the user
+	 * Get the exact Locale which has been used for the latest resource path.
 	 * 
-	 * @param path
-	 *            The file path
-	 * @return The updated path, without the locale
-	 * @TODO That should really be external to RNI in a helper kind of class
-	 */
-	protected String getLocaleFromFilename(String path)
-	{
-		final String filename = Strings.lastPathComponent(path, '/');
-		Matcher matcher = LOCALE_PATTERN.matcher(filename);
-		if (matcher.find())
-		{
-			String language = matcher.group(1);
-			String country = matcher.group(3);
-			String variant = matcher.group(5);
-
-			// did we find a language?
-			if (language != null)
-			{
-				if (isoLanguages.contains(language) == false)
-				{
-					language = null;
-					country = null;
-					variant = null;
-				}
-			}
-
-			// did we find a country?
-			if ((language != null) && (country != null))
-			{
-				if (isoCountries.contains(country) == false)
-				{
-					country = null;
-					variant = null;
-				}
-			}
+	 * @return current Locale
+	 */
+	public final Locale getLocale()
+	{
+		return localeIterator.getLocale();
+	}
 
-			if (language != null)
-			{
-				path = path.substring(0, path.length() - filename.length() + matcher.start());
-				localeIterator = new LocaleResourceNameIterator(path, new Locale(language,
-					country != null ? country : "", variant != null ? variant : ""), strict);
-			}
-		} // else skip the whole thing... probably user specific underscores used
+	/**
+	 * Get the exact Style which has been used for the latest resource path.
+	 * 
+	 * @return current Style
+	 */
+	public final String getStyle()
+	{
+		return styleIterator.getStyle();
+	}
 
-		return path;
+	/**
+	 * Get the exact Variation which has been used for the latest resource path.
+	 * 
+	 * @return current Variation
+	 */
+	public final String getVariation()
+	{
+		return styleIterator.getVariation();
 	}
 
 	/**
-	 * Get the exact Locale which has been used for the latest resource path.
+	 * Get the exact filename extension used for the latest resource path.
 	 * 
-	 * @return current Locale
+	 * @return current filename extension
 	 */
-	public final Locale getLocale()
+	public final String getExtension()
 	{
-		return currentLocale;
+		return extensionsIterator.getExtension();
 	}
 
 	/**
@@ -181,17 +150,17 @@ public class ResourceNameIterator implem
 	public boolean hasNext()
 	{
 		// Most inner loop. Loop through all extensions provided
-		if (extenstionsIterator != null)
+		if (extensionsIterator != null)
 		{
-			if (extenstionsIterator.hasNext() == true)
+			if (extensionsIterator.hasNext() == true)
 			{
 				return true;
 			}
 
 			// If there are no more extensions, than return to the next outer
-			// loop (locale), get the next value from that loop and start
+			// loop (locale). Get the next value from that loop and start
 			// over again with the first extension in the list.
-			extenstionsIterator = null;
+			extensionsIterator = null;
 		}
 
 		// 2nd inner loop: Loop through all Locale combinations
@@ -199,12 +168,10 @@ public class ResourceNameIterator implem
 		{
 			while (localeIterator.hasNext())
 			{
-				// Get the next Locale from the iterator and start the next
-				// inner iterator over again.
-				String newPath = localeIterator.next();
-				currentLocale = localeIterator.getLocale();
-				extenstionsIterator = new ExtensionResourceNameIterator(newPath, extensions);
-				if (extenstionsIterator.hasNext() == true)
+				localeIterator.next();
+
+				extensionsIterator = newExtensionResourceNameIterator(extensions);
+				if (extensionsIterator.hasNext() == true)
 				{
 					return true;
 				}
@@ -212,19 +179,18 @@ public class ResourceNameIterator implem
 			localeIterator = null;
 		}
 
-		// Most outer loop: Loop through all combinations of styles and
-		// variations
+		// Most outer loop: Loop through all combinations of styles and variations
 		while (styleIterator.hasNext())
 		{
-			String newPath = styleIterator.next();
+			styleIterator.next();
 
-			localeIterator = new LocaleResourceNameIterator(newPath, locale, strict);
+			localeIterator = newLocaleResourceNameIterator(locale, strict);
 			while (localeIterator.hasNext())
 			{
-				newPath = localeIterator.next();
-				currentLocale = localeIterator.getLocale();
-				extenstionsIterator = new ExtensionResourceNameIterator(newPath, extensions);
-				if (extenstionsIterator.hasNext() == true)
+				localeIterator.next();
+
+				extensionsIterator = newExtensionResourceNameIterator(extensions);
+				if (extensionsIterator.hasNext() == true)
 				{
 					return true;
 				}
@@ -245,15 +211,70 @@ public class ResourceNameIterator implem
 	 */
 	public String next()
 	{
-		if (extenstionsIterator != null)
+		if (extensionsIterator != null)
 		{
-			return extenstionsIterator.next();
+			extensionsIterator.next();
+
+			return toString();
 		}
 		throw new WicketRuntimeException(
 			"Illegal call of next(). Iterator not properly initialized");
 	}
 
 	/**
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString()
+	{
+		return path + prepend(getVariation(), '_') + prepend(getStyle(), '_') +
+			prepend(getLocale(), '_') + prepend(getExtension(), '.');
+	}
+
+	/**
+	 * 
+	 * @param string
+	 * @param prepend
+	 * @return The string prepended with the char
+	 */
+	private String prepend(Object string, char prepend)
+	{
+		return (string != null) ? prepend + string.toString() : "";
+	}
+
+	/**
+	 * @param locale
+	 * @param strict
+	 * @return New iterator
+	 */
+	protected LocaleResourceNameIterator newLocaleResourceNameIterator(final Locale locale,
+		boolean strict)
+	{
+		return new LocaleResourceNameIterator(locale, strict);
+	}
+
+	/**
+	 * 
+	 * @param style
+	 * @param variation
+	 * @return new iterator
+	 */
+	protected StyleAndVariationResourceNameIterator newStyleAndVariationResourceNameIterator(
+		final String style, final String variation)
+	{
+		return new StyleAndVariationResourceNameIterator(style, variation);
+	}
+
+	/**
+	 * @param extensions
+	 * @return New iterator
+	 */
+	protected ExtensionResourceNameIterator newExtensionResourceNameIterator(final String extensions)
+	{
+		return new ExtensionResourceNameIterator(extensions, ',');
+	}
+
+	/**
 	 * @see java.util.Iterator#remove()
 	 */
 	public void remove()

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceStreamLocator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceStreamLocator.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceStreamLocator.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/ResourceStreamLocator.java Wed Sep  8 06:40:02 2010
@@ -22,7 +22,9 @@ import java.util.Locale;
 import org.apache.wicket.Application;
 import org.apache.wicket.util.file.IResourceFinder;
 import org.apache.wicket.util.resource.IResourceStream;
+import org.apache.wicket.util.resource.ResourceUtils;
 import org.apache.wicket.util.resource.UrlResourceStream;
+import org.apache.wicket.util.resource.ResourceUtils.PathLocale;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -116,11 +118,24 @@ public class ResourceStreamLocator imple
 		return locate(clazz, path, style, variation, locale, extension, false);
 	}
 
-	public IResourceStream locate(Class<?> clazz, String path, String style, String variation,
-		Locale locale, String extension, boolean strict)
+	/**
+	 * 
+	 * @see org.apache.wicket.util.resource.locator.IResourceStreamLocator#locate(java.lang.Class,
+	 *      java.lang.String, java.lang.String, java.lang.String, java.util.Locale,
+	 *      java.lang.String, boolean)
+	 */
+	public IResourceStream locate(final Class<?> clazz, String path, final String style,
+		final String variation, Locale locale, final String extension, final boolean strict)
 	{
-		// Try the various combinations of style, locale and extension to find
-		// the resource.
+		// If path contains a locale, than it'll replace the locale provided to this method
+		PathLocale data = ResourceUtils.getLocaleFromFilename(path);
+		if ((data != null) && (data.locale != null))
+		{
+			path = data.path;
+			locale = data.locale;
+		}
+
+		// Try the various combinations of style, locale and extension to find the resource.
 		ResourceNameIterator iter = new ResourceNameIterator(path, style, variation, locale,
 			extension, strict);
 		while (iter.hasNext())
@@ -131,6 +146,8 @@ public class ResourceStreamLocator imple
 			if (stream != null)
 			{
 				stream.setLocale(iter.getLocale());
+				stream.setStyle(iter.getStyle());
+				stream.setVariation(iter.getVariation());
 				return stream;
 			}
 		}

Modified: wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java (original)
+++ wicket/trunk/wicket/src/main/java/org/apache/wicket/util/resource/locator/StyleAndVariationResourceNameIterator.java Wed Sep  8 06:40:02 2010
@@ -19,34 +19,12 @@ package org.apache.wicket.util.resource.
 import java.util.Iterator;
 
 /**
- * Contains the logic to build the various combinations of file path, style and locale required
- * while searching for Wicket resources. The full filename will be built like:
- * &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;.
- * <p>
- * Resource matches will be attempted in the following order:
- * <ol>
- * <li>1. &lt;path&gt;_&lt;style&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
- * <li>2. &lt;path&gt;_&lt;locale&gt;.&lt;extension&gt;</li>
- * <li>3. &lt;path&gt;_&lt;style&gt;.&lt;extension&gt;</li>
- * <li>4. &lt;path&gt;.&lt;extension&gt;</li>
- * </ol>
- * <p>
- * Locales may contain a language, a country and a region or variant. Combinations of these
- * components will be attempted in the following order:
- * <ol>
- * <li>locale.toString() see javadoc for Locale for more details</li>
- * <li>&lt;language&gt;_&lt;country&gt;</li>
- * <li>&lt;language&gt;</li>
- * </ol>
+ * Iterate over all possible combinations of style and variation
  * 
  * @author Juergen Donnerstag
- * @author Jonathan Locke
  */
 public class StyleAndVariationResourceNameIterator implements Iterator<String>
 {
-	/** The base path */
-	private final String path;
-
 	/** The style (see Session) */
 	private final String style;
 
@@ -59,14 +37,11 @@ public class StyleAndVariationResourceNa
 	/**
 	 * Construct.
 	 * 
-	 * @param path
 	 * @param style
 	 * @param variation
 	 */
-	public StyleAndVariationResourceNameIterator(final String path, final String style,
-		final String variation)
+	public StyleAndVariationResourceNameIterator(final String style, final String variation)
 	{
-		this.path = path;
 		this.style = style;
 		this.variation = variation;
 	}
@@ -81,6 +56,7 @@ public class StyleAndVariationResourceNa
 	}
 
 	/**
+	 * The return value will always be null. Use getStyle() and getVariation() instead.
 	 * 
 	 * @see java.util.Iterator#next()
 	 */
@@ -91,7 +67,7 @@ public class StyleAndVariationResourceNa
 			state++;
 			if ((style != null) && (variation != null))
 			{
-				return path + '_' + variation + '_' + style;
+				return null;
 			}
 		}
 
@@ -100,7 +76,7 @@ public class StyleAndVariationResourceNa
 			state++;
 			if (style != null)
 			{
-				return path + '_' + style;
+				return null;
 			}
 		}
 
@@ -109,12 +85,28 @@ public class StyleAndVariationResourceNa
 			state++;
 			if (variation != null)
 			{
-				return path + '_' + variation;
+				return null;
 			}
 		}
 
 		state = 4;
-		return path;
+		return null;
+	}
+
+	/**
+	 * @return Gets the style related to the iterator state
+	 */
+	public final String getStyle()
+	{
+		return ((state == 1) || (state == 2)) ? style : null;
+	}
+
+	/**
+	 * @return Gets the variation related to the iterator state
+	 */
+	public final String getVariation()
+	{
+		return ((state == 1) || (state == 3)) ? variation : null;
 	}
 
 	/**

Modified: wicket/trunk/wicket/src/test/java/org/apache/wicket/util/resource/ResourceTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket/src/test/java/org/apache/wicket/util/resource/ResourceTest.java?rev=993630&r1=993629&r2=993630&view=diff
==============================================================================
--- wicket/trunk/wicket/src/test/java/org/apache/wicket/util/resource/ResourceTest.java (original)
+++ wicket/trunk/wicket/src/test/java/org/apache/wicket/util/resource/ResourceTest.java Wed Sep  8 06:40:02 2010
@@ -140,7 +140,6 @@ public class ResourceTest extends Wicket
 
 		if (!resourcePath.endsWith(filename))
 		{
-
 			filename = Strings.afterLast(filename, '/');
 			resourcePath = Strings.afterLast(resourcePath, '/');
 			assertEquals("Did not find resource", filename, resourcePath);