moved reactor aside as a tag
git-svn-id: https://svn.apache.org/repos/asf/tiles/framework/tags/tiles-3-reactor@1333558 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tiles-autotag/maven-autotag-plugin/pom.xml b/tiles-autotag/maven-autotag-plugin/pom.xml
new file mode 100644
index 0000000..72a7365
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/pom.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-autotag</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles.autotag.plugin</groupId>
+ <artifactId>maven-autotag-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>maven-plugin</packaging>
+ <name>maven-autotag-plugin Maven Mojo</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-api</artifactId>
+ <version>1.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ <version>1.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-jsp</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-freemarker</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-velocity</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.0</version>
+ <type>jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/AbstractGenerateMojo.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/AbstractGenerateMojo.java
new file mode 100644
index 0000000..b78e1ec
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/AbstractGenerateMojo.java
@@ -0,0 +1,175 @@
+/*
+ * $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.autotag.plugin;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;
+
+/**
+ * Abstract class to generate boilerplate code starting from template model classes.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractGenerateMojo extends AbstractMojo {
+ /**
+ * The position of the template suite XML descriptor.
+ */
+ static final String META_INF_TEMPLATE_SUITE_XML = "META-INF/template-suite.xml";
+
+ /**
+ * The classpath elements.
+ *
+ * @parameter expression="${project.compileClasspathElements}"
+ * @required
+ * @readonly
+ */
+ List<String> classpathElements;
+
+ /**
+ * Location of the generated classes.
+ *
+ * @parameter expression="${project.build.directory}/autotag-classes"
+ * @required
+ */
+ File classesOutputDirectory;
+
+ /**
+ * Location of the generated resources.
+ *
+ * @parameter expression="${project.build.directory}/autotag-resources"
+ * @required
+ */
+ File resourcesOutputDirectory;
+
+ /**
+ * Name of the package.
+ * @parameter expression="sample"
+ * @required
+ */
+ String packageName;
+
+ /**
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ MavenProject project;
+
+ /** {@inheritDoc} */
+ public void execute() throws MojoExecutionException {
+ try {
+ InputStream stream = findTemplateSuiteDescriptor();
+ XStream xstream = new XStream(new Sun14ReflectionProvider());
+ TemplateSuite suite = (TemplateSuite) xstream.fromXML(stream);
+ stream.close();
+
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ TemplateGenerator generator = createTemplateGeneratorFactory(
+ new VelocityEngine(props)).createTemplateGenerator();
+ generator.generate(packageName, suite, getParameters(), getRuntimeClass());
+ if (generator.isGeneratingResources()) {
+ Resource resource = new Resource();
+ resource.setDirectory(resourcesOutputDirectory.getAbsolutePath());
+ project.addResource(resource);
+ }
+ if (generator.isGeneratingClasses()) {
+ project.addCompileSourceRoot(classesOutputDirectory.getAbsolutePath());
+ }
+ } catch (IOException e) {
+ throw new MojoExecutionException("error", e);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new MojoExecutionException("error", e);
+ }
+ }
+
+ /**
+ * Creates a template generator factory.
+ *
+ * @param velocityEngine The Velocity engine.
+ * @return The template generator factory.
+ */
+ protected abstract TemplateGeneratorFactory createTemplateGeneratorFactory(VelocityEngine velocityEngine);
+
+ /**
+ * Returns the map of parameters.
+ *
+ * @return The parameters.
+ */
+ protected abstract Map<String, String> getParameters();
+
+ /**
+ * Searches for the template suite descriptor in all dependencies and sources.
+ *
+ * @return The inputstream of the identified descriptor.
+ * @throws IOException If something goes wrong.
+ */
+ private InputStream findTemplateSuiteDescriptor() throws IOException {
+ InputStream retValue = null;
+
+ for (String path : classpathElements) {
+ File file = new File(path);
+ if (file.isDirectory()) {
+ File candidate = new File(file, META_INF_TEMPLATE_SUITE_XML);
+ if (candidate.exists()) {
+ return new FileInputStream(candidate);
+ }
+ } else if (file.getPath().endsWith(".jar")) {
+ JarFile jar = new JarFile(file);
+ ZipEntry entry = jar.getEntry(META_INF_TEMPLATE_SUITE_XML);
+ if (entry != null) {
+ return jar.getInputStream(entry);
+ }
+ }
+ }
+
+ return retValue;
+ }
+
+ /**
+ * Name of the Runtime class.
+ * @return The name of the Runtime class.
+ */
+ protected abstract String getRuntimeClass();
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/CreateDescriptorMojo.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/CreateDescriptorMojo.java
new file mode 100644
index 0000000..50fc500
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/CreateDescriptorMojo.java
@@ -0,0 +1,179 @@
+/*
+ * $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.autotag.plugin;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.tiles.autotag.core.QDoxTemplateSuiteFactory;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
+import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
+import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
+import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
+
+import com.thoughtworks.xstream.XStream;
+
+/**
+ * Creates a descriptor for the template model in XML format.
+ *
+ * @goal create-descriptor
+ *
+ * @phase generate-resources
+ */
+public class CreateDescriptorMojo extends AbstractMojo {
+ /**
+ * Location of the file.
+ *
+ * @parameter expression="${project.build.directory}/autotag-template-suite"
+ * @required
+ */
+ File outputDirectory;
+
+ /**
+ * Location of the file.
+ *
+ * @parameter expression="${project.build.sourceDirectory}"
+ * @required
+ */
+ File sourceDirectory;
+
+ /**
+ * @parameter
+ */
+ Set<String> includes;
+
+ /**
+ * The name of the template.
+ *
+ * @parameter
+ * @required
+ */
+ String name;
+
+ /**
+ * The documentation of the suite.
+ *
+ * @parameter
+ */
+ String documentation;
+
+ /**
+ * @parameter
+ */
+ Set<String> excludes;
+
+ /**
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ MavenProject project;
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ public void execute() throws MojoExecutionException {
+ try {
+ Set<File> filesSet = getSourceInclusionScanner().getIncludedSources(
+ sourceDirectory, outputDirectory);
+ File[] files = new File[filesSet.size()];
+ QDoxTemplateSuiteFactory factory = new QDoxTemplateSuiteFactory(filesSet.toArray(files));
+ factory.setSuiteName(name);
+ factory.setSuiteDocumentation(documentation);
+ TemplateSuite suite = factory.createTemplateSuite();
+ XStream xstream = new XStream();
+ File dir = new File(outputDirectory, "META-INF");
+ dir.mkdirs();
+ File outputFile = new File(dir, "template-suite.xml");
+ outputFile.createNewFile();
+ Writer writer = new FileWriter(outputFile);
+ xstream.toXML(suite, writer);
+ writer.close();
+ Resource resource = new Resource();
+ resource.setDirectory(outputDirectory.getAbsolutePath());
+ project.addResource(resource);
+ } catch (InclusionScanException e) {
+ throw new MojoExecutionException("error", e);
+ } catch (IOException e) {
+ throw new MojoExecutionException("error", e);
+ }
+ }
+
+ /**
+ * Creates a source inclusion scanner.
+ *
+ * @return The inclusion scanner.
+ */
+ private SourceInclusionScanner getSourceInclusionScanner() {
+ SourceInclusionScanner scanner = null;
+ if (includes == null) {
+ includes = new HashSet<String>();
+ }
+ if (excludes == null) {
+ excludes = new HashSet<String>();
+ }
+
+ if (includes.isEmpty() && excludes.isEmpty()) {
+ includes = Collections.singleton("**/*Model.java");
+ scanner = new SimpleSourceInclusionScanner(includes, excludes);
+ } else {
+ if (includes.isEmpty()) {
+ includes = Collections.singleton("**/*Model.java");
+ }
+ scanner = new SimpleSourceInclusionScanner(includes, excludes);
+ }
+ scanner.addSourceMapping(new SourceMapping() {
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Set getTargetFiles(File targetDir, String source) {
+ return null;
+ }
+ });
+
+ return scanner;
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojo.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojo.java
new file mode 100644
index 0000000..9498ec3
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojo.java
@@ -0,0 +1,65 @@
+/*
+ * $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.autotag.plugin;
+
+import java.util.Map;
+
+import org.apache.tiles.autotag.freemarker.FMTemplateGeneratorFactory;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates Freemarker code.
+ *
+ * @goal generate-freemarker
+ *
+ * @phase generate-sources
+ * @requiresDependencyResolution compile
+ */
+public class GenerateFreemarkerMojo extends AbstractGenerateMojo {
+
+ /**
+ * Name of the Runtime.
+ * @parameter expression="org.apache.tiles.autotag.freemarker.runtime.Runtime"
+ * @required
+ */
+ String freemarkerRuntime;
+
+ /** {@inheritDoc} */
+ @Override
+ protected Map<String, String> getParameters() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected String getRuntimeClass() {
+ return freemarkerRuntime;
+ }
+
+ @Override
+ protected TemplateGeneratorFactory createTemplateGeneratorFactory(
+ VelocityEngine velocityEngine) {
+ return new FMTemplateGeneratorFactory(classesOutputDirectory,
+ velocityEngine, TemplateGeneratorBuilder.createNewInstance());
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateJspMojo.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateJspMojo.java
new file mode 100644
index 0000000..c76d536
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateJspMojo.java
@@ -0,0 +1,93 @@
+/*
+ * $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.autotag.plugin;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.tiles.autotag.jsp.JspTemplateGeneratorFactory;
+import org.apache.velocity.app.VelocityEngine;
+
+
+/**
+ * Goal which touches a timestamp file.
+ *
+ * @goal generate-jsp
+ *
+ * @phase generate-sources
+ * @requiresDependencyResolution compile
+ */
+public class GenerateJspMojo extends AbstractGenerateMojo {
+
+ /**
+ * URI of the tag library.
+ *
+ * @parameter expression="http://www.example.com/tags/example"
+ */
+ String taglibURI;
+
+ /**
+ * Name of the Runtime.
+ * @parameter expression="org.apache.tiles.autotag.jsp.runtime.Runtime"
+ * @required
+ */
+ String jspRuntime;
+
+ /** {@inheritDoc} */
+ @Override
+ protected Map<String, String> getParameters() {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("taglibURI", taglibURI);
+ return params;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected String getRuntimeClass() {
+ return jspRuntime;
+ }
+
+ @Override
+ protected TemplateGeneratorFactory createTemplateGeneratorFactory(
+ VelocityEngine velocityEngine) {
+ return new JspTemplateGeneratorFactory(classesOutputDirectory,
+ resourcesOutputDirectory, velocityEngine,
+ TemplateGeneratorBuilder.createNewInstance());
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateVelocityMojo.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateVelocityMojo.java
new file mode 100644
index 0000000..bda7ac4
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateVelocityMojo.java
@@ -0,0 +1,83 @@
+/*
+ * $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.autotag.plugin;
+
+/*
+ * Copyright 2001-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.tiles.autotag.velocity.VelocityTemplateGeneratorFactory;
+import org.apache.velocity.app.VelocityEngine;
+
+
+/**
+ * Generates Velocity code.
+ *
+ * @goal generate-velocity
+ *
+ * @phase generate-sources
+ * @requiresDependencyResolution compile
+ */
+public class GenerateVelocityMojo extends AbstractGenerateMojo {
+
+ /**
+ * Name of the Runtime.
+ * @parameter expression="org.apache.tiles.autotag.velocity.runtime.Runtime"
+ * @required
+ */
+ String velocityRuntime;
+
+ /** {@inheritDoc} */
+ @Override
+ protected Map<String, String> getParameters() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected String getRuntimeClass() {
+ return velocityRuntime;
+ }
+
+ @Override
+ protected TemplateGeneratorFactory createTemplateGeneratorFactory(
+ VelocityEngine velocityEngine) {
+ return new VelocityTemplateGeneratorFactory(classesOutputDirectory,
+ resourcesOutputDirectory, velocityEngine,
+ TemplateGeneratorBuilder.createNewInstance());
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/package-info.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/package-info.java
new file mode 100644
index 0000000..e25ccb0
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Contains the autotag mojos.
+ */
+package org.apache.tiles.autotag.plugin;
diff --git a/tiles-autotag/maven-autotag-plugin/src/site/site.xml b/tiles-autotag/maven-autotag-plugin/src/site/site.xml
new file mode 100644
index 0000000..0a7d00d
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/AbstractGenerateMojoTest.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/AbstractGenerateMojoTest.java
new file mode 100644
index 0000000..65e47ee
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/AbstractGenerateMojoTest.java
@@ -0,0 +1,93 @@
+/*
+ * $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.autotag.plugin;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractGenerateMojo}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractGenerateMojoTest {
+
+ /**
+ * Tests {@link AbstractGenerateMojo#execute()}.
+ * @throws IOException If something goes wrong.
+ * @throws MojoExecutionException If something goes wrong.
+ */
+ @Test
+ public void testExecute() throws IOException, MojoExecutionException {
+ MavenProject mavenProject = createMock(MavenProject.class);
+ TemplateGeneratorFactory factory = createMock(TemplateGeneratorFactory.class);
+ TemplateGenerator generator = createMock(TemplateGenerator.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> params = createMock(Map.class);
+ AbstractGenerateMojo mojo = createMockBuilder(AbstractGenerateMojo.class).createMock();
+ List<String> classpathElements = new ArrayList<String>();
+ File source = new File(System.getProperty("basedir"), "src/test/resources");
+ classpathElements.add(source.getAbsolutePath());
+ mojo.classpathElements = classpathElements;
+ File temp = File.createTempFile("autotagmojogen", ".tmp");
+ temp.delete();
+ temp.mkdirs();
+ File resourcesOutputDirectory = new File(temp, "res/");
+ File classesOutputDirectory = new File(temp, "classes/");
+ resourcesOutputDirectory.mkdir();
+ classesOutputDirectory.mkdir();
+ mojo.resourcesOutputDirectory = resourcesOutputDirectory;
+ mojo.classesOutputDirectory = classesOutputDirectory;
+ mojo.packageName = "my.package";
+ mojo.project = mavenProject;
+
+ expect(mojo.createTemplateGeneratorFactory(isA(VelocityEngine.class))).andReturn(factory);
+ expect(factory.createTemplateGenerator()).andReturn(generator);
+ expect(mojo.getParameters()).andReturn(params);
+ expect(mojo.getRuntimeClass()).andReturn("my.package.Runtime");
+ generator.generate(eq("my.package"), isA(TemplateSuite.class), eq(params), eq("my.package.Runtime"));
+ expect(generator.isGeneratingClasses()).andReturn(true);
+ expect(generator.isGeneratingResources()).andReturn(true);
+ mavenProject.addResource(isA(Resource.class));
+ mavenProject.addCompileSourceRoot(classesOutputDirectory.getAbsolutePath());
+
+ replay(mavenProject, mojo, factory, generator, params);
+ mojo.execute();
+ FileUtils.deleteDirectory(temp);
+ verify(mavenProject, mojo, factory, generator, params);
+ }
+
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/CreateDescriptorMojoTest.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/CreateDescriptorMojoTest.java
new file mode 100644
index 0000000..ccd4850
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/CreateDescriptorMojoTest.java
@@ -0,0 +1,163 @@
+/*
+ * $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.autotag.plugin;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.model.Resource;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.autotag.plugin.internal.AnnotatedExampleModel;
+import org.apache.tiles.autotag.plugin.internal.ExampleExecutableModel;
+import org.apache.tiles.autotag.plugin.internal.ExampleModel;
+import org.apache.tiles.autotag.plugin.internal.NotFeasibleExampleModel;
+import org.apache.tiles.request.Request;
+import org.junit.Test;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;
+
+/**
+ * Tests {@link CreateDescriptorMojo}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CreateDescriptorMojoTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.plugin.CreateDescriptorMojo#execute()}.
+ * @throws IOException If something goes wrong.
+ * @throws MojoExecutionException If something goes wrong.
+ */
+ @Test
+ public void testExecute() throws IOException, MojoExecutionException {
+ MavenProject mavenProject = createMock(MavenProject.class);
+
+ CreateDescriptorMojo mojo = new CreateDescriptorMojo();
+ mojo.sourceDirectory = new File(System.getProperty("basedir"), "src/test/java");
+ File temp = File.createTempFile("autotagmojo", ".tmp");
+ temp.delete();
+ temp.mkdirs();
+ mojo.outputDirectory = temp;
+ mojo.name = "test";
+ mojo.documentation = "This are the docs";
+ mojo.project = mavenProject;
+
+ mavenProject.addResource(isA(Resource.class));
+
+ replay(mavenProject);
+ mojo.execute();
+ InputStream sis = new FileInputStream(new File(temp, "META-INF/template-suite.xml"));
+ XStream xstream = new XStream(new Sun14ReflectionProvider());
+ TemplateSuite suite = (TemplateSuite) xstream.fromXML(sis);
+ sis.close();
+ assertEquals("test", suite.getName());
+ assertEquals("This are the docs", suite.getDocumentation());
+ assertEquals(3, suite.getTemplateClasses().size());
+
+ TemplateClass templateClass = suite.getTemplateClassByName(ExampleModel.class.getName());
+ assertNotNull(templateClass);
+ assertEquals(ExampleModel.class.getName(), templateClass.getName());
+ assertEquals("Example start/stop template.", templateClass.getDocumentation());
+ TemplateMethod templateMethod = templateClass.getExecuteMethod();
+ assertNotNull(templateMethod);
+ assertTrue(templateMethod.hasBody());
+ assertTrue(templateClass.hasBody());
+ assertEquals("execute", templateMethod.getName());
+ assertEquals("It starts.", templateMethod.getDocumentation());
+ List<TemplateParameter> parameters = new ArrayList<TemplateParameter>(templateMethod.getParameters());
+ assertEquals(4, parameters.size());
+ TemplateParameter parameter = parameters.get(0);
+ assertEquals("one", parameter.getName());
+ assertEquals("java.lang.String", parameter.getType());
+ assertEquals("Parameter one.", parameter.getDocumentation());
+ parameter = parameters.get(1);
+ assertEquals("two", parameter.getName());
+ assertEquals("int", parameter.getType());
+ assertEquals("Parameter two.", parameter.getDocumentation());
+ parameter = parameters.get(2);
+ assertEquals("request", parameter.getName());
+ assertEquals(Request.class.getName(), parameter.getType());
+ assertEquals("The request.", parameter.getDocumentation());
+ parameter = parameters.get(3);
+ assertEquals("modelBody", parameter.getName());
+ assertEquals(ModelBody.class.getName(), parameter.getType());
+ assertEquals("The model body.", parameter.getDocumentation());
+
+ templateClass = suite.getTemplateClassByName(AnnotatedExampleModel.class.getName());
+ assertNotNull(templateClass);
+ assertEquals(AnnotatedExampleModel.class.getName(), templateClass.getName());
+ templateMethod = templateClass.getExecuteMethod();
+ assertNotNull(templateMethod);
+ assertEquals("execute", templateMethod.getName());
+ parameters = new ArrayList<TemplateParameter>(templateMethod.getParameters());
+ assertEquals(4, parameters.size());
+ parameter = parameters.get(0);
+ assertEquals("one", parameter.getName());
+ assertEquals("alternateOne", parameter.getExportedName());
+ assertEquals("java.lang.String", parameter.getType());
+ assertEquals("Parameter one.", parameter.getDocumentation());
+ assertEquals("hello", parameter.getDefaultValue());
+ assertTrue(parameter.isRequired());
+
+ templateClass = suite.getTemplateClassByName(ExampleExecutableModel.class.getName());
+ assertNotNull(templateClass);
+ assertEquals(ExampleExecutableModel.class.getName(), templateClass.getName());
+ assertEquals("Example executable template.", templateClass.getDocumentation());
+ templateMethod = templateClass.getExecuteMethod();
+ assertNotNull(templateMethod);
+ assertEquals("execute", templateMethod.getName());
+ assertEquals("It executes.", templateMethod.getDocumentation());
+ parameters = new ArrayList<TemplateParameter>(templateMethod.getParameters());
+ assertEquals(3, parameters.size());
+ parameter = parameters.get(0);
+ assertEquals("one", parameter.getName());
+ assertEquals("java.lang.String", parameter.getType());
+ assertEquals("Parameter one.", parameter.getDocumentation());
+ parameter = parameters.get(1);
+ assertEquals("two", parameter.getName());
+ assertEquals("int", parameter.getType());
+ assertEquals("Parameter two.", parameter.getDocumentation());
+ parameter = parameters.get(2);
+ assertEquals("request", parameter.getName());
+ assertEquals(Request.class.getName(), parameter.getType());
+ assertEquals("The request.", parameter.getDocumentation());
+
+ assertNull(suite.getTemplateClassByName(NotFeasibleExampleModel.class.getName()));
+ FileUtils.deleteDirectory(temp);
+ verify(mavenProject);
+ }
+
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojoTest.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojoTest.java
new file mode 100644
index 0000000..767cc38
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojoTest.java
@@ -0,0 +1,53 @@
+/*
+ * $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.autotag.plugin;
+
+import static org.junit.Assert.*;
+
+import org.apache.tiles.autotag.freemarker.FMTemplateGeneratorFactory;
+import org.junit.Test;
+
+/**
+ * Tests {@link GenerateFreemarkerMojo}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class GenerateFreemarkerMojoTest {
+
+ /**
+ * Test method for {@link GenerateFreemarkerMojo#createTemplateGeneratorFactory(VelocityEngine)}.
+ */
+ @Test
+ public void testCreateTemplateGeneratorFactory() {
+ GenerateFreemarkerMojo mojo = new GenerateFreemarkerMojo();
+ assertTrue(mojo.createTemplateGeneratorFactory(null) instanceof FMTemplateGeneratorFactory);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.plugin.GenerateFreemarkerMojo#getParameters()}.
+ */
+ @Test
+ public void testGetParameters() {
+ GenerateFreemarkerMojo mojo = new GenerateFreemarkerMojo();
+ assertNull(mojo.getParameters());
+ }
+
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateJspMojoTest.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateJspMojoTest.java
new file mode 100644
index 0000000..40e4a66
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateJspMojoTest.java
@@ -0,0 +1,54 @@
+/*
+ * $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.autotag.plugin;
+
+import static org.junit.Assert.*;
+
+import org.apache.tiles.autotag.jsp.JspTemplateGeneratorFactory;
+import org.junit.Test;
+
+/**
+ * Tests {@link GenerateJspMojo}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class GenerateJspMojoTest {
+
+ /**
+ * Test method for {@link GenerateJspMojo#createTemplateGeneratorFactory(VelocityEngine)}.
+ */
+ @Test
+ public void testCreateTemplateGeneratorFactory() {
+ GenerateJspMojo mojo = new GenerateJspMojo();
+ assertTrue(mojo.createTemplateGeneratorFactory(null) instanceof JspTemplateGeneratorFactory);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.plugin.GenerateJspMojo#getParameters()}.
+ */
+ @Test
+ public void testGetParameters() {
+ GenerateJspMojo mojo = new GenerateJspMojo();
+ mojo.taglibURI = "http://www.test.org/taglib";
+ assertEquals("http://www.test.org/taglib", mojo.getParameters().get("taglibURI"));
+ }
+
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateVelocityMojoTest.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateVelocityMojoTest.java
new file mode 100644
index 0000000..4f859ce
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/GenerateVelocityMojoTest.java
@@ -0,0 +1,53 @@
+/*
+ * $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.autotag.plugin;
+
+import static org.junit.Assert.*;
+
+import org.apache.tiles.autotag.velocity.VelocityTemplateGeneratorFactory;
+import org.junit.Test;
+
+/**
+ * Tests {@link GenerateVelocityMojo}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class GenerateVelocityMojoTest {
+
+ /**
+ * Test method for {@link GenerateVelocityMojo#createTemplateGeneratorFactory(VelocityEngine)}.
+ */
+ @Test
+ public void testCreateTemplateGeneratorFactory() {
+ GenerateVelocityMojo mojo = new GenerateVelocityMojo();
+ assertTrue(mojo.createTemplateGeneratorFactory(null) instanceof VelocityTemplateGeneratorFactory);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.plugin.GenerateVelocityMojo#getParameters()}.
+ */
+ @Test
+ public void testGetParameters() {
+ GenerateVelocityMojo mojo = new GenerateVelocityMojo();
+ assertNull(mojo.getParameters());
+ }
+
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/AnnotatedExampleModel.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/AnnotatedExampleModel.java
new file mode 100644
index 0000000..02e3678
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/AnnotatedExampleModel.java
@@ -0,0 +1,47 @@
+/*
+ * $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.autotag.plugin.internal;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.annotation.Parameter;
+import org.apache.tiles.request.Request;
+
+/**
+ * Example start/stop template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AnnotatedExampleModel {
+
+ /**
+ * It starts.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ * @param modelBody The model body.
+ */
+ public void execute(
+ @Parameter(defaultValue = "hello", name = "alternateOne", required = true) String one,
+ int two, Request request, ModelBody modelBody) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleExcluded.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleExcluded.java
new file mode 100644
index 0000000..a09ca23
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleExcluded.java
@@ -0,0 +1,44 @@
+/*
+ * $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.autotag.plugin.internal;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+
+/**
+ * Example start/stop template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExampleExcluded {
+
+ /**
+ * It starts.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ * @param modelBody The model body.
+ */
+ public void execute(String one, int two, Request request, ModelBody modelBody) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleExecutableModel.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleExecutableModel.java
new file mode 100644
index 0000000..9f49651
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleExecutableModel.java
@@ -0,0 +1,42 @@
+/*
+ * $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.autotag.plugin.internal;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * Example executable template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExampleExecutableModel {
+
+ /**
+ * It executes.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ */
+ public void execute(String one, int two, Request request) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleModel.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleModel.java
new file mode 100644
index 0000000..a080d01
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/ExampleModel.java
@@ -0,0 +1,44 @@
+/*
+ * $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.autotag.plugin.internal;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+
+/**
+ * Example start/stop template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExampleModel {
+
+ /**
+ * It starts.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ * @param modelBody The model body.
+ */
+ public void execute(String one, int two, Request request, ModelBody modelBody) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/NotFeasibleExampleModel.java b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/NotFeasibleExampleModel.java
new file mode 100644
index 0000000..a52eb62
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/java/org/apache/tiles/autotag/plugin/internal/NotFeasibleExampleModel.java
@@ -0,0 +1,38 @@
+/*
+ * $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.autotag.plugin.internal;
+
+/**
+ * This won't be registered.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotFeasibleExampleModel {
+
+ /**
+ * It starts.
+ *
+ * @param whatever Doesn't matter.
+ */
+ public void start(String whatever) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/maven-autotag-plugin/src/test/resources/META-INF/template-suite.xml b/tiles-autotag/maven-autotag-plugin/src/test/resources/META-INF/template-suite.xml
new file mode 100644
index 0000000..de0a133
--- /dev/null
+++ b/tiles-autotag/maven-autotag-plugin/src/test/resources/META-INF/template-suite.xml
@@ -0,0 +1,183 @@
+<!--
+/*
+ * $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.
+ */
+ -->
+<org.apache.tiles.autotag.model.TemplateSuite>
+ <name>test</name>
+ <templateClasses class="linked-hash-map">
+ <entry>
+ <string>org.apache.tiles.autotag.plugin.internal.ExampleExecutableModel</string>
+ <org.apache.tiles.autotag.model.TemplateClass>
+ <name>org.apache.tiles.autotag.plugin.internal.ExampleExecutableModel</name>
+ <tagName>exampleExecutable</tagName>
+ <tagClassPrefix>ExampleExecutable</tagClassPrefix>
+ <documentation>Example executable template.</documentation>
+ <executeMethod>
+ <name>execute</name>
+ <documentation>It executes.</documentation>
+ <parameters class="linked-hash-map">
+ <entry>
+ <string>one</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>one</name>
+ <exportedName>one</exportedName>
+ <documentation>Parameter one.</documentation>
+ <type>java.lang.String</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>two</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>two</name>
+ <exportedName>two</exportedName>
+ <documentation>Parameter two.</documentation>
+ <type>int</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>request</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>request</name>
+ <exportedName>request</exportedName>
+ <documentation>The request.</documentation>
+ <type>org.apache.tiles.request.Request</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ </parameters>
+ </executeMethod>
+ </org.apache.tiles.autotag.model.TemplateClass>
+ </entry>
+ <entry>
+ <string>org.apache.tiles.autotag.plugin.internal.ExampleModel</string>
+ <org.apache.tiles.autotag.model.TemplateClass>
+ <name>org.apache.tiles.autotag.plugin.internal.ExampleModel</name>
+ <tagName>example</tagName>
+ <tagClassPrefix>Example</tagClassPrefix>
+ <documentation>Example start/stop template.</documentation>
+ <executeMethod>
+ <name>execute</name>
+ <documentation>It starts.</documentation>
+ <parameters class="linked-hash-map">
+ <entry>
+ <string>one</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>one</name>
+ <exportedName>one</exportedName>
+ <documentation>Parameter one.</documentation>
+ <type>java.lang.String</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>two</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>two</name>
+ <exportedName>two</exportedName>
+ <documentation>Parameter two.</documentation>
+ <type>int</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>request</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>request</name>
+ <exportedName>request</exportedName>
+ <documentation>The request.</documentation>
+ <type>org.apache.tiles.request.Request</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>modelBody</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>modelBody</name>
+ <exportedName>modelBody</exportedName>
+ <documentation>The model body.</documentation>
+ <type>org.apache.tiles.autotag.core.runtime.ModelBody</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ </parameters>
+ </executeMethod>
+ </org.apache.tiles.autotag.model.TemplateClass>
+ </entry>
+ <entry>
+ <string>org.apache.tiles.autotag.plugin.internal.AnnotatedExampleModel</string>
+ <org.apache.tiles.autotag.model.TemplateClass>
+ <name>org.apache.tiles.autotag.plugin.internal.AnnotatedExampleModel</name>
+ <tagName>annotatedExample</tagName>
+ <tagClassPrefix>AnnotatedExample</tagClassPrefix>
+ <documentation>Example start/stop template.</documentation>
+ <executeMethod>
+ <name>execute</name>
+ <documentation>It starts.</documentation>
+ <parameters class="linked-hash-map">
+ <entry>
+ <string>one</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>one</name>
+ <exportedName>alternateOne</exportedName>
+ <documentation>Parameter one.</documentation>
+ <type>java.lang.String</type>
+ <defaultValue>hello</defaultValue>
+ <required>true</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>two</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>two</name>
+ <exportedName>two</exportedName>
+ <documentation>Parameter two.</documentation>
+ <type>int</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>request</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>request</name>
+ <exportedName>request</exportedName>
+ <documentation>The request.</documentation>
+ <type>org.apache.tiles.request.Request</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ <entry>
+ <string>modelBody</string>
+ <org.apache.tiles.autotag.model.TemplateParameter>
+ <name>modelBody</name>
+ <exportedName>modelBody</exportedName>
+ <documentation>The model body.</documentation>
+ <type>org.apache.tiles.autotag.core.runtime.ModelBody</type>
+ <required>false</required>
+ </org.apache.tiles.autotag.model.TemplateParameter>
+ </entry>
+ </parameters>
+ </executeMethod>
+ </org.apache.tiles.autotag.model.TemplateClass>
+ </entry>
+ </templateClasses>
+</org.apache.tiles.autotag.model.TemplateSuite>
\ No newline at end of file
diff --git a/tiles-autotag/pom.xml b/tiles-autotag/pom.xml
new file mode 100644
index 0000000..444155b
--- /dev/null
+++ b/tiles-autotag/pom.xml
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-master</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>4</version>
+ <relativePath/>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Autotags</name>
+ <description>Automatic generation of tags.</description>
+ <url>http://tiles.apache.org/tiles-autotag/</url>
+ <scm>
+ <connection>scm:svn:http://svn.eu.apache.org/repos/asf/tiles/framework/trunk/tiles-autotag/</connection>
+ <developerConnection>scm:svn:https://svn.eu.apache.org/repos/asf/tiles/framework/trunk/tiles-autotag/</developerConnection>
+ <url>http://svn.eu.apache.org/viewvc/tiles/framework/trunk/tiles-autotag/</url>
+ </scm>
+ <issueManagement>
+ <system>JIRA</system>
+ <url>https://issues.apache.org/jira/browse/AUTOTAG</url>
+ </issueManagement>
+
+ <modules>
+ <module>tiles-autotag-core-runtime</module>
+ <module>tiles-autotag-core</module>
+ <module>tiles-autotag-jsp</module>
+ <module>tiles-autotag-freemarker</module>
+ <module>tiles-autotag-velocity</module>
+ <module>maven-autotag-plugin</module>
+ </modules>
+ <distributionManagement>
+ <site>
+ <id>apache-site</id>
+ <url>scp://people.apache.org/www/tiles.apache.org/tiles-autotag</url>
+ </site>
+ </distributionManagement>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.qdox</groupId>
+ <artifactId>qdox</artifactId>
+ <version>1.10.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ <version>1.6.3</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.0</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <profiles>
+ <profile>
+ <id>apache-release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <createChecksum>true</createChecksum>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ <version>1.0-alpha-3</version>
+ <executions>
+ <execution>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <addDefaultLicenseMatchers>false</addDefaultLicenseMatchers>
+ <licenseMatchers>
+ <classNames>
+ <className>rat.analysis.license.ApacheSoftwareLicense20</className>
+ </classNames>
+ <classNames>
+ <className>rat.analysis.generation.GeneratedLicenseNotRequired</className>
+ </classNames>
+ </licenseMatchers>
+ <includes>
+ <include>pom.xml</include>
+ <include>src/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*LICENSE.txt</exclude>
+ <exclude>**/*MANIFEST.MF</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>linkcheck</id>
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-linkcheck-plugin</artifactId>
+ <version>1.1</version>
+ <configuration>
+ <excludedLinks>
+ <excludedLink>**/index.html</excludedLink>
+ <excludedLink>**/logo.png</excludedLink>
+ </excludedLinks>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ </profile>
+
+ </profiles>
+
+</project>
diff --git a/tiles-autotag/src/site/apt/dev/release.apt b/tiles-autotag/src/site/apt/dev/release.apt
new file mode 100644
index 0000000..ab9bd52
--- /dev/null
+++ b/tiles-autotag/src/site/apt/dev/release.apt
@@ -0,0 +1,351 @@
+~~ $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.
+~~
+ -----------
+ Release Process
+ -----------
+
+Tiles Release Process
+
+ Here you will find the steps to create releases for Tiles.
+
+Prerequisites
+
+ To create a release you have to install:
+
+ * {{{http://java.sun.com/javase/6}Java 6.0}}. If you are using a newer
+ version of Java, it is suggested to <<change JAVA_HOME environment variable>>
+ when calling Maven, so it points to an instance of Java 6.0;
+
+ * {{{http://maven.apache.org/}Maven 2.2 or 3}};
+
+ * {{{http://www.gnupg.org/}GnuPG}};
+
+ * {{{http://www.openssh.com/}OpenSSH}};
+
+ * {{{http://www.graphviz.org/}GraphViz}};
+
+One-time operations
+
+ These operations need to be performed only one time.
+
+* Create and publish your GPG key
+
+ To create a GPG key, follow the
+ {{{http://www.apache.org/dev/openpgp.html}guidelines}}.
+ Include it in:
+
+-------------------------------------
+https://svn.apache.org/repos/asf/tiles/site/KEYS
+-------------------------------------
+
+ Publish your GPG key in a PGP key server, such as
+ {{{http://pgp.mit.edu/} MIT Keyserver}}.
+
+* Create and upload yout SSH key
+
+ * Generate your SSH key (in this case we will use DSA encryption):
+
+---------------------------------
+ssh-keygen -t rsa
+---------------------------------
+
+ * Copy your public key to the server:
+
+--------------------------------------
+scp ~/.ssh/id_rsa.pub user@people.apache.org:.ssh/authorized_keys
+--------------------------------------
+
+ * Try to login:
+
+---------------------------------
+ssh user@people.apache.org
+---------------------------------
+
+ If it does not ask you a password, everything is ok.
+
+* Modify <<<settings.xml>>>
+
+ Your <<<settings.xml>>> must be modified to allow deployment.
+
+ This is the minimal configuration, obviously if you already have a <<<settings.xml>>> file,
+ you must edit it:
+
+---------------------------
+<settings xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/settings-1.0.0.xsd">
+ <servers>
+ <server>
+ <id>apache-site</id>
+ <username>YOUR_APACHE_USERNAME</username>
+ <filePermissions>664</filePermissions>
+ <directoryPermissions>775</directoryPermissions>
+ </server>
+ <server>
+ <id>apache.snapshots.https</id>
+ <username>YOUR_APACHE_USERNAME</username>
+ <password>YOUR_APACHE_PASSWORD</password>
+ </server>
+ <server>
+ <id>apache.releases.https</id>
+ <username>YOUR_APACHE_USERNAME</username>
+ <password>YOUR_APACHE_PASSWORD</password>
+ </server>
+ </servers>
+ <profiles>
+ <profile>
+ <id>release</id>
+ <properties>
+ <gpg.passphrase>YOUR_SECRET_PHRASE</gpg.passphrase>
+ </properties>
+ </profile>
+ </profile>
+ </profiles>
+</settings>
+---------------------------
+
+Repeatable operations
+
+ These steps must be performed <<for each>> release.
+
+* Prepare the release tag
+
+ To prepare the release Subversion tag, check out the branch/trunk from where
+ you are preparing the release and type:
+
+-----------------------------------
+mvn release:prepare -Dusername=YOUR_SVN_USER -Dpassword=YOUR_SVN_PASSWORD
+-----------------------------------
+
+ The plugin interactively will ask you the version to release, the Subversion
+ tag to use and the next snapshot version. It is reccomended to use the tag:
+ <<tiles-X.X.X>>.
+
+* Perform the Release
+
+ To perform the release, i.e. creating and deploying Maven artifacts, use:
+
+-----------------------------------
+mvn release:perform
+-----------------------------------
+
+* Close the staging repository
+
+ Login to {{{https://repository.apache.org} Nexus repository}} using your Apache LDAP credentials.
+ Click on "Staging". Then click on "tiles" in the list of repositories.
+ In the panel below you should see an open repository that is linked to your username and ip.
+ Right click on this repository and select "Close".
+ This will close the repository from future deployments and make it available for others to view.
+ If you are staging multiple releases together, skip this step until you have staged everything.
+ Enter the name and version of the artifact being released in the "Description" field and then click "Close".
+ This will make it easier to identify it later.
+
+* Verify the staged artifacts
+
+ If you click on your repository, a tree view will appear below.
+ You can then browse the contents to ensure the artifacts are as you expect them.
+ Pay particular attention to the existence of *.asc (signature) files.
+ If the you don't like the content of the repository, right click your repository and choose "Drop".
+ You can then rollback your release and repeat the process.
+
+ Note the repository URL, you will need this in your vote email.
+
+* Digest and upload assemblies
+
+ * Go into the release assembly target directory:
+
+-----------------------------------
+cd target/checkout/assembly/target/assembly/out
+-----------------------------------
+
+ * Create MD5 and SHA1 files for each files (including ASC files). You can do
+ it with this simple shell script:
+
+-----------------------------------
+#!/bin/sh
+
+for fileitem in *
+do
+ openssl md5 < $fileitem > $fileitem.md5
+ openssl sha1 < $fileitem > $fileitem.sha1
+done
+-----------------------------------
+
+ * Upload everything to the build site:
+
+-----------------------------------
+scp * user@people.apache.org:/www/people.apache.org/builds/tiles/${version}
+-----------------------------------
+
+* Release the JIRA version
+
+ * In JIRA go to the version that you want to release and release it.
+
+ * Create a new version, if it has not been done before.
+
+ * Create the release notes and <<write down the link>> that it uses.
+
+* Send announcement for the test build
+
+ In <<developers mailing list>> send an announcement for the test build:
+
+-----------------------------------
+Subject: [ANNOUNCE] Tiles ${version} test build available
+
+The test build of Tiles ${version} is available.
+
+
+No determination as to the quality ('alpha,' 'beta,' or 'GA') of Tiles
+${version} has been made, and at this time it is simply a "test build". We
+welcome any comments you may have, and will take all feedback into
+account if a quality vote is called for this build.
+
+Release notes:
+
+* ${jira.release.notes}
+
+Distribution:
+
+ * http://people.apache.org/builds/tiles/${version}/
+
+Maven 2 staging repository:
+
+ * https://repository.apache.org/content/repositories/tiles-[YOUR REPOSITORY ID]/
+
+A vote regarding the quality of this test build will be initiated
+within the next couple of days.
+-----------------------------------
+
+* Call for a vote
+
+ A few days after the test build announcement, call for a vote in
+ <<developers mailing list>>.
+
+-----------------------------------
+Subject: [VOTE] ${version} Release Quality
+
+The Tiles ${version} test build has been available since ${testBuildDate}.
+
+Release notes:
+
+* ${jira.release.notes}
+
+Distribution:
+
+ * http://people.apache.org/builds/tiles/${version}/
+
+Maven 2 staging repository:
+
+ * https://repository.apache.org/content/repositories/tiles-[YOUR REPOSITORY ID]/
+
+If you have had a chance to review the test build, please respond with
+a vote on its quality:
+
+ [ ] Leave at test build
+ [ ] Alpha
+ [ ] Beta
+ [ ] General Availability (GA)
+
+
+Everyone who has tested the build is invited to vote. Votes by PMC
+members are considered binding. A vote passes if there are at least
+three binding +1s and more +1s than -1s.
+-----------------------------------
+
+* Post-vote operations
+
+ After a vote is finished, and it has been decided that is
+ <<at least of alpha quality>>, there is the need of a post-vote process.
+
+** Promote staged artifacts
+
+ Once the release is deemed fit for public consumption it can be transfered to a production repository where it will be available to all users.
+
+ Login to {{{https://repository.apache.org}Nexus repository}} again.
+ Click on "Staging" and then on the repository with id "tiles-staging".
+ Find your closed staging repository, right click on it and choose "Promote".
+ Select the "Releases" repository and click "Promote".
+
+ Next click on "Repositories", select the "Releases" repository
+ and validate that your artifacts exist as you expect them.
+
+** Move assemblies
+
+ * Move assemblies to the Apache distribution mirrors:
+
+-------------------------------------------
+ssh user@people.apache.org
+
+cd /www/people.apache.org/builds/tiles/${version}
+mkdir /www/www.apache.org/dist/tiles/v${version}/
+cp * /www/www.apache.org/dist/tiles/v${version}/
+-------------------------------------------
+
+** Update the site
+
+ * Wait 24 hours to let the mirror sync to the release and then update the
+ site. In particular you have to update the index and the download pages:
+
+------------------------------------------------
+https://svn.apache.org/repos/asf/tiles/site/src/site/xdoc/index.xml
+https://svn.apache.org/repos/asf/tiles/site/src/site/apt/download.apt
+------------------------------------------------
+
+ Build and publish the site:
+
+--------------------------------------
+mvn site
+mvn site:deploy
+--------------------------------------
+
+** Send announcement
+
+ Finally, send an an announcement to the <<users>> and <<developers mailing
+ list>>:
+
+--------------------------------------
+Subject: [ANNOUNCE] Tiles ${version} ${quality} released
+
+The Apache Tiles team is pleased to announce the release of Tiles ${version}
+${quality}.
+
+Tiles ${version} is available in a binary and a source distribution.
+
+http://tiles.apache.org/download.html
+
+It is also available in the central Maven repository under Group ID
+"org.apache.tiles".
+
+The 2.0.x series of the Apache Tiles framework has a minimum
+requirement of the following specification versions:
+
+* Java Servlet 2.4 and JavaServer Pages (JSP) 2.0
+* Java Standard Edition (Java SE) 1.5
+
+The release notes are available online at:
+
+* ${jira.release.notes}
+
+Please feel free to test the distribution and post your comments to
+the user list, or, if appropriate, file a ticket with JIRA.
+--------------------------------------
+
+ <<You have finished!>>
diff --git a/tiles-autotag/src/site/apt/plugin.apt b/tiles-autotag/src/site/apt/plugin.apt
new file mode 100644
index 0000000..830a65d
--- /dev/null
+++ b/tiles-autotag/src/site/apt/plugin.apt
@@ -0,0 +1,105 @@
+~~ $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.
+~~
+ -----------
+ Building a tag library for Freemarker, JSP or Velocity
+ -----------
+
+Building a tag library for Freemarker, JSP or Velocity
+
+ Once you have {{{./taglib.html}created a generic tag library}},
+ Autotag will automatically generate the corresponding library
+ for Freemarker, JSP, or Velocity. You just create a maven project
+ and include in <<<pom.xml>>>:
+
+ * The appropriate implementation of tiles-request as a dependency.
+ For instance to build a JSP taglib:
+
+-----------------
+<dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-jsp</artifactId>
+ <version>1.0</version>
+</dependency>
+-----------------
+
+ * Your generic tag library as a dependency. For instance:
+
+-----------------
+<dependency>
+ <groupId>org.example</groupId>
+ <artifactId>my-taglib</artifactId>
+ <version>1.0-SNAPSHOT</version>
+</dependency>
+-----------------
+
+ * The appropriate configuration of maven-autotag-plugin. For instance:
+
+-----------------
+<plugin>
+ <groupId>org.apache.tiles.autotag.plugin</groupId>
+ <artifactId>maven-autotag-plugin</artifactId>
+ <version>1.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-jsp</goal>
+ </goals>
+ <configuration>
+ <packageName>org.example.mytaglib.jsp</packageName>
+ <jspRuntime>org.apache.tiles.request.jsp.autotag.JspAutotagRuntime</jspRuntime>
+ <taglibURI>http://example.org/mytaglib</taglibURI>
+ </configuration>
+ </execution>
+ </executions>
+</plugin>
+-----------------
+
+ No further code is required.
+
+Plugin goals
+
+ one or several of the following goals may be used:
+
+ [generate-jsp] generates the files required for a JSP tag library. It can then be included
+ in a JSP using the configured taglibURI.
+
+ [generate-freemarker] generates the files required for freemarker user-defined directives.
+ The directives can then be made available to freemarker by adding an instance of the
+ generated class <<<...FMModelRepository>>> to the freemarker template model.
+
+ [generate-velocity] generates the files required for velocity user directives. The directives
+ can be made available to Velocity by setting the <<<userdirective>>> property, either manually
+ or by using the generated file <<<META-INF/velocity.properties>>>.
+
+Plugin configuration
+
+ [packageName] the destination package for the generated classes.
+
+ [freemarkerRuntime] the runtime implementation of TilesRequest to use for freemarker, for
+ instance <<<org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime>>>.
+
+ [jspRuntime] the runtime implementation of TilesRequest to use for JSP, for
+ instance <<<org.apache.tiles.request.jsp.autotag.JSPAutotagRuntime>>>.
+
+ [velocityRuntime] the runtime implementation of TilesRequest to use for velocity, for
+ instance <<<org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime>>>.
+
+ [taglibURI] the URI to use for the JSP taglib.
+
diff --git a/tiles-autotag/src/site/apt/taglib.apt b/tiles-autotag/src/site/apt/taglib.apt
new file mode 100644
index 0000000..88cdfa2
--- /dev/null
+++ b/tiles-autotag/src/site/apt/taglib.apt
@@ -0,0 +1,108 @@
+~~ $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.
+~~
+ -----------
+ Creating a generic tag library with Autotag
+ -----------
+
+Creating a generic tag library
+
+ A generic tag library is a jar file including the classes that implement
+ the tags and a library descriptor <<<META-INF/template-suite.xml>>>, that can be used by
+ Autotag to build specific tag libraries for Freemarker, JSP, and Velocity.
+
+ The structure of the library descriptor is rather complex; fortunately
+ Autotag can generate it for you by parsing the sources.
+
+* The tag class
+
+ A tag in the library can be implemented by any java class that fits the following requirements:
+
+ * The class name ends with <<<Model>>>.
+
+ * It has a public, non-static, non-abstract method called <<<execute>>>.
+
+ * The <<<execute>>> method returns <<<void>>>.
+
+ * The parameters of the <<<execute>>> method are as follows:
+
+ ** the first parameters may be anything you want; at runtime they will contain the values
+ assigned to the attributes of the tag in the template. Those parameters may be annotated with
+ <<<org.apache.tiles.autotag.core.runtime.annotation.Parameter>>> in order to specify the name of
+ the attribute, the default value, or to make the parameter mandatory.
+
+ ** then, one parameter of type <<<org.apache.tiles.request.Request>>>.
+
+ ** and finally, one optional parameter of type <<<org.apache.tiles.autotag.core.runtime.ModelBody>>>;
+ at runtime it will contain the contents of the tag in the template.
+
+ For instance:
+
+----------------
+public class MyTagModel {
+
+ public void execute(
+ @Parameter(required=true) String mandatoryParam,
+ String optionalParam,
+ Request request,
+ ModelBody body) {
+ ...
+ }
+
+}
+----------------
+
+* Generating the library descriptor
+
+ the library descriptor can be generated using the create-descriptor goal of maven-autotag-plugin.
+
+-----------------
+<plugin>
+ <groupId>org.apache.tiles.autotag.plugin</groupId>
+ <artifactId>maven-autotag-plugin</artifactId>
+ <version>1.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>create-descriptor</goal>
+ </goals>
+ <configuration>
+ ...
+ </configuration>
+ </execution>
+ </executions>
+</plugin>
+-----------------
+
+** Configuration reference
+
+ [name] is the name of the tag library (for instance: <<<tiles>>>). It will be used for naming a
+ number of generated files.
+
+ [documentation] is a documentation that will be included in the library descriptor, and then
+ later in the appropriate artefacts when generating the taglibs.
+
+ [includes] specifies what source files should be included, defaults to <<<**/*Model.java>>>.
+ It follows the usual conventions in maven.
+
+ [excludes] specifies what source files should be included, defaults to nothing.
+ It follows the usual conventions in maven.
+
+ [outputDirectory] specifies where to put the generated files, defaults to
+ <<<target/autotag-template-suite>>>.
diff --git a/tiles-autotag/src/site/site.xml b/tiles-autotag/src/site/site.xml
new file mode 100644
index 0000000..dcfcd0c
--- /dev/null
+++ b/tiles-autotag/src/site/site.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="./index.html"/>
+ </menu>
+ <menu name="Reference">
+ <item
+ name="Creating an generic tag library"
+ href="./taglib.html"/>
+ <item
+ name="Building a tag library"
+ href="./plugin.html"/>
+ <item
+ name="Javadoc"
+ href="apidocs/index.html"/>
+ </menu>
+
+ <menu name="Developers">
+ <item
+ name="Building"
+ href="/dev/building.html"/>
+ <item
+ name="Snapshots"
+ href="/dev/snapshots.html"/>
+ <item
+ name="Release Process"
+ href="/dev/release.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/src/site/xdoc/dev/building.xml b/tiles-autotag/src/site/xdoc/dev/building.xml
new file mode 100644
index 0000000..97b102e
--- /dev/null
+++ b/tiles-autotag/src/site/xdoc/dev/building.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<document>
+
+ <properties>
+ <title>Apache Autotag</title>
+ </properties>
+
+ <body>
+ <section name="Building the Autotag project">
+ <subsection name="Prerequisites">
+ <p>For all the next instructions, we assume that you downloaded and
+ installed <a href="http://maven.apache.org/">Maven</a>.</p>
+ <p>To download packages from the source repository, you need to
+ download and install <a href="http://subversion.tigris.org/">
+ Subversion</a>.</p>
+ <p>If you want to build something including JavaDocs (assemblies,
+ sites and JavaDoc report itself) you need to install
+ <a href="http://www.graphviz.org/">GraphViz</a>, otherwise you will
+ notice missing pictures inside JavaDocs pages.</p>
+ </subsection>
+ <subsection name="Building main packages">
+ <p>To build the Autotag project from source you need to:</p>
+ <ul>
+ <li><p><a href="../../download.html">download</a> the source
+ distribution, or checkout the latest version:</p>
+ <p><source>svn co http://svn.apache.org/repos/asf/tiles/framework/trunk/tiles-autotag</source></p></li>
+ <li><p>go into the source directory and type:</p>
+ <p><source>mvn package</source></p></li>
+ </ul>
+ <p>You will find the generated JARs under:</p>
+ <ul>
+ <li>{autotag-dir}/maven-autotag-plugin/target/maven-autotag-plugin-${version}.jar</li>
+ <li>{autotag-dir}/tiles-autotag-core/target/tiles-autotag-core-${version}.jar</li>
+ <li>{autotag-dir}/tiles-autotag-core-runtime/target/tiles-autotag-core-runtime-${version}.jar</li>
+ <li>{autotag-dir}/tiles-autotag-freemarker/target/tiles-autotag-freemarker-${version}.jar</li>
+ <li>{autotag-dir}/tiles-autotag-jsp/target/tiles-autotag-jsp-${version}.jar</li>
+ <li>{autotag-dir}/tiles-autotag-velocity/target/tiles-autotag-velocity-${version}.jar</li>
+ </ul>
+ </subsection>
+ </section>
+ <section name="Building the websites">
+ <p>There are four Tiles websites: the main website and the projects
+ websites (tiles-request, tiles-autotag and framework).</p>
+ <subsection name="Building the main website">
+ <p>To build the main website:</p>
+ <ul>
+ <li><p>checkout the site from the source repository:</p>
+ <p><source>svn co http://svn.apache.org/repos/asf/tiles/site/</source></p></li>
+ <li><p>go into the site directory and type:</p>
+ <p><source>mvn site</source></p></li>
+ </ul>
+ <p>You will find the generated distribution under
+ <code>{tiles-site-dir}/target/site</code>.</p>
+ </subsection>
+ <subsection name="Building the tiles-autotag website">
+ <p>To build a project's website:</p>
+ <ul>
+ <li><p><a href="../../download.html">download</a> the source
+ distribution, or checkout the latest version:</p>
+ <p><source>svn co http://svn.apache.org/repos/asf/tiles/framework/trunk/tiles-autotag</source></p></li>
+ <li><p>go into the source directory and type:</p>
+ <p><source>mvn site site:stage</source></p></li>
+ </ul>
+ <p>You will find the generated website under:</p>
+ <ul>
+ <li>{tiles-autotag-dir}/target/staging</li>
+ </ul>
+ </subsection>
+ </section>
+ </body>
+
+</document>
diff --git a/tiles-autotag/src/site/xdoc/dev/snapshots.xml b/tiles-autotag/src/site/xdoc/dev/snapshots.xml
new file mode 100644
index 0000000..359f7cb
--- /dev/null
+++ b/tiles-autotag/src/site/xdoc/dev/snapshots.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<document>
+
+ <properties>
+ <title>Apache Tiles</title>
+ </properties>
+
+ <body>
+ <section name="Apache Tiles™">
+ <subsection name="Snapshots">
+
+ <p>Looking for snapshot builds of the latest version of Tiles?
+ Snapshots are occasionally published to Apache's Maven snapshot
+ repository, which can be accessed with the following configuration:</p>
+
+ <source>
+ <![CDATA[
+ <repository>
+ <id>apache.snapshots</id>
+ <name>Apache Maven Snapshot Repository</name>
+ <url>http://repository.apache.org/snapshots</url>
+ </repository>
+ ]]>
+ </source>
+
+ <p>After configuring the repository, declare a dependency on
+ Tiles Autotag:</p>
+
+ <source><![CDATA[
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ ]]>
+ </source>
+
+ <p>Or the maven plugin:</p>
+
+ <source><![CDATA[
+ <plugin>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>maven-autotag-plugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <configuration>
+ <packageName>...</packageName>
+ <freemarkerRuntime>...</freemarkerRuntime>
+ <jspRuntime>...</jspRuntime>
+ <velocityRuntime>...</velocityRuntime>
+ </configuration>
+ </plugin>
+ ]]>
+ </source>
+
+ </subsection>
+</section>
+</body>
+
+</document>
diff --git a/tiles-autotag/src/site/xdoc/index.xml b/tiles-autotag/src/site/xdoc/index.xml
new file mode 100644
index 0000000..8af02b0
--- /dev/null
+++ b/tiles-autotag/src/site/xdoc/index.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $Id: index.xml 1162124 2011-08-26 14:16:13Z mck $
+ *
+ * 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.
+ */
+-->
+<document>
+
+ <properties>
+ <title>Home</title>
+ </properties>
+
+ <body>
+
+ <section name="Apache Autotag project">
+
+ <p>Tiles-3 introduces a feature complete
+ <a href="http://svn.eu.apache.org/repos/asf/tiles/sandbox/trunk/tiles-autotag/" title="Autotag SVN directory">Autotag project</a>,
+ a project that automatically generates tags (or tag-like) artifact from a common template code for a range of templating languages.
+ Today JSP tags, Freemarker directive models and Velocity directives are generated from a common template models.
+ </p>
+ <p>Such template models must have a single public method, with this signature:</p>
+ <p>
+ <span class="Apple-style-span" style="font-family: monospace; white-space: pre;">public void execute(<parameters>, Request request, ModelBody modelBody);</span>
+ </p>
+ <p>The modelBody parameter is optional: if it is not specified, the template model does not have a body. </p>
+ <p>For more features (required fields, default values, a name different to the one specified in the parameter list) a new annotation @Parameter has been created.</p>
+ <p>A Maven 2 (based on 2.2.1) plugin contains four Mojos:</p>
+ <p> </p>
+ <ul>
+ <li>the first mojo (create-descriptor) reads the template models and produces an XML file containing the description of the read models;</li>
+ <li>the others (generate-jsp, generate-freemarker, generate-velocity) produce boilerplate code.</li>
+ </ul>
+ <p>The projects using the latter mojos must include some runtime dependencies.</p>
+ <p>The boilerplate code has been removed and uses the plugin instead: it's a lot of boilerplate, boring code, now generated automatically.
+ </p>
+ </section>
+ </body>
+
+</document>
diff --git a/tiles-autotag/tiles-autotag-core-runtime/pom.xml b/tiles-autotag/tiles-autotag-core-runtime/pom.xml
new file mode 100644
index 0000000..93a45c3
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/pom.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-autotag</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Autotag - Core runtime</name>
+ <description>Autotag: runtime core classes.</description>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <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>2.3.7</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>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <releaseProfiles>apache-release</releaseProfiles><!-- xxx tiles still uses "release" instead of "apache-release" -->
+ <goals>deploy site-deploy</goals>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ <defaultGoal>install</defaultGoal>
+ </build>
+
+ <properties>
+ <tiles.osgi.symbolicName>org.apache.${project.artifactId}</tiles.osgi.symbolicName>
+ <tiles.osgi.export>org.apache.tiles.*;version=${project.version}</tiles.osgi.export>
+ <tiles.osgi.import>*</tiles.osgi.import>
+ <tiles.osgi.dynamicImport />
+ <tiles.osgi.private />
+ <tiles.manifestfile>target/osgi/MANIFEST.MF</tiles.manifestfile>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java
new file mode 100644
index 0000000..8fc9da9
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/AbstractModelBody.java
@@ -0,0 +1,83 @@
+/*
+ * $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.autotag.core.runtime;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.apache.tiles.autotag.core.runtime.util.NullWriter;
+
+/**
+ * Base class for the abstraction of the body.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractModelBody implements ModelBody {
+
+ /**
+ * The default writer to use.
+ */
+ private Writer defaultWriter;
+
+ /**
+ * Constructor.
+ *
+ * @param defaultWriter The default writer to use.
+ */
+ public AbstractModelBody(Writer defaultWriter) {
+ this.defaultWriter = defaultWriter;
+ }
+
+ @Override
+ public void evaluate() throws IOException {
+ evaluate(defaultWriter);
+ }
+
+ @Override
+ public String evaluateAsString() throws IOException {
+ StringWriter writer = new StringWriter();
+ try {
+ evaluate(writer);
+ } finally {
+ writer.close();
+ }
+ String body = writer.toString();
+ if (body != null) {
+ body = body.replaceAll("^\\s*|\\s*$", "");
+ if (body.length() <= 0) {
+ body = null;
+ }
+ }
+ return body;
+ }
+
+ @Override
+ public void evaluateWithoutWriting() throws IOException {
+ NullWriter writer = new NullWriter();
+ try {
+ evaluate(writer);
+ } finally {
+ writer.close();
+ }
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java
new file mode 100644
index 0000000..d95d2ca
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/AutotagRuntime.java
@@ -0,0 +1,53 @@
+/*
+ * $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.autotag.core.runtime;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * Builder interface for creating requests.
+ * The implementations are expected to provide a default constructor,
+ * and to implement another interface that can be used to provide the
+ * parameters needed to build the actual request object.
+ */
+public interface AutotagRuntime {
+ /**
+ * Creates a new Request instance.
+ *
+ * @return The Request.
+ */
+ Request createRequest();
+
+ /**
+ * Creates a new ModelBody instance to match the request.
+ *
+ * @return The ModelBody.
+ */
+ ModelBody createModelBody();
+
+ /**
+ * Extracts a parameter from the tag.
+ * @param name The name of the parameter.
+ * @param defaultValue The default value if none is specified.
+ * @return The value of the parameter.
+ */
+ Object getParameter(String name, Object defaultValue);
+}
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java
new file mode 100644
index 0000000..81178ee
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/ModelBody.java
@@ -0,0 +1,62 @@
+/*
+ * $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.autotag.core.runtime;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Abstracts a tag/directive body.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ModelBody {
+
+ /**
+ * Evaluates a body and returns it as a string.
+ *
+ * @return The body, as a string.
+ * @throws IOException If something goes wrong.
+ */
+ String evaluateAsString() throws IOException;
+
+ /**
+ * Evaluates a body, but discards result.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ void evaluateWithoutWriting() throws IOException;
+
+ /**
+ * Evaluates the body and writes in the default writer.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ void evaluate() throws IOException;
+
+ /**
+ * Evaluates the body and writes the result in the writer.
+ *
+ * @param writer The writer to write the result into.
+ * @throws IOException If something goes wrong.
+ */
+ void evaluate(Writer writer) throws IOException;
+}
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java
new file mode 100644
index 0000000..6f9c99b
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/Parameter.java
@@ -0,0 +1,56 @@
+/*
+ * $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.autotag.core.runtime.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Specifies behaviour for a parameter of the "execute" method of a template class.
+ *
+ * @version $Rev$ $Date$
+ */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.PARAMETER)
+public @interface Parameter {
+
+ /**
+ * Indicates to use the parameter name itself for the exported name.
+ */
+ String SAME_NAME = "USE THE SAME NAME";
+
+ /**
+ * Returns the name of the exported property name.
+ */
+ String name() default SAME_NAME;
+
+ /**
+ * Indicates that this parameter is required.
+ */
+ boolean required() default false;
+
+ /**
+ * Indicates the default value, as it will be written in Java code.
+ */
+ String defaultValue() default "null";
+}
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java
new file mode 100644
index 0000000..261b48e
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/annotation/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Annotations to be used in template classes.
+ */
+package org.apache.tiles.autotag.core.runtime.annotation;
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java
new file mode 100644
index 0000000..1e8324a
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Runtime part for all Autotag generated code.
+ */
+package org.apache.tiles.autotag.core.runtime;
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java
new file mode 100644
index 0000000..6a66fb3
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/util/NullWriter.java
@@ -0,0 +1,50 @@
+/*
+ * $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.autotag.core.runtime.util;
+
+import java.io.Writer;
+
+/**
+ * A writer that does not write anything.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NullWriter extends Writer {
+
+ /** {@inheritDoc} */
+ @Override
+ public void close() {
+ // Does nothing
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void flush() {
+ // Does nothing
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(char[] cbuf, int off, int len) {
+ // Does nothing
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java
new file mode 100644
index 0000000..7f2e356
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/main/java/org/apache/tiles/autotag/core/runtime/util/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Utilities for Autotag core runtime.
+ */
+package org.apache.tiles.autotag.core.runtime.util;
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/site/site.xml b/tiles-autotag/tiles-autotag-core-runtime/src/site/site.xml
new file mode 100644
index 0000000..0a7d00d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/test/java/org/apache/tiles/autotag/core/runtime/AbstractModelBodyTest.java b/tiles-autotag/tiles-autotag-core-runtime/src/test/java/org/apache/tiles/autotag/core/runtime/AbstractModelBodyTest.java
new file mode 100644
index 0000000..c37ef45
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/test/java/org/apache/tiles/autotag/core/runtime/AbstractModelBodyTest.java
@@ -0,0 +1,154 @@
+/*
+ * $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.autotag.core.runtime;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.apache.tiles.autotag.core.runtime.util.NullWriter;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractModelBody}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractModelBodyTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.AbstractModelBody#evaluate()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testEvaluate() throws IOException {
+ Writer writer = createMock(Writer.class);
+ AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock();
+
+ modelBody.evaluate(writer);
+
+ replay(writer, modelBody);
+ modelBody.evaluate();
+ verify(writer, modelBody);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.AbstractModelBody#evaluateAsString()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateAsString() throws IOException {
+ AbstractModelBody modelBody = new MockModelBody(null, "return me");
+ assertEquals("return me", modelBody.evaluateAsString());
+
+ modelBody = new MockModelBody(null, "\n \n");
+ assertNull(modelBody.evaluateAsString());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.AbstractModelBody#evaluateAsString()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testEvaluateAsStringException() throws IOException {
+ Writer writer = createMock(Writer.class);
+ AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock();
+
+ modelBody.evaluate(isA(StringWriter.class));
+ expectLastCall().andThrow(new IOException());
+
+ replay(writer, modelBody);
+ try {
+ modelBody.evaluateAsString();
+ } finally {
+ verify(writer, modelBody);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.AbstractModelBody#evaluateWithoutWriting()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateWithoutWriting() throws IOException {
+ Writer writer = createMock(Writer.class);
+ AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock();
+
+ modelBody.evaluate(isA(NullWriter.class));
+
+ replay(writer, modelBody);
+ modelBody.evaluateWithoutWriting();
+ verify(writer, modelBody);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.AbstractModelBody#evaluateWithoutWriting()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testEvaluateWithoutWritingException() throws IOException {
+ Writer writer = createMock(Writer.class);
+ AbstractModelBody modelBody = createMockBuilder(AbstractModelBody.class).withConstructor(writer).createMock();
+
+ modelBody.evaluate(isA(NullWriter.class));
+ expectLastCall().andThrow(new IOException());
+
+ replay(writer, modelBody);
+ try {
+ modelBody.evaluateWithoutWriting();
+ } finally {
+ verify(writer, modelBody);
+ }
+ }
+
+ /**
+ * A mock model body.
+ *
+ * @version $Rev$ $Date$
+ */
+ public static class MockModelBody extends AbstractModelBody {
+
+ /**
+ * The result to return.
+ */
+ private String toReturn;
+
+ /**
+ * Constructor.
+ *
+ * @param defaultWriter The default writer.
+ * @param toReturn The result to return.
+ */
+ public MockModelBody(Writer defaultWriter, String toReturn) {
+ super(defaultWriter);
+ this.toReturn = toReturn;
+ }
+
+ @Override
+ public void evaluate(Writer writer) throws IOException {
+ writer.write(toReturn);
+ }
+
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core-runtime/src/test/java/org/apache/tiles/autotag/core/runtime/util/NullWriterTest.java b/tiles-autotag/tiles-autotag-core-runtime/src/test/java/org/apache/tiles/autotag/core/runtime/util/NullWriterTest.java
new file mode 100644
index 0000000..f8a2ba2
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core-runtime/src/test/java/org/apache/tiles/autotag/core/runtime/util/NullWriterTest.java
@@ -0,0 +1,74 @@
+/*
+ * $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.autotag.core.runtime.util;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link NullWriter}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NullWriterTest {
+
+ /**
+ * A dummy size.
+ */
+ private static final int DUMMY_SIZE = 15;
+ /**
+ * The object to test.
+ */
+ private NullWriter writer;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ writer = new NullWriter();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.util.NullWriter#write(char[], int, int)}.
+ */
+ @Test
+ public void testWriteCharArrayIntInt() {
+ writer.write("Hello there".toCharArray(), 0, DUMMY_SIZE);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.util.NullWriter#flush()}.
+ */
+ @Test
+ public void testFlush() {
+ writer.flush();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.runtime.util.NullWriter#close()}.
+ */
+ @Test
+ public void testClose() {
+ writer.close();
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/pom.xml b/tiles-autotag/tiles-autotag-core/pom.xml
new file mode 100644
index 0000000..b9fe1ed
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-autotag</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Autotag - Core</name>
+ <description>Core classes for Autotag.</description>
+ <build>
+ <resources>
+ </resources>
+ <testResources>
+ <testResource>
+ <directory>src/test/java</directory>
+ <includes>
+ <include>org/apache/tiles/autotag/core/internal/*.java</include>
+ </includes>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources</directory>
+ </testResource>
+ </testResources>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.qdox</groupId>
+ <artifactId>qdox</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.java
new file mode 100644
index 0000000..c4d05f9
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/AutotagRuntimeException.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.autotag.core;
+
+/**
+ * Generic exception for Autotag.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AutotagRuntimeException extends RuntimeException {
+
+ /**
+ * Constructor.
+ */
+ public AutotagRuntimeException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ */
+ public AutotagRuntimeException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause.
+ */
+ public AutotagRuntimeException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ * @param cause The cause.
+ */
+ public AutotagRuntimeException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/ClassParseException.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/ClassParseException.java
new file mode 100644
index 0000000..c2ef82b
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/ClassParseException.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.autotag.core;
+
+/**
+ * Thrown if there is a problem when parsing a class source.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ClassParseException extends AutotagRuntimeException {
+
+ /**
+ * Constructor.
+ */
+ public ClassParseException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ */
+ public ClassParseException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause.
+ */
+ public ClassParseException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ * @param cause The cause.
+ */
+ public ClassParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/QDoxTemplateSuiteFactory.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/QDoxTemplateSuiteFactory.java
new file mode 100644
index 0000000..cfc903b
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/QDoxTemplateSuiteFactory.java
@@ -0,0 +1,259 @@
+/*
+ * $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.autotag.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.annotation.Parameter;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.autotag.model.TemplateSuiteFactory;
+import org.apache.tiles.request.Request;
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.Annotation;
+import com.thoughtworks.qdox.model.DocletTag;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaMethod;
+import com.thoughtworks.qdox.model.JavaParameter;
+import com.thoughtworks.qdox.model.Type;
+
+/**
+ * Creates a template suite using QDox.
+ *
+ * @version $Rev$ $Date$
+ */
+public class QDoxTemplateSuiteFactory implements TemplateSuiteFactory {
+
+ /**
+ * The suffix of parsed classes.
+ */
+ private static final String TEMPLATE_SUFFIX = "Model";
+
+ /**
+ * The Javadoc builder.
+ */
+ private JavaDocBuilder builder;
+
+ /**
+ * The name of the suite.
+ */
+ private String suiteName;
+
+ /**
+ * The documentation of the suite.
+ */
+ private String suiteDocumentation;
+
+ /**
+ * Constructor.
+ *
+ * @param sourceFiles All the source files to parse.
+ */
+ public QDoxTemplateSuiteFactory(File... sourceFiles) {
+ builder = new JavaDocBuilder();
+ try {
+ for (File file : sourceFiles) {
+ builder.addSource(file);
+ }
+ } catch (IOException e) {
+ throw new ClassParseException(
+ "I/O Exception when adding source files", e);
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param urls All the URLs of source files to parse.
+ */
+ public QDoxTemplateSuiteFactory(URL... urls) {
+ builder = new JavaDocBuilder();
+ try {
+ for (URL url : urls) {
+ builder.addSource(url);
+ }
+ } catch (IOException e) {
+ throw new ClassParseException(
+ "I/O Exception when adding source files", e);
+ }
+ }
+
+ /**
+ * Sets the suite name to assign to the created suite.
+ *
+ * @param suiteName The suite name.
+ */
+ public void setSuiteName(String suiteName) {
+ this.suiteName = suiteName;
+ }
+
+ /**
+ * Sets the suite documentation to assign to the suite.
+ *
+ * @param suiteDocumentation The suite documentation.
+ */
+ public void setSuiteDocumentation(String suiteDocumentation) {
+ this.suiteDocumentation = suiteDocumentation;
+ }
+
+ @Override
+ public TemplateSuite createTemplateSuite() {
+ List<TemplateClass> classes = new ArrayList<TemplateClass>();
+ for (JavaClass clazz : builder.getClasses()) {
+ String tagClassPrefix = getTagClassPrefix(clazz);
+ if (tagClassPrefix != null) {
+ String tagName = tagClassPrefix.substring(0, 1).toLowerCase()
+ + tagClassPrefix.substring(1);
+ TemplateMethod executeMethod = null;
+ for (JavaMethod method : clazz.getMethods()) {
+ if (isFeasible(method)) {
+ executeMethod = createMethod(method);
+ }
+ }
+ if (executeMethod != null) {
+ TemplateClass templateClass = new TemplateClass(clazz
+ .getFullyQualifiedName(), tagName, tagClassPrefix,
+ executeMethod);
+ templateClass.setDocumentation(clazz.getComment());
+ classes.add(templateClass);
+ }
+ }
+ }
+ return new TemplateSuite(suiteName, suiteDocumentation, classes);
+ }
+
+ /**
+ * Computes the tag class prefix.
+ *
+ * @param clazz The parsed class.
+ * @return The tag class prefix.
+ */
+ private String getTagClassPrefix(JavaClass clazz) {
+ String tagName;
+ String simpleClassName = clazz.getName();
+ if (simpleClassName.endsWith(TEMPLATE_SUFFIX)
+ && simpleClassName.length() > TEMPLATE_SUFFIX.length()) {
+ tagName = simpleClassName.substring(0, 1).toUpperCase()
+ + simpleClassName.substring(1, simpleClassName.length()
+ - TEMPLATE_SUFFIX.length());
+ } else {
+ tagName = null;
+ }
+ return tagName;
+ }
+
+ /**
+ * Creates a template method descriptor from a parsed method.
+ *
+ * @param method The parsed method.
+ * @return The template method descriptor.
+ */
+ private TemplateMethod createMethod(JavaMethod method) {
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ for (JavaParameter parameter : method.getParameters()) {
+ String exportedName = parameter.getName();
+ boolean required = false;
+ String defaultValue = null;
+ Annotation[] annotations = parameter.getAnnotations();
+ if (annotations != null && annotations.length > 0) {
+ boolean found = false;
+ for (int i = 0; i < annotations.length && !found; i++) {
+ if (Parameter.class.getName().equals(annotations[i].getType().getFullyQualifiedName())) {
+ found = true;
+ String candidateName = (String) annotations[i].getNamedParameter("name");
+ if (candidateName != null && candidateName.length() > 2) {
+ exportedName = candidateName.substring(1, candidateName.length() - 1);
+ }
+ required = "true".equals(annotations[i].getNamedParameter("required"));
+ candidateName = (String) annotations[i].getNamedParameter("defaultValue");
+ if (candidateName != null && candidateName.length() > 2) {
+ defaultValue = candidateName.substring(1, candidateName.length() - 1);
+ }
+ }
+ }
+ }
+ TemplateParameter templateParameter = new TemplateParameter(
+ parameter.getName(), exportedName, parameter.getType()
+ .getFullyQualifiedName(), defaultValue, required);
+ params.add(templateParameter);
+ }
+ TemplateMethod templateMethod = new TemplateMethod(method.getName(),
+ params);
+ templateMethod.setDocumentation(method.getComment());
+ DocletTag[] tags = method.getTagsByName("param");
+ for (DocletTag tag : tags) {
+ String[] tagParams = tag.getParameters();
+ if (tagParams.length > 0) {
+ TemplateParameter templateParameter = templateMethod
+ .getParameterByName(tagParams[0]);
+ if (templateParameter != null) {
+ String tagValue = tag.getValue();
+ int pos = tagValue.indexOf(" ");
+ templateParameter.setDocumentation(tagValue.substring(pos)
+ .trim());
+ }
+ }
+ }
+ return templateMethod;
+ }
+
+ /**
+ * Verifies if the method can be used as an "execute" method.
+ *
+ * @param method The parsed method.
+ * @return <code>true</code> if it is an execute method.
+ */
+ private boolean isFeasible(JavaMethod method) {
+ Type returns = method.getReturns();
+ if ("execute".equals(method.getName()) && returns != null
+ && "void".equals(returns.getFullyQualifiedName())
+ && method.isPublic() && !method.isStatic()
+ && !method.isAbstract() && !method.isConstructor()) {
+ JavaParameter[] params = method.getParameters();
+ if (params.length > 0) {
+ JavaParameter param = params[params.length - 1];
+ if (Request.class.getName().equals(
+ param.getType().getFullyQualifiedName())) {
+ return true;
+ }
+ }
+ if (params.length >= 2) {
+ JavaParameter param1 = params[params.length - 2];
+ JavaParameter param2 = params[params.length - 1];
+ if (Request.class.getName().equals(
+ param1.getType().getFullyQualifiedName())
+ && ModelBody.class.getName().equals(
+ param2.getType().getFullyQualifiedName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/package-info.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/package-info.java
new file mode 100644
index 0000000..d7ed8d7
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/core/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * The Autotag core parsing code.
+ */
+package org.apache.tiles.autotag.core;
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java
new file mode 100644
index 0000000..dd40607
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGenerator.java
@@ -0,0 +1,142 @@
+/*
+ * $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.autotag.generate;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.tiles.autotag.core.AutotagRuntimeException;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.autotag.tool.StringTool;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+
+/**
+ * A base template class generator.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractTemplateClassGenerator implements
+ TemplateClassGenerator {
+
+ /**
+ * The Velocity engine to use.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public AbstractTemplateClassGenerator(VelocityEngine velocityEngine) {
+ this.velocityEngine = velocityEngine;
+ }
+
+ @Override
+ public void generate(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ File dir = new File(directory, getDirectoryName(directory, packageName,
+ suite, clazz, parameters, runtimeClass));
+ dir.mkdirs();
+ File file = new File(dir, getFilename(dir, packageName, suite, clazz, parameters, runtimeClass));
+ VelocityContext context = new VelocityContext();
+ context.put("packageName", packageName);
+ context.put("suite", suite);
+ context.put("clazz", clazz);
+ context.put("stringTool", new StringTool());
+ context.put("parameters", parameters);
+ context.put("runtimeClass", runtimeClass);
+ try {
+ file.createNewFile();
+ Template template = velocityEngine.getTemplate(getTemplatePath(dir,
+ packageName, suite, clazz, parameters, runtimeClass));
+ Writer writer = new FileWriter(file);
+ try {
+ template.merge(context, writer);
+ } finally {
+ writer.close();
+ }
+ } catch (ResourceNotFoundException e) {
+ throw new AutotagRuntimeException("Cannot find template resource",
+ e);
+ } catch (ParseErrorException e) {
+ throw new AutotagRuntimeException(
+ "The template resource is not parseable", e);
+ } catch (IOException e) {
+ throw new AutotagRuntimeException(
+ "I/O Exception when generating file", e);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new AutotagRuntimeException(
+ "Another generic exception while parsing the template resource",
+ e);
+ }
+ }
+
+ /**
+ * Calculates and returns the template path.
+ *
+ * @param directory The directory where the file will be written.
+ * @param packageName The name of the package.
+ * @param suite The template suite.
+ * @param clazz The template class.
+ * @param parameters The map of parameters.
+ * @return The template path.
+ */
+ protected abstract String getTemplatePath(File directory,
+ String packageName, TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters, String runtimeClass);
+
+ /**
+ * Calculates and returns the filename of the generated file.
+ *
+ * @param directory The directory where the file will be written.
+ * @param packageName The name of the package.
+ * @param suite The template suite.
+ * @param clazz The template class.
+ * @param parameters The map of parameters.
+ * @return The template path.
+ */
+ protected abstract String getFilename(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters, String runtimeClass);
+
+ /**
+ * Calculates and returns the directory where the file will be written..
+ *
+ * @param directory The directory where the file will be written.
+ * @param packageName The name of the package.
+ * @param suite The template suite.
+ * @param clazz The template class.
+ * @param parameters The map of parameters.
+ * @return The template path.
+ */
+ protected abstract String getDirectoryName(File directory,
+ String packageName, TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters, String runtimeClass);
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java
new file mode 100644
index 0000000..51f94b5
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGenerator.java
@@ -0,0 +1,132 @@
+/*
+ * $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.autotag.generate;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.tiles.autotag.core.AutotagRuntimeException;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.autotag.tool.StringTool;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+
+/**
+ * A base template suite generator.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractTemplateSuiteGenerator implements TemplateSuiteGenerator {
+
+ /**
+ * The velocity engine.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public AbstractTemplateSuiteGenerator(VelocityEngine velocityEngine) {
+ this.velocityEngine = velocityEngine;
+ }
+
+ @Override
+ public void generate(File directory, String packageName, TemplateSuite suite, Map<String, String> parameters) {
+ File dir = new File(directory, getDirectoryName(directory, packageName, suite, parameters));
+ dir.mkdirs();
+ File file = new File(dir, getFilename(dir, packageName, suite, parameters));
+ VelocityContext context = new VelocityContext();
+ context.put("packageName", packageName);
+ context.put("suite", suite);
+ context.put("stringTool", new StringTool());
+ context.put("parameters", parameters);
+ try {
+ file.createNewFile();
+ Template template = velocityEngine.getTemplate(getTemplatePath(dir,
+ packageName, suite, parameters));
+ Writer writer = new FileWriter(file);
+ try {
+ template.merge(context, writer);
+ } finally {
+ writer.close();
+ }
+ } catch (ResourceNotFoundException e) {
+ throw new AutotagRuntimeException("Cannot find template resource", e);
+ } catch (ParseErrorException e) {
+ throw new AutotagRuntimeException("The template resource is not parseable", e);
+ } catch (IOException e) {
+ throw new AutotagRuntimeException(
+ "I/O Exception when generating file", e);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new AutotagRuntimeException(
+ "Another generic exception while parsing the template resource",
+ e);
+ }
+ }
+
+ /**
+ * Calculates and returns the template path.
+ *
+ * @param directory The directory where the file will be written.
+ * @param packageName The name of the package.
+ * @param suite The template suite.
+ * @param parameters The map of parameters.
+ * @return The template path.
+ */
+ protected abstract String getTemplatePath(File directory,
+ String packageName, TemplateSuite suite,
+ Map<String, String> parameters);
+
+ /**
+ * Calculates and returns the filename of the generated file.
+ *
+ * @param directory The directory where the file will be written.
+ * @param packageName The name of the package.
+ * @param suite The template suite.
+ * @param parameters The map of parameters.
+ * @return The template path.
+ */
+ protected abstract String getFilename(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters);
+
+ /**
+ * Calculates and returns the directory where the file will be written..
+ *
+ * @param directory The directory where the file will be written.
+ * @param packageName The name of the package.
+ * @param suite The template suite.
+ * @param parameters The map of parameters.
+ * @return The template path.
+ */
+ protected abstract String getDirectoryName(File directory,
+ String packageName, TemplateSuite suite,
+ Map<String, String> parameters);
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java
new file mode 100644
index 0000000..7fe7ffd
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java
@@ -0,0 +1,195 @@
+/*
+ * $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.autotag.generate;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+
+/**
+ * The basic template generator. Use {@link TemplateGeneratorBuilder} to
+ * create instances of this class.
+ *
+ * @version $Rev$ $Date$
+ */
+class BasicTemplateGenerator implements TemplateGenerator {
+
+ /**
+ * The template suite generators.
+ */
+ private List<TSGeneratorDirectoryPair> templateSuiteGenerators;
+
+ /**
+ * The template class generators.
+ */
+ private List<TCGeneratorDirectoryPair> templateClassGenerators;
+
+ /**
+ * Indicates that this generator generates resources.
+ */
+ private boolean generatingResources = false;
+
+ /**
+ * Indicates that this generator generates classes.
+ */
+ private boolean generatingClasses = false;
+
+ /**
+ * Constructor.
+ *
+ * @param templateSuiteGenerators The template suite generators.
+ * @param templateClassGenerators The template class generators.
+ * @param generatingClasses Indicates that this generator generates classes.
+ * @param generatingResources Indicates that this generator generates resources.
+ */
+ BasicTemplateGenerator(
+ List<TSGeneratorDirectoryPair> templateSuiteGenerators,
+ List<TCGeneratorDirectoryPair> templateClassGenerators,
+ boolean generatingClasses, boolean generatingResources) {
+ this.templateSuiteGenerators = templateSuiteGenerators;
+ this.templateClassGenerators = templateClassGenerators;
+ this.generatingClasses = generatingClasses;
+ this.generatingResources = generatingResources;
+ }
+
+
+
+ @Override
+ public void generate(String packageName, TemplateSuite suite, Map<String, String> parameters,
+ String runtimeClass) {
+ for (TSGeneratorDirectoryPair pair : templateSuiteGenerators) {
+ pair.getGenerator().generate(pair.getDirectory(), packageName, suite, parameters);
+ }
+ for (TemplateClass templateClass : suite.getTemplateClasses()) {
+ for (TCGeneratorDirectoryPair pair : templateClassGenerators) {
+ pair.getGenerator().generate(pair.getDirectory(), packageName,
+ suite, templateClass, parameters, runtimeClass);
+ }
+ }
+ }
+
+ /**
+ * A pair of a template suite generator and a directory.
+ *
+ * @version $Rev$ $Date$
+ */
+ static class TSGeneratorDirectoryPair {
+ /**
+ * The directory where files are generated.
+ */
+ private File directory;
+
+ /**
+ * The generator.
+ */
+ private TemplateSuiteGenerator generator;
+
+ /**
+ * Constructor.
+ *
+ * @param directory The directory where files are generated.
+ * @param generator The generator.
+ */
+ public TSGeneratorDirectoryPair(File directory,
+ TemplateSuiteGenerator generator) {
+ this.directory = directory;
+ this.generator = generator;
+ }
+
+ /**
+ * Returns the directory where files are generated.
+ *
+ * @return The directory where files are generated.
+ */
+ public File getDirectory() {
+ return directory;
+ }
+
+ /**
+ * Returns the generator.
+ *
+ * @return The generator.
+ */
+ public TemplateSuiteGenerator getGenerator() {
+ return generator;
+ }
+ }
+
+ /**
+ * A pair of a template class generator and a directory.
+ *
+ * @version $Rev$ $Date$
+ */
+ static class TCGeneratorDirectoryPair {
+ /**
+ * The directory where files are generated.
+ */
+ private File directory;
+
+ /**
+ * The generator.
+ */
+ private TemplateClassGenerator generator;
+
+ /**
+ * Constructor.
+ *
+ * @param directory The directory where files are generated.
+ * @param generator The generator.
+ */
+ public TCGeneratorDirectoryPair(File directory,
+ TemplateClassGenerator generator) {
+ this.directory = directory;
+ this.generator = generator;
+ }
+
+ /**
+ * Returns the directory where files are generated.
+ *
+ * @return The directory where files are generated.
+ */
+ public File getDirectory() {
+ return directory;
+ }
+
+ /**
+ * Returns the generator.
+ *
+ * @return The generator.
+ */
+ public TemplateClassGenerator getGenerator() {
+ return generator;
+ }
+ }
+
+ @Override
+ public boolean isGeneratingResources() {
+ return generatingResources;
+ }
+
+ @Override
+ public boolean isGeneratingClasses() {
+ return generatingClasses;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java
new file mode 100644
index 0000000..c6fe9e0
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateClassGenerator.java
@@ -0,0 +1,49 @@
+/*
+ * $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.autotag.generate;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+
+/**
+ * Generates code from a parsed class.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface TemplateClassGenerator {
+
+ /**
+ * Generates the code.
+ *
+ * @param directory The base directory where the code will be put.
+ * @param packageName The package name.
+ * @param suite The template suite.
+ * @param clazz The template class.
+ * @param parameters Configuration parameters.
+ * @param runtimeClass The RequestBuilder implementation.
+ */
+ void generate(File directory, String packageName, TemplateSuite suite,
+ TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass);
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java
new file mode 100644
index 0000000..db67873
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGenerator.java
@@ -0,0 +1,59 @@
+/*
+ * $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.autotag.generate;
+
+
+import java.util.Map;
+
+import org.apache.tiles.autotag.model.TemplateSuite;
+
+/**
+ * Generates all the code for a template suite.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface TemplateGenerator {
+
+ /**
+ * Generates the code.
+ *
+ * @param packageName The package name.
+ * @param suite The template suite.
+ * @param parameters Configuration parameters.
+ * @param runtimeClass The RequestBuilder implementation.
+ */
+ void generate(String packageName, TemplateSuite suite, Map<String, String> parameters,
+ String runtimeClass);
+
+ /**
+ * Indicates that this generator generates resources.
+ *
+ * @return <code>true</code> if the generator generates resources.
+ */
+ boolean isGeneratingResources();
+
+ /**
+ * Indicates that this generator generates classes.
+ *
+ * @return <code>true</code> if the generator generates classes.
+ */
+ boolean isGeneratingClasses();
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java
new file mode 100644
index 0000000..3f29934
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilder.java
@@ -0,0 +1,184 @@
+/*
+ * $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.autotag.generate;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TCGeneratorDirectoryPair;
+import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TSGeneratorDirectoryPair;
+
+/**
+ * Builds a {@link TemplateGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateGeneratorBuilder {
+
+ /**
+ * The template suite generators.
+ */
+ private List<TSGeneratorDirectoryPair> templateSuiteGenerators;
+
+ /**
+ * The template class generators.
+ */
+ private List<TCGeneratorDirectoryPair> templateClassGenerators;
+
+ /**
+ * Indicates that this generator generates resources.
+ */
+ private boolean generatingResources = false;
+
+ /**
+ * Indicates that this generator generates classes.
+ */
+ private boolean generatingClasses = false;
+
+ /**
+ * The classes output directory.
+ */
+ private File classesOutputDirectory;
+
+ /**
+ * The resources output directory.
+ */
+ private File resourcesOutputDirectory;
+
+ /**
+ * Constructor.
+ */
+ private TemplateGeneratorBuilder() {
+ templateSuiteGenerators = new ArrayList<BasicTemplateGenerator.TSGeneratorDirectoryPair>();
+ templateClassGenerators = new ArrayList<BasicTemplateGenerator.TCGeneratorDirectoryPair>();
+ }
+
+ /**
+ * Creates a new instance of the builder.
+ *
+ * @return A new instance of the builder.
+ */
+ public static TemplateGeneratorBuilder createNewInstance() {
+ return new TemplateGeneratorBuilder();
+ }
+
+ /**
+ * Sets the classes output directory.
+ *
+ * @param classesOutputDirectory The classes output directory.
+ * @return This instance.
+ */
+ public TemplateGeneratorBuilder setClassesOutputDirectory(File classesOutputDirectory) {
+ this.classesOutputDirectory = classesOutputDirectory;
+ return this;
+ }
+
+ /**
+ * Sets the resources output directory.
+ *
+ * @param resourcesOutputDirectory The resources output directory.
+ * @return This instance.
+ */
+ public TemplateGeneratorBuilder setResourcesOutputDirectory(File resourcesOutputDirectory) {
+ this.resourcesOutputDirectory = resourcesOutputDirectory;
+ return this;
+ }
+
+ /**
+ * Adds a new template suite generator to generate classes.
+ *
+ * @param generator The generator to add.
+ * @return This instance.
+ */
+ public TemplateGeneratorBuilder addClassesTemplateSuiteGenerator(TemplateSuiteGenerator generator) {
+ if (classesOutputDirectory == null) {
+ throw new NullPointerException(
+ "Classes output directory not specified, call 'setClassesOutputDirectory' first");
+ }
+ templateSuiteGenerators.add(new TSGeneratorDirectoryPair(
+ classesOutputDirectory, generator));
+ generatingClasses = true;
+ return this;
+ }
+
+ /**
+ * Adds a new template class generator to generate classes.
+ *
+ * @param generator The generator to add.
+ * @return This instance.
+ */
+ public TemplateGeneratorBuilder addClassesTemplateClassGenerator(TemplateClassGenerator generator) {
+ if (classesOutputDirectory == null) {
+ throw new NullPointerException(
+ "Classes output directory not specified, call 'setClassesOutputDirectory' first");
+ }
+ templateClassGenerators.add(new TCGeneratorDirectoryPair(
+ classesOutputDirectory, generator));
+ generatingClasses = true;
+ return this;
+ }
+
+ /**
+ * Adds a new template suite generator to generate resources.
+ *
+ * @param generator The generator to add.
+ * @return This instance.
+ */
+ public TemplateGeneratorBuilder addResourcesTemplateSuiteGenerator(TemplateSuiteGenerator generator) {
+ if (resourcesOutputDirectory == null) {
+ throw new NullPointerException(
+ "Resources output directory not specified, call 'setClassesOutputDirectory' first");
+ }
+ templateSuiteGenerators.add(new TSGeneratorDirectoryPair(
+ resourcesOutputDirectory, generator));
+ generatingResources = true;
+ return this;
+ }
+
+ /**
+ * Adds a new template class generator to generate resources.
+ *
+ * @param generator The generator to add.
+ * @return This instance.
+ */
+ public TemplateGeneratorBuilder addResourcesTemplateClassGenerator(TemplateClassGenerator generator) {
+ if (resourcesOutputDirectory == null) {
+ throw new NullPointerException(
+ "Resources output directory not specified, call 'setClassesOutputDirectory' first");
+ }
+ templateClassGenerators.add(new TCGeneratorDirectoryPair(
+ resourcesOutputDirectory, generator));
+ generatingResources = true;
+ return this;
+ }
+
+ /**
+ * Builds and returns a new template generator.
+ *
+ * @return The new template generator.
+ */
+ public TemplateGenerator build() {
+ return new BasicTemplateGenerator(templateSuiteGenerators,
+ templateClassGenerators, generatingClasses, generatingResources);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java
new file mode 100644
index 0000000..76b40d7
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateGeneratorFactory.java
@@ -0,0 +1,36 @@
+/*
+ * $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.autotag.generate;
+
+/**
+ * Creates a new template generator.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface TemplateGeneratorFactory {
+
+ /**
+ * Creates a template generator.
+ *
+ * @return The newly created template generator.
+ */
+ TemplateGenerator createTemplateGenerator();
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java
new file mode 100644
index 0000000..1d7df00
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/TemplateSuiteGenerator.java
@@ -0,0 +1,44 @@
+/*
+ * $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.autotag.generate;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.model.TemplateSuite;
+
+/**
+ * Generates code from a template suite.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface TemplateSuiteGenerator {
+
+ /**
+ * Generates the code.
+ *
+ * @param directory The base directory where the code will be put.
+ * @param packageName The package name.
+ * @param suite The template suite.
+ * @param parameters Configuration parameters.
+ */
+ void generate(File directory, String packageName, TemplateSuite suite, Map<String, String> parameters);
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/package-info.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/package-info.java
new file mode 100644
index 0000000..6256497
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * The Autotag generation classes.
+ */
+package org.apache.tiles.autotag.generate;
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java
new file mode 100644
index 0000000..f869c95
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateClass.java
@@ -0,0 +1,195 @@
+/*
+ * $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.autotag.model;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * It represents a parsed template class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateClass {
+
+ /**
+ * The class name.
+ */
+ private String name;
+
+ /**
+ * The name of the tag.
+ */
+ private String tagName;
+
+ /**
+ * The prefix of the tag class.
+ */
+ private String tagClassPrefix;
+
+ /**
+ * Documentation about this tag.
+ */
+ private String documentation;
+
+ /**
+ * The method that executes the template class.
+ */
+ private TemplateMethod executeMethod;
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the template class.
+ */
+ public TemplateClass(String name) {
+ this(name, null, null, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the template class.
+ * @param tagName The name of the tag.
+ * @param tagClassPrefix The tag class prefix.
+ * @param executeMethod The method that executes the template class.
+ */
+ public TemplateClass(String name, String tagName, String tagClassPrefix,
+ TemplateMethod executeMethod) {
+ this.name = name;
+ this.tagName = tagName;
+ this.tagClassPrefix = tagClassPrefix;
+ this.executeMethod = executeMethod;
+ }
+
+ /**
+ * The name of the parsed class.
+ *
+ * @return The name of the class.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the name of the class, without the package part.
+ *
+ * @return The simple class name.
+ */
+ public String getSimpleName() {
+ int pos = name.lastIndexOf('.');
+ if (pos >= 0) {
+ return name.substring(pos + 1);
+ }
+ return name;
+ }
+
+ /**
+ * Returns the tag name.
+ *
+ * @return The tag name.
+ */
+ public String getTagName() {
+ return tagName;
+ }
+
+ /**
+ * Returns the tag class prefix.
+ *
+ * @return The tag class prefix.
+ */
+ public String getTagClassPrefix() {
+ return tagClassPrefix;
+ }
+
+ /**
+ * Returns the documentation for this class.
+ *
+ * @return The documentation.
+ */
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ /**
+ * Sets the documentation for this class.
+ *
+ * @param documentation The documentation.
+ */
+ public void setDocumentation(String documentation) {
+ this.documentation = documentation;
+ }
+
+ /**
+ * Returns the method that execute this class.
+ *
+ * @return The execute method.
+ */
+ public TemplateMethod getExecuteMethod() {
+ return executeMethod;
+ }
+
+ /**
+ * Returns the collection of regular parameters (no request, no body)
+ * of the execute method.
+ *
+ * @return The regular parameters.
+ */
+ public Collection<TemplateParameter> getParameters() {
+ Map<String, TemplateParameter> params = new LinkedHashMap<String, TemplateParameter>();
+ fillRegularParameters(params, executeMethod);
+ return params.values();
+ }
+
+ /**
+ * Indicates that this class needs a tag body.
+ *
+ * @return <code>true</code> if tag body is needed.
+ */
+ public boolean hasBody() {
+ return executeMethod.hasBody();
+ }
+
+ @Override
+ public String toString() {
+ return "TemplateClass [name=" + name + ", tagName=" + tagName
+ + ", tagClassPrefix=" + tagClassPrefix + ", documentation="
+ + documentation + ", executeMethod=" + executeMethod + "]";
+ }
+
+ /**
+ * Creates regular parameters map.
+ *
+ * @param params The map to fill.
+ * @param method The method to analyze.
+ */
+ private void fillRegularParameters(Map<String, TemplateParameter> params,
+ TemplateMethod method) {
+ if (method != null) {
+ for (TemplateParameter param : method.getParameters()) {
+ if (!param.isRequest() && !param.isBody()) {
+ params.put(param.getName(), param);
+ }
+ }
+ }
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java
new file mode 100644
index 0000000..d5703c5
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateMethod.java
@@ -0,0 +1,131 @@
+/*
+ * $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.autotag.model;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * It represents a parsed method in a parsed template class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateMethod {
+
+ /**
+ * The name of the method.
+ */
+ private String name;
+
+ /**
+ * Documentation about the method.
+ */
+ private String documentation;
+
+ /**
+ * The map of parameters.
+ */
+ private Map<String, TemplateParameter> parameters;
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the method.
+ * @param parameters The map of parameters.
+ */
+ public TemplateMethod(String name,
+ Iterable<? extends TemplateParameter> parameters) {
+ this.name = name;
+ this.parameters = new LinkedHashMap<String, TemplateParameter>();
+ for (TemplateParameter parameter : parameters) {
+ this.parameters.put(parameter.getName(), parameter);
+ }
+ }
+
+ /**
+ * Returns the name of the method.
+ *
+ * @return The name of the method.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the documentation for this method.
+ *
+ * @return The documentation.
+ */
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ /**
+ * Sets the documentation for this method.
+ *
+ * @param documentation The documentation.
+ */
+ public void setDocumentation(String documentation) {
+ this.documentation = documentation;
+ }
+
+ /**
+ * Returns the parameters of this method.
+ *
+ * @return The parameters.
+ */
+ public Collection<TemplateParameter> getParameters() {
+ return parameters.values();
+ }
+
+ /**
+ * Returns a parameter given its name.
+ *
+ * @param name The name of the parameter.
+ * @return The parameter.
+ */
+ public TemplateParameter getParameterByName(String name) {
+ return parameters.get(name);
+ }
+
+ /**
+ * Indicates that this method needs a tag body.
+ *
+ * @return <code>true</code> if tag body is needed.
+ */
+ public boolean hasBody() {
+ if (parameters.size() >= 2) {
+ for (TemplateParameter param : parameters.values()) {
+ if (param.isBody()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "TemplateMethod [name=" + name + ", documentation="
+ + documentation + ", parameters=" + parameters + "]";
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java
new file mode 100644
index 0000000..2755fcc
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateParameter.java
@@ -0,0 +1,181 @@
+/*
+ * $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.autotag.model;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+
+/**
+ * It represents a parameter in a method in a parsed template class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateParameter {
+
+ /**
+ * The name of the parameter.
+ */
+ private String name;
+
+ /**
+ * The exported name, i.e. the name of the parameter in created code. Usually
+ * helpful if this exported name is a reserved word.
+ */
+ private String exportedName;
+
+ /**
+ * The parameter documentation.
+ */
+ private String documentation;
+
+ /**
+ * The type of the prameter.
+ */
+ private String type;
+
+ /**
+ * The default value, as it will be written in Java code.
+ */
+ private String defaultValue;
+
+ /**
+ * Indicates that this parameter is required.
+ */
+ private boolean required;
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the parameter.
+ * @param exportedName The exported name, i.e. the name of the parameter in created code. Usually
+ * helpful if this exported name is a reserved word.
+ * @param type The type of the parameter.
+ * @param defaultValue The default value, as it will be written in Java code.
+ * @param required Indicates that this parameter is required.
+ */
+ public TemplateParameter(String name, String exportedName, String type, String defaultValue, boolean required) {
+ this.name = name;
+ this.exportedName = exportedName;
+ this.type = type;
+ this.defaultValue = defaultValue;
+ this.required = required;
+ }
+
+ /**
+ * Returns the documentation for this parameter.
+ *
+ * @return The documentation.
+ */
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ /**
+ * Sets the documentation for this parameter.
+ *
+ * @param documentation The documentation.
+ */
+ public void setDocumentation(String documentation) {
+ this.documentation = documentation;
+ }
+
+ /**
+ * Returns the name of the parameter.
+ *
+ * @return The name of the parameter.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the exported name, i.e. the name of the parameter in created code. Usually
+ * helpful if this exported name is a reserved word.
+ *
+ * @return The exported name.
+ */
+ public String getExportedName() {
+ return exportedName;
+ }
+
+ /**
+ * Returns the type of the parameter.
+ *
+ * @return The type.
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the default value, as it will be written in Java code.
+ *
+ * @return The default value.
+ */
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Indicates that this parameter is required.
+ *
+ * @return <code>true</code> if the parameter is required.
+ */
+ public boolean isRequired() {
+ return required;
+ }
+
+ /**
+ * Indicates that this parameter implements {@link ModelBody}.
+ *
+ * @return <code>true</code> if the parameter is a body.
+ */
+ public boolean isBody() {
+ return ModelBody.class.getName().equals(type);
+ }
+
+ /**
+ * Indicates that this parameter implements {@link Request}.
+ *
+ * @return <code>true</code> if the parameter is a request.
+ */
+ public boolean isRequest() {
+ return Request.class.getName().equals(type);
+ }
+
+ /**
+ * Returns the suffix for getter and setter of the property generated by
+ * this parameter.
+ *
+ * @return The getter and setter suffix.
+ */
+ public String getGetterSetterSuffix() {
+ return exportedName.substring(0, 1).toUpperCase() + exportedName.substring(1);
+ }
+
+ @Override
+ public String toString() {
+ return "TemplateParameter [name=" + name + ", exportedName="
+ + exportedName + ", documentation=" + documentation + ", type="
+ + type + ", defaultValue=" + defaultValue + ", required="
+ + required + "]";
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java
new file mode 100644
index 0000000..25361c8
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateSuite.java
@@ -0,0 +1,129 @@
+/*
+ * $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.autotag.model;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * It represents a suite of template classes.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateSuite {
+
+ /**
+ * The name of the suite.
+ */
+ private String name;
+
+ /**
+ * The documentation of this suite.
+ */
+ private String documentation;
+
+ /**
+ * The map of template classes.
+ */
+ private Map<String, TemplateClass> templateClasses;
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the suite.
+ * @param documentation The documentation.
+ */
+ public TemplateSuite(String name, String documentation) {
+ this(name, documentation, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name of the suite.
+ * @param documentation The documentation.
+ * @param classes The template classes.
+ */
+ public TemplateSuite(String name, String documentation,
+ Iterable<? extends TemplateClass> classes) {
+ this.name = name;
+ this.documentation = documentation;
+ templateClasses = new LinkedHashMap<String, TemplateClass>();
+ if (classes != null) {
+ for (TemplateClass templateClass : classes) {
+ templateClasses.put(templateClass.getName(), templateClass);
+ }
+ }
+ }
+
+ /**
+ * Returns the template suite name.
+ *
+ * @return The name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the documentation.
+ *
+ * @return The documentation.
+ */
+ public String getDocumentation() {
+ return documentation;
+ }
+
+ /**
+ * Adds a new template class.
+ *
+ * @param clazz The template class.
+ */
+ public void addTemplateClass(TemplateClass clazz) {
+ templateClasses.put(clazz.getName(), clazz);
+ }
+
+ /**
+ * Returns the template classes.
+ *
+ * @return The template classes.
+ */
+ public Collection<TemplateClass> getTemplateClasses() {
+ return templateClasses.values();
+ }
+
+ /**
+ * Returns a template class given its name.
+ *
+ * @param name The name of the class.
+ * @return The template class instance.
+ */
+ public TemplateClass getTemplateClassByName(String name) {
+ return templateClasses.get(name);
+ }
+
+ @Override
+ public String toString() {
+ return "TemplateSuite [name=" + name + ", documentation="
+ + documentation + ", templateClasses=" + templateClasses + "]";
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateSuiteFactory.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateSuiteFactory.java
new file mode 100644
index 0000000..4c45ebc
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/TemplateSuiteFactory.java
@@ -0,0 +1,37 @@
+/*
+ * $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.autotag.model;
+
+
+/**
+ * Creates a new template suite.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface TemplateSuiteFactory {
+
+ /**
+ * Creates a template suite.
+ *
+ * @return The created template suite.
+ */
+ TemplateSuite createTemplateSuite();
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/package-info.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/package-info.java
new file mode 100644
index 0000000..a1130d2
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/model/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Domain model classes representing a parsed template suite.
+ */
+package org.apache.tiles.autotag.model;
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/tool/StringTool.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/tool/StringTool.java
new file mode 100644
index 0000000..7341feb
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/tool/StringTool.java
@@ -0,0 +1,143 @@
+/*
+ * $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.autotag.tool;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tiles.autotag.core.AutotagRuntimeException;
+
+/**
+ * A Velocity tools to manipulate strings.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StringTool {
+
+ /**
+ * Maps a primitive type to its default value as a string.
+ */
+ private Map<String, String> type2default;
+
+ /**
+ * Maps a primitive type to its boxed version.
+ */
+ private Map<String, String> primitive2wrapped;
+
+ /**
+ * Constructor.
+ */
+ public StringTool() {
+ type2default = new HashMap<String, String>();
+ type2default.put("byte", "0");
+ type2default.put("short", "0");
+ type2default.put("int", "0");
+ type2default.put("long", "0L");
+ type2default.put("float", "0.0f");
+ type2default.put("double", "0.0d");
+ type2default.put("char", "'\\u0000'");
+ type2default.put("boolean", "false");
+
+ primitive2wrapped = new HashMap<String, String>();
+ primitive2wrapped.put("byte", Byte.class.getName());
+ primitive2wrapped.put("short", Short.class.getName());
+ primitive2wrapped.put("int", Integer.class.getName());
+ primitive2wrapped.put("long", Long.class.getName());
+ primitive2wrapped.put("float", Float.class.getName());
+ primitive2wrapped.put("double", Double.class.getName());
+ primitive2wrapped.put("char", Character.class.getName());
+ primitive2wrapped.put("boolean", Boolean.class.getName());
+ }
+
+ /**
+ * Creates a list of strings, separating a string when a newline is encountered.
+ *
+ * @param toSplit The string to split.
+ * @return The list of splitted strings.
+ */
+ public List<String> splitOnNewlines(String toSplit) {
+ List<String> retValue = new ArrayList<String>();
+ if (toSplit == null) {
+ return retValue;
+ }
+ Reader reader = new StringReader(toSplit);
+ BufferedReader bufReader = new BufferedReader(reader);
+ try {
+ String line;
+ while ((line = bufReader.readLine()) != null) {
+ retValue.add(line);
+ }
+ } catch (IOException e) {
+ throw new AutotagRuntimeException(
+ "Cannot read the string completely", e);
+ }
+ return retValue;
+ }
+
+ /**
+ * Creates a string in which the first character is capitalized.
+ *
+ * @param string The string to use.
+ * @return The same string with the first character capitalized.
+ */
+ public String capitalizeFirstLetter(String string) {
+ return string.substring(0, 1).toUpperCase() + string.substring(1);
+ }
+
+ /**
+ * Returns the default value for a type.
+ *
+ * @param type The type.
+ * @param overriddenDefaultValue The default value, as specified by developers.
+ * @return The default value to use.
+ */
+ public String getDefaultValue(String type, String overriddenDefaultValue) {
+ if (overriddenDefaultValue != null) {
+ return overriddenDefaultValue;
+ }
+
+ String retValue = type2default.get(type);
+ if (retValue == null) {
+ retValue = "null";
+ }
+ return retValue;
+ }
+
+ /**
+ * Returns the class to be used to cast an Object.
+ *
+ * @param type The type to use, even a primitive type.
+ * @return The class to be used in casts.
+ */
+ public String getClassToCast(String type) {
+ String retValue = primitive2wrapped.get(type);
+ if (retValue == null) {
+ retValue = type;
+ }
+ return retValue;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/tool/package-info.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/tool/package-info.java
new file mode 100644
index 0000000..558c330
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/tool/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Velocity tools to be used in Velocity templates.
+ */
+package org.apache.tiles.autotag.tool;
diff --git a/tiles-autotag/tiles-autotag-core/src/main/resources/org/apache/tiles/autotag/velocity.properties b/tiles-autotag/tiles-autotag-core/src/main/resources/org/apache/tiles/autotag/velocity.properties
new file mode 100644
index 0000000..0a9f2a5
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/main/resources/org/apache/tiles/autotag/velocity.properties
@@ -0,0 +1,115 @@
+# 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.
+
+# ----------------------------------------------------------------------------
+# These are the default properties for the
+# Velocity Runtime. These values are used when
+# Runtime.init() is called, and when Runtime.init(properties)
+# fails to find the specificed properties file.
+# ----------------------------------------------------------------------------
+
+
+# ----------------------------------------------------------------------------
+# R U N T I M E L O G
+# ----------------------------------------------------------------------------
+# Velocity uses the Servlet APIs logging facilites.
+
+# ----------------------------------------------------------------------------
+# This controls if Runtime.error(), info() and warn() messages include the
+# whole stack trace. The last property controls whether invalid references
+# are logged.
+# ----------------------------------------------------------------------------
+
+runtime.log.invalid.reference = true
+
+
+# ----------------------------------------------------------------------------
+# T E M P L A T E E N C O D I N G
+# ----------------------------------------------------------------------------
+
+input.encoding=ISO-8859-1
+output.encoding=ISO-8859-1
+
+
+# ----------------------------------------------------------------------------
+# F O R E A C H P R O P E R T I E S
+# ----------------------------------------------------------------------------
+# These properties control how the counter is accessed in the #foreach
+# directive. By default the reference $velocityCount will be available
+# in the body of the #foreach directive. The default starting value
+# for this reference is 1.
+# ----------------------------------------------------------------------------
+
+directive.foreach.counter.name = velocityCount
+directive.foreach.counter.initial.value = 1
+
+
+# ----------------------------------------------------------------------------
+# I N C L U D E P R O P E R T I E S
+# ----------------------------------------------------------------------------
+# These are the properties that governed the way #include'd content
+# is governed.
+# ----------------------------------------------------------------------------
+
+directive.include.output.errormsg.start = <!-- include error :
+directive.include.output.errormsg.end = see error log -->
+
+
+# ----------------------------------------------------------------------------
+# P A R S E P R O P E R T I E S
+# ----------------------------------------------------------------------------
+
+directive.parse.max.depth = 10
+
+
+# ----------------------------------------------------------------------------
+# VELOCIMACRO PROPERTIES
+# ----------------------------------------------------------------------------
+# global : name of default global library. It is expected to be in the regular
+# template path. You may remove it (either the file or this property) if
+# you wish with no harm.
+# ----------------------------------------------------------------------------
+# dev-changes by Marino
+resource.loader=class, string
+
+class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
+
+velocimacro.library.autoreload = false
+
+velocimacro.permissions.allow.inline = true
+velocimacro.permissions.allow.inline.to.replace.global = false
+velocimacro.permissions.allow.inline.local.scope = false
+
+velocimacro.context.localscope = false
+
+# ----------------------------------------------------------------------------
+# INTERPOLATION
+# ----------------------------------------------------------------------------
+# turn off and on interpolation of references and directives in string
+# literals. ON by default :)
+# ----------------------------------------------------------------------------
+runtime.interpolate.string.literals = true
+
+
+# ----------------------------------------------------------------------------
+# RESOURCE MANAGEMENT
+# ----------------------------------------------------------------------------
+# Allows alternative ResourceManager and ResourceCache implementations
+# to be plugged in.
+# ----------------------------------------------------------------------------
+resource.manager.class = org.apache.velocity.runtime.resource.ResourceManagerImpl
+resource.manager.cache.class = org.apache.velocity.runtime.resource.ResourceCacheImpl
diff --git a/tiles-autotag/tiles-autotag-core/src/site/site.xml b/tiles-autotag/tiles-autotag-core/src/site/site.xml
new file mode 100644
index 0000000..0a7d00d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/AutotagRuntimeExceptionTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/AutotagRuntimeExceptionTest.java
new file mode 100644
index 0000000..bf3338a
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/AutotagRuntimeExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.autotag.core;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link AutotagRuntimeException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AutotagRuntimeExceptionTest {
+
+ /**
+ * Test method for {@link AutotagRuntimeException#AutotagRuntimeException()}.
+ */
+ @Test
+ public void testAutotagRuntimeException() {
+ AutotagRuntimeException exception = new AutotagRuntimeException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link AutotagRuntimeException#AutotagRuntimeException(java.lang.String)}.
+ */
+ @Test
+ public void testAutotagRuntimeExceptionString() {
+ AutotagRuntimeException exception = new AutotagRuntimeException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link AutotagRuntimeException#AutotagRuntimeException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testAutotagRuntimeExceptionThrowable() {
+ Throwable cause = new Throwable();
+ AutotagRuntimeException exception = new AutotagRuntimeException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link AutotagRuntimeException#AutotagRuntimeException(java.lang.String, java.lang.Throwable)}.
+ */
+ @Test
+ public void testAutotagRuntimeExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ AutotagRuntimeException exception = new AutotagRuntimeException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/ClassParseExceptionTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/ClassParseExceptionTest.java
new file mode 100644
index 0000000..c3b2ae6
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/ClassParseExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.autotag.core;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link ClassParseException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ClassParseExceptionTest {
+
+ /**
+ * Test method for {@link ClassParseException#ClassParseException()}.
+ */
+ @Test
+ public void testClassParseException() {
+ ClassParseException exception = new ClassParseException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link ClassParseException#ClassParseException(java.lang.String)}.
+ */
+ @Test
+ public void testClassParseExceptionString() {
+ ClassParseException exception = new ClassParseException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link ClassParseException#ClassParseException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testClassParseExceptionThrowable() {
+ Throwable cause = new Throwable();
+ ClassParseException exception = new ClassParseException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link ClassParseException#ClassParseException(java.lang.String, java.lang.Throwable)}.
+ */
+ @Test
+ public void testClassParseExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ ClassParseException exception = new ClassParseException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/QDoxTemplateSuiteFactoryTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/QDoxTemplateSuiteFactoryTest.java
new file mode 100644
index 0000000..d417d7b
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/QDoxTemplateSuiteFactoryTest.java
@@ -0,0 +1,148 @@
+/*
+ * $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.autotag.core;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tiles.autotag.core.internal.AnnotatedExampleModel;
+import org.apache.tiles.autotag.core.internal.ExampleExecutableModel;
+import org.apache.tiles.autotag.core.internal.ExampleModel;
+import org.apache.tiles.autotag.core.internal.NotFeasibleExampleModel;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link QDoxTemplateSuiteFactory}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class QDoxTemplateSuiteFactoryTest {
+
+ /**
+ * The factory to test.
+ */
+ private QDoxTemplateSuiteFactory factory;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() {
+ factory = new QDoxTemplateSuiteFactory(
+ getClass().getResource("/org/apache/tiles/autotag/core/internal/ExampleModel.java"),
+ getClass().getResource("/org/apache/tiles/autotag/core/internal/AnnotatedExampleModel.java"),
+ getClass().getResource("/org/apache/tiles/autotag/core/internal/ExampleExcluded.java"),
+ getClass().getResource("/org/apache/tiles/autotag/core/internal/ExampleExecutableModel.java"),
+ getClass().getResource("/org/apache/tiles/autotag/core/internal/NotFeasibleExampleModel.java"));
+ factory.setSuiteName("The suite name");
+ factory.setSuiteDocumentation("This are the docs");
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.core.DefaultTemplateSuiteFactory#createTemplateSuite()}.
+ */
+ @Test
+ public void testCreateTemplateSuite() {
+ TemplateSuite suite = factory.createTemplateSuite();
+ assertEquals("The suite name", suite.getName());
+ assertEquals("This are the docs", suite.getDocumentation());
+ assertEquals(3, suite.getTemplateClasses().size());
+
+ TemplateClass templateClass = suite.getTemplateClassByName(ExampleModel.class.getName());
+ assertNotNull(templateClass);
+ assertEquals(ExampleModel.class.getName(), templateClass.getName());
+ assertEquals("Example start/stop template.", templateClass.getDocumentation());
+ TemplateMethod templateMethod = templateClass.getExecuteMethod();
+ assertNotNull(templateMethod);
+ assertTrue(templateMethod.hasBody());
+ assertTrue(templateClass.hasBody());
+ assertEquals("execute", templateMethod.getName());
+ assertEquals("It starts.", templateMethod.getDocumentation());
+ List<TemplateParameter> parameters = new ArrayList<TemplateParameter>(templateMethod.getParameters());
+ assertEquals(4, parameters.size());
+ TemplateParameter parameter = parameters.get(0);
+ assertEquals("one", parameter.getName());
+ assertEquals("java.lang.String", parameter.getType());
+ assertEquals("Parameter one.", parameter.getDocumentation());
+ parameter = parameters.get(1);
+ assertEquals("two", parameter.getName());
+ assertEquals("int", parameter.getType());
+ assertEquals("Parameter two.", parameter.getDocumentation());
+ parameter = parameters.get(2);
+ assertEquals("request", parameter.getName());
+ assertEquals(Request.class.getName(), parameter.getType());
+ assertEquals("The request.", parameter.getDocumentation());
+ parameter = parameters.get(3);
+ assertEquals("modelBody", parameter.getName());
+ assertEquals(ModelBody.class.getName(), parameter.getType());
+ assertEquals("The model body.", parameter.getDocumentation());
+
+ templateClass = suite.getTemplateClassByName(AnnotatedExampleModel.class.getName());
+ assertNotNull(templateClass);
+ assertEquals(AnnotatedExampleModel.class.getName(), templateClass.getName());
+ templateMethod = templateClass.getExecuteMethod();
+ assertNotNull(templateMethod);
+ assertEquals("execute", templateMethod.getName());
+ parameters = new ArrayList<TemplateParameter>(templateMethod.getParameters());
+ assertEquals(4, parameters.size());
+ parameter = parameters.get(0);
+ assertEquals("one", parameter.getName());
+ assertEquals("alternateOne", parameter.getExportedName());
+ assertEquals("java.lang.String", parameter.getType());
+ assertEquals("Parameter one.", parameter.getDocumentation());
+ assertEquals("hello", parameter.getDefaultValue());
+ assertTrue(parameter.isRequired());
+
+ templateClass = suite.getTemplateClassByName(ExampleExecutableModel.class.getName());
+ assertNotNull(templateClass);
+ assertEquals(ExampleExecutableModel.class.getName(), templateClass.getName());
+ assertEquals("Example executable template.", templateClass.getDocumentation());
+ templateMethod = templateClass.getExecuteMethod();
+ assertNotNull(templateMethod);
+ assertEquals("execute", templateMethod.getName());
+ assertEquals("It executes.", templateMethod.getDocumentation());
+ parameters = new ArrayList<TemplateParameter>(templateMethod.getParameters());
+ assertEquals(3, parameters.size());
+ parameter = parameters.get(0);
+ assertEquals("one", parameter.getName());
+ assertEquals("java.lang.String", parameter.getType());
+ assertEquals("Parameter one.", parameter.getDocumentation());
+ parameter = parameters.get(1);
+ assertEquals("two", parameter.getName());
+ assertEquals("int", parameter.getType());
+ assertEquals("Parameter two.", parameter.getDocumentation());
+ parameter = parameters.get(2);
+ assertEquals("request", parameter.getName());
+ assertEquals(Request.class.getName(), parameter.getType());
+ assertEquals("The request.", parameter.getDocumentation());
+
+ assertNull(suite.getTemplateClassByName(NotFeasibleExampleModel.class.getName()));
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/AnnotatedExampleModel.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/AnnotatedExampleModel.java
new file mode 100644
index 0000000..f2ca684
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/AnnotatedExampleModel.java
@@ -0,0 +1,47 @@
+/*
+ * $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.autotag.core.internal;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.annotation.Parameter;
+import org.apache.tiles.request.Request;
+
+/**
+ * Example start/stop template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AnnotatedExampleModel {
+
+ /**
+ * It starts.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ * @param modelBody The model body.
+ */
+ public void execute(
+ @Parameter(defaultValue = "hello", name = "alternateOne", required = true) String one,
+ int two, Request request, ModelBody modelBody) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleExcluded.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleExcluded.java
new file mode 100644
index 0000000..6693700
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleExcluded.java
@@ -0,0 +1,44 @@
+/*
+ * $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.autotag.core.internal;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+
+/**
+ * Example start/stop template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExampleExcluded {
+
+ /**
+ * It starts.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ * @param modelBody The model body.
+ */
+ public void execute(String one, int two, Request request, ModelBody modelBody) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleExecutableModel.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleExecutableModel.java
new file mode 100644
index 0000000..487e201
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleExecutableModel.java
@@ -0,0 +1,42 @@
+/*
+ * $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.autotag.core.internal;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * Example executable template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExampleExecutableModel {
+
+ /**
+ * It executes.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ */
+ public void execute(String one, int two, Request request) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleModel.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleModel.java
new file mode 100644
index 0000000..3ed332d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/ExampleModel.java
@@ -0,0 +1,44 @@
+/*
+ * $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.autotag.core.internal;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+
+/**
+ * Example start/stop template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExampleModel {
+
+ /**
+ * It starts.
+ *
+ * @param one Parameter one.
+ * @param two Parameter two.
+ * @param request The request.
+ * @param modelBody The model body.
+ */
+ public void execute(String one, int two, Request request, ModelBody modelBody) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/NotFeasibleExampleModel.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/NotFeasibleExampleModel.java
new file mode 100644
index 0000000..44dc258
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/core/internal/NotFeasibleExampleModel.java
@@ -0,0 +1,38 @@
+/*
+ * $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.autotag.core.internal;
+
+/**
+ * This won't be registered.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotFeasibleExampleModel {
+
+ /**
+ * It starts.
+ *
+ * @param whatever Doesn't matter.
+ */
+ public void start(String whatever) {
+ // Does nothing.
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGeneratorTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGeneratorTest.java
new file mode 100644
index 0000000..35bdd5b
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/AbstractTemplateClassGeneratorTest.java
@@ -0,0 +1,265 @@
+/*
+ * $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.autotag.generate;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.tiles.autotag.core.AutotagRuntimeException;
+import org.apache.tiles.autotag.core.ClassParseException;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractTemplateClassGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractTemplateClassGeneratorTest {
+
+ /**
+ * The velocity engine.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * The temporary directory.
+ */
+ private File directory;
+
+ /**
+ * The generator to test.
+ */
+ private AbstractTemplateClassGenerator generator;
+
+ /**
+ * Sets up the test.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ @Before
+ public void setUp() throws IOException {
+ velocityEngine = createMock(VelocityEngine.class);
+ generator = createMockBuilder(AbstractTemplateClassGenerator.class)
+ .withConstructor(velocityEngine).createMock();
+ directory = File.createTempFile("autotag", null);
+ }
+
+ /**
+ * Tears down the test.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(directory);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateClassGenerator#generate(java.io.File,
+ * String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass clazz = createMock(TemplateClass.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+ String runtimeClass = "org.apache.tiles.autotag.test.DoStuffRuntime";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, clazz, parameters, runtimeClass)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters, runtimeClass)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andReturn(template);
+ template.merge(isA(VelocityContext.class), isA(FileWriter.class));
+
+ replay(velocityEngine, generator, suite, clazz, template, parameters);
+ generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
+ verify(velocityEngine, generator, suite, clazz, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException1() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass clazz = createMock(TemplateClass.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+ String runtimeClass = "org.apache.tiles.autotag.test.DoStuffRuntime";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, clazz, parameters, runtimeClass)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters, runtimeClass)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andThrow(new ResourceNotFoundException("hello"));
+
+ replay(velocityEngine, generator, suite, clazz, template, parameters);
+ generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
+ verify(velocityEngine, generator, suite, clazz, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException2() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass clazz = createMock(TemplateClass.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+ String runtimeClass = "org.apache.tiles.autotag.test.DoStuffRuntime";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, clazz, parameters, runtimeClass)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters, runtimeClass)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andThrow(new ParseErrorException("hello"));
+
+ replay(velocityEngine, generator, suite, clazz, template, parameters);
+ generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
+ verify(velocityEngine, generator, suite, clazz, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException3() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass clazz = createMock(TemplateClass.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+ String runtimeClass = "org.apache.tiles.autotag.test.DoStuffRuntime";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, clazz, parameters, runtimeClass)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters, runtimeClass)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andThrow(new Exception());
+
+ replay(velocityEngine, generator, suite, clazz, template, parameters);
+ generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
+ verify(velocityEngine, generator, suite, clazz, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException4() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass clazz = createMock(TemplateClass.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+ String runtimeClass = "org.apache.tiles.autotag.test.DoStuffRuntime";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, clazz, parameters, runtimeClass)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters, runtimeClass)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andReturn(template);
+ template.merge(isA(VelocityContext.class), isA(FileWriter.class));
+ expectLastCall().andThrow(new IOException());
+
+ replay(velocityEngine, generator, suite, clazz, template, parameters);
+ generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
+ verify(velocityEngine, generator, suite, clazz, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = ClassParseException.class)
+ public void testGenerateException5() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass clazz = createMock(TemplateClass.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+ String runtimeClass = "org.apache.tiles.autotag.test.DoStuffRuntime";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, clazz, parameters, runtimeClass)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters, runtimeClass)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andReturn(template);
+ template.merge(isA(VelocityContext.class), isA(FileWriter.class));
+ expectLastCall().andThrow(new ClassParseException());
+
+ replay(velocityEngine, generator, suite, clazz, template, parameters);
+ generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
+ verify(velocityEngine, generator, suite, clazz, template, parameters);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGeneratorTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGeneratorTest.java
new file mode 100644
index 0000000..b98da2c
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/AbstractTemplateSuiteGeneratorTest.java
@@ -0,0 +1,259 @@
+/*
+ * $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.autotag.generate;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.tiles.autotag.core.AutotagRuntimeException;
+import org.apache.tiles.autotag.core.ClassParseException;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractTemplateSuiteGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractTemplateSuiteGeneratorTest {
+
+ /**
+ * The velocity engine.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * The temporary directory.
+ */
+ private File directory;
+
+ /**
+ * The generator to test.
+ */
+ private AbstractTemplateSuiteGenerator generator;
+
+ /**
+ * Sets up the test.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ @Before
+ public void setUp() throws IOException {
+ velocityEngine = createMock(VelocityEngine.class);
+ generator = createMockBuilder(AbstractTemplateSuiteGenerator.class)
+ .withConstructor(velocityEngine).createMock();
+ directory = File.createTempFile("autotag", null);
+ }
+
+ /**
+ * Tears down the test.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(directory);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateSuiteGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, parameters)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, parameters)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, parameters)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andReturn(template);
+ template.merge(isA(VelocityContext.class), isA(FileWriter.class));
+
+ replay(velocityEngine, generator, suite, template, parameters);
+ generator.generate(directory, packageName, suite, parameters);
+ verify(velocityEngine, generator, suite, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateSuiteGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException1() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, parameters)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, parameters)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, parameters)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andThrow(new ResourceNotFoundException("hello"));
+
+ replay(velocityEngine, generator, suite, template, parameters);
+ generator.generate(directory, packageName, suite, parameters);
+ verify(velocityEngine, generator, suite, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateSuiteGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException2() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, parameters)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, parameters)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, parameters)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andThrow(new ParseErrorException("hello"));
+
+ replay(velocityEngine, generator, suite, template, parameters);
+ generator.generate(directory, packageName, suite, parameters);
+ verify(velocityEngine, generator, suite, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateSuiteGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException3() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, parameters)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, parameters)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, parameters)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andThrow(new Exception());
+
+ replay(velocityEngine, generator, suite, template, parameters);
+ generator.generate(directory, packageName, suite, parameters);
+ verify(velocityEngine, generator, suite, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateSuiteGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = AutotagRuntimeException.class)
+ public void testGenerateException4() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, parameters)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, parameters)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, parameters)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andReturn(template);
+ template.merge(isA(VelocityContext.class), isA(FileWriter.class));
+ expectLastCall().andThrow(new IOException());
+
+ replay(velocityEngine, generator, suite, template, parameters);
+ generator.generate(directory, packageName, suite, parameters);
+ verify(velocityEngine, generator, suite, template, parameters);
+ }
+
+ /**
+ * Test method for {@link AbstractTemplateSuiteGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ * @throws ParseErrorException If something goes wrong.
+ * @throws ResourceNotFoundException If something goes wrong.
+ */
+ @Test(expected = ClassParseException.class)
+ public void testGenerateException5() throws Exception {
+ directory.delete();
+ directory.mkdir();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ Template template = createMock(Template.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ String packageName = "org.apache.tiles.autotag.test";
+
+ expect(generator.getDirectoryName(directory, packageName, suite, parameters)).andReturn("mydir");
+ File mydir = new File(directory, "mydir");
+ expect(generator.getFilename(mydir , packageName, suite, parameters)).andReturn("myfile.txt");
+ String sampleVmPath = "/sample.vm";
+ expect(generator.getTemplatePath(mydir, packageName, suite, parameters)).andReturn(sampleVmPath);
+ expect(velocityEngine.getTemplate("/sample.vm")).andReturn(template);
+ template.merge(isA(VelocityContext.class), isA(FileWriter.class));
+ expectLastCall().andThrow(new ClassParseException());
+
+ replay(velocityEngine, generator, suite, template, parameters);
+ generator.generate(directory, packageName, suite, parameters);
+ verify(velocityEngine, generator, suite, template, parameters);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/BasicTemplateGeneratorTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/BasicTemplateGeneratorTest.java
new file mode 100644
index 0000000..15463d3
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/BasicTemplateGeneratorTest.java
@@ -0,0 +1,80 @@
+/*
+ * $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.autotag.generate;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TCGeneratorDirectoryPair;
+import org.apache.tiles.autotag.generate.BasicTemplateGenerator.TSGeneratorDirectoryPair;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.junit.Test;
+
+/**
+ * Tests {@link BasicTemplateGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BasicTemplateGeneratorTest {
+
+ /**
+ * Test method for {@link BasicTemplateGenerator#generate(String, TemplateSuite, Map)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws IOException {
+ File file = File.createTempFile("tiles", "template");
+ file.deleteOnExit();
+ TemplateSuite suite = createMock(TemplateSuite.class);
+ TemplateClass templateClass = createMock(TemplateClass.class);
+ TemplateSuiteGenerator templateSuiteGenerator = createMock(TemplateSuiteGenerator.class);
+ TemplateClassGenerator templateClassGenerator = createMock(TemplateClassGenerator.class);
+ @SuppressWarnings("unchecked")
+ Map<String, String> parameters = createMock(Map.class);
+ List<TemplateClass> templateClasses = new ArrayList<TemplateClass>();
+
+ templateClasses.add(templateClass);
+
+ expect(suite.getTemplateClasses()).andReturn(templateClasses);
+ templateSuiteGenerator.generate(file, "my.package", suite, parameters);
+ templateClassGenerator.generate(file, "my.package", suite, templateClass, parameters, "my.Runtime");
+
+ replay(suite, templateClass, templateSuiteGenerator, templateClassGenerator, parameters);
+ TSGeneratorDirectoryPair tsPair = new TSGeneratorDirectoryPair(file, templateSuiteGenerator);
+ TCGeneratorDirectoryPair tcPair = new TCGeneratorDirectoryPair(file, templateClassGenerator);
+ List<TSGeneratorDirectoryPair> tsList = new ArrayList<BasicTemplateGenerator.TSGeneratorDirectoryPair>();
+ tsList.add(tsPair);
+ List<TCGeneratorDirectoryPair> tcList = new ArrayList<BasicTemplateGenerator.TCGeneratorDirectoryPair>();
+ tcList.add(tcPair);
+ BasicTemplateGenerator generator = new BasicTemplateGenerator(tsList, tcList, true, false);
+ assertTrue(generator.isGeneratingClasses());
+ assertFalse(generator.isGeneratingResources());
+ generator.generate("my.package", suite, parameters, "my.Runtime");
+ verify(suite, templateClass, templateSuiteGenerator, templateClassGenerator, parameters);
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilderTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilderTest.java
new file mode 100644
index 0000000..998bd6d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/TemplateGeneratorBuilderTest.java
@@ -0,0 +1,169 @@
+/*
+ * $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.autotag.generate;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import org.junit.Test;
+
+/**
+ * @author antonio
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateGeneratorBuilderTest {
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addClassesTemplateSuiteGenerator(TemplateSuiteGenerator)}.
+ */
+ @Test
+ public void testAddClassesTemplateSuiteGenerator() {
+ File dir = createMock(File.class);
+ TemplateSuiteGenerator generator = createMock(TemplateSuiteGenerator.class);
+
+ replay(dir, generator);
+ TemplateGenerator templateGenerator = TemplateGeneratorBuilder
+ .createNewInstance().setClassesOutputDirectory(dir)
+ .addClassesTemplateSuiteGenerator(generator).build();
+ assertTrue(templateGenerator.isGeneratingClasses());
+ assertFalse(templateGenerator.isGeneratingResources());
+ verify(dir, generator);
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addClassesTemplateSuiteGenerator(TemplateSuiteGenerator)}.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testAddClassesTemplateSuiteGeneratorException() {
+ TemplateSuiteGenerator generator = createMock(TemplateSuiteGenerator.class);
+
+ replay(generator);
+ try {
+ TemplateGeneratorBuilder.createNewInstance()
+ .addClassesTemplateSuiteGenerator(generator);
+ } finally {
+ verify(generator);
+ }
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addClassesTemplateClassGenerator(TemplateClassGenerator)}.
+ */
+ @Test
+ public void testAddClassesTemplateClassGenerator() {
+ File dir = createMock(File.class);
+ TemplateClassGenerator generator = createMock(TemplateClassGenerator.class);
+
+ replay(dir, generator);
+ TemplateGenerator templateGenerator = TemplateGeneratorBuilder
+ .createNewInstance().setClassesOutputDirectory(dir)
+ .addClassesTemplateClassGenerator(generator).build();
+ assertTrue(templateGenerator.isGeneratingClasses());
+ assertFalse(templateGenerator.isGeneratingResources());
+ verify(dir, generator);
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addClassesTemplateClassGenerator(TemplateClassGenerator)}.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testAddClassesTemplateClassGeneratorException() {
+ TemplateClassGenerator generator = createMock(TemplateClassGenerator.class);
+
+ replay(generator);
+ try {
+ TemplateGeneratorBuilder.createNewInstance()
+ .addClassesTemplateClassGenerator(generator);
+ } finally {
+ verify(generator);
+ }
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addResourcesTemplateSuiteGenerator(TemplateSuiteGenerator)}.
+ */
+ @Test
+ public void testAddResourcesTemplateSuiteGenerator() {
+ File dir = createMock(File.class);
+ TemplateSuiteGenerator generator = createMock(TemplateSuiteGenerator.class);
+
+ replay(dir, generator);
+ TemplateGenerator templateGenerator = TemplateGeneratorBuilder
+ .createNewInstance().setResourcesOutputDirectory(dir)
+ .addResourcesTemplateSuiteGenerator(generator).build();
+ assertFalse(templateGenerator.isGeneratingClasses());
+ assertTrue(templateGenerator.isGeneratingResources());
+ verify(dir, generator);
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addResourcesTemplateSuiteGenerator(TemplateSuiteGenerator)}.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testAddResourcesTemplateSuiteGeneratorException() {
+ TemplateSuiteGenerator generator = createMock(TemplateSuiteGenerator.class);
+
+ replay(generator);
+ try {
+ TemplateGeneratorBuilder.createNewInstance()
+ .addResourcesTemplateSuiteGenerator(generator);
+ } finally {
+ verify(generator);
+ }
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addResourcesTemplateClassGenerator(TemplateClassGenerator)}.
+ */
+ @Test
+ public void testAddResourcesTemplateClassGenerator() {
+ File dir = createMock(File.class);
+ TemplateClassGenerator generator = createMock(TemplateClassGenerator.class);
+
+ replay(dir, generator);
+ TemplateGenerator templateGenerator = TemplateGeneratorBuilder
+ .createNewInstance().setResourcesOutputDirectory(dir)
+ .addResourcesTemplateClassGenerator(generator).build();
+ assertFalse(templateGenerator.isGeneratingClasses());
+ assertTrue(templateGenerator.isGeneratingResources());
+ verify(dir, generator);
+ }
+
+ /**
+ * Test method for {@link TemplateGeneratorBuilder#addResourcesTemplateClassGenerator(TemplateClassGenerator)}.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testAddResourcesTemplateClassGeneratorException() {
+ TemplateClassGenerator generator = createMock(TemplateClassGenerator.class);
+
+ replay(generator);
+ try {
+ TemplateGeneratorBuilder.createNewInstance()
+ .addResourcesTemplateClassGenerator(generator);
+ } finally {
+ verify(generator);
+ }
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java
new file mode 100644
index 0000000..e2acdb8
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateClassTest.java
@@ -0,0 +1,157 @@
+/*
+ * $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.autotag.model;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * @author antonio
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateClassTest {
+
+ /**
+ * Test method for {@link TemplateClass#TemplateClass(String)}.
+ */
+ @Test
+ public void testTemplateConstructor1() {
+ TemplateClass templateClass = new TemplateClass("name");
+ assertEquals("name", templateClass.getName());
+ assertNull(templateClass.getTagName());
+ assertNull(templateClass.getTagClassPrefix());
+ assertNull(templateClass.getExecuteMethod());
+ Collection<TemplateParameter> params = templateClass.getParameters();
+ assertTrue(params.isEmpty());
+ }
+
+ /**
+ * Test method for {@link TemplateClass#TemplateClass(String, String, String, TemplateMethod)}.
+ */
+ @Test
+ public void testTemplateConstructor2() {
+ TemplateMethod method = createMock(TemplateMethod.class);
+
+ replay(method);
+ TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method);
+ assertEquals("name", templateClass.getName());
+ assertEquals("tagName", templateClass.getTagName());
+ assertEquals("tagClassPrefix", templateClass.getTagClassPrefix());
+ assertEquals(method, templateClass.getExecuteMethod());
+ verify(method);
+ }
+
+ /**
+ * Test method for {@link TemplateClass#getSimpleName()}.
+ */
+ @Test
+ public void testGetSimpleName() {
+ TemplateClass templateClass = new TemplateClass("name");
+ assertEquals("name", templateClass.getSimpleName());
+ templateClass = new TemplateClass("org.whatever.Hello");
+ assertEquals("Hello", templateClass.getSimpleName());
+ }
+
+ /**
+ * Test method for {@link TemplateClass#setDocumentation(String)}.
+ */
+ @Test
+ public void testSetDocumentation() {
+ TemplateClass templateClass = new TemplateClass("name");
+ templateClass.setDocumentation("docs");
+ assertEquals("docs", templateClass.getDocumentation());
+ }
+
+ /**
+ * Test method for {@link TemplateClass#getParameters()}.
+ */
+ @Test
+ public void testGetParameters() {
+ TemplateParameter param1 = createMock(TemplateParameter.class);
+ TemplateParameter param2 = createMock(TemplateParameter.class);
+ TemplateParameter param3 = createMock(TemplateParameter.class);
+ TemplateParameter param4 = createMock(TemplateParameter.class);
+ TemplateMethod method = createMock(TemplateMethod.class);
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+
+ expect(method.getParameters()).andReturn(params);
+ expect(param1.isRequest()).andReturn(true);
+ expect(param2.isRequest()).andReturn(false);
+ expect(param2.isBody()).andReturn(true);
+ expect(param3.isRequest()).andReturn(false);
+ expect(param3.isBody()).andReturn(false);
+ expect(param4.isRequest()).andReturn(false);
+ expect(param4.isBody()).andReturn(false);
+ expect(param3.getName()).andReturn("param1");
+ expect(param4.getName()).andReturn("param2");
+
+ replay(param1, param2, param3, param4, method);
+ params.add(param1);
+ params.add(param2);
+ params.add(param3);
+ params.add(param4);
+
+ TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method);
+ Collection<TemplateParameter> returnedParams = templateClass.getParameters();
+ Iterator<TemplateParameter> paramIt = returnedParams.iterator();
+ assertSame(param3, paramIt.next());
+ assertSame(param4, paramIt.next());
+ assertFalse(paramIt.hasNext());
+ verify(param1, param2, param3, param4, method);
+ }
+
+ /**
+ * Test method for {@link TemplateClass#hasBody()}.
+ */
+ @Test
+ public void testHasBody() {
+ TemplateMethod method = createMock(TemplateMethod.class);
+ expect(method.hasBody()).andReturn(true);
+
+ replay(method);
+ TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method);
+ assertTrue(templateClass.hasBody());
+ verify(method);
+ }
+
+ /**
+ * Test method for {@link TemplateClass#toString()}.
+ */
+ @Test
+ public void testToString() {
+ TemplateMethod method = new TemplateMethod("method", new ArrayList<TemplateParameter>());
+ TemplateClass templateClass = new TemplateClass("name", "tagName", "tagClassPrefix", method);
+ assertEquals(
+ "TemplateClass [name=name, tagName=tagName, tagClassPrefix=tagClassPrefix, "
+ + "documentation=null, executeMethod=TemplateMethod "
+ + "[name=method, documentation=null, parameters={}]]",
+ templateClass.toString());
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java
new file mode 100644
index 0000000..c868109
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateMethodTest.java
@@ -0,0 +1,130 @@
+/*
+ * $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.autotag.model;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link TemplateMethod}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateMethodTest {
+
+ /**
+ * Tests {@link TemplateMethod#TemplateMethod(String, Iterable)}.
+ */
+ @Test
+ public void testTemplateMethod() {
+ TemplateParameter param1 = createMock(TemplateParameter.class);
+ TemplateParameter param2 = createMock(TemplateParameter.class);
+
+ expect(param1.getName()).andReturn("param1");
+ expect(param2.getName()).andReturn("param2");
+
+ replay(param1, param2);
+ List<TemplateParameter> parameters = new ArrayList<TemplateParameter>();
+ parameters.add(param1);
+ parameters.add(param2);
+
+ TemplateMethod method = new TemplateMethod("method", parameters);
+ assertEquals("method", method.getName());
+ Iterator<TemplateParameter> params = method.getParameters().iterator();
+ assertSame(param1, params.next());
+ assertSame(param2, params.next());
+ assertFalse(params.hasNext());
+ assertSame(param1, method.getParameterByName("param1"));
+ assertSame(param2, method.getParameterByName("param2"));
+ verify(param1, param2);
+ }
+
+ /**
+ * Tests {@link TemplateMethod#setDocumentation(String)}.
+ */
+ @Test
+ public void testSetDocumentation() {
+ TemplateMethod method = new TemplateMethod("method", new ArrayList<TemplateParameter>());
+ method.setDocumentation("docs");
+ assertEquals("docs", method.getDocumentation());
+ }
+
+ /**
+ * Tests {@link TemplateMethod#hasBody()}.
+ */
+ @Test
+ public void testHasBody() {
+ TemplateParameter param1 = createMock(TemplateParameter.class);
+ TemplateParameter param2 = createMock(TemplateParameter.class);
+
+ expect(param1.getName()).andReturn("param1");
+ expect(param2.getName()).andReturn("param2");
+ expect(param1.isBody()).andReturn(true);
+
+ replay(param1, param2);
+ List<TemplateParameter> parameters = new ArrayList<TemplateParameter>();
+ parameters.add(param1);
+ parameters.add(param2);
+
+ TemplateMethod method = new TemplateMethod("method", parameters);
+ assertTrue(method.hasBody());
+ verify(param1, param2);
+ }
+
+ /**
+ * Tests {@link TemplateMethod#hasBody()}.
+ */
+ @Test
+ public void testHasBody2() {
+ TemplateParameter param1 = createMock(TemplateParameter.class);
+ TemplateParameter param2 = createMock(TemplateParameter.class);
+
+ expect(param1.getName()).andReturn("param1");
+ expect(param2.getName()).andReturn("param2");
+ expect(param1.isBody()).andReturn(false);
+ expect(param2.isBody()).andReturn(false);
+
+ replay(param1, param2);
+ List<TemplateParameter> parameters = new ArrayList<TemplateParameter>();
+ parameters.add(param1);
+ parameters.add(param2);
+
+ TemplateMethod method = new TemplateMethod("method", parameters);
+ assertFalse(method.hasBody());
+ verify(param1, param2);
+ }
+
+ /**
+ * Tests {@link TemplateMethod#toString()}.
+ */
+ @Test
+ public void testToString() {
+ TemplateMethod method = new TemplateMethod("method", new ArrayList<TemplateParameter>());
+ assertEquals("TemplateMethod [name=method, documentation=null, parameters={}]", method.toString());
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java
new file mode 100644
index 0000000..c0a100d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateParameterTest.java
@@ -0,0 +1,94 @@
+/*
+ * $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.autotag.model;
+
+import static org.junit.Assert.*;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.Request;
+import org.junit.Test;
+
+/**
+ * Tests {@link TemplateParameter}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateParameterTest {
+
+ /**
+ * Tests {@link TemplateParameter#TemplateParameter(String, String, String, String, boolean)}.
+ */
+ @Test
+ public void testTemplateParameter() {
+ TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true);
+ assertEquals("name", parameter.getName());
+ assertEquals("exportedName", parameter.getExportedName());
+ assertEquals("type", parameter.getType());
+ assertEquals("defaultValue", parameter.getDefaultValue());
+ assertTrue(parameter.isRequired());
+ assertEquals("ExportedName", parameter.getGetterSetterSuffix());
+ assertFalse(parameter.isBody());
+ assertFalse(parameter.isRequest());
+
+ parameter = new TemplateParameter("name", "exportedName", Request.class.getName(), "defaultValue", false);
+ assertEquals("name", parameter.getName());
+ assertEquals("exportedName", parameter.getExportedName());
+ assertEquals(Request.class.getName(), parameter.getType());
+ assertEquals("defaultValue", parameter.getDefaultValue());
+ assertFalse(parameter.isRequired());
+ assertEquals("ExportedName", parameter.getGetterSetterSuffix());
+ assertFalse(parameter.isBody());
+ assertTrue(parameter.isRequest());
+
+ parameter = new TemplateParameter("name", "exportedName", ModelBody.class.getName(), "defaultValue", false);
+ assertEquals("name", parameter.getName());
+ assertEquals("exportedName", parameter.getExportedName());
+ assertEquals(ModelBody.class.getName(), parameter.getType());
+ assertEquals("defaultValue", parameter.getDefaultValue());
+ assertFalse(parameter.isRequired());
+ assertEquals("ExportedName", parameter.getGetterSetterSuffix());
+ assertTrue(parameter.isBody());
+ assertFalse(parameter.isRequest());
+ }
+
+ /**
+ * Tests {@link TemplateParameter#setDocumentation(String)}.
+ */
+ @Test
+ public void testSetDocumentation() {
+ TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true);
+ parameter.setDocumentation("docs");
+ assertEquals("docs", parameter.getDocumentation());
+ }
+
+ /**
+ * Tests {@link TemplateParameter#toString()}.
+ */
+ @Test
+ public void testToString() {
+ TemplateParameter parameter = new TemplateParameter("name", "exportedName", "type", "defaultValue", true);
+ assertEquals(
+ "TemplateParameter [name=name, exportedName=exportedName, "
+ + "documentation=null, type=type, defaultValue=defaultValue, required=true]",
+ parameter.toString());
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java
new file mode 100644
index 0000000..535ee98
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/model/TemplateSuiteTest.java
@@ -0,0 +1,113 @@
+/*
+ * $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.autotag.model;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link TemplateSuite}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TemplateSuiteTest {
+
+ /**
+ * Test method for {@link TemplateSuite#TemplateSuite(java.lang.String, java.lang.String)}.
+ */
+ @Test
+ public void testTemplateSuiteCostructor1() {
+ TemplateSuite suite = new TemplateSuite("name", "docs");
+ assertEquals("name", suite.getName());
+ assertEquals("docs", suite.getDocumentation());
+ assertTrue(suite.getTemplateClasses().isEmpty());
+ }
+
+ /**
+ * Test method for {@link TemplateSuite#TemplateSuite(java.lang.String, java.lang.String, java.lang.Iterable)}.
+ */
+ @Test
+ public void testTemplateSuiteConstructor2() {
+ TemplateClass class1 = createMock(TemplateClass.class);
+ TemplateClass class2 = createMock(TemplateClass.class);
+ expect(class1.getName()).andReturn("class1");
+ expect(class2.getName()).andReturn("class2");
+
+ replay(class1, class2);
+ List<TemplateClass> classes = new ArrayList<TemplateClass>();
+ classes.add(class1);
+ classes.add(class2);
+ TemplateSuite suite = new TemplateSuite("name", "docs", classes);
+ assertEquals("name", suite.getName());
+ assertEquals("docs", suite.getDocumentation());
+ Iterator<TemplateClass> clazzes = suite.getTemplateClasses().iterator();
+ assertSame(class1, clazzes.next());
+ assertSame(class2, clazzes.next());
+ assertFalse(clazzes.hasNext());
+ assertSame(class1, suite.getTemplateClassByName("class1"));
+ assertSame(class2, suite.getTemplateClassByName("class2"));
+ verify(class1, class2);
+ }
+
+ /**
+ * Test method for {@link TemplateSuite#addTemplateClass(org.apache.tiles.autotag.model.TemplateClass)}.
+ */
+ @Test
+ public void testAddTemplateClass() {
+ TemplateClass class1 = createMock(TemplateClass.class);
+ TemplateClass class2 = createMock(TemplateClass.class);
+ expect(class1.getName()).andReturn("class1");
+ expect(class2.getName()).andReturn("class2");
+
+ replay(class1, class2);
+ List<TemplateClass> classes = new ArrayList<TemplateClass>();
+ classes.add(class1);
+ classes.add(class2);
+ TemplateSuite suite = new TemplateSuite("name", "docs");
+ assertEquals("name", suite.getName());
+ assertEquals("docs", suite.getDocumentation());
+ assertTrue(suite.getTemplateClasses().isEmpty());
+ suite.addTemplateClass(class1);
+ suite.addTemplateClass(class2);
+ Iterator<TemplateClass> clazzes = suite.getTemplateClasses().iterator();
+ assertSame(class1, clazzes.next());
+ assertSame(class2, clazzes.next());
+ assertFalse(clazzes.hasNext());
+ assertSame(class1, suite.getTemplateClassByName("class1"));
+ assertSame(class2, suite.getTemplateClassByName("class2"));
+ verify(class1, class2);
+ }
+
+ /**
+ * Test method for {@link TemplateSuite#toString()}.
+ */
+ @Test
+ public void testToString() {
+ TemplateSuite suite = new TemplateSuite("name", "docs");
+ assertEquals("TemplateSuite [name=name, documentation=docs, templateClasses={}]", suite.toString());
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/tool/StringToolTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/tool/StringToolTest.java
new file mode 100644
index 0000000..7fd6023
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/tool/StringToolTest.java
@@ -0,0 +1,82 @@
+/*
+ * $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.autotag.tool;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link StringTool}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StringToolTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.tool.StringTool#splitOnNewlines(java.lang.String)}.
+ */
+ @Test
+ public void testSplitOnNewlines() {
+ StringTool tool = new StringTool();
+ List<String> splitted = tool.splitOnNewlines("time\nto\nsplit");
+ assertEquals(3, splitted.size());
+ assertEquals("time", splitted.get(0));
+ assertEquals("to", splitted.get(1));
+ assertEquals("split", splitted.get(2));
+ splitted = tool.splitOnNewlines(null);
+ assertTrue(splitted.isEmpty());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.tool.StringTool#capitalizeFirstLetter(java.lang.String)}.
+ */
+ @Test
+ public void testCapitalizeFirstLetter() {
+ StringTool tool = new StringTool();
+ assertEquals("Whatever", tool.capitalizeFirstLetter("whatever"));
+ }
+
+ /**
+ * Test method for {@link StringTool#getDefaultValue(java.lang.String, java.lang.String)}.
+ */
+ @Test
+ public void testGetDefaultValue() {
+ StringTool tool = new StringTool();
+ assertEquals("0", tool.getDefaultValue("byte", null));
+ assertEquals("1", tool.getDefaultValue("byte", "1"));
+ assertEquals("null", tool.getDefaultValue("Whatever", null));
+ assertEquals("thatsit", tool.getDefaultValue("Whatever", "thatsit"));
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.tool.StringTool#getClassToCast(java.lang.String)}.
+ */
+ @Test
+ public void testGetClassToCast() {
+ StringTool tool = new StringTool();
+ assertEquals(Byte.class.getName(), tool.getClassToCast("byte"));
+ assertEquals("Whatever", tool.getClassToCast("Whatever"));
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/pom.xml b/tiles-autotag/tiles-autotag-freemarker/pom.xml
new file mode 100644
index 0000000..481c718
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-autotag</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-freemarker</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Autotag - Freemarker support</name>
+ <description>Generates code for Freemarker support.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java
new file mode 100644
index 0000000..ad08ea7
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMModelGenerator.java
@@ -0,0 +1,67 @@
+/*
+ * $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.autotag.freemarker;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates a single Freemarker directive model, given a template class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FMModelGenerator extends AbstractTemplateClassGenerator {
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public FMModelGenerator(VelocityEngine velocityEngine) {
+ super(velocityEngine);
+ }
+
+ @Override
+ protected String getDirectoryName(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return packageName.replaceAll("\\.", "/");
+ }
+
+ @Override
+ protected String getFilename(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return clazz.getTagClassPrefix() + "FMModel.java";
+ }
+
+ @Override
+ protected String getTemplatePath(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return "/org/apache/tiles/autotag/freemarker/fmModel.vm";
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java
new file mode 100644
index 0000000..23bc4fc
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGenerator.java
@@ -0,0 +1,65 @@
+/*
+ * $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.autotag.freemarker;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates the model repository, given the template suite.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FMModelRepositoryGenerator extends AbstractTemplateSuiteGenerator {
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public FMModelRepositoryGenerator(VelocityEngine velocityEngine) {
+ super(velocityEngine);
+ }
+
+ @Override
+ protected String getTemplatePath(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return "/org/apache/tiles/autotag/freemarker/repository.vm";
+ }
+
+ @Override
+ protected String getFilename(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ String name = suite.getName();
+ return name.substring(0, 1).toUpperCase() + name.substring(1) + "FMModelRepository.java";
+ }
+
+ @Override
+ protected String getDirectoryName(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return packageName.replaceAll("\\.", "/");
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java
new file mode 100644
index 0000000..00bf96a
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactory.java
@@ -0,0 +1,79 @@
+/*
+ * $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.autotag.freemarker;
+
+import java.io.File;
+
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Creates a template generator that generates code for Freemarker.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FMTemplateGeneratorFactory implements TemplateGeneratorFactory {
+
+ /**
+ * Location of the file.
+ *
+ * @parameter expression="${project.build.directory}/autotag-jsp-classes"
+ * @required
+ */
+ private File classesOutputDirectory;
+
+ /**
+ * The Velocity engine.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * The template generator builder.
+ */
+ private TemplateGeneratorBuilder templateGeneratorBuilder;
+
+ /**
+ * Constructor.
+ *
+ * @param classesOutputDirectory Directory where code will be placed.
+ * @param velocityEngine The Velocity engine.
+ * @param templateGeneratorBuilder The template generator builder.
+ */
+ public FMTemplateGeneratorFactory(File classesOutputDirectory,
+ VelocityEngine velocityEngine, TemplateGeneratorBuilder templateGeneratorBuilder) {
+ this.classesOutputDirectory = classesOutputDirectory;
+ this.velocityEngine = velocityEngine;
+ this.templateGeneratorBuilder = templateGeneratorBuilder;
+ }
+
+ @Override
+ public TemplateGenerator createTemplateGenerator() {
+ return templateGeneratorBuilder
+ .setClassesOutputDirectory(classesOutputDirectory)
+ .addClassesTemplateSuiteGenerator(
+ new FMModelRepositoryGenerator(velocityEngine))
+ .addClassesTemplateClassGenerator(
+ new FMModelGenerator(velocityEngine)).build();
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java
new file mode 100644
index 0000000..c230fed
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/main/java/org/apache/tiles/autotag/freemarker/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Autotag support for Freemarker.
+ */
+package org.apache.tiles.autotag.freemarker;
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm b/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm
new file mode 100644
index 0000000..ef8bdcf
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm
@@ -0,0 +1,83 @@
+#*
+ * $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.
+ *#/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package ${packageName};
+
+import java.io.IOException;
+import java.util.Map;
+
+#if(${clazz.hasBody()})
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+#end
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+
+/**
+#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation}))
+ * ${line}
+#end
+ */
+public class ${clazz.tagClassPrefix}FMModel implements TemplateDirectiveModel {
+
+ /**
+ * The template model.
+ */
+ private ${clazz.name} model;
+
+ /**
+ * Constructor.
+ *
+ * @param model
+ * The template model.
+ */
+ public ${clazz.tagClassPrefix}FMModel(${clazz.name} model) {
+ this.model = model;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
+ TemplateDirectiveBody body) throws TemplateException, IOException {
+ AutotagRuntime runtime = new ${runtimeClass}();
+ if (runtime instanceof TemplateDirectiveModel) {
+ ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body);
+ }
+ Request request = runtime.createRequest();
+#if(${clazz.hasBody()})
+ ModelBody modelBody = runtime.createModelBody();
+#end
+ model.execute(
+#foreach($parameter in ${clazz.parameters})
+ ($stringTool.getClassToCast(${parameter.type})) runtime.getParameter("${parameter.exportedName}", $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})),
+#end
+ request#if(${clazz.hasBody()}), modelBody#end
+
+ );
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm b/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm
new file mode 100644
index 0000000..20724c6
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/repository.vm
@@ -0,0 +1,58 @@
+#*
+ * $Id: tiles-jsp.tld 836180 2009-11-14 14:00:02Z 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.
+ *#/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package ${packageName};
+
+/**
+#foreach($line in $stringTool.splitOnNewlines(${suite.documentation}))
+ * $line
+#end
+ */
+public class $stringTool.capitalizeFirstLetter(${suite.name})FMModelRepository {
+
+#foreach($clazz in ${suite.getTemplateClasses()})
+ /**
+ * The "${clazz.tagName}" directive.
+ */
+ private ${clazz.tagClassPrefix}FMModel ${clazz.tagName};
+
+#end
+ /**
+ * Constructor.
+ */
+ public TilesFMModelRepository() {
+#foreach($clazz in ${suite.getTemplateClasses()})
+ ${clazz.tagName} = new ${clazz.tagClassPrefix}FMModel(new ${clazz.name}());
+#end
+ }
+#foreach($clazz in ${suite.getTemplateClasses()})
+
+ /**
+ * Returns the "${clazz.tagName}" directive.
+ *
+ * @return The "${clazz.tagName}" directive.
+ */
+ public ${clazz.tagClassPrefix}FMModel get$stringTool.capitalizeFirstLetter(${clazz.tagName})() {
+ return ${clazz.tagName};
+ }
+#end
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/site/site.xml b/tiles-autotag/tiles-autotag-freemarker/src/site/site.xml
new file mode 100644
index 0000000..0a7d00d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java b/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java
new file mode 100644
index 0000000..6c41678
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMModelGeneratorTest.java
@@ -0,0 +1,142 @@
+/*
+ * $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.autotag.freemarker;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link TagClassGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FMModelGeneratorTest {
+
+ /**
+ * Test method for {@link TagClassGenerator#generate(File, String, TemplateSuite, TemplateClass, java.util.Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ VelocityEngine velocityEngine = new VelocityEngine(props);
+
+ FMModelGenerator generator = new FMModelGenerator(velocityEngine);
+ File file = File.createTempFile("autotag", null);
+ file.delete();
+ file.mkdir();
+ file.deleteOnExit();
+ TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs.");
+
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "int", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "boolean", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false);
+ param.setDocumentation("The body.");
+ params.add(param);
+ TemplateMethod executeMethod = new TemplateMethod("execute", params);
+
+ TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate",
+ "doStuff", "DoStuff", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuff class.");
+
+ generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null,
+ "org.apache.tiles.autotag.freemarker.test.Runtime");
+
+ InputStream expected = getClass()
+ .getResourceAsStream(
+ "/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat");
+ File effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.java");
+ assertTrue(effectiveFile.exists());
+ InputStream effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ suite.addTemplateClass(clazz);
+ params = new ArrayList<TemplateParameter>();
+ param = new TemplateParameter("one", "one", "java.lang.Double", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "float", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "java.util.Date", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ executeMethod = new TemplateMethod("execute", params);
+
+ clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate",
+ "doStuffNoBody", "DoStuffNoBody", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuffNoBody class.");
+
+ suite.addTemplateClass(clazz);
+
+ generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null,
+ "org.apache.tiles.autotag.freemarker.test.Runtime");
+
+ expected = getClass()
+ .getResourceAsStream(
+ "/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat");
+ effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.java");
+ assertTrue(effectiveFile.exists());
+ effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ FileUtils.deleteDirectory(file);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java b/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java
new file mode 100644
index 0000000..20369b1
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMModelRepositoryGeneratorTest.java
@@ -0,0 +1,128 @@
+/*
+ * $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.autotag.freemarker;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link TLDGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FMModelRepositoryGeneratorTest {
+
+ /**
+ * Test method for {@link FMModelRepositoryGenerator#generate(File, String, TemplateSuite, java.util.Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ VelocityEngine velocityEngine = new VelocityEngine(props);
+
+ FMModelRepositoryGenerator generator = new FMModelRepositoryGenerator(velocityEngine);
+ File file = File.createTempFile("autotag", null);
+ file.delete();
+ file.mkdir();
+ file.deleteOnExit();
+ TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs.");
+
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "int", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "long", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false);
+ param.setDocumentation("The body.");
+ params.add(param);
+ TemplateMethod executeMethod = new TemplateMethod("execute", params);
+
+ TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate",
+ "doStuff", "DoStuff", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuff class");
+
+ suite.addTemplateClass(clazz);
+ params = new ArrayList<TemplateParameter>();
+ param = new TemplateParameter("one", "one", "java.lang.Double", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "float", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "java.util.Date", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ executeMethod = new TemplateMethod("execute", params);
+
+ clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate",
+ "doStuffNoBody", "DoStuffNoBody", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuffNoBody class");
+
+ suite.addTemplateClass(clazz);
+
+ generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, null);
+
+ InputStream expected = getClass()
+ .getResourceAsStream(
+ "/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat");
+ File effectiveFile = new File(file, "/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.java");
+ assertTrue(effectiveFile.exists());
+ InputStream effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ FileUtils.deleteDirectory(file);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java b/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java
new file mode 100644
index 0000000..ea6b1ce
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/test/java/org/apache/tiles/autotag/freemarker/FMTemplateGeneratorFactoryTest.java
@@ -0,0 +1,62 @@
+/*
+ * $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.autotag.freemarker;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link FMTemplateGeneratorFactory}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FMTemplateGeneratorFactoryTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.autotag.freemarker.FMTemplateGeneratorFactory#createTemplateGenerator()}.
+ */
+ @Test
+ public void testCreateTemplateGenerator() {
+ File classesOutputDirectory = createMock(File.class);
+ VelocityEngine velocityEngine = createMock(VelocityEngine.class);
+ TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class);
+ TemplateGenerator generator = createMock(TemplateGenerator.class);
+
+ expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder);
+ expect(builder.addClassesTemplateSuiteGenerator(isA(FMModelRepositoryGenerator.class))).andReturn(builder);
+ expect(builder.addClassesTemplateClassGenerator(isA(FMModelGenerator.class))).andReturn(builder);
+ expect(builder.build()).andReturn(generator);
+
+ replay(classesOutputDirectory, velocityEngine, builder, generator);
+ FMTemplateGeneratorFactory factory = new FMTemplateGeneratorFactory(
+ classesOutputDirectory, velocityEngine, builder);
+ assertSame(generator, factory.createTemplateGenerator());
+ verify(classesOutputDirectory, velocityEngine, builder, generator);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat b/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat
new file mode 100644
index 0000000..73b7f8b
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffFMModel.javat
@@ -0,0 +1,57 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.freemarker.test;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+
+/**
+ * Documentation of the DoStuff class.
+ */
+public class DoStuffFMModel implements TemplateDirectiveModel {
+
+ /**
+ * The template model.
+ */
+ private org.apache.tiles.autotag.template.DoStuffTemplate model;
+
+ /**
+ * Constructor.
+ *
+ * @param model
+ * The template model.
+ */
+ public DoStuffFMModel(org.apache.tiles.autotag.template.DoStuffTemplate model) {
+ this.model = model;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
+ TemplateDirectiveBody body) throws TemplateException, IOException {
+ AutotagRuntime runtime = new org.apache.tiles.autotag.freemarker.test.Runtime();
+ if (runtime instanceof TemplateDirectiveModel) {
+ ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body);
+ }
+ Request request = runtime.createRequest();
+ ModelBody modelBody = runtime.createModelBody();
+ model.execute(
+ (java.lang.String) runtime.getParameter("one", null),
+ (java.lang.Integer) runtime.getParameter("two", 0),
+ (java.lang.Boolean) runtime.getParameter("three", false),
+ request, modelBody
+ );
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat b/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat
new file mode 100644
index 0000000..076eaab
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/DoStuffNoBodyFMModel.javat
@@ -0,0 +1,55 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.freemarker.test;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+
+/**
+ * Documentation of the DoStuffNoBody class.
+ */
+public class DoStuffNoBodyFMModel implements TemplateDirectiveModel {
+
+ /**
+ * The template model.
+ */
+ private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model;
+
+ /**
+ * Constructor.
+ *
+ * @param model
+ * The template model.
+ */
+ public DoStuffNoBodyFMModel(org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model) {
+ this.model = model;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
+ TemplateDirectiveBody body) throws TemplateException, IOException {
+ AutotagRuntime runtime = new org.apache.tiles.autotag.freemarker.test.Runtime();
+ if (runtime instanceof TemplateDirectiveModel) {
+ ((TemplateDirectiveModel) runtime).execute(env, params, loopVars, body);
+ }
+ Request request = runtime.createRequest();
+ model.execute(
+ (java.lang.Double) runtime.getParameter("one", null),
+ (java.lang.Float) runtime.getParameter("two", 0.0f),
+ (java.util.Date) runtime.getParameter("three", null),
+ request
+ );
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat b/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat
new file mode 100644
index 0000000..4fe08ee
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker/src/test/resources/org/apache/tiles/autotag/freemarker/test/TldtestFMModelRepository.javat
@@ -0,0 +1,46 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.freemarker.test;
+
+/**
+ * Test for TLD docs.
+ */
+public class TldtestFMModelRepository {
+
+ /**
+ * The "doStuff" directive.
+ */
+ private DoStuffFMModel doStuff;
+
+ /**
+ * The "doStuffNoBody" directive.
+ */
+ private DoStuffNoBodyFMModel doStuffNoBody;
+
+ /**
+ * Constructor.
+ */
+ public TilesFMModelRepository() {
+ doStuff = new DoStuffFMModel(new org.apache.tiles.autotag.template.DoStuffTemplate());
+ doStuffNoBody = new DoStuffNoBodyFMModel(new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate());
+ }
+
+ /**
+ * Returns the "doStuff" directive.
+ *
+ * @return The "doStuff" directive.
+ */
+ public DoStuffFMModel getDoStuff() {
+ return doStuff;
+ }
+
+ /**
+ * Returns the "doStuffNoBody" directive.
+ *
+ * @return The "doStuffNoBody" directive.
+ */
+ public DoStuffNoBodyFMModel getDoStuffNoBody() {
+ return doStuffNoBody;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/pom.xml b/tiles-autotag/tiles-autotag-jsp/pom.xml
new file mode 100644
index 0000000..f6e95a9
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-autotag</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-jsp</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles Autotag - JSP tags automatic generation</name>
+ <description>Generates JSP tags automatically from templates.</description>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java
new file mode 100644
index 0000000..166c376
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactory.java
@@ -0,0 +1,85 @@
+/*
+ * $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.autotag.jsp;
+
+import java.io.File;
+
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Creates a template generator to build JSP code around template models.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspTemplateGeneratorFactory implements TemplateGeneratorFactory {
+
+ /**
+ * Location of the file.
+ */
+ private File classesOutputDirectory;
+
+ /**
+ * Location of the file.
+ */
+ private File resourcesOutputDirectory;
+
+ /**
+ * The Velocity engine.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * The template generator builder.
+ */
+ private TemplateGeneratorBuilder templateGeneratorBuilder;
+
+ /**
+ * Constructor.
+ *
+ * @param classesOutputDirectory The directory where classes will be generated.
+ * @param resourcesOutputDirectory The directory where the TLD file will be generated.
+ * @param velocityEngine The Velocity engine.
+ * @param templateGeneratorBuilder The template generator builder.
+ */
+ public JspTemplateGeneratorFactory(File classesOutputDirectory,
+ File resourcesOutputDirectory, VelocityEngine velocityEngine,
+ TemplateGeneratorBuilder templateGeneratorBuilder) {
+ this.classesOutputDirectory = classesOutputDirectory;
+ this.resourcesOutputDirectory = resourcesOutputDirectory;
+ this.velocityEngine = velocityEngine;
+ this.templateGeneratorBuilder = templateGeneratorBuilder;
+ }
+
+ @Override
+ public TemplateGenerator createTemplateGenerator() {
+ return templateGeneratorBuilder
+ .setClassesOutputDirectory(classesOutputDirectory)
+ .setResourcesOutputDirectory(resourcesOutputDirectory)
+ .addResourcesTemplateSuiteGenerator(
+ new TLDGenerator(velocityEngine))
+ .addClassesTemplateClassGenerator(
+ new TagClassGenerator(velocityEngine)).build();
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.java
new file mode 100644
index 0000000..8ca3fad
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/TLDGenerator.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.autotag.jsp;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates the TLD file, using a template suite.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TLDGenerator extends AbstractTemplateSuiteGenerator {
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public TLDGenerator(VelocityEngine velocityEngine) {
+ super(velocityEngine);
+ }
+
+ @Override
+ protected String getTemplatePath(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return "/org/apache/tiles/autotag/jsp/tld.vm";
+ }
+
+ @Override
+ protected String getFilename(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return suite.getName() + "-jsp.tld";
+ }
+
+ @Override
+ protected String getDirectoryName(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return "META-INF/tld/";
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java
new file mode 100644
index 0000000..17b02bc
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/TagClassGenerator.java
@@ -0,0 +1,67 @@
+/*
+ * $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.autotag.jsp;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates a tag class using a template class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TagClassGenerator extends AbstractTemplateClassGenerator {
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public TagClassGenerator(VelocityEngine velocityEngine) {
+ super(velocityEngine);
+ }
+
+ @Override
+ protected String getDirectoryName(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return packageName.replaceAll("\\.", "/");
+ }
+
+ @Override
+ protected String getFilename(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return clazz.getTagClassPrefix() + "Tag.java";
+ }
+
+ @Override
+ protected String getTemplatePath(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return "/org/apache/tiles/autotag/jsp/bodyTag.vm";
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/package-info.java b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/package-info.java
new file mode 100644
index 0000000..e75b5c0
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/main/java/org/apache/tiles/autotag/jsp/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Autotag support for JavaServer Pages.
+ */
+package org.apache.tiles.autotag.jsp;
diff --git a/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm b/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm
new file mode 100644
index 0000000..b7d9ea1
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm
@@ -0,0 +1,106 @@
+#*
+ * $Id: tiles-jsp.tld 836180 2009-11-14 14:00:02Z 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.
+ *#/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package ${packageName};
+
+import java.io.IOException;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.SimpleTagSupport;
+
+#if(${clazz.hasBody()})
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+#end
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+
+/**
+#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation}))
+ * ${line}
+#end
+ */
+public class ${clazz.tagClassPrefix}Tag extends SimpleTagSupport {
+
+ /**
+ * The template model.
+ */
+ private ${clazz.name} model = new ${clazz.name}();
+
+#foreach($parameter in ${clazz.parameters})
+ /**
+#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation}))
+ * ${line}
+#end
+ */
+ private ${parameter.type} ${parameter.name};
+
+#end
+#foreach($parameter in ${clazz.parameters})
+ /**
+ * Getter for ${parameter.exportedName} property.
+ *
+ * @return
+#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation}))
+ * ${line}
+#end
+ */
+ public ${parameter.type} #if(${parameter.type} == 'boolean')is#{else}get#end${parameter.getterSetterSuffix}() {
+ return ${parameter.name};
+ }
+
+ /**
+ * Setter for ${parameter.exportedName} property.
+ *
+ * @param ${parameter.name}
+#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation}))
+ * ${line}
+#end
+ */
+ public void set${parameter.getterSetterSuffix}(${parameter.type} ${parameter.name}) {
+ this.${parameter.name} = ${parameter.name};
+ }
+
+#end
+ /** {@inheritDoc} */
+ @Override
+ public void doTag() throws JspException, IOException {
+ AutotagRuntime runtime = new ${runtimeClass}();
+ if (runtime instanceof SimpleTagSupport) {
+ SimpleTagSupport tag = (SimpleTagSupport) runtime;
+ tag.setJspContext(getJspContext());
+ tag.setJspBody(getJspBody());
+ tag.setParent(getParent());
+ tag.doTag();
+ }
+ Request request = runtime.createRequest();
+#if(${clazz.hasBody()})
+ ModelBody modelBody = runtime.createModelBody();
+#end
+ model.execute(
+#foreach($parameter in ${clazz.parameters})
+ ${parameter.name},
+#end
+ request#if(${clazz.hasBody()}), modelBody#end
+
+ );
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm b/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm
new file mode 100644
index 0000000..9d4c0e9
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/tld.vm
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+#*
+ * $Id: tiles-jsp.tld 836180 2009-11-14 14:00:02Z 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.
+ *#
+<!-- This file was automatically generated by Apache Tiles Autotag. -->
+<taglib
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
+ xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="2.1">
+ <description>
+ <![CDATA[
+#foreach($line in $stringTool.splitOnNewlines(${suite.documentation}))
+ $line
+#end
+ ]]>
+ </description>
+ <tlib-version>1.2</tlib-version>
+ <short-name>${suite.name}</short-name>
+ <uri>${parameters.taglibURI}</uri>
+#foreach($clazz in ${suite.getTemplateClasses()})
+ <tag>
+ <description>
+ <![CDATA[
+#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation}))
+ $line
+#end
+ ]]>
+ </description>
+ <name>${clazz.tagName}</name>
+ <tag-class>${packageName}.${clazz.tagClassPrefix}Tag</tag-class>
+ <body-content>#if(${clazz.hasBody()})scriptless#{else}empty#end</body-content>
+#foreach($parameter in ${clazz.parameters})
+ <attribute>
+ <description>
+ <![CDATA[
+#foreach($line in $stringTool.splitOnNewlines(${parameter.documentation}))
+ $line
+#end
+ ]]>
+ </description>
+ <name>${parameter.exportedName}</name>
+ <required>${parameter.required}</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>${parameter.type}</type>
+ </attribute>
+#end
+ </tag>
+#end
+</taglib>
diff --git a/tiles-autotag/tiles-autotag-jsp/src/site/site.xml b/tiles-autotag/tiles-autotag-jsp/src/site/site.xml
new file mode 100644
index 0000000..0a7d00d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java b/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java
new file mode 100644
index 0000000..8692c53
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/JspTemplateGeneratorFactoryTest.java
@@ -0,0 +1,65 @@
+/*
+ * $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.autotag.jsp;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link JspTemplateGeneratorFactory}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspTemplateGeneratorFactoryTest {
+
+ /**
+ * Test method for {@link JspTemplateGeneratorFactory#createTemplateGenerator()}.
+ */
+ @Test
+ public void testCreateTemplateGenerator() {
+ File classesOutputDirectory = createMock(File.class);
+ File resourcesOutputDirectory = createMock(File.class);
+ VelocityEngine velocityEngine = createMock(VelocityEngine.class);
+ TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class);
+ TemplateGenerator generator = createMock(TemplateGenerator.class);
+
+ expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder);
+ expect(builder.setResourcesOutputDirectory(resourcesOutputDirectory)).andReturn(builder);
+ expect(builder.addResourcesTemplateSuiteGenerator(isA(TLDGenerator.class))).andReturn(builder);
+ expect(builder.addClassesTemplateClassGenerator(isA(TagClassGenerator.class))).andReturn(builder);
+ expect(builder.build()).andReturn(generator);
+
+ replay(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator);
+ JspTemplateGeneratorFactory factory = new JspTemplateGeneratorFactory(
+ classesOutputDirectory, resourcesOutputDirectory,
+ velocityEngine, builder);
+ assertSame(generator, factory.createTemplateGenerator());
+ verify(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java b/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java
new file mode 100644
index 0000000..2485c6f
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/TLDGeneratorTest.java
@@ -0,0 +1,130 @@
+/*
+ * $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.autotag.jsp;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link TLDGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TLDGeneratorTest {
+
+ /**
+ * Test method for {@link TLDGenerator#generate(File, String, TemplateSuite, Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ VelocityEngine velocityEngine = new VelocityEngine(props);
+
+ TLDGenerator generator = new TLDGenerator(velocityEngine);
+ File file = File.createTempFile("autotag", null);
+ file.delete();
+ file.mkdir();
+ file.deleteOnExit();
+ TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs.");
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("taglibURI", "http://www.initrode.net/tags/test");
+
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "int", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "long", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false);
+ param.setDocumentation("The body.");
+ params.add(param);
+ TemplateMethod executeMethod = new TemplateMethod("execute", params);
+
+ TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate",
+ "doStuff", "DoStuff", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuff class");
+
+ suite.addTemplateClass(clazz);
+ params = new ArrayList<TemplateParameter>();
+ param = new TemplateParameter("one", "one", "java.lang.Double", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "float", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "java.util.Date", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ executeMethod = new TemplateMethod("execute", params);
+
+ clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate",
+ "doStuffNoBody", "DoStuffNoBody", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuffNoBody class");
+
+ suite.addTemplateClass(clazz);
+
+ generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, parameters);
+
+ InputStream expected = getClass().getResourceAsStream("/tldtest-jsp.tld");
+ File effectiveFile = new File(file, "META-INF/tld/tldtest-jsp.tld");
+ assertTrue(effectiveFile.exists());
+ InputStream effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ FileUtils.deleteDirectory(file);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java b/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java
new file mode 100644
index 0000000..cbf2245
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/test/java/org/apache/tiles/autotag/jsp/TagClassGeneratorTest.java
@@ -0,0 +1,142 @@
+/*
+ * $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.autotag.jsp;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link TagClassGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TagClassGeneratorTest {
+
+ /**
+ * Test method for {@link TagClassGenerator#generate(File, String, TemplateSuite, TemplateClass, Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ VelocityEngine velocityEngine = new VelocityEngine(props);
+
+ TagClassGenerator generator = new TagClassGenerator(velocityEngine);
+ File file = File.createTempFile("autotag", null);
+ file.delete();
+ file.mkdir();
+ file.deleteOnExit();
+ TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs.");
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("taglibURI", "http://www.initrode.net/tags/test");
+
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "int", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "boolean", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false);
+ param.setDocumentation("The body.");
+ params.add(param);
+ TemplateMethod executeMethod = new TemplateMethod("execute", params);
+
+ TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate",
+ "doStuff", "DoStuff", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuff class.");
+
+ generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters,
+ "org.apache.tiles.autotag.jsp.test.Runtime");
+
+ InputStream expected = getClass().getResourceAsStream("/org/apache/tiles/autotag/jsp/test/DoStuffTag.java");
+ File effectiveFile = new File(file, "/org/apache/tiles/autotag/jsp/test/DoStuffTag.java");
+ assertTrue(effectiveFile.exists());
+ InputStream effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ suite.addTemplateClass(clazz);
+ params = new ArrayList<TemplateParameter>();
+ param = new TemplateParameter("one", "one", "java.lang.Double", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "float", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "java.util.Date", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ executeMethod = new TemplateMethod("execute", params);
+
+ clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate",
+ "doStuffNoBody", "DoStuffNoBody", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuffNoBody class.");
+
+ suite.addTemplateClass(clazz);
+
+ generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters,
+ "org.apache.tiles.autotag.jsp.test.Runtime");
+
+ expected = getClass().getResourceAsStream("/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java");
+ effectiveFile = new File(file, "/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java");
+ assertTrue(effectiveFile.exists());
+ effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ FileUtils.deleteDirectory(file);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java b/tiles-autotag/tiles-autotag-jsp/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java
new file mode 100644
index 0000000..e5189c8
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffNoBodyTag.java
@@ -0,0 +1,118 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.jsp.test;
+
+import java.io.IOException;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.SimpleTagSupport;
+
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+
+/**
+ * Documentation of the DoStuffNoBody class.
+ */
+public class DoStuffNoBodyTag extends SimpleTagSupport {
+
+ /**
+ * The template model.
+ */
+ private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model = new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate();
+
+ /**
+ * Parameter one.
+ */
+ private java.lang.Double one;
+
+ /**
+ * Parameter two.
+ */
+ private float two;
+
+ /**
+ * Parameter three.
+ */
+ private java.util.Date three;
+
+ /**
+ * Getter for one property.
+ *
+ * @return
+ * Parameter one.
+ */
+ public java.lang.Double getOne() {
+ return one;
+ }
+
+ /**
+ * Setter for one property.
+ *
+ * @param one
+ * Parameter one.
+ */
+ public void setOne(java.lang.Double one) {
+ this.one = one;
+ }
+
+ /**
+ * Getter for two property.
+ *
+ * @return
+ * Parameter two.
+ */
+ public float getTwo() {
+ return two;
+ }
+
+ /**
+ * Setter for two property.
+ *
+ * @param two
+ * Parameter two.
+ */
+ public void setTwo(float two) {
+ this.two = two;
+ }
+
+ /**
+ * Getter for three property.
+ *
+ * @return
+ * Parameter three.
+ */
+ public java.util.Date getThree() {
+ return three;
+ }
+
+ /**
+ * Setter for three property.
+ *
+ * @param three
+ * Parameter three.
+ */
+ public void setThree(java.util.Date three) {
+ this.three = three;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void doTag() throws JspException, IOException {
+ AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.test.Runtime();
+ if (runtime instanceof SimpleTagSupport) {
+ SimpleTagSupport tag = (SimpleTagSupport) runtime;
+ tag.setJspContext(getJspContext());
+ tag.setJspBody(getJspBody());
+ tag.setParent(getParent());
+ tag.doTag();
+ }
+ Request request = runtime.createRequest();
+ model.execute(
+ one,
+ two,
+ three,
+ request
+ );
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java b/tiles-autotag/tiles-autotag-jsp/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java
new file mode 100644
index 0000000..796b838
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/test/resources/org/apache/tiles/autotag/jsp/test/DoStuffTag.java
@@ -0,0 +1,120 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.jsp.test;
+
+import java.io.IOException;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.SimpleTagSupport;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+
+/**
+ * Documentation of the DoStuff class.
+ */
+public class DoStuffTag extends SimpleTagSupport {
+
+ /**
+ * The template model.
+ */
+ private org.apache.tiles.autotag.template.DoStuffTemplate model = new org.apache.tiles.autotag.template.DoStuffTemplate();
+
+ /**
+ * Parameter one.
+ */
+ private java.lang.String one;
+
+ /**
+ * Parameter two.
+ */
+ private int two;
+
+ /**
+ * Parameter three.
+ */
+ private boolean three;
+
+ /**
+ * Getter for one property.
+ *
+ * @return
+ * Parameter one.
+ */
+ public java.lang.String getOne() {
+ return one;
+ }
+
+ /**
+ * Setter for one property.
+ *
+ * @param one
+ * Parameter one.
+ */
+ public void setOne(java.lang.String one) {
+ this.one = one;
+ }
+
+ /**
+ * Getter for two property.
+ *
+ * @return
+ * Parameter two.
+ */
+ public int getTwo() {
+ return two;
+ }
+
+ /**
+ * Setter for two property.
+ *
+ * @param two
+ * Parameter two.
+ */
+ public void setTwo(int two) {
+ this.two = two;
+ }
+
+ /**
+ * Getter for three property.
+ *
+ * @return
+ * Parameter three.
+ */
+ public boolean isThree() {
+ return three;
+ }
+
+ /**
+ * Setter for three property.
+ *
+ * @param three
+ * Parameter three.
+ */
+ public void setThree(boolean three) {
+ this.three = three;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void doTag() throws JspException, IOException {
+ AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.test.Runtime();
+ if (runtime instanceof SimpleTagSupport) {
+ SimpleTagSupport tag = (SimpleTagSupport) runtime;
+ tag.setJspContext(getJspContext());
+ tag.setJspBody(getJspBody());
+ tag.setParent(getParent());
+ tag.doTag();
+ }
+ Request request = runtime.createRequest();
+ ModelBody modelBody = runtime.createModelBody();
+ model.execute(
+ one,
+ two,
+ three,
+ request, modelBody
+ );
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-jsp/src/test/resources/tldtest-jsp.tld b/tiles-autotag/tiles-autotag-jsp/src/test/resources/tldtest-jsp.tld
new file mode 100644
index 0000000..2db4ddc
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp/src/test/resources/tldtest-jsp.tld
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This file was automatically generated by Apache Tiles Autotag. -->
+<taglib
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
+ xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ version="2.1">
+ <description>
+ <![CDATA[
+ Test for TLD docs.
+ ]]>
+ </description>
+ <tlib-version>1.2</tlib-version>
+ <short-name>tldtest</short-name>
+ <uri>http://www.initrode.net/tags/test</uri>
+ <tag>
+ <description>
+ <![CDATA[
+ Documentation of the DoStuff class
+ ]]>
+ </description>
+ <name>doStuff</name>
+ <tag-class>org.apache.tiles.autotag.jsp.test.DoStuffTag</tag-class>
+ <body-content>scriptless</body-content>
+ <attribute>
+ <description>
+ <![CDATA[
+ Parameter one.
+ ]]>
+ </description>
+ <name>one</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.String</type>
+ </attribute>
+ <attribute>
+ <description>
+ <![CDATA[
+ Parameter two.
+ ]]>
+ </description>
+ <name>two</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>int</type>
+ </attribute>
+ <attribute>
+ <description>
+ <![CDATA[
+ Parameter three.
+ ]]>
+ </description>
+ <name>three</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>long</type>
+ </attribute>
+ </tag>
+ <tag>
+ <description>
+ <![CDATA[
+ Documentation of the DoStuffNoBody class
+ ]]>
+ </description>
+ <name>doStuffNoBody</name>
+ <tag-class>org.apache.tiles.autotag.jsp.test.DoStuffNoBodyTag</tag-class>
+ <body-content>empty</body-content>
+ <attribute>
+ <description>
+ <![CDATA[
+ Parameter one.
+ ]]>
+ </description>
+ <name>one</name>
+ <required>true</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.lang.Double</type>
+ </attribute>
+ <attribute>
+ <description>
+ <![CDATA[
+ Parameter two.
+ ]]>
+ </description>
+ <name>two</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>float</type>
+ </attribute>
+ <attribute>
+ <description>
+ <![CDATA[
+ Parameter three.
+ ]]>
+ </description>
+ <name>three</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+ <type>java.util.Date</type>
+ </attribute>
+ </tag>
+</taglib>
diff --git a/tiles-autotag/tiles-autotag-velocity/pom.xml b/tiles-autotag/tiles-autotag-velocity/pom.xml
new file mode 100644
index 0000000..d0399ca
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-autotag</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-velocity</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Autotag - Velocity support</name>
+ <description>Module to generate Velocity code to use tag models.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java
new file mode 100644
index 0000000..8493fc3
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGenerator.java
@@ -0,0 +1,67 @@
+/*
+ * $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.autotag.velocity;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.AbstractTemplateClassGenerator;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates a Velocity directive using a template class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityDirectiveGenerator extends AbstractTemplateClassGenerator {
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public VelocityDirectiveGenerator(VelocityEngine velocityEngine) {
+ super(velocityEngine);
+ }
+
+ @Override
+ protected String getDirectoryName(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return packageName.replaceAll("\\.", "/");
+ }
+
+ @Override
+ protected String getFilename(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return clazz.getTagClassPrefix() + "Directive.java";
+ }
+
+ @Override
+ protected String getTemplatePath(File directory, String packageName,
+ TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+ String runtimeClass) {
+ return "/org/apache/tiles/autotag/velocity/velocityDirective.vm";
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.java
new file mode 100644
index 0000000..a9a8619
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGenerator.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.autotag.velocity;
+
+import java.io.File;
+import java.util.Map;
+
+import org.apache.tiles.autotag.generate.AbstractTemplateSuiteGenerator;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Generates a Velocity properties containing the list of generated user directives for future use.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityPropertiesGenerator extends AbstractTemplateSuiteGenerator {
+
+ /**
+ * Constructor.
+ *
+ * @param velocityEngine The Velocity engine.
+ */
+ public VelocityPropertiesGenerator(VelocityEngine velocityEngine) {
+ super(velocityEngine);
+ }
+
+ @Override
+ protected String getTemplatePath(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return "/org/apache/tiles/autotag/velocity/velocityProperties.vm";
+ }
+
+ @Override
+ protected String getFilename(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return "velocity.properties";
+ }
+
+ @Override
+ protected String getDirectoryName(File directory, String packageName,
+ TemplateSuite suite, Map<String, String> parameters) {
+ return "META-INF/";
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java
new file mode 100644
index 0000000..02f0f14
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactory.java
@@ -0,0 +1,87 @@
+/*
+ * $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.autotag.velocity;
+
+import java.io.File;
+
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.tiles.autotag.generate.TemplateGeneratorFactory;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * Creates a template generator that generates code to build Velocity code
+ * around template classes.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityTemplateGeneratorFactory implements
+ TemplateGeneratorFactory {
+
+ /**
+ * Location of the file.
+ */
+ private File classesOutputDirectory;
+
+ /**
+ * Location of the file.
+ */
+ private File resourcesOutputDirectory;
+
+ /**
+ * The Velocity engine.
+ */
+ private VelocityEngine velocityEngine;
+
+ /**
+ * The template generator builder.
+ */
+ private TemplateGeneratorBuilder templateGeneratorBuilder;
+
+ /**
+ * Constructor.
+ *
+ * @param classesOutputDirectory The directory where classes will be generated.
+ * @param resourcesOutputDirectory The directory where velocity.properties will be written.
+ * @param velocityEngine The Velocity engine.
+ * @param templateGeneratorBuilder The template generator builder.
+ */
+ public VelocityTemplateGeneratorFactory(File classesOutputDirectory,
+ File resourcesOutputDirectory, VelocityEngine velocityEngine,
+ TemplateGeneratorBuilder templateGeneratorBuilder) {
+ this.classesOutputDirectory = classesOutputDirectory;
+ this.resourcesOutputDirectory = resourcesOutputDirectory;
+ this.velocityEngine = velocityEngine;
+ this.templateGeneratorBuilder = templateGeneratorBuilder;
+ }
+
+ @Override
+ public TemplateGenerator createTemplateGenerator() {
+ return templateGeneratorBuilder
+ .setClassesOutputDirectory(classesOutputDirectory)
+ .setResourcesOutputDirectory(resourcesOutputDirectory)
+ .addResourcesTemplateSuiteGenerator(
+ new VelocityPropertiesGenerator(velocityEngine))
+ .addClassesTemplateClassGenerator(
+ new VelocityDirectiveGenerator(velocityEngine)).build();
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/package-info.java b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/package-info.java
new file mode 100644
index 0000000..a2c9d18
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/main/java/org/apache/tiles/autotag/velocity/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Autotag support for Velocity.
+ */
+package org.apache.tiles.autotag.velocity;
diff --git a/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm b/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm
new file mode 100644
index 0000000..f0bef91
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm
@@ -0,0 +1,82 @@
+#*
+ * $Id: tiles-jsp.tld 836180 2009-11-14 14:00:02Z 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.
+ *#/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package ${packageName};
+
+import java.io.IOException;
+import java.io.Writer;
+
+#if(${clazz.hasBody()})
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+#end
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.directive.Directive;
+import org.apache.velocity.runtime.parser.node.Node;
+
+/**
+#foreach($line in $stringTool.splitOnNewlines(${clazz.documentation}))
+ * ${line}
+#end
+ */
+public class ${clazz.tagClassPrefix}Directive extends Directive {
+
+ /**
+ * The template model.
+ */
+ private ${clazz.name} model = new ${clazz.name}();
+
+ /** {@inheritDoc} */
+ @Override
+ public String getName() {
+ return "${suite.name}_${clazz.tagName}";
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getType() {
+ return #if(${clazz.hasBody()})BLOCK#{else}LINE#{end};
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean render(InternalContextAdapter context, Writer writer, Node node)
+ throws IOException {
+ AutotagRuntime runtime = new ${runtimeClass}();
+ if (runtime instanceof Directive) {
+ ((Directive) runtime).render(context, writer, node);
+ }
+ Request request = runtime.createRequest();
+#if(${clazz.hasBody()})
+ ModelBody modelBody = runtime.createModelBody();
+#end
+ model.execute(
+#foreach($parameter in ${clazz.parameters})
+ ($stringTool.getClassToCast(${parameter.type})) runtime.getParameter("${parameter.exportedName}", $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})),
+#end
+ request#if(${clazz.hasBody()}), modelBody#end
+
+ );
+ return true;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm b/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm
new file mode 100644
index 0000000..4fc1bb7
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityProperties.vm
@@ -0,0 +1,22 @@
+#*
+ * $Id: tiles-jsp.tld 836180 2009-11-14 14:00:02Z 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.
+ *## This file was automatically generated by Apache Tiles Autotag.
+userdirective=#foreach($clazz in ${suite.getTemplateClasses()})#if($velocityCount > 1),\
+ #{end}${packageName}.${clazz.tagClassPrefix}Directive#end
diff --git a/tiles-autotag/tiles-autotag-velocity/src/site/site.xml b/tiles-autotag/tiles-autotag-velocity/src/site/site.xml
new file mode 100644
index 0000000..0a7d00d
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Tiles Autotags">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Tiles Autotag"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java b/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java
new file mode 100644
index 0000000..9806199
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityDirectiveGeneratorTest.java
@@ -0,0 +1,143 @@
+/*
+ * $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.autotag.velocity;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityDirectiveGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityDirectiveGeneratorTest {
+
+ /**
+ * Test method for
+ * {@link VelocityDirectiveGenerator#generate(File, String, TemplateSuite, TemplateClass, java.util.Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ VelocityEngine velocityEngine = new VelocityEngine(props);
+
+ VelocityDirectiveGenerator generator = new VelocityDirectiveGenerator(velocityEngine);
+ File file = File.createTempFile("autotag", null);
+ file.delete();
+ file.mkdir();
+ file.deleteOnExit();
+ TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs.");
+
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "int", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "boolean", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false);
+ param.setDocumentation("The body.");
+ params.add(param);
+ TemplateMethod executeMethod = new TemplateMethod("execute", params);
+
+ TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate",
+ "doStuff", "DoStuff", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuff class.");
+
+ generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null,
+ "org.apache.tiles.autotag.velocity.test.Runtime");
+
+ InputStream expected = getClass()
+ .getResourceAsStream(
+ "/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat");
+ File effectiveFile = new File(file, "/org/apache/tiles/autotag/velocity/test/DoStuffDirective.java");
+ assertTrue(effectiveFile.exists());
+ InputStream effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ suite.addTemplateClass(clazz);
+ params = new ArrayList<TemplateParameter>();
+ param = new TemplateParameter("one", "one", "java.lang.Double", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "float", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "java.util.Date", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ executeMethod = new TemplateMethod("execute", params);
+
+ clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate",
+ "doStuffNoBody", "DoStuffNoBody", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuffNoBody class.");
+
+ suite.addTemplateClass(clazz);
+
+ generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null,
+ "org.apache.tiles.autotag.velocity.test.Runtime");
+
+ expected = getClass()
+ .getResourceAsStream(
+ "/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat");
+ effectiveFile = new File(file, "/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.java");
+ assertTrue(effectiveFile.exists());
+ effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ FileUtils.deleteDirectory(file);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java b/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java
new file mode 100644
index 0000000..f8b5f92
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityPropertiesGeneratorTest.java
@@ -0,0 +1,128 @@
+/*
+ * $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.autotag.velocity;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.model.TemplateClass;
+import org.apache.tiles.autotag.model.TemplateMethod;
+import org.apache.tiles.autotag.model.TemplateParameter;
+import org.apache.tiles.autotag.model.TemplateSuite;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityPropertiesGenerator}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityPropertiesGeneratorTest {
+
+ /**
+ * Test method for
+ * {@link org.apache.tiles.autotag.velocity.VelocityPropertiesGenerator
+ * #generate(File, String, TemplateSuite, java.util.Map)}.
+ * @throws Exception If something goes wrong.
+ */
+ @Test
+ public void testGenerate() throws Exception {
+ Properties props = new Properties();
+ InputStream propsStream = getClass().getResourceAsStream("/org/apache/tiles/autotag/velocity.properties");
+ props.load(propsStream);
+ propsStream.close();
+ VelocityEngine velocityEngine = new VelocityEngine(props);
+
+ VelocityPropertiesGenerator generator = new VelocityPropertiesGenerator(velocityEngine);
+ File file = File.createTempFile("autotag", null);
+ file.delete();
+ file.mkdir();
+ file.deleteOnExit();
+ TemplateSuite suite = new TemplateSuite("tldtest", "Test for TLD docs.");
+
+ List<TemplateParameter> params = new ArrayList<TemplateParameter>();
+ TemplateParameter param = new TemplateParameter("one", "one", "java.lang.String", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "int", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "long", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ param = new TemplateParameter("modelBody", "modelBody", ModelBody.class.getName(), null, false);
+ param.setDocumentation("The body.");
+ params.add(param);
+ TemplateMethod executeMethod = new TemplateMethod("execute", params);
+
+ TemplateClass clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffTemplate",
+ "doStuff", "DoStuff", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuff class");
+
+ suite.addTemplateClass(clazz);
+ params = new ArrayList<TemplateParameter>();
+ param = new TemplateParameter("one", "one", "java.lang.Double", null, true);
+ param.setDocumentation("Parameter one.");
+ params.add(param);
+ param = new TemplateParameter("two", "two", "float", null, false);
+ param.setDocumentation("Parameter two.");
+ params.add(param);
+ param = new TemplateParameter("three", "three", "java.util.Date", null, false);
+ param.setDocumentation("Parameter three.");
+ params.add(param);
+ param = new TemplateParameter("request", "request", Request.class.getName(), null, false);
+ param.setDocumentation("The request.");
+ params.add(param);
+ executeMethod = new TemplateMethod("execute", params);
+
+ clazz = new TemplateClass("org.apache.tiles.autotag.template.DoStuffNoBodyTemplate",
+ "doStuffNoBody", "DoStuffNoBody", executeMethod);
+ clazz.setDocumentation("Documentation of the DoStuffNoBody class");
+
+ suite.addTemplateClass(clazz);
+
+ generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, null);
+
+ InputStream expected = getClass().getResourceAsStream("/velocity.properties.test");
+ File effectiveFile = new File(file, "META-INF/velocity.properties");
+ assertTrue(effectiveFile.exists());
+ InputStream effective = new FileInputStream(effectiveFile);
+ assertTrue(IOUtils.contentEquals(effective, expected));
+ effective.close();
+ expected.close();
+
+ FileUtils.deleteDirectory(file);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java b/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java
new file mode 100644
index 0000000..a17ffd8
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/test/java/org/apache/tiles/autotag/velocity/VelocityTemplateGeneratorFactoryTest.java
@@ -0,0 +1,65 @@
+/*
+ * $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.autotag.velocity;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import org.apache.tiles.autotag.generate.TemplateGenerator;
+import org.apache.tiles.autotag.generate.TemplateGeneratorBuilder;
+import org.apache.velocity.app.VelocityEngine;
+import org.junit.Test;
+
+/**
+ * Tests {@link JspTemplateGeneratorFactory}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityTemplateGeneratorFactoryTest {
+
+ /**
+ * Test method for {@link JspTemplateGeneratorFactory#createTemplateGenerator()}.
+ */
+ @Test
+ public void testCreateTemplateGenerator() {
+ File classesOutputDirectory = createMock(File.class);
+ File resourcesOutputDirectory = createMock(File.class);
+ VelocityEngine velocityEngine = createMock(VelocityEngine.class);
+ TemplateGeneratorBuilder builder = createMock(TemplateGeneratorBuilder.class);
+ TemplateGenerator generator = createMock(TemplateGenerator.class);
+
+ expect(builder.setClassesOutputDirectory(classesOutputDirectory)).andReturn(builder);
+ expect(builder.setResourcesOutputDirectory(resourcesOutputDirectory)).andReturn(builder);
+ expect(builder.addResourcesTemplateSuiteGenerator(isA(VelocityPropertiesGenerator.class))).andReturn(builder);
+ expect(builder.addClassesTemplateClassGenerator(isA(VelocityDirectiveGenerator.class))).andReturn(builder);
+ expect(builder.build()).andReturn(generator);
+
+ replay(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator);
+ VelocityTemplateGeneratorFactory factory = new VelocityTemplateGeneratorFactory(
+ classesOutputDirectory, resourcesOutputDirectory,
+ velocityEngine, builder);
+ assertSame(generator, factory.createTemplateGenerator());
+ verify(classesOutputDirectory, resourcesOutputDirectory, velocityEngine, builder, generator);
+ }
+
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat b/tiles-autotag/tiles-autotag-velocity/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat
new file mode 100644
index 0000000..5caf980
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffDirective.javat
@@ -0,0 +1,56 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.velocity.test;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.directive.Directive;
+import org.apache.velocity.runtime.parser.node.Node;
+
+/**
+ * Documentation of the DoStuff class.
+ */
+public class DoStuffDirective extends Directive {
+
+ /**
+ * The template model.
+ */
+ private org.apache.tiles.autotag.template.DoStuffTemplate model = new org.apache.tiles.autotag.template.DoStuffTemplate();
+
+ /** {@inheritDoc} */
+ @Override
+ public String getName() {
+ return "tldtest_doStuff";
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getType() {
+ return BLOCK;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean render(InternalContextAdapter context, Writer writer, Node node)
+ throws IOException {
+ AutotagRuntime runtime = new org.apache.tiles.autotag.velocity.test.Runtime();
+ if (runtime instanceof Directive) {
+ ((Directive) runtime).render(context, writer, node);
+ }
+ Request request = runtime.createRequest();
+ ModelBody modelBody = runtime.createModelBody();
+ model.execute(
+ (java.lang.String) runtime.getParameter("one", null),
+ (java.lang.Integer) runtime.getParameter("two", 0),
+ (java.lang.Boolean) runtime.getParameter("three", false),
+ request, modelBody
+ );
+ return true;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat b/tiles-autotag/tiles-autotag-velocity/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat
new file mode 100644
index 0000000..88c9919
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/test/resources/org/apache/tiles/autotag/velocity/test/DoStuffNoBodyDirective.javat
@@ -0,0 +1,54 @@
+/*
+ * This file was automatically generated by Apache Tiles Autotag.
+ */
+package org.apache.tiles.autotag.velocity.test;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.directive.Directive;
+import org.apache.velocity.runtime.parser.node.Node;
+
+/**
+ * Documentation of the DoStuffNoBody class.
+ */
+public class DoStuffNoBodyDirective extends Directive {
+
+ /**
+ * The template model.
+ */
+ private org.apache.tiles.autotag.template.DoStuffNoBodyTemplate model = new org.apache.tiles.autotag.template.DoStuffNoBodyTemplate();
+
+ /** {@inheritDoc} */
+ @Override
+ public String getName() {
+ return "tldtest_doStuffNoBody";
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getType() {
+ return LINE;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean render(InternalContextAdapter context, Writer writer, Node node)
+ throws IOException {
+ AutotagRuntime runtime = new org.apache.tiles.autotag.velocity.test.Runtime();
+ if (runtime instanceof Directive) {
+ ((Directive) runtime).render(context, writer, node);
+ }
+ Request request = runtime.createRequest();
+ model.execute(
+ (java.lang.Double) runtime.getParameter("one", null),
+ (java.lang.Float) runtime.getParameter("two", 0.0f),
+ (java.util.Date) runtime.getParameter("three", null),
+ request
+ );
+ return true;
+ }
+}
diff --git a/tiles-autotag/tiles-autotag-velocity/src/test/resources/velocity.properties.test b/tiles-autotag/tiles-autotag-velocity/src/test/resources/velocity.properties.test
new file mode 100644
index 0000000..4d4051a
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity/src/test/resources/velocity.properties.test
@@ -0,0 +1,3 @@
+# This file was automatically generated by Apache Tiles Autotag.
+userdirective=org.apache.tiles.autotag.velocity.test.DoStuffDirective,\
+ org.apache.tiles.autotag.velocity.test.DoStuffNoBodyDirective
\ No newline at end of file
diff --git a/tiles-request/pom.xml b/tiles-request/pom.xml
new file mode 100644
index 0000000..cb10f74
--- /dev/null
+++ b/tiles-request/pom.xml
@@ -0,0 +1,375 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-master</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>4</version>
+ <relativePath/>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Tiles Request Framework</name>
+ <description>Request abstraction for various request and template technologies</description>
+ <url>http://tiles.apache.org/tiles-request/</url>
+ <scm>
+ <connection>scm:svn:http://svn.eu.apache.org/repos/asf/tiles/framework/trunk/tiles-request/</connection>
+ <developerConnection>scm:svn:https://svn.eu.apache.org/repos/asf/tiles/framework/trunk/tiles-request/</developerConnection>
+ <url>http://svn.eu.apache.org/viewvc/tiles/framework/trunk/tiles-request/</url>
+ </scm>
+ <issueManagement>
+ <system>JIRA</system>
+ <url>https://issues.apache.org/jira/browse/TREQ</url>
+ </issueManagement>
+
+ <modules>
+ <module>tiles-request-api</module>
+ <module>tiles-request-servlet</module>
+ <module>tiles-request-servlet-wildcard</module>
+ <module>tiles-request-portlet</module>
+ <module>tiles-request-portlet-wildcard</module>
+ <module>tiles-request-jsp</module>
+ <module>tiles-request-freemarker</module>
+ <module>tiles-request-velocity</module>
+ <module>tiles-request-mustache</module>
+ </modules>
+ <distributionManagement>
+ <site>
+ <id>apache-site</id>
+ <url>scp://people.apache.org/www/tiles.apache.org/tiles-request</url>
+ </site>
+ </distributionManagement>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <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>2.3.7</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>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <releaseProfiles>apache-release</releaseProfiles><!-- xxx tiles still uses "release" instead of "apache-release" -->
+ <goals>deploy site-deploy</goals>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ <defaultGoal>install</defaultGoal>
+ </build>
+
+ <properties>
+ <tiles.osgi.symbolicName>org.apache.${project.artifactId}</tiles.osgi.symbolicName>
+ <tiles.osgi.export>org.apache.tiles.*;version=${project.version}</tiles.osgi.export>
+ <tiles.osgi.import>*</tiles.osgi.import>
+ <tiles.osgi.dynamicImport />
+ <tiles.osgi.private />
+ <tiles.manifestfile>target/osgi/MANIFEST.MF</tiles.manifestfile>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-portlet</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>1.5.8</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>3.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shale</groupId>
+ <artifactId>shale-test</artifactId>
+ <version>1.0.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>1.5.8</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>2.5.6</version>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc-portlet</artifactId>
+ <version>2.5.6</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <version>2.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-tools</artifactId>
+ <version>2.0</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>struts-taglib</artifactId>
+ <groupId>org.apache.struts</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>struts-tiles</artifactId>
+ <groupId>org.apache.struts</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>struts-core</artifactId>
+ <groupId>org.apache.struts</groupId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>sslext</artifactId>
+ <groupId>sslext</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-chain</artifactId>
+ <groupId>commons-chain</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-validator</artifactId>
+ <groupId>commons-validator</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-digester</artifactId>
+ <groupId>commons-digester</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-beanutils</artifactId>
+ <groupId>commons-beanutils</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>dom4j</artifactId>
+ <groupId>dom4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>2.3.15</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.spullara.mustache.java</groupId>
+ <artifactId>core</artifactId>
+ <version>0.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.spullara.mustache.java</groupId>
+ <artifactId>builder</artifactId>
+ <version>0.6.2</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <profiles>
+ <profile>
+ <id>apache-release</id>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <createChecksum>true</createChecksum>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ <version>1.0-alpha-3</version>
+ <executions>
+ <execution>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <addDefaultLicenseMatchers>false</addDefaultLicenseMatchers>
+ <licenseMatchers>
+ <classNames>
+ <className>rat.analysis.license.ApacheSoftwareLicense20</className>
+ </classNames>
+ </licenseMatchers>
+ <includes>
+ <include>pom.xml</include>
+ <include>src/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/*LICENSE.txt</exclude>
+ <exclude>**/*MANIFEST.MF</exclude>
+ </excludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>linkcheck</id>
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-linkcheck-plugin</artifactId>
+ <version>1.1</version>
+ <configuration>
+ <excludedLinks>
+ <excludedLink>**/index.html</excludedLink>
+ <excludedLink>**/logo.png</excludedLink>
+ </excludedLinks>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+
+ </profile>
+ </profiles>
+
+</project>
diff --git a/tiles-request/src/site/apt/dev/release.apt b/tiles-request/src/site/apt/dev/release.apt
new file mode 100644
index 0000000..ab9bd52
--- /dev/null
+++ b/tiles-request/src/site/apt/dev/release.apt
@@ -0,0 +1,351 @@
+~~ $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.
+~~
+ -----------
+ Release Process
+ -----------
+
+Tiles Release Process
+
+ Here you will find the steps to create releases for Tiles.
+
+Prerequisites
+
+ To create a release you have to install:
+
+ * {{{http://java.sun.com/javase/6}Java 6.0}}. If you are using a newer
+ version of Java, it is suggested to <<change JAVA_HOME environment variable>>
+ when calling Maven, so it points to an instance of Java 6.0;
+
+ * {{{http://maven.apache.org/}Maven 2.2 or 3}};
+
+ * {{{http://www.gnupg.org/}GnuPG}};
+
+ * {{{http://www.openssh.com/}OpenSSH}};
+
+ * {{{http://www.graphviz.org/}GraphViz}};
+
+One-time operations
+
+ These operations need to be performed only one time.
+
+* Create and publish your GPG key
+
+ To create a GPG key, follow the
+ {{{http://www.apache.org/dev/openpgp.html}guidelines}}.
+ Include it in:
+
+-------------------------------------
+https://svn.apache.org/repos/asf/tiles/site/KEYS
+-------------------------------------
+
+ Publish your GPG key in a PGP key server, such as
+ {{{http://pgp.mit.edu/} MIT Keyserver}}.
+
+* Create and upload yout SSH key
+
+ * Generate your SSH key (in this case we will use DSA encryption):
+
+---------------------------------
+ssh-keygen -t rsa
+---------------------------------
+
+ * Copy your public key to the server:
+
+--------------------------------------
+scp ~/.ssh/id_rsa.pub user@people.apache.org:.ssh/authorized_keys
+--------------------------------------
+
+ * Try to login:
+
+---------------------------------
+ssh user@people.apache.org
+---------------------------------
+
+ If it does not ask you a password, everything is ok.
+
+* Modify <<<settings.xml>>>
+
+ Your <<<settings.xml>>> must be modified to allow deployment.
+
+ This is the minimal configuration, obviously if you already have a <<<settings.xml>>> file,
+ you must edit it:
+
+---------------------------
+<settings xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/settings-1.0.0.xsd">
+ <servers>
+ <server>
+ <id>apache-site</id>
+ <username>YOUR_APACHE_USERNAME</username>
+ <filePermissions>664</filePermissions>
+ <directoryPermissions>775</directoryPermissions>
+ </server>
+ <server>
+ <id>apache.snapshots.https</id>
+ <username>YOUR_APACHE_USERNAME</username>
+ <password>YOUR_APACHE_PASSWORD</password>
+ </server>
+ <server>
+ <id>apache.releases.https</id>
+ <username>YOUR_APACHE_USERNAME</username>
+ <password>YOUR_APACHE_PASSWORD</password>
+ </server>
+ </servers>
+ <profiles>
+ <profile>
+ <id>release</id>
+ <properties>
+ <gpg.passphrase>YOUR_SECRET_PHRASE</gpg.passphrase>
+ </properties>
+ </profile>
+ </profile>
+ </profiles>
+</settings>
+---------------------------
+
+Repeatable operations
+
+ These steps must be performed <<for each>> release.
+
+* Prepare the release tag
+
+ To prepare the release Subversion tag, check out the branch/trunk from where
+ you are preparing the release and type:
+
+-----------------------------------
+mvn release:prepare -Dusername=YOUR_SVN_USER -Dpassword=YOUR_SVN_PASSWORD
+-----------------------------------
+
+ The plugin interactively will ask you the version to release, the Subversion
+ tag to use and the next snapshot version. It is reccomended to use the tag:
+ <<tiles-X.X.X>>.
+
+* Perform the Release
+
+ To perform the release, i.e. creating and deploying Maven artifacts, use:
+
+-----------------------------------
+mvn release:perform
+-----------------------------------
+
+* Close the staging repository
+
+ Login to {{{https://repository.apache.org} Nexus repository}} using your Apache LDAP credentials.
+ Click on "Staging". Then click on "tiles" in the list of repositories.
+ In the panel below you should see an open repository that is linked to your username and ip.
+ Right click on this repository and select "Close".
+ This will close the repository from future deployments and make it available for others to view.
+ If you are staging multiple releases together, skip this step until you have staged everything.
+ Enter the name and version of the artifact being released in the "Description" field and then click "Close".
+ This will make it easier to identify it later.
+
+* Verify the staged artifacts
+
+ If you click on your repository, a tree view will appear below.
+ You can then browse the contents to ensure the artifacts are as you expect them.
+ Pay particular attention to the existence of *.asc (signature) files.
+ If the you don't like the content of the repository, right click your repository and choose "Drop".
+ You can then rollback your release and repeat the process.
+
+ Note the repository URL, you will need this in your vote email.
+
+* Digest and upload assemblies
+
+ * Go into the release assembly target directory:
+
+-----------------------------------
+cd target/checkout/assembly/target/assembly/out
+-----------------------------------
+
+ * Create MD5 and SHA1 files for each files (including ASC files). You can do
+ it with this simple shell script:
+
+-----------------------------------
+#!/bin/sh
+
+for fileitem in *
+do
+ openssl md5 < $fileitem > $fileitem.md5
+ openssl sha1 < $fileitem > $fileitem.sha1
+done
+-----------------------------------
+
+ * Upload everything to the build site:
+
+-----------------------------------
+scp * user@people.apache.org:/www/people.apache.org/builds/tiles/${version}
+-----------------------------------
+
+* Release the JIRA version
+
+ * In JIRA go to the version that you want to release and release it.
+
+ * Create a new version, if it has not been done before.
+
+ * Create the release notes and <<write down the link>> that it uses.
+
+* Send announcement for the test build
+
+ In <<developers mailing list>> send an announcement for the test build:
+
+-----------------------------------
+Subject: [ANNOUNCE] Tiles ${version} test build available
+
+The test build of Tiles ${version} is available.
+
+
+No determination as to the quality ('alpha,' 'beta,' or 'GA') of Tiles
+${version} has been made, and at this time it is simply a "test build". We
+welcome any comments you may have, and will take all feedback into
+account if a quality vote is called for this build.
+
+Release notes:
+
+* ${jira.release.notes}
+
+Distribution:
+
+ * http://people.apache.org/builds/tiles/${version}/
+
+Maven 2 staging repository:
+
+ * https://repository.apache.org/content/repositories/tiles-[YOUR REPOSITORY ID]/
+
+A vote regarding the quality of this test build will be initiated
+within the next couple of days.
+-----------------------------------
+
+* Call for a vote
+
+ A few days after the test build announcement, call for a vote in
+ <<developers mailing list>>.
+
+-----------------------------------
+Subject: [VOTE] ${version} Release Quality
+
+The Tiles ${version} test build has been available since ${testBuildDate}.
+
+Release notes:
+
+* ${jira.release.notes}
+
+Distribution:
+
+ * http://people.apache.org/builds/tiles/${version}/
+
+Maven 2 staging repository:
+
+ * https://repository.apache.org/content/repositories/tiles-[YOUR REPOSITORY ID]/
+
+If you have had a chance to review the test build, please respond with
+a vote on its quality:
+
+ [ ] Leave at test build
+ [ ] Alpha
+ [ ] Beta
+ [ ] General Availability (GA)
+
+
+Everyone who has tested the build is invited to vote. Votes by PMC
+members are considered binding. A vote passes if there are at least
+three binding +1s and more +1s than -1s.
+-----------------------------------
+
+* Post-vote operations
+
+ After a vote is finished, and it has been decided that is
+ <<at least of alpha quality>>, there is the need of a post-vote process.
+
+** Promote staged artifacts
+
+ Once the release is deemed fit for public consumption it can be transfered to a production repository where it will be available to all users.
+
+ Login to {{{https://repository.apache.org}Nexus repository}} again.
+ Click on "Staging" and then on the repository with id "tiles-staging".
+ Find your closed staging repository, right click on it and choose "Promote".
+ Select the "Releases" repository and click "Promote".
+
+ Next click on "Repositories", select the "Releases" repository
+ and validate that your artifacts exist as you expect them.
+
+** Move assemblies
+
+ * Move assemblies to the Apache distribution mirrors:
+
+-------------------------------------------
+ssh user@people.apache.org
+
+cd /www/people.apache.org/builds/tiles/${version}
+mkdir /www/www.apache.org/dist/tiles/v${version}/
+cp * /www/www.apache.org/dist/tiles/v${version}/
+-------------------------------------------
+
+** Update the site
+
+ * Wait 24 hours to let the mirror sync to the release and then update the
+ site. In particular you have to update the index and the download pages:
+
+------------------------------------------------
+https://svn.apache.org/repos/asf/tiles/site/src/site/xdoc/index.xml
+https://svn.apache.org/repos/asf/tiles/site/src/site/apt/download.apt
+------------------------------------------------
+
+ Build and publish the site:
+
+--------------------------------------
+mvn site
+mvn site:deploy
+--------------------------------------
+
+** Send announcement
+
+ Finally, send an an announcement to the <<users>> and <<developers mailing
+ list>>:
+
+--------------------------------------
+Subject: [ANNOUNCE] Tiles ${version} ${quality} released
+
+The Apache Tiles team is pleased to announce the release of Tiles ${version}
+${quality}.
+
+Tiles ${version} is available in a binary and a source distribution.
+
+http://tiles.apache.org/download.html
+
+It is also available in the central Maven repository under Group ID
+"org.apache.tiles".
+
+The 2.0.x series of the Apache Tiles framework has a minimum
+requirement of the following specification versions:
+
+* Java Servlet 2.4 and JavaServer Pages (JSP) 2.0
+* Java Standard Edition (Java SE) 1.5
+
+The release notes are available online at:
+
+* ${jira.release.notes}
+
+Please feel free to test the distribution and post your comments to
+the user list, or, if appropriate, file a ticket with JIRA.
+--------------------------------------
+
+ <<You have finished!>>
diff --git a/tiles-request/src/site/site.xml b/tiles-request/src/site/site.xml
new file mode 100644
index 0000000..15e8926
--- /dev/null
+++ b/tiles-request/src/site/site.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../index.html"/>
+ <item
+ name="Tiles Request Microframework"
+ href="./index.html"/>
+ </menu>
+ <menu name="Reference">
+ <item
+ name="Javadoc"
+ href="apidocs/index.html"/>
+ </menu>
+
+ <menu name="Developers">
+ <item
+ name="Building"
+ href="/dev/building.html"/>
+ <item
+ name="Snapshots"
+ href="/dev/snapshots.html"/>
+ <item
+ name="Release Process"
+ href="/dev/release.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/src/site/xdoc/dev/building.xml b/tiles-request/src/site/xdoc/dev/building.xml
new file mode 100644
index 0000000..92dceaa
--- /dev/null
+++ b/tiles-request/src/site/xdoc/dev/building.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<document>
+
+ <properties>
+ <title>Apache Request Microframework</title>
+ </properties>
+
+ <body>
+ <section name="Building the Request Microframework">
+ <subsection name="Prerequisites">
+ <p>For all the next instructions, we assume that you downloaded and
+ installed <a href="http://maven.apache.org/">Maven</a>.</p>
+ <p>To download packages from the source repository, you need to
+ download and install <a href="http://subversion.tigris.org/">
+ Subversion</a>.</p>
+ <p>If you want to build something including JavaDocs (assemblies,
+ sites and JavaDoc report itself) you need to install
+ <a href="http://www.graphviz.org/">GraphViz</a>, otherwise you will
+ notice missing pictures inside JavaDocs pages.</p>
+ </subsection>
+ <subsection name="Building main packages">
+ <p>To build the Request Microframework from source you need to:</p>
+ <ul>
+ <li><p><a href="../../download.html">download</a> the source
+ distribution, or checkout the latest version:</p>
+ <p><source>svn co http://svn.apache.org/repos/asf/tiles/framework/trunk/tiles-request</source></p></li>
+ <li><p>go into the source directory and type:</p>
+ <p><source>mvn package</source></p></li>
+ </ul>
+ <p>You will find the generated JARs under:</p>
+ <ul>
+ <li>{tiles-dir}/tiles-request-api/target/tiles-request-api-${version}.jar</li>
+ <li>{tiles-dir}/tiles-request-{implementation}/target/tiles-request-{implementation}-${version}.jar</li>
+ </ul>
+ </subsection>
+ </section>
+ <section name="Building the websites">
+ <p>There are four Tiles websites: the main website and the projects
+ websites (tiles-request, tiles-autotag and framework).</p>
+ <subsection name="Building the main website">
+ <p>To build the main website:</p>
+ <ul>
+ <li><p>checkout the site from the source repository:</p>
+ <p><source>svn co http://svn.apache.org/repos/asf/tiles/site/</source></p></li>
+ <li><p>go into the site directory and type:</p>
+ <p><source>mvn site</source></p></li>
+ </ul>
+ <p>You will find the generated distribution under
+ <code>{tiles-site-dir}/target/site</code>.</p>
+ </subsection>
+ <subsection name="Building the tiles-request website">
+ <p>To build a project's website:</p>
+ <ul>
+ <li><p><a href="../download.html">download</a> the source
+ distribution, or checkout the latest version:</p>
+ <p><source>svn co http://svn.apache.org/repos/asf/tiles/framework/trunk/tiles-request</source></p></li>
+ <li><p>go into the source directory and type:</p>
+ <p><source>mvn site site:stage</source></p></li>
+ </ul>
+ <p>You will find the generated website under:</p>
+ <ul>
+ <li>{tiles-request-dir}/target/staging</li>
+ </ul>
+ </subsection>
+ </section>
+ </body>
+
+</document>
diff --git a/tiles-request/src/site/xdoc/dev/snapshots.xml b/tiles-request/src/site/xdoc/dev/snapshots.xml
new file mode 100644
index 0000000..adfed4f
--- /dev/null
+++ b/tiles-request/src/site/xdoc/dev/snapshots.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<document>
+
+ <properties>
+ <title>Apache Tiles</title>
+ </properties>
+
+ <body>
+ <section name="Apache Tiles™">
+ <subsection name="Snapshots">
+
+ <p>Looking for snapshot builds of the latest version of Tiles?
+ Snapshots are occasionally published to Apache's Maven snapshot
+ repository, which can be accessed with the following configuration:</p>
+
+ <source>
+ <![CDATA[
+ <repository>
+ <id>apache.snapshots</id>
+ <name>Apache Maven Snapshot Repository</name>
+ <url>http://repository.apache.org/snapshots</url>
+ </repository>
+ ]]>
+ </source>
+
+ <p>After configuring the repository, declare a dependency on
+ Tiles Request:</p>
+
+ <source><![CDATA[
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ ]]>
+ </source>
+
+ </subsection>
+</section>
+</body>
+
+</document>
diff --git a/tiles-request/src/site/xdoc/index.xml b/tiles-request/src/site/xdoc/index.xml
new file mode 100644
index 0000000..178737c
--- /dev/null
+++ b/tiles-request/src/site/xdoc/index.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $Id: index.xml 1162124 2011-08-26 14:16:13Z mck $
+ *
+ * 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.
+ */
+-->
+<document>
+
+ <properties>
+ <title>Home</title>
+ </properties>
+
+ <body>
+
+ <section name="Apache Request microframework project">
+
+ <p>Tiles has served the purpose of rendering views for the Model-View-Controller pattern in JavaEE for years.</p>
+ <p>Tiles-3 introduces a complete standalone and super simple abstraction around request/response objects.
+ <p>We've all seen that the various technologies like Servlet, Portlet, JSP, Velocity, FreeMarker seem to have a different abstraction of a common pattern.
+ They all have a concept of:</p>
+ <ul>
+ <li>request: the client request, or some sort of it;</li>
+ <li>response: the response to send to the client, or to the caller, with a writer/output stream to write into;</li>
+ <li>attributes: usually maps (or map-like structures) with string keys and object values;</li>
+ <li>scope: places where different attribute maps are stored (request, session, etc.)</li>
+ </ul>
+ <p>Now all of these scopes are concentrated into "Request" interfaces, that acts as a single point of reference for the developer.
+ In theory, everything you need for rendering a view can be obtained by an object that implements Request, and Request implementations can be built that do not rely on an application server environment.</p>
+ <p> </p>
+ <p>Currently there are bindings for Servlet, Portlet, JSP, Mustache, Velocity and FreeMarker.</p></p>
+
+ </section>
+ </body>
+
+</document>
diff --git a/tiles-request/tiles-request-api/pom.xml b/tiles-request/tiles-request-api/pom.xml
new file mode 100644
index 0000000..8da0917
--- /dev/null
+++ b/tiles-request/tiles-request-api/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-request</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles request - API</name>
+ <description>API for the Tiles Request framework.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractClientRequest.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractClientRequest.java
new file mode 100644
index 0000000..ccec97b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractClientRequest.java
@@ -0,0 +1,97 @@
+/*
+ * $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.request;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Base class for "client" requests, i.e. requests that come unchanged by the
+ * container, such as ServletRequest and PortletRequest.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractClientRequest extends AbstractRequest {
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * Constructor.
+ *
+ * @param applicationContext The application context.
+ */
+ public AbstractClientRequest(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+
+ @Override
+ public void dispatch(String path) throws IOException {
+ if (isForceInclude()) {
+ doInclude(path);
+ } else {
+ setForceInclude(true);
+ doForward(path);
+ }
+ }
+
+ @Override
+ public void include(String path) throws IOException {
+ setForceInclude(true);
+ doInclude(path);
+ }
+
+ @Override
+ public ApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ /**
+ * Returns the application scope.
+ *
+ * @return The application scope.
+ */
+ public Map<String, Object> getApplicationScope() {
+ return applicationContext.getApplicationScope();
+ }
+
+ /**
+ * Forwards to a path.
+ *
+ * @param path The path to forward to.
+ * @throws IOException If something goes wrong when forwarding.
+ */
+ protected abstract void doForward(String path) throws IOException;
+
+ /**
+ * Includes the result of a path.
+ *
+ * @param path The path to forward to.
+ * @throws IOException If something goes wrong when forwarding.
+ */
+ protected abstract void doInclude(String path) throws IOException;
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractRequest.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractRequest.java
new file mode 100644
index 0000000..a850f94
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractRequest.java
@@ -0,0 +1,61 @@
+/*
+ * $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.request;
+
+/**
+ * Base request.
+ *
+ * @version $Rev$ $Date: 2010-11-14 21:32:50 +0100 (dom, 14 nov 2010)$
+ */
+public abstract class AbstractRequest implements DispatchRequest {
+
+ /**
+ * Name of the attribute used to store the force-include option.
+ *
+ */
+ public static final String FORCE_INCLUDE_ATTRIBUTE_NAME = AbstractRequest.class
+ .getName() + ".FORCE_INCLUDE";
+
+ /**
+ * Sets the flag to force inclusion at next dispatch.
+ *
+ * @param forceInclude <code>true</code> means that, at the next dispatch, response
+ * will be included and never forwarded.
+ */
+ protected void setForceInclude(boolean forceInclude) {
+ getContext("request").put(FORCE_INCLUDE_ATTRIBUTE_NAME, forceInclude);
+ }
+
+ /**
+ * Checks if, when dispatching to a resource, the result must be included
+ * and not forwarded to.
+ *
+ * @return <code>true</code> if inclusion is forced.
+ */
+ protected boolean isForceInclude() {
+ Boolean forceInclude = (Boolean) getContext("request").get(
+ FORCE_INCLUDE_ATTRIBUTE_NAME);
+ if (forceInclude != null) {
+ return forceInclude;
+ }
+ return false;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractViewRequest.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractViewRequest.java
new file mode 100644
index 0000000..b3282d9
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/AbstractViewRequest.java
@@ -0,0 +1,65 @@
+/*
+ * $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.request;
+
+import java.io.IOException;
+
+
+/**
+ * Base class for "view" requests, i.e. requests created into view technologies,
+ * such as JSP, Velocity and Freemarker. In particular, all calls to
+ * {@link #dispatch(String)} will cause an inclusion and never a forward.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractViewRequest extends DispatchRequestWrapper {
+
+ /**
+ * Constructor.
+ *
+ * @param request The base request.
+ */
+ public AbstractViewRequest(DispatchRequest request) {
+ super(request);
+ }
+
+ @Override
+ public void dispatch(String path) throws IOException {
+ setForceInclude(true);
+ doInclude(path);
+ }
+
+ @Override
+ public void include(String path) throws IOException {
+ setForceInclude(true);
+ doInclude(path);
+ }
+
+ /**
+ * Includes the result. By default, uses the wrapped request for the inclusion.
+ *
+ * @param path The path whose result will be included.
+ * @throws IOException If something goes wrong.
+ */
+ protected void doInclude(String path) throws IOException {
+ getWrappedRequest().include(path);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationAccess.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationAccess.java
new file mode 100644
index 0000000..260e791
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationAccess.java
@@ -0,0 +1,54 @@
+/*
+ * $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.request;
+
+
+/**
+ * Entry point to get information about the application.
+ *
+ * @version $Rev: 1064782 $ $Date: 2011-01-28 18:08:52 +0100 (Fri, 28 Jan 2011) $
+ */
+public final class ApplicationAccess {
+
+ /**
+ * The attribute name that will be used to store the application context itself.
+ */
+ public static final String APPLICATION_CONTEXT_ATTRIBUTE =
+ ApplicationContext.class.getName() + ".ATTRIBUTE";
+
+ /**
+ * Constructor.
+ */
+ private ApplicationAccess() {
+ }
+
+ /**
+ * Registers an application context. It will be registered into itself as an
+ * attribute, using the {@link #APPLICATION_CONTEXT_ATTRIBUTE} name.
+ *
+ * @param applicationContext The application context to register.
+ */
+ public static void register(ApplicationContext applicationContext) {
+ applicationContext.getApplicationScope().put(
+ APPLICATION_CONTEXT_ATTRIBUTE, applicationContext);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContext.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContext.java
new file mode 100644
index 0000000..24c236f
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContext.java
@@ -0,0 +1,83 @@
+/*
+ * $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.request;
+
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Defines a set of methods which tiles use to communicate to
+ * the tiles container and runtime environment. There is only
+ * one application context per container.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ApplicationContext {
+
+ /**
+ * Returns the original, technology-dependent, context.
+ *
+ * @return The original application context.
+ */
+ Object getContext();
+
+ /**
+ * Returns a mutable Map that maps application scope attribute names to
+ * their values.
+ *
+ * @return Map of key value pairs.
+ */
+ Map<String, Object> getApplicationScope();
+
+ /**
+ * Return an immutable Map that maps context application initialization
+ * parameters to their values.
+ *
+ * @return initialization parameters
+ */
+ Map<String, String> getInitParams();
+
+ /**
+ * Return the application resource mapped to the specified path.
+ *
+ * @param localePath path to the desired resource, including the Locale suffix.
+ * @return the first located resource which matches the given path or null if no such resource exists.
+ */
+ ApplicationResource getResource(String localePath);
+
+ /**
+ * Return a localized version of an ApplicationResource.
+ *
+ * @param base the ApplicationResource.
+ * @param locale the desired Locale.
+ * @return the first located resource which matches the given path or null if no such resource exists.
+ */
+ ApplicationResource getResource(ApplicationResource base, Locale locale);
+
+ /**
+ * Return the application resources mapped to the specified path.
+ *
+ * @param path to the desired resource.
+ * @return all resources which match the given path.
+ */
+ Collection<ApplicationResource> getResources(String path);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContextAware.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContextAware.java
new file mode 100644
index 0000000..1526ffd
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContextAware.java
@@ -0,0 +1,38 @@
+/*
+ * $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.request;
+
+
+/**
+ * It represents an object that can have a reference to the
+ * {@link ApplicationContext}.
+ *
+ * @version $Rev: 893303 $ $Date: 2009-12-22 21:18:35 +0100 (Tue, 22 Dec 2009) $
+ */
+public interface ApplicationContextAware {
+
+ /**
+ * Sets the Tiles application context.
+ *
+ * @param applicationContext The Tiles application context.
+ */
+ void setApplicationContext(ApplicationContext applicationContext);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContextWrapper.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContextWrapper.java
new file mode 100644
index 0000000..3696f97
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationContextWrapper.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request;
+
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+
+
+/**
+ * Delegate for ease of customization.
+ *
+ * @version $Rev: 933750 $ $Date: 2010-04-13 21:16:06 +0200 (Tue, 13 Apr 2010) $
+ */
+public class ApplicationContextWrapper implements ApplicationContext {
+
+ /**
+ * The original context.
+ */
+ private ApplicationContext context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The original context.
+ */
+ public ApplicationContextWrapper(ApplicationContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Returns the wrapped application context.
+ *
+ * @return The wrapped application context.
+ */
+ public ApplicationContext getWrappedApplicationContext() {
+ return context;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getApplicationScope() {
+ return context.getApplicationScope();
+ }
+
+ /** {@inheritDoc} */
+ public Object getContext() {
+ return context.getContext();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getInitParams() {
+ return context.getInitParams();
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationResource getResource(String localePath) {
+ return context.getResource(localePath);
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationResource getResource(ApplicationResource base, Locale locale) {
+ return context.getResource(base, locale);
+ }
+
+ /** {@inheritDoc} */
+ public Collection<ApplicationResource> getResources(String path) {
+ return context.getResources(path);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationResource.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationResource.java
new file mode 100644
index 0000000..6f5c05b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/ApplicationResource.java
@@ -0,0 +1,84 @@
+/*
+ * $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.request;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
+/**
+ * A (localized) resource accessible through the ApplicationContext.
+ * Typically this is a file inside the web application's war.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ApplicationResource {
+
+ /**
+ * Get the path name for this resource.
+ * You can access this ressource by passing the path to
+ * {@link ApplicationContext#getResource(String) getResource}.
+ *
+ * @return the path including localization.
+ */
+ String getLocalePath();
+
+ /**
+ * Get the path name for this resource. Multiple versions of
+ * a resource can share the same path if the locale part is different.
+ *
+ * @return the path excluding localization.
+ */
+ String getPath();
+
+ /**
+ * Get the Locale for this resource.
+ *
+ * @return the Locale.
+ */
+ Locale getLocale();
+
+ /**
+ * Get the path name of another version of the resource.
+ *
+ * @param locale the Locale for the new version.
+ * @return the path including localization.
+ */
+ String getLocalePath(Locale locale);
+
+ /**
+ * Get a java.io.InputStream to read the contents of this resource.
+ *
+ * @return the InputStream.
+ * @throws IOException if the contents cannot be read.
+ */
+ InputStream getInputStream() throws IOException;
+
+ /**
+ * Get the last modification date for this resource.
+ *
+ * @return the difference, measured in milliseconds, between the current
+ * time and midnight, January 1, 1970 UTC.
+ * @throws IOException if the last modification date cannot be found.
+ */
+ long getLastModified() throws IOException;
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DefaultRequestWrapper.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DefaultRequestWrapper.java
new file mode 100644
index 0000000..a1ff9f1
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DefaultRequestWrapper.java
@@ -0,0 +1,131 @@
+/*
+ * $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.request;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tiles.request.attribute.Addable;
+
+/**
+ * Delegate for ease of customization.
+ *
+ * @version $Rev: 1215009 $ $Date: 2011-12-16 01:32:31 +0100 (Fri, 16 Dec 2011) $
+ */
+public class DefaultRequestWrapper implements RequestWrapper {
+
+ /**
+ * The wrapper request context object.
+ */
+ private Request context;
+
+ /**
+ * Constructor.
+ *
+ * @param context
+ * The request context to wrap.
+ */
+ public DefaultRequestWrapper(Request context) {
+ this.context = context;
+ }
+
+ /** {@inheritDoc} */
+ public Request getWrappedRequest() {
+ return context;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getHeader() {
+ return context.getHeader();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getHeaderValues() {
+ return context.getHeaderValues();
+ }
+
+ /** {@inheritDoc} */
+ public Addable<String> getResponseHeaders() {
+ return context.getResponseHeaders();
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationContext getApplicationContext() {
+ return context.getApplicationContext();
+ }
+
+ /** {@inheritDoc} */
+ public OutputStream getOutputStream() throws IOException {
+ return context.getOutputStream();
+ }
+
+ /** {@inheritDoc} */
+ public Writer getWriter() throws IOException {
+ return context.getWriter();
+ }
+
+ /** {@inheritDoc} */
+ public PrintWriter getPrintWriter() throws IOException {
+ return context.getPrintWriter();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isResponseCommitted() {
+ return context.isResponseCommitted();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getParam() {
+ return context.getParam();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getParamValues() {
+ return context.getParamValues();
+ }
+
+ /** {@inheritDoc} */
+ public Locale getRequestLocale() {
+ return context.getRequestLocale();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isUserInRole(String role) {
+ return context.isUserInRole(role);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getContext(String scope) {
+ return context.getContext(scope);
+ }
+
+ /** {@inheritDoc} */
+ public List<String> getAvailableScopes() {
+ return context.getAvailableScopes();
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DispatchRequest.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DispatchRequest.java
new file mode 100644
index 0000000..26141c6
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DispatchRequest.java
@@ -0,0 +1,56 @@
+/*
+ * $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.request;
+
+import java.io.IOException;
+
+
+/**
+ * Encapsulation of request information.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface DispatchRequest extends Request {
+
+ /**
+ * Dispatches the request to a specified path.
+ *
+ * @param path The path to dispatch to.
+ * @throws IOException If something goes wrong during dispatching.
+ */
+ void dispatch(String path) throws IOException;
+
+ /**
+ * Includes the response from the specified URL in the current response output.
+ *
+ * @param path The path to include.
+ * @throws IOException If something goes wrong during inclusion.
+ */
+ void include(String path) throws IOException;
+
+ /**
+ * Sets the content type when rendering the result.
+ *
+ * @param contentType The content type. It should follow the specifications
+ * from W3C about content types.
+ */
+ void setContentType(String contentType);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java
new file mode 100644
index 0000000..e118f1f
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/DispatchRequestWrapper.java
@@ -0,0 +1,145 @@
+/*
+ * $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.request;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tiles.request.attribute.Addable;
+
+/**
+ * Delegate for ease of customization.
+ *
+ * @version $Rev: 1215009 $ $Date: 2011-12-16 01:32:31 +0100 (Fri, 16 Dec 2011) $
+ */
+public class DispatchRequestWrapper extends AbstractRequest implements
+ RequestWrapper {
+
+ /**
+ * The wrapper request context object.
+ */
+ private DispatchRequest context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The request context to wrap.
+ */
+ public DispatchRequestWrapper(DispatchRequest context) {
+ this.context = context;
+ }
+
+ /** {@inheritDoc} */
+ public DispatchRequest getWrappedRequest() {
+ return context;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getHeader() {
+ return context.getHeader();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getHeaderValues() {
+ return context.getHeaderValues();
+ }
+
+ /** {@inheritDoc} */
+ public Addable<String> getResponseHeaders() {
+ return context.getResponseHeaders();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getContext(String scope) {
+ return context.getContext(scope);
+ }
+
+ /** {@inheritDoc} */
+ public List<String> getAvailableScopes() {
+ return context.getAvailableScopes();
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationContext getApplicationContext() {
+ return context.getApplicationContext();
+ }
+
+ /** {@inheritDoc} */
+ public void dispatch(String path) throws IOException {
+ context.dispatch(path);
+ }
+
+ /** {@inheritDoc} */
+ public void include(String path) throws IOException {
+ context.include(path);
+ }
+
+ /** {@inheritDoc} */
+ public OutputStream getOutputStream() throws IOException {
+ return context.getOutputStream();
+ }
+
+ /** {@inheritDoc} */
+ public Writer getWriter() throws IOException {
+ return context.getWriter();
+ }
+
+ /** {@inheritDoc} */
+ public PrintWriter getPrintWriter() throws IOException {
+ return context.getPrintWriter();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isResponseCommitted() {
+ return context.isResponseCommitted();
+ }
+
+ /** {@inheritDoc} */
+ public void setContentType(String contentType) {
+ context.setContentType(contentType);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getParam() {
+ return context.getParam();
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getParamValues() {
+ return context.getParamValues();
+ }
+
+ /** {@inheritDoc} */
+ public Locale getRequestLocale() {
+ return context.getRequestLocale();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isUserInRole(String role) {
+ return context.isUserInRole(role);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java
new file mode 100644
index 0000000..3484c42
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/NotAvailableFeatureException.java
@@ -0,0 +1,66 @@
+/*
+ * $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.request;
+
+/**
+ * Exception that indicates that a feature could not be used since it is not
+ * available.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotAvailableFeatureException extends RequestException {
+
+ /**
+ * Constructor.
+ *
+ */
+ public NotAvailableFeatureException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public NotAvailableFeatureException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The cause to be wrapped.
+ */
+ public NotAvailableFeatureException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The cause to be wrapped.
+ */
+ public NotAvailableFeatureException(String message, Throwable e) {
+ super(message, e);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/Request.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/Request.java
new file mode 100644
index 0000000..08e4a59
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/Request.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.request;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tiles.request.attribute.Addable;
+
+
+/**
+ * Encapsulation of request information.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Request {
+
+ /**
+ * Return an immutable Map that maps header names to the first (or only)
+ * header value (as a String).
+ *
+ * @return The header map.
+ */
+ Map<String, String> getHeader();
+
+ /**
+ * Return an immutable Map that maps header names to the set of all values
+ * specified in the request (as a String array). Header names must be
+ * matched in a case-insensitive manner.
+ *
+ * @return The header values map.
+ */
+ Map<String, String[]> getHeaderValues();
+
+ /**
+ * Return an Addable object that can be used to write headers to the response.
+ *
+ * @return An Addable object.
+ */
+ Addable<String> getResponseHeaders();
+
+ /**
+ * Returns a context map, given the scope name.
+ *
+ * @param scope The name of the scope.
+ * @return The context.
+ */
+ Map<String, Object> getContext(String scope);
+
+ /**
+ * Returns all available scopes, that are the ones returned by
+ * {@link #getNativeScopes()} plus derivative scopes (e.g. flash scope).
+ *
+ * @return All the available scopes.
+ */
+ List<String> getAvailableScopes();
+
+ /**
+ * Returns the associated application context.
+ *
+ * @return The application context associated to this request.
+ */
+ ApplicationContext getApplicationContext();
+
+ /**
+ * Returns an output stream to be used to write directly in the response.
+ *
+ * @return The output stream that writes in the response.
+ * @throws IOException If something goes wrong when getting the output stream.
+ */
+ OutputStream getOutputStream() throws IOException;
+
+ /**
+ * Returns a writer to be used to write directly in the response.
+ *
+ * @return The writer that writes in the response.
+ * @throws IOException If something goes wrong when getting the writer.
+ */
+ Writer getWriter() throws IOException;
+
+ /**
+ * Returns a print writer to be used to write directly in the response.
+ *
+ * @return The print writer that writes in the response.
+ * @throws IOException If something goes wrong when getting the print
+ * writer.
+ */
+ PrintWriter getPrintWriter() throws IOException;
+
+ /**
+ * Checks if the response has been committed.
+ *
+ * @return <code>true</code> only if the response has been committed.
+ */
+ boolean isResponseCommitted();
+
+ /**
+ * Return an immutable Map that maps request parameter names to the first
+ * (or only) value (as a String).
+ *
+ * @return The parameter map.
+ */
+ Map<String, String> getParam();
+
+ /**
+ * Return an immutable Map that maps request parameter names to the set of
+ * all values (as a String array).
+ *
+ * @return The parameter values map.
+ */
+ Map<String, String[]> getParamValues();
+
+ /**
+ * Return the preferred Locale in which the client will accept content.
+ *
+ * @return The current request locale. It is the locale of the request
+ * object itself and it is NOT the locale that the user wants to use. See
+ * {@link org.apache.tiles.locale.LocaleResolver} to implement strategies to
+ * resolve locales.
+ */
+ Locale getRequestLocale();
+
+ /**
+ * Determine whether or not the specified user is in the given role.
+ * @param role the role to check against.
+ * @return <code>true</code> if the user is in the given role.
+ */
+ boolean isUserInRole(String role);
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/RequestException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/RequestException.java
new file mode 100644
index 0000000..430937e
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/RequestException.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.request;
+
+/**
+ * Thrown when something related to a request fails.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestException extends RuntimeException {
+
+ /**
+ * Constructor.
+ */
+ public RequestException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ */
+ public RequestException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause.
+ */
+ public RequestException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ * @param cause The cause.
+ */
+ public RequestException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/RequestWrapper.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/RequestWrapper.java
new file mode 100644
index 0000000..d82db8c
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/RequestWrapper.java
@@ -0,0 +1,38 @@
+/*
+ * $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.request;
+
+
+/**
+ * Delegate for ease of customization.
+ *
+ * @version $Rev: 1215002 $ $Date: 2011-12-16 01:27:17 +0100 (Fri, 16 Dec 2011) $
+ */
+public interface RequestWrapper extends Request {
+
+ /**
+ * Returns the wrapped Tiles request.
+ *
+ * @return The wrapped Tiles request.
+ */
+ Request getWrappedRequest();
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/Addable.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/Addable.java
new file mode 100644
index 0000000..5e8b9a9
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/Addable.java
@@ -0,0 +1,38 @@
+/*
+ * $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.request.attribute;
+
+/**
+ * Allows to get and set attributes.
+ *
+ * @version $Rev$ $Date$
+ * @param <V> The type of the value of the attribute.
+ */
+public interface Addable<V> {
+
+ /**
+ * Sets a value for the given key.
+ *
+ * @param key The key of the attribute.
+ * @param value The value of the attribute.
+ */
+ void setValue(String key, V value);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java
new file mode 100644
index 0000000..5c313ac
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/AttributeExtractor.java
@@ -0,0 +1,29 @@
+/*
+ * $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.request.attribute;
+
+/**
+ * Allows to get, put and remove Object-type attributes.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface AttributeExtractor extends HasRemovableKeys<Object>, HasAddableKeys<Object> {
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java
new file mode 100644
index 0000000..88ae480
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/EnumeratedValuesExtractor.java
@@ -0,0 +1,39 @@
+/*
+ * $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.request.attribute;
+
+import java.util.Enumeration;
+
+/**
+ * Allows to get values from multi-valued attributes.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface EnumeratedValuesExtractor extends HasAddableKeys<String> {
+
+ /**
+ * Returns the values stored at the given key.
+ *
+ * @param key The key of the attribute.
+ * @return The values of the attribute.
+ */
+ Enumeration<String> getValues(String key);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java
new file mode 100644
index 0000000..115fd2b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasAddableKeys.java
@@ -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.
+ */
+package org.apache.tiles.request.attribute;
+
+/**
+ * Allows to get and set attributes.
+ *
+ * @version $Rev$ $Date$
+ * @param <V> The type of the value of the attribute.
+ */
+public interface HasAddableKeys<V> extends HasKeys<V>, Addable<V> {
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasKeys.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasKeys.java
new file mode 100644
index 0000000..32ea92c
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasKeys.java
@@ -0,0 +1,47 @@
+/*
+ * $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.request.attribute;
+
+import java.util.Enumeration;
+
+/**
+ * Allows to get attributes.
+ *
+ * @version $Rev$ $Date$
+ * @param <V> The type of the value of the attribute.
+ */
+public interface HasKeys<V> {
+
+ /**
+ * The enumeration of the keys of the stored attributes.
+ *
+ * @return The keys.
+ */
+ Enumeration<String> getKeys();
+
+ /**
+ * Returns the value of the attribute with the given key.
+ *
+ * @param key The key of the attribute.
+ * @return The value.
+ */
+ V getValue(String key);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java
new file mode 100644
index 0000000..160737f
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/HasRemovableKeys.java
@@ -0,0 +1,37 @@
+/*
+ * $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.request.attribute;
+
+/**
+ * Allows to get and remove attributes.
+ *
+ * @version $Rev$ $Date$
+ * @param <V> The type of the value of the attribute.
+ */
+public interface HasRemovableKeys<V> extends HasKeys<V> {
+
+ /**
+ * Removes an attribute.
+ *
+ * @param key The key of the attribute to remove.
+ */
+ void removeValue(String key);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/package-info.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/package-info.java
new file mode 100644
index 0000000..5b70eee
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/attribute/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * $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.
+ */
+/**
+ * Methods to get, set and remove attributes from different sources (like HTTP requests
+ * or sessions).
+ * By implementing {@link org.apache.tiles.request.attribute.AttributeExtractor},
+ * you can use a Map from {@link org.apache.tiles.request.collection} to manipulate the
+ * attributes of another class.
+ */
+package org.apache.tiles.request.attribute;
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java
new file mode 100644
index 0000000..c6813fa
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/AddableParameterMap.java
@@ -0,0 +1,93 @@
+/*
+ * $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.request.collection;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasAddableKeys;
+
+/**
+ * Exposes an {@link HasAddableKeys} object as a put/get (no remove) map.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AddableParameterMap extends ReadOnlyEnumerationMap<String> {
+
+ /**
+ * The request.
+ */
+ private HasAddableKeys<String> request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request object to use.
+ */
+ public AddableParameterMap(HasAddableKeys<String> request) {
+ super(request);
+ this.request = request;
+ }
+
+ /** {@inheritDoc} */
+ public Set<Map.Entry<String, String>> entrySet() {
+ return new AddableParameterEntrySet();
+ }
+
+ /** {@inheritDoc} */
+ public String put(String key, String value) {
+ String oldValue = request.getValue(key);
+ request.setValue(key, value);
+ return oldValue;
+ }
+
+
+ /** {@inheritDoc} */
+ public void putAll(Map<? extends String, ? extends String> map) {
+ for (Map.Entry<? extends String, ? extends String> entry : map
+ .entrySet()) {
+ request.setValue(entry.getKey(), entry.getValue());
+ }
+ }
+
+
+ /**
+ * Entry set implementation for {@link AddableParameterMap}.
+ */
+ private class AddableParameterEntrySet extends ReadOnlyEnumerationMap<String>.ReadOnlyEnumerationMapEntrySet {
+
+ @Override
+ public boolean add(java.util.Map.Entry<String, String> e) {
+ request.setValue(e.getKey(), e.getValue());
+ return true;
+ }
+
+ @Override
+ public boolean addAll(
+ Collection<? extends java.util.Map.Entry<String, String>> c) {
+ for (Map.Entry<String, String> entry : c) {
+ request.setValue(entry.getKey(), entry.getValue());
+ }
+ return true;
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java
new file mode 100644
index 0000000..5d68e23
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/CollectionUtil.java
@@ -0,0 +1,70 @@
+/*
+ * $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.request.collection;
+
+import java.util.Enumeration;
+
+/**
+ * Utilities for requests.
+ *
+ * @version $Rev: 1064782 $ $Date: 2011-01-28 18:08:52 +0100 (Fri, 28 Jan 2011) $
+ */
+public final class CollectionUtil {
+
+ /**
+ * Constructor.
+ */
+ private CollectionUtil() {
+
+ }
+
+ /**
+ * Returns the string representation of the key.
+ *
+ * @param key The key.
+ * @return The string representation of the key.
+ * @throws IllegalArgumentException If the key is <code>null</code>.
+ */
+ public static String key(Object key) {
+ if (key == null) {
+ throw new IllegalArgumentException();
+ } else if (key instanceof String) {
+ return ((String) key);
+ } else {
+ return (key.toString());
+ }
+ }
+
+ /**
+ * Returns the number of elements in an enumeration, by iterating it.
+ *
+ * @param keys The enumeration.
+ * @return The number of elements.
+ */
+ public static int enumerationSize(Enumeration<?> keys) {
+ int n = 0;
+ while (keys.hasMoreElements()) {
+ keys.nextElement();
+ n++;
+ }
+ return n;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java
new file mode 100644
index 0000000..3a0f8d2
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/HeaderValuesMap.java
@@ -0,0 +1,525 @@
+/*
+ * $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.request.collection;
+
+import static org.apache.tiles.request.collection.CollectionUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.EnumeratedValuesExtractor;
+
+
+/**
+ * Exposes an {@link EnumeratedValuesExtractor} object as a read-only map.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderValuesMap implements Map<String, String[]> {
+
+ /**
+ * The request.
+ */
+ private EnumeratedValuesExtractor request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request object to use.
+ */
+ public HeaderValuesMap(EnumeratedValuesExtractor request) {
+ this.request = request;
+ }
+
+
+ /** {@inheritDoc} */
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean containsKey(Object key) {
+ return (request.getValue(key(key)) != null);
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean containsValue(Object value) {
+ if (!(value instanceof String[])) {
+ return (false);
+ }
+ String[] test = (String[]) value;
+ Enumeration<String> names = request.getKeys();
+ while (names.hasMoreElements()) {
+ String name = names.nextElement();
+ if (compareHeaders(name, array2set(test))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /** {@inheritDoc} */
+ public Set<Map.Entry<String, String[]>> entrySet() {
+ return new HeadersEntrySet();
+ }
+
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object o) {
+ EnumeratedValuesExtractor otherRequest = ((HeaderValuesMap) o).request;
+ boolean retValue = true;
+ for (Enumeration<String> attribs = request.getKeys(); attribs
+ .hasMoreElements()
+ && retValue;) {
+ String parameterName = attribs.nextElement();
+ Set<String> valueSet = enumeration2set(otherRequest.getValues(parameterName));
+ retValue = compareHeaders(parameterName, valueSet);
+ }
+
+ return retValue;
+ }
+
+
+ /** {@inheritDoc} */
+ public String[] get(Object key) {
+ return getHeaderValues(key(key));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ int retValue = 0;
+ for (Enumeration<String> attribs = request.getKeys(); attribs
+ .hasMoreElements();) {
+ String parameterName = attribs.nextElement();
+ Enumeration<String> values = request.getValues(parameterName);
+ int valueHash = 0;
+ while (values.hasMoreElements()) {
+ valueHash += values.nextElement().hashCode();
+ }
+ retValue += parameterName.hashCode() ^ valueHash;
+ }
+ return retValue;
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean isEmpty() {
+ return !request.getKeys().hasMoreElements();
+ }
+
+
+ /** {@inheritDoc} */
+ public Set<String> keySet() {
+ return new KeySet(request);
+ }
+
+
+ /** {@inheritDoc} */
+ public String[] put(String key, String[] value) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public void putAll(Map<? extends String, ? extends String[]> map) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public String[] remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ /** {@inheritDoc} */
+ public int size() {
+ return enumerationSize(request.getKeys());
+ }
+
+
+ /** {@inheritDoc} */
+ public Collection<String[]> values() {
+ return new HeaderValuesCollection();
+ }
+
+ /**
+ * Extracts values enumeration of an attribute and returns the corresponding array of values.
+ *
+ * @param key The key of the attribute.
+ * @return The values of the attribute.
+ */
+ private String[] getHeaderValues(String key) {
+ List<String> list = new ArrayList<String>();
+ Enumeration<String> values = request.getValues(key);
+ while (values.hasMoreElements()) {
+ list.add(values.nextElement());
+ }
+ String[] retValue = list.toArray(new String[list.size()]);
+ return retValue;
+ }
+
+ /**
+ * Converts the content of a string enumeration to an array of strings.
+ *
+ * @param enumeration The enumeration to convert.
+ * @return The corresponding array.
+ */
+ private Set<String> enumeration2set(Enumeration<String> enumeration) {
+ Set<String> retValue = new HashSet<String>();
+ while (enumeration.hasMoreElements()) {
+ retValue.add(enumeration.nextElement());
+ }
+ return retValue;
+ }
+
+ /**
+ * Transforms a string array in a string set.
+ *
+ * @param valueArray The array to convert.
+ * @return The corresponding set.
+ */
+ private Set<String> array2set(String[] valueArray) {
+ Set<String> values = new HashSet<String>();
+ for (int i = 0; i < valueArray.length; i++) {
+ values.add(valueArray[i]);
+ }
+ return values;
+ }
+
+ /**
+ * Checks if values of a header attribute are the same as the one passed in
+ * the set.
+ *
+ * @param name The name of the header.
+ * @param testSet The set of values it must contain.
+ * @return <code>true</code> if all the values, and only them, are present
+ * in the header values.
+ */
+ private boolean compareHeaders(String name, Set<String> testSet) {
+ Enumeration<String> values = request.getValues(name);
+ boolean matched = true;
+ while (values.hasMoreElements() && matched) {
+ String currentValue = values.nextElement();
+ matched = testSet.remove(currentValue);
+ }
+ matched = matched && testSet.isEmpty();
+ return matched;
+ }
+
+ /**
+ * Entry set implementation for {@link HeaderValuesMap}.
+ */
+ private class HeadersEntrySet implements Set<Map.Entry<String, String[]>> {
+
+ @Override
+ public boolean add(java.util.Map.Entry<String, String[]> e) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(
+ Collection<? extends java.util.Map.Entry<String, String[]>> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean contains(Object o) {
+ return containsEntry((java.util.Map.Entry<String, String[]>) o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ Collection<Map.Entry<String, String[]>> realCollection =
+ (Collection<Map.Entry<String, String[]>>) c;
+ for (Map.Entry<String, String[]> entry : realCollection) {
+ if (!containsEntry(entry)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return HeaderValuesMap.this.isEmpty();
+ }
+
+ @Override
+ public Iterator<java.util.Map.Entry<String, String[]>> iterator() {
+ return new HeadersEntrySetIterator();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return HeaderValuesMap.this.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toList().toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return toList().toArray(a);
+ }
+
+ /**
+ * Checks whether the given entry is present in the headers.
+ *
+ * @param entry The entry to check.
+ * @return <code></code> if the key and the values of the entry are present.
+ */
+ private boolean containsEntry(Map.Entry<String, String[]> entry) {
+ Enumeration<String> entryValues = request.getValues(key(entry.getKey()));
+ String[] valueArray = entry.getValue();
+ Set<String> values = array2set(valueArray);
+ while (entryValues.hasMoreElements()) {
+ if (!values.remove(entryValues.nextElement())) {
+ return false;
+ }
+ }
+ return values.isEmpty();
+ }
+
+ /**
+ * Turns this entry set into a list.
+ *
+ * @return The collection, turned into a list.
+ */
+ private List<Map.Entry<String, String[]>> toList() {
+ List<Map.Entry<String, String[]>> entries = new ArrayList<Map.Entry<String, String[]>>();
+ Enumeration<String> names = request.getKeys();
+ while (names.hasMoreElements()) {
+ entries.add(extractNextEntry(names));
+ }
+ return entries;
+ }
+
+ /**
+ * Returns the next entry, by getting the next element in the given enumeration.
+ *
+ * @param names The enumeration to get the next name from..
+ * @return The next map entry.
+ */
+ private MapEntry<String, String[]> extractNextEntry(
+ Enumeration<String> names) {
+ String name = names.nextElement();
+ return new MapEntryArrayValues<String, String>(name, getHeaderValues(name), false);
+ }
+
+ /**
+ * Iterates {@link HeadersEntrySet} elements.
+ */
+ private class HeadersEntrySetIterator implements Iterator<Map.Entry<String, String[]>> {
+
+ /**
+ * The enumeration to use.
+ */
+ private Enumeration<String> namesEnumeration = request.getKeys();
+
+ @Override
+ public boolean hasNext() {
+ return namesEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public Map.Entry<String, String[]> next() {
+ return extractNextEntry(namesEnumeration);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+ }
+
+ /**
+ * It is a collection of all values of the header. Each element is an array
+ * of values of a single header.
+ */
+ private class HeaderValuesCollection implements Collection<String[]> {
+
+ @Override
+ public boolean add(String[] e) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends String[]> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return containsValue(o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ Collection<String[]> realCollection = (Collection<String[]>) c;
+ for (String[] value : realCollection) {
+ if (!containsValue(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return HeaderValuesMap.this.isEmpty();
+ }
+
+ @Override
+ public Iterator<String[]> iterator() {
+ return new HeaderValuesCollectionIterator();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return HeaderValuesMap.this.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toList().toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return toList().toArray(a);
+ }
+
+ /**
+ * Turns this collection into a list.
+ *
+ * @return The list.
+ */
+ private List<String[]> toList() {
+ List<String[]> entries = new ArrayList<String[]>();
+ Enumeration<String> names = request.getKeys();
+ while (names.hasMoreElements()) {
+ entries.add(enumeration2array(request.getValues(names.nextElement())));
+ }
+ return entries;
+ }
+
+ /**
+ * Converts the content of a string enumeration to an array of strings.
+ *
+ * @param enumeration The enumeration to convert.
+ * @return The corresponding array.
+ */
+ private String[] enumeration2array(Enumeration<String> enumeration) {
+ List<String> list1 = new ArrayList<String>();
+ while (enumeration.hasMoreElements()) {
+ list1.add(enumeration.nextElement());
+ }
+
+ return list1.toArray(new String[list1.size()]);
+ }
+
+ /**
+ * Iterates elements of {@link HeaderValuesCollection}.
+ */
+ private class HeaderValuesCollectionIterator implements Iterator<String[]> {
+
+ /**
+ * The enumeration of the name of header attributes.
+ */
+ private Enumeration<String> namesEnumeration = request.getKeys();
+
+ @Override
+ public boolean hasNext() {
+ return namesEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public String[] next() {
+ return enumeration2array(request.getValues(namesEnumeration.nextElement()));
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/KeySet.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/KeySet.java
new file mode 100644
index 0000000..b029b54
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/KeySet.java
@@ -0,0 +1,166 @@
+/*
+ * $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.request.collection;
+
+import static org.apache.tiles.request.collection.CollectionUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasKeys;
+
+/**
+ * Exposes keys of a {@link HasKeys} object as a set.
+ *
+ * @version $Rev$ $Date$
+ */
+public class KeySet implements Set<String> {
+
+ /**
+ * The request to read.
+ */
+ private HasKeys<?> request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request to read.
+ */
+ public KeySet(HasKeys<?> request) {
+ this.request = request;
+ }
+
+ @Override
+ public boolean add(String e) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends String> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return request.getValue(key(o)) != null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ Collection<String> realCollection = (Collection<String>) c;
+ for (String key : realCollection) {
+ if (request.getValue(key(key)) == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return !request.getKeys().hasMoreElements();
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return new KeySetIterator();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return enumerationSize(request.getKeys());
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toList().toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return toList().toArray(a);
+ }
+
+ /**
+ * Turns this set into a list.
+ *
+ * @return The corresponding list.
+ */
+ private List<String> toList() {
+ List<String> entries = new ArrayList<String>();
+ Enumeration<String> names = request.getKeys();
+ while (names.hasMoreElements()) {
+ entries.add(names.nextElement());
+ }
+ return entries;
+ }
+
+ /**
+ * Iterates elements of {@link KeySet}.
+ */
+ private class KeySetIterator implements Iterator<String> {
+
+ /**
+ * The key names enumeration.
+ */
+ private Enumeration<String> namesEnumeration = request.getKeys();
+
+ @Override
+ public boolean hasNext() {
+ return namesEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public String next() {
+ return namesEnumeration.nextElement();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/MapEntry.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/MapEntry.java
new file mode 100644
index 0000000..faf2702
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/MapEntry.java
@@ -0,0 +1,136 @@
+/*
+ * $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.request.collection;
+
+
+import java.util.Map;
+
+
+/**
+ * <p>Map.Entry implementation that can be constructed to either be read-only
+ * or not.</p>
+ *
+ * @version $Rev$ $Date$
+ * @param <K> The key type.
+ * @param <V> The value type.
+ */
+
+public class MapEntry<K, V> implements Map.Entry<K, V> {
+
+
+ /**
+ * <p>The entry key.</p>
+ */
+ private K key;
+
+ /**
+ * <p>The entry value.</p>
+ */
+ private V value;
+
+ /**
+ * <p>Whether the entry can be modified.</p>
+ */
+ private boolean modifiable = false;
+
+
+ /**
+ * <p>Creates a map entry that can either allow modifications or not.</p>
+ *
+ * @param key The entry key
+ * @param value The entry value
+ * @param modifiable Whether the entry should allow modification or not
+ */
+ public MapEntry(K key, V value, boolean modifiable) {
+ this.key = key;
+ this.value = value;
+ this.modifiable = modifiable;
+ }
+
+
+ /**
+ * <p>Gets the entry key.</p>
+ *
+ * @return The entry key
+ */
+ public K getKey() {
+ return key;
+ }
+
+
+ /**
+ * <p>Gets the entry value.</p>
+ *
+ * @return The entry key
+ */
+ public V getValue() {
+ return value;
+ }
+
+
+ /**
+ * <p>Sets the entry value if the entry can be modified.</p>
+ *
+ * @param val The new value
+ * @return The old entry value
+ * @throws UnsupportedOperationException If the entry cannot be modified
+ */
+ public V setValue(V val) {
+ if (modifiable) {
+ V oldVal = this.value;
+ this.value = val;
+ return oldVal;
+ }
+ throw new UnsupportedOperationException("The map entry is not modifiable");
+ }
+
+
+ /**
+ * <p>Determines if this entry is equal to the passed object.</p>
+ *
+ * @param o The object to test
+ * @return True if equal, else false
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean equals(Object o) {
+ if (o != null && o instanceof Map.Entry) {
+ Map.Entry<K, V> entry = (Map.Entry<K, V>) o;
+ return (this.getKey() == null ? entry.getKey() == null : this
+ .getKey().equals(entry.getKey()))
+ && (this.getValue() == null ? entry.getValue() == null
+ : this.getValue().equals(entry.getValue()));
+ }
+ return false;
+ }
+
+
+ /**
+ * <p>Returns the hashcode for this entry.</p>
+ *
+ * @return The and'ed hashcode of the key and value
+ */
+ @Override
+ public int hashCode() {
+ return (this.getKey() == null ? 0 : this.getKey().hashCode())
+ ^ (this.getValue() == null ? 0 : this.getValue().hashCode());
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java
new file mode 100644
index 0000000..4184f81
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/MapEntryArrayValues.java
@@ -0,0 +1,103 @@
+/*
+ * $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.request.collection;
+
+
+import java.util.Map;
+
+
+/**
+ * Multi-valued map entry.
+ *
+ * @version $Rev$ $Date$
+ * @param <K> The key type.
+ * @param <V> The value type.
+ */
+
+public class MapEntryArrayValues<K, V> extends MapEntry<K, V[]> {
+
+ /**
+ * Constructor.
+ *
+ * @param key The key of the entry.
+ * @param value The array of values.
+ * @param modifiable If <code>true</code> the entry is modifiable.
+ */
+ public MapEntryArrayValues(K key, V[] value, boolean modifiable) {
+ super(key, value, modifiable);
+ }
+
+
+ /**
+ * <p>Returns the hashcode for this entry.</p>
+ *
+ * @return The and'ed hashcode of the key and value
+ */
+ @Override
+ public int hashCode() {
+ int valueHash = 0;
+ V[] value = getValue();
+ if (value != null) {
+ for (int i = 0; i < value.length; i++) {
+ valueHash += value[i].hashCode();
+ }
+ }
+
+ return (this.getKey() == null ? 0 : this.getKey().hashCode())
+ ^ valueHash;
+ }
+
+ /**
+ * <p>Determines if this entry is equal to the passed object.</p>
+ *
+ * @param o The object to test
+ * @return True if equal, else false
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean equals(Object o) {
+ if (o != null && o instanceof Map.Entry) {
+ Map.Entry<K, V[]> entry = (Map.Entry<K, V[]>) o;
+ if (this.getKey() == null ? entry.getKey() == null : this
+ .getKey().equals(entry.getKey())) {
+ V[] values = getValue();
+ V[] otherValues = entry.getValue();
+ if (values != null) {
+ if (otherValues != null) {
+ if (values.length == otherValues.length) {
+ boolean same = true;
+ for (int i = 0; i < values.length && same; i++) {
+ same = values[i] == null ? otherValues[i] == null
+ : values[i].equals(otherValues[i]);
+ }
+ return same;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return otherValues == null;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java
new file mode 100644
index 0000000..5452691
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMap.java
@@ -0,0 +1,438 @@
+/*
+ * $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.request.collection;
+
+import static org.apache.tiles.request.collection.CollectionUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasKeys;
+
+/**
+ * Wraps an {@link HasKeys} object into a read-only map.
+ *
+ * @version $Rev$ $Date$
+ * @param <V> The type of the values.
+ */
+public class ReadOnlyEnumerationMap<V> implements Map<String, V> {
+
+ /**
+ * The request.
+ */
+ protected HasKeys<V> request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request object to use.
+ */
+ public ReadOnlyEnumerationMap(HasKeys<V> request) {
+ this.request = request;
+ }
+
+ /** {@inheritDoc} */
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean containsKey(Object key) {
+ return (request.getValue(key(key)) != null);
+ }
+
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ public boolean containsValue(Object value) {
+ V realValue = (V) value;
+ for (Enumeration<String> keysIt = request.getKeys(); keysIt.hasMoreElements();) {
+ if (realValue.equals(request.getValue(keysIt.nextElement()))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /** {@inheritDoc} */
+ public Set<Map.Entry<String, V>> entrySet() {
+ return new ReadOnlyEnumerationMapEntrySet();
+ }
+
+
+ /** {@inheritDoc} */
+ public V get(Object key) {
+ return (request.getValue(key(key)));
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean isEmpty() {
+ return !request.getKeys().hasMoreElements();
+ }
+
+
+ /** {@inheritDoc} */
+ public Set<String> keySet() {
+ return new KeySet(request);
+ }
+
+
+ /** {@inheritDoc} */
+ public V put(String key, V value) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public void putAll(Map<? extends String, ? extends V> map) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public V remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ /** {@inheritDoc} */
+ public int size() {
+ return enumerationSize(request.getKeys());
+ }
+
+
+ /** {@inheritDoc} */
+ public Collection<V> values() {
+ return new ReadOnlyEnumerationMapValuesCollection();
+ }
+
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object o) {
+ HasKeys<V> otherRequest = ((ReadOnlyEnumerationMap<V>) o).request;
+ boolean retValue = true;
+ Set<String> otherKeys = new HashSet<String>();
+ for (Enumeration<String> attribs = otherRequest.getKeys(); attribs
+ .hasMoreElements();) {
+ otherKeys.add(attribs.nextElement());
+ }
+ for (Enumeration<String> attribs = request.getKeys(); attribs
+ .hasMoreElements()
+ && retValue;) {
+ String parameterName = attribs.nextElement();
+ retValue = request.getValue(parameterName).equals(
+ otherRequest.getValue(parameterName));
+ otherKeys.remove(parameterName);
+ }
+
+ return retValue && otherKeys.isEmpty();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ int retValue = 0;
+ for (Enumeration<String> attribs = request.getKeys(); attribs
+ .hasMoreElements();) {
+ String parameterName = attribs.nextElement();
+ V value = request.getValue(parameterName);
+ retValue += parameterName.hashCode() ^ (value == null ? 0 : value.hashCode());
+ }
+ return retValue;
+ }
+
+ /**
+ * Entry set implementation for {@link ReadOnlyEnumerationMap}.
+ */
+ class ReadOnlyEnumerationMapEntrySet implements Set<Map.Entry<String, V>> {
+
+ @Override
+ public boolean add(java.util.Map.Entry<String, V> e) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(
+ Collection<? extends java.util.Map.Entry<String, V>> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean contains(Object o) {
+ return containsEntry((java.util.Map.Entry<String, V>) o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ Collection<Map.Entry<String, V>> realCollection =
+ (Collection<Map.Entry<String, V>>) c;
+ for (Map.Entry<String, V> entry : realCollection) {
+ if (!containsEntry(entry)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return ReadOnlyEnumerationMap.this.isEmpty();
+ }
+
+ @Override
+ public Iterator<java.util.Map.Entry<String, V>> iterator() {
+ return new ReadOnlyEnumerationMapEntrySetIterator();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return ReadOnlyEnumerationMap.this.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toList().toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return toList().toArray(a);
+ }
+
+ /**
+ * Checks whether the entry is present.
+ *
+ * @param entry The entry to check.
+ * @return <code>true</code> if the entry is present.
+ */
+ protected boolean containsEntry(Map.Entry<String, V> entry) {
+ V storedValue = request.getValue(key(entry.getKey()));
+ return storedValue != null && storedValue.equals(entry.getValue());
+ }
+
+ /**
+ * Turns this set into a list.
+ *
+ * @return The list.
+ */
+ private List<Map.Entry<String, V>> toList() {
+ List<Map.Entry<String, V>> entries = new ArrayList<Map.Entry<String, V>>();
+ Enumeration<String> names = request.getKeys();
+ while (names.hasMoreElements()) {
+ entries.add(extractNextEntry(names));
+ }
+ return entries;
+ }
+
+ /**
+ * Returns the next entry, given the enumeration.
+ *
+ * @param names The enumeration to get the next key from.
+ * @return The next entry.
+ */
+ private MapEntry<String, V> extractNextEntry(
+ Enumeration<String> names) {
+ String name = names.nextElement();
+ return new MapEntry<String, V>(name, request.getValue(name),
+ false);
+ }
+
+ /**
+ * Iterates entries of {@link ReadOnlyEnumerationMap}.
+ */
+ private class ReadOnlyEnumerationMapEntrySetIterator implements Iterator<Map.Entry<String, V>> {
+
+ /**
+ * Enumerates keys.
+ */
+ private Enumeration<String> namesEnumeration = request.getKeys();
+
+ @Override
+ public boolean hasNext() {
+ return namesEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public java.util.Map.Entry<String, V> next() {
+ return extractNextEntry(namesEnumeration);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+ }
+
+ /**
+ * Values collection for {@link ReadOnlyEnumerationMap}.
+ */
+ private class ReadOnlyEnumerationMapValuesCollection implements Collection<V> {
+
+ @Override
+ public boolean add(V e) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends V> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return containsValue(o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ Collection<String> realCollection = (Collection<String>) c;
+ List<String> valueList = new ArrayList<String>(realCollection);
+ for (Enumeration<String> keysEnum = request.getKeys(); keysEnum.hasMoreElements();) {
+ valueList.remove(request.getValue(keysEnum.nextElement()));
+ if (valueList.isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return ReadOnlyEnumerationMap.this.isEmpty();
+ }
+
+ @Override
+ public Iterator<V> iterator() {
+ return new ReadOnlyEnumerationMapValuesCollectionIterator();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return ReadOnlyEnumerationMap.this.size();
+ }
+
+ @Override
+ public Object[] toArray() {
+ return toList().toArray();
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ return toList().toArray(a);
+ }
+
+ /**
+ * Turns this collection into a list.
+ *
+ * @return The list.
+ */
+ private List<V> toList() {
+ List<V> entries = new ArrayList<V>();
+ Enumeration<String> names = request.getKeys();
+ while (names.hasMoreElements()) {
+ entries.add(request.getValue(names.nextElement()));
+ }
+ return entries;
+ }
+
+ /**
+ * Iterates values of {@link ReadOnlyEnumerationMap}.
+ */
+ private class ReadOnlyEnumerationMapValuesCollectionIterator implements Iterator<V> {
+
+ /**
+ * Enumerates attribute keys.
+ */
+ private Enumeration<String> namesEnumeration = request.getKeys();
+
+ @Override
+ public boolean hasNext() {
+ return namesEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public V next() {
+ return request.getValue(namesEnumeration.nextElement());
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.java
new file mode 100644
index 0000000..1430f80
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/RemovableKeySet.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.request.collection;
+
+import static org.apache.tiles.request.collection.CollectionUtil.*;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasRemovableKeys;
+
+/**
+ * Wraps {@link HasRemovableKeys} keys as a set.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RemovableKeySet extends KeySet {
+
+ /**
+ * The request.
+ */
+ private HasRemovableKeys<?> request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request.
+ */
+ public RemovableKeySet(HasRemovableKeys<?> request) {
+ super(request);
+ this.request = request;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ String skey = key(o);
+ Object previous = request.getValue(skey);
+ if (previous != null) {
+ request.removeValue(skey);
+ return true;
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ Collection<String> realCollection = (Collection<String>) c;
+ boolean retValue = false;
+ for (String entry : realCollection) {
+ retValue |= remove(entry);
+ }
+ return retValue;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ Collection<String> realCollection = (Collection<String>) c;
+ boolean retValue = false;
+ Set<String> keysToRemove = new LinkedHashSet<String>();
+ for (Enumeration<String> keys = request.getKeys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ if (!realCollection.contains(key)) {
+ retValue = true;
+ keysToRemove.add(key);
+ }
+ }
+ for (String key : keysToRemove) {
+ request.removeValue(key);
+ }
+ return retValue;
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/ScopeMap.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/ScopeMap.java
new file mode 100644
index 0000000..93465ea
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/ScopeMap.java
@@ -0,0 +1,178 @@
+/*
+ * $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.request.collection;
+
+import static org.apache.tiles.request.collection.CollectionUtil.*;
+
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Exposes a scope context as a <String, Object> map.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public class ScopeMap extends ReadOnlyEnumerationMap<Object> {
+
+ /**
+ * The context to read.
+ */
+ private AttributeExtractor context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The servlet context to use.
+ */
+ public ScopeMap(AttributeExtractor context) {
+ super(context);
+ this.context = context;
+ }
+
+
+ /** {@inheritDoc} */
+ public void clear() {
+ Enumeration<String> keys = context.getKeys();
+ while (keys.hasMoreElements()) {
+ context.removeValue(keys.nextElement());
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Set<Map.Entry<String, Object>> entrySet() {
+ return new ScopeEntrySet();
+ }
+
+ /** {@inheritDoc} */
+ public Set<String> keySet() {
+ return new RemovableKeySet(context);
+ }
+
+ /** {@inheritDoc} */
+ public Object put(String key, Object value) {
+ String skey = key(key);
+ Object previous = context.getValue(skey);
+ context.setValue(skey, value);
+ return previous;
+ }
+
+ /** {@inheritDoc} */
+ public void putAll(Map<? extends String, ? extends Object> map) {
+ Iterator<? extends String> keys = map.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = keys.next();
+ context.setValue(key, map.get(key));
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Object remove(Object key) {
+ String skey = key(key);
+ Object previous = context.getValue(skey);
+ context.removeValue(skey);
+ return (previous);
+ }
+
+ /**
+ * Entry set implementation for {@link ScopeMap}.
+ */
+ private class ScopeEntrySet extends ReadOnlyEnumerationMap<Object>.ReadOnlyEnumerationMapEntrySet {
+
+ @Override
+ public boolean add(java.util.Map.Entry<String, Object> e) {
+ String key = e.getKey();
+ Object value = e.getValue();
+ Object oldValue = get(key);
+ if (oldValue == null || !oldValue.equals(value)) {
+ context.setValue(key, value);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addAll(
+ Collection<? extends java.util.Map.Entry<String, Object>> c) {
+ boolean retValue = false;
+ for (Map.Entry<String, Object> entry : c) {
+ retValue |= add(entry);
+ }
+ return retValue;
+ }
+
+ @Override
+ public void clear() {
+ ScopeMap.this.clear();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean remove(Object o) {
+ Map.Entry<String, Object> entry = (java.util.Map.Entry<String, Object>) o;
+ String key = entry.getKey();
+ Object currentValue = context.getValue(key);
+ if (currentValue != null && currentValue.equals(entry.getValue())) {
+ context.removeValue(key);
+ return true;
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ Collection<Map.Entry<String, Object>> realCollection = (Collection<java.util.Map.Entry<String, Object>>) c;
+ boolean retValue = false;
+ for (Map.Entry<String, Object> entry : realCollection) {
+ retValue |= remove(entry);
+ }
+ return retValue;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ Collection<Map.Entry<String, Object>> realCollection = (Collection<java.util.Map.Entry<String, Object>>) c;
+ boolean retValue = false;
+ Set<String> keysToRemove = new LinkedHashSet<String>();
+ for (Enumeration<String> keys = context.getKeys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ Object value = context.getValue(key);
+ Map.Entry<String, Object> entry = new MapEntry<String, Object>(key, value, false);
+ if (!realCollection.contains(entry)) {
+ retValue = true;
+ keysToRemove.add(key);
+ }
+ }
+ for (String key : keysToRemove) {
+ context.removeValue(key);
+ }
+ return retValue;
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/package-info.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/package-info.java
new file mode 100644
index 0000000..02818bf
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/collection/package-info.java
@@ -0,0 +1,36 @@
+/*
+ * $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.
+ */
+/**
+ * Special collections and maps for attributes (like HTTP request
+ * or session attributes).
+ * These can be used to access another object's attributes through
+ * a Map interface.
+ * <ul>
+ * <li> {@link org.apache.tiles.request.collection.ScopeMap} provides
+ * full get/put/remove access to the attributes.
+ * <li> {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap}
+ * provides get-only access.
+ * <li> {@link org.apache.tiles.request.collection.HeaderValuesMap}
+ * provides get-only access to a multi-valued map (typically, headers).
+ * </ul>
+ */
+package org.apache.tiles.request.collection;
+
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java
new file mode 100644
index 0000000..4da8afd
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/LocaleUtil.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request.locale;
+
+import java.util.Locale;
+
+/**
+ * Utilities for locale manipulation.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class LocaleUtil {
+
+ /**
+ * The "null" Locale, i.e. a Locale that points to no real locale.
+ *
+ * @deprecated use Locale.ROOT instead.
+ */
+ @Deprecated
+ public static final Locale NULL_LOCALE = Locale.ROOT;
+
+ /**
+ * Private constructor to avoid instantiation.
+ */
+ private LocaleUtil() {
+ }
+
+ /**
+ * <p>
+ * Returns the "parent" locale of a given locale.
+ * </p>
+ * <p>
+ * If the original locale is only language-based, the {@link #NULL_LOCALE}
+ * object is returned.
+ * </p>
+ * <p>
+ * If the original locale is {@link #NULL_LOCALE}, then <code>null</code>
+ * is returned.
+ * </p>
+ *
+ * @param locale The original locale.
+ * @return The parent locale.
+ */
+ public static Locale getParentLocale(Locale locale) {
+ Locale retValue = null;
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+ if (!"".equals(variant)) {
+ retValue = new Locale(language, country);
+ } else if (!"".equals(country)) {
+ retValue = new Locale(language);
+ } else if (!"".equals(language)) {
+ retValue = Locale.ROOT;
+ }
+
+ return retValue;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java
new file mode 100644
index 0000000..9864239
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/PostfixedApplicationResource.java
@@ -0,0 +1,196 @@
+/*
+ * $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.request.locale;
+
+import java.util.Locale;
+
+import org.apache.tiles.request.ApplicationResource;
+
+/**
+ * An ApplicationResource whose localization is managed by postfixing the file name.
+ * The various localizations are file sitting next to each other, with the locale identified in the postfix.
+ *
+ * For instance:
+ * <pre>
+ * /WEB-INF/tiles.xml
+ * /WEB-INF/tiles_fr.xml
+ * /WEB-INF/tiles_it.xml
+ * /WEB-INF/tiles_it_IT.xml
+ * </pre>
+ *
+ * Two PostfixedApplicationResources are equals if they share the same localized path and the same class.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class PostfixedApplicationResource implements ApplicationResource {
+
+ /** The path without its suffix and its locale postfix. */
+ private String pathPrefix;
+ /** The suffix. */
+ private String suffix;
+ /** The Locale. */
+ private Locale locale;
+
+ /**
+ * Create a new PostfixedApplicationResource for the specified path.
+ * @param localePath the path including localization.
+ */
+ protected PostfixedApplicationResource(String localePath) {
+ int prefixIndex = localePath.indexOf('_', localePath.lastIndexOf("/"));
+ int suffixIndex = localePath.lastIndexOf('.');
+ if (suffixIndex < 0) {
+ suffix = "";
+ suffixIndex = localePath.length();
+ } else {
+ suffix = localePath.substring(suffixIndex);
+ }
+ if (prefixIndex < 0) {
+ pathPrefix = localePath.substring(0, suffixIndex);
+ locale = Locale.ROOT;
+ } else {
+ pathPrefix = localePath.substring(0, prefixIndex);
+ String localeString = localePath.substring(prefixIndex + 1, suffixIndex);
+ int countryIndex = localeString.indexOf('_');
+ if (countryIndex < 0) {
+ locale = new Locale(localeString);
+ } else {
+ int variantIndex = localeString.indexOf('_', countryIndex + 1);
+ if (variantIndex < 0) {
+ locale = new Locale(localeString.substring(0, countryIndex),
+ localeString.substring(countryIndex + 1));
+ } else {
+ locale = new Locale(localeString.substring(0, countryIndex), localeString.substring(
+ countryIndex + 1, variantIndex), localeString.substring(variantIndex + 1));
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a new PostfixedApplicationResource for the specified path.
+ * @param path the path excluding localization.
+ * @param locale the Locale.
+ */
+ protected PostfixedApplicationResource(String path, Locale locale) {
+ int suffixIndex = path.lastIndexOf('.');
+ if (suffixIndex < 0) {
+ suffix = "";
+ pathPrefix = path;
+ } else {
+ pathPrefix = path.substring(0, suffixIndex);
+ suffix = path.substring(suffixIndex);
+ }
+ this.locale = locale;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final String getLocalePath() {
+ return getLocalePath(locale);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final String getPath() {
+ return pathPrefix + suffix;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final String getLocalePath(Locale newLocale) {
+ return pathPrefix + getPostfix(newLocale) + suffix;
+ }
+
+ /**
+ * Get the postfix for that Locale.
+ * @param locale a locale.
+ * @return the matching postfix.
+ */
+ private static final String getPostfix(Locale locale) {
+ if (locale == null) {
+ return "";
+ }
+
+ StringBuilder builder = new StringBuilder();
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+ if (!"".equals(language)) {
+ builder.append("_");
+ builder.append(language);
+ if (!"".equals(country)) {
+ builder.append("_");
+ builder.append(country);
+ if (!"".equals(variant)) {
+ builder.append("_");
+ builder.append(variant);
+ }
+ }
+ }
+ return builder.toString();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public final Locale getLocale() {
+ return locale;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((locale == null) ? 0 : locale.hashCode());
+ result = prime * result + ((pathPrefix == null) ? 0 : pathPrefix.hashCode());
+ result = prime * result + ((suffix == null) ? 0 : suffix.hashCode());
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ PostfixedApplicationResource other = (PostfixedApplicationResource) obj;
+ if (locale == null) {
+ if (other.locale != null)
+ return false;
+ } else if (!locale.equals(other.locale))
+ return false;
+ if (pathPrefix == null) {
+ if (other.pathPrefix != null)
+ return false;
+ } else if (!pathPrefix.equals(other.pathPrefix))
+ return false;
+ if (suffix == null) {
+ if (other.suffix != null)
+ return false;
+ } else if (!suffix.equals(other.suffix))
+ return false;
+ return true;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java
new file mode 100644
index 0000000..9535a20
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/locale/URLApplicationResource.java
@@ -0,0 +1,107 @@
+/*
+ * $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.request.locale;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Locale;
+
+/**
+ * A {@link PostfixedApplicationResource} that can be accessed through a URL.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public class URLApplicationResource extends PostfixedApplicationResource {
+
+ /** the URL where the contents can be found. */
+ private URL url;
+ /** if the URL matches a file, this is the file. */
+ private File file;
+
+ /**
+ * Creates a URLApplicationResource for the specified path that can be accessed through the specified URL.
+ *
+ * @param localePath the path including localization.
+ * @param url the URL where the contents can be found.
+ */
+ public URLApplicationResource(String localePath, URL url) {
+ super(localePath);
+ this.url = url;
+ if ("file".equals(url.getProtocol())) {
+ file = new File(url.getPath());
+ }
+ }
+
+ /**
+ * Creates a URLApplicationResource for the specified path that can be accessed through the specified URL.
+ *
+ * @param path the path excluding localization.
+ * @param locale the Locale.
+ * @param url the URL where the contents can be found.
+ */
+ public URLApplicationResource(String path, Locale locale, URL url) throws MalformedURLException {
+ super(path, locale);
+ this.url = new URL(url, getLocalePath());
+ if ("file".equals(url.getProtocol())) {
+ file = new File(this.url.getPath());
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public InputStream getInputStream() throws IOException {
+ if (file != null) {
+ return new FileInputStream(file);
+ } else {
+ return url.openConnection().getInputStream();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public long getLastModified() throws IOException {
+ if (file != null) {
+ return file.lastModified();
+ } else {
+ URLConnection connection = url.openConnection();
+ if (connection instanceof JarURLConnection) {
+ return ((JarURLConnection) connection).getJarEntry().getTime();
+ } else {
+ long result = connection.getLastModified();
+ return result;
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String toString() {
+ return "Resource " + getLocalePath() + " at " + url.toString();
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/package-info.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/package-info.java
new file mode 100644
index 0000000..65d2558
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/package-info.java
@@ -0,0 +1,46 @@
+/*
+ * $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.
+ */
+/**
+ * This package defines the concept of "request" as the event causing a
+ * document to be generated from a template. The process is also called
+ * "rendering the template". Typical examples are servlet requests or
+ * portlet requests.
+ *
+ * This API is independent of the underlying technology, allowing the user
+ * to deal with similarities in servlets and portlets, or various template
+ * technologies, in a uniform way.
+ *
+ * It is based on 3 main interfaces:
+ * <ul>
+ * <li>{@link org.apache.tiles.request.Request} is the main abstraction,
+ * encapsulating the parameters of the template (as attributes and scopes)
+ * and the target document (as java.io.OutputStream).
+ * {@link org.apache.tiles.request.DispatchRequest} holds some features common
+ * to servlets and portlets that are unlikely to be found outside of a JavaEE
+ * web environment.
+ * <li>{@link org.apache.tiles.ApplicationContext} can be used to access
+ * application-wide configuration and resources (typically the files containing
+ * the templates).
+ * <li>{@link org.apache.tiles.request.render.Renderer} is the interface supported
+ * by the engine in charge of rendering the template.
+ * <ul>
+ */
+package org.apache.tiles.request;
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/CannotAccessMethodException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/CannotAccessMethodException.java
new file mode 100644
index 0000000..3311ab5
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/CannotAccessMethodException.java
@@ -0,0 +1,66 @@
+/*
+ * $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.request.reflect;
+
+import org.apache.tiles.request.RequestException;
+
+/**
+ * Indicates that a method cannot be accessed.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CannotAccessMethodException extends RequestException {
+
+ /**
+ * Constructor.
+ */
+ public CannotAccessMethodException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public CannotAccessMethodException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The exception to be wrapped.
+ */
+ public CannotAccessMethodException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public CannotAccessMethodException(String message, Throwable e) {
+ super(message, e);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java
new file mode 100644
index 0000000..08b6621
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/CannotInstantiateObjectException.java
@@ -0,0 +1,66 @@
+/*
+ * $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.request.reflect;
+
+import org.apache.tiles.request.RequestException;
+
+/**
+ * Indicates that an object cannot be instantiated.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CannotInstantiateObjectException extends RequestException {
+
+ /**
+ * Constructor.
+ */
+ public CannotInstantiateObjectException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public CannotInstantiateObjectException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The exception to be wrapped.
+ */
+ public CannotInstantiateObjectException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public CannotInstantiateObjectException(String message, Throwable e) {
+ super(message, e);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java
new file mode 100644
index 0000000..96a9898
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/ClassUtil.java
@@ -0,0 +1,144 @@
+/*
+ * $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.request.reflect;
+
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Utilities to work with dynamic class loading and instantiation.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class ClassUtil {
+
+ /**
+ * Constructor, private to avoid instantiation.
+ */
+ private ClassUtil() {
+ }
+
+ /**
+ * Returns the class and casts it to the correct subclass.<br>
+ * It tries to use the thread's current classloader first and, if it does
+ * not succeed, uses the classloader of ClassUtil.
+ *
+ * @param <T> The subclass to use.
+ * @param className The name of the class to load.
+ * @param baseClass The base class to subclass to.
+ * @return The loaded class.
+ * @throws ClassNotFoundException If the class has not been found.
+ */
+ public static <T> Class<? extends T> getClass(String className,
+ Class<T> baseClass) throws ClassNotFoundException {
+ ClassLoader classLoader = Thread.currentThread()
+ .getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = ClassUtil.class.getClassLoader();
+ }
+ return Class.forName(className, true, classLoader)
+ .asSubclass(baseClass);
+ }
+
+ /**
+ * 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.
+ */
+ 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.
+ */
+ public static Object instantiate(String className, boolean returnNull) {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ if (classLoader == null) {
+ classLoader = ClassUtil.class.getClassLoader();
+ }
+ try {
+ Class<? extends Object> namedClass = getClass(className, Object.class);
+ 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);
+ }
+ }
+
+ /**
+ * Collects bean infos from a class and filling a list.
+ *
+ * @param clazz The class to be inspected.
+ * @param name2descriptor The map in the form: name of the property ->
+ * descriptor.
+ */
+ public static void collectBeanInfo(Class<?> clazz,
+ Map<String, PropertyDescriptor> name2descriptor) {
+ Logger log = LoggerFactory.getLogger(ClassUtil.class);
+ BeanInfo info = null;
+ try {
+ info = Introspector.getBeanInfo(clazz);
+ } catch (Exception ex) {
+ if (log.isDebugEnabled()) {
+ log.debug("Cannot inspect class " + clazz, ex);
+ }
+ }
+ if (info == null) {
+ return;
+ }
+ for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
+ pd.setValue("type", pd.getPropertyType());
+ pd.setValue("resolvableAtDesignTime", Boolean.TRUE);
+ name2descriptor.put(pd.getName(), pd);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/package-info.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/package-info.java
new file mode 100644
index 0000000..299c145
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/reflect/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Utilities to work with dynamic class loading and instantiation.
+ */
+package org.apache.tiles.request.reflect;
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java
new file mode 100644
index 0000000..e580400
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/BasicRendererFactory.java
@@ -0,0 +1,84 @@
+/*
+ * $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.request.render;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * Basic renderer factory implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BasicRendererFactory implements RendererFactory {
+
+ /**
+ * The renderer name/renderer map.
+ */
+ protected Map<String, Renderer> renderers;
+
+ /**
+ * The default renderer.
+ */
+ protected Renderer defaultRenderer;
+
+ /**
+ * Constructor.
+ */
+ public BasicRendererFactory() {
+ renderers = new HashMap<String, Renderer>();
+ }
+
+ /** {@inheritDoc} */
+ public Renderer getRenderer(String name) {
+ Renderer retValue;
+ if (name != null) {
+ retValue = renderers.get(name);
+ if (retValue == null) {
+ throw new NoSuchRendererException("Cannot find a renderer named '" + name + "'");
+ }
+ } else {
+ retValue = defaultRenderer;
+ }
+
+ return retValue;
+ }
+
+ /**
+ * Sets the default renderer.
+ *
+ * @param renderer The default renderer.
+ */
+ public void setDefaultRenderer(Renderer renderer) {
+ this.defaultRenderer = renderer;
+ }
+
+ /**
+ * Registers a renderer.
+ *
+ * @param name The name of the renderer.
+ * @param renderer The renderer to register.
+ */
+ public void registerRenderer(String name, Renderer renderer) {
+ renderers.put(name, renderer);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/CannotRenderException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/CannotRenderException.java
new file mode 100644
index 0000000..0e5ddf3
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/CannotRenderException.java
@@ -0,0 +1,65 @@
+/*
+ * $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.request.render;
+
+
+/**
+ * Indicates that something went wrong during the rendering process.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CannotRenderException extends RenderException {
+
+ /**
+ * Constructor.
+ */
+ public CannotRenderException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public CannotRenderException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The exception to be wrapped.
+ */
+ public CannotRenderException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public CannotRenderException(String message, Throwable e) {
+ super(message, e);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java
new file mode 100644
index 0000000..0b1de93
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/ChainedDelegateRenderer.java
@@ -0,0 +1,85 @@
+/*
+ * $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.request.render;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * Renders an attribute that has no associated renderer using delegation to
+ * other renderers.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ChainedDelegateRenderer implements Renderer {
+
+ /**
+ * The list of chained renderers.
+ */
+ private List<Renderer> renderers;
+
+ /**
+ * Constructor.
+ */
+ public ChainedDelegateRenderer() {
+ renderers = new ArrayList<Renderer>();
+ }
+
+ /**
+ * Adds an attribute renderer to the list. The first inserted this way, the
+ * first is checked when rendering.
+ *
+ * @param renderer The renderer to add.
+ */
+ public void addAttributeRenderer(Renderer renderer) {
+ renderers.add(renderer);
+ }
+
+
+ @Override
+ public void render(String value, Request request) throws IOException {
+ if (value == null) {
+ throw new NullPointerException("The attribute value is null");
+ }
+
+ for (Renderer renderer : renderers) {
+ if (renderer.isRenderable(value, request)) {
+ renderer.render(value, request);
+ return;
+ }
+ }
+
+ throw new CannotRenderException("Cannot renderer value '" + value + "'");
+ }
+
+ /** {@inheritDoc} */
+ public boolean isRenderable(String value, Request request) {
+ for (Renderer renderer : renderers) {
+ if (renderer.isRenderable(value, request)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java
new file mode 100644
index 0000000..ef3ed25
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/DispatchRenderer.java
@@ -0,0 +1,52 @@
+/*
+ * $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.request.render;
+
+import java.io.IOException;
+
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.DispatchRequest;
+
+/**
+ * Renders an attribute that contains a reference to a template.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DispatchRenderer implements Renderer {
+
+ /** {@inheritDoc} */
+ @Override
+ public void render(String path, Request request) throws IOException {
+ if (path == null) {
+ throw new CannotRenderException("Cannot dispatch a null path");
+ }
+ if (!(request instanceof DispatchRequest)) {
+ throw new CannotRenderException("Cannot dispatch outside of a web environment");
+ }
+
+ ((DispatchRequest) request).dispatch(path);
+ }
+
+ /** {@inheritDoc} */
+ public boolean isRenderable(String path, Request request) {
+ return path != null && path.startsWith("/");
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java
new file mode 100644
index 0000000..3240d0f
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/NoSuchRendererException.java
@@ -0,0 +1,66 @@
+/*
+ * $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.request.render;
+
+
+/**
+ * It is raised when a named renderer has not been found with that name.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NoSuchRendererException extends RenderException {
+
+ /**
+ * Constructor.
+ */
+ public NoSuchRendererException() {
+ super();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public NoSuchRendererException(String message, Throwable e) {
+ super(message, e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public NoSuchRendererException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The exception to be wrapped.
+ */
+ public NoSuchRendererException(Throwable e) {
+ super(e);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/PublisherRenderer.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/PublisherRenderer.java
new file mode 100644
index 0000000..a6a0baa
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/PublisherRenderer.java
@@ -0,0 +1,101 @@
+/*
+ * $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.request.render;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * Provides a Publisher-Subscriber implementation around the provided renderer to delegate to.
+ *
+ * @version $Rev: 1035784 $ $Date: 2010-11-16 20:24:12 +0000 (Tue, 16 Nov 2010) $
+ */
+public class PublisherRenderer implements Renderer {
+
+ public interface RendererListener{
+ /** Called before the delegate's render method is called. */
+ void start(String template, Request request) throws IOException;
+ /** Called after the delegate's render method is called. */
+ void end(String template, Request request) throws IOException;
+ /** If the delegate render method throws an IOException it is passed through this. */
+ void handleIOException(IOException ex, Request request) throws IOException;
+ }
+
+ private final Renderer renderer;
+ private final List<RendererListener> listeners = new ArrayList<RendererListener>();
+ private final List<RendererListener> listenersReversed = new ArrayList<RendererListener>();
+
+ public PublisherRenderer(Renderer renderer){
+ this.renderer = renderer;
+ }
+
+ @Override
+ public void render(String path, Request request) throws IOException {
+ if (path == null) {
+ throw new CannotRenderException("Cannot dispatch a null path");
+ }
+ try{
+ for(RendererListener listener : listeners){
+ listener.start(path, request);
+ }
+ renderer.render(path, request);
+ }catch(IOException ex){
+ handleIOException(ex, request);
+ }finally{
+ for(RendererListener wrapper : listenersReversed){
+ wrapper.end(path, request);
+ }
+ }
+ }
+
+ @Override
+ public boolean isRenderable(String path, Request request) {
+ return renderer.isRenderable(path, request);
+ }
+
+ public void addListener(RendererListener listener){
+ listeners.add(listener);
+ listenersReversed.clear();
+ listenersReversed.addAll(listeners);
+ Collections.reverse(listenersReversed);
+ }
+
+ private void handleIOException(IOException exception, Request request) throws IOException{
+ IOException ex = exception;
+ boolean throwIt = listeners.isEmpty();
+ for(RendererListener listener : listenersReversed){
+ try{
+ listener.handleIOException(ex, request);
+ throwIt = false;
+ }catch(IOException newEx){
+ ex = newEx;
+ throwIt = true;
+ }
+ }
+ if(throwIt){
+ throw ex;
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/RenderException.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/RenderException.java
new file mode 100644
index 0000000..37fcee7
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/RenderException.java
@@ -0,0 +1,65 @@
+/*
+ * $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.request.render;
+
+import org.apache.tiles.request.RequestException;
+
+/**
+ * Thrown when rendering fails.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RenderException extends RequestException {
+
+ /**
+ * Constructor.
+ */
+ public RenderException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ */
+ public RenderException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause.
+ */
+ public RenderException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ * @param cause The cause.
+ */
+ public RenderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/Renderer.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/Renderer.java
new file mode 100644
index 0000000..79db2ac
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/Renderer.java
@@ -0,0 +1,53 @@
+/*
+ * $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.request.render;
+
+import java.io.IOException;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * An object that can render a path, depending on the request passed as a
+ * parameter.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Renderer {
+
+ /**
+ * Renders a path.
+ *
+ * @param path The path to render.
+ * @param request The Tiles request context.
+ * @throws IOException If something goes wrong during rendition.
+ */
+ void render(String path, Request request) throws IOException;
+
+ /**
+ * Checks if this renderer can render a path. Note that this does not mean
+ * it is the <strong>best</strong> renderer available, but checks only its capability.
+ *
+ * @param path The path to be rendered.
+ * @param request The request context.
+ * @return <code>true</code> if this renderer can render the attribute.
+ */
+ boolean isRenderable(String path, Request request);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/RendererFactory.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/RendererFactory.java
new file mode 100644
index 0000000..163206f
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/RendererFactory.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.request.render;
+
+
+
+/**
+ * <p>
+ * Factory interface used to create/retrieve instances of the
+ * {@link AttributeRenderer} interface.
+ * </p>
+ *
+ * <p>
+ * This factory provides an extension point into the default tiles
+ * implementation. Implementors wishing to provide per request initialization of
+ * the AttributeRenderer (for instance) may provide a custom renderer.
+ * </p>
+ *
+ * @version $Rev$ $Date$
+ */
+public interface RendererFactory {
+
+ /**
+ * Returns a renderer by its name.
+ *
+ * @param name The name of the renderer.
+ * @return The renderer.
+ */
+ Renderer getRenderer(String name);
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/StringRenderer.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/StringRenderer.java
new file mode 100644
index 0000000..b31a57a
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/StringRenderer.java
@@ -0,0 +1,47 @@
+/*
+ * $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.request.render;
+
+import java.io.IOException;
+
+import org.apache.tiles.request.Request;
+
+/**
+ * Renders an attribute that contains a string.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StringRenderer implements Renderer {
+
+ /** {@inheritDoc} */
+ @Override
+ public void render(String value, Request request) throws IOException {
+ if (value == null) {
+ throw new CannotRenderException("Cannot render a null string");
+ }
+ request.getWriter().write(value);
+ }
+
+ /** {@inheritDoc} */
+ public boolean isRenderable(String value, Request request) {
+ return value != null;
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/package-info.java b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/package-info.java
new file mode 100644
index 0000000..1796814
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/main/java/org/apache/tiles/request/render/package-info.java
@@ -0,0 +1,35 @@
+/*
+ * $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.
+ */
+/**
+ * Classes to allow rendering of a template (described by its path)
+ * in a uniform way.
+ *
+ * Besides the top level interface {@link org.apache.tiles.request.render.Renderer},
+ * the package contains:
+ * <ul>
+ * <li>trivial examples: {@link org.apache.tiles.request.render.StringRenderer}
+ * and {@link org.apache.tiles.request.render.DispatchRenderer}.
+ * <li>usual design patterns: {@link org.apache.tiles.request.render.ChainedDelegateRenderer},
+ * {@link org.apache.tiles.request.render.PublisherRenderer}, and
+ * {@link org.apache.tiles.request.render.RendererFactory}.
+ * </ul>
+ */
+package org.apache.tiles.request.render;
diff --git a/tiles-request/tiles-request-api/src/site/site.xml b/tiles-request/tiles-request-api/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.java
new file mode 100644
index 0000000..9a62e8a
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractClientRequestTest.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.request;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractClientRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractClientRequestTest {
+
+ /**
+ * The request to test.
+ */
+ private AbstractClientRequest request;
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * The application scope.
+ */
+ private Map<String, Object> applicationScope;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ applicationContext = createMock(ApplicationContext.class);
+ applicationScope = new HashMap<String, Object>();
+ request = createMockBuilder(AbstractClientRequest.class)
+ .withConstructor(applicationContext).createMock();
+
+ expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractClientRequest#dispatch(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testDispatch() throws IOException {
+ Map<String, Object> requestScope = new HashMap<String, Object>();
+
+ expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+ request.doForward("/my/path.html");
+ request.doInclude("/my/path2.html");
+
+ replay(request, applicationContext);
+ request.dispatch("/my/path.html");
+ request.dispatch("/my/path2.html");
+ verify(request, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractClientRequest#include(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testInclude() throws IOException {
+ Map<String, Object> requestScope = new HashMap<String, Object>();
+
+ expect(request.getContext("request")).andReturn(requestScope).anyTimes();
+ request.doInclude("/my/path2.html");
+
+ replay(request, applicationContext);
+ request.include("/my/path2.html");
+ assertTrue((Boolean)request.getContext("request").get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME));
+ verify(request, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractClientRequest#getApplicationContext()}.
+ */
+ @Test
+ public void testGetApplicationContext() {
+ replay(request, applicationContext);
+ assertEquals(applicationContext, request.getApplicationContext());
+ verify(request, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractClientRequest#getContext(java.lang.String)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetContext() {
+ Map<String, Object> scope = createMock(Map.class);
+
+ expect(request.getContext("myScope")).andReturn(scope);
+
+ replay(request, applicationContext, scope);
+ assertEquals(scope, request.getContext("myScope"));
+ verify(request, applicationContext, scope);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractClientRequest#getAvailableScopes()}.
+ */
+ @Test
+ public void testGetAvailableScopes() {
+ String[] scopes = new String[] {"one", "two", "three"};
+
+ expect(request.getAvailableScopes()).andReturn(Arrays.asList(scopes));
+
+ replay(request, applicationContext);
+ assertArrayEquals(scopes, request.getAvailableScopes().toArray());
+ verify(request, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractClientRequest#getApplicationScope()}.
+ */
+ @Test
+ public void testGetApplicationScope() {
+ replay(request, applicationContext);
+ assertEquals(applicationScope, request.getApplicationScope());
+ verify(request, applicationContext);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractRequestTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractRequestTest.java
new file mode 100644
index 0000000..367fea7
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractRequestTest.java
@@ -0,0 +1,54 @@
+/*
+ * $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.request;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractRequestTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractRequest#setForceInclude(boolean)}.
+ */
+ @Test
+ public void testSetForceInclude() {
+ AbstractRequest request = createMockBuilder(AbstractRequest.class).createMock();
+ Map<String, Object> scope = new HashMap<String, Object>();
+
+ expect(request.getContext("request")).andReturn(scope).anyTimes();
+
+ replay(request);
+ assertFalse(request.isForceInclude());
+ request.setForceInclude(true);
+ assertTrue(request.isForceInclude());
+ verify(request);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java
new file mode 100644
index 0000000..283648d
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/AbstractViewRequestTest.java
@@ -0,0 +1,122 @@
+/*
+ * $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.request;
+
+import static org.junit.Assert.*;
+import static org.easymock.classextension.EasyMock.*;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractViewRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AbstractViewRequestTest {
+
+ /**
+ * The request to test.
+ */
+ private AbstractViewRequest request;
+
+ /**
+ * The internal request.
+ */
+ private DispatchRequest wrappedRequest;
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * The application scope.
+ */
+ private Map<String, Object> applicationScope;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ wrappedRequest = createMock(DispatchRequest.class);
+ request = createMockBuilder(AbstractViewRequest.class).withConstructor(
+ wrappedRequest).createMock();
+ applicationContext = createMock(ApplicationContext.class);
+ applicationScope = new HashMap<String, Object>();
+
+ expect(wrappedRequest.getApplicationContext()).andReturn(applicationContext).anyTimes();
+ expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractViewRequest#dispatch(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testDispatch() throws IOException {
+ Map<String, Object> requestScope = new HashMap<String, Object>();
+
+ expect(request.getContext("request")).andReturn(requestScope);
+ wrappedRequest.include("/my/path.html");
+
+ replay(wrappedRequest, request, applicationContext);
+ request.dispatch("/my/path.html");
+ assertTrue((Boolean) requestScope.get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME));
+ verify(wrappedRequest, request, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractViewRequest#include(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testInclude() throws IOException {
+ Map<String, Object> requestScope = new HashMap<String, Object>();
+
+ expect(request.getContext("request")).andReturn(requestScope);
+ wrappedRequest.include("/my/path.html");
+
+ replay(wrappedRequest, request, applicationContext);
+ request.include("/my/path.html");
+ assertTrue((Boolean) requestScope.get(AbstractRequest.FORCE_INCLUDE_ATTRIBUTE_NAME));
+ verify(wrappedRequest, request, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.AbstractViewRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testDoInclude() throws IOException {
+ wrappedRequest.include("/my/path.html");
+
+ replay(wrappedRequest, request, applicationContext);
+ request.doInclude("/my/path.html");
+ verify(wrappedRequest, request, applicationContext);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java
new file mode 100644
index 0000000..4d4de4c
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/ApplicationAccessTest.java
@@ -0,0 +1,55 @@
+/*
+ * $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.request;
+
+import static org.junit.Assert.*;
+import static org.easymock.EasyMock.*;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link ApplicationAccess}.
+ *
+ * @version $Rev: 1066446 $ $Date: 2011-02-02 13:38:04 +0100 (Wed, 02 Feb 2011) $
+ */
+public class ApplicationAccessTest {
+
+ /**
+ * Test method for {@link ApplicationAccess#register(ApplicationContext)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRegister() {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ Map<String, Object> applicationScope = createMock(Map.class);
+
+ expect(applicationContext.getApplicationScope()).andReturn(applicationScope);
+ expect(applicationScope.put(ApplicationAccess
+ .APPLICATION_CONTEXT_ATTRIBUTE, applicationContext)).andReturn(null);
+
+ replay(applicationContext, applicationScope);
+ ApplicationAccess.register(applicationContext);
+ verify(applicationContext, applicationScope);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/ApplicationContextWrapperTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/ApplicationContextWrapperTest.java
new file mode 100644
index 0000000..f5ebfa7
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/ApplicationContextWrapperTest.java
@@ -0,0 +1,142 @@
+/*
+ * $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.request;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link ApplicationContextWrapper}.
+ *
+ * @version $Rev: 1066446 $ $Date: 2011-02-02 13:38:04 +0100 (Wed, 02 Feb 2011) $
+ */
+public class ApplicationContextWrapperTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.ApplicationContextWrapper#getWrappedApplicationContext()}.
+ */
+ @Test
+ public void testGetWrappedApplicationContext() {
+ ApplicationContext wrappedContext = createMock(ApplicationContext.class);
+
+ replay(wrappedContext);
+ ApplicationContextWrapper wrapper = new ApplicationContextWrapper(wrappedContext);
+ assertEquals(wrappedContext, wrapper.getWrappedApplicationContext());
+ verify(wrappedContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.ApplicationContextWrapper#getApplicationScope()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetApplicationScope() {
+ ApplicationContext wrappedContext = createMock(ApplicationContext.class);
+ Map<String, Object> applicationScope = createMock(Map.class);
+
+ expect(wrappedContext.getApplicationScope()).andReturn(applicationScope);
+
+ replay(wrappedContext, applicationScope);
+ ApplicationContextWrapper wrapper = new ApplicationContextWrapper(wrappedContext);
+ assertEquals(applicationScope, wrapper.getApplicationScope());
+ verify(wrappedContext, applicationScope);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.ApplicationContextWrapper#getContext()}.
+ */
+ @Test
+ public void testGetContext() {
+ ApplicationContext wrappedContext = createMock(ApplicationContext.class);
+ Object obj = createMock(Object.class);
+
+ expect(wrappedContext.getContext()).andReturn(obj);
+
+ replay(wrappedContext, obj);
+ ApplicationContextWrapper wrapper = new ApplicationContextWrapper(wrappedContext);
+ assertEquals(obj, wrapper.getContext());
+ verify(wrappedContext, obj);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.ApplicationContextWrapper#getInitParams()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetInitParams() {
+ ApplicationContext wrappedContext = createMock(ApplicationContext.class);
+ Map<String, String> obj = createMock(Map.class);
+
+ expect(wrappedContext.getInitParams()).andReturn(obj);
+
+ replay(wrappedContext, obj);
+ ApplicationContextWrapper wrapper = new ApplicationContextWrapper(wrappedContext);
+ assertEquals(obj, wrapper.getInitParams());
+ verify(wrappedContext, obj);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.ApplicationContextWrapper#getResource(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetResource() throws IOException {
+ ApplicationContext wrappedContext = createMock(ApplicationContext.class);
+ ApplicationResource obj = createMock(ApplicationResource.class);
+ ApplicationResource objFr = createMock(ApplicationResource.class);
+
+ expect(wrappedContext.getResource("whatever.html")).andReturn(obj);
+ expect(wrappedContext.getResource(obj, Locale.FRENCH)).andReturn(objFr);
+
+ replay(wrappedContext);
+ ApplicationContextWrapper wrapper = new ApplicationContextWrapper(wrappedContext);
+ assertEquals(obj, wrapper.getResource("whatever.html"));
+ assertEquals(objFr, wrapper.getResource(obj, Locale.FRENCH));
+ verify(wrappedContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.ApplicationContextWrapper#getResources(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetResources() throws IOException {
+ ApplicationContext wrappedContext = createMock(ApplicationContext.class);
+ Collection<ApplicationResource> obj = createMock(Collection.class);
+
+ expect(wrappedContext.getResources("whatever.html")).andReturn(obj);
+
+ replay(wrappedContext, obj);
+ ApplicationContextWrapper wrapper = new ApplicationContextWrapper(wrappedContext);
+ assertEquals(obj, wrapper.getResources("whatever.html"));
+ verify(wrappedContext, obj);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/DefaultRequestWrapperTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/DefaultRequestWrapperTest.java
new file mode 100644
index 0000000..c768d4c
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/DefaultRequestWrapperTest.java
@@ -0,0 +1,319 @@
+/*
+ * $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.request;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.classextension.EasyMock.createMock;
+import static org.easymock.classextension.EasyMock.replay;
+import static org.easymock.classextension.EasyMock.verify;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.tiles.request.attribute.Addable;
+import org.junit.Test;
+
+/**
+ * Tests {@link DefaultRequestWrapper}.
+ *
+ * @version $Rev: 1215009 $ $Date: 2011-12-16 01:32:31 +0100 (Fri, 16 Dec 2011) $
+ */
+public class DefaultRequestWrapperTest {
+
+ /**
+ * Creates the RequestWrapper to be tested.
+ *
+ * @param wrappedRequest the request to be wrapped.
+ * @return the RequestWrapper.
+ */
+ protected RequestWrapper createRequestWrapper(Request wrappedRequest) {
+ DefaultRequestWrapper request = new DefaultRequestWrapper(wrappedRequest);
+ return request;
+ }
+
+ /**
+ * Creates a mock Request adequate to the test.
+ *
+ * @return the Request object.
+ */
+ protected Request createMockRequest() {
+ Request wrappedRequest = createMock(Request.class);
+ return wrappedRequest;
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getWrappedRequest()}.
+ */
+ @Test
+ public void testGetWrappedRequest() {
+ Request wrappedRequest = createMockRequest();
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(wrappedRequest, request.getWrappedRequest());
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getHeader()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetHeader() {
+ Request wrappedRequest = createMockRequest();
+ Map<String, String> header = createMock(Map.class);
+
+ expect(wrappedRequest.getHeader()).andReturn(header);
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(header, request.getHeader());
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getResponseHeaders()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetResponseHeaders() {
+ Request wrappedRequest = createMockRequest();
+ Addable<String> header = createMock(Addable.class);
+
+ expect(wrappedRequest.getResponseHeaders()).andReturn(header);
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(header, request.getResponseHeaders());
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getHeaderValues()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetHeaderValues() {
+ Request wrappedRequest = createMockRequest();
+ Map<String, String[]> header = createMock(Map.class);
+
+ expect(wrappedRequest.getHeaderValues()).andReturn(header);
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(header, request.getHeaderValues());
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getContext(java.lang.String)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetContext() {
+ Request wrappedRequest = createMockRequest();
+ Map<String, Object> context = createMock(Map.class);
+
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+
+ expect(wrappedRequest.getContext("one")).andReturn(context);
+
+ replay(wrappedRequest, context);
+ assertEquals(context, request.getContext("one"));
+ verify(wrappedRequest, context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getAvailableScopes()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetAvailableScopes() {
+ Request wrappedRequest = createMockRequest();
+ Map<String, Object> context = createMock(Map.class);
+
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+
+ String[] scopes = new String[] {"one", "two", "three"};
+ expect(wrappedRequest.getAvailableScopes()).andReturn(Arrays.asList(scopes));
+
+ replay(wrappedRequest, context);
+ assertArrayEquals(scopes, request.getAvailableScopes().toArray());
+ verify(wrappedRequest, context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getApplicationContext()}.
+ */
+ @Test
+ public void testGetApplicationContext() {
+ Request wrappedRequest = createMockRequest();
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ expect(wrappedRequest.getApplicationContext()).andReturn(applicationContext);
+
+ replay(wrappedRequest, applicationContext);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(applicationContext, request.getApplicationContext());
+ verify(wrappedRequest, applicationContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getOutputStream()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetOutputStream() throws IOException {
+ Request wrappedRequest = createMockRequest();
+ OutputStream stream = createMock(OutputStream.class);
+
+ expect(wrappedRequest.getOutputStream()).andReturn(stream);
+
+ replay(wrappedRequest, stream);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(stream, request.getOutputStream());
+ verify(wrappedRequest, stream);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetWriter() throws IOException {
+ Request wrappedRequest = createMockRequest();
+ Writer writer = createMock(Writer.class);
+
+ expect(wrappedRequest.getWriter()).andReturn(writer);
+
+ replay(wrappedRequest, writer);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(writer, request.getWriter());
+ verify(wrappedRequest, writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getPrintWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetPrintWriter() throws IOException {
+ Request wrappedRequest = createMockRequest();
+ PrintWriter writer = createMock(PrintWriter.class);
+
+ expect(wrappedRequest.getPrintWriter()).andReturn(writer);
+
+ replay(wrappedRequest, writer);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(writer, request.getPrintWriter());
+ verify(wrappedRequest, writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#isResponseCommitted()}.
+ */
+ @Test
+ public void testIsResponseCommitted() {
+ Request wrappedRequest = createMockRequest();
+
+ expect(wrappedRequest.isResponseCommitted()).andReturn(Boolean.TRUE);
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertTrue(request.isResponseCommitted());
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getParam()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParam() {
+ Request wrappedRequest = createMockRequest();
+ Map<String, String> param = createMock(Map.class);
+
+ expect(wrappedRequest.getParam()).andReturn(param);
+
+ replay(wrappedRequest, param);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(param, request.getParam());
+ verify(wrappedRequest, param);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getParamValues()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParamValues() {
+ Request wrappedRequest = createMockRequest();
+ Map<String, String[]> param = createMock(Map.class);
+
+ expect(wrappedRequest.getParamValues()).andReturn(param);
+
+ replay(wrappedRequest, param);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(param, request.getParamValues());
+ verify(wrappedRequest, param);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#getRequestLocale()}.
+ */
+ @Test
+ public void testGetRequestLocale() {
+ Request wrappedRequest = createMockRequest();
+ Locale param = Locale.ITALY;
+
+ expect(wrappedRequest.getRequestLocale()).andReturn(param);
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertEquals(param, request.getRequestLocale());
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DefaultRequestWrapper#isUserInRole(java.lang.String)}.
+ */
+ @Test
+ public void testIsUserInRole() {
+ Request wrappedRequest = createMockRequest();
+
+ expect(wrappedRequest.isUserInRole("myrole")).andReturn(Boolean.TRUE);
+
+ replay(wrappedRequest);
+ RequestWrapper request = createRequestWrapper(wrappedRequest);
+ assertTrue(request.isUserInRole("myrole"));
+ verify(wrappedRequest);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java
new file mode 100644
index 0000000..a9b05ad
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/DispatchRequestWrapperTest.java
@@ -0,0 +1,96 @@
+/*
+ * $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.request;
+
+import static org.easymock.classextension.EasyMock.createMock;
+import static org.easymock.classextension.EasyMock.replay;
+import static org.easymock.classextension.EasyMock.verify;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link DispatchRequestWrapper}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DispatchRequestWrapperTest extends DefaultRequestWrapperTest {
+
+ @Override
+ protected DispatchRequest createMockRequest() {
+ DispatchRequest wrappedRequest = createMock(DispatchRequest.class);
+ return wrappedRequest;
+ }
+
+ @Override
+ protected DispatchRequestWrapper createRequestWrapper(Request wrappedRequest) {
+ DispatchRequestWrapper request = new DispatchRequestWrapper((DispatchRequest) wrappedRequest);
+ return request;
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DispatchRequestWrapper#dispatch(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testDispatch() throws IOException {
+ DispatchRequest wrappedRequest = createMockRequest();
+
+ wrappedRequest.dispatch("/my/path.html");
+
+ replay(wrappedRequest);
+ DispatchRequestWrapper request = createRequestWrapper(wrappedRequest);
+ request.dispatch("/my/path.html");
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DispatchRequestWrapper#include(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testInclude() throws IOException {
+ DispatchRequest wrappedRequest = createMockRequest();
+
+ wrappedRequest.include("/my/path.html");
+
+ replay(wrappedRequest);
+ DispatchRequestWrapper request = createRequestWrapper(wrappedRequest);
+ request.include("/my/path.html");
+ verify(wrappedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.DispatchRequestWrapper#setContentType(java.lang.String)}.
+ */
+ @Test
+ public void testSetContentType() {
+ DispatchRequest wrappedRequest = createMockRequest();
+
+ wrappedRequest.setContentType("text/html");
+
+ replay(wrappedRequest);
+ DispatchRequestWrapper request = createRequestWrapper(wrappedRequest);
+ request.setContentType("text/html");
+ verify(wrappedRequest);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java
new file mode 100644
index 0000000..da14b2b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/NotAvailableFeatureExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link NotAvailableFeatureException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotAvailableFeatureExceptionTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.NotAvailableFeatureException#NotAvailableFeatureException()}.
+ */
+ @Test
+ public void testNotAvailableFeatureException() {
+ NotAvailableFeatureException exception = new NotAvailableFeatureException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAvailableFeatureException#NotAvailableFeatureException(String)}.
+ */
+ @Test
+ public void testNotAvailableFeatureExceptionString() {
+ NotAvailableFeatureException exception = new NotAvailableFeatureException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAvailableFeatureException#NotAvailableFeatureException(Throwable)}.
+ */
+ @Test
+ public void testNotAvailableFeatureExceptionThrowable() {
+ Throwable cause = new Throwable();
+ NotAvailableFeatureException exception = new NotAvailableFeatureException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAvailableFeatureException#NotAvailableFeatureException(String, Throwable)}.
+ */
+ @Test
+ public void testNotAvailableFeatureExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ NotAvailableFeatureException exception = new NotAvailableFeatureException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/RequestExceptionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/RequestExceptionTest.java
new file mode 100644
index 0000000..d3693d7
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/RequestExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link RequestException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestExceptionTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.RequestException#RequestException()}.
+ */
+ @Test
+ public void testRequestException() {
+ RequestException exception = new RequestException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.RequestException#RequestException(java.lang.String)}.
+ */
+ @Test
+ public void testRequestExceptionString() {
+ RequestException exception = new RequestException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.RequestException#RequestException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testRequestExceptionThrowable() {
+ Throwable cause = new Throwable();
+ RequestException exception = new RequestException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link RequestException#RequestException(String, Throwable)}.
+ */
+ @Test
+ public void testRequestExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ RequestException exception = new RequestException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java
new file mode 100644
index 0000000..7e702da
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/AddableParameterMapTest.java
@@ -0,0 +1,114 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasAddableKeys;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link AddableParameterMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AddableParameterMapTest {
+
+ /**
+ * The object to test.
+ */
+ private AddableParameterMap map;
+
+ /**
+ * The extractor to use.
+ */
+ private HasAddableKeys<String> extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ extractor = createMock(HasAddableKeys.class);
+ map = new AddableParameterMap(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.AddableParameterMap#entrySet()}.
+ */
+ @Test
+ public void testEntrySet() {
+ Set<Map.Entry<String, String>> entrySet = map.entrySet();
+ MapEntry<String, String> entry1 = new MapEntry<String, String>("one", "value1", false);
+ MapEntry<String, String> entry2 = new MapEntry<String, String>("two", "value2", false);
+ List<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(2);
+ entries.add(entry1);
+ entries.add(entry2);
+
+ extractor.setValue("one", "value1");
+ expectLastCall().times(2);
+ extractor.setValue("two", "value2");
+ replay(extractor);
+ entrySet.add(entry1);
+ entrySet.addAll(entries);
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link AddableParameterMap#put(String, String)}.
+ */
+ @Test
+ public void testPut() {
+ expect(extractor.getValue("one")).andReturn(null);
+ extractor.setValue("one", "value1");
+
+ replay(extractor);
+ assertNull(map.put("one", "value1"));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.AddableParameterMap#putAll(java.util.Map)}.
+ */
+ @Test
+ public void testPutAll() {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put("one", "value1");
+ map.put("two", "value2");
+
+ extractor.setValue("one", "value1");
+ extractor.setValue("two", "value2");
+
+ replay(extractor);
+ this.map.putAll(map);
+ verify(extractor);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java
new file mode 100644
index 0000000..4fcc496
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/CollectionUtilTest.java
@@ -0,0 +1,74 @@
+/*
+ * $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.request.collection;
+
+import org.apache.tiles.request.collection.CollectionUtil;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import org.junit.Test;
+
+/**
+ * Test {@link RequestUtil}.
+ *
+ * @version $Rev: 1066446 $ $Date: 2011-02-02 13:38:04 +0100 (Wed, 02 Feb 2011) $
+ */
+public class CollectionUtilTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.RequestUtil#key(java.lang.Object)}.
+ */
+ @Test
+ public void testKey() {
+ assertEquals("1", CollectionUtil.key(1));
+ assertEquals("hello", CollectionUtil.key("hello"));
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.RequestUtil#key(java.lang.Object)}.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testKeyException() {
+ CollectionUtil.key(null);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.RequestUtil#enumerationSize(java.util.Enumeration)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testEnumerationSize() {
+ Enumeration<Object> enumeration = createMock(Enumeration.class);
+
+ expect(enumeration.hasMoreElements()).andReturn(true);
+ expect(enumeration.nextElement()).andReturn(1);
+ expect(enumeration.hasMoreElements()).andReturn(true);
+ expect(enumeration.nextElement()).andReturn(1);
+ expect(enumeration.hasMoreElements()).andReturn(false);
+
+ replay(enumeration);
+ assertEquals(2, CollectionUtil.enumerationSize(enumeration));
+ verify(enumeration);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java
new file mode 100644
index 0000000..d845a0e
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesCollectionTest.java
@@ -0,0 +1,419 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tiles.request.attribute.EnumeratedValuesExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link HeaderValuesMap#values()}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderValuesCollectionTest {
+
+
+ /**
+ * The extractor to use.
+ */
+ private EnumeratedValuesExtractor extractor;
+
+ /**
+ * The map to test.
+ */
+ private HeaderValuesMap map;
+
+ /**
+ * The collection.
+ */
+ private Collection<String[]> coll;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ extractor = createMock(EnumeratedValuesExtractor.class);
+ map = new HeaderValuesMap(extractor);
+ coll = map.values();
+ }
+
+ /**
+ * Tests {@link Collection#add(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAdd() {
+ coll.add(null);
+ }
+
+ /**
+ * Tests {@link Collection#addAll(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAddAll() {
+ coll.addAll(null);
+ }
+
+ /**
+ * Tests {@link Collection#clear(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ coll.clear();
+ }
+
+ /**
+ * Tests {@link Collection#contains(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValue() {
+ assertFalse(map.containsValue(1));
+
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ assertTrue(coll.contains(new String[] {"value2", "value3"}));
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Tests {@link Collection#contains(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValueFalse() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ assertFalse(coll.contains(new String[] {"value2", "value4"}));
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Tests {@link Collection#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAll() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys).times(2);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValues("one")).andReturn(values1).times(2);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ List<String[]> coll = new ArrayList<String[]>();
+ coll.add(new String[] {"value1"});
+ coll.add(new String[] {"value2", "value3"});
+ assertTrue(this.coll.containsAll(coll));
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Tests {@link Collection#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAllFalse() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys, values1, values2);
+ List<String[]> coll = new ArrayList<String[]>();
+ coll.add(new String[] {"value4"});
+ assertFalse(this.coll.containsAll(coll));
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link Collection#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(coll.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIterator() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values2);
+ Iterator<String[]> entryIt = coll.iterator();
+ assertTrue(entryIt.hasNext());
+ assertArrayEquals(new String[] { "value2", "value3" }, entryIt.next());
+ verify(extractor, keys, values2);
+ }
+
+ /**
+ * Test method for {@link Collection#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = UnsupportedOperationException.class)
+ public void testIteratorRemove() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+
+ try {
+ replay(extractor, keys);
+ coll.iterator().remove();
+ } finally {
+ verify(extractor, keys);
+ }
+ }
+
+ /**
+ * Tests {@link Collection#remove(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ coll.remove(null);
+ }
+
+ /**
+ * Tests {@link Collection#removeAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveAll() {
+ coll.removeAll(null);
+ }
+
+ /**
+ * Tests {@link Collection#retainAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRetainAll() {
+ coll.retainAll(null);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, coll.size());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#toArray()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ String[][] entryArray = new String[2][];
+ entryArray[0] = new String[] {"value1"};
+ entryArray[1] = new String[] {"value2", "value3"};
+
+ replay(extractor, keys, values1, values2);
+ assertArrayEquals(entryArray, coll.toArray());
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link Collection#toArray(Object[])}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArrayTArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ String[][] entryArray = new String[2][];
+ entryArray[0] = new String[] {"value1"};
+ entryArray[1] = new String[] {"value2", "value3"};
+ String[][] realArray = new String[2][];
+
+ replay(extractor, keys, values1, values2);
+ assertArrayEquals(entryArray, coll.toArray(realArray));
+ verify(extractor, keys, values1, values2);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java
new file mode 100644
index 0000000..1e94d53
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapEntrySetTest.java
@@ -0,0 +1,360 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.EnumeratedValuesExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link HeaderValuesMap entry set}.
+ *
+ */
+public class HeaderValuesMapEntrySetTest {
+
+
+ /**
+ * The extractor to use.
+ */
+ private EnumeratedValuesExtractor extractor;
+
+ /**
+ * The map to test.
+ */
+ private HeaderValuesMap map;
+
+ /**
+ * The set to test.
+ */
+ private Set<Map.Entry<String, String[]>> entrySet;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ extractor = createMock(EnumeratedValuesExtractor.class);
+ map = new HeaderValuesMap(extractor);
+ entrySet = map.entrySet();
+ }
+
+ /**
+ * Tests {@link Set#add(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAdd() {
+ entrySet.add(null);
+ }
+
+ /**
+ * Tests {@link Set#addAll(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAddAll() {
+ entrySet.addAll(null);
+ }
+
+ /**
+ * Tests {@link Set#clear(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ entrySet.clear();
+ }
+
+ /**
+ * Tests {@link Set#contains(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContains() {
+ Map.Entry<String, String[]> entry = createMock(Map.Entry.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(entry.getKey()).andReturn("two");
+ expect(entry.getValue()).andReturn(new String[] {"value2", "value3"});
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, entry, values2);
+ assertTrue(entrySet.contains(entry));
+ verify(extractor, entry, values2);
+ }
+
+ /**
+ * Tests {@link Set#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAll() {
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+ Map.Entry<String, String[]> entry1 = createMock(Map.Entry.class);
+ Map.Entry<String, String[]> entry2 = createMock(Map.Entry.class);
+
+ expect(entry1.getKey()).andReturn("one");
+ expect(entry1.getValue()).andReturn(new String[] {"value1"});
+ expect(entry2.getKey()).andReturn("two");
+ expect(entry2.getValue()).andReturn(new String[] {"value2", "value3"});
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, values1, values2, entry1, entry2);
+ List<Map.Entry<String, String[]>> coll = new ArrayList<Map.Entry<String, String[]>>();
+ coll.add(entry1);
+ coll.add(entry2);
+ assertTrue(entrySet.containsAll(coll));
+ verify(extractor, values1, values2, entry1, entry2);
+ }
+
+ /**
+ * Tests {@link Set#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAllFalse() {
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Map.Entry<String, String[]> entry1 = createMock(Map.Entry.class);
+
+ expect(entry1.getKey()).andReturn("one");
+ expect(entry1.getValue()).andReturn(new String[] {"value4"});
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+
+ replay(extractor, values1, entry1);
+ List<Map.Entry<String, String[]>> coll = new ArrayList<Map.Entry<String, String[]>>();
+ coll.add(entry1);
+ assertFalse(entrySet.containsAll(coll));
+ verify(extractor, values1, entry1);
+ }
+
+ /**
+ * Test method for {@link Set#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(entrySet.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIterator() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values2);
+ Iterator<Map.Entry<String, String[]>> entryIt = entrySet.iterator();
+ assertTrue(entryIt.hasNext());
+ MapEntryArrayValues<String, String> entry = new MapEntryArrayValues<String, String>(
+ "two", new String[] { "value2", "value3" }, false);
+ assertEquals(entry, entryIt.next());
+ verify(extractor, keys, values2);
+ }
+
+ /**
+ * Test method for {@link Set#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = UnsupportedOperationException.class)
+ public void testIteratorRemove() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+
+ try {
+ replay(extractor, keys);
+ entrySet.iterator().remove();
+ } finally {
+ verify(extractor, keys);
+ }
+ }
+
+ /**
+ * Tests {@link Set#remove(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ entrySet.remove(null);
+ }
+
+ /**
+ * Tests {@link Set#removeAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveAll() {
+ entrySet.removeAll(null);
+ }
+
+ /**
+ * Tests {@link Set#retainAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRetainAll() {
+ entrySet.retainAll(null);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, entrySet.size());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#toArray()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ MapEntryArrayValues<String, String>[] entryArray = new MapEntryArrayValues[2];
+ entryArray[0] = new MapEntryArrayValues<String, String>("one", new String[] {"value1"}, false);
+ entryArray[1] = new MapEntryArrayValues<String, String>("two", new String[] {"value2", "value3"}, false);
+
+ replay(extractor, keys, values1, values2);
+ assertArrayEquals(entryArray, entrySet.toArray());
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link Set#toArray(Object[])}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArrayTArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ MapEntryArrayValues<String, String>[] entryArray = new MapEntryArrayValues[2];
+ entryArray[0] = new MapEntryArrayValues<String, String>("one", new String[] {"value1"}, false);
+ entryArray[1] = new MapEntryArrayValues<String, String>("two", new String[] {"value2", "value3"}, false);
+ MapEntryArrayValues<String, String>[] realArray = new MapEntryArrayValues[2];
+
+ replay(extractor, keys, values1, values2);
+ assertArrayEquals(entryArray, entrySet.toArray(realArray));
+ verify(extractor, keys, values1, values2);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java
new file mode 100644
index 0000000..715e5d9
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/HeaderValuesMapTest.java
@@ -0,0 +1,344 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import org.apache.tiles.request.attribute.EnumeratedValuesExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link HeaderValuesMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderValuesMapTest {
+
+ /**
+ * The extractor to use.
+ */
+ private EnumeratedValuesExtractor extractor;
+
+ /**
+ * The map to test.
+ */
+ private HeaderValuesMap map;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ extractor = createMock(EnumeratedValuesExtractor.class);
+ map = new HeaderValuesMap(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#hashCode()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHashCode() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ assertEquals(
+ ("one".hashCode() ^ "value1".hashCode())
+ + ("two".hashCode() ^ ("value2".hashCode() + "value3"
+ .hashCode())),
+ map.hashCode());
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#clear()}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ map.clear();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#containsKey(java.lang.Object)}.
+ */
+ @Test
+ public void testContainsKey() {
+ expect(extractor.getValue("one")).andReturn("value1");
+ expect(extractor.getValue("two")).andReturn(null);
+
+ replay(extractor);
+ assertTrue(map.containsKey("one"));
+ assertFalse(map.containsKey("two"));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#containsValue(java.lang.Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValue() {
+ assertFalse(map.containsValue(1));
+
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ assertTrue(map.containsValue(new String[] {"value2", "value3"}));
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#containsValue(java.lang.Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValueFalse() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ assertFalse(map.containsValue(new String[] {"value2", "value4"}));
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#equals(java.lang.Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testEqualsObject() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+ EnumeratedValuesExtractor otherExtractor = createMock(EnumeratedValuesExtractor.class);
+ Enumeration<String> otherValues1 = createMock(Enumeration.class);
+ Enumeration<String> otherValues2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("one")).andReturn(values1);
+ expect(values1.hasMoreElements()).andReturn(true);
+ expect(values1.nextElement()).andReturn("value1");
+ expect(values1.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ expect(otherExtractor.getValues("one")).andReturn(otherValues1);
+ expect(otherValues1.hasMoreElements()).andReturn(true);
+ expect(otherValues1.nextElement()).andReturn("value1");
+ expect(otherValues1.hasMoreElements()).andReturn(false);
+
+ expect(otherExtractor.getValues("two")).andReturn(otherValues2);
+ expect(otherValues2.hasMoreElements()).andReturn(true);
+ expect(otherValues2.nextElement()).andReturn("value2");
+ expect(otherValues2.hasMoreElements()).andReturn(true);
+ expect(otherValues2.nextElement()).andReturn("value3");
+ expect(otherValues2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, otherExtractor, keys, values1, values2, otherValues1, otherValues2);
+ HeaderValuesMap otherMap = new HeaderValuesMap(otherExtractor);
+ assertTrue(map.equals(otherMap));
+ verify(extractor, otherExtractor, keys, values1, values2, otherValues1, otherValues2);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#get(java.lang.Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGet() {
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getValues("two")).andReturn(values2);
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value2");
+ expect(values2.hasMoreElements()).andReturn(true);
+ expect(values2.nextElement()).andReturn("value3");
+ expect(values2.hasMoreElements()).andReturn(false);
+
+ replay(extractor, values2);
+ assertArrayEquals(new String[] {"value2", "value3"}, map.get("two"));
+ verify(extractor, values2);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(map.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmptyTrue() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertTrue(map.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#keySet()}.
+ */
+ @Test
+ public void testKeySet() {
+ replay(extractor);
+ assertTrue(map.keySet() instanceof KeySet);
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link HeaderValuesMap#put(String, String[])}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testPut() {
+ map.put("one", new String[] {"value1", "value2"});
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#putAll(java.util.Map)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testPutAll() {
+ map.putAll(new HashMap<String, String[]>());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#remove(java.lang.Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ map.remove("one");
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, map.size());
+ verify(extractor, keys);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/KeySetTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/KeySetTest.java
new file mode 100644
index 0000000..e7a939e
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/KeySetTest.java
@@ -0,0 +1,301 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasKeys;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link KeySet}.
+ *
+ */
+public class KeySetTest {
+
+
+ /**
+ * The extractor to use.
+ */
+ private HasKeys<Integer> extractor;
+
+ /**
+ * The key set.
+ */
+ private Set<String> entrySet;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ extractor = createMock(HasKeys.class);
+ entrySet = new KeySet(extractor);
+ }
+
+ /**
+ * Tests {@link Set#add(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAdd() {
+ entrySet.add(null);
+ }
+
+ /**
+ * Tests {@link Set#addAll(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAddAll() {
+ entrySet.addAll(null);
+ }
+
+ /**
+ * Tests {@link Set#clear(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ entrySet.clear();
+ }
+
+ /**
+ * Tests {@link Set#contains(Object)}.
+ */
+ @Test
+ public void testContains() {
+ expect(extractor.getValue("one")).andReturn(1);
+
+ replay(extractor);
+ assertTrue(entrySet.contains("one"));
+ verify(extractor);
+ }
+
+ /**
+ * Tests {@link Set#contains(Object)}.
+ */
+ @Test
+ public void testContainsFalse() {
+ expect(extractor.getValue("one")).andReturn(null);
+
+ replay(extractor);
+ assertFalse(entrySet.contains("one"));
+ verify(extractor);
+ }
+
+ /**
+ * Tests {@link Set#containsAll(Object)}.
+ */
+ @Test
+ public void testContainsAll() {
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(1);
+
+ replay(extractor);
+ List<String> coll = new ArrayList<String>();
+ coll.add("one");
+ coll.add("two");
+ assertTrue(entrySet.containsAll(coll));
+ verify(extractor);
+ }
+
+ /**
+ * Tests {@link Set#containsAll(Object)}.
+ */
+ @Test
+ public void testContainsAllFalse() {
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(null);
+
+ replay(extractor);
+ List<String> coll = new ArrayList<String>();
+ coll.add("one");
+ coll.add("two");
+ assertFalse(entrySet.containsAll(coll));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link Set#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(entrySet.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmptyTrue() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertTrue(entrySet.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIterator() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ replay(extractor, keys, values2);
+ Iterator<String> entryIt = entrySet.iterator();
+ assertTrue(entryIt.hasNext());
+ assertEquals("two", entryIt.next());
+ verify(extractor, keys, values2);
+ }
+
+ /**
+ * Test method for {@link Set#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = UnsupportedOperationException.class)
+ public void testIteratorRemove() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+
+ try {
+ replay(extractor, keys);
+ entrySet.iterator().remove();
+ } finally {
+ verify(extractor, keys);
+ }
+ }
+
+ /**
+ * Tests {@link Set#remove(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ entrySet.remove(null);
+ }
+
+ /**
+ * Tests {@link Set#removeAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveAll() {
+ entrySet.removeAll(null);
+ }
+
+ /**
+ * Tests {@link Set#retainAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRetainAll() {
+ entrySet.retainAll(null);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, entrySet.size());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#toArray()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+ replay(extractor, keys, values1, values2);
+ assertArrayEquals(new String[] {"one", "two"}, entrySet.toArray());
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link Set#toArray(Object[])}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArrayTArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys, values1, values2);
+ String[] realArray = new String[2];
+ assertArrayEquals(new String[] {"one", "two"}, entrySet.toArray(realArray));
+ verify(extractor, keys, values1, values2);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.java
new file mode 100644
index 0000000..3a04d58
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/MapEntryArrayValuesTest.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.request.collection;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link MapEntryArrayValues}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MapEntryArrayValuesTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntryArrayValues#hashCode()}.
+ */
+ @Test
+ public void testHashCode() {
+ MapEntryArrayValues<String, String> entry = new MapEntryArrayValues<String, String>(
+ "key", new String[] { "value1", "value2" }, false);
+ assertEquals("key".hashCode() ^ ("value1".hashCode() + "value2".hashCode()), entry.hashCode());
+ entry = new MapEntryArrayValues<String, String>(
+ null, new String[] { "value1", "value2" }, false);
+ assertEquals(0 ^ ("value1".hashCode() + "value2".hashCode()), entry.hashCode());
+ entry = new MapEntryArrayValues<String, String>(
+ "key", null, false);
+ assertEquals("key".hashCode() ^ 0, entry.hashCode());
+ entry = new MapEntryArrayValues<String, String>(
+ null, null, false);
+ assertEquals(0 ^ 0, entry.hashCode());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntryArrayValues#equals(java.lang.Object)}.
+ */
+ @Test
+ public void testEqualsObject() {
+ MapEntryArrayValues<String, String> entry = new MapEntryArrayValues<String, String>(
+ "key", new String[] { "value1", "value2" }, false);
+ assertFalse(entry.equals(null));
+ assertFalse(entry.equals("whatever"));
+ MapEntryArrayValues<String, String> entry2 = new MapEntryArrayValues<String, String>(
+ "key", new String[] { "value1", "value2" }, false);
+ assertTrue(entry.equals(entry2));
+ entry2 = new MapEntryArrayValues<String, String>(
+ "key", null, false);
+ assertFalse(entry.equals(entry2));
+ entry2 = new MapEntryArrayValues<String, String>("key2", new String[] {
+ "value1", "value2" }, false);
+ assertFalse(entry.equals(entry2));
+ entry2 = new MapEntryArrayValues<String, String>("key", new String[] {
+ "value1", "value3" }, false);
+ assertFalse(entry.equals(entry2));
+ entry = new MapEntryArrayValues<String, String>(null, new String[] {
+ "value1", "value2" }, false);
+ entry2 = new MapEntryArrayValues<String, String>(null, new String[] {
+ "value1", "value2" }, false);
+ assertTrue(entry.equals(entry2));
+ entry = new MapEntryArrayValues<String, String>("key", null, false);
+ entry2 = new MapEntryArrayValues<String, String>("key", null, false);
+ assertTrue(entry.equals(entry2));
+ entry2 = new MapEntryArrayValues<String, String>("key", new String[] {
+ "value1", "value2" }, false);
+ assertFalse(entry.equals(entry2));
+ entry = new MapEntryArrayValues<String, String>(null, new String[] {
+ null, "value2" }, false);
+ entry2 = new MapEntryArrayValues<String, String>(null, new String[] {
+ null, "value2" }, false);
+ assertTrue(entry.equals(entry2));
+ entry2 = new MapEntryArrayValues<String, String>(null, new String[] {
+ "value1", "value2" }, false);
+ assertFalse(entry.equals(entry2));
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java
new file mode 100644
index 0000000..a458b1b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/MapEntryTest.java
@@ -0,0 +1,110 @@
+/*
+ * $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.request.collection;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link MapEntry}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MapEntryTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntry#hashCode()}.
+ */
+ @Test
+ public void testHashCode() {
+ MapEntry<String, String> entry = new MapEntry<String, String>("key", "value", false);
+ assertEquals("key".hashCode() ^ "value".hashCode(), entry.hashCode());
+ entry = new MapEntry<String, String>(null, "value", false);
+ assertEquals(0 ^ "value".hashCode(), entry.hashCode());
+ entry = new MapEntry<String, String>("key", null, false);
+ assertEquals("key".hashCode() ^ 0, entry.hashCode());
+ entry = new MapEntry<String, String>(null, null, false);
+ assertEquals(0 ^ 0, entry.hashCode());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntry#getKey()}.
+ */
+ @Test
+ public void testGetKey() {
+ MapEntry<String, String> entry = new MapEntry<String, String>("key", "value", false);
+ assertEquals("key", entry.getKey());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntry#getValue()}.
+ */
+ @Test
+ public void testGetValue() {
+ MapEntry<String, String> entry = new MapEntry<String, String>("key", "value", false);
+ assertEquals("value", entry.getValue());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntry#setValue(java.lang.Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ MapEntry<String, String> entry = new MapEntry<String, String>("key", "value", true);
+ assertEquals("value", entry.getValue());
+ entry.setValue("value2");
+ assertEquals("value2", entry.getValue());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntry#setValue(java.lang.Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testSetValueException() {
+ MapEntry<String, String> entry = new MapEntry<String, String>("key", "value", false);
+ assertEquals("value", entry.getValue());
+ entry.setValue("value2");
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.MapEntry#equals(java.lang.Object)}.
+ */
+ @Test
+ public void testEqualsObject() {
+ MapEntry<String, String> entry = new MapEntry<String, String>("key", "value", false);
+ assertFalse(entry.equals(null));
+ assertFalse(entry.equals("whatever"));
+ MapEntry<String, String> entry2 = new MapEntry<String, String>("key", "value", false);
+ assertTrue(entry.equals(entry2));
+ entry2 = new MapEntry<String, String>("key2", "value", false);
+ assertFalse(entry.equals(entry2));
+ entry2 = new MapEntry<String, String>("key", "value2", false);
+ assertFalse(entry.equals(entry2));
+ entry = new MapEntry<String, String>(null, "value", false);
+ entry2 = new MapEntry<String, String>(null, "value", false);
+ assertTrue(entry.equals(entry2));
+ entry = new MapEntry<String, String>("key", null, false);
+ entry2 = new MapEntry<String, String>("key", null, false);
+ assertTrue(entry.equals(entry2));
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java
new file mode 100644
index 0000000..41cd752
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapEntrySetTest.java
@@ -0,0 +1,318 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.HasKeys;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ReadOnlyEnumerationMap#entrySet()}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReadOnlyEnumerationMapEntrySetTest {
+
+ /**
+ * The extractor to use.
+ */
+ private HasKeys<Integer> extractor;
+
+ /**
+ * The map to test.
+ */
+ private ReadOnlyEnumerationMap<Integer> map;
+
+ /**
+ * The set to test.
+ */
+ private Set<Map.Entry<String, Integer>> entrySet;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ extractor = createMock(HasKeys.class);
+ map = new ReadOnlyEnumerationMap<Integer>(extractor);
+ entrySet = map.entrySet();
+ }
+
+ /**
+ * Tests {@link Set#add(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAdd() {
+ entrySet.add(null);
+ }
+
+ /**
+ * Tests {@link Set#addAll(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAddAll() {
+ entrySet.addAll(null);
+ }
+
+ /**
+ * Tests {@link Set#clear(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ entrySet.clear();
+ }
+
+ /**
+ * Tests {@link Set#contains(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContains() {
+ Map.Entry<String, Integer> entry = createMock(Map.Entry.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(entry.getKey()).andReturn("two");
+ expect(entry.getValue()).andReturn(2);
+
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, entry, values2);
+ assertTrue(entrySet.contains(entry));
+ verify(extractor, entry, values2);
+ }
+
+ /**
+ * Tests {@link Set#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAll() {
+ Map.Entry<String, Integer> entry1 = createMock(Map.Entry.class);
+ Map.Entry<String, Integer> entry2 = createMock(Map.Entry.class);
+
+ expect(entry1.getKey()).andReturn("one");
+ expect(entry1.getValue()).andReturn(1);
+ expect(entry2.getKey()).andReturn("two");
+ expect(entry2.getValue()).andReturn(2);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, entry1, entry2);
+ List<Map.Entry<String, Integer>> coll = new ArrayList<Map.Entry<String, Integer>>();
+ coll.add(entry1);
+ coll.add(entry2);
+ assertTrue(entrySet.containsAll(coll));
+ verify(extractor, entry1, entry2);
+ }
+
+ /**
+ * Tests {@link Set#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAllFalse() {
+ Map.Entry<String, String> entry1 = createMock(Map.Entry.class);
+
+ expect(entry1.getKey()).andReturn("one");
+ expect(entry1.getValue()).andReturn("value4");
+
+ expect(extractor.getValue("one")).andReturn(1);
+
+ replay(extractor, entry1);
+ List<Map.Entry<String, String>> coll = new ArrayList<Map.Entry<String, String>>();
+ coll.add(entry1);
+ assertFalse(entrySet.containsAll(coll));
+ verify(extractor, entry1);
+ }
+
+ /**
+ * Test method for {@link Set#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(entrySet.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIterator() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ Iterator<Map.Entry<String, Integer>> entryIt = entrySet.iterator();
+ assertTrue(entryIt.hasNext());
+ MapEntry<String, Integer> entry = new MapEntry<String, Integer>(
+ "two", 2, false);
+ assertEquals(entry, entryIt.next());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = UnsupportedOperationException.class)
+ public void testIteratorRemove() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+
+ try {
+ replay(extractor, keys);
+ entrySet.iterator().remove();
+ } finally {
+ verify(extractor, keys);
+ }
+ }
+
+ /**
+ * Tests {@link Set#remove(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ entrySet.remove(null);
+ }
+
+ /**
+ * Tests {@link Set#removeAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveAll() {
+ entrySet.removeAll(null);
+ }
+
+ /**
+ * Tests {@link Set#retainAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRetainAll() {
+ entrySet.retainAll(null);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, entrySet.size());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Set#toArray()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ MapEntry<String, Integer>[] entryArray = new MapEntry[2];
+ entryArray[0] = new MapEntry<String, Integer>("one", 1, false);
+ entryArray[1] = new MapEntry<String, Integer>("two", 2, false);
+
+ replay(extractor, keys, values1, values2);
+ assertArrayEquals(entryArray, entrySet.toArray());
+ verify(extractor, keys, values1, values2);
+ }
+
+ /**
+ * Test method for {@link Set#toArray(Object[])}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArrayTArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> values1 = createMock(Enumeration.class);
+ Enumeration<String> values2 = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ MapEntry<String, Integer>[] entryArray = new MapEntry[2];
+ entryArray[0] = new MapEntry<String, Integer>("one", 1, false);
+ entryArray[1] = new MapEntry<String, Integer>("two", 2, false);
+
+ replay(extractor, keys, values1, values2);
+ MapEntry<String, String>[] realArray = new MapEntry[2];
+ assertArrayEquals(entryArray, entrySet.toArray(realArray));
+ verify(extractor, keys, values1, values2);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java
new file mode 100644
index 0000000..547b219
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapTest.java
@@ -0,0 +1,330 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import org.apache.tiles.request.attribute.HasKeys;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ReadOnlyEnumerationMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReadOnlyEnumerationMapTest {
+
+ /**
+ * The extractor to use.
+ */
+ private HasKeys<Integer> extractor;
+
+ /**
+ * The map to test.
+ */
+ private ReadOnlyEnumerationMap<Integer> map;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ extractor = createMock(HasKeys.class);
+ map = new ReadOnlyEnumerationMap<Integer>(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#clear()}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ map.clear();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#containsKey(java.lang.Object)}.
+ */
+ @Test
+ public void testContainsKey() {
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(null);
+
+ replay(extractor);
+ assertTrue(map.containsKey("one"));
+ assertFalse(map.containsKey("two"));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link ReadOnlyEnumerationMap#containsValue(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValue() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ assertTrue(map.containsValue(2));
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link ReadOnlyEnumerationMap#containsValue(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValueFalse() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(1);
+
+ replay(extractor, keys);
+ assertFalse(map.containsValue(3));
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#get(java.lang.Object)}.
+ */
+ @Test
+ public void testGet() {
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor);
+ assertEquals(new Integer(2), map.get("two"));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(map.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmptyTrue() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertTrue(map.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#keySet()}.
+ */
+ @Test
+ public void testKeySet() {
+ replay(extractor);
+ assertTrue(map.keySet() instanceof KeySet);
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link ReadOnlyEnumerationMap#put(String, String[])}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testPut() {
+ map.put("one", 1);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#putAll(java.util.Map)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testPutAll() {
+ map.putAll(new HashMap<String, Integer>());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#remove(java.lang.Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ map.remove("one");
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ReadOnlyEnumerationMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, map.size());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.extractor.collection.AbstractEnumerationMap#hashCode()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testHashCode() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("first");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("second");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ Integer value1 = 1;
+
+ expect(extractor.getValue("first")).andReturn(value1);
+ expect(extractor.getValue("second")).andReturn(null);
+
+ replay(extractor, keys);
+ assertEquals(("first".hashCode() ^ value1.hashCode())
+ + ("second".hashCode() ^ 0), map.hashCode());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.extractor.collection.AbstractEnumerationMap#equals(java.lang.Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testEqualsObject() {
+ HasKeys<Integer> otherRequest = createMock(HasKeys.class);
+ ReadOnlyEnumerationMap<Integer> otherMap = createMockBuilder(
+ ReadOnlyEnumerationMap.class).withConstructor(otherRequest)
+ .createMock();
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> otherKeys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(otherRequest.getKeys()).andReturn(otherKeys);
+
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("first");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("second");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("first")).andReturn(1);
+ expect(extractor.getValue("second")).andReturn(2);
+
+ expect(otherKeys.hasMoreElements()).andReturn(true);
+ expect(otherKeys.nextElement()).andReturn("first");
+ expect(otherKeys.hasMoreElements()).andReturn(true);
+ expect(otherKeys.nextElement()).andReturn("second");
+ expect(otherKeys.hasMoreElements()).andReturn(false);
+
+ expect(otherRequest.getValue("first")).andReturn(1);
+ expect(otherRequest.getValue("second")).andReturn(2);
+
+ replay(extractor, otherRequest, otherMap, keys, otherKeys);
+ assertTrue(map.equals(otherMap));
+ verify(extractor, otherRequest, otherMap, keys, otherKeys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.extractor.collection.AbstractEnumerationMap#equals(java.lang.Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testEqualsObjectFalse() {
+ HasKeys<Integer> otherRequest = createMock(HasKeys.class);
+ ReadOnlyEnumerationMap<Integer> otherMap = createMockBuilder(
+ ReadOnlyEnumerationMap.class).withConstructor(otherRequest)
+ .createMock();
+ Enumeration<String> keys = createMock(Enumeration.class);
+ Enumeration<String> otherKeys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(otherRequest.getKeys()).andReturn(otherKeys);
+
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("first");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("second");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("first")).andReturn(1);
+ expect(extractor.getValue("second")).andReturn(2);
+
+ expect(otherKeys.hasMoreElements()).andReturn(true);
+ expect(otherKeys.nextElement()).andReturn("first");
+ expect(otherKeys.hasMoreElements()).andReturn(true);
+ expect(otherKeys.nextElement()).andReturn("second");
+ expect(otherKeys.hasMoreElements()).andReturn(false);
+
+ expect(otherRequest.getValue("first")).andReturn(1);
+ expect(otherRequest.getValue("second")).andReturn(3);
+
+ replay(extractor, otherRequest, otherMap, keys, otherKeys);
+ assertFalse(map.equals(otherMap));
+ verify(extractor, otherRequest, otherMap, keys, otherKeys);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java
new file mode 100644
index 0000000..13f35dd
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ReadOnlyEnumerationMapValuesCollectionTest.java
@@ -0,0 +1,337 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tiles.request.attribute.HasKeys;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ReadOnlyEnumerationMap#values()}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ReadOnlyEnumerationMapValuesCollectionTest {
+ /**
+ * The extractor to use.
+ */
+ private HasKeys<Integer> extractor;
+
+ /**
+ * The map to test.
+ */
+ private ReadOnlyEnumerationMap<Integer> map;
+
+ /**
+ * The collection to test.
+ */
+ private Collection<Integer> coll;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ extractor = createMock(HasKeys.class);
+ map = new ReadOnlyEnumerationMap<Integer>(extractor);
+ coll = map.values();
+ }
+
+ /**
+ * Tests {@link Collection#add(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAdd() {
+ coll.add(null);
+ }
+
+ /**
+ * Tests {@link Collection#addAll(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testAddAll() {
+ coll.addAll(null);
+ }
+
+ /**
+ * Tests {@link Collection#clear(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testClear() {
+ coll.clear();
+ }
+
+ /**
+ * Tests {@link Collection#contains(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValue() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ assertTrue(coll.contains(2));
+ verify(extractor, keys);
+ }
+
+ /**
+ * Tests {@link Collection#contains(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsValueFalse() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ assertFalse(coll.contains(3));
+ verify(extractor, keys);
+ }
+
+ /**
+ * Tests {@link Collection#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAll() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ List<Integer> coll = new ArrayList<Integer>();
+ coll.add(1);
+ coll.add(2);
+ assertTrue(this.coll.containsAll(coll));
+ verify(extractor, keys);
+ }
+
+ /**
+ * Tests {@link Collection#containsAll(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testContainsAllFalse() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ List<Integer> coll = new ArrayList<Integer>();
+ coll.add(3);
+ assertFalse(this.coll.containsAll(coll));
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#isEmpty()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIsEmpty() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+
+ replay(extractor, keys);
+ assertFalse(coll.isEmpty());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testIterator() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+
+ expect(extractor.getValue("two")).andReturn(2);
+
+ replay(extractor, keys);
+ Iterator<Integer> entryIt = coll.iterator();
+ assertTrue(entryIt.hasNext());
+ assertEquals(new Integer(2), entryIt.next());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#iterator()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = UnsupportedOperationException.class)
+ public void testIteratorRemove() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+
+ try {
+ replay(extractor, keys);
+ coll.iterator().remove();
+ } finally {
+ verify(extractor, keys);
+ }
+ }
+
+ /**
+ * Tests {@link Collection#remove(Object)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemove() {
+ coll.remove(null);
+ }
+
+ /**
+ * Tests {@link Collection#removeAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRemoveAll() {
+ coll.removeAll(null);
+ }
+
+ /**
+ * Tests {@link Collection#retainAll(java.util.Collection)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testRetainAll() {
+ coll.retainAll(null);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.HeaderValuesMap#size()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testSize() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ replay(extractor, keys);
+ assertEquals(2, coll.size());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#toArray()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ Integer[] entryArray = new Integer[] {1, 2};
+
+ replay(extractor, keys);
+ assertArrayEquals(entryArray, coll.toArray());
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link Collection#toArray(Object[])}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testToArrayTArray() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+
+ Integer[] entryArray = new Integer[] {1, 2};
+
+ replay(extractor, keys);
+ Integer[] realArray = new Integer[2];
+ assertArrayEquals(entryArray, coll.toArray(realArray));
+ verify(extractor, keys);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java
new file mode 100644
index 0000000..c7fcda3
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/RemovableKeySetTest.java
@@ -0,0 +1,132 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import org.apache.tiles.request.attribute.HasRemovableKeys;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link RemovableKeySet}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RemovableKeySetTest {
+
+ /**
+ * The extractor to use.
+ */
+ private HasRemovableKeys<Integer> extractor;
+
+ /**
+ * The key set to test.
+ */
+ private RemovableKeySet entrySet;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ extractor = createMock(HasRemovableKeys.class);
+ entrySet = new RemovableKeySet(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.RemovableKeySet#remove(java.lang.Object)}.
+ */
+ @Test
+ public void testRemove() {
+ expect(extractor.getValue("one")).andReturn(1);
+ extractor.removeValue("one");
+
+ replay(extractor);
+ assertTrue(entrySet.remove("one"));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.RemovableKeySet#remove(java.lang.Object)}.
+ */
+ @Test
+ public void testRemoveNoEffect() {
+ expect(extractor.getValue("one")).andReturn(null);
+
+ replay(extractor);
+ assertFalse(entrySet.remove("one"));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.RemovableKeySet#removeAll(java.util.Collection)}.
+ */
+ @Test
+ public void testRemoveAll() {
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+ extractor.removeValue("one");
+ extractor.removeValue("two");
+
+ replay(extractor);
+ List<String> coll = new ArrayList<String>();
+ coll.add("one");
+ coll.add("two");
+ assertTrue(entrySet.removeAll(coll));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.RemovableKeySet#retainAll(java.util.Collection)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRetainAll() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("three");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ extractor.removeValue("three");
+
+ replay(extractor, keys);
+ List<String> coll = new ArrayList<String>();
+ coll.add("one");
+ coll.add("two");
+ assertTrue(entrySet.retainAll(coll));
+ verify(extractor, keys);
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java
new file mode 100644
index 0000000..229af41
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ScopeMapEntrySetTest.java
@@ -0,0 +1,249 @@
+/*
+ * $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.request.collection;
+
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ScopeMap#entrySet()}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeMapEntrySetTest {
+
+ /**
+ * The map to test.
+ */
+ private ScopeMap map;
+
+ /**
+ * The extractor to use.
+ */
+ private AttributeExtractor extractor;
+
+ /**
+ * The entry set to test.
+ */
+ private Set<Map.Entry<String, Object>> entrySet;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ extractor = createMock(AttributeExtractor.class);
+ map = new ScopeMap(extractor);
+ entrySet = map.entrySet();
+ }
+
+ /**
+ * Tests {@link Set#add(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testAdd() {
+ Map.Entry<String, Object> entry = createMock(Map.Entry.class);
+
+ expect(entry.getKey()).andReturn("one");
+ expect(entry.getValue()).andReturn(1);
+ expect(extractor.getValue("one")).andReturn(null);
+
+ extractor.setValue("one", 1);
+
+ replay(extractor, entry);
+ assertTrue(entrySet.add(entry));
+ verify(extractor, entry);
+ }
+
+ /**
+ * Tests {@link Set#add(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testAddNoEffect() {
+ Map.Entry<String, Object> entry = createMock(Map.Entry.class);
+
+ expect(entry.getKey()).andReturn("one");
+ expect(entry.getValue()).andReturn(1);
+ expect(extractor.getValue("one")).andReturn(1);
+
+ replay(extractor, entry);
+ assertFalse(entrySet.add(entry));
+ verify(extractor, entry);
+ }
+
+ /**
+ * Tests {@link Set#addAll(java.util.Collection)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testAddAll() {
+ Map.Entry<String, Object> entry1 = createMock(Map.Entry.class);
+ Map.Entry<String, Object> entry2 = createMock(Map.Entry.class);
+
+ expect(entry1.getKey()).andReturn("one");
+ expect(entry1.getValue()).andReturn(1);
+ expect(entry2.getKey()).andReturn("two");
+ expect(entry2.getValue()).andReturn(2);
+ expect(extractor.getValue("one")).andReturn(null);
+ expect(extractor.getValue("two")).andReturn(null);
+
+ extractor.setValue("one", 1);
+ extractor.setValue("two", 2);
+
+ replay(extractor, entry1, entry2);
+ List<Map.Entry<String, Object>> coll = new ArrayList<Map.Entry<String, Object>>();
+ coll.add(entry1);
+ coll.add(entry2);
+ assertTrue(entrySet.addAll(coll));
+ verify(extractor, entry1, entry2);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ScopeMap#clear()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testClear() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ extractor.removeValue("one");
+ extractor.removeValue("two");
+
+ replay(extractor, keys);
+ entrySet.clear();
+ verify(extractor, keys);
+ }
+
+ /**
+ * Tests {@link Set#remove(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRemove() {
+ Map.Entry<String, Object> entry = createMock(Map.Entry.class);
+
+ expect(entry.getKey()).andReturn("one");
+ expect(entry.getValue()).andReturn(1);
+ expect(extractor.getValue("one")).andReturn(1);
+ extractor.removeValue("one");
+
+ replay(extractor, entry);
+ assertTrue(entrySet.remove(entry));
+ verify(extractor, entry);
+ }
+
+ /**
+ * Tests {@link Set#remove(Object)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRemoveNoEffect() {
+ Map.Entry<String, Object> entry = createMock(Map.Entry.class);
+
+ expect(entry.getKey()).andReturn("one");
+ expect(extractor.getValue("one")).andReturn(null);
+
+ replay(extractor, entry);
+ assertFalse(entrySet.remove(entry));
+ verify(extractor, entry);
+ }
+
+ /**
+ * Tests {@link Set#addAll(java.util.Collection)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRemoveAll() {
+ Map.Entry<String, Object> entry1 = createMock(Map.Entry.class);
+ Map.Entry<String, Object> entry2 = createMock(Map.Entry.class);
+
+ expect(entry1.getKey()).andReturn("one");
+ expect(entry1.getValue()).andReturn(1);
+ expect(entry2.getKey()).andReturn("two");
+ expect(entry2.getValue()).andReturn(2);
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(2);
+ extractor.removeValue("one");
+ extractor.removeValue("two");
+
+ replay(extractor, entry1, entry2);
+ List<Map.Entry<String, Object>> coll = new ArrayList<Map.Entry<String, Object>>();
+ coll.add(entry1);
+ coll.add(entry2);
+ assertTrue(entrySet.removeAll(coll));
+ verify(extractor, entry1, entry2);
+ }
+
+ /**
+ * Tests {@link Set#addAll(java.util.Collection)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRetainAll() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("three");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ Map.Entry<String, Object> entry1 = new MapEntry<String, Object>("one", 1, false);
+ Map.Entry<String, Object> entry2 = new MapEntry<String, Object>("two", 2, false);
+
+ expect(extractor.getValue("one")).andReturn(1);
+ expect(extractor.getValue("two")).andReturn(3);
+ expect(extractor.getValue("three")).andReturn(4);
+ extractor.removeValue("two");
+ extractor.removeValue("three");
+
+ replay(extractor, keys);
+ List<Map.Entry<String, Object>> coll = new ArrayList<Map.Entry<String, Object>>();
+ coll.add(entry1);
+ coll.add(entry2);
+ assertTrue(entrySet.retainAll(coll));
+ verify(extractor, keys);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java
new file mode 100644
index 0000000..914d118
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/collection/ScopeMapTest.java
@@ -0,0 +1,136 @@
+/*
+ * $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.request.collection;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ScopeMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeMapTest {
+
+ /**
+ * The map tot est.
+ */
+ private ScopeMap map;
+
+ /**
+ * The extractor to use.
+ */
+ private AttributeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ extractor = createMock(AttributeExtractor.class);
+ map = new ScopeMap(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ScopeMap#clear()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testClear() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(extractor.getKeys()).andReturn(keys);
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("one");
+ expect(keys.hasMoreElements()).andReturn(true);
+ expect(keys.nextElement()).andReturn("two");
+ expect(keys.hasMoreElements()).andReturn(false);
+
+ extractor.removeValue("one");
+ extractor.removeValue("two");
+
+ replay(extractor, keys);
+ map.clear();
+ verify(extractor, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ScopeMap#keySet()}.
+ */
+ @Test
+ public void testKeySet() {
+ replay(extractor);
+ assertTrue(map.keySet() instanceof RemovableKeySet);
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ScopeMap#put(java.lang.String, java.lang.Object)}.
+ */
+ @Test
+ public void testPutStringObject() {
+ expect(extractor.getValue("one")).andReturn(null);
+ extractor.setValue("one", 1);
+
+ replay(extractor);
+ assertNull(map.put("one", 1));
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ScopeMap#putAll(java.util.Map)}.
+ */
+ @Test
+ public void testPutAllMapOfQextendsStringQextendsObject() {
+ Map<String, Object> items = new LinkedHashMap<String, Object>();
+ items.put("one", 1);
+ items.put("two", 2);
+
+ extractor.setValue("one", 1);
+ extractor.setValue("two", 2);
+
+ replay(extractor);
+ map.putAll(items);
+ verify(extractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.collection.ScopeMap#remove(java.lang.Object)}.
+ */
+ @Test
+ public void testRemoveObject() {
+ expect(extractor.getValue("one")).andReturn(1);
+ extractor.removeValue("one");
+
+ replay(extractor);
+ assertEquals(new Integer(1), map.remove("one"));
+ verify(extractor);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java
new file mode 100644
index 0000000..d603542
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/locale/LocaleUtilTest.java
@@ -0,0 +1,51 @@
+/*
+ * $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.request.locale;
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link LocaleUtil}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class LocaleUtilTest extends TestCase {
+
+ /**
+ * Test method for {@link LocaleUtil#getParentLocale(Locale)}.
+ */
+ public void testGetParentLocale() {
+ assertNull("The parent locale of NULL_LOCALE is not correct",
+ LocaleUtil.getParentLocale(Locale.ROOT));
+ assertEquals("The parent locale of 'en' is not correct",
+ Locale.ROOT, LocaleUtil
+ .getParentLocale(Locale.ENGLISH));
+ assertEquals("The parent locale of 'en_US' is not correct",
+ Locale.ENGLISH, LocaleUtil.getParentLocale(Locale.US));
+ Locale locale = new Locale("es", "ES", "Traditional_WIN");
+ Locale parentLocale = new Locale("es", "ES");
+ assertEquals("The parent locale of 'es_ES_Traditional_WIN' is not correct",
+ parentLocale, LocaleUtil.getParentLocale(locale));
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java
new file mode 100644
index 0000000..02c13e4
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/locale/PostfixedApplicationResourceTest.java
@@ -0,0 +1,111 @@
+/*
+ * $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.request.locale;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
+import org.junit.Test;
+
+/**
+ * Tests PostfixedApplicationResource.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PostfixedApplicationResourceTest {
+
+ private class TestApplicationResource extends PostfixedApplicationResource {
+ public TestApplicationResource(String path, Locale locale) {
+ super(path, locale);
+ }
+
+ public TestApplicationResource(String localePath) {
+ super(localePath);
+ }
+
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return null;
+ }
+
+ @Override
+ public long getLastModified() throws IOException {
+ return 0;
+ }
+
+ };
+
+ /**
+ * Test getLocalePath(String path, Locale locale).
+ */
+ @Test
+ public void testGetLocalePath() {
+ TestApplicationResource resource = new TestApplicationResource("/my/path_fr.html");
+ assertEquals("/my/path.html", resource.getLocalePath(null));
+ assertEquals("/my/path.html", resource.getLocalePath(Locale.ROOT));
+ assertEquals("/my/path_it.html", resource.getLocalePath(Locale.ITALIAN));
+ assertEquals("/my/path_it_IT.html", resource.getLocalePath(Locale.ITALY));
+ assertEquals("/my/path_en_GB_scotland.html", resource.getLocalePath(new Locale("en", "GB", "scotland")));
+ }
+
+ @Test
+ public void testBuildFromString() {
+ TestApplicationResource resource = new TestApplicationResource("/my/path_en_GB_scotland.html");
+ assertEquals("/my/path_en_GB_scotland.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale());
+ resource = new TestApplicationResource("/my/path_it_IT.html");
+ assertEquals("/my/path_it_IT.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(Locale.ITALY, resource.getLocale());
+ resource = new TestApplicationResource("/my/path_it.html");
+ assertEquals("/my/path_it.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(Locale.ITALIAN, resource.getLocale());
+ resource = new TestApplicationResource("/my/path.html");
+ assertEquals("/my/path.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ }
+
+ @Test
+ public void testBuildFromStringAndLocale() {
+ TestApplicationResource resource = new TestApplicationResource("/my/path.html", new Locale("en", "GB", "scotland"));
+ assertEquals("/my/path_en_GB_scotland.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(new Locale("en", "GB", "scotland"), resource.getLocale());
+ resource = new TestApplicationResource("/my/path.html", Locale.ITALY);
+ assertEquals("/my/path_it_IT.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(Locale.ITALY, resource.getLocale());
+ resource = new TestApplicationResource("/my/path.html", Locale.ITALIAN);
+ assertEquals("/my/path_it.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(Locale.ITALIAN, resource.getLocale());
+ resource = new TestApplicationResource("/my/path.html", Locale.ROOT);
+ assertEquals("/my/path.html", resource.getLocalePath());
+ assertEquals("/my/path.html", resource.getPath());
+ assertEquals(Locale.ROOT, resource.getLocale());
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/CannotAccessMethodExceptionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/CannotAccessMethodExceptionTest.java
new file mode 100644
index 0000000..5d2a8a3
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/CannotAccessMethodExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request.reflect;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link CannotAccessMethodException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CannotAccessMethodExceptionTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.CannotAccessMethodException#CannotAccessMethodException()}.
+ */
+ @Test
+ public void testCannotAccessMethodException() {
+ CannotAccessMethodException exception = new CannotAccessMethodException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link CannotAccessMethodException#CannotAccessMethodException(String)}.
+ */
+ @Test
+ public void testCannotAccessMethodExceptionString() {
+ CannotAccessMethodException exception = new CannotAccessMethodException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link CannotAccessMethodException#CannotAccessMethodException(Throwable)}.
+ */
+ @Test
+ public void testCannotAccessMethodExceptionThrowable() {
+ Throwable cause = new Throwable();
+ CannotAccessMethodException exception = new CannotAccessMethodException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link CannotAccessMethodException#CannotAccessMethodException(String, Throwable)}.
+ */
+ @Test
+ public void testCannotAccessMethodExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ CannotAccessMethodException exception = new CannotAccessMethodException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java
new file mode 100644
index 0000000..4b3bd9b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/CannotInstantiateObjectExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request.reflect;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link CannotInstantiateObjectException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class CannotInstantiateObjectExceptionTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.CannotInstantiateObjectException#CannotInstantiateObjectException()}.
+ */
+ @Test
+ public void testCannotInstantiateObjectException() {
+ CannotInstantiateObjectException exception = new CannotInstantiateObjectException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link CannotInstantiateObjectException#CannotInstantiateObjectException(String)}.
+ */
+ @Test
+ public void testCannotInstantiateObjectExceptionString() {
+ CannotInstantiateObjectException exception = new CannotInstantiateObjectException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link CannotInstantiateObjectException#CannotInstantiateObjectException(Throwable)}.
+ */
+ @Test
+ public void testCannotInstantiateObjectExceptionThrowable() {
+ Throwable cause = new Throwable();
+ CannotInstantiateObjectException exception = new CannotInstantiateObjectException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link CannotInstantiateObjectException#CannotInstantiateObjectException(String, Throwable)}.
+ */
+ @Test
+ public void testCannotInstantiateObjectExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ CannotInstantiateObjectException exception = new CannotInstantiateObjectException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java
new file mode 100644
index 0000000..e1b94f3
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/reflect/ClassUtilTest.java
@@ -0,0 +1,176 @@
+/*
+ * $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.request.reflect;
+
+import static org.junit.Assert.*;
+
+import java.beans.PropertyDescriptor;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link ClassUtil}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ClassUtilTest {
+
+ /**
+ * The size of descriptor map.
+ */
+ private static final int MAP_SIZE = 3;
+
+ /**
+ * Test method for {@link ClassUtil#collectBeanInfo(Class, Map)}.
+ */
+ @Test
+ public void testCollectBeanInfo() {
+ Map<String, PropertyDescriptor> name2descriptor = new HashMap<String, PropertyDescriptor>();
+ ClassUtil.collectBeanInfo(TestInterface.class, name2descriptor);
+ assertEquals(MAP_SIZE, name2descriptor.size());
+ PropertyDescriptor descriptor = name2descriptor.get("value");
+ assertEquals("value", descriptor.getName());
+ assertEquals(int.class, descriptor.getPropertyType());
+ assertNotNull(descriptor.getReadMethod());
+ assertNotNull(descriptor.getWriteMethod());
+ descriptor = name2descriptor.get("value2");
+ assertEquals("value2", descriptor.getName());
+ assertEquals(long.class, descriptor.getPropertyType());
+ assertNotNull(descriptor.getReadMethod());
+ assertNull(descriptor.getWriteMethod());
+ descriptor = name2descriptor.get("value3");
+ assertEquals("value3", descriptor.getName());
+ assertEquals(String.class, descriptor.getPropertyType());
+ assertNull(descriptor.getReadMethod());
+ assertNotNull(descriptor.getWriteMethod());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#getClass(String, Class)}.
+ * @throws ClassNotFoundException If something goes wrong.
+ */
+ @Test
+ public void testGetClass() throws ClassNotFoundException {
+ assertEquals(TestInterface.class, ClassUtil.getClass(
+ TestInterface.class.getName(), Object.class));
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#getClass(String, Class)}.
+ * @throws ClassNotFoundException If something goes wrong.
+ */
+ @Test(expected = ClassNotFoundException.class)
+ public void testGetClassException() throws ClassNotFoundException {
+ ClassUtil.getClass("this.class.does.not.Exist", Object.class);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#instantiate(String, boolean)}.
+ */
+ @Test
+ public void testInstantiate() {
+ assertNotNull(ClassUtil.instantiate(TestClass.class.getName(), true));
+ assertNull(ClassUtil.instantiate("this.class.does.not.Exist", true));
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#instantiate(String, boolean)}.
+ */
+ @Test
+ public void testInstantiateOneParameter() {
+ assertNotNull(ClassUtil.instantiate(TestClass.class.getName()));
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#instantiate(String)}.
+ */
+ @Test(expected = CannotInstantiateObjectException.class)
+ public void testInstantiateOneParameterException() {
+ assertNotNull(ClassUtil.instantiate("this.class.does.not.Exist"));
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#instantiate(String)}.
+ */
+ @Test(expected = CannotInstantiateObjectException.class)
+ public void testInstantiateInstantiationException() {
+ ClassUtil.instantiate(TestInterface.class.getName());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.reflect.ClassUtil#instantiate(String)}.
+ */
+ @Test(expected = CannotInstantiateObjectException.class)
+ public void testInstantiateIllegalAccessException() {
+ ClassUtil.instantiate(TestPrivateClass.class.getName());
+ }
+
+ /**
+ * Interface to be used as test.
+ *
+ * @version $Rev$ $Date$
+ */
+ public static interface TestInterface {
+
+ /**
+ * The value.
+ *
+ * @return The value.
+ */
+ int getValue();
+
+ /**
+ * The value.
+ *
+ * @param value The value.
+ */
+ void setValue(int value);
+
+ /**
+ * The value.
+ *
+ * @return The value.
+ */
+ long getValue2();
+
+ /**
+ * The value.
+ *
+ * @param value3 The value.
+ */
+ void setValue3(String value3);
+ }
+
+ /**
+ * A test static class.
+ */
+ public static class TestClass {
+ }
+
+ /**
+ * A test static private class.
+ */
+ private static class TestPrivateClass {
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java
new file mode 100644
index 0000000..722357b
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/BasicRendererFactoryTest.java
@@ -0,0 +1,111 @@
+/*
+ * $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.request.render;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Basic renderer factory implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BasicRendererFactoryTest {
+
+ /**
+ * The renderer factory.
+ */
+ private BasicRendererFactory rendererFactory;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ rendererFactory = new BasicRendererFactory();
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ replay(applicationContext);
+ }
+
+ /**
+ * Tests execution and
+ * {@link BasicRendererFactory#getRenderer(String)}.
+ */
+ @Test
+ public void testInitAndGetRenderer() {
+ Renderer renderer1 = createMock(Renderer.class);
+ Renderer renderer2 = createMock(Renderer.class);
+ Renderer renderer3 = createMock(Renderer.class);
+ Renderer renderer4 = createMock(Renderer.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ replay(renderer1, renderer2, renderer3, renderer4, applicationContext);
+ rendererFactory.registerRenderer("string", renderer1);
+ rendererFactory.registerRenderer("test", renderer2);
+ rendererFactory.registerRenderer("test2", renderer3);
+ rendererFactory.setDefaultRenderer(renderer4);
+ Renderer renderer = rendererFactory.getRenderer("string");
+ assertSame(renderer1, renderer);
+ renderer = rendererFactory.getRenderer("test");
+ assertSame(renderer2, renderer);
+ renderer = rendererFactory.getRenderer("test2");
+ assertSame(renderer3, renderer);
+ renderer = rendererFactory.getRenderer(null);
+ assertSame(renderer4, renderer);
+ verify(renderer1, renderer2, renderer3, renderer4, applicationContext);
+ }
+
+ /**
+ * Tests execution and
+ * {@link BasicRendererFactory#getRenderer(String)}.
+ */
+ @Test(expected = NoSuchRendererException.class)
+ public void testGetRendererException() {
+ Renderer renderer1 = createMock(Renderer.class);
+ Renderer renderer2 = createMock(Renderer.class);
+ Renderer renderer3 = createMock(Renderer.class);
+ Renderer renderer4 = createMock(Renderer.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ replay(renderer1, renderer2, renderer3, renderer4, applicationContext);
+ rendererFactory.registerRenderer("string", renderer1);
+ rendererFactory.registerRenderer("test", renderer2);
+ rendererFactory.registerRenderer("test2", renderer3);
+ rendererFactory.setDefaultRenderer(renderer4);
+ try {
+ rendererFactory.getRenderer("nothing");
+ } finally {
+ verify(renderer1, renderer2, renderer3, renderer4, applicationContext);
+ }
+ }
+
+ /**
+ * Tests {@link BasicRendererFactory#initializeRenderer(AttributeRenderer)}.
+ */
+ @Test
+ public void testInitializeRenderer() {
+ // TODO This will be removed in future, only named renderers should be available.
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java
new file mode 100644
index 0000000..2f89255
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/ChainedDelegateRendererTest.java
@@ -0,0 +1,211 @@
+/*
+ * $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.request.render;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import org.apache.tiles.request.Request;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ChainedDelegateRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ChainedDelegateRendererTest {
+
+ /**
+ * The renderer.
+ */
+ private ChainedDelegateRenderer renderer;
+
+ /**
+ * A mock string attribute renderer.
+ */
+ private Renderer stringRenderer;
+
+ /**
+ * A mock template attribute renderer.
+ */
+ private Renderer templateRenderer;
+
+ /**
+ * A mock definition attribute renderer.
+ */
+ private Renderer definitionRenderer;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ stringRenderer = createMock(Renderer.class);
+ templateRenderer = createMock(Renderer.class);
+ definitionRenderer = createMock(Renderer.class);
+ renderer = new ChainedDelegateRenderer();
+ renderer.addAttributeRenderer(definitionRenderer);
+ renderer.addAttributeRenderer(templateRenderer);
+ renderer.addAttributeRenderer(stringRenderer);
+ }
+
+ /**
+ * Tests
+ * {@link ChainedDelegateRenderer#render(String, Request)}
+ * writing a definition.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test
+ public void testWriteDefinition() throws IOException {
+ Request requestContext = EasyMock
+ .createMock(Request.class);
+
+ expect(
+ definitionRenderer.isRenderable("my.definition",
+ requestContext)).andReturn(Boolean.TRUE);
+ definitionRenderer.render("my.definition", requestContext);
+
+ replay(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ renderer.render("my.definition", requestContext);
+ verify(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ }
+
+ /**
+ * Tests
+ * {@link ChainedDelegateRenderer#render(String, Request)}
+ * writing a definition.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testWriteNull() throws IOException {
+ StringWriter writer = new StringWriter();
+ Request requestContext = EasyMock
+ .createMock(Request.class);
+
+ replay(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ try {
+ renderer.render(null, requestContext);
+ } finally {
+ writer.close();
+ verify(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ }
+ }
+
+ /**
+ * Tests
+ * {@link ChainedDelegateRenderer#render(String, Request)}
+ * writing a definition.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test(expected = CannotRenderException.class)
+ public void testWriteNotRenderable() throws IOException {
+ StringWriter writer = new StringWriter();
+ Request requestContext = EasyMock
+ .createMock(Request.class);
+
+ expect(
+ definitionRenderer.isRenderable("Result",
+ requestContext)).andReturn(Boolean.FALSE);
+ expect(
+ templateRenderer.isRenderable("Result",
+ requestContext)).andReturn(Boolean.FALSE);
+ expect(stringRenderer.isRenderable("Result", requestContext))
+ .andReturn(Boolean.FALSE);
+
+ replay(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ try {
+ renderer.render("Result", requestContext);
+ } finally {
+ writer.close();
+ verify(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ }
+ }
+
+ /**
+ * Tests
+ * {@link ChainedDelegateRenderer#render(String, Request)}
+ * writing a string.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test
+ public void testWriteString() throws IOException {
+ Request requestContext = EasyMock
+ .createMock(Request.class);
+ expect(
+ definitionRenderer.isRenderable("Result",
+ requestContext)).andReturn(Boolean.FALSE);
+ expect(
+ templateRenderer.isRenderable("Result",
+ requestContext)).andReturn(Boolean.FALSE);
+ expect(
+ stringRenderer.isRenderable("Result",
+ requestContext)).andReturn(Boolean.TRUE);
+ stringRenderer.render("Result", requestContext);
+
+ replay(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ renderer.render("Result", requestContext);
+ verify(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ }
+
+ /**
+ * Tests
+ * {@link ChainedDelegateRenderer#render(String, Request)}
+ * writing a template.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test
+ public void testWriteTemplate() throws IOException {
+ StringWriter writer = new StringWriter();
+ Request requestContext = EasyMock
+ .createMock(Request.class);
+ templateRenderer.render("/myTemplate.jsp", requestContext);
+ expect(
+ definitionRenderer.isRenderable("/myTemplate.jsp",
+ requestContext)).andReturn(Boolean.FALSE);
+ expect(
+ templateRenderer.isRenderable("/myTemplate.jsp",
+ requestContext)).andReturn(Boolean.TRUE);
+
+ replay(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ renderer.render("/myTemplate.jsp", requestContext);
+ writer.close();
+ verify(requestContext, stringRenderer, templateRenderer,
+ definitionRenderer);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java
new file mode 100644
index 0000000..52a9936
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/DispatchRendererTest.java
@@ -0,0 +1,92 @@
+/*
+ * $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.request.render;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.DispatchRequest;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link DispatchRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DispatchRendererTest {
+
+ /**
+ * The renderer.
+ */
+ private DispatchRenderer renderer;
+
+ /** {@inheritDoc} */
+ @Before
+ public void setUp() {
+ renderer = new DispatchRenderer();
+ }
+
+ /**
+ * Tests
+ * {@link DispatchRenderer#render(String, DispatchRequest)}.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test
+ public void testWrite() throws IOException {
+ DispatchRequest requestContext = createMock(DispatchRequest.class);
+ requestContext.dispatch("/myTemplate.jsp");
+ replay(requestContext);
+ renderer.render("/myTemplate.jsp", requestContext);
+ verify(requestContext);
+ }
+
+ /**
+ * Tests
+ * {@link DispatchRenderer#render(String, DispatchRequest)}.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test(expected = CannotRenderException.class)
+ public void testWriteNull() throws IOException {
+ DispatchRequest requestContext = createMock(DispatchRequest.class);
+ replay(requestContext);
+ renderer.render(null, requestContext);
+ verify(requestContext);
+ }
+
+ /**
+ * Tests
+ * {@link DispatchRenderer#isRenderable(String, DispatchRequest)}.
+ */
+ @Test
+ public void testIsRenderable() {
+ Request requestContext = createMock(DispatchRequest.class);
+ replay(requestContext);
+ assertTrue(renderer.isRenderable("/myTemplate.jsp", requestContext));
+ assertFalse(renderer.isRenderable(null, requestContext));
+ verify(requestContext);
+ }
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java
new file mode 100644
index 0000000..4c3ef77
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/NoSuchRendererExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request.render;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link NoSuchRendererException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NoSuchRendererExceptionTest {
+
+ /**
+ * Test method for {@link NoSuchRendererException#NoSuchRendererException()}.
+ */
+ @Test
+ public void testNoSuchRendererException() {
+ NoSuchRendererException exception = new NoSuchRendererException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NoSuchRendererException#NoSuchRendererException(java.lang.String)}.
+ */
+ @Test
+ public void testNoSuchRendererExceptionString() {
+ NoSuchRendererException exception = new NoSuchRendererException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NoSuchRendererException#NoSuchRendererException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testNoSuchRendererExceptionThrowable() {
+ Throwable cause = new Throwable();
+ NoSuchRendererException exception = new NoSuchRendererException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NoSuchRendererException#NoSuchRendererException(java.lang.String, java.lang.Throwable)}.
+ */
+ @Test
+ public void testNoSuchRendererExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ NoSuchRendererException exception = new NoSuchRendererException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/StringRendererTest.java b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/StringRendererTest.java
new file mode 100644
index 0000000..df7e1a9
--- /dev/null
+++ b/tiles-request/tiles-request-api/src/test/java/org/apache/tiles/request/render/StringRendererTest.java
@@ -0,0 +1,80 @@
+/*
+ * $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.request.render;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import org.apache.tiles.request.Request;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link StringRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StringRendererTest {
+
+ /**
+ * The renderer.
+ */
+ private StringRenderer renderer;
+
+ /** {@inheritDoc} */
+ @Before
+ public void setUp() {
+ renderer = new StringRenderer();
+ }
+
+ /**
+ * Tests
+ * {@link StringRenderer#render(String, Request)}.
+ *
+ * @throws IOException If something goes wrong during rendition.
+ */
+ @Test
+ public void testWrite() throws IOException {
+ StringWriter writer = new StringWriter();
+ Request requestContext = createMock(Request.class);
+ expect(requestContext.getWriter()).andReturn(writer);
+ replay(requestContext);
+ renderer.render("Result", requestContext);
+ writer.close();
+ assertEquals("Not written 'Result'", "Result", writer.toString());
+ verify(requestContext);
+ }
+
+ /**
+ * Tests
+ * {@link StringRenderer#isRenderable(String, Request)}.
+ */
+ @Test
+ public void testIsRenderable() {
+ Request requestContext = createMock(Request.class);
+ replay(requestContext);
+ assertTrue(renderer.isRenderable("Result", requestContext));
+ verify(requestContext);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/pom.xml b/tiles-request/tiles-request-freemarker/pom.xml
new file mode 100644
index 0000000..4dabc58
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-request</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-freemarker</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles Request - Freemarker support</name>
+ <description>Freemarker implementation of the Tiles request framework</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java
new file mode 100644
index 0000000..b2a60ba
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/EnvironmentScopeMap.java
@@ -0,0 +1,66 @@
+/*
+ * $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.request.freemarker;
+
+import java.util.Set;
+
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.freemarker.extractor.EnvironmentScopeExtractor;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateModelException;
+
+/**
+ * <p>
+ * Private implementation of <code>Map</code> for servlet request attributes.
+ * </p>
+ *
+ * @version $Rev$ $Date$
+ */
+
+final class EnvironmentScopeMap extends ScopeMap {
+
+ /**
+ * The request object to use.
+ */
+ private Environment request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request object to use.
+ */
+ public EnvironmentScopeMap(Environment request) {
+ super(new EnvironmentScopeExtractor(request));
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Set<String> keySet() {
+ try {
+ return request.getKnownVariableNames();
+ } catch (TemplateModelException e) {
+ throw new FreemarkerRequestException(
+ "Cannot get known variable names", e);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java
new file mode 100644
index 0000000..212badf
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequest.java
@@ -0,0 +1,154 @@
+/*
+ * $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.request.freemarker;
+
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.AbstractViewRequest;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.DispatchRequest;
+import org.apache.tiles.request.servlet.ServletRequest;
+
+import freemarker.core.Environment;
+import freemarker.ext.servlet.HttpRequestHashModel;
+
+/**
+ * The FreeMarker-specific request context.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerRequest extends AbstractViewRequest {
+
+ /**
+ * The natively available scopes. In fact, only "page".
+ */
+ private List<String> scopes;
+
+ /**
+ * The FreeMarker current environment.
+ */
+ private Environment env;
+
+ /**
+ * The page scope map.
+ */
+ private Map<String, Object> pageScope;
+
+ /**
+ * Creates a new Freemarker request.
+ *
+ * @param applicationContext The application context.
+ * @param env The Freemarker's environment object.
+ * @return A new request.
+ */
+ public static FreemarkerRequest createServletFreemarkerRequest(
+ ApplicationContext applicationContext, Environment env) {
+ HttpRequestHashModel requestModel = FreemarkerRequestUtil
+ .getRequestHashModel(env);
+ HttpServletRequest request = requestModel.getRequest();
+ HttpServletResponse response = requestModel.getResponse();
+ DispatchRequest enclosedRequest = new ServletRequest(
+ applicationContext, request, response);
+ return new FreemarkerRequest(enclosedRequest, env);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param enclosedRequest
+ * The request that exposes non-FreeMarker specific properties
+ * @param env
+ * The FreeMarker environment.
+ */
+ public FreemarkerRequest(DispatchRequest enclosedRequest,
+ Environment env) {
+ super(enclosedRequest);
+ List<String> scopes = new ArrayList<String>();
+ scopes.addAll(enclosedRequest.getAvailableScopes());
+ scopes.add("page");
+ this.scopes = Collections.unmodifiableList(scopes);
+ this.env = env;
+ }
+
+ /**
+ * Returns the environment object.
+ *
+ * @return The environment.
+ */
+ public Environment getEnvironment() {
+ return env;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Locale getRequestLocale() {
+ return env.getLocale();
+ }
+
+ /**
+ * Returns the page scope.
+ *
+ * @return The page scope.
+ */
+ public Map<String, Object> getPageScope() {
+ if (pageScope == null) {
+ pageScope = new EnvironmentScopeMap(env);
+ }
+ return pageScope;
+ }
+
+ @Override
+ public List<String> getAvailableScopes() {
+ return scopes;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter getPrintWriter() {
+ Writer writer = env.getOut();
+ if (writer instanceof PrintWriter) {
+ return (PrintWriter) writer;
+ }
+ return new PrintWriter(writer);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Writer getWriter() {
+ return env.getOut();
+ }
+
+ @Override
+ public Map<String, Object> getContext(String scope) {
+ return "page".equals(scope) ? getPageScope() : super.getContext(scope);
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java
new file mode 100644
index 0000000..b2a33f2
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestException.java
@@ -0,0 +1,65 @@
+/*
+ * $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.request.freemarker;
+
+import org.apache.tiles.request.RequestException;
+
+/**
+ * Thrown when a Freemarker request fails.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerRequestException extends RequestException {
+
+ /**
+ * Constructor.
+ */
+ public FreemarkerRequestException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public FreemarkerRequestException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause to be wrapped.
+ */
+ public FreemarkerRequestException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param cause The cause to be wrapped.
+ */
+ public FreemarkerRequestException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java
new file mode 100644
index 0000000..929e8cc
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtil.java
@@ -0,0 +1,94 @@
+/*
+ * $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.request.freemarker;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.servlet.ServletUtil;
+
+import freemarker.core.Environment;
+import freemarker.ext.servlet.FreemarkerServlet;
+import freemarker.ext.servlet.HttpRequestHashModel;
+import freemarker.ext.servlet.ServletContextHashModel;
+import freemarker.template.TemplateModelException;
+
+/**
+ * Utilities to work with Freemarker requests.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class FreemarkerRequestUtil {
+
+ /**
+ * Constructor.
+ */
+ private FreemarkerRequestUtil() {
+ }
+
+ /**
+ * Returns the HTTP request hash model.
+ *
+ * @param env The current FreeMarker environment.
+ * @return The request hash model.
+ */
+ public static HttpRequestHashModel getRequestHashModel(Environment env) {
+ try {
+ return (HttpRequestHashModel) env.getDataModel().get(
+ FreemarkerServlet.KEY_REQUEST);
+ } catch (TemplateModelException e) {
+ throw new NotAvailableFreemarkerServletException(
+ "Exception got when obtaining the request hash model", e);
+ }
+ }
+
+ /**
+ * Returns the servlet context hash model.
+ *
+ * @param env The current FreeMarker environment.
+ * @return The servlet context hash model.
+ */
+ public static ServletContextHashModel getServletContextHashModel(
+ Environment env) {
+ try {
+ return (ServletContextHashModel) env.getDataModel().get(
+ FreemarkerServlet.KEY_APPLICATION);
+ } catch (TemplateModelException e) {
+ throw new NotAvailableFreemarkerServletException(
+ "Exception got when obtaining the application hash model",
+ e);
+ }
+ }
+
+ /**
+ * Returns the application context. It must be
+ * first saved creating an {@link ApplicationContext} and using
+ * {@link org.apache.tiles.request.ApplicationAccess#register(ApplicationContext)}.
+ *
+ * @param env The Freemarker environment.
+ * @return The
+ */
+ public static ApplicationContext getApplicationContext(
+ Environment env) {
+ return ServletUtil
+ .getApplicationContext(getServletContextHashModel(env)
+ .getServlet().getServletContext());
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java
new file mode 100644
index 0000000..a265428
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletException.java
@@ -0,0 +1,66 @@
+/*
+ * $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.request.freemarker;
+
+import org.apache.tiles.request.NotAvailableFeatureException;
+
+/**
+ * Thrown when a the Freemarker servlet is not available.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotAvailableFreemarkerServletException extends
+ NotAvailableFeatureException {
+
+ /**
+ * Constructor.
+ */
+ public NotAvailableFreemarkerServletException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public NotAvailableFreemarkerServletException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The cause to be wrapped.
+ */
+ public NotAvailableFreemarkerServletException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The cause to be wrapped.
+ */
+ public NotAvailableFreemarkerServletException(String message, Throwable e) {
+ super(message, e);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.java
new file mode 100644
index 0000000..04df896
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagException.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.request.freemarker.autotag;
+
+/**
+ * Thrown when a Freemarker problem under Autotag runtime part happens.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerAutotagException extends RuntimeException {
+
+ /**
+ * Constructor.
+ */
+ public FreemarkerAutotagException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ */
+ public FreemarkerAutotagException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cause The cause.
+ */
+ public FreemarkerAutotagException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The message of the exception.
+ * @param cause The cause.
+ */
+ public FreemarkerAutotagException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java
new file mode 100644
index 0000000..9eabac3
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntime.java
@@ -0,0 +1,71 @@
+/*
+ * $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.request.freemarker.autotag;
+
+import java.util.Map;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.freemarker.FreemarkerRequest;
+import org.apache.tiles.request.freemarker.FreemarkerRequestUtil;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateModel;
+
+/**
+ * A Runtime for implementing a Freemarker Template Directive.
+ */
+public class FreemarkerAutotagRuntime implements AutotagRuntime, TemplateDirectiveModel {
+
+ private Environment env;
+ private TemplateDirectiveBody body;
+ private Map<String, TemplateModel> params;
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) {
+ this.env = env;
+ this.body = body;
+ this.params = params;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Request createRequest() {
+ return FreemarkerRequest.createServletFreemarkerRequest(FreemarkerRequestUtil.getApplicationContext(env), env);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelBody createModelBody() {
+ return new FreemarkerModelBody(env.getOut(), body);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Object getParameter(String name, Object defaultValue) {
+ return FreemarkerUtil.getAsObject((TemplateModel)params.get(name), defaultValue);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java
new file mode 100644
index 0000000..a006bca
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBody.java
@@ -0,0 +1,67 @@
+/*
+ * $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.request.freemarker.autotag;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.tiles.autotag.core.runtime.AbstractModelBody;
+
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateException;
+
+/**
+ * Body implementation of a Freemarker model body.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerModelBody extends AbstractModelBody {
+
+ /**
+ * The real body.
+ */
+ private TemplateDirectiveBody templateDirectiveBody;
+
+ /**
+ * Constructor.
+ *
+ * @param defaultWriter The default writer.
+ * @param templateDirectiveBody The real body.
+ */
+ public FreemarkerModelBody(Writer defaultWriter, TemplateDirectiveBody templateDirectiveBody) {
+ super(defaultWriter);
+ this.templateDirectiveBody = templateDirectiveBody;
+ }
+
+ @Override
+ public void evaluate(Writer writer) throws IOException {
+ if (templateDirectiveBody == null) {
+ return;
+ }
+
+ try {
+ templateDirectiveBody.render(writer);
+ } catch (TemplateException e) {
+ throw new IOException("TemplateException when rendering body", e);
+ }
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java
new file mode 100644
index 0000000..881e511
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtil.java
@@ -0,0 +1,63 @@
+/*
+ * $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.request.freemarker.autotag;
+
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.utility.DeepUnwrap;
+
+/**
+ * Utilities for FreeMarker usage in Tiles.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class FreemarkerUtil {
+
+ /**
+ * Private constructor to avoid instantiation.
+ */
+ private FreemarkerUtil() {
+ }
+
+ /**
+ * Unwraps a TemplateModel to extract an object.
+ *
+ * @param model The TemplateModel to unwrap.
+ * @param defaultValue The default value, as specified in the template
+ * model, or null if not specified.
+ * @return The unwrapped object.
+ */
+ public static Object getAsObject(TemplateModel model, Object defaultValue) {
+ try {
+ Object retValue = defaultValue;
+ if (model != null) {
+ Object value = DeepUnwrap.unwrap(model);
+ if (value != null) {
+ retValue = value;
+ }
+ }
+ return retValue;
+ } catch (TemplateModelException e) {
+ throw new FreemarkerAutotagException("Cannot unwrap a model", e);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java
new file mode 100644
index 0000000..fb875dc
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/autotag/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Runtime part of Autotag support for Freemarker.
+ */
+package org.apache.tiles.request.freemarker.autotag;
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java
new file mode 100644
index 0000000..78fcb9d
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractor.java
@@ -0,0 +1,92 @@
+/*
+ * $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.request.freemarker.extractor;
+
+import java.util.Collections;
+import java.util.Enumeration;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+import org.apache.tiles.request.freemarker.FreemarkerRequestException;
+
+import freemarker.core.Environment;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.utility.DeepUnwrap;
+
+/**
+ * Extract attributes from {@link Environment} objects as a scope.
+ *
+ * @version $Rev$ $Date$
+ */
+public class EnvironmentScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The environment.
+ */
+ private Environment request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The environment.
+ */
+ public EnvironmentScopeExtractor(Environment request) {
+ this.request = request;
+ }
+
+ @Override
+ public void removeValue(String name) {
+ request.setVariable(name, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ try {
+ return Collections.<String> enumeration(request.getKnownVariableNames());
+ } catch (TemplateModelException e) {
+ throw new FreemarkerRequestException("Cannot iterate variable names correctly", e);
+ }
+ }
+
+ @Override
+ public Object getValue(String key) {
+ try {
+ TemplateModel variable = request.getVariable(key);
+ if (variable != null) {
+ return DeepUnwrap.unwrap(variable);
+ }
+ return null;
+ } catch (TemplateModelException e) {
+ throw new FreemarkerRequestException("Cannot get attribute with name '" + key + "'", e);
+ }
+ }
+
+ @Override
+ public void setValue(String key, Object value) {
+ try {
+ TemplateModel model = request.getObjectWrapper().wrap(value);
+ request.setVariable(key, model);
+ } catch (TemplateModelException e) {
+ throw new FreemarkerRequestException("Error when wrapping an object setting the '" + key + "' attribute", e);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java
new file mode 100644
index 0000000..8e94691
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/extractor/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Extractors to get information from Freemarker objects.
+ */
+package org.apache.tiles.request.freemarker.extractor;
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/package-info.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/package-info.java
new file mode 100644
index 0000000..234a67c
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Support for Freemarker's Environment as a request.
+ */
+package org.apache.tiles.request.freemarker;
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/AttributeValueFreemarkerServlet.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/AttributeValueFreemarkerServlet.java
new file mode 100644
index 0000000..98c0bc9
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/AttributeValueFreemarkerServlet.java
@@ -0,0 +1,56 @@
+/*
+ * $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.request.freemarker.render;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tiles.request.freemarker.servlet.SharedVariableLoaderFreemarkerServlet;
+
+/**
+ * Extends {@link SharedVariableLoaderFreemarkerServlet} to use the attribute value as the template name.
+ */
+public class AttributeValueFreemarkerServlet extends SharedVariableLoaderFreemarkerServlet {
+
+ /**
+ * The serial UID.
+ */
+ private static final long serialVersionUID = 5412169082301451211L;
+
+ /**
+ * Holds the value that should be used as the template name.
+ */
+ private ThreadLocal<String> valueHolder = new ThreadLocal<String>();
+
+ /**
+ * Sets the value to use as the template name.
+ *
+ * @param value The template name.
+ */
+ public void setValue(String value) {
+ valueHolder.set(value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected String requestUrlToTemplatePath(HttpServletRequest request) {
+ return valueHolder.get();
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/FreemarkerRenderer.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/FreemarkerRenderer.java
new file mode 100644
index 0000000..e18dc1d
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/FreemarkerRenderer.java
@@ -0,0 +1,85 @@
+/*
+ * $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.request.freemarker.render;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.freemarker.FreemarkerRequestException;
+import org.apache.tiles.request.render.CannotRenderException;
+import org.apache.tiles.request.render.Renderer;
+import org.apache.tiles.request.servlet.ExternalWriterHttpServletResponse;
+import org.apache.tiles.request.servlet.ServletRequest;
+
+/**
+ * FreeMarker renderer for rendering FreeMarker templates as Tiles attributes.
+ * It is only usable under a Servlet environment, because it uses
+ * {@link AttributeValueFreemarkerServlet} internally to forward the request.<br/>
+ * To initialize it correctly, call {@link #setParameter(String, String)} for all the
+ * parameters that you want to set, and then call {@link #commit()}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerRenderer implements Renderer {
+
+ /**
+ * The servlet that is used to forward the request to.
+ */
+ private AttributeValueFreemarkerServlet servlet;
+
+ /**
+ * Constructor.
+ *
+ * @param servlet The servlet to use.
+ */
+ public FreemarkerRenderer(AttributeValueFreemarkerServlet servlet) {
+ this.servlet = servlet;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void render(String path, Request request) throws IOException {
+ if (path == null) {
+ throw new CannotRenderException("Cannot dispatch a null path");
+ }
+ ServletRequest servletRequest = org.apache.tiles.request.servlet.ServletUtil.getServletRequest(request);
+ HttpServletRequest httpRequest = servletRequest.getRequest();
+ HttpServletResponse httpResponse = servletRequest.getResponse();
+ servlet.setValue(path);
+ try {
+ servlet.doGet(httpRequest,
+ new ExternalWriterHttpServletResponse(httpResponse,
+ request.getPrintWriter()));
+ } catch (ServletException e) {
+ throw new FreemarkerRequestException("Exception when rendering a FreeMarker attribute", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public boolean isRenderable(String path, Request request) {
+ return path != null && path.startsWith("/") && path.endsWith(".ftl");
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/FreemarkerRendererBuilder.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/FreemarkerRendererBuilder.java
new file mode 100644
index 0000000..dfb743f
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/FreemarkerRendererBuilder.java
@@ -0,0 +1,103 @@
+/*
+ * $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.request.freemarker.render;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.freemarker.FreemarkerRequestException;
+
+/**
+ * Builds instances of {@link FreemarkerRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class FreemarkerRendererBuilder {
+
+ /**
+ * The initialization parameters.
+ */
+ private Map<String, String> params = new HashMap<String, String>();
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * Constructor.
+ */
+ private FreemarkerRendererBuilder() {
+ }
+
+ /**
+ * Creates a new instance of this class.
+ *
+ * @return A new instance of the builder.
+ */
+ public static FreemarkerRendererBuilder createInstance() {
+ return new FreemarkerRendererBuilder();
+ }
+
+ /**
+ * Sets a parameter for the internal servlet.
+ *
+ * @param key The name of the parameter.
+ * @param value The value of the parameter.
+ * @return This object.
+ */
+ public FreemarkerRendererBuilder setParameter(String key, String value) {
+ params.put(key, value);
+ return this;
+ }
+
+ /**
+ * Sets the application context.
+ *
+ * @param applicationContext The application context.
+ * @return This object.
+ */
+ public FreemarkerRendererBuilder setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ return this;
+ }
+
+ /**
+ * Creates a new {@link FreemarkerRenderer} with the given configuration.
+ *
+ * @return A new Freemarker renderer.
+ */
+ public FreemarkerRenderer build() {
+ AttributeValueFreemarkerServlet servlet = new AttributeValueFreemarkerServlet();
+ try {
+ servlet.init(new InitParamsServletConfig(params, applicationContext));
+ return new FreemarkerRenderer(servlet);
+ } catch (ServletException e) {
+ throw new FreemarkerRequestException(
+ "Cannot initialize internal servlet", e);
+ }
+
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/InitParamsServletConfig.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/InitParamsServletConfig.java
new file mode 100644
index 0000000..1599246
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/InitParamsServletConfig.java
@@ -0,0 +1,81 @@
+/*
+ * $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.request.freemarker.render;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+
+/**
+ * Implements {@link ServletConfig} to initialize the internal servlet using parameters
+ * set through {@link FreemarkerRenderer#setParameter(String, String)}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitParamsServletConfig implements ServletConfig {
+
+ /**
+ * The initialization parameters.
+ */
+ private Map<String, String> params = new HashMap<String, String>();
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * Constructor.
+ *
+ * @param params Configuration parameters.
+ * @param applicationContext The application context.
+ */
+ public InitParamsServletConfig(Map<String, String> params, ApplicationContext applicationContext) {
+ this.params = params;
+ this.applicationContext = applicationContext;
+ }
+
+ /** {@inheritDoc} */
+ public String getInitParameter(String name) {
+ return params.get(name);
+ }
+
+ /** {@inheritDoc} */
+ public Enumeration<String> getInitParameterNames() {
+ return Collections.enumeration(params.keySet());
+ }
+
+ /** {@inheritDoc} */
+ public ServletContext getServletContext() {
+ return org.apache.tiles.request.servlet.ServletUtil.getServletContext(applicationContext);
+ }
+
+ /** {@inheritDoc} */
+ public String getServletName() {
+ return "FreeMarker Attribute Renderer";
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/package-info.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/package-info.java
new file mode 100644
index 0000000..925f6a2
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/render/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Rendering of Freemarker templates.
+ */
+package org.apache.tiles.request.freemarker.render;
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java
new file mode 100644
index 0000000..36cfc0c
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableFactory.java
@@ -0,0 +1,38 @@
+/*
+ * $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.request.freemarker.servlet;
+
+import freemarker.template.TemplateModel;
+
+/**
+ * It is an object that can create a shared variable, as a template model.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface SharedVariableFactory {
+
+ /**
+ * Creates a new shared variable.
+ *
+ * @return The shared variable.
+ */
+ TemplateModel create();
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableLoaderFreemarkerServlet.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableLoaderFreemarkerServlet.java
new file mode 100644
index 0000000..0401d43
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/SharedVariableLoaderFreemarkerServlet.java
@@ -0,0 +1,215 @@
+/*
+ * $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.request.freemarker.servlet;
+
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.tiles.request.reflect.ClassUtil;
+
+import freemarker.cache.TemplateLoader;
+import freemarker.ext.servlet.FreemarkerServlet;
+import freemarker.template.Configuration;
+
+/**
+ * Extends FreemarkerServlet to load Tiles directives as a shared variable.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SharedVariableLoaderFreemarkerServlet extends FreemarkerServlet {
+
+ /**
+ * The serial UID.
+ */
+ private static final long serialVersionUID = 4301098067909854507L;
+
+ /**
+ * The init parameter under which the factories will be put. The value of the parameter
+ * must be a semicolon (;) separated list of couples, each member of the couple must
+ * be separated by commas (,).
+ */
+ public static final String CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM =
+ "org.apache.tiles.request.freemarker.CUSTOM_SHARED_VARIABLE_FACTORIES";
+
+ /**
+ * Maps a name of a shared variable to its factory.
+ */
+ private Map<String, SharedVariableFactory> name2variableFactory =
+ new LinkedHashMap<String, SharedVariableFactory>();
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ String param = config.getInitParameter(CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM);
+ if (param != null) {
+ String[] couples = param.split("\\s*;\\s*");
+ for (int i = 0; i < couples.length; i++) {
+ String[] couple = couples[i].split("\\s*,\\s*");
+ if (couple == null || couple.length != 2) {
+ throw new ServletException(
+ "Cannot parse custom shared variable partial init param: '"
+ + couples[i] + "'");
+ }
+ name2variableFactory.put(couple[0],
+ (SharedVariableFactory) ClassUtil.instantiate(couple[1]));
+ }
+ }
+ super.init(new ExcludingParameterServletConfig(config));
+ }
+
+ /**
+ * Adds anew shared variable factory in a manual way.
+ *
+ * @param variableName The name of the shared variable.
+ * @param factory The shared variable factory.
+ */
+ public void addSharedVariableFactory(String variableName, SharedVariableFactory factory) {
+ name2variableFactory.put(variableName, factory);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected Configuration createConfiguration() {
+ Configuration configuration = super.createConfiguration();
+
+ for (Map.Entry<String, SharedVariableFactory> entry : name2variableFactory.entrySet()) {
+ configuration.setSharedVariable(entry.getKey(), entry.getValue().create());
+ }
+ return configuration;
+ }
+
+ /** {@inheritDoc} */
+
+ @Override
+ protected TemplateLoader createTemplateLoader(String templatePath) {
+ return new WebappClassTemplateLoader(getServletContext());
+ }
+
+ /**
+ * Servlet configuration that excludes some parameters. It is useful to adapt to
+ * FreemarkerServlet behaviour, because it gets angry if it sees some extra
+ * parameters that it does not recognize.
+ */
+ private class ExcludingParameterServletConfig implements ServletConfig {
+
+ /**
+ * The servlet configuration.
+ */
+ private ServletConfig config;
+
+ /**
+ * Constructor.
+ *
+ * @param config The servlet configuration.
+ */
+ public ExcludingParameterServletConfig(ServletConfig config) {
+ this.config = config;
+ }
+
+ @Override
+ public String getServletName() {
+ return config.getServletName();
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return config.getServletContext();
+ }
+
+ @Override
+ public String getInitParameter(String name) {
+ if (CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM.equals(name)) {
+ return null;
+ }
+ return config.getInitParameter(name);
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Enumeration getInitParameterNames() {
+ return new SkippingEnumeration(config.getInitParameterNames());
+ }
+
+ }
+
+ /**
+ * An enumeration that skip just
+ * {@link SharedVariableLoaderFreemarkerServlet#CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM},
+ * again not to let the FreemarkerServlet be angry about it.
+ */
+ private static class SkippingEnumeration implements Enumeration<String> {
+
+ /**
+ * The original enumeration.
+ */
+ private Enumeration<String> enumeration;
+
+ /**
+ * The next element.
+ */
+ private String next = null;
+
+ /**
+ * Constructor.
+ *
+ * @param enumeration The original enumeration.
+ */
+ public SkippingEnumeration(Enumeration<String> enumeration) {
+ this.enumeration = enumeration;
+ updateNextElement();
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return next != null;
+ }
+
+ @Override
+ public String nextElement() {
+ String retValue = next;
+ updateNextElement();
+ return retValue;
+ }
+
+ /**
+ * Updates the next element that will be passed.
+ */
+ private void updateNextElement() {
+ String value = null;
+ boolean done = false;
+ while (this.enumeration.hasMoreElements() && !done) {
+ value = this.enumeration.nextElement();
+ if (value.equals(CUSTOM_SHARED_VARIABLE_FACTORIES_INIT_PARAM)) {
+ value = null;
+ } else {
+ done = true;
+ }
+ }
+ next = value;
+ }
+
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java
new file mode 100644
index 0000000..28ed069
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/WebappClassTemplateLoader.java
@@ -0,0 +1,86 @@
+/*
+ * $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.request.freemarker.servlet;
+
+import java.io.IOException;
+import java.io.Reader;
+
+import javax.servlet.ServletContext;
+
+import freemarker.cache.ClassTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.cache.WebappTemplateLoader;
+
+/**
+ * Delegates loading templates using a {@link WebappTemplateLoader} and, if not
+ * found, a {@link ClassTemplateLoader}. The resources are loaded from the
+ * webapp root and from the classpath root.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WebappClassTemplateLoader implements TemplateLoader {
+
+ /**
+ * The webapp template loader.
+ */
+ private WebappTemplateLoader webappTemplateLoader;
+
+ /**
+ * The webapp template loader.
+ */
+ private ClassTemplateLoader classTemplateLoader;
+
+ /**
+ * Constructor.
+ *
+ * @param servletContext The servlet context.
+ */
+ public WebappClassTemplateLoader(ServletContext servletContext) {
+ webappTemplateLoader = new WebappTemplateLoader(servletContext);
+ classTemplateLoader = new ClassTemplateLoader(getClass(), "/");
+ }
+
+ /** {@inheritDoc} */
+ public Object findTemplateSource(String name) throws IOException {
+ Object retValue = webappTemplateLoader.findTemplateSource(name);
+ if (retValue == null) {
+ retValue = classTemplateLoader.findTemplateSource(name);
+ }
+ return retValue;
+ }
+
+ /** {@inheritDoc} */
+ public void closeTemplateSource(Object templateSource) throws IOException {
+ webappTemplateLoader.closeTemplateSource(templateSource);
+ }
+
+ /** {@inheritDoc} */
+ public long getLastModified(Object templateSource) {
+ return webappTemplateLoader.getLastModified(templateSource);
+ }
+
+ /** {@inheritDoc} */
+ public Reader getReader(Object templateSource, String encoding)
+ throws IOException {
+ return webappTemplateLoader.getReader(templateSource, encoding);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java
new file mode 100644
index 0000000..c93d7b0
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/main/java/org/apache/tiles/request/freemarker/servlet/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Servlets for easy addition of shared variables.
+ */
+package org.apache.tiles.request.freemarker.servlet;
diff --git a/tiles-request/tiles-request-freemarker/src/site/site.xml b/tiles-request/tiles-request-freemarker/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/EnvironmentScopeMapTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/EnvironmentScopeMapTest.java
new file mode 100644
index 0000000..835768b
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/EnvironmentScopeMapTest.java
@@ -0,0 +1,99 @@
+/*
+ * $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.request.freemarker;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Set;
+
+import org.junit.Test;
+
+import freemarker.core.Environment;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateHashModelEx;
+import freemarker.template.TemplateModelException;
+
+/**
+ * Tests {@link EnvironmentScopeMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class EnvironmentScopeMapTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.freemarker.EnvironmentScopeMap#keySet()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testKeySet() {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ Set<String> names = createMock(Set.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(template.getConfiguration()).andReturn(configuration);
+ expect(configuration.getSharedVariableNames()).andReturn(names);
+
+ replay(template, model, configuration, names);
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeMap map = new EnvironmentScopeMap(env);
+ assertEquals(names, map.keySet());
+ verify(template, model, configuration, names);
+ }
+
+
+ /**
+ * Test method for {@link org.apache.tiles.request.freemarker.EnvironmentScopeMap#keySet()}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = FreemarkerRequestException.class)
+ public void testKeySetException() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModelEx model = createMock(TemplateHashModelEx.class);
+ Configuration configuration = createMock(Configuration.class);
+ Set<String> names = createMock(Set.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(model.keys()).andThrow(new TemplateModelException());
+ expect(template.getConfiguration()).andReturn(configuration);
+ expect(configuration.getSharedVariableNames()).andReturn(names);
+
+ try {
+ replay(template, model, configuration, names);
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeMap map = new EnvironmentScopeMap(env);
+ map.keySet();
+ } finally {
+ verify(template, model, configuration, names);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestExceptionTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestExceptionTest.java
new file mode 100644
index 0000000..732d339
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request.freemarker;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link FreemarkerRequestException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerRequestExceptionTest {
+
+ /**
+ * Test method for {@link FreemarkerRequestException#FreemarkerRequestException()}.
+ */
+ @Test
+ public void testFreemarkerRequestException() {
+ FreemarkerRequestException exception = new FreemarkerRequestException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestException#FreemarkerRequestException(java.lang.String)}.
+ */
+ @Test
+ public void testFreemarkerRequestExceptionString() {
+ FreemarkerRequestException exception = new FreemarkerRequestException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestException#FreemarkerRequestException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testFreemarkerRequestExceptionThrowable() {
+ Throwable cause = new Throwable();
+ FreemarkerRequestException exception = new FreemarkerRequestException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestException#FreemarkerRequestException(String, Throwable)}.
+ */
+ @Test
+ public void testFreemarkerRequestExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ FreemarkerRequestException exception = new FreemarkerRequestException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestTest.java
new file mode 100644
index 0000000..7a0de89
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestTest.java
@@ -0,0 +1,261 @@
+/*
+ * $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.request.freemarker;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.DispatchRequest;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.junit.Before;
+import org.junit.Test;
+
+import freemarker.core.Environment;
+import freemarker.ext.servlet.HttpRequestHashModel;
+import freemarker.template.ObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateModelException;
+
+/**
+ * Tests {@link FreemarkerRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerRequestTest {
+
+ /**
+ * The reuqest context to test.
+ */
+ private FreemarkerRequest context;
+
+ /**
+ * A string writer.
+ */
+ private StringWriter writer;
+
+ /**
+ * The FreeMarker environment.
+ */
+ private Environment env;
+
+ /**
+ * The locale object.
+ */
+ private Locale locale;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ writer = new StringWriter();
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ replay(template, model);
+ env = new Environment(template, model, writer);
+ locale = Locale.ITALY;
+ env.setLocale(locale);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#createServletFreemarkerRequest(ApplicationContext, Environment)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testCreateServletFreemarkerRequest() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ PrintWriter writer = new PrintWriter(new StringWriter());
+ HttpServletRequest httpRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse httpResponse = createMock(HttpServletResponse.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+
+ replay(httpRequest, httpResponse, objectWrapper);
+ HttpRequestHashModel requestHashModel = new HttpRequestHashModel(httpRequest, httpResponse, objectWrapper);
+ expect(model.get("Request")).andReturn(requestHashModel);
+
+ replay(template, model, applicationContext);
+ Environment env = new Environment(template, model, writer);
+ Locale locale = Locale.ITALY;
+ env.setLocale(locale);
+
+ FreemarkerRequest request = FreemarkerRequest.createServletFreemarkerRequest(applicationContext, env);
+ ServletRequest servletRequest = (ServletRequest) request.getWrappedRequest();
+ assertEquals(httpRequest, servletRequest.getRequest());
+ assertEquals(httpResponse, servletRequest.getResponse());
+ verify(template, model, httpRequest, httpResponse, objectWrapper, applicationContext);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#dispatch(String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testDispatch() throws IOException {
+ String path = "this way";
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ Map<String, Object> requestScope = new HashMap<String, Object>();
+
+ enclosedRequest.include(path);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ expect(enclosedRequest.getContext("request")).andReturn(requestScope);
+ replay(enclosedRequest, applicationContext);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ context.dispatch(path);
+ verify(enclosedRequest, applicationContext);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getPageScope()}.
+ */
+ @Test
+ public void testGetPageScope() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertTrue(context.getPageScope() instanceof EnvironmentScopeMap);
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getNativeScopes()}.
+ */
+ @Test
+ public void testGetAvailableScopes() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertArrayEquals(new String[] { "parent", "page" }, //
+ context.getAvailableScopes().toArray());
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getRequestLocale()}.
+ */
+ @Test
+ public void testGetRequestLocale() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertEquals(locale, context.getRequestLocale());
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getRequest()}.
+ */
+ @Test
+ public void testGetRequest() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertEquals(env, context.getEnvironment());
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getResponse()}.
+ */
+ @Test
+ public void testGetResponse() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertEquals(env, context.getEnvironment());
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getPrintWriter()}.
+ */
+ @Test
+ public void testGetPrintWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertEquals(env, context.getEnvironment());
+ assertNotNull(context.getPrintWriter());
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getPrintWriter()}.
+ */
+ @Test
+ public void testGetPrintWriterPrintWriter() {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ PrintWriter writer = new PrintWriter(new StringWriter());
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ replay(template, model);
+ Environment env = new Environment(template, model, writer);
+ Locale locale = Locale.ITALY;
+ env.setLocale(locale);
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertSame(writer, context.getPrintWriter());
+ verify(enclosedRequest, template, model);
+ }
+
+
+ /**
+ * Tests {@link FreemarkerRequest#getWriter()}.
+ */
+ @Test
+ public void testGetWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new FreemarkerRequest(enclosedRequest, env);
+ assertEquals(env, context.getEnvironment());
+ assertNotNull(context.getWriter());
+ verify(enclosedRequest);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtilTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtilTest.java
new file mode 100644
index 0000000..4d5b48f
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/FreemarkerRequestUtilTest.java
@@ -0,0 +1,209 @@
+/*
+ * $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.request.freemarker;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Locale;
+
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.junit.Before;
+import org.junit.Test;
+
+import freemarker.core.Environment;
+import freemarker.ext.servlet.HttpRequestHashModel;
+import freemarker.ext.servlet.ServletContextHashModel;
+import freemarker.template.ObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateModelException;
+
+/**
+ * Tests {@link FreemarkerRequestUtil}.
+ *
+ */
+public class FreemarkerRequestUtilTest {
+
+ /**
+ * A string writer.
+ */
+ private StringWriter writer;
+
+ /**
+ * The FreeMarker environment.
+ */
+ private Environment env;
+
+ /**
+ * The locale object.
+ */
+ private Locale locale;
+
+ /**
+ * The template.
+ */
+ private Template template;
+
+ /**
+ * The template model.
+ */
+ private TemplateHashModel model;
+
+ /**
+ * Sets up the model.
+ */
+ @Before
+ public void setUp() {
+ template = createMock(Template.class);
+ model = createMock(TemplateHashModel.class);
+ writer = new StringWriter();
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestUtil#getRequestHashModel(freemarker.core.Environment)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetRequestHashModel() throws TemplateModelException {
+ HttpServletRequest request = createMock(HttpServletRequest.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ HttpRequestHashModel requestModel = new HttpRequestHashModel(request, objectWrapper);
+
+ expect(model.get("Request")).andReturn(requestModel);
+
+ replay(template, model, request, objectWrapper);
+ env = new Environment(template, model, writer);
+ locale = Locale.ITALY;
+ env.setLocale(locale);
+ assertEquals(requestModel, FreemarkerRequestUtil.getRequestHashModel(env));
+ verify(template, model, request, objectWrapper);
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestUtil#getRequestHashModel(freemarker.core.Environment)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test(expected = NotAvailableFreemarkerServletException.class)
+ public void testGetRequestHashModelException() throws TemplateModelException {
+ HttpServletRequest request = createMock(HttpServletRequest.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+
+ expect(model.get("Request")).andThrow(new TemplateModelException());
+
+ replay(template, model, request, objectWrapper);
+ try {
+ env = new Environment(template, model, writer);
+ locale = Locale.ITALY;
+ env.setLocale(locale);
+ FreemarkerRequestUtil.getRequestHashModel(env);
+ } finally {
+ verify(template, model, request, objectWrapper);
+ }
+ }
+
+
+ /**
+ * Test method for {@link FreemarkerRequestUtil
+ * #getServletContextHashModel(freemarker.core.Environment)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetServletContextHashModel() throws TemplateModelException {
+ GenericServlet servlet = createMock(GenericServlet.class);
+ ServletContext servletContext = createMock(ServletContext.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ expect(servlet.getServletContext()).andReturn(servletContext);
+ replay(servlet, objectWrapper);
+ ServletContextHashModel servletContextModel = new ServletContextHashModel(servlet, objectWrapper);
+
+ expect(model.get("Application")).andReturn(servletContextModel);
+
+ replay(template, model, servletContext);
+ env = new Environment(template, model, writer);
+ locale = Locale.ITALY;
+ env.setLocale(locale);
+ assertEquals(servletContextModel, FreemarkerRequestUtil.getServletContextHashModel(env));
+ verify(template, model, servlet, servletContext, objectWrapper);
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestUtil
+ * #getServletContextHashModel(freemarker.core.Environment)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test(expected = NotAvailableFreemarkerServletException.class)
+ public void testGetServletContextHashModelException() throws TemplateModelException {
+ GenericServlet servlet = createMock(GenericServlet.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ replay(servlet, objectWrapper);
+
+ expect(model.get("Application")).andThrow(new TemplateModelException());
+
+ replay(template, model);
+ try {
+ env = new Environment(template, model, writer);
+ locale = Locale.ITALY;
+ env.setLocale(locale);
+ FreemarkerRequestUtil.getServletContextHashModel(env);
+ } finally {
+ verify(template, model, servlet, objectWrapper);
+ }
+ }
+
+ /**
+ * Test method for {@link FreemarkerRequestUtil
+ * #getApplicationContext(Environment)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetApplicationContext() throws TemplateModelException {
+ GenericServlet servlet = createMock(GenericServlet.class);
+ ServletContext servletContext = createMock(ServletContext.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ expect(servlet.getServletContext()).andReturn(servletContext).times(2);
+ expect(servletContext.getAttribute(ApplicationAccess
+ .APPLICATION_CONTEXT_ATTRIBUTE)).andReturn(applicationContext);
+
+ replay(servlet, objectWrapper);
+ ServletContextHashModel servletContextModel = new ServletContextHashModel(servlet, objectWrapper);
+
+ expect(model.get("Application")).andReturn(servletContextModel);
+
+ replay(template, model, servletContext);
+ env = new Environment(template, model, writer);
+ locale = Locale.ITALY;
+ env.setLocale(locale);
+ assertEquals(applicationContext, FreemarkerRequestUtil.getApplicationContext(env));
+ verify(template, model, servlet, servletContext, objectWrapper);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletExceptionTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletExceptionTest.java
new file mode 100644
index 0000000..92d32c3
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/NotAvailableFreemarkerServletExceptionTest.java
@@ -0,0 +1,79 @@
+/*
+ * $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.request.freemarker;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link NotAvailableFreemarkerServletException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotAvailableFreemarkerServletExceptionTest {
+
+ /**
+ * Test method for {@link NotAvailableFreemarkerServletException#NotAvailableFreemarkerServletException()}.
+ */
+ @Test
+ public void testNotAvailableFreemarkerServletException() {
+ NotAvailableFreemarkerServletException exception = new NotAvailableFreemarkerServletException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAvailableFreemarkerServletException#NotAvailableFreemarkerServletException(String)}.
+ */
+ @Test
+ public void testNotAvailableFreemarkerServletExceptionString() {
+ NotAvailableFreemarkerServletException exception = new NotAvailableFreemarkerServletException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAvailableFreemarkerServletException#NotAvailableFreemarkerServletException(Throwable)}.
+ */
+ @Test
+ public void testNotAvailableFreemarkerServletExceptionThrowable() {
+ Throwable cause = new Throwable();
+ NotAvailableFreemarkerServletException exception = new NotAvailableFreemarkerServletException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for
+ * {@link NotAvailableFreemarkerServletException#NotAvailableFreemarkerServletException(String, Throwable)}.
+ */
+ @Test
+ public void testNotAvailableFreemarkerServletExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ NotAvailableFreemarkerServletException exception =
+ new NotAvailableFreemarkerServletException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagExceptionTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagExceptionTest.java
new file mode 100644
index 0000000..aac061a
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagExceptionTest.java
@@ -0,0 +1,78 @@
+/*
+ * $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.request.freemarker.autotag;
+
+import static org.junit.Assert.*;
+
+import org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagException;
+import org.junit.Test;
+
+/**
+ * Tests {@link FreemarkerAutotagException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerAutotagExceptionTest {
+
+ /**
+ * Test method for {@link FreemarkerAutotagException#FreemarkerAutotagException()}.
+ */
+ @Test
+ public void testFreemarkerAutotagException() {
+ FreemarkerAutotagException exception = new FreemarkerAutotagException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link FreemarkerAutotagException#FreemarkerAutotagException(java.lang.String)}.
+ */
+ @Test
+ public void testFreemarkerAutotagExceptionString() {
+ FreemarkerAutotagException exception = new FreemarkerAutotagException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link FreemarkerAutotagException#FreemarkerAutotagException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testFreemarkerAutotagExceptionThrowable() {
+ Throwable cause = new Throwable();
+ FreemarkerAutotagException exception = new FreemarkerAutotagException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link FreemarkerAutotagException#FreemarkerAutotagException(String, Throwable)}.
+ */
+ @Test
+ public void testFreemarkerAutotagExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ FreemarkerAutotagException exception = new FreemarkerAutotagException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntimeTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntimeTest.java
new file mode 100644
index 0000000..9a93b21
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerAutotagRuntimeTest.java
@@ -0,0 +1,160 @@
+/*
+ * $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.request.freemarker.autotag;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.freemarker.FreemarkerRequest;
+import org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagRuntime;
+import org.apache.tiles.request.freemarker.autotag.FreemarkerModelBody;
+import org.junit.Test;
+import freemarker.core.Environment;
+import freemarker.core.Macro;
+import freemarker.ext.servlet.FreemarkerServlet;
+import freemarker.ext.servlet.HttpRequestHashModel;
+import freemarker.ext.servlet.ServletContextHashModel;
+import freemarker.template.ObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+/**
+ * Tests {@link FreemarkerAutotagRuntime}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerAutotagRuntimeTest {
+
+ @Test
+ public void testCreateRequest() throws IOException, TemplateModelException{
+ @SuppressWarnings("unchecked")
+ Map<String, TemplateModel> params = createMock(Map.class);
+ Template template = createMock(Template.class);
+ TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
+ Writer out = createMock(Writer.class);
+ TemplateDirectiveBody body = createMock(TemplateDirectiveBody.class);
+ GenericServlet servlet = createMock(GenericServlet.class);
+ ObjectWrapper wrapper = createMock(ObjectWrapper.class);
+ ServletContext servletContext = createMock(ServletContext.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ HttpServletRequest httpServletRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse httpServletResponse = createMock(HttpServletResponse.class);
+
+ expect(template.getMacros()).andReturn(new HashMap<String, Macro>());
+ expect(servlet.getServletContext()).andReturn(servletContext)
+ .anyTimes();
+ expect(
+ servletContext
+ .getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE))
+ .andReturn(applicationContext);
+
+ replay(servlet, wrapper, servletContext, applicationContext,
+ httpServletRequest, httpServletResponse);
+ ServletContextHashModel servletContextHashModel = new ServletContextHashModel(
+ servlet, wrapper);
+ HttpRequestHashModel httpRequestHashModel = new HttpRequestHashModel(
+ httpServletRequest, httpServletResponse, wrapper);
+
+ expect(rootDataModel.get(FreemarkerServlet.KEY_APPLICATION)).andReturn(
+ servletContextHashModel);
+ expect(rootDataModel.get(FreemarkerServlet.KEY_REQUEST)).andReturn(
+ httpRequestHashModel);
+
+ replay(template, rootDataModel, out);
+ Environment env = new Environment(template, rootDataModel, out);
+
+ replay(params, body);
+ FreemarkerAutotagRuntime runtime = new FreemarkerAutotagRuntime();
+
+ runtime.execute(env, params, new TemplateModel[0], body);
+ Request request = runtime.createRequest();
+ assertTrue(request instanceof FreemarkerRequest);
+ verify(servlet, wrapper, servletContext, applicationContext,
+ httpServletRequest, httpServletResponse,
+ template, rootDataModel, out,
+ params, body);
+ }
+
+ @Test
+ public void testCreateModelBody() {
+ Template template = createMock(Template.class);
+ TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
+ Writer out = createMock(Writer.class);
+ expect(template.getMacros()).andReturn(new HashMap<String, Macro>());
+ replay(template, rootDataModel, out);
+ Environment env = new Environment(template, rootDataModel, out);
+ @SuppressWarnings("unchecked")
+ Map<String, TemplateModel> params = createMock(Map.class);
+ TemplateDirectiveBody body = createMock(TemplateDirectiveBody.class);
+ replay(params, body);
+ FreemarkerAutotagRuntime runtime = new FreemarkerAutotagRuntime();
+ runtime.execute(env, params, new TemplateModel[0], body);
+ ModelBody modelBody = runtime.createModelBody();
+ assertTrue(modelBody instanceof FreemarkerModelBody);
+ verify(template, rootDataModel, out, params, body);
+ }
+
+ @Test
+ public void testGetParameter() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
+ Writer out = createMock(Writer.class);
+ expect(template.getMacros()).andReturn(new HashMap<String, Macro>());
+ replay(template, rootDataModel, out);
+ Environment env = new Environment(template, rootDataModel, out);
+ TemplateNumberModel model = createMock(TemplateNumberModel.class);
+ expect(model.getAsNumber()).andReturn(new Integer(42)).anyTimes();
+ @SuppressWarnings("unchecked")
+ Map<String, TemplateModel> params = createMock(Map.class);
+ TemplateDirectiveBody body = createMock(TemplateDirectiveBody.class);
+ expect(params.get(eq("notnullParam"))).andReturn(model).anyTimes();
+ expect(params.get(eq("nullParam"))).andReturn(null).anyTimes();
+ replay(model, params, body);
+ FreemarkerAutotagRuntime runtime = new FreemarkerAutotagRuntime();
+ runtime.execute(env, params, new TemplateModel[0], body);
+ Object notnullParam = runtime.getParameter("notnullParam", null);
+ Object nullParam = runtime.getParameter("nullParam", null);
+ Object notnullParamDefault = runtime.getParameter("notnullParam", new Integer(24));
+ Object nullParamDefault = runtime.getParameter("nullParam", new Integer(24));
+ assertEquals(42, notnullParam);
+ assertEquals(null, nullParam);
+ assertEquals(42, notnullParamDefault);
+ assertEquals(24, nullParamDefault);
+ verify(template, rootDataModel, out, model, params, body);
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBodyTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBodyTest.java
new file mode 100644
index 0000000..30233d5
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerModelBodyTest.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.request.freemarker.autotag;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.tiles.request.freemarker.autotag.FreemarkerModelBody;
+import org.junit.Test;
+
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateException;
+
+/**
+ * Tests {@link FreemarkerModelBody}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerModelBodyTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.freemarker.autotag.FreemarkerModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ * @throws TemplateException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateWriter() throws TemplateException, IOException {
+ TemplateDirectiveBody body = createMock(TemplateDirectiveBody.class);
+ Writer writer = createMock(Writer.class);
+
+ body.render(writer);
+
+ replay(body, writer);
+ FreemarkerModelBody modelBody = new FreemarkerModelBody(null, body);
+ modelBody.evaluate(writer);
+ verify(body, writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.freemarker.autotag.FreemarkerModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ * @throws TemplateException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateWriterNull() throws TemplateException, IOException {
+ Writer writer = createMock(Writer.class);
+
+ replay(writer);
+ FreemarkerModelBody modelBody = new FreemarkerModelBody(null, null);
+ modelBody.evaluate(writer);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.freemarker.autotag.FreemarkerModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ * @throws TemplateException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testEvaluateWriterException() throws TemplateException, IOException {
+ TemplateDirectiveBody body = createMock(TemplateDirectiveBody.class);
+ Writer writer = createMock(Writer.class);
+
+ body.render(writer);
+ expectLastCall().andThrow(new TemplateException(null));
+
+ replay(body, writer);
+ try {
+ FreemarkerModelBody modelBody = new FreemarkerModelBody(null, body);
+ modelBody.evaluate(writer);
+ } finally {
+ verify(body, writer);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtilTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtilTest.java
new file mode 100644
index 0000000..1841b23
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/autotag/FreemarkerUtilTest.java
@@ -0,0 +1,113 @@
+/*
+ * $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.request.freemarker.autotag;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.Writer;
+import java.util.HashMap;
+
+import org.apache.tiles.request.freemarker.autotag.FreemarkerAutotagException;
+import org.apache.tiles.request.freemarker.autotag.FreemarkerUtil;
+import org.junit.Test;
+
+import freemarker.core.Environment;
+import freemarker.core.Macro;
+import freemarker.template.Template;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+
+/**
+ * Tests {@link FreemarkerUtil}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerUtilTest {
+
+ /**
+ * Test method for {@link FreemarkerUtil#getAsObject(TemplateModel, Object)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetAsObject() throws TemplateModelException {
+ TemplateNumberModel model = createMock(TemplateNumberModel.class);
+ Template template = createMock(Template.class);
+ TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
+ Writer out = createMock(Writer.class);
+
+ expect(model.getAsNumber()).andReturn(new Integer(42));
+ expect(template.getMacros()).andReturn(new HashMap<String, Macro>());
+
+ replay(template, rootDataModel, out);
+ new Environment(template, rootDataModel, out);
+
+ replay(model);
+ assertEquals(new Integer(42), FreemarkerUtil.getAsObject(model, new Integer(1)));
+ verify(template, rootDataModel, out, model);
+ }
+
+ /**
+ * Test method for {@link FreemarkerUtil#getAsObject(TemplateModel, Object)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetAsObjectDefault() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
+ Writer out = createMock(Writer.class);
+
+ expect(template.getMacros()).andReturn(new HashMap<String, Macro>());
+
+ replay(template, rootDataModel, out);
+ new Environment(template, rootDataModel, out);
+
+ assertEquals(new Integer(1), FreemarkerUtil.getAsObject(null, new Integer(1)));
+ verify(template, rootDataModel, out);
+ }
+
+ /**
+ * Test method for {@link FreemarkerUtil#getAsObject(TemplateModel, Object)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test(expected = FreemarkerAutotagException.class)
+ public void testGetAsObjectException() throws TemplateModelException {
+ TemplateNumberModel model = createMock(TemplateNumberModel.class);
+ Template template = createMock(Template.class);
+ TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
+ Writer out = createMock(Writer.class);
+
+ expect(model.getAsNumber()).andThrow(new TemplateModelException());
+ expect(template.getMacros()).andReturn(new HashMap<String, Macro>());
+
+ replay(template, rootDataModel, out);
+ new Environment(template, rootDataModel, out);
+
+ replay(model);
+ try {
+ assertEquals(new Integer(42), FreemarkerUtil.getAsObject(model, new Integer(1)));
+ } finally {
+ verify(template, rootDataModel, out, model);
+ }
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractorTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractorTest.java
new file mode 100644
index 0000000..6a85415
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/extractor/EnvironmentScopeExtractorTest.java
@@ -0,0 +1,265 @@
+/*
+ * $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.request.freemarker.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.tiles.request.freemarker.FreemarkerRequestException;
+import org.junit.Test;
+
+import freemarker.core.Environment;
+import freemarker.template.Configuration;
+import freemarker.template.ObjectWrapper;
+import freemarker.template.Template;
+import freemarker.template.TemplateHashModel;
+import freemarker.template.TemplateHashModelEx;
+import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateScalarModel;
+
+/**
+ * Tests {@link EnvironmentScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class EnvironmentScopeExtractorTest {
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#removeValue(java.lang.String)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testRemoveValue() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateModel valueModel = createMock(TemplateModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(model.get("key")).andReturn(null);
+ expect(template.getConfiguration()).andReturn(configuration);
+ expect(configuration.getSharedVariable("key")).andReturn(null);
+
+ replay(template, model, valueModel, configuration);
+ Environment env = new Environment(template, model, writer);
+ env.setVariable("key", valueModel);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ extractor.removeValue("key");
+ assertNull(env.getVariable("key"));
+ verify(template, model, valueModel, configuration);
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#getKeys()}.
+ */
+ @Test
+ public void testGetKeys() {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateModel valueModel = createMock(TemplateModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ Set<String> names = new HashSet<String>();
+ names.add("testGetKeys");
+
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(template.getConfiguration()).andReturn(configuration);
+ expect(configuration.getSharedVariableNames()).andReturn(names);
+
+ replay(template, model, valueModel, configuration);
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ Enumeration<String> keys = extractor.getKeys();
+ assertEquals("testGetKeys", keys.nextElement());
+ assertFalse(keys.hasMoreElements());
+ verify(template, model, valueModel, configuration);
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#getKeys()}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @SuppressWarnings("unchecked")
+ @Test(expected = FreemarkerRequestException.class)
+ public void testGetKeysException() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModelEx model = createMock(TemplateHashModelEx.class);
+ TemplateModel valueModel = createMock(TemplateModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ Set<String> names = createMock(Set.class);
+ Iterator<String> namesIt = createMock(Iterator.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(model.keys()).andThrow(new TemplateModelException());
+ expect(template.getConfiguration()).andReturn(configuration);
+ expect(configuration.getSharedVariableNames()).andReturn(names);
+
+ replay(template, model, valueModel, configuration, names, namesIt);
+ try {
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ extractor.getKeys();
+ } finally {
+ verify(template, model, valueModel, configuration, names, namesIt);
+ }
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#getValue(java.lang.String)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetValue() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateScalarModel valueModel = createMock(TemplateScalarModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(valueModel.getAsString()).andReturn("value");
+
+ replay(template, model, valueModel, configuration, objectWrapper);
+ Environment env = new Environment(template, model, writer);
+ env.setVariable("key", valueModel);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ assertEquals("value", extractor.getValue("key"));
+ verify(template, model, valueModel, configuration, objectWrapper);
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#getValue(java.lang.String)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testGetValueNull() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateScalarModel valueModel = createMock(TemplateScalarModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(model.get("key")).andReturn(null);
+ expect(template.getConfiguration()).andReturn(configuration);
+ expect(configuration.getSharedVariable("key")).andReturn(null);
+
+ replay(template, model, valueModel, configuration, objectWrapper);
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ assertNull(extractor.getValue("key"));
+ verify(template, model, valueModel, configuration, objectWrapper);
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#getValue(java.lang.String)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test(expected = FreemarkerRequestException.class)
+ public void testGetValueException() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateScalarModel valueModel = createMock(TemplateScalarModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(model.get("key")).andThrow(new TemplateModelException());
+
+ replay(template, model, valueModel, configuration, objectWrapper);
+ try {
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ extractor.getValue("key");
+ } finally {
+ verify(template, model, valueModel, configuration, objectWrapper);
+ }
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#setValue(java.lang.String, java.lang.Object)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test
+ public void testSetValue() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateModel valueModel = createMock(TemplateModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(template.getObjectWrapper()).andReturn(objectWrapper);
+ expect(objectWrapper.wrap("value")).andReturn(valueModel);
+
+ replay(template, model, valueModel, configuration, objectWrapper);
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ extractor.setValue("key", "value");
+ assertEquals(valueModel, env.getVariable("key"));
+ verify(template, model, valueModel, configuration, objectWrapper);
+ }
+
+ /**
+ * Test method for {@link EnvironmentScopeExtractor#setValue(java.lang.String, java.lang.Object)}.
+ * @throws TemplateModelException If something goes wrong.
+ */
+ @Test(expected = FreemarkerRequestException.class)
+ public void testSetValueException() throws TemplateModelException {
+ Template template = createMock(Template.class);
+ TemplateHashModel model = createMock(TemplateHashModel.class);
+ TemplateModel valueModel = createMock(TemplateModel.class);
+ Configuration configuration = createMock(Configuration.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+ Writer writer = new StringWriter();
+
+ expect(template.getMacros()).andReturn(new HashMap<Object, Object>());
+ expect(template.getObjectWrapper()).andReturn(objectWrapper);
+ expect(objectWrapper.wrap("value")).andThrow(new TemplateModelException());
+
+ replay(template, model, valueModel, configuration, objectWrapper);
+ try {
+ Environment env = new Environment(template, model, writer);
+ EnvironmentScopeExtractor extractor = new EnvironmentScopeExtractor(env);
+ extractor.setValue("key", "value");
+ assertEquals(valueModel, env.getVariable("key"));
+ } finally {
+ verify(template, model, valueModel, configuration, objectWrapper);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/render/FreemarkerRendererTest.java b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/render/FreemarkerRendererTest.java
new file mode 100644
index 0000000..9b4ee63
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/java/org/apache/tiles/request/freemarker/render/FreemarkerRendererTest.java
@@ -0,0 +1,238 @@
+/*
+ * $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.request.freemarker.render;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.render.CannotRenderException;
+import org.apache.tiles.request.servlet.ServletApplicationContext;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.junit.Before;
+import org.junit.Test;
+
+import freemarker.ext.servlet.HttpRequestHashModel;
+import freemarker.ext.servlet.HttpRequestParametersHashModel;
+import freemarker.ext.servlet.ServletContextHashModel;
+import freemarker.template.ObjectWrapper;
+
+/**
+ * Tests {@link FreemarkerRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class FreemarkerRendererTest {
+
+ /**
+ * The attribute name of the application model.
+ */
+ private static final String ATTR_APPLICATION_MODEL =
+ ".freemarker.Application";
+
+ /**
+ * The attribute name of the JSP taglibs model.
+ */
+ private static final String ATTR_JSP_TAGLIBS_MODEL =
+ ".freemarker.JspTaglibs";
+
+ /**
+ * The attribute name of the request model.
+ */
+ private static final String ATTR_REQUEST_MODEL = ".freemarker.Request";
+
+ /**
+ * The attribute name of the request parameters model.
+ */
+ private static final String ATTR_REQUEST_PARAMETERS_MODEL =
+ ".freemarker.RequestParameters";
+
+ /**
+ * The renderer to test.
+ */
+ private FreemarkerRenderer renderer;
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext servletContext;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ applicationContext = createMock(ServletApplicationContext.class);
+ servletContext = createMock(ServletContext.class);
+
+ expect(applicationContext.getContext()).andReturn(servletContext);
+
+ replay(applicationContext, servletContext);
+ renderer = FreemarkerRendererBuilder.createInstance()
+ .setApplicationContext(applicationContext)
+ .setParameter("TemplatePath", "/")
+ .setParameter("NoCache", "true")
+ .setParameter("ContentType", "text/html")
+ .setParameter("template_update_delay", "0")
+ .setParameter("default_encoding", "ISO-8859-1")
+ .setParameter("number_format", "0.##########").build();
+ }
+
+ /**
+ * Tests {@link FreemarkerRenderer#render(String, org.apache.tiles.request.Request)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test
+ public void testWrite() throws IOException, ServletException {
+ ApplicationContext applicationContext = createMock(ServletApplicationContext.class);
+ ServletContext servletContext = createMock(ServletContext.class);
+ GenericServlet servlet = createMockBuilder(GenericServlet.class).createMock();
+ ServletConfig servletConfig = createMock(ServletConfig.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+
+ expect(servletConfig.getServletContext()).andReturn(servletContext);
+
+ replay(servlet, servletConfig);
+ servlet.init(servletConfig);
+ ServletContextHashModel servletContextHashModel = new ServletContextHashModel(servlet, objectWrapper);
+
+ expect(applicationContext.getContext()).andReturn(servletContext).anyTimes();
+ expect(servletContext.getRealPath(isA(String.class))).andReturn(null).anyTimes();
+ URL resource = getClass().getResource("/test.ftl");
+ expect(servletContext.getResource(isA(String.class))).andReturn(resource).anyTimes();
+ expect(servletContext.getAttribute(ATTR_APPLICATION_MODEL)).andReturn(servletContextHashModel);
+ expect(servletContext.getAttribute(ATTR_JSP_TAGLIBS_MODEL)).andReturn(null);
+
+ replay(applicationContext, servletContext, objectWrapper);
+
+ FreemarkerRenderer renderer = FreemarkerRendererBuilder
+ .createInstance().setApplicationContext(applicationContext)
+ .setParameter("TemplatePath", "/")
+ .setParameter("NoCache", "true")
+ .setParameter("ContentType", "text/html")
+ .setParameter("template_update_delay", "0")
+ .setParameter("default_encoding", "ISO-8859-1")
+ .setParameter("number_format", "0.##########").build();
+
+ ServletRequest request = createMock(ServletRequest.class);
+ HttpServletRequest httpRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(stringWriter);
+ HttpRequestHashModel requestModel = new HttpRequestHashModel(httpRequest, response, objectWrapper);
+ HttpRequestParametersHashModel parametersModel = new HttpRequestParametersHashModel(httpRequest);
+
+ expect(request.getRequest()).andReturn(httpRequest);
+ expect(request.getResponse()).andReturn(response);
+ expect(request.getPrintWriter()).andReturn(printWriter);
+ expect(httpRequest.getSession(false)).andReturn(null);
+ expect(httpRequest.getAttribute(ATTR_REQUEST_MODEL)).andReturn(requestModel);
+ expect(httpRequest.getAttribute(ATTR_REQUEST_PARAMETERS_MODEL)).andReturn(parametersModel);
+ response.setContentType("text/html; charset=ISO-8859-1");
+ response.setHeader(eq("Cache-Control"), isA(String.class));
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader(eq("Expires"), isA(String.class));
+
+ replay(request, httpRequest, response);
+ renderer.render("hello", request);
+ stringWriter.close();
+ assertTrue(stringWriter.toString().startsWith("Hello!"));
+ verify(applicationContext, servletContext, request, httpRequest,
+ response, servlet, servletConfig, objectWrapper);
+ }
+
+ /**
+ * Tests {@link FreemarkerRenderer#render(String, org.apache.tiles.request.Request)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test(expected = CannotRenderException.class)
+ public void testRenderException1() throws IOException, ServletException {
+ ApplicationContext applicationContext = createMock(ServletApplicationContext.class);
+ ServletContext servletContext = createMock(ServletContext.class);
+ GenericServlet servlet = createMockBuilder(GenericServlet.class).createMock();
+ ServletConfig servletConfig = createMock(ServletConfig.class);
+ ObjectWrapper objectWrapper = createMock(ObjectWrapper.class);
+
+ replay(servlet, servletConfig);
+ servlet.init(servletConfig);
+
+ expect(applicationContext.getContext()).andReturn(servletContext).anyTimes();
+ expect(servletContext.getRealPath(isA(String.class))).andReturn(null).anyTimes();
+ URL resource = getClass().getResource("/test.ftl");
+ expect(servletContext.getResource(isA(String.class))).andReturn(resource).anyTimes();
+
+ replay(applicationContext, servletContext, objectWrapper);
+
+ FreemarkerRenderer renderer = FreemarkerRendererBuilder
+ .createInstance().setApplicationContext(applicationContext)
+ .setParameter("TemplatePath", "/")
+ .setParameter("NoCache", "true")
+ .setParameter("ContentType", "text/html")
+ .setParameter("template_update_delay", "0")
+ .setParameter("default_encoding", "ISO-8859-1")
+ .setParameter("number_format", "0.##########").build();
+
+ ServletRequest request = createMock(ServletRequest.class);
+
+ replay(request);
+ try {
+ renderer.render(null, request);
+ } finally {
+ verify(applicationContext, servletContext, request, servlet,
+ servletConfig, objectWrapper);
+ }
+ }
+
+ /**
+ * Test method for
+ * {@link FreemarkerRenderer
+ * #isRenderable(Object, org.apache.tiles.Attribute, org.apache.tiles.context.TilesRequestContext)}
+ * .
+ */
+ @Test
+ public void testIsRenderable() {
+ assertTrue(renderer.isRenderable("/my/template.ftl", null));
+ assertFalse(renderer.isRenderable("my/template.ftl", null));
+ assertFalse(renderer.isRenderable("/my/template.jsp", null));
+ verify(applicationContext, servletContext);
+ }
+
+}
diff --git a/tiles-request/tiles-request-freemarker/src/test/resources/test.ftl b/tiles-request/tiles-request-freemarker/src/test/resources/test.ftl
new file mode 100644
index 0000000..3397cec
--- /dev/null
+++ b/tiles-request/tiles-request-freemarker/src/test/resources/test.ftl
@@ -0,0 +1,25 @@
+<#--
+/*
+ * $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.
+ *
+ */
+-->
+Hello!
+
diff --git a/tiles-request/tiles-request-jsp/pom.xml b/tiles-request/tiles-request-jsp/pom.xml
new file mode 100644
index 0000000..a726060
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-request</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-jsp</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles Request - JSP support</name>
+ <description>JSP implementation of the Tiles Request framework.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet.jsp</groupId>
+ <artifactId>jsp-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shale</groupId>
+ <artifactId>shale-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java
new file mode 100644
index 0000000..9f9ec4f
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspPrintWriterAdapter.java
@@ -0,0 +1,388 @@
+/*
+ * $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.request.jsp;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.jsp.JspWriter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Adapts a {@link JspWriter} to a {@link PrintWriter}, swallowing {@link IOException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspPrintWriterAdapter extends PrintWriter {
+
+ /**
+ * The JSP writer.
+ */
+ private JspWriter writer;
+
+ /**
+ * The logging object.
+ */
+ private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+ /**
+ * Constructor.
+ *
+ * @param writer The JSP writer.
+ */
+ public JspPrintWriterAdapter(JspWriter writer) {
+ super(writer);
+ this.writer = writer;
+ }
+
+ /**
+ * Returns the original JSP writer.
+ *
+ * @return The JSP writer.
+ */
+ public JspWriter getJspWriter() {
+ return writer;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter append(char c) {
+ try {
+ writer.append(c);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter append(CharSequence csq, int start, int end) {
+ try {
+ writer.append(csq, start, end);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter append(CharSequence csq) {
+ try {
+ writer.append(csq);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void close() {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void flush() {
+ try {
+ writer.flush();
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(boolean b) {
+ try {
+ writer.print(b);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(char c) {
+ try {
+ writer.print(c);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(char[] s) {
+ try {
+ writer.print(s);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(double d) {
+ try {
+ writer.print(d);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(float f) {
+ try {
+ writer.print(f);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(int i) {
+ try {
+ writer.print(i);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(long l) {
+ try {
+ writer.print(l);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(Object obj) {
+ try {
+ writer.print(obj);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void print(String s) {
+ try {
+ writer.print(s);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println() {
+ try {
+ writer.println();
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(boolean x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(char x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(char[] x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(double x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(float x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(int x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(long x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(Object x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void println(String x) {
+ try {
+ writer.println(x);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(char[] buf, int off, int len) {
+ try {
+ writer.write(buf, off, len);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(char[] buf) {
+ try {
+ writer.write(buf);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(int c) {
+ try {
+ writer.write(c);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(String s, int off, int len) {
+ try {
+ writer.write(s, off, len);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void write(String s) {
+ try {
+ writer.write(s);
+ } catch (IOException e) {
+ log.error("Error when writing in JspWriter", e);
+ setError();
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspRequest.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspRequest.java
new file mode 100644
index 0000000..ab00ef3
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspRequest.java
@@ -0,0 +1,215 @@
+/*
+ * $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.request.jsp;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.tiles.request.AbstractViewRequest;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.DispatchRequest;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.jsp.extractor.ScopeExtractor;
+import org.apache.tiles.request.jsp.extractor.SessionScopeExtractor;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.apache.tiles.request.servlet.ServletUtil;
+
+/**
+ * Context implementation used for executing tiles within a
+ * jsp tag library.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspRequest extends AbstractViewRequest {
+
+ /**
+ * The native available scopes.
+ */
+ private static final List<String> SCOPES
+ = Collections.unmodifiableList(Arrays.asList("page", "request", "session", "application"));
+
+ /**
+ * The current page context.
+ */
+ private PageContext pageContext;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of page scope
+ * attributes.</p>
+ */
+ private Map<String, Object> pageScope = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request scope
+ * attributes.</p>
+ */
+ private Map<String, Object> requestScope = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of session scope
+ * attributes.</p>
+ */
+ private Map<String, Object> sessionScope = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of application scope
+ * attributes.</p>
+ */
+ private Map<String, Object> applicationScope = null;
+
+ /**
+ * Creates a JSP request.
+ *
+ * @param applicationContext The application context.
+ * @param pageContext The page context.
+ * @return A new JSP request.
+ */
+ public static JspRequest createServletJspRequest(ApplicationContext applicationContext, PageContext pageContext) {
+ return new JspRequest(new ServletRequest(
+ applicationContext, (HttpServletRequest) pageContext
+ .getRequest(), (HttpServletResponse) pageContext
+ .getResponse()), pageContext);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param enclosedRequest The request that is wrapped here.
+ * @param pageContext The page context to use.
+ */
+ public JspRequest(DispatchRequest enclosedRequest,
+ PageContext pageContext) {
+ super(enclosedRequest);
+ this.pageContext = pageContext;
+ }
+
+ @Override
+ public List<String> getAvailableScopes() {
+ return SCOPES;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInclude(String path) throws IOException {
+ try {
+ pageContext.include(path, false);
+ } catch (ServletException e) {
+ throw ServletUtil.wrapServletException(e, "JSPException including path '"
+ + path + "'.");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter getPrintWriter() {
+ return new JspPrintWriterAdapter(pageContext.getOut());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Writer getWriter() {
+ return pageContext.getOut();
+ }
+
+ /**
+ * Returns the page scope.
+ *
+ * @return The page scope.
+ */
+ public Map<String, Object> getPageScope() {
+ if ((pageScope == null) && (pageContext != null)) {
+ pageScope = new ScopeMap(new ScopeExtractor(pageContext,
+ PageContext.PAGE_SCOPE));
+ }
+ return (pageScope);
+ }
+
+ /**
+ * Returns the request scope.
+ *
+ * @return The request scope.
+ */
+ public Map<String, Object> getRequestScope() {
+ if ((requestScope == null) && (pageContext != null)) {
+ requestScope = new ScopeMap(new ScopeExtractor(pageContext,
+ PageContext.REQUEST_SCOPE));
+ }
+ return (requestScope);
+ }
+
+ /**
+ * Returns the session scope.
+ *
+ * @return The session scope.
+ */
+ public Map<String, Object> getSessionScope() {
+ if ((sessionScope == null) && (pageContext != null)) {
+ sessionScope = new ScopeMap(new SessionScopeExtractor(pageContext));
+ }
+ return (sessionScope);
+ }
+
+ /**
+ * Returns the application scope.
+ *
+ * @return The application scope.
+ */
+ public Map<String, Object> getApplicationScope() {
+ if ((applicationScope == null) && (pageContext != null)) {
+ applicationScope = new ScopeMap(new ScopeExtractor(pageContext,
+ PageContext.APPLICATION_SCOPE));
+ }
+ return (applicationScope);
+ }
+
+ /**
+ * Returns the page context that originated the request.
+ *
+ * @return The page context.
+ */
+ public PageContext getPageContext() {
+ return pageContext;
+ }
+
+ @Override
+ public Map<String, Object> getContext(String scope) {
+ if("page".equals(scope)){
+ return getPageScope();
+ }else if("request".equals(scope)){
+ return getRequestScope();
+ }else if("session".equals(scope)){
+ return getSessionScope();
+ }else if("application".equals(scope)){
+ return getApplicationScope();
+ }
+ throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check.");
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspUtil.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspUtil.java
new file mode 100644
index 0000000..2083f10
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/JspUtil.java
@@ -0,0 +1,55 @@
+/*
+ * $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.request.jsp;
+
+import javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+
+/**
+ * JSP utilities for JSP requests and related.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class JspUtil {
+
+ /**
+ * Constructor.
+ */
+ private JspUtil() {
+ }
+
+ /**
+ * Returns the application context. It must be
+ * first saved creating an {@link ApplicationContext} and using
+ * {@link org.apache.tiles.request.ApplicationAccess#register(ApplicationContext)}.
+ *
+ * @param jspContext The JSP context.
+ * @return The application context.
+ */
+ public static ApplicationContext getApplicationContext(JspContext jspContext) {
+ return (ApplicationContext) jspContext.getAttribute(
+ ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE,
+ PageContext.APPLICATION_SCOPE);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java
new file mode 100644
index 0000000..9b72230
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntime.java
@@ -0,0 +1,61 @@
+/*
+ * $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.request.jsp.autotag;
+
+import javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.SimpleTagSupport;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.jsp.JspRequest;
+
+/**
+ * A Runtime for implementing JSP tag libraries.
+ */
+public class JspAutotagRuntime extends SimpleTagSupport implements AutotagRuntime {
+ /** {@inheritDoc} */
+ @Override
+ public void doTag() {
+ // do nothing like the parent implementation,
+ // but don't throw exceptions either
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Request createRequest() {
+ JspContext pageContext = getJspContext();
+ return JspRequest.createServletJspRequest(org.apache.tiles.request.jsp.JspUtil.getApplicationContext(pageContext),
+ (PageContext) pageContext);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelBody createModelBody() {
+ return new JspModelBody(getJspBody(), getJspContext());
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Object getParameter(String name, Object defaultValue) {
+ throw new UnsupportedOperationException("the parameters are injected into the tag itself, no need to fetch them");
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java
new file mode 100644
index 0000000..8918786
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/JspModelBody.java
@@ -0,0 +1,68 @@
+/*
+ * $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.request.jsp.autotag;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.JspFragment;
+
+import org.apache.tiles.autotag.core.runtime.AbstractModelBody;
+
+/**
+ * The body abstraction in a JSP tag.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspModelBody extends AbstractModelBody {
+
+ /**
+ * The real body.
+ */
+ private JspFragment jspFragment;
+
+ /**
+ * Constructor.
+ *
+ * @param jspFragment The real body.
+ * @param jspContext The page context.
+ */
+ public JspModelBody(JspFragment jspFragment, JspContext jspContext) {
+ super(jspContext.getOut());
+ this.jspFragment = jspFragment;
+ }
+
+ @Override
+ public void evaluate(Writer writer) throws IOException {
+ if (jspFragment == null) {
+ return;
+ }
+
+ try {
+ jspFragment.invoke(writer);
+ } catch (JspException e) {
+ throw new IOException("JspException when evaluating the body", e);
+ }
+ }
+
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java
new file mode 100644
index 0000000..08adc1b
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/autotag/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Runtime part of Autotag support for JavaServer pages.
+ */
+package org.apache.tiles.request.jsp.autotag;
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java
new file mode 100644
index 0000000..68ae799
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/ScopeExtractor.java
@@ -0,0 +1,76 @@
+/*
+ * $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.request.jsp.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.jsp.JspContext;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extracts attributes from a numbered scope from {@link JspContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The JSP context.
+ */
+ private JspContext context;
+
+ /**
+ * The scope number to use.
+ */
+ private int scope;
+
+ /**
+ * Constructor.
+ *
+ * @param context The JSP context.
+ * @param scope The scope number.
+ */
+ public ScopeExtractor(JspContext context, int scope) {
+ this.context = context;
+ this.scope = scope;
+ }
+
+ @Override
+ public void removeValue(String name) {
+ context.removeAttribute(name, scope);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return context.getAttributeNamesInScope(scope);
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return context.getAttribute(key, scope);
+ }
+
+ @Override
+ public void setValue(String key, Object value) {
+ context.setAttribute(key, value, scope);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java
new file mode 100644
index 0000000..359a840
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractor.java
@@ -0,0 +1,81 @@
+/*
+ * $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.request.jsp.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.jsp.PageContext;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extracts attributes from session scope from {@link PageContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The page context.
+ */
+ private PageContext context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The page context.
+ */
+ public SessionScopeExtractor(PageContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public void removeValue(String name) {
+ if (context.getSession() == null) {
+ return;
+ }
+ context.removeAttribute(name, PageContext.SESSION_SCOPE);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ if (context.getSession() == null) {
+ return null;
+ }
+ return context.getAttributeNamesInScope(PageContext.SESSION_SCOPE);
+ }
+
+ @Override
+ public Object getValue(String key) {
+ if (context.getSession() == null) {
+ return null;
+ }
+ return context.getAttribute(key, PageContext.SESSION_SCOPE);
+ }
+
+ @Override
+ public void setValue(String key, Object value) {
+ if (context.getSession() == null) {
+ return;
+ }
+ context.setAttribute(key, value, PageContext.SESSION_SCOPE);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java
new file mode 100644
index 0000000..0e2d9cb
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/extractor/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Extractors to get scopes from {@link javax.servlet.jsp.PageContext}.
+ */
+package org.apache.tiles.request.jsp.extractor;
diff --git a/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/package-info.java b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/package-info.java
new file mode 100644
index 0000000..edf2b21
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/main/java/org/apache/tiles/request/jsp/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Support of Tiles request in a JSP environment.
+ */
+package org.apache.tiles.request.jsp;
diff --git a/tiles-request/tiles-request-jsp/src/site/site.xml b/tiles-request/tiles-request-jsp/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspPrintWriterAdapterTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspPrintWriterAdapterTest.java
new file mode 100644
index 0000000..be059a9
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspPrintWriterAdapterTest.java
@@ -0,0 +1,971 @@
+/*
+ * $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.request.jsp;
+
+import static org.easymock.classextension.EasyMock.*;
+
+import java.io.IOException;
+
+import javax.servlet.jsp.JspWriter;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests {@link JspPrintWriterAdapter}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspPrintWriterAdapterTest extends TestCase {
+
+ /**
+ * The string length.
+ */
+ private static final int STRING_LENGTH = 10;
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteInt() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.write(1);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(1);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(char[])}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteCharArray() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(aryEq(result.toCharArray()));
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result.toCharArray());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(char[], int, int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteCharArrayIntInt() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(aryEq(result.toCharArray()), eq(0),
+ eq(STRING_LENGTH));
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result.toCharArray(), 0, STRING_LENGTH);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#flush()}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testFlush() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.flush();
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#close()}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testClose() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.close();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.close();
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(boolean)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintBoolean() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(true);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(true);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(char)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintChar() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print('c');
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print('c');
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintInt() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(long)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintLong() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1L);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1L);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(float)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintFloat() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1f);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1f);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(double)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintDouble() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1d);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1d);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(char[])}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintCharArray() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.print(aryEq(result.toCharArray()));
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(result.toCharArray());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println()}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintln() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println();
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(boolean)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnBoolean() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(true);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(true);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(char)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnChar() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println('c');
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println('c');
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnInt() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(long)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnLong() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1L);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1L);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(float)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnFloat() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1f);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1f);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(double)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnDouble() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1d);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1d);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(char[])}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnCharArray() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.println(aryEq(result.toCharArray()));
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(result.toCharArray());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#getJspWriter()}.
+ */
+ public void testGetJspWriter() {
+ JspWriter writer = createMock(JspWriter.class);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ assertEquals(writer, adapter.getJspWriter());
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#append(char)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testAppendChar() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ expect(writer.append('c')).andReturn(writer);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ assertEquals(adapter, adapter.append('c'));
+ verify(writer);
+ }
+
+ /**
+ * Test method for
+ * {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#append(java.lang.CharSequence, int, int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testAppendCharSequenceIntInt() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ CharSequence sequence = createMock(CharSequence.class);
+ expect(writer.append(sequence, 0, STRING_LENGTH)).andReturn(writer);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ assertEquals(adapter, adapter.append(sequence, 0, STRING_LENGTH));
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#append(java.lang.CharSequence)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testAppendCharSequence() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ CharSequence sequence = createMock(CharSequence.class);
+ expect(writer.append(sequence)).andReturn(writer);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ assertEquals(adapter, adapter.append(sequence));
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(java.lang.Object)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintObject() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ Object obj = createMock(Object.class);
+ writer.print(obj);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(obj);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(java.lang.String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintString() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print("this is a string");
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print("this is a string");
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(java.lang.Object)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnObject() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ Object obj = createMock(Object.class);
+ writer.println(obj);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(obj);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(java.lang.String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnString() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println("this is a string");
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println("this is a string");
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(java.lang.String, int, int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteStringIntInt() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(result, 0, STRING_LENGTH);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result, 0, STRING_LENGTH);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(java.lang.String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteString() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(result);
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result);
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteIntEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.write(1);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(1);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(char[])}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteCharArrayEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(aryEq(result.toCharArray()));
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result.toCharArray());
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(char[], int, int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteCharArrayIntIntEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(aryEq(result.toCharArray()), eq(0),
+ eq(STRING_LENGTH));
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result.toCharArray(), 0, STRING_LENGTH);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#flush()}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testFlushEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.flush();
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.flush();
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#close()}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testCloseEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.close();
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.close();
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(boolean)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintBooleanEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(true);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(true);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(char)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintCharEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print('c');
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print('c');
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintIntEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(long)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintLongEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1L);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1L);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(float)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintFloatEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1f);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1f);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(double)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintDoubleEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print(1d);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(1d);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(char[])}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintCharArrayEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.print(aryEq(result.toCharArray()));
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(result.toCharArray());
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println()}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println();
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println();
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(boolean)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnBooleanEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(true);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(true);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(char)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnCharEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println('c');
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println('c');
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnIntEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(long)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnLongEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1L);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1L);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(float)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnFloatEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1f);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1f);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(double)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnDoubleEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println(1d);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(1d);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(char[])}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnCharArrayEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.println(aryEq(result.toCharArray()));
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(result.toCharArray());
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#append(char)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testAppendCharEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ expect(writer.append('c')).andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ assertEquals(adapter, adapter.append('c'));
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for
+ * {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#append(java.lang.CharSequence, int, int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testAppendCharSequenceIntIntEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ CharSequence sequence = createMock(CharSequence.class);
+ expect(writer.append(sequence, 0, STRING_LENGTH)).andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ assertEquals(adapter, adapter.append(sequence, 0, STRING_LENGTH));
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#append(java.lang.CharSequence)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testAppendCharSequenceEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ CharSequence sequence = createMock(CharSequence.class);
+ expect(writer.append(sequence)).andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ assertEquals(adapter, adapter.append(sequence));
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(java.lang.Object)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintObjectEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ Object obj = createMock(Object.class);
+ writer.print(obj);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print(obj);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#print(java.lang.String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintStringEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.print("this is a string");
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.print("this is a string");
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(java.lang.Object)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnObjectEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ Object obj = createMock(Object.class);
+ writer.println(obj);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println(obj);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#println(java.lang.String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testPrintlnStringEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ writer.println("this is a string");
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.println("this is a string");
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(java.lang.String, int, int)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteStringIntIntEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(result, 0, STRING_LENGTH);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result, 0, STRING_LENGTH);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspPrintWriterAdapter#write(java.lang.String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ public void testWriteStringEx() throws IOException {
+ JspWriter writer = createMock(JspWriter.class);
+ String result = "this is a test";
+ writer.write(result);
+ expectLastCall().andThrow(new IOException());
+ writer.flush();
+ JspPrintWriterAdapter adapter = new JspPrintWriterAdapter(writer);
+ replay(writer);
+ adapter.write(result);
+ assertTrue(adapter.checkError());
+ verify(writer);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspRequestTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspRequestTest.java
new file mode 100644
index 0000000..14c9a47
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspRequestTest.java
@@ -0,0 +1,201 @@
+/*
+ * $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.request.jsp;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.DispatchRequest;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link JspRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspRequestTest {
+
+ /**
+ * The enclosed request.
+ */
+ private DispatchRequest enclosedRequest;
+
+ /**
+ * The page context.
+ */
+ private PageContext context;
+
+ /**
+ * The request to test.
+ */
+ private JspRequest request;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ enclosedRequest = createMock(DispatchRequest.class);
+ context = createMock(PageContext.class);
+ request = new JspRequest(enclosedRequest, context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getWriter()}.
+ */
+ @Test
+ public void testGetWriter() {
+ JspWriter writer = createMock(JspWriter.class);
+
+ expect(context.getOut()).andReturn(writer);
+
+ replay(context, enclosedRequest, writer);
+ assertEquals(writer, request.getWriter());
+ verify(context, enclosedRequest, writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getPrintWriter()}.
+ */
+ @Test
+ public void testGetPrintWriter() {
+ JspWriter writer = createMock(JspWriter.class);
+
+ expect(context.getOut()).andReturn(writer);
+
+ replay(context, enclosedRequest, writer);
+ assertEquals(writer, ((JspPrintWriterAdapter) request.getPrintWriter())
+ .getJspWriter());
+ verify(context, enclosedRequest, writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test
+ public void testDoInclude() throws ServletException, IOException {
+ context.include("/my/path", false);
+
+ replay(context, enclosedRequest);
+ request.doInclude("/my/path");
+ verify(context, enclosedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludeException() throws ServletException, IOException {
+ context.include("/my/path", false);
+ expectLastCall().andThrow(new ServletException());
+
+ replay(context, enclosedRequest);
+ request.doInclude("/my/path");
+ verify(context, enclosedRequest);
+ }
+
+ /**
+ * Test method for {@link JspRequest#createServletJspRequest(ApplicationContext, PageContext)}.
+ */
+ @Test
+ public void testCreateServletJspRequest() {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse servletResponse = createMock(HttpServletResponse.class);
+
+ expect(context.getRequest()).andReturn(servletRequest);
+ expect(context.getResponse()).andReturn(servletResponse);
+
+ replay(context, applicationContext, servletRequest, servletResponse);
+ JspRequest request = JspRequest.createServletJspRequest(applicationContext, context);
+ ServletRequest wrappedRequest = (ServletRequest) request.getWrappedRequest();
+ assertEquals(servletRequest, wrappedRequest.getRequest());
+ assertEquals(servletResponse, wrappedRequest.getResponse());
+ verify(context, applicationContext, servletRequest, servletResponse);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getPageScope()}.
+ */
+ @Test
+ public void testGetPageScope() {
+ replay(context, enclosedRequest);
+ assertTrue(request.getPageScope() instanceof ScopeMap);
+ verify(context, enclosedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getRequestScope()}.
+ */
+ @Test
+ public void testGetRequestScope() {
+ replay(context, enclosedRequest);
+ assertTrue(request.getRequestScope() instanceof ScopeMap);
+ verify(context, enclosedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getSessionScope()}.
+ */
+ @Test
+ public void testGetSessionScope() {
+ replay(context, enclosedRequest);
+ assertTrue(request.getSessionScope() instanceof ScopeMap);
+ verify(context, enclosedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getApplicationScope()}.
+ */
+ @Test
+ public void testGetApplicationScope() {
+ replay(context, enclosedRequest);
+ assertTrue(request.getApplicationScope() instanceof ScopeMap);
+ verify(context, enclosedRequest);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspRequest#getPageContext()}.
+ */
+ @Test
+ public void testGetPageContext() {
+ replay(context, enclosedRequest);
+ assertEquals(context, request.getPageContext());
+ verify(context, enclosedRequest);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspUtilTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspUtilTest.java
new file mode 100644
index 0000000..ee90a40
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/JspUtilTest.java
@@ -0,0 +1,56 @@
+/*
+ * $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.request.jsp;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.PageContext;
+
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.junit.Test;
+
+/**
+ * Tests {@link JspUtil}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspUtilTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.JspUtil#getApplicationContext(javax.servlet.jsp.JspContext)}.
+ */
+ @Test
+ public void testGetApplicationContext() {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ JspContext jspContext = createMock(JspContext.class);
+
+ expect(jspContext.getAttribute(ApplicationAccess
+ .APPLICATION_CONTEXT_ATTRIBUTE, PageContext.APPLICATION_SCOPE))
+ .andReturn(applicationContext);
+
+ replay(applicationContext, jspContext);
+ assertEquals(applicationContext, JspUtil.getApplicationContext(jspContext));
+ verify(applicationContext, jspContext);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntimeTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntimeTest.java
new file mode 100644
index 0000000..53baf2c
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/autotag/JspAutotagRuntimeTest.java
@@ -0,0 +1,100 @@
+/*
+ * $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.request.jsp.autotag;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.JspFragment;
+import javax.servlet.jsp.tagext.JspTag;
+
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.jsp.JspRequest;
+import org.apache.tiles.request.jsp.autotag.JspAutotagRuntime;
+import org.apache.tiles.request.jsp.autotag.JspModelBody;
+import org.junit.Test;
+
+public class JspAutotagRuntimeTest {
+ @Test
+ public void testCreateRequest() {
+ JspFragment jspBody = createMock(JspFragment.class);
+ PageContext pageContext = createMock(PageContext.class);
+ JspTag parent = createMock(JspTag.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ HttpServletRequest httpServletRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse httpServletResponse = createMock(HttpServletResponse.class);
+ expect(pageContext.getAttribute(
+ ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE,
+ PageContext.APPLICATION_SCOPE)).andReturn(applicationContext);
+ expect(pageContext.getRequest()).andReturn(httpServletRequest);
+ expect(pageContext.getResponse()).andReturn(httpServletResponse);
+ replay(jspBody, pageContext, parent, applicationContext, httpServletRequest, httpServletResponse);
+ JspAutotagRuntime runtime = new JspAutotagRuntime();
+ runtime.setJspBody(jspBody);
+ runtime.setJspContext(pageContext);
+ runtime.setParent(parent);
+ runtime.doTag();
+ Request jspRequest = runtime.createRequest();
+ assertTrue(jspRequest instanceof JspRequest);
+ verify(jspBody, pageContext, parent, applicationContext, httpServletRequest, httpServletResponse);
+ }
+
+ @Test
+ public void testCreateModelBody() {
+ JspFragment jspBody = createMock(JspFragment.class);
+ JspContext jspContext = createMock(JspContext.class);
+ JspTag parent = createMock(JspTag.class);
+ JspWriter writer = createMock(JspWriter.class);
+ expect(jspContext.getOut()).andReturn(writer);
+ replay(jspBody, jspContext, parent, writer);
+ JspAutotagRuntime runtime = new JspAutotagRuntime();
+ runtime.setJspBody(jspBody);
+ runtime.setJspContext(jspContext);
+ runtime.setParent(parent);
+ runtime.doTag();
+ ModelBody jspModelBody = runtime.createModelBody();
+ assertTrue(jspModelBody instanceof JspModelBody);
+ verify(jspBody, jspContext, parent, writer);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetParameter() {
+ JspFragment jspBody = createMock(JspFragment.class);
+ JspContext jspContext = createMock(JspContext.class);
+ JspTag parent = createMock(JspTag.class);
+ replay(jspBody, jspContext, parent);
+ JspAutotagRuntime runtime = new JspAutotagRuntime();
+ runtime.setJspBody(jspBody);
+ runtime.setJspContext(jspContext);
+ runtime.setParent(parent);
+ runtime.doTag();
+ runtime.getParameter("test", null);
+ verify(jspBody, jspContext, parent);
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/autotag/JspModelBodyTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/autotag/JspModelBodyTest.java
new file mode 100644
index 0000000..f00cb24
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/autotag/JspModelBodyTest.java
@@ -0,0 +1,104 @@
+/*
+ * $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.request.jsp.autotag;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspWriter;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.JspFragment;
+
+import org.apache.tiles.request.jsp.autotag.JspModelBody;
+import org.junit.Test;
+
+/**
+ * Tests {@link JspModelBody}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JspModelBodyTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.autotag.freemarker.runtime.JspModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ * @throws JspException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateWriter() throws JspException, IOException {
+ JspFragment body = createMock(JspFragment.class);
+ PageContext pageContext = createMock(PageContext.class);
+ JspWriter writer = createMock(JspWriter.class);
+
+ expect(pageContext.getOut()).andReturn(null);
+ body.invoke(writer);
+
+ replay(body, pageContext, writer);
+ JspModelBody modelBody = new JspModelBody(body, pageContext);
+ modelBody.evaluate(writer);
+ verify(body, pageContext, writer);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.autotag.freemarker.runtime.JspModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ * @throws JspException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateWriterNull() throws JspException, IOException {
+ PageContext pageContext = createMock(PageContext.class);
+ Writer writer = createMock(Writer.class);
+
+ expect(pageContext.getOut()).andReturn(null);
+
+ replay(writer, pageContext);
+ JspModelBody modelBody = new JspModelBody(null, pageContext);
+ modelBody.evaluate(writer);
+ verify(writer, pageContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.autotag.freemarker.runtime.JspModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ * @throws JspException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testEvaluateWriterException() throws JspException, IOException {
+ PageContext pageContext = createMock(PageContext.class);
+ JspFragment body = createMock(JspFragment.class);
+ JspWriter writer = createMock(JspWriter.class);
+
+ expect(pageContext.getOut()).andReturn(null);
+ body.invoke(writer);
+ expectLastCall().andThrow(new JspException());
+
+ replay(body, pageContext, writer);
+ try {
+ JspModelBody modelBody = new JspModelBody(body, pageContext);
+ modelBody.evaluate(writer);
+ } finally {
+ verify(body, pageContext, writer);
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/extractor/ScopeExtractorTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/extractor/ScopeExtractorTest.java
new file mode 100644
index 0000000..465e8a8
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/extractor/ScopeExtractorTest.java
@@ -0,0 +1,110 @@
+/*
+ * $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.request.jsp.extractor;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.jsp.JspContext;
+import javax.servlet.jsp.PageContext;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ScopeExtractorTest {
+
+ /**
+ * The JSP context.
+ */
+ private JspContext context;
+
+ /**
+ * The extractor to test.
+ */
+ private ScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ context = createMock(JspContext.class);
+ extractor = new ScopeExtractor(context, PageContext.PAGE_SCOPE);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ context.removeAttribute("key", PageContext.PAGE_SCOPE);
+
+ replay(context);
+ extractor.removeValue("key");
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ expect(context.getAttributeNamesInScope(PageContext.PAGE_SCOPE)).andReturn(keys);
+
+ replay(context);
+ assertEquals(keys, extractor.getKeys());
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(context.getAttribute("key", PageContext.PAGE_SCOPE)).andReturn("value");
+
+ replay(context);
+ assertEquals("value", extractor.getValue("key"));
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link ScopeExtractor#setValue(String, Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ context.setAttribute("key", "value", PageContext.PAGE_SCOPE);
+
+ replay(context);
+ extractor.setValue("key", "value");
+ verify(context);
+ }
+
+}
diff --git a/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractorTest.java b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractorTest.java
new file mode 100644
index 0000000..6aed2d4
--- /dev/null
+++ b/tiles-request/tiles-request-jsp/src/test/java/org/apache/tiles/request/jsp/extractor/SessionScopeExtractorTest.java
@@ -0,0 +1,169 @@
+/*
+ * $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.request.jsp.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.jsp.PageContext;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link SessionScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionScopeExtractorTest {
+
+ /**
+ * The page context.
+ */
+ private PageContext context;
+
+ /**
+ * The session.
+ */
+ private HttpSession session;
+
+ /**
+ * The extracto to test.
+ */
+ private SessionScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ context = createMock(PageContext.class);
+ session = createMock(HttpSession.class);
+ extractor = new SessionScopeExtractor(context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ expect(context.getSession()).andReturn(session);
+ context.removeAttribute("key", PageContext.SESSION_SCOPE);
+
+ replay(context, session);
+ extractor.removeValue("key");
+ verify(context, session);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ expect(context.getSession()).andReturn(session);
+ Enumeration<String> keys = createMock(Enumeration.class);
+ expect(context.getAttributeNamesInScope(PageContext.SESSION_SCOPE)).andReturn(keys);
+
+ replay(context, session);
+ assertEquals(keys, extractor.getKeys());
+ verify(context, session);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(context.getSession()).andReturn(session);
+ expect(context.getAttribute("key", PageContext.SESSION_SCOPE)).andReturn("value");
+
+ replay(context, session);
+ assertEquals("value", extractor.getValue("key"));
+ verify(context, session);
+ }
+
+ /**
+ * Test method for {@link ScopeExtractor#setValue(String, Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ expect(context.getSession()).andReturn(session);
+ context.setAttribute("key", "value", PageContext.SESSION_SCOPE);
+
+ replay(context, session);
+ extractor.setValue("key", "value");
+ verify(context, session);
+ }
+
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValueNoSession() {
+ expect(context.getSession()).andReturn(null);
+
+ replay(context, session);
+ extractor.removeValue("key");
+ verify(context, session);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#getKeys()}.
+ */
+ @Test
+ public void testGetKeysNoSession() {
+ expect(context.getSession()).andReturn(null);
+
+ replay(context, session);
+ assertNull(extractor.getKeys());
+ verify(context, session);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.jsp.extractor.ScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValueNoSession() {
+ expect(context.getSession()).andReturn(null);
+
+ replay(context, session);
+ assertNull(extractor.getValue("key"));
+ verify(context, session);
+ }
+
+ /**
+ * Test method for {@link ScopeExtractor#setValue(String, Object)}.
+ */
+ @Test
+ public void testSetValueNoSession() {
+ expect(context.getSession()).andReturn(null);
+
+ replay(context, session);
+ extractor.setValue("key", "value");
+ verify(context, session);
+ }
+}
diff --git a/tiles-request/tiles-request-mustache/pom.xml b/tiles-request/tiles-request-mustache/pom.xml
new file mode 100644
index 0000000..c114b37
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-request</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-mustache</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles request - Mustache support</name>
+ <description>Tiles request implementation for Mustache templates.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.github.spullara.mustache.java</groupId>
+ <artifactId>core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.github.spullara.mustache.java</groupId>
+ <artifactId>builder</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheRenderer.java b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheRenderer.java
new file mode 100644
index 0000000..5c286f2
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheRenderer.java
@@ -0,0 +1,98 @@
+/*
+ * $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.request.mustache;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.sampullara.mustache.MustacheBuilder;
+import com.sampullara.mustache.MustacheException;
+import com.sampullara.mustache.Scope;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.render.CannotRenderException;
+import org.apache.tiles.request.render.Renderer;
+
+/**
+ * The Mustache-specific renderer.
+ *
+ * @version $Rev: 1215006 $ $Date: 2011-12-16 01:30:41 +0100 (Fri, 16 Dec 2011) $
+ */
+public final class MustacheRenderer implements Renderer {
+
+ private Pattern acceptPattern;
+
+ @Override
+ public void render(String path, Request request) throws IOException {
+ if (path == null) {
+ throw new CannotRenderException("Cannot dispatch a null path");
+ }
+
+ try{
+ new MustacheBuilder()
+ .build(new BufferedReader(new InputStreamReader(getResourceStream(request, path))), path)
+ .execute(request.getWriter(), buildScope(request));
+
+ }catch(MustacheException ex){
+ throw new IOException("failed to MustacheRenderer.render(" + path + ",request)", ex);
+ }
+ }
+
+ private static InputStream getResourceStream(Request request, String path) throws IOException {
+ final ApplicationContext applicationContext = request.getApplicationContext();
+ final ApplicationResource resource = applicationContext.getResource(path);
+ return resource.getInputStream();
+ }
+
+ private static Scope buildScope(Request request){
+ Scope scope = null;
+ List<String> availableScopes = request.getAvailableScopes();
+ for(int i = availableScopes.size() -1; i >= 0; --i){
+ scope = null == scope
+ ? new Scope(request.getContext(availableScopes.get(i)))
+ : new Scope(request.getContext(availableScopes.get(i)), scope);
+ }
+ return scope;
+ }
+
+ //@Override
+ public boolean isRenderable(String path, Request request) {
+ if (path == null) {
+ return false;
+ }
+ if (acceptPattern != null) {
+ final Matcher matcher = acceptPattern.matcher(path);
+ return matcher.matches();
+ }
+ return true;
+ }
+
+ public void setAcceptPattern(Pattern acceptPattern) {
+ this.acceptPattern = acceptPattern;
+ }
+}
diff --git a/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheScopeExtractor.java b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheScopeExtractor.java
new file mode 100644
index 0000000..2c839e2
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheScopeExtractor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2012 Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tiles.request.mustache;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Set;
+
+import com.sampullara.mustache.Scope;
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+
+public final class MustacheScopeExtractor implements AttributeExtractor {
+ private final Scope scope;
+
+ public MustacheScopeExtractor(Scope scope){
+ this.scope = scope;
+ }
+
+ @Override
+ public void removeValue(String key) {
+ scope.remove(key);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return (Enumeration<String>) Collections.enumeration((Set<?>)scope.keySet());
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return scope.get(key);
+ }
+
+ @Override
+ public void setValue(String key, Object value) {
+ scope.put(value, value);
+ }
+}
\ No newline at end of file
diff --git a/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheScopeMap.java b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheScopeMap.java
new file mode 100644
index 0000000..f323588
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/MustacheScopeMap.java
@@ -0,0 +1,75 @@
+/*
+ * $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.request.mustache;
+
+import java.util.Set;
+
+import com.sampullara.mustache.Scope;
+import org.apache.tiles.request.collection.ScopeMap;
+
+
+final class MustacheScopeMap extends ScopeMap {
+
+ /**
+ * The request object to use.
+ */
+ private Scope scope = null;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request object to use.
+ */
+ public MustacheScopeMap(Scope request) {
+ super(new MustacheScopeExtractor(request));
+ this.scope = request;
+ }
+
+ @Override
+ public Object remove(Object key) {
+ return scope.remove(key);
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ return scope.put(key, value);
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return scope.containsKey(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size() < 1;
+ }
+
+ @Override
+ public Set<String> keySet() {
+ return (Set<String>)(Set<?>)scope.keySet();
+ }
+
+ @Override
+ public int size() {
+ return scope.keySet().size();
+ }
+}
diff --git a/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/package-info.java b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/package-info.java
new file mode 100644
index 0000000..7422cdf
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/main/java/org/apache/tiles/request/mustache/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Support of Tiles request for Mustache.
+ */
+package org.apache.tiles.request.mustache;
diff --git a/tiles-request/tiles-request-mustache/src/site/site.xml b/tiles-request/tiles-request-mustache/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-mustache/src/test/java/org/apache/tiles/request/mustache/MustacheRendererTest.java b/tiles-request/tiles-request-mustache/src/test/java/org/apache/tiles/request/mustache/MustacheRendererTest.java
new file mode 100644
index 0000000..fd920f7
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/test/java/org/apache/tiles/request/mustache/MustacheRendererTest.java
@@ -0,0 +1,112 @@
+/*
+ * $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.request.mustache;
+
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.mustache.MustacheRenderer;
+import org.apache.tiles.request.render.CannotRenderException;
+import org.apache.tiles.request.render.Renderer;
+import org.apache.tiles.request.Request;
+import org.junit.Test;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests {@link MustacheRenderer}.
+ *
+ * @version $Rev: 1066788 $ $Date: 2011-02-03 11:49:11 +0000 (Thu, 03 Feb 2011) $
+ */
+public final class MustacheRendererTest {
+
+ /**
+ * Tests {@link MustacheRenderer#render(String, org.apache.tiles.request.Request)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testRender() throws IOException {
+ Request request = createMock(Request.class);
+ Writer writer = createMock(Writer.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ ApplicationResource applicationResource = createMock(ApplicationResource.class);
+ expect(applicationResource.getInputStream()).andReturn(getClass().getResource("/test.html").openStream());
+
+ Map<String,Object> context = Collections.singletonMap("testKey", (Object)"test value");
+
+ expect(request.getApplicationContext()).andReturn(applicationContext);
+ expect(applicationContext.getResource(isA(String.class))).andReturn(applicationResource).anyTimes();
+ expect(request.getAvailableScopes()).andReturn(Arrays.asList("request", "session", "application"));
+ expect(request.getContext("request")).andReturn(context);
+ expect(request.getContext("session")).andReturn(Collections.<String,Object>emptyMap());
+ expect(request.getContext("application")).andReturn(Collections.<String,Object>emptyMap());
+ expect(request.getWriter()).andReturn(writer);
+ writer.write("test template with test value");
+ writer.flush();
+
+ replay(request, applicationContext, applicationResource, writer);
+ Renderer renderer = new MustacheRenderer();
+ renderer.render("/test.html", request);
+ verify(request, applicationContext, applicationResource, writer);
+ }
+
+ /**
+ * Tests {@link MustacheRenderer#render(String, org.apache.tiles.request.Request)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = CannotRenderException.class)
+ public void testRenderException() throws IOException {
+ Request request = createMock(Request.class);
+ replay(request);
+ Renderer renderer = new MustacheRenderer();
+ try {
+ renderer.render(null, request);
+ } finally {
+ verify(request);
+ }
+ }
+
+ /**
+ * Test method for
+ * {@link MustacheRenderer#isRenderable(String, org.apache.tiles.request.Request)}
+ * .
+ */
+ @Test
+ public void testIsRenderable() {
+ MustacheRenderer renderer = new MustacheRenderer();
+ final Pattern pattern = Pattern.compile("/.*");
+ renderer.setAcceptPattern(pattern);
+
+ assertTrue(renderer.isRenderable("/my/template.html", null));
+ assertTrue(renderer.isRenderable("/my/template.any", null));
+ assertFalse(renderer.isRenderable("my/template.html", null));
+ assertFalse(renderer.isRenderable(null, null));
+ }
+}
diff --git a/tiles-request/tiles-request-mustache/src/test/resources/test.html b/tiles-request/tiles-request-mustache/src/test/resources/test.html
new file mode 100644
index 0000000..594cbb0
--- /dev/null
+++ b/tiles-request/tiles-request-mustache/src/test/resources/test.html
@@ -0,0 +1,20 @@
+{{!
+ ! $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.
+}}test template with {{testKey}}
\ No newline at end of file
diff --git a/tiles-request/tiles-request-portlet-wildcard/pom.xml b/tiles-request/tiles-request-portlet-wildcard/pom.xml
new file mode 100644
index 0000000..075b485
--- /dev/null
+++ b/tiles-request/tiles-request-portlet-wildcard/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>tiles-request-portlet-wildcard</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>Tiles - Wildcard file loading in Portlets</name>
+ <description>Tiles Wildcard file loading in Portlets: Allows to load resources using wildcards.</description>
+
+ <properties>
+ <tiles.osgi.symbolicName>org.apache.tiles.portlet.wildcard</tiles.osgi.symbolicName>
+ </properties>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <excludes>
+ <exclude>LICENSE.txt</exclude>
+ <exclude>NOTICE.txt</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>META-INF</targetPath>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-portlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc-portlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/tiles-request/tiles-request-portlet-wildcard/src/main/java/org/apache/tiles/request/portlet/wildcard/WildcardPortletApplicationContext.java b/tiles-request/tiles-request-portlet-wildcard/src/main/java/org/apache/tiles/request/portlet/wildcard/WildcardPortletApplicationContext.java
new file mode 100644
index 0000000..c178932
--- /dev/null
+++ b/tiles-request/tiles-request-portlet-wildcard/src/main/java/org/apache/tiles/request/portlet/wildcard/WildcardPortletApplicationContext.java
@@ -0,0 +1,116 @@
+/*
+ * $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.request.portlet.wildcard;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.locale.URLApplicationResource;
+import org.apache.tiles.request.portlet.PortletApplicationContext;
+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$
+ */
+public class WildcardPortletApplicationContext extends PortletApplicationContext {
+
+ /**
+ * The pattern resolver.
+ */
+ protected ResourcePatternResolver resolver;
+
+ /**
+ * Constructor.
+ *
+ * @param portletContext The portlet context.
+ */
+ public WildcardPortletApplicationContext(PortletContext portletContext) {
+ super(portletContext);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void initialize(PortletContext context) {
+ super.initialize(context);
+
+ resolver = new PortletContextResourcePatternResolver(context);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ApplicationResource getResource(String localePath) {
+ ApplicationResource retValue = null;
+ Collection<ApplicationResource> resourceSet = getResources(localePath);
+ if (resourceSet != null && !resourceSet.isEmpty()) {
+ retValue = resourceSet.iterator().next();
+ }
+ return retValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ApplicationResource getResource(ApplicationResource base, Locale locale) {
+ ApplicationResource retValue = null;
+ Collection<ApplicationResource> resourceSet = getResources(base.getLocalePath(locale));
+ if (resourceSet != null && !resourceSet.isEmpty()) {
+ retValue = resourceSet.iterator().next();
+ }
+ return retValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Collection<ApplicationResource> getResources(String path) {
+ Resource[] resources;
+ try {
+ resources = resolver.getResources(path);
+ } catch (IOException e) {
+ return Collections.<ApplicationResource> emptyList();
+ }
+ Collection<ApplicationResource> resourceList = new ArrayList<ApplicationResource>();
+ if (resources != null && resources.length > 0) {
+ for (int i = 0; i < resources.length; i++) {
+ URL url;
+ try {
+ url = resources[i].getURL();
+ resourceList.add(new URLApplicationResource(url.toExternalForm(), url));
+ } catch (IOException e) {
+ // shouldn't happen with the kind of resources we're using
+ throw new IllegalArgumentException("no URL for " + resources[i].toString(), e);
+ }
+ }
+ }
+ return resourceList;
+ }
+}
diff --git a/tiles-request/tiles-request-portlet-wildcard/src/main/java/org/apache/tiles/request/portlet/wildcard/package-info.java b/tiles-request/tiles-request-portlet-wildcard/src/main/java/org/apache/tiles/request/portlet/wildcard/package-info.java
new file mode 100644
index 0000000..45ca43b
--- /dev/null
+++ b/tiles-request/tiles-request-portlet-wildcard/src/main/java/org/apache/tiles/request/portlet/wildcard/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * 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.
+ */
+package org.apache.tiles.request.portlet.wildcard;
diff --git a/tiles-request/tiles-request-portlet-wildcard/src/site/site.xml b/tiles-request/tiles-request-portlet-wildcard/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-portlet-wildcard/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-portlet-wildcard/src/test/java/org/apache/tiles/request/portlet/wildcard/WildcardPortletApplicationContextTest.java b/tiles-request/tiles-request-portlet-wildcard/src/test/java/org/apache/tiles/request/portlet/wildcard/WildcardPortletApplicationContextTest.java
new file mode 100644
index 0000000..1bf84f5
--- /dev/null
+++ b/tiles-request/tiles-request-portlet-wildcard/src/test/java/org/apache/tiles/request/portlet/wildcard/WildcardPortletApplicationContextTest.java
@@ -0,0 +1,160 @@
+/*
+ * $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.request.portlet.wildcard;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.portlet.PortletContext;
+
+import junit.framework.TestCase;
+
+import org.apache.tiles.request.locale.URLApplicationResource;
+import org.easymock.EasyMock;
+
+
+/**
+ * Tests {@link WildcardPortletApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WildcardPortletApplicationContextTest 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 = 1;
+
+ /**
+ * The root Tiles application context.
+ */
+ private PortletContext portletContext;
+
+ /**
+ * The enhanced Tiles application context.
+ */
+ private WildcardPortletApplicationContext 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 WildcardPortletApplicationContext(portletContext);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void tearDown() {
+ 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(new URLApplicationResource(u.toExternalForm(), u), context.getResource("/" + url));
+ assertEquals(new URLApplicationResource(pomUrl.toExternalForm(), 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/request/portlet/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-request/tiles-request-portlet/pom.xml b/tiles-request/tiles-request-portlet/pom.xml
new file mode 100644
index 0000000..6941891
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>tiles-request-portlet</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>Tiles - Portlet support</name>
+ <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>
+ <directory>src/main/resources</directory>
+ <excludes>
+ <exclude>LICENSE.txt</exclude>
+ <exclude>NOTICE.txt</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>META-INF</targetPath>
+ </resource>
+ </resources>
+
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.portlet</groupId>
+ <artifactId>portlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.shale</groupId>
+ <artifactId>shale-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+</project>
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/ActionPortletRequest.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/ActionPortletRequest.java
new file mode 100644
index 0000000..e927788
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/ActionPortletRequest.java
@@ -0,0 +1,52 @@
+/*
+ * $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.request.portlet;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.StateAwareRequestDelegate;
+import org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate;
+
+/**
+ * Portlet request for an {@link ActionRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ActionPortletRequest extends PortletRequest {
+
+ /**
+ * Constructor.
+ *
+ * @param applicationContext The application context.
+ * @param context The portlet context.
+ * @param request The portlet request.
+ * @param response The portlet response.
+ */
+ public ActionPortletRequest(ApplicationContext applicationContext,
+ PortletContext context, ActionRequest request, ActionResponse response) {
+ super(applicationContext, context, request, response,
+ new StateAwareRequestDelegate(request, response),
+ new StateAwareResponseDelegate());
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/EventPortletRequest.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/EventPortletRequest.java
new file mode 100644
index 0000000..0855375
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/EventPortletRequest.java
@@ -0,0 +1,53 @@
+/*
+ * $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.request.portlet;
+
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.StateAwareRequestDelegate;
+import org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate;
+
+/**
+ * Portlet request for an {@link EventRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class EventPortletRequest extends PortletRequest {
+
+ /**
+ * Constructor.
+ *
+ * @param applicationContext The application context.
+ * @param context The portlet context.
+ * @param request The portlet request.
+ * @param response The portlet response.
+ */
+ public EventPortletRequest(ApplicationContext applicationContext,
+ PortletContext context, EventRequest request,
+ EventResponse response) {
+ super(applicationContext, context, request, response,
+ new StateAwareRequestDelegate(request, response),
+ new StateAwareResponseDelegate());
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/PortletApplicationContext.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/PortletApplicationContext.java
new file mode 100644
index 0000000..95bb31a
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/PortletApplicationContext.java
@@ -0,0 +1,152 @@
+/*
+ * $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.request.portlet;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.locale.URLApplicationResource;
+import org.apache.tiles.request.portlet.extractor.ApplicationScopeExtractor;
+import org.apache.tiles.request.portlet.extractor.InitParameterExtractor;
+
+/**
+ * Portlet-based TilesApplicationContext implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PortletApplicationContext implements ApplicationContext {
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of application scope
+ * attributes.</p>
+ */
+ private Map<String, Object> applicationScope = null;
+
+ /**
+ * <p>The <code>PortletContext</code> for this web application.</p>
+ */
+ protected PortletContext context = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of context initialization
+ * parameters.</p>
+ */
+ private Map<String, String> initParam = null;
+
+ /**
+ * Creates a new instance of PortletTilesApplicationContext.
+ *
+ * @param context The portlet context to use.
+ */
+ public PortletApplicationContext(PortletContext context) {
+ initialize(context);
+ }
+
+ /** {@inheritDoc} */
+ public Object getContext() {
+ return context;
+ }
+
+ /**
+ * <p>Initialize (or reinitialize) this {@link PortletApplicationContext} instance
+ * for the specified Portlet API objects.</p>
+ *
+ * @param context The <code>PortletContext</code> for this web application
+ */
+ public void initialize(PortletContext context) {
+
+ // Save the specified Portlet API object references
+ this.context = context;
+
+ }
+
+ /**
+ * <p>Return the {@link PortletContext} for this context.</p>
+ *
+ * @return The original portlet context.
+ */
+ public PortletContext getPortletContext() {
+ return (this.context);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getApplicationScope() {
+ if ((applicationScope == null) && (context != null)) {
+ applicationScope = new ScopeMap(new ApplicationScopeExtractor(context));
+ }
+ return (applicationScope);
+
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getInitParams() {
+ if ((initParam == null) && (context != null)) {
+ initParam = new ReadOnlyEnumerationMap<String>(new InitParameterExtractor(context));
+ }
+ return (initParam);
+
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationResource getResource(String localePath) {
+ try {
+ URL url = context.getResource(localePath);
+ if (url != null) {
+ return new URLApplicationResource(localePath, url);
+ } else {
+ return null;
+ }
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationResource getResource(ApplicationResource base, Locale locale) {
+ try {
+ URL url = context.getResource(base.getLocalePath(locale));
+ if (url != null) {
+ return new URLApplicationResource(base.getPath(), locale, url);
+ } else {
+ return null;
+ }
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Collection<ApplicationResource> getResources(String path) {
+ ArrayList<ApplicationResource> resources = new ArrayList<ApplicationResource>();
+ resources.add(getResource(path));
+ return resources;
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java
new file mode 100644
index 0000000..fa13cc3
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/PortletRequest.java
@@ -0,0 +1,337 @@
+/*
+ * $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.request.portlet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletResponse;
+import javax.portlet.PortletSession;
+
+import org.apache.tiles.request.AbstractClientRequest;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.attribute.Addable;
+import org.apache.tiles.request.collection.HeaderValuesMap;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.portlet.delegate.RequestDelegate;
+import org.apache.tiles.request.portlet.delegate.ResponseDelegate;
+import org.apache.tiles.request.portlet.extractor.HeaderExtractor;
+import org.apache.tiles.request.portlet.extractor.RequestScopeExtractor;
+import org.apache.tiles.request.portlet.extractor.SessionScopeExtractor;
+
+/**
+ * Portlet-based TilesApplicationContext implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PortletRequest extends AbstractClientRequest {
+
+ /**
+ * The native available scopes.
+ */
+ private static final List<String> SCOPES
+ = Collections.unmodifiableList(Arrays.asList("request", "portletSession", "session", "application"));
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of header name-value
+ * combinations (immutable).</p>
+ */
+ private Map<String, String> header = null;
+
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of header name-value
+ * combinations (write-only).</p>
+ */
+ private Addable<String> responseHeaders = null;
+
+
+ /**
+ * <p>The lazily instantitated <code>Map</code> of header name-values
+ * combinations (immutable).</p>
+ */
+ private Map<String, String[]> headerValues = null;
+
+ /**
+ * The <code>PortletContext</code> for this application.
+ */
+ protected PortletContext context = null;
+
+ /**
+ * <p>The <code>PortletRequest</code> for this request.</p>
+ */
+ protected javax.portlet.PortletRequest request = null;
+
+ /**
+ * The delegate to get information about parameters.
+ */
+ protected RequestDelegate requestDelegate;
+
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request scope
+ * attributes.</p>
+ */
+ private Map<String, Object> requestScope = null;
+
+
+ /**
+ * <p>The <code>PortletResponse</code> for this request.</p>
+ */
+ protected PortletResponse response = null;
+
+ /**
+ * The delegate to get information from a response (output stream, writer, etc.).
+ */
+ protected ResponseDelegate responseDelegate;
+
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of session scope
+ * attributes.</p>
+ */
+ private Map<String, Object> sessionScope = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of portlet session scope
+ * attributes.</p>
+ */
+ private Map<String, Object> portletSessionScope = null;
+
+
+ /**
+ * Creates a new instance of PortletTilesRequestContext.
+ *
+ * @param applicationContext The Tiles application context.
+ * @param context The portlet context to use.
+ * @param request The request object to use.
+ * @param response The response object to use.
+ * @param requestDelegate The request delegate.
+ * @param responseDelegate The response delegate.
+ */
+ public PortletRequest(ApplicationContext applicationContext,
+ PortletContext context, javax.portlet.PortletRequest request,
+ PortletResponse response, RequestDelegate requestDelegate, ResponseDelegate responseDelegate) {
+ super(applicationContext);
+
+ // Save the specified Portlet API object references
+ this.context = context;
+ this.request = request;
+ this.response = response;
+ this.requestDelegate = requestDelegate;
+ this.responseDelegate = responseDelegate;
+ }
+
+ /**
+ * <p>Return the {@link PortletRequest} for this context.</p>
+ *
+ * @return The used portlet request.
+ */
+ public javax.portlet.PortletRequest getRequest() {
+ return (this.request);
+ }
+
+ /**
+ * <p>Return the {@link PortletResponse} for this context.</p>
+ *
+ * @return The used portlet response.
+ */
+ public PortletResponse getResponse() {
+ return (this.response);
+ }
+
+ /**
+ * Returns the portlet context.
+ *
+ * @return The portlet context.
+ */
+ public PortletContext getPortletContext() {
+ return context;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getHeader() {
+ if ((header == null) && (request != null)) {
+ header = new ReadOnlyEnumerationMap<String>(new HeaderExtractor(request, null));
+ }
+ return (header);
+ }
+
+ /** {@inheritDoc} */
+ public Addable<String> getResponseHeaders() {
+ if ((responseHeaders == null) && (request != null)) {
+ responseHeaders = new HeaderExtractor(null, response);
+ }
+ return (responseHeaders);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getHeaderValues() {
+ if ((headerValues == null) && (request != null)) {
+ headerValues = new HeaderValuesMap(new HeaderExtractor(request, response));
+ }
+ return (headerValues);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getRequestScope() {
+ if ((requestScope == null) && (request != null)) {
+ requestScope = new ScopeMap(new RequestScopeExtractor(request));
+ }
+ return (requestScope);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getSessionScope() {
+ if ((sessionScope == null) && (request != null)) {
+ sessionScope = new ScopeMap(new SessionScopeExtractor(request,
+ PortletSession.APPLICATION_SCOPE));
+ }
+ return (sessionScope);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getPortletSessionScope() {
+ if ((portletSessionScope == null) && (request != null)) {
+ portletSessionScope = new ScopeMap(new SessionScopeExtractor(
+ request, PortletSession.APPLICATION_SCOPE));
+ }
+ return (portletSessionScope);
+ }
+
+ @Override
+ public List<String> getAvailableScopes() {
+ return SCOPES;
+ }
+
+ /** {@inheritDoc} */
+ public Locale getRequestLocale() {
+ return request.getLocale();
+ }
+
+ @Override
+ public Map<String, String> getParam() {
+ return requestDelegate.getParam();
+ }
+
+ @Override
+ public Map<String, String[]> getParamValues() {
+ return requestDelegate.getParamValues();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isUserInRole(String role) {
+ return request.isUserInRole(role);
+ }
+
+ @Override
+ public OutputStream getOutputStream() throws IOException {
+ return responseDelegate.getOutputStream();
+ }
+
+ @Override
+ public PrintWriter getPrintWriter() throws IOException {
+ return responseDelegate.getPrintWriter();
+ }
+
+ @Override
+ public Writer getWriter() throws IOException {
+ return responseDelegate.getWriter();
+ }
+
+ @Override
+ public boolean isResponseCommitted() {
+ return responseDelegate.isResponseCommitted();
+ }
+
+ @Override
+ public void setContentType(String contentType) {
+ responseDelegate.setContentType(contentType);
+ }
+
+ /** {@inheritDoc} */
+ public void doForward(String path) throws IOException {
+ if (responseDelegate.isResponseCommitted()) {
+ doInclude(path);
+ return;
+ }
+
+ try {
+ PortletRequestDispatcher rd = getPortletContext()
+ .getRequestDispatcher(path);
+
+ if (rd == null) {
+ throw new IOException(
+ "No portlet request dispatcher returned for path '"
+ + path + "'");
+ }
+
+ rd.forward(request, response);
+ } catch (PortletException e) {
+ throw new IOException("PortletException while including path '"
+ + path + "'.", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void doInclude(String path) throws IOException {
+ try {
+ PortletRequestDispatcher rd = getPortletContext()
+ .getRequestDispatcher(path);
+
+ if (rd == null) {
+ throw new IOException(
+ "No portlet request dispatcher returned for path '"
+ + path + "'");
+ }
+
+ rd.include(request, response);
+ } catch (PortletException e) {
+ throw new IOException("PortletException while including path '"
+ + path + "'.", e);
+ }
+ }
+
+ @Override
+ public Map<String, Object> getContext(String scope) {
+ if("request".equals(scope)){
+ return getRequestScope();
+ }else if("application".equals(scope)){
+ return getApplicationScope();
+ }else if("portletSession".equals(scope)){
+ return getPortletSessionScope();
+ }else if("application".equals(scope)){
+ return getApplicationScope();
+ }
+ throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check.");
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java
new file mode 100644
index 0000000..0eb5117
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/RenderPortletRequest.java
@@ -0,0 +1,53 @@
+/*
+ * $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.request.portlet;
+
+import javax.portlet.PortletContext;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate;
+import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate;
+
+/**
+ * Portlet request for a {@link RenderRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RenderPortletRequest extends PortletRequest {
+
+ /**
+ * Constructor.
+ *
+ * @param applicationContext The application context.
+ * @param context The portlet context.
+ * @param request The portlet request.
+ * @param response The portlet response.
+ */
+ public RenderPortletRequest(ApplicationContext applicationContext,
+ PortletContext context, RenderRequest request,
+ RenderResponse response) {
+ super(applicationContext, context, request, response,
+ new PortletRequestDelegate(request), new MimeResponseDelegate(
+ response));
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/ResourcePortletRequest.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/ResourcePortletRequest.java
new file mode 100644
index 0000000..7870287
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/ResourcePortletRequest.java
@@ -0,0 +1,53 @@
+/*
+ * $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.request.portlet;
+
+import javax.portlet.PortletContext;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate;
+import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate;
+
+/**
+ * Portlet request for a {@link ResourceRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourcePortletRequest extends PortletRequest {
+
+ /**
+ * Constructor.
+ *
+ * @param applicationContext The application context.
+ * @param context The portlet context.
+ * @param request The portlet request.
+ * @param response The portlet response.
+ */
+ public ResourcePortletRequest(ApplicationContext applicationContext,
+ PortletContext context, ResourceRequest request,
+ ResourceResponse response) {
+ super(applicationContext, context, request, response,
+ new PortletRequestDelegate(request), new MimeResponseDelegate(
+ response));
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java
new file mode 100644
index 0000000..f9b6ac4
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegate.java
@@ -0,0 +1,75 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import javax.portlet.MimeResponse;
+
+/**
+ * Response delegate in case of {@link MimeResponse}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MimeResponseDelegate implements ResponseDelegate {
+
+ /**
+ * The response.
+ */
+ private MimeResponse response;
+
+ /**
+ * Constructor.
+ *
+ * @param response The response.
+ */
+ public MimeResponseDelegate(MimeResponse response) {
+ this.response = response;
+ }
+
+ /** {@inheritDoc} */
+ public OutputStream getOutputStream() throws IOException {
+ return response.getPortletOutputStream();
+ }
+
+ /** {@inheritDoc} */
+ public PrintWriter getPrintWriter() throws IOException {
+ return response.getWriter();
+ }
+
+ /** {@inheritDoc} */
+ public Writer getWriter() throws IOException {
+ return response.getWriter();
+ }
+
+ /** {@inheritDoc} */
+ public boolean isResponseCommitted() {
+ return response.isCommitted();
+ }
+
+ /** {@inheritDoc} */
+ public void setContentType(String contentType) {
+ response.setContentType(contentType);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java
new file mode 100644
index 0000000..cb7ff69
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegate.java
@@ -0,0 +1,78 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.util.Map;
+
+import javax.portlet.PortletRequest;
+
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.portlet.extractor.ParameterExtractor;
+
+/**
+ * Request delegate in case of simple Portlet request.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PortletRequestDelegate implements RequestDelegate {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request
+ * parameter name-value.</p>
+ */
+ private Map<String, String> param = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request
+ * parameter name-values.</p>
+ */
+ private Map<String, String[]> paramValues = null;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request.
+ */
+ public PortletRequestDelegate(PortletRequest request) {
+ this.request = request;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getParam() {
+ if ((param == null) && (request != null)) {
+ param = new ReadOnlyEnumerationMap<String>(new ParameterExtractor(request));
+ }
+ return (param);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getParamValues() {
+ if ((paramValues == null) && (request != null)) {
+ paramValues = request.getParameterMap();
+ }
+ return (paramValues);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java
new file mode 100644
index 0000000..e7b9e97
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/RequestDelegate.java
@@ -0,0 +1,45 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.util.Map;
+
+/**
+ * Exposes the parameters of a portlet request, if available.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface RequestDelegate {
+
+ /**
+ * The parameters, as single values.
+ *
+ * @return The parameters.
+ */
+ Map<String, String> getParam();
+
+ /**
+ * The parameters, with values as array of strings.
+ *
+ * @return The parameters.
+ */
+ Map<String, String[]> getParamValues();
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java
new file mode 100644
index 0000000..b7afb5a
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/ResponseDelegate.java
@@ -0,0 +1,72 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * Exposes features of a response, if they are available.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ResponseDelegate {
+
+ /**
+ * Returns the output stream.
+ *
+ * @return The output stream.
+ * @throws IOException If the underlying response causes a problem.
+ */
+ OutputStream getOutputStream() throws IOException;
+
+ /**
+ * Returns the print writer.
+ *
+ * @return The print writer.
+ * @throws IOException If the underlying response causes a problem.
+ */
+ PrintWriter getPrintWriter() throws IOException;
+
+ /**
+ * Returns the writer.
+ *
+ * @return The writer.
+ * @throws IOException If the underlying response causes a problem.
+ */
+ Writer getWriter() throws IOException;
+
+ /**
+ * Sets the content type of the response.
+ *
+ * @param contentType The content type.
+ */
+ void setContentType(String contentType);
+
+ /**
+ * Checks if the response is committed.
+ *
+ * @return <code>true</code> if the response is committed.
+ */
+ boolean isResponseCommitted();
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMap.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMap.java
new file mode 100644
index 0000000..1930815
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMap.java
@@ -0,0 +1,115 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Parameter map to be used when the response is a {@link javax.portlet.StateAwareResponse}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareParameterMap implements Map<String, String[]> {
+
+ /**
+ * The request parameter map.
+ */
+ private Map<String, String[]> requestMap;
+
+ /**
+ * The response parameter map.
+ */
+ private Map<String, String[]> responseMap;
+
+ /**
+ * Constructor.
+ *
+ * @param requestMap The request parameter map.
+ * @param responseMap The response parameter map.
+ */
+ public StateAwareParameterMap(Map<String, String[]> requestMap,
+ Map<String, String[]> responseMap) {
+ this.requestMap = requestMap;
+ this.responseMap = responseMap;
+ }
+
+ @Override
+ public void clear() {
+ responseMap.clear();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return requestMap.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return requestMap.containsValue(value);
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<String, String[]>> entrySet() {
+ return requestMap.entrySet();
+ }
+
+ @Override
+ public String[] get(Object key) {
+ return requestMap.get(key);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return requestMap.isEmpty();
+ }
+
+ @Override
+ public Set<String> keySet() {
+ return requestMap.keySet();
+ }
+
+ @Override
+ public String[] put(String key, String[] value) {
+ return responseMap.put(key, value);
+ }
+
+ @Override
+ public void putAll(Map<? extends String, ? extends String[]> m) {
+ responseMap.putAll(m);
+ }
+
+ @Override
+ public String[] remove(Object key) {
+ return responseMap.remove(key);
+ }
+
+ @Override
+ public int size() {
+ return requestMap.size();
+ }
+
+ @Override
+ public Collection<String[]> values() {
+ return requestMap.values();
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegate.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegate.java
new file mode 100644
index 0000000..854c0cc
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegate.java
@@ -0,0 +1,90 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.util.Map;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.StateAwareResponse;
+
+import org.apache.tiles.request.collection.AddableParameterMap;
+import org.apache.tiles.request.portlet.extractor.StateAwareParameterExtractor;
+
+/**
+ * Exposes parameters getting them from a portlet reques and allowing to be put
+ * into a {@link StateAwareResponse}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareRequestDelegate implements RequestDelegate {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The response.
+ */
+ private StateAwareResponse response;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request.
+ * @param response The response.
+ */
+ public StateAwareRequestDelegate(PortletRequest request,
+ StateAwareResponse response) {
+ this.request = request;
+ this.response = response;
+ }
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request
+ * parameter name-value.</p>
+ */
+ private Map<String, String> param = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request
+ * parameter name-values.</p>
+ */
+ private Map<String, String[]> paramValues = null;
+
+ /** {@inheritDoc} */
+ public Map<String, String> getParam() {
+ if ((param == null) && (request != null)) {
+ param = new AddableParameterMap(new StateAwareParameterExtractor(
+ request, response));
+ }
+ return (param);
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getParamValues() {
+ if ((paramValues == null) && (request != null)) {
+ paramValues = new StateAwareParameterMap(request.getParameterMap(),
+ response.getRenderParameterMap());
+ }
+ return (paramValues);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegate.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegate.java
new file mode 100644
index 0000000..0130b01
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegate.java
@@ -0,0 +1,63 @@
+/*
+ * $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.request.portlet.delegate;
+
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+/**
+ * A state aware response does not allow to access to the output stream and similar,
+ * so it is, essentially, a feature blocker.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareResponseDelegate implements ResponseDelegate {
+
+ @Override
+ public OutputStream getOutputStream() {
+ throw new UnsupportedOperationException(
+ "No outputstream available for state-aware response");
+ }
+
+ @Override
+ public PrintWriter getPrintWriter() {
+ throw new UnsupportedOperationException(
+ "No outputstream available for state-aware response");
+ }
+
+ @Override
+ public Writer getWriter() {
+ throw new UnsupportedOperationException(
+ "No outputstream available for state-aware response");
+ }
+
+ @Override
+ public boolean isResponseCommitted() {
+ return false;
+ }
+
+ @Override
+ public void setContentType(String contentType) {
+ throw new UnsupportedOperationException(
+ "No outputstream available for state-aware response");
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java
new file mode 100644
index 0000000..5080dc3
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/delegate/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Delegations to map all the different types of request and responses.
+ */
+package org.apache.tiles.request.portlet.delegate;
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java
new file mode 100644
index 0000000..b167908
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractor.java
@@ -0,0 +1,69 @@
+/*
+ * $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.request.portlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extracts attributes from portlet application scope.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ApplicationScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The portlet context.
+ */
+ private PortletContext context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The portlet context.
+ */
+ public ApplicationScopeExtractor(PortletContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public void setValue(String name, Object value) {
+ context.setAttribute(name, value);
+ }
+
+ @Override
+ public void removeValue(String name) {
+ context.removeAttribute(name);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return context.getAttributeNames();
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return context.getAttribute(key);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java
new file mode 100644
index 0000000..52485d2
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/HeaderExtractor.java
@@ -0,0 +1,78 @@
+/*
+ * $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.request.portlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+
+import org.apache.tiles.request.attribute.EnumeratedValuesExtractor;
+
+/**
+ * Extracts and puts headers in portlet requests and responses.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderExtractor implements EnumeratedValuesExtractor {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The response.
+ */
+ private PortletResponse response;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request.
+ * @param response The response.
+ */
+ public HeaderExtractor(PortletRequest request,
+ PortletResponse response) {
+ this.request = request;
+ this.response = response;
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return request.getPropertyNames();
+ }
+
+ @Override
+ public String getValue(String key) {
+ return request.getProperty(key);
+ }
+
+ @Override
+ public Enumeration<String> getValues(String key) {
+ return request.getProperties(key);
+ }
+
+ @Override
+ public void setValue(String key, String value) {
+ response.setProperty(key, value);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java
new file mode 100644
index 0000000..dca552b
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractor.java
@@ -0,0 +1,60 @@
+/*
+ * $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.request.portlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.attribute.HasKeys;
+
+/**
+ * Extracts init parameters from a portlet context.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitParameterExtractor implements HasKeys<String> {
+
+ /**
+ * The portlet context.
+ */
+ private PortletContext context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The portlet context.
+ */
+ public InitParameterExtractor(PortletContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return context.getInitParameterNames();
+ }
+
+ @Override
+ public String getValue(String key) {
+ return context.getInitParameter(key);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java
new file mode 100644
index 0000000..3a95931
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/ParameterExtractor.java
@@ -0,0 +1,59 @@
+/*
+ * $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.request.portlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+
+import org.apache.tiles.request.attribute.HasKeys;
+
+/**
+ * Extracts parameters from a portlet request.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ParameterExtractor implements HasKeys<String> {
+
+ /**
+ * The portlet request.
+ */
+ private PortletRequest request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The portlet request.
+ */
+ public ParameterExtractor(PortletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return request.getParameterNames();
+ }
+
+ @Override
+ public String getValue(String key) {
+ return request.getParameter(key);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java
new file mode 100644
index 0000000..7b74cfa
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractor.java
@@ -0,0 +1,69 @@
+/*
+ * $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.request.portlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extracts attributes from request scope of a portlet request.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The portlet request.
+ */
+ private PortletRequest request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The portlet request.
+ */
+ public RequestScopeExtractor(PortletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public void setValue(String name, Object value) {
+ request.setAttribute(name, value);
+ }
+
+ @Override
+ public void removeValue(String name) {
+ request.removeAttribute(name);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return request.getAttributeNames();
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return request.getAttribute(key);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java
new file mode 100644
index 0000000..5f32ef5
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractor.java
@@ -0,0 +1,93 @@
+/*
+ * $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.request.portlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extracts attributes from the session scope of a portlet request.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The portlet request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The subscope (application or portlet).
+ */
+ private int scope;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request.
+ * @param scope The subscope (application or portlet).
+ */
+ public SessionScopeExtractor(PortletRequest request, int scope) {
+ this.request = request;
+ if (scope != PortletSession.APPLICATION_SCOPE
+ && scope != PortletSession.PORTLET_SCOPE) {
+ throw new IllegalArgumentException(
+ "The scope must be either APPLICATION_SCOPE or PORTLET_SCOPE");
+ }
+ this.scope = scope;
+ }
+
+ @Override
+ public void setValue(String name, Object value) {
+ request.getPortletSession().setAttribute(name, value, scope);
+ }
+
+ @Override
+ public void removeValue(String name) {
+ PortletSession session = request.getPortletSession(false);
+ if (session != null) {
+ session.removeAttribute(name, scope);
+ }
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ PortletSession session = request.getPortletSession(false);
+ if (session != null) {
+ return session.getAttributeNames(scope);
+ }
+ return null;
+ }
+
+ @Override
+ public Object getValue(String key) {
+ PortletSession session = request.getPortletSession(false);
+ if (session != null) {
+ return session.getAttribute(key, scope);
+ }
+ return null;
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
new file mode 100644
index 0000000..d1606c4
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractor.java
@@ -0,0 +1,55 @@
+/*
+ * $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.request.portlet.extractor;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.StateAwareResponse;
+
+import org.apache.tiles.request.attribute.HasAddableKeys;
+
+/**
+ * Extracts parameters from a request and allows putting render parameters in a state aware response.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareParameterExtractor extends ParameterExtractor implements HasAddableKeys<String> {
+
+ /**
+ * The portlet response.
+ */
+ private StateAwareResponse response;
+
+ /**
+ * Constructor.
+ *
+ * @param request The portlet request.
+ * @param response The portlet response.
+ */
+ public StateAwareParameterExtractor(PortletRequest request, StateAwareResponse response) {
+ super(request);
+ this.response = response;
+ }
+
+ @Override
+ public void setValue(String key, String value) {
+ response.setRenderParameter(key, value);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java
new file mode 100644
index 0000000..a37ccbb
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/extractor/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Extractors to get scopes from Portlet requests.
+ */
+package org.apache.tiles.request.portlet.extractor;
diff --git a/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/package-info.java b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/package-info.java
new file mode 100644
index 0000000..b9eb0d1
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/main/java/org/apache/tiles/request/portlet/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Support of Tiles requests to portlets.
+ */
+package org.apache.tiles.request.portlet;
diff --git a/tiles-request/tiles-request-portlet/src/site/site.xml b/tiles-request/tiles-request-portlet/src/site/site.xml
new file mode 100644
index 0000000..d52171a
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/ActionPortletRequestTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/ActionPortletRequestTest.java
new file mode 100644
index 0000000..629f45f
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/ActionPortletRequestTest.java
@@ -0,0 +1,72 @@
+/*
+ * $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.request.portlet;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Field;
+
+import javax.portlet.ActionRequest;
+import javax.portlet.ActionResponse;
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.StateAwareRequestDelegate;
+import org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate;
+import org.junit.Test;
+
+/**
+ * Tests {@link ActionPortletRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ActionPortletRequestTest {
+
+ /**
+ * Test method for
+ * {@link ActionPortletRequest#ActionPortletRequest(ApplicationContext,
+ * PortletContext, ActionRequest, ActionResponse)}.
+ * @throws NoSuchFieldException If something goes wrong.
+ * @throws SecurityException If something goes wrong.
+ * @throws IllegalAccessException If something goes wrong.
+ * @throws IllegalArgumentException If something goes wrong.
+ */
+ @Test
+ public void testActionPortletRequest() throws NoSuchFieldException,
+ IllegalAccessException {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ PortletContext portletContext = createMock(PortletContext.class);
+ ActionRequest request = createMock(ActionRequest.class);
+ ActionResponse response = createMock(ActionResponse.class);
+
+ replay(applicationContext, portletContext, request, response);
+ ActionPortletRequest req = new ActionPortletRequest(applicationContext,
+ portletContext, request, response);
+ Class<? extends ActionPortletRequest> clazz = req.getClass();
+ Field field = clazz.getSuperclass().getDeclaredField("requestDelegate");
+ assertTrue(field.get(req) instanceof StateAwareRequestDelegate);
+ field = clazz.getSuperclass().getDeclaredField("responseDelegate");
+ assertTrue(field.get(req) instanceof StateAwareResponseDelegate);
+ verify(applicationContext, portletContext, request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/EventPortletRequestTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/EventPortletRequestTest.java
new file mode 100644
index 0000000..998cb02
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/EventPortletRequestTest.java
@@ -0,0 +1,70 @@
+/*
+ * $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.request.portlet;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Field;
+
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.StateAwareRequestDelegate;
+import org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate;
+import org.junit.Test;
+
+/**
+ * Tests {@link EventPortletRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class EventPortletRequestTest {
+
+ /**
+ * Test method for
+ * {@link EventPortletRequest#EventPortletRequest(ApplicationContext, PortletContext, EventRequest, EventResponse)}.
+ * @throws NoSuchFieldException If something goes wrong.
+ * @throws SecurityException If something goes wrong.
+ * @throws IllegalAccessException If something goes wrong.
+ * @throws IllegalArgumentException If something goes wrong.
+ */
+ @Test
+ public void testEventPortletRequest() throws NoSuchFieldException, IllegalAccessException {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ PortletContext portletContext = createMock(PortletContext.class);
+ EventRequest request = createMock(EventRequest.class);
+ EventResponse response = createMock(EventResponse.class);
+
+ replay(applicationContext, portletContext, request, response);
+ EventPortletRequest req = new EventPortletRequest(applicationContext,
+ portletContext, request, response);
+ Class<? extends EventPortletRequest> clazz = req.getClass();
+ Field field = clazz.getSuperclass().getDeclaredField("requestDelegate");
+ assertTrue(field.get(req) instanceof StateAwareRequestDelegate);
+ field = clazz.getSuperclass().getDeclaredField("responseDelegate");
+ assertTrue(field.get(req) instanceof StateAwareResponseDelegate);
+ verify(applicationContext, portletContext, request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/PortletApplicationContextTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/PortletApplicationContextTest.java
new file mode 100644
index 0000000..0c0aad6
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/PortletApplicationContextTest.java
@@ -0,0 +1,151 @@
+/*
+ * $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.request.portlet;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Locale;
+
+import javax.portlet.PortletContext;
+
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link PortletApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PortletApplicationContextTest {
+
+ /**
+ * The portlet context.
+ */
+ private PortletContext portletContext;
+
+ /**
+ * The application context.
+ */
+ private PortletApplicationContext context;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ portletContext = createMock(PortletContext.class);
+ context = new PortletApplicationContext(portletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletApplicationContext#getContext()}.
+ */
+ @Test
+ public void testGetContext() {
+ replay(portletContext);
+ assertEquals(portletContext, context.getContext());
+ verify(portletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletApplicationContext#getPortletContext()}.
+ */
+ @Test
+ public void testGetPortletContext() {
+ replay(portletContext);
+ assertEquals(portletContext, context.getPortletContext());
+ verify(portletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletApplicationContext#getApplicationScope()}.
+ */
+ @Test
+ public void testGetApplicationScope() {
+ replay(portletContext);
+ assertTrue(context.getApplicationScope() instanceof ScopeMap);
+ verify(portletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletApplicationContext#getInitParams()}.
+ */
+ @Test
+ public void testGetInitParams() {
+ replay(portletContext);
+ assertTrue(context.getInitParams() instanceof ReadOnlyEnumerationMap);
+ verify(portletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletApplicationContext#getResource(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetResource() throws IOException {
+ URL url = new URL("file:///portletContext/my/path.html");
+ url = new URL(url.toExternalForm()); // normalize it
+ URL urlFr = new URL("file:///portletContext/my/path_fr.html");
+ urlFr = new URL(urlFr.toExternalForm()); // normalize it
+ expect(portletContext.getResource("/my/path.html")).andReturn(url);
+ expect(portletContext.getResource("/my/path_fr.html")).andReturn(urlFr);
+ expect(portletContext.getResource("/null/path.html")).andReturn(null);
+
+ replay(portletContext);
+ ApplicationResource resource = context.getResource("/my/path.html");
+ assertNotNull(resource);
+ assertEquals(resource.getLocalePath(), "/my/path.html");
+ assertEquals(resource.getPath(), "/my/path.html");
+ assertEquals(Locale.ROOT, resource.getLocale());
+ ApplicationResource resourceFr = context.getResource(resource, Locale.FRENCH);
+ assertNotNull(resourceFr);
+ assertEquals("/my/path_fr.html", resourceFr.getLocalePath());
+ assertEquals("/my/path.html", resourceFr.getPath());
+ assertEquals(Locale.FRENCH, resourceFr.getLocale());
+ ApplicationResource nullResource = context.getResource("/null/path.html");
+ assertNull(nullResource);
+ verify(portletContext);
+ }
+
+ /**
+ * Test method for {@link PortletApplicationContext#getResources(String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetResources() throws IOException {
+ URL url = new URL("file:///portletContext/my/path.html");
+ expect(portletContext.getResource("/my/path")).andReturn(url);
+
+ replay(portletContext);
+ Collection<ApplicationResource> resources = context.getResources("/my/path");
+ assertEquals(1, resources.size());
+ assertEquals(resources.iterator().next().getLocalePath(), "/my/path");
+ verify(portletContext);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java
new file mode 100644
index 0000000..f9d2581
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/PortletRequestTest.java
@@ -0,0 +1,430 @@
+/*
+ * $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.request.portlet;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.portlet.PortletContext;
+import javax.portlet.PortletException;
+import javax.portlet.PortletRequestDispatcher;
+import javax.portlet.PortletResponse;
+import javax.servlet.ServletOutputStream;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.collection.HeaderValuesMap;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.portlet.delegate.RequestDelegate;
+import org.apache.tiles.request.portlet.delegate.ResponseDelegate;
+import org.apache.tiles.request.portlet.extractor.HeaderExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link PortletRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PortletRequestTest {
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * The portlet context.
+ */
+ private PortletContext portletContext;
+
+ /**
+ * The request.
+ */
+ private javax.portlet.PortletRequest request;
+
+ /**
+ * The response.
+ */
+ private PortletResponse response;
+
+ /**
+ * The request to test.
+ */
+ private PortletRequest req;
+
+ /**
+ * The request delegate.
+ */
+ private RequestDelegate requestDelegate;
+
+ /**
+ * The response delegate.
+ */
+ private ResponseDelegate responseDelegate;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ applicationContext = createMock(ApplicationContext.class);
+ portletContext = createMock(PortletContext.class);
+ request = createMock(javax.portlet.PortletRequest.class);
+ response = createMock(PortletResponse.class);
+ requestDelegate = createMock(RequestDelegate.class);
+ responseDelegate = createMock(ResponseDelegate.class);
+ req = new PortletRequest(applicationContext, portletContext, request,
+ response, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws PortletException If something goes wrong.
+ */
+ @Test
+ public void testDoForward() throws PortletException, IOException {
+ PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+ expect(responseDelegate.isResponseCommitted()).andReturn(false);
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.forward(request, response);
+
+ replay(applicationContext, portletContext, request, response, rd);
+ req.doForward("/my/path");
+ verify(applicationContext, portletContext, request, response, rd);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoForwardNoDispatcher() throws IOException {
+ expect(responseDelegate.isResponseCommitted()).andReturn(false);
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null);
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ try {
+ req.doForward("/my/path");
+ } finally {
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws PortletException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoForwardPortletException() throws PortletException, IOException {
+ PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+ expect(responseDelegate.isResponseCommitted()).andReturn(false);
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.forward(request, response);
+ expectLastCall().andThrow(new PortletException());
+
+ replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ try {
+ req.doForward("/my/path");
+ } finally {
+ verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws PortletException If something goes wrong.
+ */
+ @Test
+ public void testDoForwardInclude() throws PortletException, IOException {
+ PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+ expect(responseDelegate.isResponseCommitted()).andReturn(true);
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.include(request, response);
+
+ replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ req.doForward("/my/path");
+ verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws PortletException If something goes wrong.
+ */
+ @Test
+ public void testDoInclude() throws IOException, PortletException {
+ PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.include(request, response);
+
+ replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ req.doInclude("/my/path");
+ verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludeNoDispatcher() throws IOException {
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(null);
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ try {
+ req.doInclude("/my/path");
+ } finally {
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws PortletException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludePortletException() throws IOException, PortletException {
+ PortletRequestDispatcher rd = createMock(PortletRequestDispatcher.class);
+
+ expect(portletContext.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.include(request, response);
+ expectLastCall().andThrow(new PortletException());
+
+ replay(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ try {
+ req.doInclude("/my/path");
+ } finally {
+ verify(applicationContext, request, response, rd, portletContext, requestDelegate, responseDelegate);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getHeader()}.
+ */
+ @Test
+ public void testGetHeader() {
+ assertTrue(req.getHeader() instanceof ReadOnlyEnumerationMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getResponseHeaders()}.
+ */
+ @Test
+ public void testGetResponseHeaders() {
+ assertTrue(req.getResponseHeaders() instanceof HeaderExtractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getHeaderValues()}.
+ */
+ @Test
+ public void testGetHeaderValues() {
+ assertTrue(req.getHeaderValues() instanceof HeaderValuesMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getParam()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParam() {
+ Map<String, String> map = createMock(Map.class);
+
+ expect(requestDelegate.getParam()).andReturn(map);
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ assertEquals(map, req.getParam());
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getParamValues()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParamValues() {
+ Map<String, String[]> paramMap = createMock(Map.class);
+
+ expect(requestDelegate.getParamValues()).andReturn(paramMap);
+
+ replay(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate);
+ assertEquals(paramMap, req.getParamValues());
+ verify(applicationContext, request, response, paramMap, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getRequestScope()}.
+ */
+ @Test
+ public void testGetRequestScope() {
+ assertTrue(req.getRequestScope() instanceof ScopeMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getSessionScope()}.
+ */
+ @Test
+ public void testGetSessionScope() {
+ assertTrue(req.getSessionScope() instanceof ScopeMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getPortletSessionScope()}.
+ */
+ @Test
+ public void testGetPortletSessionScope() {
+ assertTrue(req.getPortletSessionScope() instanceof ScopeMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getOutputStream()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetOutputStream() throws IOException {
+ ServletOutputStream os = createMock(ServletOutputStream.class);
+
+ expect(responseDelegate.getOutputStream()).andReturn(os);
+
+ replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+ assertEquals(req.getOutputStream(), os);
+ verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetWriter() throws IOException {
+ PrintWriter os = createMock(PrintWriter.class);
+
+ expect(responseDelegate.getWriter()).andReturn(os);
+
+ replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+ assertEquals(req.getWriter(), os);
+ verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getPrintWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetPrintWriter() throws IOException {
+ PrintWriter os = createMock(PrintWriter.class);
+
+ expect(responseDelegate.getPrintWriter()).andReturn(os);
+
+ replay(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+ assertEquals(req.getPrintWriter(), os);
+ verify(applicationContext, request, response, os, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#isResponseCommitted()}.
+ */
+ @Test
+ public void testIsResponseCommitted() {
+ expect(responseDelegate.isResponseCommitted()).andReturn(true);
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ assertTrue(req.isResponseCommitted());
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#setContentType(java.lang.String)}.
+ */
+ @Test
+ public void testSetContentType() {
+ responseDelegate.setContentType("text/html");
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ req.setContentType("text/html");
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getRequestLocale()}.
+ */
+ @Test
+ public void testGetRequestLocale() {
+ Locale locale = Locale.ITALY;
+
+ expect(request.getLocale()).andReturn(locale);
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ assertEquals(locale, req.getRequestLocale());
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getRequestObjects()}.
+ */
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getRequest()}.
+ */
+ @Test
+ public void testGetRequest() {
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ assertEquals(request, req.getRequest());
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#getResponse()}.
+ */
+ @Test
+ public void testGetResponse() {
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ assertEquals(response, req.getResponse());
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.PortletRequest#isUserInRole(java.lang.String)}.
+ */
+ @Test
+ public void testIsUserInRole() {
+ expect(request.isUserInRole("myrole")).andReturn(true);
+
+ replay(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ assertTrue(req.isUserInRole("myrole"));
+ verify(applicationContext, request, response, portletContext, requestDelegate, responseDelegate);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java
new file mode 100644
index 0000000..b88983f
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/RenderPortletRequestTest.java
@@ -0,0 +1,71 @@
+/*
+ * $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.request.portlet;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Field;
+
+import javax.portlet.PortletContext;
+import javax.portlet.RenderRequest;
+import javax.portlet.RenderResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate;
+import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate;
+import org.junit.Test;
+
+/**
+ * Tests {@link RenderPortletRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RenderPortletRequestTest {
+
+ /**
+ * Test method for
+ * {@link RenderPortletRequest#RenderPortletRequest(ApplicationContext, PortletContext,
+ * RenderRequest, RenderResponse)}.
+ * @throws NoSuchFieldException If something goes wrong.
+ * @throws SecurityException If something goes wrong.
+ * @throws IllegalAccessException If something goes wrong.
+ * @throws IllegalArgumentException If something goes wrong.
+ */
+ @Test
+ public void testRenderPortletRequest() throws NoSuchFieldException, IllegalAccessException {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ PortletContext portletContext = createMock(PortletContext.class);
+ RenderRequest request = createMock(RenderRequest.class);
+ RenderResponse response = createMock(RenderResponse.class);
+
+ replay(applicationContext, portletContext, request, response);
+ RenderPortletRequest req = new RenderPortletRequest(applicationContext,
+ portletContext, request, response);
+ Class<? extends RenderPortletRequest> clazz = req.getClass();
+ Field field = clazz.getSuperclass().getDeclaredField("requestDelegate");
+ assertTrue(field.get(req) instanceof PortletRequestDelegate);
+ field = clazz.getSuperclass().getDeclaredField("responseDelegate");
+ assertTrue(field.get(req) instanceof MimeResponseDelegate);
+ verify(applicationContext, portletContext, request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/ResourcePortletRequestTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/ResourcePortletRequestTest.java
new file mode 100644
index 0000000..130cb5d
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/ResourcePortletRequestTest.java
@@ -0,0 +1,71 @@
+/*
+ * $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.request.portlet;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.Field;
+
+import javax.portlet.PortletContext;
+import javax.portlet.ResourceRequest;
+import javax.portlet.ResourceResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.portlet.delegate.MimeResponseDelegate;
+import org.apache.tiles.request.portlet.delegate.PortletRequestDelegate;
+import org.junit.Test;
+
+/**
+ * Tests {@link ResourcePortletRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourcePortletRequestTest {
+
+ /**
+ * Test method for
+ * {@link ResourcePortletRequest#ResourcePortletRequest(ApplicationContext, PortletContext,
+ * ResourceRequest, ResourceResponse)}.
+ * @throws NoSuchFieldException If something goes wrong.
+ * @throws SecurityException If something goes wrong.
+ * @throws IllegalAccessException If something goes wrong.
+ * @throws IllegalArgumentException If something goes wrong.
+ */
+ @Test
+ public void testResourcePortletRequest() throws NoSuchFieldException, IllegalAccessException {
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+ PortletContext portletContext = createMock(PortletContext.class);
+ ResourceRequest request = createMock(ResourceRequest.class);
+ ResourceResponse response = createMock(ResourceResponse.class);
+
+ replay(applicationContext, portletContext, request, response);
+ ResourcePortletRequest req = new ResourcePortletRequest(applicationContext,
+ portletContext, request, response);
+ Class<? extends ResourcePortletRequest> clazz = req.getClass();
+ Field field = clazz.getSuperclass().getDeclaredField("requestDelegate");
+ assertTrue(field.get(req) instanceof PortletRequestDelegate);
+ field = clazz.getSuperclass().getDeclaredField("responseDelegate");
+ assertTrue(field.get(req) instanceof MimeResponseDelegate);
+ verify(applicationContext, portletContext, request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java
new file mode 100644
index 0000000..f16525f
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/MimeResponseDelegateTest.java
@@ -0,0 +1,130 @@
+/*
+ * $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.request.portlet.delegate;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import javax.portlet.MimeResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link MimeResponseDelegate}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class MimeResponseDelegateTest {
+
+ /**
+ * The response.
+ */
+ private MimeResponse response;
+
+ /**
+ * The delegate to test.
+ */
+ private MimeResponseDelegate delegate;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ response = createMock(MimeResponse.class);
+ delegate = new MimeResponseDelegate(response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.MimeResponseDelegate#getOutputStream()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetOutputStream() throws IOException {
+ OutputStream os = createMock(OutputStream.class);
+
+ expect(response.getPortletOutputStream()).andReturn(os);
+
+ replay(response, os);
+ assertEquals(os, delegate.getOutputStream());
+ verify(response, os);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.MimeResponseDelegate#getPrintWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetPrintWriter() throws IOException {
+ PrintWriter os = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(os);
+
+ replay(response, os);
+ assertEquals(os, delegate.getPrintWriter());
+ verify(response, os);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.MimeResponseDelegate#getWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetWriter() throws IOException {
+ PrintWriter os = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(os);
+
+ replay(response, os);
+ assertEquals(os, delegate.getWriter());
+ verify(response, os);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.MimeResponseDelegate#isResponseCommitted()}.
+ */
+ @Test
+ public void testIsResponseCommitted() {
+ expect(response.isCommitted()).andReturn(true);
+
+ replay(response);
+ assertTrue(delegate.isResponseCommitted());
+ verify(response);
+ }
+
+ /**
+ * Test method for {@link MimeResponseDelegate#setContentType(String)}.
+ */
+ @Test
+ public void testSetContentType() {
+ response.setContentType("text/html");
+
+ replay(response);
+ delegate.setContentType("text/html");
+ verify(response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java
new file mode 100644
index 0000000..14da05c
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/PortletRequestDelegateTest.java
@@ -0,0 +1,85 @@
+/*
+ * $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.request.portlet.delegate;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Map;
+
+import javax.portlet.PortletRequest;
+
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link PortletRequestDelegate}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class PortletRequestDelegateTest {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The delegate to test.
+ */
+ private PortletRequestDelegate delegate;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(PortletRequest.class);
+ delegate = new PortletRequestDelegate(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.PortletRequestDelegate#getParam()}.
+ */
+ @Test
+ public void testGetParam() {
+ replay(request);
+ assertTrue(delegate.getParam() instanceof ReadOnlyEnumerationMap);
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.PortletRequestDelegate#getParamValues()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParamValues() {
+ Map<String, String[]> params = createMock(Map.class);
+
+ expect(request.getParameterMap()).andReturn(params);
+
+ replay(request, params);
+ assertEquals(params, delegate.getParamValues());
+ verify(request, params);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMapTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMapTest.java
new file mode 100644
index 0000000..2439b44
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareParameterMapTest.java
@@ -0,0 +1,226 @@
+/*
+ * $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.request.portlet.delegate;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link StateAwareParameterMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareParameterMapTest {
+
+ /**
+ * The request map.
+ */
+ private Map<String, String[]> requestMap;
+
+ /**
+ * The response map.
+ */
+ private Map<String, String[]> responseMap;
+
+ /**
+ * The map to test.
+ */
+ private StateAwareParameterMap map;
+
+ /**
+ * Sets up the test.
+ */
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ requestMap = createMock(Map.class);
+ responseMap = createMock(Map.class);
+ map = new StateAwareParameterMap(requestMap, responseMap);
+
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#clear()}.
+ */
+ @Test
+ public void testClear() {
+ responseMap.clear();
+
+ replay(requestMap, responseMap);
+ map.clear();
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link StateAwareParameterMap#containsKey(Object)}.
+ */
+ @Test
+ public void testContainsKey() {
+ expect(requestMap.containsKey("key")).andReturn(true);
+
+ replay(requestMap, responseMap);
+ assertTrue(map.containsKey("key"));
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link StateAwareParameterMap#containsValue(Object)}.
+ */
+ @Test
+ public void testContainsValue() {
+ String[] values = new String[] {"value1", "value2"};
+ expect(requestMap.containsValue(values)).andReturn(true);
+
+ replay(requestMap, responseMap);
+ assertTrue(map.containsValue(values));
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#entrySet()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testEntrySet() {
+ Set<Map.Entry<String, String[]>> entrySet = createMock(Set.class);
+
+ expect(requestMap.entrySet()).andReturn(entrySet);
+
+ replay(requestMap, responseMap, entrySet);
+ assertEquals(entrySet, map.entrySet());
+ verify(requestMap, responseMap, entrySet);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#get(java.lang.Object)}.
+ */
+ @Test
+ public void testGet() {
+ String[] values = new String[] {"value1", "value2"};
+ expect(requestMap.get("key")).andReturn(values);
+
+ replay(requestMap, responseMap);
+ assertArrayEquals(values, map.get("key"));
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#isEmpty()}.
+ */
+ @Test
+ public void testIsEmpty() {
+ expect(requestMap.isEmpty()).andReturn(false);
+
+ replay(requestMap, responseMap);
+ assertFalse(map.isEmpty());
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#keySet()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testKeySet() {
+ Set<String> keySet = createMock(Set.class);
+
+ expect(requestMap.keySet()).andReturn(keySet);
+
+ replay(requestMap, responseMap, keySet);
+ assertEquals(keySet, map.keySet());
+ verify(requestMap, responseMap, keySet);
+ }
+
+ /**
+ * Test method for {@link StateAwareParameterMap#put(String, String[])}.
+ */
+ @Test
+ public void testPut() {
+ String[] values = new String[] {"value1", "value2"};
+ expect(responseMap.put(eq("key"), aryEq(values))).andReturn(null);
+
+ replay(requestMap, responseMap);
+ assertNull(map.put("key", values));
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#putAll(java.util.Map)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testPutAll() {
+ Map<String, String[]> entries = createMock(Map.class);
+ responseMap.putAll(entries);
+
+ replay(requestMap, responseMap, entries);
+ map.putAll(entries);
+ verify(requestMap, responseMap, entries);
+ }
+
+ /**
+ * Test method for {@link StateAwareParameterMap#remove(Object)}.
+ */
+ @Test
+ public void testRemove() {
+ String[] values = new String[] {"value1", "value2"};
+ expect(responseMap.remove("key")).andReturn(values);
+
+ replay(requestMap, responseMap);
+ assertArrayEquals(values, map.remove("key"));
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#size()}.
+ */
+ @Test
+ public void testSize() {
+ expect(requestMap.size()).andReturn(1);
+
+ replay(requestMap, responseMap);
+ assertEquals(1, map.size());
+ verify(requestMap, responseMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareParameterMap#values()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testValues() {
+ Collection<String[]> values = createMock(Collection.class);
+
+ expect(requestMap.values()).andReturn(values);
+
+ replay(requestMap, responseMap, values);
+ assertEquals(values, map.values());
+ verify(requestMap, responseMap, values);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegateTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegateTest.java
new file mode 100644
index 0000000..a9ba958
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareRequestDelegateTest.java
@@ -0,0 +1,94 @@
+/*
+ * $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.request.portlet.delegate;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Map;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.StateAwareResponse;
+
+import org.apache.tiles.request.collection.AddableParameterMap;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link StateAwareRequestDelegate}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareRequestDelegateTest {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The response.
+ */
+ private StateAwareResponse response;
+
+ /**
+ * The delegate to test.
+ */
+ private StateAwareRequestDelegate delegate;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(PortletRequest.class);
+ response = createMock(StateAwareResponse.class);
+ delegate = new StateAwareRequestDelegate(request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareRequestDelegate#getParam()}.
+ */
+ @Test
+ public void testGetParam() {
+ replay(request);
+ assertTrue(delegate.getParam() instanceof AddableParameterMap);
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareRequestDelegate#getParamValues()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParamValues() {
+ Map<String, String[]> requestMap = createMock(Map.class);
+ Map<String, String[]> responseMap = createMock(Map.class);
+
+ expect(request.getParameterMap()).andReturn(requestMap);
+ expect(response.getRenderParameterMap()).andReturn(responseMap);
+
+ replay(request);
+ assertTrue(delegate.getParamValues() instanceof StateAwareParameterMap);
+ verify(request);
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegateTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegateTest.java
new file mode 100644
index 0000000..d8a6b0d
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/delegate/StateAwareResponseDelegateTest.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request.portlet.delegate;
+
+import static org.junit.Assert.*;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link StateAwareResponseDelegate}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareResponseDelegateTest {
+
+ /**
+ * The delegate to test.
+ */
+ private StateAwareResponseDelegate delegate;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ delegate = new StateAwareResponseDelegate();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate#getOutputStream()}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetOutputStream() {
+ delegate.getOutputStream();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate#getPrintWriter()}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetPrintWriter() {
+ delegate.getPrintWriter();
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.delegate.StateAwareResponseDelegate#getWriter()}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testGetWriter() {
+ delegate.getWriter();
+ }
+
+ /**
+ * Test method for {@link StateAwareResponseDelegate#isResponseCommitted()}.
+ */
+ @Test
+ public void testIsResponseCommitted() {
+ assertFalse(delegate.isResponseCommitted());
+ }
+
+ /**
+ * Test method for {@link StateAwareResponseDelegate#setContentType(java.lang.String)}.
+ */
+ @Test(expected = UnsupportedOperationException.class)
+ public void testSetContentType() {
+ delegate.setContentType("text/html");
+ }
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java
new file mode 100644
index 0000000..2378b45
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/ApplicationScopeExtractorTest.java
@@ -0,0 +1,110 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletContext;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ApplicationScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ApplicationScopeExtractorTest {
+
+ /**
+ * The portlet context.
+ */
+ private PortletContext context;
+
+ /**
+ * The extractot to test.
+ */
+ private ApplicationScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ context = createMock(PortletContext.class);
+ extractor = new ApplicationScopeExtractor(context);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#setValue(java.lang.String, java.lang.Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ context.setAttribute("attribute", "value");
+
+ replay(context);
+ extractor.setValue("attribute", "value");
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ context.removeAttribute("attribute");
+
+ replay(context);
+ extractor.removeValue("attribute");
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ expect(context.getAttributeNames()).andReturn(keys);
+
+ replay(context, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(context, keys);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(context.getAttribute("attribute")).andReturn("value");
+
+ replay(context);
+ assertEquals("value", extractor.getValue("attribute"));
+ verify(context);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java
new file mode 100644
index 0000000..3d81ce5
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/HeaderExtractorTest.java
@@ -0,0 +1,121 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link HeaderExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderExtractorTest {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The response.
+ */
+ private PortletResponse response;
+
+ /**
+ * The extractor to test.
+ */
+ private HeaderExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(PortletRequest.class);
+ response = createMock(PortletResponse.class);
+ extractor = new HeaderExtractor(request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.HeaderExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getPropertyNames()).andReturn(keys);
+
+ replay(request, response, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, response, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.HeaderExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getProperty("name")).andReturn("value");
+
+ replay(request, response);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.HeaderExtractor#getValues(java.lang.String)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetValues() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getProperties("name")).andReturn(keys);
+
+ replay(request, response, keys);
+ assertEquals(keys, extractor.getValues("name"));
+ verify(request, response, keys);
+ }
+
+ /**
+ * Test method for {@link HeaderExtractor#setValue(String, String)}.
+ */
+ @Test
+ public void testSetValue() {
+ response.setProperty("name", "value");
+
+ replay(request, response);
+ extractor.setValue("name", "value");
+ verify(request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java
new file mode 100644
index 0000000..4480080
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/InitParameterExtractorTest.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletContext;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link InitParameterExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitParameterExtractorTest {
+
+ /**
+ * The portlet context.
+ */
+ private PortletContext context;
+
+ /**
+ * The extractor to test.
+ */
+ private InitParameterExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ context = createMock(PortletContext.class);
+ extractor = new InitParameterExtractor(context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.InitParameterExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(context.getInitParameterNames()).andReturn(keys);
+
+ replay(context, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(context, keys);
+ }
+
+ /**
+ * Test method for {@link InitParameterExtractor#getValue(String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(context.getInitParameter("name")).andReturn("value");
+
+ replay(context);
+ assertEquals("value", extractor.getValue("name"));
+ verify(context);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java
new file mode 100644
index 0000000..dcb9bac
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/ParameterExtractorTest.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ParameterExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ParameterExtractorTest {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The extractor to test.
+ */
+ private ParameterExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(PortletRequest.class);
+ extractor = new ParameterExtractor(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.ParameterExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getParameterNames()).andReturn(keys);
+
+ replay(request, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.ParameterExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getParameter("name")).andReturn("value");
+
+ replay(request);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java
new file mode 100644
index 0000000..d922acd
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/RequestScopeExtractorTest.java
@@ -0,0 +1,111 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link RequestScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeExtractorTest {
+
+ /**
+ * The request to test.
+ */
+ private PortletRequest request;
+
+ /**
+ * The extractor to test.
+ */
+ private RequestScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(PortletRequest.class);
+ extractor = new RequestScopeExtractor(request);
+ }
+
+ /**
+ * Test method for {@link RequestScopeExtractor#setValue(String, Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ request.setAttribute("name", "value");
+
+ replay(request);
+ extractor.setValue("name", "value");
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link RequestScopeExtractor#removeValue(String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ request.removeAttribute("name");
+
+ replay(request);
+ extractor.removeValue("name");
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.portlet.extractor.RequestScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getAttributeNames()).andReturn(keys);
+
+ replay(request, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, keys);
+ }
+
+ /**
+ * Test method for {@link RequestScopeExtractor#getValue(String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getAttribute("name")).andReturn("value");
+
+ replay(request);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java
new file mode 100644
index 0000000..85c6eb6
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/SessionScopeExtractorTest.java
@@ -0,0 +1,157 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link SessionScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionScopeExtractorTest {
+
+ /**
+ * The request.
+ */
+ private PortletRequest request;
+
+ /**
+ * The session.
+ */
+ private PortletSession session;
+
+ /**
+ * The scope to test.
+ */
+ private SessionScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(PortletRequest.class);
+ session = createMock(PortletSession.class);
+ extractor = new SessionScopeExtractor(request, PortletSession.PORTLET_SCOPE);
+ }
+
+
+ /**
+ * Tests {@link SessionScopeExtractor#SessionScopeExtractor(PortletRequest, int)}.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testIllegalScope() {
+ replay(request, session);
+ new SessionScopeExtractor(request, 0);
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#setValue(java.lang.String, java.lang.Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ expect(request.getPortletSession()).andReturn(session);
+ session.setAttribute("name", "value", PortletSession.PORTLET_SCOPE);
+
+ replay(request, session);
+ extractor.setValue("name", "value");
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ expect(request.getPortletSession(false)).andReturn(session);
+ session.removeAttribute("name", PortletSession.PORTLET_SCOPE);
+
+ replay(request, session);
+ extractor.removeValue("name");
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getPortletSession(false)).andReturn(session);
+ expect(session.getAttributeNames(PortletSession.PORTLET_SCOPE)).andReturn(keys);
+
+ replay(request, session, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, session, keys);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getKeys()}.
+ */
+ @Test
+ public void testGetKeysNoSession() {
+ expect(request.getPortletSession(false)).andReturn(null);
+
+ replay(request, session);
+ assertNull(extractor.getKeys());
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getPortletSession(false)).andReturn(session);
+ expect(session.getAttribute("name", PortletSession.PORTLET_SCOPE)).andReturn("value");
+
+ replay(request, session);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValueNoSession() {
+ expect(request.getPortletSession(false)).andReturn(null);
+
+ replay(request, session);
+ assertNull(extractor.getValue("name"));
+ verify(request, session);
+ }
+
+}
diff --git a/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java
new file mode 100644
index 0000000..331040e
--- /dev/null
+++ b/tiles-request/tiles-request-portlet/src/test/java/org/apache/tiles/request/portlet/extractor/StateAwareParameterExtractorTest.java
@@ -0,0 +1,53 @@
+/*
+ * $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.request.portlet.extractor;
+
+import static org.easymock.classextension.EasyMock.*;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.StateAwareResponse;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link StateAwareParameterExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StateAwareParameterExtractorTest {
+
+ /**
+ * Test method for {@link StateAwareParameterExtractor#setValue(String, String)}.
+ */
+ @Test
+ public void testSetValue() {
+ PortletRequest request = createMock(PortletRequest.class);
+ StateAwareResponse response = createMock(StateAwareResponse.class);
+
+ response.setRenderParameter("name", "value");
+
+ replay(request, response);
+ StateAwareParameterExtractor extractor = new StateAwareParameterExtractor(request, response);
+ extractor.setValue("name", "value");
+ verify(request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet-wildcard/pom.xml b/tiles-request/tiles-request-servlet-wildcard/pom.xml
new file mode 100644
index 0000000..a7ede2d
--- /dev/null
+++ b/tiles-request/tiles-request-servlet-wildcard/pom.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<!--
+/*
+ * $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.
+ */
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>tiles-request-servlet-wildcard</artifactId>
+ <packaging>jar</packaging>
+ <name>Tiles Request - Wildcard file loading in Servlets</name>
+ <description>Wildcard file loading in Servlets: Allows to load resources using wildcards.</description>
+
+ <properties>
+ <tiles.osgi.symbolicName>org.apache.tiles.servlet.wildcard</tiles.osgi.symbolicName>
+ </properties>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <excludes>
+ <exclude>LICENSE.txt</exclude>
+ <exclude>NOTICE.txt</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ </includes>
+ <targetPath>META-INF</targetPath>
+ </resource>
+ </resources>
+
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/tiles-request/tiles-request-servlet-wildcard/src/main/java/org/apache/tiles/request/servlet/wildcard/WildcardServletApplicationContext.java b/tiles-request/tiles-request-servlet-wildcard/src/main/java/org/apache/tiles/request/servlet/wildcard/WildcardServletApplicationContext.java
new file mode 100644
index 0000000..359d9b2
--- /dev/null
+++ b/tiles-request/tiles-request-servlet-wildcard/src/main/java/org/apache/tiles/request/servlet/wildcard/WildcardServletApplicationContext.java
@@ -0,0 +1,109 @@
+/*
+ * $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.request.servlet.wildcard;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Locale;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.locale.URLApplicationResource;
+import org.apache.tiles.request.servlet.ServletApplicationContext;
+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$
+ */
+public class WildcardServletApplicationContext extends ServletApplicationContext {
+
+ /**
+ * The pattern resolver.
+ */
+ protected ResourcePatternResolver resolver;
+
+ /**
+ * Constructor.
+ *
+ * @param servletContext The servlet context.
+ */
+ public WildcardServletApplicationContext(ServletContext servletContext) {
+ super(servletContext);
+ resolver = new ServletContextResourcePatternResolver(servletContext);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ApplicationResource getResource(String localePath) {
+ ApplicationResource retValue = null;
+ Collection<ApplicationResource> urlSet = getResources(localePath);
+ if (urlSet != null && !urlSet.isEmpty()) {
+ retValue = urlSet.iterator().next();
+ }
+ return retValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ApplicationResource getResource(ApplicationResource base, Locale locale) {
+ ApplicationResource retValue = null;
+ Collection<ApplicationResource> urlSet = getResources(base.getLocalePath(locale));
+ if (urlSet != null && !urlSet.isEmpty()) {
+ retValue = urlSet.iterator().next();
+ }
+ return retValue;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Collection<ApplicationResource> getResources(String path) {
+ Resource[] resources;
+ try {
+ resources = resolver.getResources(path);
+ } catch (IOException e) {
+ return Collections.<ApplicationResource> emptyList();
+ }
+ Collection<ApplicationResource> resourceList = new ArrayList<ApplicationResource>();
+ if (resources != null && resources.length > 0) {
+ for (int i = 0; i < resources.length; i++) {
+ URL url;
+ try {
+ url = resources[i].getURL();
+ resourceList.add(new URLApplicationResource(url.toExternalForm(), url));
+ } catch (IOException e) {
+ // shouldn't happen with the kind of resources we're using
+ throw new IllegalArgumentException("no URL for " + resources[i].toString(), e);
+ }
+ }
+ }
+ return resourceList;
+ }
+}
diff --git a/tiles-request/tiles-request-servlet-wildcard/src/main/java/org/apache/tiles/request/servlet/wildcard/package-info.java b/tiles-request/tiles-request-servlet-wildcard/src/main/java/org/apache/tiles/request/servlet/wildcard/package-info.java
new file mode 100644
index 0000000..105a6d8
--- /dev/null
+++ b/tiles-request/tiles-request-servlet-wildcard/src/main/java/org/apache/tiles/request/servlet/wildcard/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * 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.
+ */
+package org.apache.tiles.request.servlet.wildcard;
diff --git a/tiles-request/tiles-request-servlet-wildcard/src/site/site.xml b/tiles-request/tiles-request-servlet-wildcard/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-servlet-wildcard/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-servlet-wildcard/src/test/java/org/apache/tiles/request/servlet/wildcard/WildcardServletApplicationContextTest.java b/tiles-request/tiles-request-servlet-wildcard/src/test/java/org/apache/tiles/request/servlet/wildcard/WildcardServletApplicationContextTest.java
new file mode 100644
index 0000000..1b4cd77
--- /dev/null
+++ b/tiles-request/tiles-request-servlet-wildcard/src/test/java/org/apache/tiles/request/servlet/wildcard/WildcardServletApplicationContextTest.java
@@ -0,0 +1,155 @@
+/*
+ * $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.request.servlet.wildcard;
+
+import junit.framework.TestCase;
+
+import org.apache.tiles.request.locale.URLApplicationResource;
+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 WildcardServletApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class WildcardServletApplicationContextTest 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 WildcardServletApplicationContext 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 WildcardServletApplicationContext(servletContext);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void tearDown() {
+ 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(new URLApplicationResource(u.toExternalForm(), u), context.getResource(url));
+ assertEquals(new URLApplicationResource(pomUrl.toExternalForm(), pomUrl), context.getResource("/WEB-INF/*.xml"));
+ assertEquals(TEST_PROPERTIES_SIZE, context.getResources(
+ "classpath*:/test.properties").size());
+
+ assertEquals(1, context.getResources(
+ "classpath*:/org/apache/tiles/request/servlet/wildcard/*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-request/tiles-request-servlet/pom.xml b/tiles-request/tiles-request-servlet/pom.xml
new file mode 100644
index 0000000..24b457c
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-request</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles request - Servlet support</name>
+ <description>Tiles request implementation for Servlet technology.</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shale</groupId>
+ <artifactId>shale-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java
new file mode 100644
index 0000000..66c2cdb
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponse.java
@@ -0,0 +1,58 @@
+/*
+ * $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.request.servlet;
+
+import java.io.PrintWriter;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+/**
+ * Wraps an HTTP response and overrides its print writer.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExternalWriterHttpServletResponse extends
+ HttpServletResponseWrapper {
+
+ /**
+ * The print writer to use, instead of the response's one.
+ */
+ private PrintWriter writer;
+
+ /**
+ * Constructor.
+ *
+ * @param response The response to wrap.
+ * @param writer The print writer to use, instead of the response's one.
+ */
+ public ExternalWriterHttpServletResponse(HttpServletResponse response, PrintWriter writer) {
+ super(response);
+ this.writer = writer;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter getWriter() {
+ return writer;
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java
new file mode 100644
index 0000000..3b13425
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/NotAServletEnvironmentException.java
@@ -0,0 +1,67 @@
+/*
+ * $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.request.servlet;
+
+
+/**
+ * Exception that indicates that a resource could not be used because it is not
+ * in a servlet environment.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotAServletEnvironmentException extends RuntimeException {
+
+ /**
+ * Constructor.
+ */
+ public NotAServletEnvironmentException() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ */
+ public NotAServletEnvironmentException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param e The exception to be wrapped.
+ */
+ public NotAServletEnvironmentException(Throwable e) {
+ super(e);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message The detail message.
+ * @param e The exception to be wrapped.
+ */
+ public NotAServletEnvironmentException(String message, Throwable e) {
+ super(message, e);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java
new file mode 100644
index 0000000..e841cc3
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletApplicationContext.java
@@ -0,0 +1,132 @@
+/*
+ * $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.request.servlet;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.locale.URLApplicationResource;
+import org.apache.tiles.request.servlet.extractor.ApplicationScopeExtractor;
+import org.apache.tiles.request.servlet.extractor.InitParameterExtractor;
+
+/**
+ * Servlet-based implementation of the TilesApplicationContext interface.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServletApplicationContext implements ApplicationContext {
+
+ /**
+ * The servlet context to use.
+ */
+ private ServletContext servletContext;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of application scope
+ * attributes.</p>
+ */
+ private Map<String, Object> applicationScope = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of context initialization
+ * parameters.</p>
+ */
+ private Map<String, String> initParam = null;
+
+ /**
+ * Creates a new instance of ServletTilesApplicationContext.
+ *
+ * @param servletContext The servlet context to use.
+ */
+ public ServletApplicationContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ /** {@inheritDoc} */
+ public Object getContext() {
+ return servletContext;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getApplicationScope() {
+
+ if ((applicationScope == null) && (servletContext != null)) {
+ applicationScope = new ScopeMap(new ApplicationScopeExtractor(servletContext));
+ }
+ return (applicationScope);
+
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getInitParams() {
+
+ if ((initParam == null) && (servletContext != null)) {
+ initParam = new ReadOnlyEnumerationMap<String>(new InitParameterExtractor(servletContext));
+ }
+ return (initParam);
+
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationResource getResource(String localePath) {
+ try {
+ URL url = servletContext.getResource(localePath);
+ if (url != null) {
+ return new URLApplicationResource(localePath, url);
+ } else {
+ return null;
+ }
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public ApplicationResource getResource(ApplicationResource base, Locale locale) {
+ try {
+ URL url = servletContext.getResource(base.getLocalePath(locale));
+ if (url != null) {
+ return new URLApplicationResource(base.getPath(), locale, url);
+ } else {
+ return null;
+ }
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public Collection<ApplicationResource> getResources(String path) {
+ ArrayList<ApplicationResource> resources = new ArrayList<ApplicationResource>();
+ resources.add(getResource(path));
+ return resources;
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java
new file mode 100644
index 0000000..d03809a
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletRequest.java
@@ -0,0 +1,320 @@
+/*
+ * $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.request.servlet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.AbstractClientRequest;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.attribute.Addable;
+import org.apache.tiles.request.collection.HeaderValuesMap;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.servlet.extractor.ParameterExtractor;
+import org.apache.tiles.request.servlet.extractor.RequestScopeExtractor;
+import org.apache.tiles.request.servlet.extractor.HeaderExtractor;
+import org.apache.tiles.request.servlet.extractor.SessionScopeExtractor;
+
+/**
+ * Servlet-based implementation of the TilesApplicationContext interface.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServletRequest extends AbstractClientRequest {
+
+ /**
+ * The native available scopes: request, session and application.
+ */
+ private static final List<String> SCOPES
+ = Collections.unmodifiableList(Arrays.asList("request", "session", "application"));
+
+ /**
+ * The request object to use.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The response object to use.
+ */
+ private HttpServletResponse response;
+
+ /**
+ * The response output stream, lazily initialized.
+ */
+ private OutputStream outputStream;
+
+ /**
+ * The response writer, lazily initialized.
+ */
+ private PrintWriter writer;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of header name-value
+ * combinations (immutable).</p>
+ */
+ private Map<String, String> header = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of header name-value
+ * combinations (write-only).</p>
+ */
+ private Addable<String> responseHeaders = null;
+
+
+ /**
+ * <p>The lazily instantitated <code>Map</code> of header name-values
+ * combinations (immutable).</p>
+ */
+ private Map<String, String[]> headerValues = null;
+
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request
+ * parameter name-value.</p>
+ */
+ private Map<String, String> param = null;
+
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of request scope
+ * attributes.</p>
+ */
+ private Map<String, Object> requestScope = null;
+
+ /**
+ * <p>The lazily instantiated <code>Map</code> of session scope
+ * attributes.</p>
+ */
+ private Map<String, Object> sessionScope = null;
+
+
+ /**
+ * Creates a new instance of ServletTilesRequestContext.
+ *
+ * @param applicationContext The application context.
+ * @param request The request object.
+ * @param response The response object.
+ */
+ public ServletRequest(
+ ApplicationContext applicationContext,
+ HttpServletRequest request, HttpServletResponse response) {
+ super(applicationContext);
+ this.request = request;
+ this.response = response;
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String> getHeader() {
+
+ if ((header == null) && (request != null)) {
+ header = new ReadOnlyEnumerationMap<String>(new HeaderExtractor(request, null));
+ }
+ return (header);
+
+ }
+
+ /** {@inheritDoc} */
+ public Addable<String> getResponseHeaders() {
+
+ if ((responseHeaders == null) && (response != null)) {
+ responseHeaders = new HeaderExtractor(null, response);
+ }
+ return (responseHeaders);
+
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, String[]> getHeaderValues() {
+
+ if ((headerValues == null) && (request != null)) {
+ headerValues = new HeaderValuesMap(new HeaderExtractor(request, response));
+ }
+ return (headerValues);
+
+ }
+
+
+ /** {@inheritDoc} */
+ public Map<String, String> getParam() {
+
+ if ((param == null) && (request != null)) {
+ param = new ReadOnlyEnumerationMap<String>(new ParameterExtractor(request));
+ }
+ return (param);
+
+ }
+
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
+ public Map<String, String[]> getParamValues() {
+ return request.getParameterMap();
+ }
+
+ @Override
+ public Map<String, Object> getContext(String scope) {
+ if("request".equals(scope)){
+ return getRequestScope();
+ }else if("session".equals(scope)){
+ return getSessionScope();
+ }else if("application".equals(scope)){
+ return getApplicationScope();
+ }
+ throw new IllegalArgumentException(scope + " does not exist. Call getAvailableScopes() first to check.");
+ }
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getRequestScope() {
+
+ if ((requestScope == null) && (request != null)) {
+ requestScope = new ScopeMap(new RequestScopeExtractor(request));
+ }
+ return (requestScope);
+
+ }
+
+
+ /** {@inheritDoc} */
+ public Map<String, Object> getSessionScope() {
+
+ if ((sessionScope == null) && (request != null)) {
+ sessionScope = new ScopeMap(new SessionScopeExtractor(request));
+ }
+ return (sessionScope);
+
+ }
+
+ @Override
+ public List<String> getAvailableScopes() {
+ return SCOPES;
+ }
+
+ /** {@inheritDoc} */
+ public void doForward(String path) throws IOException {
+ if (response.isCommitted()) {
+ doInclude(path);
+ } else {
+ forward(path);
+ }
+ }
+
+
+ /** {@inheritDoc} */
+ public void doInclude(String path) throws IOException {
+ RequestDispatcher rd = request.getRequestDispatcher(path);
+
+ if (rd == null) {
+ throw new IOException("No request dispatcher returned for path '"
+ + path + "'");
+ }
+
+ try {
+ rd.include(request, response);
+ } catch (ServletException ex) {
+ throw ServletUtil.wrapServletException(ex, "ServletException including path '"
+ + path + "'.");
+ }
+ }
+
+ /**
+ * Forwards to a path.
+ *
+ * @param path The path to forward to.
+ * @throws IOException If something goes wrong during the operation.
+ */
+ private void forward(String path) throws IOException {
+ RequestDispatcher rd = request.getRequestDispatcher(path);
+
+ if (rd == null) {
+ throw new IOException("No request dispatcher returned for path '"
+ + path + "'");
+ }
+
+ try {
+ rd.forward(request, response);
+ } catch (ServletException ex) {
+ throw ServletUtil.wrapServletException(ex, "ServletException including path '"
+ + path + "'.");
+ }
+ }
+
+ /** {@inheritDoc} */
+ public OutputStream getOutputStream() throws IOException {
+ if (outputStream == null) {
+ outputStream = response.getOutputStream();
+ }
+ return outputStream;
+ }
+
+ /** {@inheritDoc} */
+ public Writer getWriter() throws IOException {
+ return getPrintWriter();
+ }
+
+ /** {@inheritDoc} */
+ public PrintWriter getPrintWriter() throws IOException {
+ if (writer == null) {
+ writer = response.getWriter();
+ }
+ return writer;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isResponseCommitted() {
+ return response.isCommitted();
+ }
+
+ /** {@inheritDoc} */
+ public void setContentType(String contentType) {
+ response.setContentType(contentType);
+ }
+
+ /** {@inheritDoc} */
+ public Locale getRequestLocale() {
+ return request.getLocale();
+ }
+
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+
+ public HttpServletResponse getResponse() {
+ return response;
+ }
+
+ /** {@inheritDoc} */
+ public boolean isUserInRole(String role) {
+ return request.isUserInRole(role);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java
new file mode 100644
index 0000000..652e8e9
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/ServletUtil.java
@@ -0,0 +1,122 @@
+/*
+ * $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.request.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.DispatchRequestWrapper;
+import org.apache.tiles.request.Request;
+
+/**
+ * Utilities for Tiles request servlet support.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class ServletUtil {
+
+ /**
+ * Constructor.
+ */
+ private ServletUtil() {
+ }
+
+ /**
+ * Wraps a ServletException to create an IOException with the root cause if present.
+ *
+ * @param ex The exception to wrap.
+ * @param message The message of the exception.
+ * @return The wrapped exception.
+ */
+ public static IOException wrapServletException(ServletException ex,
+ String message) {
+ IOException retValue;
+ Throwable rootCause = ex.getRootCause();
+ if (rootCause != null) {
+ // Replace the ServletException with an IOException, with the root
+ // cause of the first as the cause of the latter.
+ retValue = new IOException(message, rootCause);
+ } else {
+ retValue = new IOException(message, ex);
+ }
+
+ return retValue;
+ }
+
+ /**
+ * Returns the application context getting it from the servlet context. It must be
+ * first saved creating a {@link ServletApplicationContext} and using
+ * {@link ApplicationAccess#register(ApplicationContext)}.
+ *
+ * @param servletContext The servlet context.
+ * @return The application context, if found, <code>null</code> otherwise.
+ */
+ public static ApplicationContext getApplicationContext(ServletContext servletContext) {
+ return (ApplicationContext) servletContext
+ .getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE);
+ }
+
+ /**
+ * Opens a TilesRequestContext until it finds a ServletTilesRequestContext.
+ *
+ * @param request The request to open.
+ * @return The servlet-based request context.
+ * @throws NotAServletEnvironmentException If a servlet-based request
+ * context could not be found.
+ */
+ public static ServletRequest getServletRequest(Request request) {
+ Request currentRequest = request;
+ while (true) {
+ if (currentRequest == null) {
+ throw new NotAServletEnvironmentException("Last Tiles request context is null");
+ }
+
+ if (currentRequest instanceof ServletRequest) {
+ return (ServletRequest) currentRequest;
+ }
+ if (!(currentRequest instanceof DispatchRequestWrapper)) {
+ throw new NotAServletEnvironmentException("Not a Servlet environment, not supported");
+ }
+ currentRequest = ((DispatchRequestWrapper) currentRequest).getWrappedRequest();
+ }
+ }
+
+ /**
+ * Gets a servlet context from a TilesApplicationContext.
+ *
+ * @param applicationContext The application context to analyze.
+ * @return The servlet context.
+ * @throws NotAServletEnvironmentException If the application context is not
+ * servlet-based.
+ */
+ public static ServletContext getServletContext(ApplicationContext applicationContext) {
+ if (applicationContext instanceof ServletApplicationContext) {
+ return (ServletContext) ((ServletApplicationContext) applicationContext).getContext();
+ }
+
+ throw new NotAServletEnvironmentException("Not a Servlet-based environment");
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java
new file mode 100644
index 0000000..b7e3460
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractor.java
@@ -0,0 +1,70 @@
+/*
+ * $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.request.servlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extract attributes from application scope.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ApplicationScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The servlet context.
+ */
+ public ApplicationScopeExtractor(ServletContext context) {
+ this.context = context;
+ }
+
+ @Override
+ public void setValue(String name, Object value) {
+ context.setAttribute(name, value);
+ }
+
+ @Override
+ public void removeValue(String name) {
+ context.removeAttribute(name);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ return context.getAttributeNames();
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return context.getAttribute(key);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java
new file mode 100644
index 0000000..2820903
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/HeaderExtractor.java
@@ -0,0 +1,80 @@
+/*
+ * $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.request.servlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.attribute.EnumeratedValuesExtractor;
+
+/**
+ * Extract header values from an HTTP request.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderExtractor implements EnumeratedValuesExtractor {
+
+ /**
+ * The request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The response.
+ */
+ private HttpServletResponse response;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request.
+ * @param response The response.
+ */
+ public HeaderExtractor(HttpServletRequest request,
+ HttpServletResponse response) {
+ this.request = request;
+ this.response = response;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ return request.getHeaderNames();
+ }
+
+ @Override
+ public String getValue(String key) {
+ return request.getHeader(key);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getValues(String key) {
+ return request.getHeaders(key);
+ }
+
+ @Override
+ public void setValue(String key, String value) {
+ response.setHeader(key, value);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java
new file mode 100644
index 0000000..6dbf7b7
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractor.java
@@ -0,0 +1,61 @@
+/*
+ * $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.request.servlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.attribute.HasKeys;
+
+/**
+ * Extract initialization parameters from the servlet context.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitParameterExtractor implements HasKeys<String> {
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The servlet context.
+ */
+ public InitParameterExtractor(ServletContext context) {
+ this.context = context;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ return context.getInitParameterNames();
+ }
+
+ @Override
+ public String getValue(String key) {
+ return context.getInitParameter(key);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java
new file mode 100644
index 0000000..9749270
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/ParameterExtractor.java
@@ -0,0 +1,60 @@
+/*
+ * $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.request.servlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tiles.request.attribute.HasKeys;
+
+/**
+ * Extract parameters from the request.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ParameterExtractor implements HasKeys<String> {
+
+ /**
+ * The servlet request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The servlet request.
+ */
+ public ParameterExtractor(HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ return request.getParameterNames();
+ }
+
+ @Override
+ public String getValue(String key) {
+ return request.getParameter(key);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java
new file mode 100644
index 0000000..d558e10
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractor.java
@@ -0,0 +1,70 @@
+/*
+ * $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.request.servlet.extractor;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extracts attributes from request scope.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The servlet request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The servlet request.
+ */
+ public RequestScopeExtractor(HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public void setValue(String name, Object value) {
+ request.setAttribute(name, value);
+ }
+
+ @Override
+ public void removeValue(String name) {
+ request.removeAttribute(name);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ return request.getAttributeNames();
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return request.getAttribute(key);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java
new file mode 100644
index 0000000..6d49743
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractor.java
@@ -0,0 +1,83 @@
+/*
+ * $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.request.servlet.extractor;
+
+import java.util.Enumeration;
+import java.util.Collections;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+
+/**
+ * Extract attributes from session scope.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The servlet request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * Constructor.
+ *
+ * @param request The servlet request.
+ */
+ public SessionScopeExtractor(HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public void setValue(String name, Object value) {
+ request.getSession().setAttribute(name, value);
+ }
+
+ @Override
+ public void removeValue(String name) {
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ session.removeAttribute(name);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Enumeration<String> getKeys() {
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ return session.getAttributeNames();
+ }
+ return Collections.enumeration(Collections.<String>emptySet());
+ }
+
+ @Override
+ public Object getValue(String key) {
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ return session.getAttribute(key);
+ }
+ return null;
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java
new file mode 100644
index 0000000..0df9334
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/extractor/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Extractors to get attributes and other info from servlet requests and contexts.
+ */
+package org.apache.tiles.request.servlet.extractor;
diff --git a/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/package-info.java b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/package-info.java
new file mode 100644
index 0000000..331e1f1
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/main/java/org/apache/tiles/request/servlet/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Tiles request support for Servlet technology.
+ */
+package org.apache.tiles.request.servlet;
diff --git a/tiles-request/tiles-request-servlet/src/site/site.xml b/tiles-request/tiles-request-servlet/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponseTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponseTest.java
new file mode 100644
index 0000000..67d0562
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ExternalWriterHttpServletResponseTest.java
@@ -0,0 +1,55 @@
+/*
+ * $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.request.servlet;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link ExternalWriterHttpServletResponse}.
+ */
+public class ExternalWriterHttpServletResponseTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ExternalWriterHttpServletResponse#getWriter()}.
+ */
+ @Test
+ public void testGetWriter() {
+ HttpServletResponse wrappedResponse = createMock(HttpServletResponse.class);
+ Writer writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ replay(wrappedResponse);
+ ExternalWriterHttpServletResponse response = new ExternalWriterHttpServletResponse(
+ wrappedResponse, printWriter);
+ assertEquals(printWriter, response.getWriter());
+ verify(wrappedResponse);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/NotAServletEnvironmentExceptionTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/NotAServletEnvironmentExceptionTest.java
new file mode 100644
index 0000000..6a750f8
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/NotAServletEnvironmentExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * $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.request.servlet;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * Tests {@link NotAServletEnvironmentException}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NotAServletEnvironmentExceptionTest {
+
+ /**
+ * Test method for {@link NotAServletEnvironmentException#NotAServletEnvironmentException()}.
+ */
+ @Test
+ public void testNotAServletEnvironmentException() {
+ NotAServletEnvironmentException exception = new NotAServletEnvironmentException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAServletEnvironmentException#NotAServletEnvironmentException(java.lang.String)}.
+ */
+ @Test
+ public void testNotAServletEnvironmentExceptionString() {
+ NotAServletEnvironmentException exception = new NotAServletEnvironmentException("my message");
+ assertEquals("my message", exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAServletEnvironmentException#NotAServletEnvironmentException(java.lang.Throwable)}.
+ */
+ @Test
+ public void testNotAServletEnvironmentExceptionThrowable() {
+ Throwable cause = new Throwable();
+ NotAServletEnvironmentException exception = new NotAServletEnvironmentException(cause);
+ assertEquals(cause.toString(), exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+ /**
+ * Test method for {@link NotAServletEnvironmentException#NotAServletEnvironmentException(String, Throwable)}.
+ */
+ @Test
+ public void testNotAServletEnvironmentExceptionStringThrowable() {
+ Throwable cause = new Throwable();
+ NotAServletEnvironmentException exception = new NotAServletEnvironmentException("my message", cause);
+ assertEquals("my message", exception.getMessage());
+ assertEquals(cause, exception.getCause());
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletApplicationContextTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletApplicationContextTest.java
new file mode 100644
index 0000000..1ab3413
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletApplicationContextTest.java
@@ -0,0 +1,139 @@
+/*
+ * $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.request.servlet;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Locale;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.ApplicationResource;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ServletApplicationContext}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServletApplicationContextTest {
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext servletContext;
+
+ /**
+ * The application context to test.
+ */
+ private ServletApplicationContext context;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ servletContext = createMock(ServletContext.class);
+ context = new ServletApplicationContext(servletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletApplicationContext#getContext()}.
+ */
+ @Test
+ public void testGetContext() {
+ replay(servletContext);
+ assertEquals(servletContext, context.getContext());
+ verify(servletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletApplicationContext#getApplicationScope()}.
+ */
+ @Test
+ public void testGetApplicationScope() {
+ replay(servletContext);
+ assertTrue(context.getApplicationScope() instanceof ScopeMap);
+ verify(servletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletApplicationContext#getInitParams()}.
+ */
+ @Test
+ public void testGetInitParams() {
+ replay(servletContext);
+ assertTrue(context.getInitParams() instanceof ReadOnlyEnumerationMap);
+ verify(servletContext);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletApplicationContext#getResource(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetResource() throws IOException {
+ URL url = new URL("file:///servletContext/my/path.html");
+ URL urlFr = new URL("file:///servletContext/my/path_fr.html");
+ expect(servletContext.getResource("/my/path.html")).andReturn(url);
+ expect(servletContext.getResource("/my/path_fr.html")).andReturn(urlFr);
+ expect(servletContext.getResource("/null/path.html")).andReturn(null);
+
+ replay(servletContext);
+ ApplicationResource resource = context.getResource("/my/path.html");
+ assertNotNull(resource);
+ assertEquals(resource.getLocalePath(), "/my/path.html");
+ assertEquals(resource.getPath(), "/my/path.html");
+ assertEquals(Locale.ROOT, resource.getLocale());
+ ApplicationResource resourceFr = context.getResource(resource, Locale.FRENCH);
+ assertNotNull(resourceFr);
+ assertEquals("/my/path_fr.html", resourceFr.getLocalePath());
+ assertEquals("/my/path.html", resourceFr.getPath());
+ assertEquals(Locale.FRENCH, resourceFr.getLocale());
+ ApplicationResource nullResource = context.getResource("/null/path.html");
+ assertNull(nullResource);
+ verify(servletContext);
+ }
+
+ /**
+ * Test method for {@link ServletApplicationContext#getResources(String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetResources() throws IOException {
+ URL url = new URL("file:///servletContext/my/path");
+ expect(servletContext.getResource("/my/path")).andReturn(url);
+
+ replay(servletContext);
+ Collection<ApplicationResource> resources = context.getResources("/my/path");
+ assertEquals(1, resources.size());
+ assertEquals(resources.iterator().next().getLocalePath(), "/my/path");
+ verify(servletContext);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletRequestTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletRequestTest.java
new file mode 100644
index 0000000..14b05cf
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletRequestTest.java
@@ -0,0 +1,391 @@
+/*
+ * $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.request.servlet;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.collection.HeaderValuesMap;
+import org.apache.tiles.request.collection.ReadOnlyEnumerationMap;
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.servlet.extractor.HeaderExtractor;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ServletRequest}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServletRequestTest {
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * The request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The response.
+ */
+ private HttpServletResponse response;
+
+ /**
+ * The request to test.
+ */
+ private ServletRequest req;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ applicationContext = createMock(ApplicationContext.class);
+ request = createMock(HttpServletRequest.class);
+ response = createMock(HttpServletResponse.class);
+ req = new ServletRequest(applicationContext, request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test
+ public void testDoForward() throws ServletException, IOException {
+ RequestDispatcher rd = createMock(RequestDispatcher.class);
+
+ expect(response.isCommitted()).andReturn(false);
+ expect(request.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.forward(request, response);
+
+ replay(applicationContext, request, response, rd);
+ req.doForward("/my/path");
+ verify(applicationContext, request, response, rd);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoForwardNoDispatcher() throws IOException {
+ expect(response.isCommitted()).andReturn(false);
+ expect(request.getRequestDispatcher("/my/path")).andReturn(null);
+
+ replay(applicationContext, request, response);
+ try {
+ req.doForward("/my/path");
+ } finally {
+ verify(applicationContext, request, response);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoForwardServletException() throws ServletException, IOException {
+ RequestDispatcher rd = createMock(RequestDispatcher.class);
+
+ expect(response.isCommitted()).andReturn(false);
+ expect(request.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.forward(request, response);
+ expectLastCall().andThrow(new ServletException());
+
+ replay(applicationContext, request, response, rd);
+ try {
+ req.doForward("/my/path");
+ } finally {
+ verify(applicationContext, request, response, rd);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doForward(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test
+ public void testDoForwardInclude() throws ServletException, IOException {
+ RequestDispatcher rd = createMock(RequestDispatcher.class);
+
+ expect(response.isCommitted()).andReturn(true);
+ expect(request.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.include(request, response);
+
+ replay(applicationContext, request, response, rd);
+ req.doForward("/my/path");
+ verify(applicationContext, request, response, rd);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test
+ public void testDoInclude() throws IOException, ServletException {
+ RequestDispatcher rd = createMock(RequestDispatcher.class);
+
+ expect(request.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.include(request, response);
+
+ replay(applicationContext, request, response, rd);
+ req.doInclude("/my/path");
+ verify(applicationContext, request, response, rd);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludeNoDispatcher() throws IOException {
+ expect(request.getRequestDispatcher("/my/path")).andReturn(null);
+
+ replay(applicationContext, request, response);
+ try {
+ req.doInclude("/my/path");
+ } finally {
+ verify(applicationContext, request, response);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#doInclude(java.lang.String)}.
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludeServletException() throws IOException, ServletException {
+ RequestDispatcher rd = createMock(RequestDispatcher.class);
+
+ expect(request.getRequestDispatcher("/my/path")).andReturn(rd);
+ rd.include(request, response);
+ expectLastCall().andThrow(new ServletException());
+
+ replay(applicationContext, request, response, rd);
+ try {
+ req.doInclude("/my/path");
+ } finally {
+ verify(applicationContext, request, response, rd);
+ }
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getHeader()}.
+ */
+ @Test
+ public void testGetHeader() {
+ assertTrue(req.getHeader() instanceof ReadOnlyEnumerationMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getHeader()}.
+ */
+ @Test
+ public void testGetResponseHeaders() {
+ assertTrue(req.getResponseHeaders() instanceof HeaderExtractor);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getHeaderValues()}.
+ */
+ @Test
+ public void testGetHeaderValues() {
+ assertTrue(req.getHeaderValues() instanceof HeaderValuesMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getParam()}.
+ */
+ @Test
+ public void testGetParam() {
+ assertTrue(req.getParam() instanceof ReadOnlyEnumerationMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getParamValues()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetParamValues() {
+ Map<String, String[]> paramMap = createMock(Map.class);
+
+ expect(request.getParameterMap()).andReturn(paramMap);
+
+ replay(applicationContext, request, response, paramMap);
+ assertEquals(paramMap, req.getParamValues());
+ verify(applicationContext, request, response, paramMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getRequestScope()}.
+ */
+ @Test
+ public void testGetRequestScope() {
+ assertTrue(req.getRequestScope() instanceof ScopeMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getSessionScope()}.
+ */
+ @Test
+ public void testGetSessionScope() {
+ assertTrue(req.getSessionScope() instanceof ScopeMap);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getOutputStream()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetOutputStream() throws IOException {
+ ServletOutputStream os = createMock(ServletOutputStream.class);
+
+ expect(response.getOutputStream()).andReturn(os);
+
+ replay(applicationContext, request, response, os);
+ assertEquals(req.getOutputStream(), os);
+ verify(applicationContext, request, response, os);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetWriter() throws IOException {
+ PrintWriter os = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(os);
+
+ replay(applicationContext, request, response, os);
+ assertEquals(req.getWriter(), os);
+ verify(applicationContext, request, response, os);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getPrintWriter()}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testGetPrintWriter() throws IOException {
+ PrintWriter os = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(os);
+
+ replay(applicationContext, request, response, os);
+ assertEquals(req.getPrintWriter(), os);
+ verify(applicationContext, request, response, os);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#isResponseCommitted()}.
+ */
+ @Test
+ public void testIsResponseCommitted() {
+ expect(response.isCommitted()).andReturn(true);
+
+ replay(applicationContext, request, response);
+ assertTrue(req.isResponseCommitted());
+ verify(applicationContext, request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#setContentType(java.lang.String)}.
+ */
+ @Test
+ public void testSetContentType() {
+ response.setContentType("text/html");
+
+ replay(applicationContext, request, response);
+ req.setContentType("text/html");
+ verify(applicationContext, request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getRequestLocale()}.
+ */
+ @Test
+ public void testGetRequestLocale() {
+ Locale locale = Locale.ITALY;
+
+ expect(request.getLocale()).andReturn(locale);
+
+ replay(applicationContext, request, response);
+ assertEquals(locale, req.getRequestLocale());
+ verify(applicationContext, request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getRequest()}.
+ */
+ @Test
+ public void testGetRequest() {
+ replay(applicationContext, request, response);
+ assertEquals(request, req.getRequest());
+ verify(applicationContext, request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#getResponse()}.
+ */
+ @Test
+ public void testGetResponse() {
+ replay(applicationContext, request, response);
+ assertEquals(response, req.getResponse());
+ verify(applicationContext, request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.ServletRequest#isUserInRole(java.lang.String)}.
+ */
+ @Test
+ public void testIsUserInRole() {
+ expect(request.isUserInRole("myrole")).andReturn(true);
+
+ replay(applicationContext, request, response);
+ assertTrue(req.isUserInRole("myrole"));
+ verify(applicationContext, request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletUtilTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletUtilTest.java
new file mode 100644
index 0000000..38942b0
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/ServletUtilTest.java
@@ -0,0 +1,82 @@
+/*
+ * $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.request.servlet;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.junit.Test;
+
+/**
+ * Tests {@link ServletUtil}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ServletUtilTest {
+
+ /**
+ * Test method for {@link ServletUtil#wrapServletException(ServletException, String)}.
+ */
+ @Test
+ public void testWrapServletException() {
+ ServletException servletException = new ServletException();
+ IOException exception = ServletUtil.wrapServletException(servletException, "my message");
+ assertEquals(servletException, exception.getCause());
+ assertEquals("my message", exception.getMessage());
+ }
+
+ /**
+ */
+ @Test
+ public void testWrapServletExceptionWithCause() {
+ Throwable cause = createMock(Throwable.class);
+
+ replay(cause);
+ ServletException servletException = new ServletException(cause);
+ IOException exception = ServletUtil.wrapServletException(servletException, "my message");
+ assertEquals(cause, exception.getCause());
+ assertEquals("my message", exception.getMessage());
+ verify(cause);
+ }
+
+ /**
+ * Test method for {@link ServletUtil#getApplicationContext(ServletContext)}.
+ */
+ @Test
+ public void testGetApplicationContext() {
+ ServletContext servletContext = createMock(ServletContext.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ expect(servletContext.getAttribute(ApplicationAccess
+ .APPLICATION_CONTEXT_ATTRIBUTE)).andReturn(applicationContext);
+
+ replay(servletContext, applicationContext);
+ assertEquals(applicationContext, ServletUtil.getApplicationContext(servletContext));
+ verify(servletContext, applicationContext);
+ }
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractorTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractorTest.java
new file mode 100644
index 0000000..72f8939
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/ApplicationScopeExtractorTest.java
@@ -0,0 +1,109 @@
+/*
+ * $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.request.servlet.extractor;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ApplicationScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ApplicationScopeExtractorTest {
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext context;
+
+ /**
+ * The extractor to test.
+ */
+ private ApplicationScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ context = createMock(ServletContext.class);
+ extractor = new ApplicationScopeExtractor(context);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#setValue(String, Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ context.setAttribute("attribute", "value");
+
+ replay(context);
+ extractor.setValue("attribute", "value");
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#removeValue(String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ context.removeAttribute("attribute");
+
+ replay(context);
+ extractor.removeValue("attribute");
+ verify(context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.ApplicationScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+ expect(context.getAttributeNames()).andReturn(keys);
+
+ replay(context, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(context, keys);
+ }
+
+ /**
+ * Test method for {@link ApplicationScopeExtractor#getValue(String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(context.getAttribute("attribute")).andReturn("value");
+
+ replay(context);
+ assertEquals("value", extractor.getValue("attribute"));
+ verify(context);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/HeaderExtractorTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/HeaderExtractorTest.java
new file mode 100644
index 0000000..e05f86f
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/HeaderExtractorTest.java
@@ -0,0 +1,120 @@
+/*
+ * $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.request.servlet.extractor;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link HeaderExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class HeaderExtractorTest {
+
+ /**
+ * The request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The response.
+ */
+ private HttpServletResponse response;
+
+ /**
+ * The extractor to test.
+ */
+ private HeaderExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(HttpServletRequest.class);
+ response = createMock(HttpServletResponse.class);
+ extractor = new HeaderExtractor(request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.HeaderExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getHeaderNames()).andReturn(keys);
+
+ replay(request, response, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, response, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.HeaderExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getHeader("name")).andReturn("value");
+
+ replay(request, response);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request, response);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.HeaderExtractor#getValues(java.lang.String)}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetValues() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getHeaders("name")).andReturn(keys);
+
+ replay(request, response, keys);
+ assertEquals(keys, extractor.getValues("name"));
+ verify(request, response, keys);
+ }
+
+ /**
+ * Test method for {@link HeaderExtractor#setValue(String, String)}.
+ */
+ @Test
+ public void testSetValue() {
+ response.setHeader("name", "value");
+
+ replay(request, response);
+ extractor.setValue("name", "value");
+ verify(request, response);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractorTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractorTest.java
new file mode 100644
index 0000000..f45acaf
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/InitParameterExtractorTest.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request.servlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.ServletContext;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link InitParameterExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class InitParameterExtractorTest {
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext context;
+
+ /**
+ * The extractor to test.
+ */
+ private InitParameterExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ context = createMock(ServletContext.class);
+ extractor = new InitParameterExtractor(context);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.InitParameterExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(context.getInitParameterNames()).andReturn(keys);
+
+ replay(context, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(context, keys);
+ }
+
+ /**
+ * Test method for {@link InitParameterExtractor#getValue(String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(context.getInitParameter("name")).andReturn("value");
+
+ replay(context);
+ assertEquals("value", extractor.getValue("name"));
+ verify(context);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/ParameterExtractorTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/ParameterExtractorTest.java
new file mode 100644
index 0000000..df0b0bf
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/ParameterExtractorTest.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request.servlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ParameterExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ParameterExtractorTest {
+
+ /**
+ * The request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The extractor to test.
+ */
+ private ParameterExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(HttpServletRequest.class);
+ extractor = new ParameterExtractor(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.ParameterExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getParameterNames()).andReturn(keys);
+
+ replay(request, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, keys);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.ParameterExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getParameter("name")).andReturn("value");
+
+ replay(request);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractorTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractorTest.java
new file mode 100644
index 0000000..c5ef1c8
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/RequestScopeExtractorTest.java
@@ -0,0 +1,111 @@
+/*
+ * $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.request.servlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link RequestScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class RequestScopeExtractorTest {
+
+ /**
+ * The request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The extractor to test.
+ */
+ private RequestScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(HttpServletRequest.class);
+ extractor = new RequestScopeExtractor(request);
+ }
+
+ /**
+ * Test method for {@link RequestScopeExtractor#setValue(String, Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ request.setAttribute("name", "value");
+
+ replay(request);
+ extractor.setValue("name", "value");
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link RequestScopeExtractor#removeValue(String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ request.removeAttribute("name");
+
+ replay(request);
+ extractor.removeValue("name");
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.servlet.extractor.RequestScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getAttributeNames()).andReturn(keys);
+
+ replay(request, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, keys);
+ }
+
+ /**
+ * Test method for {@link RequestScopeExtractor#getValue(String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getAttribute("name")).andReturn("value");
+
+ replay(request);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request);
+ }
+
+}
diff --git a/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractorTest.java b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractorTest.java
new file mode 100644
index 0000000..8be27b4
--- /dev/null
+++ b/tiles-request/tiles-request-servlet/src/test/java/org/apache/tiles/request/servlet/extractor/SessionScopeExtractorTest.java
@@ -0,0 +1,148 @@
+/*
+ * $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.request.servlet.extractor;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link SessionScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SessionScopeExtractorTest {
+
+ /**
+ * The request.
+ */
+ private HttpServletRequest request;
+
+ /**
+ * The session.
+ */
+ private HttpSession session;
+
+ /**
+ * The extractot to test.
+ */
+ private SessionScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(HttpServletRequest.class);
+ session = createMock(HttpSession.class);
+ extractor = new SessionScopeExtractor(request);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#setValue(java.lang.String, java.lang.Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ expect(request.getSession()).andReturn(session);
+ session.setAttribute("name", "value");
+
+ replay(request, session);
+ extractor.setValue("name", "value");
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ expect(request.getSession(false)).andReturn(session);
+ session.removeAttribute("name");
+
+ replay(request, session);
+ extractor.removeValue("name");
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getKeys()}.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testGetKeys() {
+ Enumeration<String> keys = createMock(Enumeration.class);
+
+ expect(request.getSession(false)).andReturn(session);
+ expect(session.getAttributeNames()).andReturn(keys);
+
+ replay(request, session, keys);
+ assertEquals(keys, extractor.getKeys());
+ verify(request, session, keys);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getKeys()}.
+ */
+ @Test
+ public void testGetKeysNoSession() {
+ expect(request.getSession(false)).andReturn(null);
+
+ replay(request, session);
+ Enumeration<String> keys = extractor.getKeys();
+ assertNotNull(keys);
+ assertFalse(keys.hasMoreElements());
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.getSession(false)).andReturn(session);
+ expect(session.getAttribute("name")).andReturn("value");
+
+ replay(request, session);
+ assertEquals("value", extractor.getValue("name"));
+ verify(request, session);
+ }
+
+ /**
+ * Test method for {@link SessionScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValueNoSession() {
+ expect(request.getSession(false)).andReturn(null);
+
+ replay(request, session);
+ assertNull(extractor.getValue("name"));
+ verify(request, session);
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/pom.xml b/tiles-request/tiles-request-velocity/pom.xml
new file mode 100644
index 0000000..c8fe373
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>tiles-request</artifactId>
+ <groupId>org.apache.tiles</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-velocity</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Tiles Request - Velocity support</name>
+ <description>Velocity implementation of the Tiles request framework</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-tools</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-request-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tiles</groupId>
+ <artifactId>tiles-autotag-core-runtime</artifactId>
+ <optional>true</optional>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java
new file mode 100644
index 0000000..1f087f6
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/VelocityRequest.java
@@ -0,0 +1,178 @@
+/*
+ * $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.request.velocity;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.AbstractViewRequest;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.DispatchRequest;
+import org.apache.tiles.request.servlet.ExternalWriterHttpServletResponse;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.apache.tiles.request.servlet.ServletUtil;
+import org.apache.velocity.context.Context;
+
+/**
+ * The implementation of the Tiles request context specific for Velocity.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityRequest extends AbstractViewRequest {
+
+ /**
+ * The native available scopes, in fact only "page".
+ */
+ private final List<String> scopes;
+
+ /**
+ * The Velocity current context.
+ */
+ private final Context ctx;
+
+ /**
+ * The writer to use to render the response. It may be null, if not necessary.
+ */
+ private Writer writer;
+
+ /**
+ * The map of the page scope.
+ */
+ private Map<String, Object> pageScope;
+
+ /**
+ * Factory method to create a Velocity request.
+ *
+ * @param applicationContext The application context.
+ * @param request The request.
+ * @param response The response.
+ * @param velocityContext The Velocity context.
+ * @param writer The writer to write into.
+ * @return The request.
+ */
+ public static VelocityRequest createVelocityRequest(
+ ApplicationContext applicationContext, HttpServletRequest request,
+ HttpServletResponse response, Context velocityContext, Writer writer) {
+ DispatchRequest servletRequest = new ServletRequest(
+ applicationContext, request, response);
+ VelocityRequest velocityRequest = new VelocityRequest(
+ servletRequest, velocityContext, writer);
+ return velocityRequest;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param enclosedRequest The request that exposes non-Velocity specific properties
+ * @param ctx The Velocity current context.
+ * @param writer The writer to use to render the response. It may be null, if not necessary.
+ */
+ public VelocityRequest(
+ DispatchRequest enclosedRequest, Context ctx, Writer writer) {
+ super(enclosedRequest);
+ List<String> scopes = new ArrayList<String>();
+ scopes.addAll(enclosedRequest.getAvailableScopes());
+ scopes.add("page");
+ this.scopes = Collections.unmodifiableList(scopes);
+ this.ctx = ctx;
+ this.writer = writer;
+ }
+
+ @Override
+ public List<String> getAvailableScopes() {
+ return scopes;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInclude(String path) throws IOException {
+ ServletRequest servletRequest = org.apache.tiles.request.servlet.ServletUtil.getServletRequest(this);
+ HttpServletRequest request = servletRequest.getRequest();
+ HttpServletResponse response = servletRequest.getResponse();
+ RequestDispatcher rd = request.getRequestDispatcher(path);
+
+ if (rd == null) {
+ throw new IOException("No request dispatcher returned for path '"
+ + path + "'");
+ }
+
+ PrintWriter printWriter = getPrintWriter();
+ try {
+ rd.include(request, new ExternalWriterHttpServletResponse(response,
+ printWriter));
+ } catch (ServletException ex) {
+ throw ServletUtil.wrapServletException(ex, "ServletException including path '"
+ + path + "'.");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter getPrintWriter() {
+ if (writer == null) {
+ throw new IllegalStateException(
+ "A writer-less Tiles request has been created, cannot return a PrintWriter");
+ }
+ if (writer instanceof PrintWriter) {
+ return (PrintWriter) writer;
+ }
+ return new PrintWriter(writer);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Writer getWriter() {
+ if (writer == null) {
+ throw new IllegalStateException(
+ "A writer-less Tiles request has been created, cannot return a PrintWriter");
+ }
+ return writer;
+ }
+
+ /**
+ * Returns the page scope.
+ *
+ * @return The page scope.
+ */
+ public Map<String, Object> getPageScope() {
+ if (pageScope == null) {
+ pageScope = new VelocityScopeMap(ctx);
+ }
+ return pageScope;
+ }
+
+ @Override
+ public Map<String, Object> getContext(String scope) {
+ return "page".equals(scope) ? getPageScope() : super.getContext(scope);
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java
new file mode 100644
index 0000000..b268fac
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/VelocityScopeMap.java
@@ -0,0 +1,89 @@
+/*
+ * $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.request.velocity;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.tiles.request.collection.ScopeMap;
+import org.apache.tiles.request.velocity.extractor.VelocityScopeExtractor;
+import org.apache.velocity.context.Context;
+
+/**
+ * <p>Private implementation of <code>Map</code> for servlet request
+ * attributes.</p>
+ *
+ * @version $Rev$ $Date$
+ */
+
+final class VelocityScopeMap extends ScopeMap {
+
+ /**
+ * The request object to use.
+ */
+ private Context request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param request The request object to use.
+ */
+ public VelocityScopeMap(Context request) {
+ super(new VelocityScopeExtractor(request));
+ this.request = request;
+ }
+
+ @Override
+ public Object remove(Object key) {
+ return request.remove(key);
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ return request.put(key, value);
+ }
+
+ /** {@inheritDoc} */
+ public boolean containsKey(Object key) {
+ return request.containsKey(key);
+ }
+
+
+ /** {@inheritDoc} */
+ public boolean isEmpty() {
+ return size() < 1;
+ }
+
+
+ /** {@inheritDoc} */
+ public Set<String> keySet() {
+ Set<String> set = new HashSet<String>();
+ for (Object key : request.getKeys()) {
+ set.add((String) key);
+ }
+ return (set);
+ }
+
+ /** {@inheritDoc} */
+ public int size() {
+ return request.getKeys().length;
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java
new file mode 100644
index 0000000..9d7b419
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntime.java
@@ -0,0 +1,106 @@
+/*
+ * $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.request.velocity.autotag;
+
+import java.io.Writer;
+import java.util.Map;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.servlet.ServletUtil;
+import org.apache.tiles.request.velocity.VelocityRequest;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.directive.Directive;
+import org.apache.velocity.runtime.parser.node.ASTBlock;
+import org.apache.velocity.runtime.parser.node.ASTMap;
+import org.apache.velocity.runtime.parser.node.Node;
+import org.apache.velocity.tools.view.ViewContext;
+
+/**
+ * A Runtime for implementing Velocity Directives.
+ */
+public class VelocityAutotagRuntime extends Directive implements AutotagRuntime {
+ private InternalContextAdapter context;
+ private Writer writer;
+ private Node node;
+ private Map<String, Object> params;
+
+ /** {@inheritDoc} */
+ @Override
+ public Request createRequest() {
+ ViewContext viewContext = (ViewContext) context.getInternalUserContext();
+ HttpServletRequest request = viewContext.getRequest();
+ HttpServletResponse response = viewContext.getResponse();
+ ServletContext servletContext = viewContext.getServletContext();
+ return VelocityRequest.createVelocityRequest(ServletUtil.getApplicationContext(servletContext),
+ request,
+ response,
+ context,
+ writer);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelBody createModelBody() {
+ ASTBlock block = (ASTBlock) node.jjtGetChild(1);
+ return new VelocityModelBody(context, block, writer);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getParameter(String name, Object defaultValue) {
+ if (params == null) {
+ ASTMap astMap = (ASTMap) node.jjtGetChild(0);
+ params = (Map<String, Object>) astMap.value(context);
+ }
+ Object result = params.get(name);
+ if (result == null) {
+ result = defaultValue;
+ }
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int getType() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean render(InternalContextAdapter context, Writer writer, Node node) {
+ this.context = context;
+ this.writer = writer;
+ this.node = node;
+ return false;
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java
new file mode 100644
index 0000000..6fed188
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityModelBody.java
@@ -0,0 +1,65 @@
+/*
+ * $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.request.velocity.autotag;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.tiles.autotag.core.runtime.AbstractModelBody;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.parser.node.ASTBlock;
+
+/**
+ * Body abstraction for a Velocity directive body.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityModelBody extends AbstractModelBody {
+
+ /**
+ * The real body.
+ */
+ private ASTBlock body;
+
+ /**
+ * The Velocity context.
+ */
+ private InternalContextAdapter context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The Velocity context.
+ * @param body The real body.
+ * @param defaultWriter The default writer.
+ */
+ public VelocityModelBody(InternalContextAdapter context, ASTBlock body, Writer defaultWriter) {
+ super(defaultWriter);
+ this.context = context;
+ this.body = body;
+ }
+
+ @Override
+ public void evaluate(Writer writer) throws IOException {
+ body.render(context, writer);
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java
new file mode 100644
index 0000000..ffdab20
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/VelocityUtil.java
@@ -0,0 +1,74 @@
+/*
+ * $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.request.velocity.autotag;
+
+import java.util.Map;
+
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.parser.node.ASTMap;
+import org.apache.velocity.runtime.parser.node.Node;
+
+/**
+ * Utilities for Velocity usage in Tiles.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class VelocityUtil {
+
+ /**
+ * Private constructor to avoid instantiation.
+ */
+ private VelocityUtil() {
+ }
+
+ /**
+ * Extracts the parameters from the directives, by getting the child at
+ * position 0 supposing it is a map.
+ *
+ * @param context The Velocity context.
+ * @param node The node to use.
+ * @return The extracted parameters.
+ */
+ @SuppressWarnings("unchecked")
+ public static Map<String, Object> getParameters(InternalContextAdapter context,
+ Node node) {
+ ASTMap astMap = (ASTMap) node.jjtGetChild(0);
+ Map<String, Object> params = (Map<String, Object>) astMap
+ .value(context);
+ return params;
+ }
+
+ /**
+ * Returns the "value" parameter if it is not null, otherwise returns
+ * "defaultValue".
+ *
+ * @param value The value to return, if it is not null.
+ * @param defaultValue The value to return, if <code>value</code> is null.
+ * @return The value, defaulted if necessary.
+ */
+ public static Object getObject(Object value, Object defaultValue) {
+ if (value == null) {
+ value = defaultValue;
+ }
+ return value;
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java
new file mode 100644
index 0000000..812198c
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/autotag/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $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.
+ */
+/**
+ * Runtime part of Autotag support for Velocity.
+ */
+package org.apache.tiles.request.velocity.autotag;
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java
new file mode 100644
index 0000000..e81821d
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractor.java
@@ -0,0 +1,103 @@
+/*
+ * $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.request.velocity.extractor;
+
+import java.util.Enumeration;
+
+import org.apache.tiles.request.attribute.AttributeExtractor;
+import org.apache.velocity.context.Context;
+
+/**
+ * Extracts attributes from Velocity context..
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityScopeExtractor implements AttributeExtractor {
+
+ /**
+ * The Velocity context.
+ */
+ private Context context;
+
+ /**
+ * Constructor.
+ *
+ * @param context The Velocity context.
+ */
+ public VelocityScopeExtractor(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public void removeValue(String name) {
+ context.remove(name);
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return new KeyEnumeration(context.getKeys());
+ }
+
+ @Override
+ public Object getValue(String key) {
+ return context.get(key);
+ }
+
+ @Override
+ public void setValue(String key, Object value) {
+ context.put(key, value);
+ }
+
+ /**
+ * Enumerates an array.
+ */
+ private static class KeyEnumeration implements Enumeration<String> {
+
+ /**
+ * The current index.
+ */
+ private int index = 0;
+
+ /**
+ * The array to enumerate.
+ */
+ private Object[] keys;
+
+ /**
+ * Constructor.
+ *
+ * @param keys The array to enumerate.
+ */
+ public KeyEnumeration(Object[] keys) {
+ this.keys = keys;
+ }
+
+ @Override
+ public boolean hasMoreElements() {
+ return index < keys.length;
+ }
+
+ @Override
+ public String nextElement() {
+ return (String) keys[index++];
+ }
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java
new file mode 100644
index 0000000..bed6df2
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/extractor/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Extractors to get info about Velocity-specific objects.
+ */
+package org.apache.tiles.request.velocity.extractor;
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/package-info.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/package-info.java
new file mode 100644
index 0000000..54b7c71
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Tiles request support for Velocity.
+ */
+package org.apache.tiles.request.velocity;
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java
new file mode 100644
index 0000000..b967948
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfig.java
@@ -0,0 +1,87 @@
+/*
+ * $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.request.velocity.render;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.servlet.ServletUtil;
+import org.apache.velocity.tools.view.JeeConfig;
+
+/**
+ * Implements JeeConfig to use parameters set through
+ * {@link VelocityRenderer#setParameter(String, String)}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ApplicationContextJeeConfig implements JeeConfig {
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * The initialization parameters for VelocityView.
+ */
+ private Map<String, String> params;
+
+ /**
+ * Constructor.
+ *
+ * @param applicationContext The application context.
+ * @param params Configuration parameters.
+ */
+ public ApplicationContextJeeConfig(ApplicationContext applicationContext, Map<String, String> params) {
+ this.applicationContext = applicationContext;
+ this.params = new HashMap<String, String>(params);
+ }
+
+ /** {@inheritDoc} */
+ public String getInitParameter(String name) {
+ return params.get(name);
+ }
+
+ /** {@inheritDoc} */
+ public String findInitParameter(String key) {
+ return params.get(key);
+ }
+
+ /** {@inheritDoc} */
+ public Enumeration<String> getInitParameterNames() {
+ return Collections.enumeration(params.keySet());
+ }
+
+ /** {@inheritDoc} */
+ public String getName() {
+ return "Application Context JEE Config";
+ }
+
+ /** {@inheritDoc} */
+ public ServletContext getServletContext() {
+ return ServletUtil.getServletContext(applicationContext);
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java
new file mode 100644
index 0000000..990b5a5
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/VelocityRenderer.java
@@ -0,0 +1,83 @@
+/*
+ * $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.request.velocity.render;
+
+import java.io.IOException;
+
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.render.CannotRenderException;
+import org.apache.tiles.request.render.Renderer;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.apache.tiles.request.servlet.ServletUtil;
+import org.apache.velocity.Template;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.tools.view.VelocityView;
+
+/**
+ * Attribute renderer for rendering Velocity templates as attributes. <br>
+ * It is available only to Servlet-based environment.<br>
+ * It uses {@link VelocityView} to render the response.<br>
+ * To initialize it correctly, call {@link #setParameter(String, String)} for
+ * all the parameters that you want to set, and then call {@link #commit()}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityRenderer implements Renderer {
+
+ /**
+ * The VelocityView object to use.
+ */
+ private VelocityView velocityView;
+
+ /**
+ * Constructor.
+ *
+ * @param velocityView The Velocity view manager.
+ */
+ public VelocityRenderer(VelocityView velocityView) {
+ this.velocityView = velocityView;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void render(String path, Request request) throws IOException {
+ if (path == null) {
+ throw new CannotRenderException("Cannot dispatch a null path");
+ }
+
+ ServletRequest servletRequest = ServletUtil.getServletRequest(request);
+ // then get a context
+ Context context = velocityView.createContext(servletRequest
+ .getRequest(), servletRequest.getResponse());
+
+ // get the template
+ Template template = velocityView.getTemplate((String) path);
+
+ // merge the template and context into the writer
+ velocityView.merge(template, context, request.getWriter());
+ }
+
+ /** {@inheritDoc} */
+ public boolean isRenderable(String path, Request request) {
+ return path != null && path.startsWith("/") && path.endsWith(".vm");
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.java
new file mode 100644
index 0000000..b041af2
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/VelocityRendererBuilder.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.request.velocity.render;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.velocity.tools.view.VelocityView;
+
+/**
+ * Builds a {@link VelocityRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public final class VelocityRendererBuilder {
+
+ /**
+ * The initialization parameters for VelocityView.
+ */
+ private Map<String, String> params = new HashMap<String, String>();
+
+ /**
+ * The application context.
+ */
+ private ApplicationContext applicationContext;
+
+ /**
+ * Constructor.
+ */
+ private VelocityRendererBuilder() {
+ }
+
+ /**
+ * Returns a new instance of the builder.
+ *
+ * @return A new builder.
+ */
+ public static VelocityRendererBuilder createInstance() {
+ return new VelocityRendererBuilder();
+ }
+
+ /**
+ * Sets a parameter for the internal servlet.
+ *
+ * @param key The name of the parameter.
+ * @param value The value of the parameter.
+ * @return This builder.
+ */
+ public VelocityRendererBuilder setParameter(String key, String value) {
+ params.put(key, value);
+ return this;
+ }
+
+ /**
+ * Sets the application context.
+ *
+ * @param applicationContext The application context.
+ * @return This builder.
+ */
+ public VelocityRendererBuilder setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ return this;
+ }
+
+ /**
+ * Creates the Velocity renderer.
+ *
+ * @return The Velocity renderer.
+ */
+ public VelocityRenderer build() {
+ VelocityView velocityView = new VelocityView(
+ new ApplicationContextJeeConfig(applicationContext, params));
+ return new VelocityRenderer(velocityView);
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/package-info.java b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/package-info.java
new file mode 100644
index 0000000..1b2877f
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/main/java/org/apache/tiles/request/velocity/render/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * $Id: package-info.java 1049711 2010-12-15 21:12:00Z 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.
+ */
+/**
+ * Renderering support for Velocity.
+ */
+package org.apache.tiles.request.velocity.render;
diff --git a/tiles-request/tiles-request-velocity/src/site/site.xml b/tiles-request/tiles-request-velocity/src/site/site.xml
new file mode 100644
index 0000000..8e92dd7
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/site/site.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+/*
+ * $Id: site.xml 1081442 2011-03-14 16:21:08Z 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.
+ */
+-->
+<project name="Apache - Request Microframework">
+ <bannerLeft>
+ <name>Apache Software Foundation</name>
+ <src>http://www.apache.org/images/asf-logo.gif</src>
+ <href>http://www.apache.org</href>
+ </bannerLeft>
+ <bannerRight>
+ <name>Apache Tiles™</name>
+ <src>http://tiles.apache.org/images/logo.png</src>
+ <href>http://tiles.apache.org</href>
+ </bannerRight>
+ <body>
+
+ <links>
+ <item name="Apache" href="http://www.apache.org" />
+ <item name="Tiles" href="http://tiles.apache.org" />
+ </links>
+
+
+ <menu name="Apache Tiles™">
+ <item
+ name="Tiles Home"
+ href="../../index.html"/>
+ <item
+ name="Request Microframework"
+ href="../index.html"/>
+ </menu>
+
+ <menu ref="modules" />
+ <menu ref="reports" />
+
+ </body>
+</project>
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/VelocityRequestTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/VelocityRequestTest.java
new file mode 100644
index 0000000..1bc3f91
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/VelocityRequestTest.java
@@ -0,0 +1,273 @@
+/*
+ * $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.request.velocity;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.DispatchRequest;
+import org.apache.tiles.request.servlet.ExternalWriterHttpServletResponse;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.apache.velocity.context.Context;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityRequest}.
+ */
+public class VelocityRequestTest {
+
+ /**
+ * The request context to test.
+ */
+ private VelocityRequest context;
+
+ /**
+ * The Velocity context.
+ */
+ private Context velocityContext;
+
+ /**
+ * A string writer.
+ */
+ private StringWriter writer;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ velocityContext = createMock(Context.class);
+ writer = new StringWriter();
+ }
+
+ /**
+ * Tests {@link VelocityRequest
+ * #createVelocityRequest(ApplicationContext, HttpServletRequest, HttpServletResponse, Context, Writer)}.
+ */
+ @Test
+ public void testCreateVelocityRequest() {
+ HttpServletRequest httpRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ replay(velocityContext, httpRequest, response, applicationContext);
+ context = VelocityRequest.createVelocityRequest(applicationContext,
+ httpRequest, response, velocityContext, writer);
+ ServletRequest servletRequest = (ServletRequest) context.getWrappedRequest();
+ assertEquals(httpRequest, servletRequest.getRequest());
+ assertEquals(response, servletRequest.getResponse());
+ verify(velocityContext, httpRequest, response, applicationContext);
+ }
+
+ /**
+ * Tests {@link FreemarkerRequest#getNativeScopes()}.
+ */
+ @Test
+ public void testGetAvailableScopes() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+ replay(enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ assertArrayEquals(new String[] {"parent", "page"}, context.getAvailableScopes().toArray());
+ verify(enclosedRequest);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#doInclude(String)}.
+ *
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test
+ public void testDoInclude() throws IOException, ServletException {
+ String path = "this way";
+ ServletRequest enclosedRequest = createMock(ServletRequest.class);
+ HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ RequestDispatcher dispatcher = createMock(RequestDispatcher.class);
+
+ expect(servletRequest.getRequestDispatcher("this way")).andReturn(dispatcher);
+ dispatcher.include(eq(servletRequest), isA(ExternalWriterHttpServletResponse.class));
+ replay(servletRequest, response, dispatcher);
+
+ expect(enclosedRequest.getRequest()).andReturn(servletRequest);
+ expect(enclosedRequest.getResponse()).andReturn(response);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ context.doInclude(path);
+ verify(velocityContext, enclosedRequest, servletRequest, response, dispatcher);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#doInclude(String)}.
+ *
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludeNoRequestDispatcher() throws IOException {
+ String path = "this way";
+ ServletRequest enclosedRequest = createMock(ServletRequest.class);
+ HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+
+ expect(servletRequest.getRequestDispatcher("this way")).andReturn(null);
+ replay(servletRequest, response);
+
+ expect(enclosedRequest.getRequest()).andReturn(servletRequest);
+ expect(enclosedRequest.getResponse()).andReturn(response);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ context.doInclude(path);
+ verify(velocityContext, enclosedRequest, servletRequest, response);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#doInclude(String)}.
+ *
+ * @throws IOException If something goes wrong.
+ * @throws ServletException If something goes wrong.
+ */
+ @Test(expected = IOException.class)
+ public void testDoIncludeServletException() throws IOException, ServletException {
+ String path = "this way";
+ ServletRequest enclosedRequest = createMock(ServletRequest.class);
+ HttpServletRequest servletRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ RequestDispatcher dispatcher = createMock(RequestDispatcher.class);
+
+ expect(servletRequest.getRequestDispatcher("this way")).andReturn(dispatcher);
+ dispatcher.include(eq(servletRequest), isA(ExternalWriterHttpServletResponse.class));
+ expectLastCall().andThrow(new ServletException());
+ replay(servletRequest, response, dispatcher);
+
+ expect(enclosedRequest.getRequest()).andReturn(servletRequest);
+ expect(enclosedRequest.getResponse()).andReturn(response);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ context.doInclude(path);
+ verify(velocityContext, enclosedRequest, servletRequest, response, dispatcher);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#getPrintWriter()}.
+ */
+ @Test
+ public void testGetPrintWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ assertNotNull(context.getPrintWriter());
+ verify(velocityContext, enclosedRequest);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#getPrintWriter()}.
+ */
+ @Test
+ public void testGetPrintWriterPrintWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ PrintWriter printWriter = new PrintWriter(writer);
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, printWriter);
+ assertEquals(printWriter, context.getPrintWriter());
+ verify(velocityContext, enclosedRequest);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#getPrintWriter()}.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testGetPrintWriterNoWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, null);
+ context.getPrintWriter();
+ verify(velocityContext, enclosedRequest);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#getWriter()}.
+ */
+ @Test
+ public void testGetWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ assertEquals(writer, context.getWriter());
+ verify(velocityContext, enclosedRequest);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#getWriter()}.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testGetWriterNoWriter() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, null);
+ context.getWriter();
+ verify(velocityContext, enclosedRequest);
+ }
+
+ /**
+ * Tests {@link VelocityRequest#getPageScope()}.
+ */
+ @Test
+ public void testGetPageScope() {
+ DispatchRequest enclosedRequest = createMock(DispatchRequest.class);
+ expect(enclosedRequest.getAvailableScopes()).andReturn(Collections.singletonList("parent"));
+
+ replay(velocityContext, enclosedRequest);
+ context = new VelocityRequest(enclosedRequest, velocityContext, writer);
+ assertTrue(context.getPageScope() instanceof VelocityScopeMap);
+ verify(velocityContext, enclosedRequest);
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/VelocityScopeMapTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/VelocityScopeMapTest.java
new file mode 100644
index 0000000..4f64306
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/VelocityScopeMapTest.java
@@ -0,0 +1,144 @@
+/*
+ * $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.request.velocity;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Set;
+
+import org.apache.velocity.context.Context;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityScopeMap}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityScopeMapTest {
+
+ /**
+ * The Velocity context.
+ */
+ private Context request;
+
+ /**
+ * The map to test.
+ */
+ private VelocityScopeMap map;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(Context.class);
+ map = new VelocityScopeMap(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.VelocityScopeMap#containsKey(java.lang.Object)}.
+ */
+ @Test
+ public void testContainsKey() {
+ expect(request.containsKey("key")).andReturn(true);
+
+ replay(request);
+ assertTrue(map.containsKey("key"));
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.VelocityScopeMap#isEmpty()}.
+ */
+ @Test
+ public void testIsEmpty() {
+ expect(request.getKeys()).andReturn(new Object[0]);
+
+ replay(request);
+ assertTrue(map.isEmpty());
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.VelocityScopeMap#isEmpty()}.
+ */
+ @Test
+ public void testIsEmptyFalse() {
+ expect(request.getKeys()).andReturn(new Object[] {"one", "two"});
+
+ replay(request);
+ assertFalse(map.isEmpty());
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.VelocityScopeMap#keySet()}.
+ */
+ @Test
+ public void testKeySet() {
+ expect(request.getKeys()).andReturn(new Object[] {"one", "two"});
+
+ replay(request);
+ Set<String> set = map.keySet();
+ assertEquals(2, set.size());
+ assertTrue(set.contains("one"));
+ assertTrue(set.contains("two"));
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.VelocityScopeMap#size()}.
+ */
+ @Test
+ public void testSize() {
+ expect(request.getKeys()).andReturn(new Object[] {"one", "two"});
+
+ replay(request);
+ assertEquals(2, map.size());
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link VelocityScopeMap#put(String, Object)}.
+ */
+ @Test
+ public void testPutStringObject() {
+ expect(request.put("key", "value")).andReturn("oldValue");
+
+ replay(request);
+ assertEquals("oldValue", map.put("key", "value"));
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.VelocityScopeMap#remove(java.lang.Object)}.
+ */
+ @Test
+ public void testRemoveObject() {
+ expect(request.remove("key")).andReturn("value");
+
+ replay(request);
+ assertEquals("value", map.remove("key"));
+ verify(request);
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntimeTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntimeTest.java
new file mode 100644
index 0000000..526c55d
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityAutotagRuntimeTest.java
@@ -0,0 +1,110 @@
+/*
+ * $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.request.velocity.autotag;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+import java.io.Writer;
+import java.util.Map;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.tiles.autotag.core.runtime.ModelBody;
+import org.apache.tiles.request.ApplicationAccess;
+import org.apache.tiles.request.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.velocity.VelocityRequest;
+import org.apache.tiles.request.velocity.autotag.VelocityAutotagRuntime;
+import org.apache.tiles.request.velocity.autotag.VelocityModelBody;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.parser.node.ASTBlock;
+import org.apache.velocity.runtime.parser.node.ASTMap;
+import org.apache.velocity.runtime.parser.node.Node;
+import org.apache.velocity.tools.view.ViewToolContext;
+import org.junit.Test;
+
+public class VelocityAutotagRuntimeTest {
+ @Test
+ public void testCreateRequest() {
+ InternalContextAdapter context = createMock(InternalContextAdapter.class);
+ Writer writer = createMock(Writer.class);
+ Node node = createMock(Node.class);
+ ViewToolContext viewContext = createMock(ViewToolContext.class);
+ HttpServletRequest request = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ ServletContext servletContext = createMock(ServletContext.class);
+ ApplicationContext applicationContext = createMock(ApplicationContext.class);
+
+ expect(context.getInternalUserContext()).andReturn(viewContext);
+ expect(viewContext.getRequest()).andReturn(request);
+ expect(viewContext.getResponse()).andReturn(response);
+ expect(viewContext.getServletContext()).andReturn(servletContext);
+ expect(servletContext.getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE)).andReturn(applicationContext);
+
+ replay(context, writer, node, viewContext, request, response, servletContext, applicationContext);
+ VelocityAutotagRuntime runtime = new VelocityAutotagRuntime();
+ runtime.render(context, writer, node);
+ Request velocityRequest = runtime.createRequest();
+ assertTrue(velocityRequest instanceof VelocityRequest);
+ verify(context, writer, node, viewContext, request, response, servletContext, applicationContext);
+ }
+
+ @Test
+ public void testCreateModelBody() {
+ InternalContextAdapter context = createMock(InternalContextAdapter.class);
+ Writer writer = createMock(Writer.class);
+ Node node = createMock(Node.class);
+ ASTBlock block = createMock(ASTBlock.class);
+ expect(node.jjtGetChild(1)).andReturn(block);
+ replay(context, writer, node, block);
+ VelocityAutotagRuntime runtime = new VelocityAutotagRuntime();
+ runtime.render(context, writer, node);
+ ModelBody modelBody = runtime.createModelBody();
+ assertTrue(modelBody instanceof VelocityModelBody);
+ verify(context, writer, node, block);
+ }
+
+ @Test
+ public void testGetParameter() {
+ InternalContextAdapter context = createMock(InternalContextAdapter.class);
+ Writer writer = createMock(Writer.class);
+ Node node = createMock(Node.class);
+ ASTMap astMap = createMock(ASTMap.class);
+ @SuppressWarnings("unchecked")
+ Map<String, Object> params = createMock(Map.class);
+ expect(node.jjtGetChild(0)).andReturn(astMap);
+ expect(astMap.value(context)).andReturn(params);
+ expect(params.get(eq("notnullParam"))).andReturn(new Integer(42)).anyTimes();
+ expect(params.get(eq("nullParam"))).andReturn(null).anyTimes();
+ replay(context, writer, node, astMap, params);
+ VelocityAutotagRuntime runtime = new VelocityAutotagRuntime();
+ runtime.render(context, writer, node);
+ Object notnullParam = runtime.getParameter("notnullParam", null);
+ Object nullParam = runtime.getParameter("nullParam", null);
+ Object notnullParamDefault = runtime.getParameter("notnullParam", new Integer(24));
+ Object nullParamDefault = runtime.getParameter("nullParam", new Integer(24));
+ assertEquals(42, notnullParam);
+ assertEquals(null, nullParam);
+ assertEquals(42, notnullParamDefault);
+ assertEquals(24, nullParamDefault);
+ verify(context, writer, node, astMap, params);
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityModelBodyTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityModelBodyTest.java
new file mode 100644
index 0000000..bca5efd
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityModelBodyTest.java
@@ -0,0 +1,60 @@
+/*
+ * $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.request.velocity.autotag;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.tiles.request.velocity.autotag.VelocityModelBody;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.parser.node.ASTBlock;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityModelBody}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityModelBodyTest {
+
+ /**
+ * Test method for {@link org.apache.tiles.request.velocity.autotag.VelocityModelBody#evaluate(java.io.Writer)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testEvaluateWriter() throws IOException {
+ InternalContextAdapter internalContextAdapter = createMock(InternalContextAdapter.class);
+ ASTBlock body = createMock(ASTBlock.class);
+ Writer writer = createMock(Writer.class);
+ expect(body.render(internalContextAdapter, writer)).andReturn(true);
+
+ replay(internalContextAdapter, body, writer);
+ VelocityModelBody modelBody = createMockBuilder(VelocityModelBody.class)
+ .withConstructor(internalContextAdapter, body, writer)
+ .createMock();
+ replay(modelBody);
+ modelBody.evaluate(writer);
+ verify(internalContextAdapter, body, writer, modelBody);
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityUtilTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityUtilTest.java
new file mode 100644
index 0000000..633ed9c
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/autotag/VelocityUtilTest.java
@@ -0,0 +1,71 @@
+/*
+ * $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.request.velocity.autotag;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Map;
+
+import org.apache.tiles.request.velocity.autotag.VelocityUtil;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.runtime.parser.node.ASTMap;
+import org.apache.velocity.runtime.parser.node.Node;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityUtil}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityUtilTest {
+
+ /**
+ * Test method for {@link VelocityUtil#getParameters(InternalContextAdapter, Node)}.
+ */
+ @Test
+ public void testGetParameters() {
+ InternalContextAdapter context = createMock(InternalContextAdapter.class);
+ Node node = createMock(Node.class);
+ ASTMap astMap = createMock(ASTMap.class);
+ @SuppressWarnings("unchecked")
+ Map<String, Object> params = createMock(Map.class);
+
+ expect(node.jjtGetChild(0)).andReturn(astMap);
+ expect(astMap.value(context)).andReturn(params);
+
+ replay(context, node, astMap, params);
+ assertSame(params, VelocityUtil.getParameters(context, node));
+ verify(context, node, astMap, params);
+ }
+
+ /**
+ * Test method for {@link VelocityUtil#getObject(Object, Object)}.
+ */
+ @Test
+ public void testGetObject() {
+ assertEquals(new Integer(1), VelocityUtil.getObject(new Integer(1), new Integer(2)));
+ assertEquals(new Integer(1), VelocityUtil.getObject(new Integer(1), null));
+ assertEquals(new Integer(2), VelocityUtil.getObject(null, new Integer(2)));
+ assertNull(VelocityUtil.getObject(null, null));
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractorTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractorTest.java
new file mode 100644
index 0000000..4a86fe8
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/extractor/VelocityScopeExtractorTest.java
@@ -0,0 +1,110 @@
+/*
+ * $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.request.velocity.extractor;
+
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+
+import org.apache.velocity.context.Context;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityScopeExtractor}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityScopeExtractorTest {
+
+ /**
+ * The Velocity context.
+ */
+ private Context request;
+
+ /**
+ * The extractor to test.
+ */
+ private VelocityScopeExtractor extractor;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ request = createMock(Context.class);
+ extractor = new VelocityScopeExtractor(request);
+ }
+
+ /**
+ * Test method for {@link VelocityScopeExtractor#removeValue(java.lang.String)}.
+ */
+ @Test
+ public void testRemoveValue() {
+ expect(request.remove("key")).andReturn("value");
+
+ replay(request);
+ extractor.removeValue("key");
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link VelocityScopeExtractor#getKeys()}.
+ */
+ @Test
+ public void testGetKeys() {
+ expect(request.getKeys()).andReturn(new Object[] {"one", "two"});
+
+ replay(request);
+ Enumeration<String> keys = extractor.getKeys();
+ assertTrue(keys.hasMoreElements());
+ assertEquals("one", keys.nextElement());
+ assertTrue(keys.hasMoreElements());
+ assertEquals("two", keys.nextElement());
+ assertFalse(keys.hasMoreElements());
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link VelocityScopeExtractor#getValue(java.lang.String)}.
+ */
+ @Test
+ public void testGetValue() {
+ expect(request.get("key")).andReturn("value");
+
+ replay(request);
+ assertEquals("value", extractor.getValue("key"));
+ verify(request);
+ }
+
+ /**
+ * Test method for {@link VelocityScopeExtractor#setValue(java.lang.String, java.lang.Object)}.
+ */
+ @Test
+ public void testSetValue() {
+ expect(request.put("key", "value")).andReturn(null);
+
+ replay(request);
+ extractor.setValue("key", "value");
+ verify(request);
+ }
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfigTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfigTest.java
new file mode 100644
index 0000000..036e6e5
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/render/ApplicationContextJeeConfigTest.java
@@ -0,0 +1,145 @@
+/*
+ * $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.request.velocity.render;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tiles.request.servlet.ServletApplicationContext;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests {@link ApplicationContextJeeConfig}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ApplicationContextJeeConfigTest {
+
+ /**
+ * The configuration to test.
+ */
+ private ApplicationContextJeeConfig config;
+
+ /**
+ * The application context.
+ */
+ private ServletApplicationContext applicationContext;
+
+ /**
+ * The servlet context.
+ */
+ private ServletContext servletContext;
+
+ /**
+ * Custom parameters.
+ */
+ private Map<String, String> params;
+
+ /**
+ * Sets up the test.
+ */
+ @Before
+ public void setUp() {
+ servletContext = createMock(ServletContext.class);
+ applicationContext = new ServletApplicationContext(servletContext);
+ }
+
+ /**
+ * Tears down the test.
+ */
+ @After
+ public void tearDown() {
+ verify(servletContext);
+ }
+
+ /**
+ * Tests {@link ApplicationContextJeeConfig#getInitParameter(String)}.
+ */
+ @Test
+ public void testGetInitParameter() {
+ params = new HashMap<String, String>();
+ params.put("one", "value1");
+ config = new ApplicationContextJeeConfig(applicationContext, params);
+ replay(servletContext);
+ assertEquals("value1", config.getInitParameter("one"));
+ }
+
+ /**
+ * Tests {@link ApplicationContextJeeConfig#findInitParameter(String)}.
+ */
+ @Test
+ public void testFindInitParameter() {
+ params = new HashMap<String, String>();
+ params.put("one", "value1");
+ config = new ApplicationContextJeeConfig(applicationContext, params);
+ replay(servletContext);
+ assertEquals("value1", config.findInitParameter("one"));
+ }
+
+ /**
+ * Tests {@link ApplicationContextJeeConfig#getInitParameterNames()}.
+ */
+ @Test
+ public void testGetInitParameterNames() {
+ params = new HashMap<String, String>();
+ params.put("one", "value1");
+ config = new ApplicationContextJeeConfig(applicationContext, params);
+ replay(servletContext);
+ @SuppressWarnings("unchecked")
+ Enumeration<String> names = config.getInitParameterNames();
+ assertTrue(names.hasMoreElements());
+ assertEquals("one", names.nextElement());
+ assertFalse(names.hasMoreElements());
+ }
+
+ /**
+ * Tests {@link ApplicationContextJeeConfig#getName()}.
+ */
+ @Test
+ public void testGetName() {
+ params = new HashMap<String, String>();
+ params.put("one", "value1");
+ config = new ApplicationContextJeeConfig(applicationContext, params);
+ replay(servletContext);
+ assertEquals("Application Context JEE Config", config.getName());
+ }
+
+ /**
+ * Tests {@link ApplicationContextJeeConfig#getServletContext()}.
+ */
+ @Test
+ public void testGetServletContext() {
+ params = new HashMap<String, String>();
+ params.put("one", "value1");
+ config = new ApplicationContextJeeConfig(applicationContext, params);
+ replay(servletContext);
+ assertEquals(servletContext, config.getServletContext());
+ }
+
+}
diff --git a/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/render/VelocityRendererTest.java b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/render/VelocityRendererTest.java
new file mode 100644
index 0000000..9a07157
--- /dev/null
+++ b/tiles-request/tiles-request-velocity/src/test/java/org/apache/tiles/request/velocity/render/VelocityRendererTest.java
@@ -0,0 +1,109 @@
+/*
+ * $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.request.velocity.render;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.classextension.EasyMock.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tiles.request.render.CannotRenderException;
+import org.apache.tiles.request.render.Renderer;
+import org.apache.tiles.request.servlet.ServletRequest;
+import org.apache.velocity.Template;
+import org.apache.velocity.tools.view.VelocityView;
+import org.apache.velocity.tools.view.ViewToolContext;
+import org.junit.Test;
+
+/**
+ * Tests {@link VelocityRenderer}.
+ *
+ * @version $Rev$ $Date$
+ */
+public class VelocityRendererTest {
+
+ /**
+ * Tests {@link VelocityRenderer#render(String, org.apache.tiles.request.Request)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test
+ public void testRender() throws IOException {
+ VelocityView view = createMock(VelocityView.class);
+ ServletRequest request = createMock(ServletRequest.class);
+ HttpServletRequest httpRequest = createMock(HttpServletRequest.class);
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ ViewToolContext context = createMock(ViewToolContext.class);
+ Template template = createMock(Template.class);
+ Writer writer = createMock(Writer.class);
+
+ expect(request.getRequest()).andReturn(httpRequest);
+ expect(request.getResponse()).andReturn(response);
+ expect(view.createContext(httpRequest, response)).andReturn(context);
+ expect(view.getTemplate("/test.vm")).andReturn(template);
+ expect(request.getWriter()).andReturn(writer);
+ view.merge(template, context, writer);
+
+ replay(view, request, httpRequest, response, context, template, writer);
+ Renderer renderer = new VelocityRenderer(view);
+ renderer.render("/test.vm", request);
+ verify(view, request, httpRequest, response, context, template, writer);
+ }
+
+ /**
+ * Tests {@link VelocityRenderer#render(String, org.apache.tiles.request.Request)}.
+ * @throws IOException If something goes wrong.
+ */
+ @Test(expected = CannotRenderException.class)
+ public void testRenderException() throws IOException {
+ VelocityView view = createMock(VelocityView.class);
+ ServletRequest request = createMock(ServletRequest.class);
+
+ replay(view, request);
+ Renderer renderer = new VelocityRenderer(view);
+ try {
+ renderer.render(null, request);
+ } finally {
+ verify(view, request);
+ }
+ }
+
+ /**
+ * Test method for
+ * {@link VelocityRenderer#isRenderable(String, org.apache.tiles.request.Request)}
+ * .
+ */
+ @Test
+ public void testIsRenderable() {
+ VelocityView view = createMock(VelocityView.class);
+ replay(view);
+ Renderer renderer = new VelocityRenderer(view);
+ assertTrue(renderer.isRenderable("/my/template.vm", null));
+ assertFalse(renderer.isRenderable("my/template.vm", null));
+ assertFalse(renderer.isRenderable("/my/template.jsp", null));
+ verify(view);
+ }
+
+}