[maven-release-plugin]  copy for tag tiles-2.1.0

git-svn-id: https://svn.apache.org/repos/asf/tiles/framework/tags/tiles-2.1.0@680788 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/NOTICE.txt b/NOTICE.txt
index 8386627..7716163 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,6 +1,11 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
 
+   The binary distribution contains software developed by:
+   SpringSource: http://www.springsource.com/
+   
+   The Java 1.4-compatible distribution contains software developed by:
+   Retrotranslator (http://retrotranslator.sourceforge.net/).
\ No newline at end of file
diff --git a/assembly/pom.xml b/assembly/pom.xml
index 57469a1..d3dbf19 100644
--- a/assembly/pom.xml
+++ b/assembly/pom.xml
@@ -30,13 +30,13 @@
   <parent>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
   </parent>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/tiles/framework/trunk/assembly</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/tiles/framework/trunk/assembly</developerConnection>
-    <url>http://svn.apache.org/viewcvs.cgi/tiles/framework/trunk/assembly</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/tiles/framework/tags/tiles-2.1.0assembly</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/tiles/framework/tags/tiles-2.1.0assembly</developerConnection>
+    <url>http://svn.apache.org/viewcvs.cgi/tiles/framework/tags/tiles-2.1.0assembly</url>
   </scm>
   
   <build>
@@ -111,6 +111,30 @@
 
     <dependency>
       <groupId>org.apache.tiles</groupId>
+      <artifactId>tiles-servlet</artifactId>
+      <version>${pom.version}</version>
+      <exclusions>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-core</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tiles</groupId>
+      <artifactId>tiles-portlet</artifactId>
+      <version>${pom.version}</version>
+      <exclusions>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-core</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tiles</groupId>
       <artifactId>tiles-jsp</artifactId>
       <version>${pom.version}</version>
       <exclusions>
@@ -122,6 +146,22 @@
               <groupId>org.apache.tiles</groupId>
               <artifactId>tiles-core</artifactId>
           </exclusion>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-servlet</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tiles</groupId>
+      <artifactId>tiles-compat</artifactId>
+      <version>${pom.version}</version>
+      <exclusions>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-core</artifactId>
+          </exclusion>
       </exclusions>
     </dependency>
 
@@ -147,6 +187,32 @@
 
     <dependency>
       <groupId>org.apache.tiles</groupId>
+      <artifactId>tiles-servlet</artifactId>
+      <version>${pom.version}</version>
+      <classifier>j4</classifier>
+      <exclusions>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-core</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tiles</groupId>
+      <artifactId>tiles-portlet</artifactId>
+      <version>${pom.version}</version>
+      <classifier>j4</classifier>
+      <exclusions>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-core</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tiles</groupId>
       <artifactId>tiles-jsp</artifactId>
       <version>${pom.version}</version>
       <classifier>j4</classifier>
@@ -159,6 +225,23 @@
               <groupId>org.apache.tiles</groupId>
               <artifactId>tiles-core</artifactId>
           </exclusion>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-servlet</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.tiles</groupId>
+      <artifactId>tiles-compat</artifactId>
+      <version>${pom.version}</version>
+      <classifier>j4</classifier>
+      <exclusions>
+          <exclusion>
+              <groupId>org.apache.tiles</groupId>
+              <artifactId>tiles-core</artifactId>
+          </exclusion>
       </exclusions>
     </dependency>
 
@@ -201,6 +284,40 @@
       <scope>runtime</scope>
     </dependency>
 
+    <dependency>
+        <groupId>org.apache.tomcat</groupId>
+        <artifactId>jasper-el</artifactId>
+        <version>6.0.16</version>
+        <scope>runtime</scope>
+        <optional>true</optional>
+        <exclusions>
+          <exclusion>
+            <groupId>org.apache.tomcat</groupId>
+            <artifactId>el-api</artifactId>
+          </exclusion>
+        </exclusions>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+      <version>2.5.5</version>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-webmvc-portlet</artifactId>
+      <version>2.5.5</version>
+      <optional>true</optional>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework</groupId>
+          <artifactId>spring-webmvc</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
   </dependencies>
 
 </project>
diff --git a/assembly/src/main/assembly/bin-j4.xml b/assembly/src/main/assembly/bin-j4.xml
index 67d274b..de51170 100644
--- a/assembly/src/main/assembly/bin-j4.xml
+++ b/assembly/src/main/assembly/bin-j4.xml
@@ -24,12 +24,10 @@
     <dependencySets>
         <dependencySet>
             <outputDirectory>/lib</outputDirectory>
-            <excludes>
-                <exclude>org.apache.tiles:tiles-api</exclude>
-                <exclude>org.apache.tiles:tiles-core</exclude>
-                <exclude>org.apache.tiles:tiles-jsp</exclude>
-                <exclude>org.apache.tiles:tiles-test</exclude>
-            </excludes>
+            <includes>
+                <include>net.sf.retrotranslator:retrotranslator-runtime</include>
+                <include>backport-util-concurrent:backport-util-concurrent</include>
+            </includes>
         </dependencySet>
         <dependencySet>
             <outputFileNameMapping>${artifactId}-${version}-j4.${extension}</outputFileNameMapping>
@@ -37,7 +35,10 @@
             <includes>
                 <include>org.apache.tiles:tiles-api:jar:j4</include>
                 <include>org.apache.tiles:tiles-core:jar:j4</include>
+                <include>org.apache.tiles:tiles-servlet:jar:j4</include>
                 <include>org.apache.tiles:tiles-jsp:jar:j4</include>
+                <include>org.apache.tiles:tiles-portlet:jar:j4</include>
+                <include>org.apache.tiles:tiles-compat:jar:j4</include>
             </includes>
         </dependencySet>
     </dependencySets>
@@ -51,5 +52,12 @@
                 <include>NOTICE.txt</include>
             </includes>
         </fileSet>
+        <fileSet>
+            <directory>src/main/resources</directory>
+            <outputDirectory>/</outputDirectory>
+            <includes>
+                <include>RETROTRANSLATOR-LICENSE.txt</include>
+            </includes>
+        </fileSet>
     </fileSets>
 </assembly>
diff --git a/assembly/src/main/assembly/bin.xml b/assembly/src/main/assembly/bin.xml
index 96552d2..5a5a890 100644
--- a/assembly/src/main/assembly/bin.xml
+++ b/assembly/src/main/assembly/bin.xml
@@ -24,13 +24,28 @@
     <dependencySets>
         <dependencySet>
             <outputDirectory>/lib</outputDirectory>
+            <includes>
+                <include>commons-logging:commons-logging-api</include>
+                <include>commons-beanutils:commons-beanutils</include>
+                <include>commons-digester:commons-digester</include>
+            </includes>
+        </dependencySet>
+        <dependencySet>
+            <outputDirectory>/lib/optional</outputDirectory>
             <excludes>
                 <exclude>org.apache.tiles:tiles-api</exclude>
                 <exclude>org.apache.tiles:tiles-core</exclude>
+                <exclude>org.apache.tiles:tiles-servlet</exclude>
                 <exclude>org.apache.tiles:tiles-jsp</exclude>
+                <exclude>org.apache.tiles:tiles-portlet</exclude>
+                <exclude>org.apache.tiles:tiles-compat</exclude>
                 <exclude>org.apache.tiles:tiles-test</exclude>
-		        <exclude>net.sf.retrotranslator:retrotranslator-runtime</exclude>
-		        <exclude>backport-util-concurrent:backport-util-concurrent</exclude>
+                <exclude>commons-logging:commons-logging</exclude>
+                <exclude>commons-logging:commons-logging-api</exclude>
+                <exclude>commons-beanutils:commons-beanutils</exclude>
+                <exclude>commons-digester:commons-digester</exclude>
+                <exclude>net.sf.retrotranslator:retrotranslator-runtime</exclude>
+                <exclude>backport-util-concurrent:backport-util-concurrent</exclude>
             </excludes>
         </dependencySet>
         <dependencySet>
@@ -38,7 +53,10 @@
             <includes>
                 <include>org.apache.tiles:tiles-api</include>
                 <include>org.apache.tiles:tiles-core</include>
+                <include>org.apache.tiles:tiles-servlet</include>
                 <include>org.apache.tiles:tiles-jsp</include>
+                <include>org.apache.tiles:tiles-portlet</include>
+                <include>org.apache.tiles:tiles-compat</include>
             </includes>
             <excludes>
                 <exclude>*:j4</exclude>
diff --git a/assembly/src/main/assembly/src.xml b/assembly/src/main/assembly/src.xml
index de3a194..bbd91c9 100644
--- a/assembly/src/main/assembly/src.xml
+++ b/assembly/src/main/assembly/src.xml
@@ -54,6 +54,14 @@
             </includes>
         </fileSet>
         <fileSet>
+            <directory>../tiles-servlet</directory>
+            <outputDirectory>src/tiles-servlet</outputDirectory>
+            <includes>
+                <include>pom.xml</include>
+                <include>src/</include>
+            </includes>
+        </fileSet>
+        <fileSet>
             <directory>../tiles-jsp</directory>
             <outputDirectory>src/tiles-jsp</outputDirectory>
             <includes>
@@ -62,6 +70,22 @@
             </includes>
         </fileSet>
         <fileSet>
+            <directory>../tiles-portlet</directory>
+            <outputDirectory>src/tiles-portlet</outputDirectory>
+            <includes>
+                <include>pom.xml</include>
+                <include>src/</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>../tiles-compat</directory>
+            <outputDirectory>src/tiles-compat</outputDirectory>
+            <includes>
+                <include>pom.xml</include>
+                <include>src/</include>
+            </includes>
+        </fileSet>
+        <fileSet>
             <directory>../tiles-test</directory>
             <outputDirectory>src/tiles-test</outputDirectory>
             <includes>
diff --git a/assembly/src/main/resources/NOTICE.txt b/assembly/src/main/resources/NOTICE.txt
index 8386627..9e9e90a 100644
--- a/assembly/src/main/resources/NOTICE.txt
+++ b/assembly/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/assembly/src/main/resources/RETROTRANSLATOR-LICENSE.txt b/assembly/src/main/resources/RETROTRANSLATOR-LICENSE.txt
new file mode 100644
index 0000000..c2a8559
--- /dev/null
+++ b/assembly/src/main/resources/RETROTRANSLATOR-LICENSE.txt
@@ -0,0 +1,29 @@
+ Retrotranslator: a Java bytecode transformer that translates Java classes
+ compiled with JDK 5.0 into classes that can be run on JVM 1.4.
+
+ Copyright (c) 2005, 2006 Taras Puchko
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pom.xml b/pom.xml
index 57cc750..1341944 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,16 +32,16 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
     <packaging>pom</packaging>
     <name>Tiles 2</name>
     <description>Tiles 2: A framework for page composition.</description>
     <url>http://tiles.apache.org/framework/</url>
 
     <scm>
-        <connection>scm:svn:http://svn.apache.org/repos/asf/tiles/framework/trunk/</connection>
-        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/tiles/framework/trunk/</developerConnection>
-        <url>http://svn.apache.org/viewvc/tiles/framework/trunk/</url>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/tiles/framework/tags/tiles-2.1.0</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/tiles/framework/tags/tiles-2.1.0</developerConnection>
+        <url>http://svn.apache.org/viewvc/tiles/framework/tags/tiles-2.1.0</url>
     </scm>
 
     <ciManagement />
@@ -84,20 +84,57 @@
                     <artifactId>maven-jar-plugin</artifactId>
                     <configuration>
                         <archive>
-                            <manifestEntries>
-                                <Specification-Title>${project.name}</Specification-Title>
-                                <Specification-Version>${project.version}</Specification-Version>
-                                <Specification-Vendor>${project.organization.name}</Specification-Vendor>
-                                <Implementation-Title>${project.name}</Implementation-Title>
-                                <Implementation-Version>${project.version}</Implementation-Version>
-                                <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
-                                <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
-                            </manifestEntries>
+                            <manifestFile>${tiles.manifestfile}</manifestFile>
+                            <manifest>
+                                <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            </manifest>
                         </archive>
                     </configuration>
                 </plugin>
+                <plugin>
+                    <groupId>org.apache.felix</groupId>
+                    <artifactId>maven-bundle-plugin</artifactId>
+                    <version>1.4.0</version>
+                    <inherited>true</inherited>
+                </plugin>
             </plugins>
         </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <excludeDependencies>true</excludeDependencies>
+                    <manifestLocation>target/osgi</manifestLocation>
+                    <instructions>
+                        <_nouses>true</_nouses>
+                        <Bundle-SymbolicName>${tiles.osgi.symbolicName}</Bundle-SymbolicName>
+                        <Export-Package>${tiles.osgi.export}</Export-Package>
+                        <Private-Package>${tiles.osgi.private}</Private-Package>
+                        <Import-Package>${tiles.osgi.import}</Import-Package>
+                        <DynamicImport-Package>${tiles.osgi.dynamicImport}</DynamicImport-Package>
+                        <Bundle-DocURL>${project.url}</Bundle-DocURL>
+                        <Specification-Title>${project.name}</Specification-Title>
+                        <Specification-Version>${project.version}</Specification-Version>
+                        <Specification-Vendor>${project.organization.name}</Specification-Vendor>
+                        <Implementation-Title>${project.name}</Implementation-Title>
+                        <Implementation-Version>${project.version}</Implementation-Version>
+                        <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                        <Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
+                    </instructions>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>bundle-manifest</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>manifest</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
 
         <defaultGoal>install</defaultGoal>
     </build>
@@ -168,6 +205,15 @@
         </plugins>
     </reporting>
 
+    <properties>
+        <tiles.osgi.symbolicName>org.apache.${artifactId}</tiles.osgi.symbolicName>
+        <tiles.osgi.export>org.apache.tiles.*;version=${pom.version}</tiles.osgi.export>
+        <tiles.osgi.import>*</tiles.osgi.import>
+        <tiles.osgi.dynamicImport />
+        <tiles.osgi.private />
+        <tiles.manifestfile>target/osgi/MANIFEST.MF</tiles.manifestfile>
+    </properties>
+
     <dependencies />
     
     <profiles>
diff --git a/tiles-api/pom.xml b/tiles-api/pom.xml
index 25d6520..1945154 100644
--- a/tiles-api/pom.xml
+++ b/tiles-api/pom.xml
@@ -26,7 +26,7 @@
     <parent>
         <groupId>org.apache.tiles</groupId>
         <artifactId>tiles-parent</artifactId>
-        <version>2.1.0-SNAPSHOT</version>
+        <version>2.1.0</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
@@ -36,6 +36,10 @@
     <description>Tiles APIs, containing interfaces and classes to interact with
     Tiles.</description>
 
+    <properties>
+        <tiles.osgi.symbolicName>org.apache.tiles.api</tiles.osgi.symbolicName>
+    </properties>
+
     <build>
 
         <resources>
diff --git a/tiles-api/src/main/java/org/apache/tiles/access/TilesAccess.java b/tiles-api/src/main/java/org/apache/tiles/access/TilesAccess.java
index 446a4c1..66ea340 100644
--- a/tiles-api/src/main/java/org/apache/tiles/access/TilesAccess.java
+++ b/tiles-api/src/main/java/org/apache/tiles/access/TilesAccess.java
@@ -24,6 +24,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.tiles.TilesApplicationContext;
 import org.apache.tiles.TilesContainer;
+import org.apache.tiles.reflect.ClassUtil;
 
 import java.lang.reflect.Method;
 
@@ -164,14 +165,10 @@
      * @return The object, that is the value of the specified attribute.
      */
     private static Object getAttribute(Object context, String attributeName) {
-        try {
-            Class<?> contextClass = context.getClass();
-            Method attrMethod = contextClass.getMethod("getAttribute", String.class);
-            return attrMethod.invoke(context, attributeName);
-        } catch (Exception e) {
-            LOG.warn("Unable to retrieve container from specified context: '" + context + "'", e);
-            return null;
-        }
+        Class<?> contextClass = context.getClass();
+        Method attrMethod = ClassUtil.getForcedAccessibleMethod(
+                contextClass, "getAttribute", String.class);
+        return ClassUtil.invokeMethod(context, attrMethod, attributeName);
     }
 
     /**
@@ -184,17 +181,10 @@
      * attribute.
      */
     private static void setAttribute(Object context, String name, Object value) {
-        try {
-            Class<?> contextClass = context.getClass();
-            Method attrMethod = contextClass.getMethod("setAttribute", String.class, Object.class);
-            attrMethod.invoke(context, name, value);
-        } catch (RuntimeException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new TilesAccessException(
-                    "Unable to set attribute for specified context: '"
-                            + context + "'", e);
-        }
+        Class<?> contextClass = context.getClass();
+        Method attrMethod = ClassUtil.getForcedAccessibleMethod(
+                contextClass, "setAttribute", String.class, Object.class);
+        ClassUtil.invokeMethod(context, attrMethod, name, value);
     }
 
     /**
@@ -205,16 +195,9 @@
      * @throws TilesAccessException If something goes wrong during removal.
      */
     private static void removeAttribute(Object context, String name) {
-        try {
-            Class<?> contextClass = context.getClass();
-            Method attrMethod = contextClass.getMethod("removeAttribute", String.class);
-            attrMethod.invoke(context, name);
-        } catch (RuntimeException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new TilesAccessException(
-                    "Unable to remove attribute for specified context: '"
-                            + context + "'", e);
-        }
+        Class<?> contextClass = context.getClass();
+        Method attrMethod = ClassUtil.getForcedAccessibleMethod(
+                contextClass, "removeAttribute", String.class);
+        ClassUtil.invokeMethod(context, attrMethod, name);
     }
 }
diff --git a/tiles-core/src/main/java/org/apache/tiles/util/CannotInstantiateObjectException.java b/tiles-api/src/main/java/org/apache/tiles/reflect/CannotAccessMethodException.java
similarity index 71%
copy from tiles-core/src/main/java/org/apache/tiles/util/CannotInstantiateObjectException.java
copy to tiles-api/src/main/java/org/apache/tiles/reflect/CannotAccessMethodException.java
index fc3be16..a70725b 100644
--- a/tiles-core/src/main/java/org/apache/tiles/util/CannotInstantiateObjectException.java
+++ b/tiles-api/src/main/java/org/apache/tiles/reflect/CannotAccessMethodException.java
@@ -1,5 +1,5 @@
 /*
- * $Id$
+ * $Id: CannotInstantiateObjectException.java 637434 2008-03-15 15:48:38Z apetrelli $
  *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -18,24 +18,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tiles.util;
+package org.apache.tiles.reflect;
 
 import org.apache.tiles.TilesException;
 
 /**
- * Indicates that an object cannot be instantiated.
+ * Indicates that a method cannot be accessed.
  *
- * @version $Rev$ $Date$
+ * @version $Rev: 637434 $ $Date: 2008-03-15 16:48:38 +0100 (sab, 15 mar 2008) $
  * @since 2.1.0
  */
-public class CannotInstantiateObjectException extends TilesException {
+public class CannotAccessMethodException extends TilesException {
 
     /**
      * Constructor.
      *
      * @since 2.1.0
      */
-    public CannotInstantiateObjectException() {
+    public CannotAccessMethodException() {
     }
 
     /**
@@ -44,7 +44,7 @@
      * @param message The detail message.
      * @since 2.1.0
      */
-    public CannotInstantiateObjectException(String message) {
+    public CannotAccessMethodException(String message) {
         super(message);
     }
 
@@ -54,7 +54,7 @@
      * @param e The exception to be wrapped.
      * @since 2.1.0
      */
-    public CannotInstantiateObjectException(Exception e) {
+    public CannotAccessMethodException(Exception e) {
         super(e);
     }
 
@@ -65,9 +65,8 @@
      * @param e The exception to be wrapped.
      * @since 2.1.0
      */
-    public CannotInstantiateObjectException(String message, Exception e) {
+    public CannotAccessMethodException(String message, Exception e) {
         super(message, e);
-        // TODO Auto-generated constructor stub
     }
 
 }
diff --git a/tiles-core/src/main/java/org/apache/tiles/util/CannotInstantiateObjectException.java b/tiles-api/src/main/java/org/apache/tiles/reflect/CannotInstantiateObjectException.java
similarity index 89%
rename from tiles-core/src/main/java/org/apache/tiles/util/CannotInstantiateObjectException.java
rename to tiles-api/src/main/java/org/apache/tiles/reflect/CannotInstantiateObjectException.java
index fc3be16..731c276 100644
--- a/tiles-core/src/main/java/org/apache/tiles/util/CannotInstantiateObjectException.java
+++ b/tiles-api/src/main/java/org/apache/tiles/reflect/CannotInstantiateObjectException.java
@@ -1,5 +1,5 @@
 /*
- * $Id$
+ * $Id: CannotInstantiateObjectException.java 637434 2008-03-15 15:48:38Z apetrelli $
  *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -18,14 +18,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.tiles.util;
+package org.apache.tiles.reflect;
 
 import org.apache.tiles.TilesException;
 
 /**
  * Indicates that an object cannot be instantiated.
  *
- * @version $Rev$ $Date$
+ * @version $Rev: 637434 $ $Date: 2008-03-15 16:48:38 +0100 (sab, 15 mar 2008) $
  * @since 2.1.0
  */
 public class CannotInstantiateObjectException extends TilesException {
@@ -67,7 +67,6 @@
      */
     public CannotInstantiateObjectException(String message, Exception e) {
         super(message, e);
-        // TODO Auto-generated constructor stub
     }
 
 }
diff --git a/tiles-api/src/main/java/org/apache/tiles/reflect/ClassUtil.java b/tiles-api/src/main/java/org/apache/tiles/reflect/ClassUtil.java
new file mode 100644
index 0000000..8c72591
--- /dev/null
+++ b/tiles-api/src/main/java/org/apache/tiles/reflect/ClassUtil.java
@@ -0,0 +1,150 @@
+/*
+ * $Id: ClassUtil.java 637434 2008-03-15 15:48:38Z apetrelli $
+ *
+ * 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.tiles.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Utilities to work with dynamic class loading and instantiation.
+ *
+ * @version $Rev: 637434 $ $Date: 2008-03-15 16:48:38 +0100 (sab, 15 mar 2008) $
+ * @since 2.0.7
+ */
+public final class ClassUtil {
+
+    /**
+     * Constructor, private to avoid instantiation.
+     */
+    private ClassUtil() {
+    }
+
+    /**
+     * Returns an instance of the given class name, by calling the default
+     * constructor.
+     *
+     * @param className The class name to load and to instantiate.
+     * @return The new instance of the class name.
+     * @throws CannotInstantiateObjectException If something goes wrong during
+     * instantiation.
+     * @since 2.0.7
+     */
+    public static Object instantiate(String className) {
+        return instantiate(className, false);
+    }
+
+    /**
+     * Returns an instance of the given class name, by calling the default
+     * constructor.
+     *
+     * @param className The class name to load and to instantiate.
+     * @param returnNull If <code>true</code>, if the class is not found it
+     * returns <code>true</code>, otherwise it throws a
+     * <code>TilesException</code>.
+     * @return The new instance of the class name.
+     * @throws CannotInstantiateObjectException If something goes wrong during instantiation.
+     * @since 2.0.7
+     */
+    public static Object instantiate(String className, boolean returnNull) {
+        ClassLoader original = Thread.currentThread().getContextClassLoader();
+        if (original == null) {
+            Thread.currentThread().setContextClassLoader(ClassUtil.class.getClassLoader());
+        }
+        try {
+            Class<?> namedClass = Class.forName(className);
+            return namedClass.newInstance();
+        } catch (ClassNotFoundException e) {
+            if (returnNull) {
+                return null;
+            }
+            throw new CannotInstantiateObjectException(
+                    "Unable to resolve factory class: '" + className + "'", e);
+        } catch (IllegalAccessException e) {
+            throw new CannotInstantiateObjectException(
+                    "Unable to access factory class: '" + className + "'", e);
+        } catch (InstantiationException e) {
+            throw new CannotInstantiateObjectException(
+                    "Unable to instantiate factory class: '"
+                            + className
+                            + "'. Make sure that this class has a default constructor",
+                    e);
+        } finally {
+            Thread.currentThread().setContextClassLoader(original);
+        }
+    }
+
+    /**
+     * Gets a method and forces it to be accessible, even if it is not.
+     *
+     * @param clazz The class from which the method will be got.
+     * @param methodName The name of the method.
+     * @param parameterTypes The parameter types that the method must match.
+     * @return The method, if it is found.
+     * @since 2.0.7
+     */
+    public static Method getForcedAccessibleMethod(Class<?> clazz,
+            String methodName, Class<?>... parameterTypes) {
+        Method method;
+        try {
+            method = clazz.getMethod(methodName, parameterTypes);
+        } catch (SecurityException e) {
+            throw new CannotAccessMethodException("Cannot access method '"
+                    + methodName + "' in class '" + clazz.getName()
+                    + "' for security reasons", e);
+        } catch (NoSuchMethodException e) {
+            throw new CannotAccessMethodException("The method '"
+                    + methodName + "' in class '" + clazz.getName()
+                    + "' does not exist", e);
+        }
+        if (!method.isAccessible()) {
+            method.setAccessible(true);
+        }
+        return method;
+    }
+
+    /**
+     * Invokes a method, masking with a runtime exception all the exceptions.
+     *
+     * @param obj The object from which a method will be called.
+     * @param method The method to call.
+     * @param args The arguments of the method.
+     * @return The object returned, if the method is not "void".
+     * @since 2.0.7
+     */
+    public static Object invokeMethod(Object obj, Method method, Object... args) {
+        try {
+            return method.invoke(obj, args);
+        } catch (IllegalArgumentException e) {
+            throw new CannotAccessMethodException("The arguments for '"
+                    + method.getName() + "' in class '"
+                    + obj.getClass().getName() + "' are not valid", e);
+        } catch (IllegalAccessException e) {
+            throw new CannotAccessMethodException("Cannot access '"
+                    + method.getName() + "' in class '"
+                    + obj.getClass().getName() + "'", e);
+        } catch (InvocationTargetException e) {
+            throw new CannotAccessMethodException(
+                    "An exception has been thrown inside '" + method.getName()
+                    + "' in class '" + obj.getClass().getName() + "'", e);
+        }
+    }
+}
diff --git a/tiles-api/src/main/java/org/apache/tiles/reflect/package.html b/tiles-api/src/main/java/org/apache/tiles/reflect/package.html
new file mode 100644
index 0000000..dfb17d9
--- /dev/null
+++ b/tiles-api/src/main/java/org/apache/tiles/reflect/package.html
@@ -0,0 +1,30 @@
+<!--
+/*
+ * $Id$
+ *
+ * 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.
+ */
+-->
+<html>
+<head>
+    <title>Tiles reflection utilities</title>
+</head>
+<body>
+Classes to manage reflection in a centralized way for Tiles.
+</body>
+</html>
\ No newline at end of file
diff --git a/tiles-api/src/main/resources/NOTICE.txt b/tiles-api/src/main/resources/NOTICE.txt
index 8386627..9e9e90a 100644
--- a/tiles-api/src/main/resources/NOTICE.txt
+++ b/tiles-api/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/tiles-compat/pom.xml b/tiles-compat/pom.xml
index eecc35b..0007b82 100644
--- a/tiles-compat/pom.xml
+++ b/tiles-compat/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -36,6 +36,10 @@
   <description>Tiles compatibility library, to help migration from Struts-Tiles.
   </description>
 
+  <properties>
+      <tiles.osgi.symbolicName>org.apache.tiles.compat</tiles.osgi.symbolicName>
+  </properties>
+
   <build>
     <resources>
       <resource>
@@ -133,6 +137,12 @@
     </dependency>
 
     <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.5</version>
+    </dependency>
+
+    <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.0</version>
@@ -153,13 +163,6 @@
       <scope>test</scope>
     </dependency>
 
-    <dependency>
-      <groupId>javax.servlet</groupId>
-      <artifactId>servlet-api</artifactId>
-      <version>2.5</version>
-      <scope>test</scope>
-    </dependency>
-
   </dependencies>
 
   <repositories>
diff --git a/tiles-compat/src/main/resources/NOTICE.txt b/tiles-compat/src/main/resources/NOTICE.txt
index 8386627..9e9e90a 100644
--- a/tiles-compat/src/main/resources/NOTICE.txt
+++ b/tiles-compat/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/tiles-core/pom.xml b/tiles-core/pom.xml
index bab762d..b0f40e8 100644
--- a/tiles-core/pom.xml
+++ b/tiles-core/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -36,6 +36,10 @@
   <description>Tiles Core Library, including basic implementation of the APIs.
   </description>
 
+  <properties>
+      <tiles.osgi.symbolicName>org.apache.tiles.core</tiles.osgi.symbolicName>
+  </properties>
+
   <build>
     <resources>
       <resource>
@@ -145,13 +149,6 @@
     </dependency>
 
     <dependency>
-      <groupId>javax.portlet</groupId>
-      <artifactId>portlet-api</artifactId>
-      <version>1.0</version>
-      <scope>provided</scope>
-    </dependency>
-
-    <dependency>
       <groupId>javax.el</groupId>
       <artifactId>el-api</artifactId>
       <version>1.0</version>
diff --git a/tiles-core/src/main/java/org/apache/tiles/definition/LocaleDefinitionsFactory.java b/tiles-core/src/main/java/org/apache/tiles/definition/LocaleDefinitionsFactory.java
index eff97d8..8b3581d 100644
--- a/tiles-core/src/main/java/org/apache/tiles/definition/LocaleDefinitionsFactory.java
+++ b/tiles-core/src/main/java/org/apache/tiles/definition/LocaleDefinitionsFactory.java
@@ -33,7 +33,7 @@
 import org.apache.tiles.definition.dao.DefinitionDAO;
 import org.apache.tiles.locale.LocaleResolver;
 import org.apache.tiles.locale.impl.DefaultLocaleResolver;
-import org.apache.tiles.util.ClassUtil;
+import org.apache.tiles.reflect.ClassUtil;
 
 /**
  * {@link DefinitionsFactory DefinitionsFactory} implementation that manages
diff --git a/tiles-core/src/main/java/org/apache/tiles/definition/dao/BaseLocaleUrlDefinitionDAO.java b/tiles-core/src/main/java/org/apache/tiles/definition/dao/BaseLocaleUrlDefinitionDAO.java
index 11602b0..fc8f5ff 100644
--- a/tiles-core/src/main/java/org/apache/tiles/definition/dao/BaseLocaleUrlDefinitionDAO.java
+++ b/tiles-core/src/main/java/org/apache/tiles/definition/dao/BaseLocaleUrlDefinitionDAO.java
@@ -44,7 +44,7 @@
 import org.apache.tiles.definition.RefreshMonitor;
 import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
 import org.apache.tiles.impl.BasicTilesContainer;
-import org.apache.tiles.util.ClassUtil;
+import org.apache.tiles.reflect.ClassUtil;
 
 /**
  * Base abstract class for a DAO that is based on URLs and locale as a
@@ -185,15 +185,31 @@
 
         try {
             for (int i = 0; i < resources.length; i++) {
-                URL resourceUrl = applicationContext.getResource(resources[i]);
-                if (resourceUrl != null) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Adding resource '" + resourceUrl
-                                + "' to definitions factory.");
+                Set<URL> urls = applicationContext.getResources(resources[i]);
+                if (urls != null && !urls.isEmpty()) {
+                    for (URL resourceUrl : urls) {
+                        if (resourceUrl != null) {
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug("Adding resource '" + resourceUrl
+                                        + "' to definitions factory.");
+                            }
+                            String externalForm = resourceUrl.toExternalForm();
+                            if (externalForm.indexOf('_', externalForm
+                                    .lastIndexOf("/")) < 0) {
+                                sourceURLs.add(resourceUrl);
+                            } else if (LOG.isDebugEnabled()) {
+                                LOG.debug("Not adding resource '" + resourceUrl
+                                        + "' to definitions factory because it is "
+                                        + "supposed to be an internationalization.");
+                            }
+
+                        } else {
+                            LOG.warn("Unable to find configured definition '"
+                                    + resources[i] + "'");
+                        }
                     }
-                    sourceURLs.add(resourceUrl);
                 } else {
-                    LOG.warn("Unable to find configured definition '"
+                    LOG.warn("Unable to find resources under the name '"
                             + resources[i] + "'");
                 }
             }
diff --git a/tiles-core/src/main/java/org/apache/tiles/evaluator/el/ELAttributeEvaluator.java b/tiles-core/src/main/java/org/apache/tiles/evaluator/el/ELAttributeEvaluator.java
index 126fdb4..0003f77 100644
--- a/tiles-core/src/main/java/org/apache/tiles/evaluator/el/ELAttributeEvaluator.java
+++ b/tiles-core/src/main/java/org/apache/tiles/evaluator/el/ELAttributeEvaluator.java
@@ -36,7 +36,7 @@
 import org.apache.tiles.awareness.TilesApplicationContextAware;
 import org.apache.tiles.context.TilesRequestContext;
 import org.apache.tiles.evaluator.AttributeEvaluator;
-import org.apache.tiles.util.ClassUtil;
+import org.apache.tiles.reflect.ClassUtil;
 
 /**
  * Evaluates string expression with typical EL syntax.<br>
diff --git a/tiles-core/src/main/java/org/apache/tiles/factory/AbstractTilesContainerFactory.java b/tiles-core/src/main/java/org/apache/tiles/factory/AbstractTilesContainerFactory.java
index 3172c85..aa530b4 100644
--- a/tiles-core/src/main/java/org/apache/tiles/factory/AbstractTilesContainerFactory.java
+++ b/tiles-core/src/main/java/org/apache/tiles/factory/AbstractTilesContainerFactory.java
@@ -26,7 +26,7 @@
 import java.util.Map;
 
 import org.apache.tiles.TilesContainer;
-import org.apache.tiles.util.ClassUtil;
+import org.apache.tiles.reflect.ClassUtil;
 
 /**
  * Abstract Factory that creates instances of {@link TilesContainerFactory}.
@@ -104,22 +104,19 @@
     protected static Map<String, String> getInitParameterMap(Object context) {
         Map<String, String> initParameters = new HashMap<String, String>();
         Class<?> contextClass = context.getClass();
-        try {
-            Method method = contextClass.getMethod("getInitParameterNames");
-            Enumeration<String> e = (Enumeration<String>) method
-                    .invoke(context);
+        Method method = ClassUtil.getForcedAccessibleMethod(contextClass,
+                "getInitParameterNames");
+        Enumeration<String> e = (Enumeration<String>) ClassUtil
+                .invokeMethod(context, method);
 
-            method = contextClass.getMethod("getInitParameter", String.class);
-            while (e.hasMoreElements()) {
-                String key = e.nextElement();
-                initParameters.put(key, (String) method.invoke(context, key));
-            }
-        } catch (Exception e) {
-            throw new TilesContainerFactoryException(
-                    "Unable to retrieve init parameters."
-                    + " Is this context a ServletContext, PortletContext,"
-                    + " or similar object?", e);
+        method = ClassUtil.getForcedAccessibleMethod(contextClass,
+                "getInitParameter", String.class);
+        while (e.hasMoreElements()) {
+            String key = e.nextElement();
+            initParameters.put(key, (String) ClassUtil.invokeMethod(
+                    context, method, key));
         }
+
         return initParameters;
     }
 
@@ -136,16 +133,13 @@
     protected static String getInitParameter(Object context,
             String parameterName) {
         Object value;
-        try {
-            Class<?> contextClass = context.getClass();
-            Method getInitParameterMethod =
-                contextClass.getMethod("getInitParameter", String.class);
-            value = getInitParameterMethod.invoke(context, parameterName);
-        } catch (Exception e) {
-            throw new TilesContainerFactoryException(
-                    "Unrecognized context.  Is this context"
-                    + " a ServletContext, PortletContext, or similar?", e);
-        }
+        Class<?> contextClass = context.getClass();
+        Method getInitParameterMethod = ClassUtil
+                .getForcedAccessibleMethod(contextClass,
+                        "getInitParameter", String.class);
+        value = ClassUtil.invokeMethod(context, getInitParameterMethod,
+                parameterName);
+
         return value == null ? null : value.toString();
     }
 }
diff --git a/tiles-core/src/main/java/org/apache/tiles/factory/KeyedDefinitionsFactoryTilesContainerFactory.java b/tiles-core/src/main/java/org/apache/tiles/factory/KeyedDefinitionsFactoryTilesContainerFactory.java
index acedfc4..6d11874 100644
--- a/tiles-core/src/main/java/org/apache/tiles/factory/KeyedDefinitionsFactoryTilesContainerFactory.java
+++ b/tiles-core/src/main/java/org/apache/tiles/factory/KeyedDefinitionsFactoryTilesContainerFactory.java
@@ -34,8 +34,8 @@
 import org.apache.tiles.impl.KeyedDefinitionsFactoryTilesContainer.KeyExtractor;
 import org.apache.tiles.impl.mgmt.CachingKeyedDefinitionsFactoryTilesContainer;
 import org.apache.tiles.mgmt.MutableTilesContainer;
+import org.apache.tiles.reflect.ClassUtil;
 import org.apache.tiles.renderer.RendererFactory;
-import org.apache.tiles.util.ClassUtil;
 
 /**
  * Factory that creates instances of container that will extend the
diff --git a/tiles-core/src/main/java/org/apache/tiles/factory/TilesContainerFactory.java b/tiles-core/src/main/java/org/apache/tiles/factory/TilesContainerFactory.java
index aa927d7..a69f804 100644
--- a/tiles-core/src/main/java/org/apache/tiles/factory/TilesContainerFactory.java
+++ b/tiles-core/src/main/java/org/apache/tiles/factory/TilesContainerFactory.java
@@ -39,9 +39,9 @@
 import org.apache.tiles.mgmt.MutableTilesContainer;
 import org.apache.tiles.preparer.BasicPreparerFactory;
 import org.apache.tiles.preparer.PreparerFactory;
+import org.apache.tiles.reflect.ClassUtil;
 import org.apache.tiles.renderer.RendererFactory;
 import org.apache.tiles.renderer.impl.BasicRendererFactory;
-import org.apache.tiles.util.ClassUtil;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/tiles-core/src/main/java/org/apache/tiles/preparer/BasicPreparerFactory.java b/tiles-core/src/main/java/org/apache/tiles/preparer/BasicPreparerFactory.java
index 9c380a0..003bbf5 100644
--- a/tiles-core/src/main/java/org/apache/tiles/preparer/BasicPreparerFactory.java
+++ b/tiles-core/src/main/java/org/apache/tiles/preparer/BasicPreparerFactory.java
@@ -23,7 +23,7 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tiles.context.TilesRequestContext;
-import org.apache.tiles.util.ClassUtil;
+import org.apache.tiles.reflect.ClassUtil;
 
 import java.util.HashMap;
 import java.util.Map;
diff --git a/tiles-core/src/main/java/org/apache/tiles/renderer/impl/BasicRendererFactory.java b/tiles-core/src/main/java/org/apache/tiles/renderer/impl/BasicRendererFactory.java
index 7f03602..cbdbabc 100644
--- a/tiles-core/src/main/java/org/apache/tiles/renderer/impl/BasicRendererFactory.java
+++ b/tiles-core/src/main/java/org/apache/tiles/renderer/impl/BasicRendererFactory.java
@@ -31,10 +31,10 @@
 import org.apache.tiles.context.TilesContextFactory;
 import org.apache.tiles.evaluator.AttributeEvaluator;
 import org.apache.tiles.evaluator.AttributeEvaluatorAware;
+import org.apache.tiles.reflect.ClassUtil;
 import org.apache.tiles.renderer.AttributeRenderer;
 import org.apache.tiles.renderer.RendererException;
 import org.apache.tiles.renderer.RendererFactory;
-import org.apache.tiles.util.ClassUtil;
 
 /**
  * Basic renderer factory implementation.
diff --git a/tiles-core/src/main/java/org/apache/tiles/util/ClassUtil.java b/tiles-core/src/main/java/org/apache/tiles/util/ClassUtil.java
index abe7fbf..58030e2 100644
--- a/tiles-core/src/main/java/org/apache/tiles/util/ClassUtil.java
+++ b/tiles-core/src/main/java/org/apache/tiles/util/ClassUtil.java
@@ -20,10 +20,14 @@
  */
 package org.apache.tiles.util;
 
+import org.apache.tiles.reflect.CannotInstantiateObjectException;
+
+
 /**
  * Utilities to work with dynamic class loading and instantiation.
  *
  * @version $Rev$ $Date$
+ * @deprecated Use {@link org.apache.tiles.reflect.ClassUtil}.
  */
 public final class ClassUtil {
 
@@ -84,5 +88,4 @@
             Thread.currentThread().setContextClassLoader(original);
         }
     }
-
 }
diff --git a/tiles-core/src/main/resources/NOTICE.txt b/tiles-core/src/main/resources/NOTICE.txt
index 8386627..9e9e90a 100644
--- a/tiles-core/src/main/resources/NOTICE.txt
+++ b/tiles-core/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/LocaleDefinitionsFactoryTest.java b/tiles-core/src/test/java/org/apache/tiles/definition/LocaleDefinitionsFactoryTest.java
index 3b6d756..69b3d28 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/LocaleDefinitionsFactoryTest.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/LocaleDefinitionsFactoryTest.java
@@ -23,8 +23,10 @@
 
 import java.net.URL;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -99,15 +101,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
 
@@ -144,15 +155,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
 
@@ -241,15 +261,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
 
@@ -307,9 +336,12 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
 
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/TestReloadableDefinitionsFactory.java b/tiles-core/src/test/java/org/apache/tiles/definition/TestReloadableDefinitionsFactory.java
index 339f11f..fbd82ef 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/TestReloadableDefinitionsFactory.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/TestReloadableDefinitionsFactory.java
@@ -29,7 +29,9 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.tiles.Definition;
 import org.apache.tiles.TilesApplicationContext;
@@ -107,7 +109,10 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource(urlPath)).andReturn(url);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(applicationContext.getResources(urlPath)).andReturn(
+                urlSet);
         EasyMock.replay(applicationContext);
         ((TilesApplicationContextAware) factory)
                 .setApplicationContext(applicationContext);
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java b/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java
index 2328e84..e63bd63 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/TestUrlDefinitionsFactory.java
@@ -23,8 +23,10 @@
 
 import java.net.URL;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
@@ -99,15 +101,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
         TilesRequestContext emptyContext = new MockOnlyLocaleTilesContext(null);
@@ -145,15 +156,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
 
@@ -243,9 +263,12 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext
-                .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         factory.setApplicationContext(applicationContext);
 
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/dao/CachingLocaleUrlDefinitionDAOTest.java b/tiles-core/src/test/java/org/apache/tiles/definition/dao/CachingLocaleUrlDefinitionDAOTest.java
index 94770ee..bd47ee7 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/dao/CachingLocaleUrlDefinitionDAOTest.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/dao/CachingLocaleUrlDefinitionDAOTest.java
@@ -31,9 +31,13 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
 
 import org.apache.tiles.Definition;
 import org.apache.tiles.TilesApplicationContext;
@@ -46,8 +50,6 @@
 import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
 import org.easymock.EasyMock;
 
-import junit.framework.TestCase;
-
 /**
  * Tests {@link CachingLocaleUrlDefinitionDAO}.
  *
@@ -92,18 +94,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         definitionDao.setApplicationContext(applicationContext);
 
@@ -190,18 +198,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         definitionDao.setApplicationContext(applicationContext);
 
@@ -361,8 +375,10 @@
                 "org/apache/tiles/config/defs3.xml");
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource("/WEB-INF/tiles.xml"))
-                .andReturn(url1);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(applicationContext.getResources("/WEB-INF/tiles.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         Map<String, String> params = new HashMap<String, String>();
         definitionDao.setApplicationContext(applicationContext);
@@ -377,18 +393,24 @@
         EasyMock.reset(applicationContext);
 
         applicationContext = EasyMock.createMock(TilesApplicationContext.class);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         params.clear();
         params.put(DefinitionsFactory.READER_IMPL_PROPERTY,
@@ -424,18 +446,24 @@
                 "org/apache/tiles/config/defs3.xml");
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         Map<String, String> params = new HashMap<String, String>();
         params.put(DefinitionsFactory.DEFINITIONS_CONFIG,
@@ -505,7 +533,10 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource(urlPath)).andReturn(url);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(applicationContext.getResources(urlPath)).andReturn(
+                urlSet);
         EasyMock.replay(applicationContext);
         ((TilesApplicationContextAware) definitionDao)
                 .setApplicationContext(applicationContext);
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/dao/LocaleUrlDefinitionDAOTest.java b/tiles-core/src/test/java/org/apache/tiles/definition/dao/LocaleUrlDefinitionDAOTest.java
index a6fc9cf..b14b1f7 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/dao/LocaleUrlDefinitionDAOTest.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/dao/LocaleUrlDefinitionDAOTest.java
@@ -31,9 +31,13 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
+
+import junit.framework.TestCase;
 
 import org.apache.tiles.Definition;
 import org.apache.tiles.TilesApplicationContext;
@@ -46,8 +50,6 @@
 import org.apache.tiles.definition.digester.DigesterDefinitionsReader;
 import org.easymock.EasyMock;
 
-import junit.framework.TestCase;
-
 /**
  * Tests {@link LocaleUrlDefinitionDAO}.
  *
@@ -92,18 +94,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         definitionDao.setApplicationContext(applicationContext);
 
@@ -190,18 +198,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         definitionDao.setApplicationContext(applicationContext);
 
@@ -361,8 +375,10 @@
                 "org/apache/tiles/config/defs3.xml");
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource("/WEB-INF/tiles.xml"))
-                .andReturn(url1);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(applicationContext.getResources("/WEB-INF/tiles.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         Map<String, String> params = new HashMap<String, String>();
         definitionDao.setApplicationContext(applicationContext);
@@ -377,18 +393,24 @@
         EasyMock.reset(applicationContext);
 
         applicationContext = EasyMock.createMock(TilesApplicationContext.class);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         params.clear();
         params.put(DefinitionsFactory.READER_IMPL_PROPERTY,
@@ -422,26 +444,41 @@
                 "org/apache/tiles/config/defs2.xml");
         URL url3 = this.getClass().getClassLoader().getResource(
                 "org/apache/tiles/config/defs3.xml");
+        URL url4 = this.getClass().getClassLoader().getResource(
+                "org/apache/tiles/config/defs1_en_US.xml");
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url4);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1_en_US.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         Map<String, String> params = new HashMap<String, String>();
         params.put(DefinitionsFactory.DEFINITIONS_CONFIG,
                 "org/apache/tiles/config/defs1.xml,"
                         + "org/apache/tiles/config/defs2.xml,"
-                        + "org/apache/tiles/config/defs3.xml");
+                        + "org/apache/tiles/config/defs3.xml,"
+                        + "org/apache/tiles/config/defs1_en_US.xml");
         definitionDao.setApplicationContext(applicationContext);
         definitionDao.setSourceURLs(new ArrayList<URL>());
         definitionDao.identifySources(params);
@@ -505,7 +542,10 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource(urlPath)).andReturn(url);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(applicationContext.getResources(urlPath)).andReturn(
+                urlSet);
         EasyMock.replay(applicationContext);
         ((TilesApplicationContextAware) definitionDao)
                 .setApplicationContext(applicationContext);
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java b/tiles-core/src/test/java/org/apache/tiles/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java
index 359fffc..a4623a5 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/dao/ResolvingLocaleUrlDefinitionDAOTest.java
@@ -31,9 +31,11 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.tiles.Definition;
 import org.apache.tiles.TilesApplicationContext;
@@ -92,18 +94,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         definitionDao.setApplicationContext(applicationContext);
 
@@ -191,18 +199,24 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         definitionDao.setApplicationContext(applicationContext);
 
@@ -363,8 +377,12 @@
                 "org/apache/tiles/config/defs3.xml");
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource("/WEB-INF/tiles.xml"))
-                .andReturn(url1);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("/WEB-INF/tiles.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         Map<String, String> params = new HashMap<String, String>();
         definitionDao.setApplicationContext(applicationContext);
@@ -379,18 +397,24 @@
         EasyMock.reset(applicationContext);
 
         applicationContext = EasyMock.createMock(TilesApplicationContext.class);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         params.clear();
         params.put(DefinitionsFactory.READER_IMPL_PROPERTY,
@@ -424,26 +448,41 @@
                 "org/apache/tiles/config/defs2.xml");
         URL url3 = this.getClass().getClassLoader().getResource(
                 "org/apache/tiles/config/defs3.xml");
+        URL url4 = this.getClass().getClassLoader().getResource(
+                "org/apache/tiles/config/defs1_en_US.xml");
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url1);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs1.xml"))
-                .andReturn(url1);
+                        .getResources("org/apache/tiles/config/defs1.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url2);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs2.xml"))
-                .andReturn(url2);
+                        .getResources("org/apache/tiles/config/defs2.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url3);
         EasyMock.expect(
                 applicationContext
-                        .getResource("org/apache/tiles/config/defs3.xml"))
-                .andReturn(url3);
+                        .getResources("org/apache/tiles/config/defs3.xml"))
+                .andReturn(urlSet);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url4);
+        EasyMock.expect(
+                applicationContext
+                        .getResources("org/apache/tiles/config/defs1_en_US.xml"))
+                .andReturn(urlSet);
         EasyMock.replay(applicationContext);
         Map<String, String> params = new HashMap<String, String>();
         params.put(DefinitionsFactory.DEFINITIONS_CONFIG,
                 "org/apache/tiles/config/defs1.xml,"
                         + "org/apache/tiles/config/defs2.xml,"
-                        + "org/apache/tiles/config/defs3.xml");
+                        + "org/apache/tiles/config/defs3.xml,"
+                        + "org/apache/tiles/config/defs1_en_US.xml");
         definitionDao.setApplicationContext(applicationContext);
         definitionDao.setSourceURLs(new ArrayList<URL>());
         definitionDao.identifySources(params);
@@ -507,7 +546,10 @@
 
         TilesApplicationContext applicationContext = EasyMock
                 .createMock(TilesApplicationContext.class);
-        EasyMock.expect(applicationContext.getResource(urlPath)).andReturn(url);
+        Set<URL> urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(applicationContext.getResources(urlPath)).andReturn(
+                urlSet);
         EasyMock.replay(applicationContext);
         ((TilesApplicationContextAware) definitionDao)
                 .setApplicationContext(applicationContext);
diff --git a/tiles-core/src/test/java/org/apache/tiles/impl/KeyedDefinitionsFactoryTilesContainerTest.java b/tiles-core/src/test/java/org/apache/tiles/impl/KeyedDefinitionsFactoryTilesContainerTest.java
index 6d688d8..e67447a 100644
--- a/tiles-core/src/test/java/org/apache/tiles/impl/KeyedDefinitionsFactoryTilesContainerTest.java
+++ b/tiles-core/src/test/java/org/apache/tiles/impl/KeyedDefinitionsFactoryTilesContainerTest.java
@@ -25,11 +25,11 @@
 import java.net.URL;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.Vector;
 
-import javax.servlet.ServletContext;
-
 import junit.framework.TestCase;
 
 import org.apache.tiles.TilesApplicationContext;
@@ -116,12 +116,19 @@
                 KeyedDefinitionsFactoryTilesContainer.DEFINITIONS_CONFIG_PREFIX
                 + "two", "/WEB-INF/tiles-two.xml");
         try {
+            Set<URL> urlSet;
             URL url = getClass().getResource("/org/apache/tiles/factory/test-defs.xml");
-            EasyMock.expect(context.getResource("/WEB-INF/tiles.xml")).andReturn(url);
+            urlSet = new HashSet<URL>();
+            urlSet.add(url);
+            EasyMock.expect(context.getResources("/WEB-INF/tiles.xml")).andReturn(urlSet);
             url = getClass().getResource("/org/apache/tiles/factory/test-defs-key-one.xml");
-            EasyMock.expect(context.getResource("/WEB-INF/tiles-one.xml")).andReturn(url);
+            urlSet = new HashSet<URL>();
+            urlSet.add(url);
+            EasyMock.expect(context.getResources("/WEB-INF/tiles-one.xml")).andReturn(urlSet);
             url = getClass().getResource("/org/apache/tiles/factory/test-defs-key-two.xml");
-            EasyMock.expect(context.getResource("/WEB-INF/tiles-two.xml")).andReturn(url);
+            urlSet = new HashSet<URL>();
+            urlSet.add(url);
+            EasyMock.expect(context.getResources("/WEB-INF/tiles-two.xml")).andReturn(urlSet);
         } catch (MalformedURLException e) {
             throw new RuntimeException("Error getting Tiles configuration URL",
                     e);
@@ -150,19 +157,20 @@
     /**
      * Tests initialization for postponed definitions factories.
      *
-     * @throws MalformedURLException If sources are not valid (that should not
-     * happen).
+     * @throws IOException If something goes wrong.
      */
     @SuppressWarnings("deprecation")
-    public void testPostponedDefinitionsFactoryInitialization() throws MalformedURLException {
+    public void testPostponedDefinitionsFactoryInitialization()
+            throws IOException {
         KeyedDefinitionsFactoryTilesContainer container;
-        ServletContext context = EasyMock.createMock(ServletContext.class);
+        ContextLikeTilesApplicationContext context = EasyMock
+                .createMock(ContextLikeTilesApplicationContext.class);
+
 
         Vector<String> v = new Vector<String>();
         v.add(AbstractTilesContainerFactory.CONTAINER_FACTORY_INIT_PARAM);
         v.add(ChainedTilesContextFactory.FACTORY_CLASS_NAMES);
 
-        EasyMock.reset(context);
         EasyMock.expect(context.getInitParameter(
                 AbstractTilesContainerFactory.CONTAINER_FACTORY_INIT_PARAM))
                 .andReturn(KeyedDefinitionsFactoryTilesContainerFactory.class.getName())
@@ -180,12 +188,19 @@
         EasyMock.expect(context.getInitParameter(
                 KeyedDefinitionsFactoryTilesContainerFactory.CONTAINER_KEYS_INIT_PARAM))
                 .andReturn(null);
+        Set<URL> urlSet = new HashSet<URL>();
         URL url = getClass().getResource("/org/apache/tiles/factory/test-defs.xml");
-        EasyMock.expect(context.getResource("/WEB-INF/tiles.xml")).andReturn(url);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(context.getResources("/WEB-INF/tiles.xml")).andReturn(urlSet);
         url = getClass().getResource("/org/apache/tiles/factory/test-defs-key-one.xml");
-        EasyMock.expect(context.getResource("/WEB-INF/tiles-one.xml")).andReturn(url);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(context.getResources("/WEB-INF/tiles-one.xml")).andReturn(urlSet);
         url = getClass().getResource("/org/apache/tiles/factory/test-defs-key-two.xml");
-        EasyMock.expect(context.getResource("/WEB-INF/tiles-two.xml")).andReturn(url);
+        urlSet = new HashSet<URL>();
+        urlSet.add(url);
+        EasyMock.expect(context.getResources("/WEB-INF/tiles-two.xml")).andReturn(urlSet);
         EasyMock.expect(context.getInitParameterNames()).andReturn(v.elements()).anyTimes();
         EasyMock.replay(context);
         KeyedDefinitionsFactoryTilesContainerFactory factory =
diff --git a/tiles-jsp/pom.xml b/tiles-jsp/pom.xml
index 2415d40..99402e7 100644
--- a/tiles-jsp/pom.xml
+++ b/tiles-jsp/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -36,6 +36,10 @@
   <description>Tiles JSP support: Classes and tag libraries to use Tiles in a
   JSP environment.</description>
 
+  <properties>
+      <tiles.osgi.symbolicName>org.apache.tiles.jsp</tiles.osgi.symbolicName>
+  </properties>
+
   <build>
     <resources>
       <resource>
diff --git a/tiles-jsp/src/main/resources/NOTICE.txt b/tiles-jsp/src/main/resources/NOTICE.txt
index 8386627..9e9e90a 100644
--- a/tiles-jsp/src/main/resources/NOTICE.txt
+++ b/tiles-jsp/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/tiles-portlet/pom.xml b/tiles-portlet/pom.xml
index 04b2bc6..9b9c99e 100644
--- a/tiles-portlet/pom.xml
+++ b/tiles-portlet/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -36,6 +36,10 @@
   <description>Tiles portlet support, to enable use of Tiles inside a Portlet container.
   </description>
 
+  <properties>
+      <tiles.osgi.symbolicName>org.apache.tiles.portlet</tiles.osgi.symbolicName>
+  </properties>
+
   <build>
     <resources>
       <resource>
@@ -127,6 +131,26 @@
     </dependency>
 
     <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+      <version>2.5.5</version>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-webmvc-portlet</artifactId>
+      <version>2.5.5</version>
+      <optional>true</optional>
+      <exclusions>
+        <exclusion>
+          <groupId>org.springframework</groupId>
+          <artifactId>spring-webmvc</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+
+    <dependency>
       <groupId>javax.portlet</groupId>
       <artifactId>portlet-api</artifactId>
       <version>1.0</version>
diff --git a/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/PortletTilesApplicationContext.java b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/PortletTilesApplicationContext.java
index 9100909..ac157a3 100644
--- a/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/PortletTilesApplicationContext.java
+++ b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/PortletTilesApplicationContext.java
@@ -26,7 +26,8 @@
 import javax.portlet.PortletContext;
 import javax.portlet.PortletRequest;
 import javax.portlet.PortletResponse;
-import java.net.MalformedURLException;
+
+import java.io.IOException;
 import java.net.URL;
 import java.util.Map;
 import java.util.Set;
@@ -133,12 +134,12 @@
 
 
     /** {@inheritDoc} */
-    public URL getResource(String path) throws MalformedURLException {
+    public URL getResource(String path) throws IOException {
         return context.getResource(path);
     }
 
     /** {@inheritDoc} */
-    public Set<URL> getResources(String path) throws MalformedURLException {
+    public Set<URL> getResources(String path) throws IOException {
         HashSet<URL> set = new HashSet<URL>();
         set.add(getResource(path));
         return set;
diff --git a/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesApplicationContext.java b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesApplicationContext.java
new file mode 100644
index 0000000..87ad2eb
--- /dev/null
+++ b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesApplicationContext.java
@@ -0,0 +1,95 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.portlet.context.wildcard;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.portlet.context.PortletTilesApplicationContext;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.web.portlet.context.PortletContextResourcePatternResolver;
+
+/**
+ * Portlet-based implementation of the TilesApplicationContext interface that
+ * can resolve resources even using wildcards.
+ *
+ * @version $Rev$ $Date$
+ * @since 2.1.0
+ */
+public class WildcardPortletTilesApplicationContext extends
+        PortletTilesApplicationContext {
+
+    /**
+     * The pattern resolver.
+     *
+     * @since 2.1.0
+     */
+    protected ResourcePatternResolver resolver;
+
+    /**
+     * Constructor.
+     *
+     * @param portletContext The portlet context.
+     * @since 2.1.0
+     */
+    public WildcardPortletTilesApplicationContext(PortletContext portletContext) {
+        super(portletContext);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void initialize(PortletContext context) {
+        super.initialize(context);
+
+        resolver = new PortletContextResourcePatternResolver(context);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public URL getResource(String path) throws IOException {
+        URL retValue = null;
+        Set<URL> urlSet = getResources(path);
+        if (urlSet != null && !urlSet.isEmpty()) {
+            retValue = urlSet.iterator().next();
+        }
+        return retValue;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Set<URL> getResources(String path) throws IOException {
+        Set<URL> urlSet = null;
+        Resource[] resources = resolver.getResources(path);
+        if (resources != null && resources.length > 0) {
+            urlSet = new HashSet<URL>();
+            for (int i = 0; i < resources.length; i++) {
+                urlSet.add(resources[i].getURL());
+            }
+        }
+        return urlSet;
+    }
+}
diff --git a/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesContextFactory.java b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesContextFactory.java
new file mode 100644
index 0000000..686ea0b
--- /dev/null
+++ b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesContextFactory.java
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.portlet.context.wildcard;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.TilesApplicationContext;
+import org.apache.tiles.portlet.context.PortletTilesContextFactory;
+
+/**
+ * Acts like {@link ServletTilesContextFactory}, except in the
+ * {@link #createApplicationContext(Object)} method that creates an instance of
+ * {@link WildcardPortletTilesApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WildcardPortletTilesContextFactory extends
+        PortletTilesContextFactory {
+
+    /** {@inheritDoc} */
+    @Override
+    public TilesApplicationContext createApplicationContext(Object context) {
+        if (context instanceof PortletContext) {
+            PortletContext portletContext = (PortletContext) context;
+            return new WildcardPortletTilesApplicationContext(portletContext);
+        }
+        return null;
+    }
+}
diff --git a/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/package.html b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/package.html
new file mode 100644
index 0000000..fa87542
--- /dev/null
+++ b/tiles-portlet/src/main/java/org/apache/tiles/portlet/context/wildcard/package.html
@@ -0,0 +1,32 @@
+<!--
+/*
+ * $Id$
+ *
+ * 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.
+ */
+-->
+<html>
+<head>
+    <title>Tiles portlet-specific context package with wildcard support</title>
+</head>
+<body>
+Classes and interfaces that allow to access the various contexts from a portlet
+application. These classes can manage resource getting through the use of
+Spring-like wildcards patterns.
+</body>
+</html>
\ No newline at end of file
diff --git a/tiles-portlet/src/test/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesApplicationContextTest.java b/tiles-portlet/src/test/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesApplicationContextTest.java
new file mode 100644
index 0000000..c6fa8b3
--- /dev/null
+++ b/tiles-portlet/src/test/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesApplicationContextTest.java
@@ -0,0 +1,158 @@
+/*
+ * $Id: WildcardServletTilesApplicationContextTest.java 676174 2008-07-12 13:01:03Z apetrelli $
+ *
+ * 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.tiles.portlet.context.wildcard;
+
+import junit.framework.TestCase;
+import org.easymock.EasyMock;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Set;
+import java.util.Vector;
+import java.util.HashSet;
+
+import javax.portlet.PortletContext;
+
+
+/**
+ * Tests {@link WildcardPortletTilesApplicationContext}.
+ *
+ * @version $Rev: 676174 $ $Date: 2008-07-12 15:01:03 +0200 (sab, 12 lug 2008) $
+ */
+public class WildcardPortletTilesApplicationContextTest extends TestCase {
+
+    /**
+     * Number of properties container inside the test.properties file.
+     */
+    private static final int TEST_PROPERTIES_SIZE = 3;
+
+    /**
+     * Number of test classes.
+     */
+    private static final int TEST_TEST_SIZE = 2;
+
+    /**
+     * The root Tiles application context.
+     */
+    private PortletContext portletContext;
+
+    /**
+     * The enhanced Tiles application context.
+     */
+    private WildcardPortletTilesApplicationContext context;
+
+    /**
+     * The original class loader.
+     */
+    private ClassLoader original;
+
+    /** {@inheritDoc} */
+    @Override
+    public void setUp() {
+        portletContext = EasyMock.createMock(PortletContext.class);
+        original = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(new MockClassLoader());
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("Error when using the mock classloader");
+        }
+        context = new WildcardPortletTilesApplicationContext(portletContext);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void tearDown() throws Exception {
+        Thread.currentThread().setContextClassLoader(original);
+    }
+
+    /**
+     * Tests resource getting.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    public void testGetResources() throws IOException {
+        String url = "test.properties";
+        HashSet<URL> set = new HashSet<URL>();
+        URL u = new URL("file://tiles/test.properties");
+        set.add(u);
+        EasyMock.expect(portletContext.getResource("/" + url)).andReturn(u)
+                .anyTimes();
+        File dir = new File(".");
+        EasyMock.expect(portletContext.getResource("/WEB-INF/")).andReturn(
+                dir.toURI().toURL());
+        URL pomUrl = new URL("file://tiles/pom.xml");
+        EasyMock.expect(portletContext.getResource("/WEB-INF/pom.xml"))
+                .andReturn(pomUrl);
+        Set<String> elementSet = new HashSet<String>();
+        elementSet.add("/WEB-INF/pom.xml");
+        EasyMock.expect(portletContext.getResourcePaths("/WEB-INF/")).andReturn(elementSet);
+        EasyMock.replay(portletContext);
+
+        assertEquals(u, context.getResource("/" + url));
+        assertEquals(pomUrl, context.getResource("/WEB-INF/*.xml"));
+        assertEquals(TEST_PROPERTIES_SIZE, context.getResources(
+                "classpath*:/test.properties").size());
+
+        assertEquals(TEST_TEST_SIZE, context.getResources(
+                "classpath*:/org/apache/tiles/portlet/context/wildcard/*Test.class").size());
+        EasyMock.verify(portletContext);
+    }
+
+    /**
+     * An mock class loader.
+     */
+    public class MockClassLoader extends ClassLoader {
+
+        /**
+         * A vector of resources.
+         */
+        private Vector<URL> testPropertiesResources;
+
+        /**
+         * Constructor.
+         *
+         * @throws MalformedURLException If the URL is not valid (that should
+         * not happen).
+         */
+        public MockClassLoader() throws MalformedURLException {
+            testPropertiesResources = new Vector<URL>();
+            testPropertiesResources.add(new URL("file://tiles/test/test.properties"));
+            testPropertiesResources.add(new URL("file://tiles/two/test.properties"));
+            testPropertiesResources.add(new URL("file://tiles/three/test.properties"));
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public Enumeration<URL> findResources(String path) throws IOException {
+            Enumeration<URL> retValue = null;
+            if ("test.properties".equals(path)) {
+                retValue = testPropertiesResources.elements();
+            } else {
+                retValue = super.findResources(path);
+            }
+
+            return retValue;
+        }
+    }
+}
diff --git a/tiles-portlet/src/test/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesContextFactoryTest.java b/tiles-portlet/src/test/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesContextFactoryTest.java
new file mode 100644
index 0000000..496ed4d
--- /dev/null
+++ b/tiles-portlet/src/test/java/org/apache/tiles/portlet/context/wildcard/WildcardPortletTilesContextFactoryTest.java
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.portlet.context.wildcard;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.TilesApplicationContext;
+import org.easymock.EasyMock;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link WildcardPortletTilesContextFactory}.
+ */
+public class WildcardPortletTilesContextFactoryTest extends TestCase {
+
+    /**
+     * The factory to test.
+     */
+    private WildcardPortletTilesContextFactory factory;
+
+    /**
+     * The servlet context.
+     */
+    private PortletContext servletContext;
+
+    /** {@inheritDoc} */
+    public void setUp() {
+        servletContext = EasyMock.createMock(PortletContext.class);
+        factory = new WildcardPortletTilesContextFactory();
+        EasyMock.replay(servletContext);
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.tiles.servlet.context.wildcard.WildcardPortletTilesContextFactory
+     * #createApplicationContext(java.lang.Object)}.
+     */
+    public void testCreateApplicationContext() {
+        TilesApplicationContext context = factory
+                .createApplicationContext(servletContext);
+        assertTrue("The class of the application context is not correct",
+                context instanceof WildcardPortletTilesApplicationContext);
+    }
+}
diff --git a/tiles-servlet/pom.xml b/tiles-servlet/pom.xml
index c6997ee..407784b 100644
--- a/tiles-servlet/pom.xml
+++ b/tiles-servlet/pom.xml
@@ -26,7 +26,7 @@
   <parent>
     <groupId>org.apache.tiles</groupId>
     <artifactId>tiles-parent</artifactId>
-    <version>2.1.0-SNAPSHOT</version>
+    <version>2.1.0</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -36,6 +36,10 @@
   <description>Tiles servlet support, to enable use of Tiles inside a Servlet environment.
   </description>
 
+  <properties>
+      <tiles.osgi.symbolicName>org.apache.tiles.servlet</tiles.osgi.symbolicName>
+  </properties>
+
   <build>
     <resources>
       <resource>
@@ -127,24 +131,19 @@
     </dependency>
 
     <dependency>
-      <groupId>commons-digester</groupId>
-      <artifactId>commons-digester</artifactId>
-      <version>1.8</version>
-      <exclusions>
-        <exclusion>
-          <groupId>commons-logging</groupId>
-          <artifactId>commons-logging</artifactId>
-        </exclusion>
-      </exclusions>
-    </dependency>
-
-    <dependency>
       <groupId>commons-logging</groupId>
       <artifactId>commons-logging-api</artifactId>
       <version>1.1</version>
     </dependency>
 
     <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-web</artifactId>
+      <version>2.5.5</version>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
       <version>2.5</version>
diff --git a/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/ServletTilesApplicationContext.java b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/ServletTilesApplicationContext.java
index 2c8e8ae..85b4344 100644
--- a/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/ServletTilesApplicationContext.java
+++ b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/ServletTilesApplicationContext.java
@@ -26,7 +26,8 @@
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.net.MalformedURLException;
+
+import java.io.IOException;
 import java.net.URL;
 import java.util.Map;
 import java.util.Set;
@@ -95,12 +96,12 @@
     }
 
     /** {@inheritDoc} */
-    public URL getResource(String path) throws MalformedURLException {
+    public URL getResource(String path) throws IOException {
         return servletContext.getResource(path);
     }
 
     /** {@inheritDoc} */
-    public Set<URL> getResources(String path) throws MalformedURLException {
+    public Set<URL> getResources(String path) throws IOException {
         HashSet<URL> urls = new HashSet<URL>();
         urls.add(getResource(path));
         return urls;
diff --git a/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesApplicationContext.java b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesApplicationContext.java
new file mode 100644
index 0000000..88655fb
--- /dev/null
+++ b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesApplicationContext.java
@@ -0,0 +1,95 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.servlet.context.wildcard;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.servlet.context.ServletTilesApplicationContext;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.web.context.support.ServletContextResourcePatternResolver;
+
+/**
+ * Servlet-based implementation of the TilesApplicationContext interface that
+ * can resolve resources even using wildcards.
+ *
+ * @version $Rev$ $Date$
+ * @since 2.1.0
+ */
+public class WildcardServletTilesApplicationContext extends
+        ServletTilesApplicationContext {
+
+    /**
+     * The pattern resolver.
+     *
+     * @since 2.1.0
+     */
+    protected ResourcePatternResolver resolver;
+
+    /**
+     * Constructor.
+     *
+     * @param servletContext The servlet context.
+     * @since 2.1.0
+     */
+    public WildcardServletTilesApplicationContext(ServletContext servletContext) {
+        super(servletContext);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void initialize(ServletContext context) {
+        super.initialize(context);
+
+        resolver = new ServletContextResourcePatternResolver(context);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public URL getResource(String path) throws IOException {
+        URL retValue = null;
+        Set<URL> urlSet = getResources(path);
+        if (urlSet != null && !urlSet.isEmpty()) {
+            retValue = urlSet.iterator().next();
+        }
+        return retValue;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Set<URL> getResources(String path) throws IOException {
+        Set<URL> urlSet = null;
+        Resource[] resources = resolver.getResources(path);
+        if (resources != null && resources.length > 0) {
+            urlSet = new HashSet<URL>();
+            for (int i = 0; i < resources.length; i++) {
+                urlSet.add(resources[i].getURL());
+            }
+        }
+        return urlSet;
+    }
+}
diff --git a/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesContextFactory.java b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesContextFactory.java
new file mode 100644
index 0000000..e020b1d
--- /dev/null
+++ b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesContextFactory.java
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.servlet.context.wildcard;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.TilesApplicationContext;
+import org.apache.tiles.servlet.context.ServletTilesContextFactory;
+
+/**
+ * Acts like {@link ServletTilesContextFactory}, except in the
+ * {@link #createApplicationContext(Object)} method that creates an instance of
+ * {@link WildcardServletTilesApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WildcardServletTilesContextFactory extends
+        ServletTilesContextFactory {
+
+    /** {@inheritDoc} */
+    @Override
+    public TilesApplicationContext createApplicationContext(Object context) {
+        if (context instanceof ServletContext) {
+            ServletContext servletContext = (ServletContext) context;
+            return new WildcardServletTilesApplicationContext(servletContext);
+        }
+        return null;
+    }
+}
diff --git a/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/package.html b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/package.html
new file mode 100644
index 0000000..3f35735
--- /dev/null
+++ b/tiles-servlet/src/main/java/org/apache/tiles/servlet/context/wildcard/package.html
@@ -0,0 +1,32 @@
+<!--
+/*
+ * $Id$
+ *
+ * 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.
+ */
+-->
+<html>
+<head>
+    <title>Tiles servlet-specific context package with wildcard support</title>
+</head>
+<body>
+Classes and interfaces that allow to access the various contexts from a servlet
+application. These classes can manage resource getting through the use of
+Spring-like wildcards patterns.
+</body>
+</html>
\ No newline at end of file
diff --git a/tiles-servlet/src/main/resources/NOTICE.txt b/tiles-servlet/src/main/resources/NOTICE.txt
index 8386627..9e9e90a 100644
--- a/tiles-servlet/src/main/resources/NOTICE.txt
+++ b/tiles-servlet/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/tiles-servlet/src/test/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesApplicationContextTest.java b/tiles-servlet/src/test/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesApplicationContextTest.java
new file mode 100644
index 0000000..0a884d0
--- /dev/null
+++ b/tiles-servlet/src/test/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesApplicationContextTest.java
@@ -0,0 +1,153 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.servlet.context.wildcard;
+
+import junit.framework.TestCase;
+import org.easymock.EasyMock;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Set;
+import java.util.Vector;
+import java.util.HashSet;
+
+import javax.servlet.ServletContext;
+
+
+/**
+ * Tests {@link WildcardServletTilesApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WildcardServletTilesApplicationContextTest extends TestCase {
+
+    /**
+     * Number of properties container inside the test.properties file.
+     */
+    private static final int TEST_PROPERTIES_SIZE = 3;
+
+    /**
+     * The root Tiles application context.
+     */
+    private ServletContext servletContext;
+
+    /**
+     * The enhanced Tiles application context.
+     */
+    private WildcardServletTilesApplicationContext context;
+
+    /**
+     * The original class loader.
+     */
+    private ClassLoader original;
+
+    /** {@inheritDoc} */
+    @Override
+    public void setUp() {
+        servletContext = EasyMock.createMock(ServletContext.class);
+        original = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(new MockClassLoader());
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("Error when using the mock classloader");
+        }
+        context = new WildcardServletTilesApplicationContext(servletContext);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void tearDown() throws Exception {
+        Thread.currentThread().setContextClassLoader(original);
+    }
+
+    /**
+     * Tests resource getting.
+     *
+     * @throws IOException If something goes wrong.
+     */
+    public void testGetResources() throws IOException {
+        String url = "test.properties";
+        HashSet<URL> set = new HashSet<URL>();
+        URL u = new URL("file://tiles/test.properties");
+        set.add(u);
+        EasyMock.expect(servletContext.getResource("/" + url)).andReturn(u)
+                .anyTimes();
+        File dir = new File(".");
+        EasyMock.expect(servletContext.getResource("/WEB-INF/")).andReturn(
+                dir.toURI().toURL());
+        URL pomUrl = new URL("file://tiles/pom.xml");
+        EasyMock.expect(servletContext.getResource("/WEB-INF/pom.xml"))
+                .andReturn(pomUrl);
+        Set<String> elementSet = new HashSet<String>();
+        elementSet.add("/WEB-INF/pom.xml");
+        EasyMock.expect(servletContext.getResourcePaths("/WEB-INF/")).andReturn(elementSet);
+        EasyMock.replay(servletContext);
+
+        assertEquals(u, context.getResource("/" + url));
+        assertEquals(pomUrl, context.getResource("/WEB-INF/*.xml"));
+        assertEquals(TEST_PROPERTIES_SIZE, context.getResources(
+                "classpath*:/test.properties").size());
+
+        assertEquals(TEST_PROPERTIES_SIZE, context.getResources(
+                "classpath*:/org/apache/tiles/servlet/context/*Test.class").size());
+        EasyMock.verify(servletContext);
+    }
+
+    /**
+     * An mock class loader.
+     */
+    public class MockClassLoader extends ClassLoader {
+
+        /**
+         * A vector of resources.
+         */
+        private Vector<URL> testPropertiesResources;
+
+        /**
+         * Constructor.
+         *
+         * @throws MalformedURLException If the URL is not valid (that should
+         * not happen).
+         */
+        public MockClassLoader() throws MalformedURLException {
+            testPropertiesResources = new Vector<URL>();
+            testPropertiesResources.add(new URL("file://tiles/test/test.properties"));
+            testPropertiesResources.add(new URL("file://tiles/two/test.properties"));
+            testPropertiesResources.add(new URL("file://tiles/three/test.properties"));
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public Enumeration<URL> findResources(String path) throws IOException {
+            Enumeration<URL> retValue = null;
+            if ("test.properties".equals(path)) {
+                retValue = testPropertiesResources.elements();
+            } else {
+                retValue = super.findResources(path);
+            }
+
+            return retValue;
+        }
+    }
+}
diff --git a/tiles-servlet/src/test/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesContextFactoryTest.java b/tiles-servlet/src/test/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesContextFactoryTest.java
new file mode 100644
index 0000000..462c8a0
--- /dev/null
+++ b/tiles-servlet/src/test/java/org/apache/tiles/servlet/context/wildcard/WildcardServletTilesContextFactoryTest.java
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * 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.tiles.servlet.context.wildcard;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.TilesApplicationContext;
+import org.easymock.EasyMock;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link WildcardServletTilesContextFactory}.
+ */
+public class WildcardServletTilesContextFactoryTest extends TestCase {
+
+    /**
+     * The factory to test.
+     */
+    private WildcardServletTilesContextFactory factory;
+
+    /**
+     * The servlet context.
+     */
+    private ServletContext servletContext;
+
+    /** {@inheritDoc} */
+    public void setUp() {
+        servletContext = EasyMock.createMock(ServletContext.class);
+        factory = new WildcardServletTilesContextFactory();
+        EasyMock.replay(servletContext);
+    }
+
+    /**
+     * Test method for
+     * {@link org.apache.tiles.servlet.context.wildcard.WildcardServletTilesContextFactory
+     * #createApplicationContext(java.lang.Object)}.
+     */
+    public void testCreateApplicationContext() {
+        TilesApplicationContext context = factory
+                .createApplicationContext(servletContext);
+        assertTrue("The class of the application context is not correct",
+                context instanceof WildcardServletTilesApplicationContext);
+    }
+}
diff --git a/tiles-test/pom.xml b/tiles-test/pom.xml
index b0104e6..d71b2dd 100644
--- a/tiles-test/pom.xml
+++ b/tiles-test/pom.xml
@@ -26,7 +26,7 @@
    <parent>
       <groupId>org.apache.tiles</groupId>
       <artifactId>tiles-parent</artifactId>
-      <version>2.1.0-SNAPSHOT</version>
+      <version>2.1.0</version>
    </parent>
 
    <modelVersion>4.0.0</modelVersion>
@@ -95,7 +95,12 @@
       <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
-        <version>2.5.4</version>
+        <version>2.5.5</version>
+      </dependency>
+      <dependency>
+        <groupId>org.springframework</groupId>
+        <artifactId>spring-web</artifactId>
+        <version>2.5.5</version>
       </dependency>
    </dependencies>
    
@@ -121,7 +126,7 @@
            <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
-               <version>1.0-SNAPSHOT</version>
+               <version>1.0-20080724.220124-9</version>
                <configuration>
                    <container>
                        <containerId>tomcat6x</containerId>
@@ -307,18 +312,6 @@
             <dependencies>
                 <dependency>
                    <groupId>javax.servlet</groupId>
-                   <artifactId>servlet-api</artifactId>
-                   <version>2.4</version>
-                   <scope>provided</scope>
-                </dependency>
-                <dependency>
-                   <groupId>javax.servlet</groupId>
-                   <artifactId>jsp-api</artifactId>
-                   <version>2.0</version>
-                   <scope>provided</scope>
-                </dependency>
-                <dependency>
-                   <groupId>javax.servlet</groupId>
                    <artifactId>jstl</artifactId>
                    <version>1.1.2</version>
                    <scope>runtime</scope>
diff --git a/tiles-test/src/main/java/org/apache/tiles/test/factory/TestAlternateTilesContainerFactory.java b/tiles-test/src/main/java/org/apache/tiles/test/factory/TestAlternateTilesContainerFactory.java
index 4d17143..d9fa17e 100644
--- a/tiles-test/src/main/java/org/apache/tiles/test/factory/TestAlternateTilesContainerFactory.java
+++ b/tiles-test/src/main/java/org/apache/tiles/test/factory/TestAlternateTilesContainerFactory.java
@@ -53,7 +53,7 @@
             TilesContextFactory contextFactory) {
         List<URL> urls = new ArrayList<URL>(URL_COUNT);
         try {
-            urls.add(applicationContext.getResource("/WEB-INF/tiles-defs-alt.xml"));
+            urls.add(applicationContext.getResource("/WEB-INF/tiles-alt-defs.xml"));
         } catch (IOException e) {
             throw new DefinitionsFactoryException(
                     "Cannot load definition URLs", e);
diff --git a/tiles-test/src/main/java/org/apache/tiles/test/factory/TestTilesContainerFactory.java b/tiles-test/src/main/java/org/apache/tiles/test/factory/TestTilesContainerFactory.java
index dc6c35a..8530721 100644
--- a/tiles-test/src/main/java/org/apache/tiles/test/factory/TestTilesContainerFactory.java
+++ b/tiles-test/src/main/java/org/apache/tiles/test/factory/TestTilesContainerFactory.java
@@ -24,6 +24,7 @@
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import javax.el.ArrayELResolver;
 import javax.el.CompositeELResolver;
@@ -35,8 +36,8 @@
 import org.apache.tiles.TilesApplicationContext;
 import org.apache.tiles.TilesContainer;
 import org.apache.tiles.compat.definition.digester.CompatibilityDigesterDefinitionsReader;
+import org.apache.tiles.context.ChainedTilesContextFactory;
 import org.apache.tiles.context.TilesContextFactory;
-import org.apache.tiles.context.enhanced.EnhancedContextFactory;
 import org.apache.tiles.definition.DefinitionsFactoryException;
 import org.apache.tiles.definition.DefinitionsReader;
 import org.apache.tiles.evaluator.AttributeEvaluator;
@@ -46,8 +47,10 @@
 import org.apache.tiles.factory.BasicTilesContainerFactory;
 import org.apache.tiles.impl.BasicTilesContainer;
 import org.apache.tiles.impl.mgmt.CachingTilesContainer;
+import org.apache.tiles.jsp.context.JspTilesContextFactory;
 import org.apache.tiles.locale.LocaleResolver;
 import org.apache.tiles.renderer.impl.BasicRendererFactory;
+import org.apache.tiles.servlet.context.wildcard.WildcardServletTilesContextFactory;
 import org.apache.tiles.test.evaluator.el.MultiversionExpressionFactoryFactory;
 import org.apache.tiles.test.renderer.ReverseStringAttributeRenderer;
 
@@ -59,6 +62,11 @@
 public class TestTilesContainerFactory extends BasicTilesContainerFactory {
 
     /**
+     * The count of elements in the Tiles context factory chain.
+     */
+    private static final int CONTEXT_FACTORY_CHAIN_COUNT = 2;
+
+    /**
      * The number of URLs to load..
      */
     private static final int URL_COUNT = 3;
@@ -71,10 +79,13 @@
 
     /** {@inheritDoc} */
     @Override
-    protected TilesContextFactory createContextFactory(Object context) {
-        EnhancedContextFactory factory = new  EnhancedContextFactory();
-        registerChainedContextFactories(context, factory);
-        return factory;
+    protected void registerChainedContextFactories(Object context,
+            ChainedTilesContextFactory contextFactory) {
+        List<TilesContextFactory> factories = new ArrayList<TilesContextFactory>(
+                CONTEXT_FACTORY_CHAIN_COUNT);
+        factories.add(new WildcardServletTilesContextFactory());
+        factories.add(new JspTilesContextFactory());
+        contextFactory.setFactories(factories);
     }
 
     /** {@inheritDoc} */
@@ -125,9 +136,16 @@
             TilesContextFactory contextFactory) {
         List<URL> urls = new ArrayList<URL>(URL_COUNT);
         try {
-            urls.add(applicationContext.getResource("/WEB-INF/tiles-defs.xml"));
-            urls.add(applicationContext.getResource("/org/apache/tiles/classpath-defs.xml"));
-            urls.add(applicationContext.getResource("/WEB-INF/tiles-defs-1.1.xml"));
+            Set<URL> urlSet = applicationContext
+                    .getResources("/WEB-INF/tiles-defs*.xml");
+            for (URL url : urlSet) {
+                String externalForm = url.toExternalForm();
+                if (externalForm.indexOf('_', externalForm.lastIndexOf("/")) < 0) {
+                    urls.add(url);
+                }
+            }
+            urls.add(applicationContext.getResource(
+                    "classpath:/org/apache/tiles/classpath-defs.xml"));
         } catch (IOException e) {
             throw new DefinitionsFactoryException(
                     "Cannot load definition URLs", e);
diff --git a/tiles-test/src/main/resources/NOTICE.txt b/tiles-test/src/main/resources/NOTICE.txt
index 368e618..3eff9f2 100644
--- a/tiles-test/src/main/resources/NOTICE.txt
+++ b/tiles-test/src/main/resources/NOTICE.txt
@@ -1,5 +1,5 @@
    Apache Tiles
-   Copyright 1999-2007 The Apache Software Foundation
+   Copyright 1999-2008 The Apache Software Foundation
 
    This product includes software developed at
    The Apache Software Foundation (http://www.apache.org/).
diff --git a/tiles-test/src/main/webapp/WEB-INF/tiles-defs-alt.xml b/tiles-test/src/main/webapp/WEB-INF/tiles-alt-defs.xml
similarity index 100%
rename from tiles-test/src/main/webapp/WEB-INF/tiles-defs-alt.xml
rename to tiles-test/src/main/webapp/WEB-INF/tiles-alt-defs.xml
diff --git a/tiles-test/src/main/webapp/index.jsp b/tiles-test/src/main/webapp/index.jsp
index 261afdb..3b32b84 100644
--- a/tiles-test/src/main/webapp/index.jsp
+++ b/tiles-test/src/main/webapp/index.jsp
@@ -30,7 +30,7 @@
 <body>
     <h1>Tiles 2 Test Application</h1>
     
-    <h2>Currently working tests</h2>
+    <h2>Features in Tiles 2.0.x</h2>
 
     <h3>Standard Render/Attribute Tests</h3>
     <a href="testinsertdefinition.jsp">Test Insert Configured Definition</a><br/>
@@ -39,12 +39,42 @@
     <a href="testinsertdefinition_preparer_configured.jsp">Test Insert Configured Definition with Preparer configured in the definition itself</a><br/>
     <a href="testinsertdefinition_classpath.jsp">Test Insert Configured Classpath Definition</a><br/>
     <a href="testinsertdefinition_override.jsp">Test Insert Configured Definition with an overridden content</a><br/>
-    <a href="testinsertdefinition_override_template.jsp">Test Insert Configured Definition with an overridden template</a><br/>
     <a href="testinsertdefinition_override_and_not.jsp">Test Insert Configured Definition with an overridden content and one with original content</a><br/>
     <a href="testinsertdefinition_inline.jsp">Test Insert Configured Definition with an inline content</a><br/>
     <a href="testinsertdefinition_composite.jsp">Test Insert Configured Definition that contains another definition inside</a><br/>
     <a href="testinsertdefinition_exception.jsp">Test Insert Configured Definition with an exception in an attribute page</a><br/>
     <a href="testinsertdefinition_freemarker.jsp">Test Insert Configured Definition with FreeMarker</a><br/>
+    <a href="testinsertdefinition_openbody.jsp">Test Insert Configured Definition with Open Body</a><br/>
+    <a href="testput.jsp">Test Put Tag</a><br/>
+    <a href="testput_flush.jsp">Test Put Tag with Flush</a><br/>
+    <a href="testput_el.jsp">Test Put Tag using EL</a><br/>
+    <a href="testput_servlet.jsp">Test Put Tag using a servlet mapping as a template</a><br/>
+    <a href="testputlist.jsp">Test Put List Tag</a><br/>
+    <a href="testimportattribute.jsp">Test importAttribute Tag</a><br/>
+    <a href="testimportattribute_all.jsp">Test importAttribute Tag with no name</a><br/>
+    <a href="testdecorationfilter.jsp">Test Tiles Definition Filter</a><br/>
+    <a href="testdispatchservlet.tiles">Test Tiles Dispatch Servlet</a><br/>
+    <a href="selectlocale.jsp">Test Localization</a><br/>
+
+    <h3>Mutable Container Tests</h3>
+    <a href="testinitcontainer.jsp">Test Initialize Container</a><br/>
+    <a href="testdef.jsp">Test Definition Tag</a><br/>
+    <a href="testdef_extend.jsp">Test Definition Tag extending configured and custom definitions</a><br/>
+    <a href="testdef_preparer.jsp">Test Definition Tag with Preparer</a><br/>
+    <a href="testinsertdefinition_composite_tags_includes_configured.jsp">Test Insert Definition that contains another definition inside (configured via tiles-defs.xml) using JSP tags</a><br/>
+    <a href="testinsertdefinition_composite_tags.jsp">Test Insert Definition that contains another definition inside using JSP tags</a><br/>
+    <a href="testinsertdefinition_composite_tags_includes_configured_notype.jsp">Test Insert Definition that contains another definition inside (configured via tiles-defs.xml) using JSP tags without types</a><br/>
+    <a href="testinsertdefinition_composite_tags_notype.jsp">Test Insert Definition that contains another definition inside using JSP tags without types</a><br/></body>
+    
+    <h3>Roles Verification tests</h3>
+    <a href="testinsertdefinition_role.jsp">Test Insert Configured Definition with Specified Role</a><br/>
+    <a href="testinsertdefinition_role_tag.jsp">Test Insert Configured Definition with Specified Role in Tag</a><br/>
+    <a href="testinsertdefinition_attribute_roles.jsp">Test Insert Configured Definition with Attribute that have Roles</a><br/>
+
+    <h2>Features in Tiles 2.1.x</h2>
+
+    <h3>Standard Render/Attribute Tests</h3>
+    <a href="testinsertdefinition_override_template.jsp">Test Insert Configured Definition with an overridden template</a><br/>
     <a href="testinsertdefinition_old.jsp">Test Insert Configured Definition in Old Format</a><br/>
     <a href="testinsertdefinition_cascaded.jsp">Test Insert Configured Cascaded Definition</a><br/>
     <a href="testinsertdefinition_cascaded_overridden.jsp">Test Insert Configured Cascaded Definition with Override</a><br/>
@@ -58,49 +88,23 @@
     <a href="testinsertnestedlistdefinition.jsp">Test Insert Nested List Definition</a><br/>
     <a href="testinsertnestedlistdefinition_tags.jsp">Test Insert Nested List Definition only using JSP tags</a><br/>
     <a href="testinsertdefinition_el.jsp">Test Insert Configured Definition with EL</a><br/>
-    <a href="testinsertdefinition_openbody.jsp">Test Insert Configured Definition with Open Body</a><br/>
     <a href="testinsertdefinition_wildcard.jsp">Test Insert Configured Definition with Wildcards</a><br/>
-    <a href="testput.jsp">Test Put Tag</a><br/>
-    <a href="testput_flush.jsp">Test Put Tag with Flush</a><br/>
-    <a href="testput_el.jsp">Test Put Tag using EL</a><br/>
-    <a href="testput_servlet.jsp">Test Put Tag using a servlet mapping as a template</a><br/>
     <a href="testput_cascaded.jsp">Test Put Tag with Cascaded Attributes</a><br/>
     <a href="testput_cascaded_overridden.jsp">Test Put Tag with Overridden Cascaded Attributes</a><br/>
     <a href="testput_cascaded_template.jsp">Test Put Tag with Cascaded Attributes and Template</a><br/>
     <a href="testput_reversed.jsp">Test Put Tag with Reversed Attribute</a><br/>
     <a href="testput_reversed_explicit.jsp">Test Put Tag with Reversed Explicit Attribute</a><br/>
-    <a href="testputlist.jsp">Test Put List Tag</a><br/>
     <a href="testputlist_cascaded.jsp">Test Put List Cascaded Tag</a><br/>
     <a href="testputlist_inherit.jsp">Test Put List Tag with Inherit</a><br/>
-    <a href="testimportattribute.jsp">Test importAttribute Tag</a><br/>
-    <a href="testimportattribute_all.jsp">Test importAttribute Tag with no name</a><br/>
     <a href="testimportattribute_inherit.jsp">Test importAttribute Tag with List Inherit</a><br/>
-    <a href="testdecorationfilter.jsp">Test Tiles Definition Filter</a><br/>
-    <a href="testdispatchservlet.tiles">Test Tiles Dispatch Servlet</a><br/>
-    <a href="selectlocale.jsp">Test Localization</a><br/>
     <a href="testsetcurrentcontainer.jsp">Test setCurrentContainer Tag</a><br/>
 
     <h3>Mutable Container Tests</h3>
-    <a href="testinitcontainer.jsp">Test Initialize Container</a><br/>
-    <a href="testdef.jsp">Test Definition Tag</a><br/>
-    <a href="testdef_extend.jsp">Test Definition Tag extending configured and custom definitions</a><br/>
-    <a href="testdef_preparer.jsp">Test Definition Tag with Preparer</a><br/>
     <a href="testdef_list_inherit.jsp">Test Definition Tag with a List Inherit</a><br/>
-    <a href="testinsertdefinition_composite_tags_includes_configured.jsp">Test Insert Definition that contains another definition inside (configured via tiles-defs.xml) using JSP tags</a><br/>
-    <a href="testinsertdefinition_composite_tags.jsp">Test Insert Definition that contains another definition inside using JSP tags</a><br/>
-    <a href="testinsertdefinition_composite_tags_includes_configured_notype.jsp">Test Insert Definition that contains another definition inside (configured via tiles-defs.xml) using JSP tags without types</a><br/>
-    <a href="testinsertdefinition_composite_tags_notype.jsp">Test Insert Definition that contains another definition inside using JSP tags without types</a><br/></body>
-    
-    <h3>Roles Verification tests</h3>
-    <a href="testinsertdefinition_role.jsp">Test Insert Configured Definition with Specified Role</a><br/>
-    <a href="testinsertdefinition_role_tag.jsp">Test Insert Configured Definition with Specified Role in Tag</a><br/>
-    <a href="testinsertdefinition_attribute_roles.jsp">Test Insert Configured Definition with Attribute that have Roles</a><br/>
 
     <h3>Database Verification tests</h3>
     <a href="testinsertdefinition_db.jsp">Test Insert Configured Definition from DB</a><br/>
     <a href="testinsertdefinition_extended_db.jsp">Test Insert Extended Configured Definition from DB</a><br/>
     <a href="selectlocale_db.jsp">Test Localization from DB</a><br/>
 
-    <h2>Currently not working tests</h2>
-
 </html>
\ No newline at end of file