Decoupling the generator from the runtime in autotag

git-svn-id: https://svn.apache.org/repos/asf/tiles/framework/trunk@1201651 13f79535-47bb-0310-9956-ffa450edef68
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
index fc73df1..b78e1ec 100644
--- 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
@@ -106,7 +106,7 @@
             propsStream.close();
             TemplateGenerator generator = createTemplateGeneratorFactory(
                     new VelocityEngine(props)).createTemplateGenerator();
-            generator.generate(packageName, suite, getParameters());
+            generator.generate(packageName, suite, getParameters(), getRuntimeClass());
             if (generator.isGeneratingResources()) {
                 Resource resource = new Resource();
                 resource.setDirectory(resourcesOutputDirectory.getAbsolutePath());
@@ -167,4 +167,9 @@
         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/GenerateFreemarkerMojo.java b/tiles-autotag/maven-autotag-plugin/src/main/java/org/apache/tiles/autotag/plugin/GenerateFreemarkerMojo.java
index ba14a0e..9498ec3 100644
--- 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
@@ -37,12 +37,25 @@
  */
 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) {
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
index 5ac46a9..c76d536 100644
--- 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
@@ -62,6 +62,13 @@
      */
     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() {
@@ -70,6 +77,12 @@
         return params;
     }
 
+    /** {@inheritDoc} */
+    @Override
+    protected String getRuntimeClass() {
+        return jspRuntime;
+    }
+
     @Override
     protected TemplateGeneratorFactory createTemplateGeneratorFactory(
             VelocityEngine velocityEngine) {
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
index 5a8f9a5..bda7ac4 100644
--- 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
@@ -54,12 +54,25 @@
  */
 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) {
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
index 71fa582..65e47ee 100644
--- 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
@@ -77,7 +77,8 @@
         expect(mojo.createTemplateGeneratorFactory(isA(VelocityEngine.class))).andReturn(factory);
         expect(factory.createTemplateGenerator()).andReturn(generator);
         expect(mojo.getParameters()).andReturn(params);
-        generator.generate(eq("my.package"), isA(TemplateSuite.class), eq(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));
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/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
index 76e875f..dd40607 100644
--- 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
@@ -60,21 +60,23 @@
 
     @Override
     public void generate(File directory, String packageName,
-            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters) {
+            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters,
+            String runtimeClass) {
         File dir = new File(directory, getDirectoryName(directory, packageName,
-                suite, clazz, parameters));
+                suite, clazz, parameters, runtimeClass));
         dir.mkdirs();
-        File file = new File(dir, getFilename(dir, packageName, suite, clazz, parameters));
+        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));
+                    packageName, suite, clazz, parameters, runtimeClass));
             Writer writer = new FileWriter(file);
             try {
                 template.merge(context, writer);
@@ -110,7 +112,7 @@
      * @return The template path.
      */
     protected abstract String getTemplatePath(File directory,
-            String packageName, TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters);
+            String packageName, TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters, String runtimeClass);
 
     /**
      * Calculates and returns the filename of the generated file.
@@ -123,7 +125,7 @@
      * @return The template path.
      */
     protected abstract String getFilename(File directory, String packageName,
-            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters);
+            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters, String runtimeClass);
 
     /**
      * Calculates and returns the directory where the file will be written..
@@ -136,5 +138,5 @@
      * @return The template path.
      */
     protected abstract String getDirectoryName(File directory,
-            String packageName, TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters);
+            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/BasicTemplateGenerator.java b/tiles-autotag/tiles-autotag-core/src/main/java/org/apache/tiles/autotag/generate/BasicTemplateGenerator.java
index 3f2f728..7fe7ffd 100644
--- 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
@@ -76,14 +76,15 @@
 
 
     @Override
-    public void generate(String packageName, TemplateSuite suite, Map<String, String> parameters) {
+    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);
+                        suite, templateClass, parameters, runtimeClass);
             }
         }
     }
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
index a514831..c6fe9e0 100644
--- 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
@@ -41,7 +41,9 @@
      * @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);
+            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
index 78b79f8..db67873 100644
--- 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
@@ -38,8 +38,10 @@
      * @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);
+    void generate(String packageName, TemplateSuite suite, Map<String, String> parameters, 
+        String runtimeClass);
 
     /**
      * Indicates that this generator generates resources.
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
index b365c62..35bdd5b 100644
--- 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
@@ -99,17 +99,18 @@
         @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)).andReturn("mydir");
+        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)).andReturn("myfile.txt");
+        expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
         String sampleVmPath = "/sample.vm";
-        expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters)).andReturn(sampleVmPath);
+        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);
+        generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
         verify(velocityEngine, generator, suite, clazz, template, parameters);
     }
 
@@ -127,16 +128,17 @@
         @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)).andReturn("mydir");
+        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)).andReturn("myfile.txt");
+        expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
         String sampleVmPath = "/sample.vm";
-        expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters)).andReturn(sampleVmPath);
+        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);
+        generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
         verify(velocityEngine, generator, suite, clazz, template, parameters);
     }
 
@@ -154,16 +156,17 @@
         @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)).andReturn("mydir");
+        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)).andReturn("myfile.txt");
+        expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
         String sampleVmPath = "/sample.vm";
-        expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters)).andReturn(sampleVmPath);
+        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);
+        generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
         verify(velocityEngine, generator, suite, clazz, template, parameters);
     }
 
@@ -181,16 +184,17 @@
         @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)).andReturn("mydir");
+        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)).andReturn("myfile.txt");
+        expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
         String sampleVmPath = "/sample.vm";
-        expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters)).andReturn(sampleVmPath);
+        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);
+        generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
         verify(velocityEngine, generator, suite, clazz, template, parameters);
     }
 
@@ -210,18 +214,19 @@
         @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)).andReturn("mydir");
+        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)).andReturn("myfile.txt");
+        expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
         String sampleVmPath = "/sample.vm";
-        expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters)).andReturn(sampleVmPath);
+        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);
+        generator.generate(directory, packageName, suite, clazz, parameters, runtimeClass);
         verify(velocityEngine, generator, suite, clazz, template, parameters);
     }
 
@@ -241,18 +246,19 @@
         @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)).andReturn("mydir");
+        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)).andReturn("myfile.txt");
+        expect(generator.getFilename(mydir , packageName, suite, clazz, parameters, runtimeClass)).andReturn("myfile.txt");
         String sampleVmPath = "/sample.vm";
-        expect(generator.getTemplatePath(mydir, packageName, suite, clazz, parameters)).andReturn(sampleVmPath);
+        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);
+        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/BasicTemplateGeneratorTest.java b/tiles-autotag/tiles-autotag-core/src/test/java/org/apache/tiles/autotag/generate/BasicTemplateGeneratorTest.java
index 80e40b7..15463d3 100644
--- 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
@@ -62,7 +62,7 @@
 
         expect(suite.getTemplateClasses()).andReturn(templateClasses);
         templateSuiteGenerator.generate(file, "my.package", suite, parameters);
-        templateClassGenerator.generate(file, "my.package", suite, templateClass, parameters);
+        templateClassGenerator.generate(file, "my.package", suite, templateClass, parameters, "my.Runtime");
 
         replay(suite, templateClass, templateSuiteGenerator, templateClassGenerator, parameters);
         TSGeneratorDirectoryPair tsPair = new TSGeneratorDirectoryPair(file, templateSuiteGenerator);
@@ -74,7 +74,7 @@
         BasicTemplateGenerator generator = new BasicTemplateGenerator(tsList, tcList, true, false);
         assertTrue(generator.isGeneratingClasses());
         assertFalse(generator.isGeneratingResources());
-        generator.generate("my.package", suite, parameters);
+        generator.generate("my.package", suite, parameters, "my.Runtime");
         verify(suite, templateClass, templateSuiteGenerator, templateClassGenerator, parameters);
     }
 }
diff --git a/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/BodyFMModel.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/BodyFMModel.java
deleted file mode 100644
index 01f67c8..0000000
--- a/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/BodyFMModel.java
+++ /dev/null
@@ -1,63 +0,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.
- */
-package org.apache.tiles.autotag.freemarker.runtime;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.apache.tiles.autotag.core.runtime.ModelBody;
-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;
-
-/**
- * Base directive model for models with a body.
- *
- * @version $Rev$ $Date$
- */
-public abstract class BodyFMModel implements TemplateDirectiveModel {
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
-            TemplateDirectiveBody body) throws IOException {
-        Request request = FreemarkerRequest.createServletFreemarkerRequest(
-                FreemarkerRequestUtil.getApplicationContext(env), env);
-        ModelBody modelBody = new FreemarkerModelBody(env.getOut(), body);
-        execute(params, request, modelBody);
-    }
-
-    /**
-     * Executes the model.
-     *
-     * @param parms Parameters.
-     * @param request The request.
-     * @param modelBody The body.
-     * @throws IOException If something goes wrong.
-     */
-    protected abstract void execute(Map<String, TemplateModel> parms,
-            Request request, ModelBody modelBody) throws IOException;
-}
diff --git a/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/BodylessFMModel.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/BodylessFMModel.java
deleted file mode 100644
index 5b1fbb7..0000000
--- a/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/BodylessFMModel.java
+++ /dev/null
@@ -1,60 +0,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.
- */
-package org.apache.tiles.autotag.freemarker.runtime;
-
-import java.io.IOException;
-import java.util.Map;
-
-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;
-
-/**
- * Base directive model for models with a body.
- *
- * @version $Rev$ $Date$
- */
-public abstract class BodylessFMModel implements TemplateDirectiveModel {
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,
-            TemplateDirectiveBody body) throws IOException {
-        Request request = FreemarkerRequest.createServletFreemarkerRequest(
-                FreemarkerRequestUtil.getApplicationContext(env), env);
-        execute(params, request);
-    }
-
-    /**
-     * Executes the model.
-     *
-     * @param parms Parameters.
-     * @param request The request.
-     * @throws IOException If something goes wrong.
-     */
-    protected abstract void execute(Map<String, TemplateModel> parms,
-            Request request) throws IOException;
-}
diff --git a/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerAutotagRuntime.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerAutotagRuntime.java
new file mode 100644
index 0000000..64ada57
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/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.autotag.freemarker.runtime;
+
+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-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerUtil.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerUtil.java
index 6f50038..c3a9cbd 100644
--- a/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerUtil.java
+++ b/tiles-autotag/tiles-autotag-freemarker-runtime/src/main/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerUtil.java
@@ -50,9 +50,12 @@
      */
     public static Object getAsObject(TemplateModel model, Object defaultValue) {
         try {
-            Object retValue = DeepUnwrap.unwrap(model);
-            if (retValue == null) {
-                retValue = defaultValue;
+            Object retValue = defaultValue;
+            if (model != null) {
+                Object value = DeepUnwrap.unwrap(model);
+                if (value != null) {
+                    retValue = value;
+                }
             }
             return retValue;
         } catch (TemplateModelException e) {
diff --git a/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/BodyFMModelTest.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/BodyFMModelTest.java
deleted file mode 100644
index 3147c33..0000000
--- a/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/BodyFMModelTest.java
+++ /dev/null
@@ -1,116 +0,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.
- */
-package org.apache.tiles.autotag.freemarker.runtime;
-
-import static org.easymock.EasyMock.*;
-
-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.request.ApplicationContext;
-import org.apache.tiles.request.freemarker.FreemarkerRequest;
-import org.apache.tiles.request.util.ApplicationAccess;
-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;
-
-/**
- * Tests {@link BodyFMModel}.
- *
- * @version $Rev$ $Date$
- */
-public class BodyFMModelTest {
-
-    /**
-     * Test method for
-     * {@link BodyFMModel#execute(Environment, Map, TemplateModel[], TemplateDirectiveBody)}
-     * .
-     *
-     * @throws IOException If something goes wrong.
-     * @throws TemplateModelException If something goes wrong.
-     */
-    @Test
-    public void testExecute() throws IOException, TemplateModelException {
-        BodyFMModel model = createMockBuilder(BodyFMModel.class).createMock();
-        @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);
-
-        model.execute(eq(params), isA(FreemarkerRequest.class),
-                isA(FreemarkerModelBody.class));
-
-        replay(model, params, body);
-        model.execute(env, params, new TemplateModel[0], body);
-        verify(model, params, template, rootDataModel, out, servlet, wrapper,
-                servletContext, httpServletRequest, httpServletResponse, body,
-                applicationContext);
-    }
-
-}
diff --git a/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/BodylessFMModelTest.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/BodylessFMModelTest.java
deleted file mode 100644
index 70a99c7..0000000
--- a/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/BodylessFMModelTest.java
+++ /dev/null
@@ -1,113 +0,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.
- */
-package org.apache.tiles.autotag.freemarker.runtime;
-
-import static org.easymock.EasyMock.*;
-
-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.request.ApplicationContext;
-import org.apache.tiles.request.freemarker.FreemarkerRequest;
-import org.apache.tiles.request.util.ApplicationAccess;
-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.TemplateHashModel;
-import freemarker.template.TemplateModel;
-import freemarker.template.TemplateModelException;
-
-/**
- * Tests {@link BodyFMModel}.
- *
- * @version $Rev$ $Date$
- */
-public class BodylessFMModelTest {
-
-    /**
-     * Test method for
-     * {@link BodylessFMModel#execute(Environment, Map, TemplateModel[], TemplateDirectiveBody)}
-     * .
-     *
-     * @throws IOException If something goes wrong.
-     * @throws TemplateModelException If something goes wrong.
-     */
-    @Test
-    public void testExecute() throws IOException, TemplateModelException {
-        BodylessFMModel model = createMockBuilder(BodylessFMModel.class).createMock();
-        @SuppressWarnings("unchecked")
-        Map<String, TemplateModel> params = createMock(Map.class);
-        Template template = createMock(Template.class);
-        TemplateHashModel rootDataModel = createMock(TemplateHashModel.class);
-        Writer out = createMock(Writer.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);
-
-        model.execute(eq(params), isA(FreemarkerRequest.class));
-
-        replay(model, params);
-        model.execute(env, params, new TemplateModel[0], null);
-        verify(model, params, template, rootDataModel, out, servlet, wrapper,
-                servletContext, httpServletRequest, httpServletResponse,
-                applicationContext);
-    }
-
-}
diff --git a/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerAutotagRuntimeTest.java b/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerAutotagRuntimeTest.java
new file mode 100644
index 0000000..db31177
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-freemarker-runtime/src/test/java/org/apache/tiles/autotag/freemarker/runtime/FreemarkerAutotagRuntimeTest.java
@@ -0,0 +1,158 @@
+/*
+ * $Id$
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.runtime;
+
+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.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.freemarker.FreemarkerRequest;
+import org.apache.tiles.request.util.ApplicationAccess;
+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-autotag/tiles-autotag-freemarker/pom.xml b/tiles-autotag/tiles-autotag-freemarker/pom.xml
index f79a6fe..6b37cfd 100644
--- a/tiles-autotag/tiles-autotag-freemarker/pom.xml
+++ b/tiles-autotag/tiles-autotag-freemarker/pom.xml
@@ -17,11 +17,6 @@
   		<version>1.0-SNAPSHOT</version>
   	</dependency>
   	<dependency>
-  		<groupId>org.apache.tiles</groupId>
-  		<artifactId>tiles-request-freemarker</artifactId>
-  		<version>1.0-SNAPSHOT</version>
-  	</dependency>
-  	<dependency>
   		<groupId>junit</groupId>
   		<artifactId>junit</artifactId>
   		<version>4.8.1</version>
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
index dc7fd14..ad08ea7 100644
--- 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
@@ -46,19 +46,22 @@
 
     @Override
     protected String getDirectoryName(File directory, String packageName,
-            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters) {
+            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) {
+            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) {
+            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/resources/org/apache/tiles/autotag/freemarker/fmModel.vm b/tiles-autotag/tiles-autotag-freemarker/src/main/resources/org/apache/tiles/autotag/freemarker/fmModel.vm
index 20774cb..cc83fd8 100644
--- 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
@@ -25,10 +25,13 @@
 #if(${clazz.hasBody()})
 import org.apache.tiles.autotag.core.runtime.ModelBody;
 #end
-import org.apache.tiles.autotag.freemarker.runtime.Body#if(!${clazz.hasBody()})less#{end}FMModel;
-import org.apache.tiles.autotag.freemarker.runtime.FreemarkerUtil;
+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;
 
 /**
@@ -36,7 +39,7 @@
  * ${line}
 #end
  */
-public class ${clazz.tagClassPrefix}FMModel extends Body#if(!${clazz.hasBody()})less#{end}FMModel {
+public class ${clazz.tagClassPrefix}FMModel implements TemplateDirectiveModel {
 
     /**
      * The template model.
@@ -54,11 +57,21 @@
     }
 
     /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
     @Override
-    public void execute(Map<String, TemplateModel> parms, Request request#if(${clazz.hasBody()}), ModelBody modelBody#end) throws IOException {
+    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})) FreemarkerUtil.getAsObject(parms.get("${parameter.exportedName}"), $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})),
+            ($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/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
index f7cd4b6..6c41678 100644
--- 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
@@ -88,7 +88,8 @@
                 "doStuff", "DoStuff", executeMethod);
         clazz.setDocumentation("Documentation of the DoStuff class.");
 
-        generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null);
+        generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null,
+                           "org.apache.tiles.autotag.freemarker.test.Runtime");
 
         InputStream expected = getClass()
                 .getResourceAsStream(
@@ -122,7 +123,8 @@
 
         suite.addTemplateClass(clazz);
 
-        generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null);
+        generator.generate(file, "org.apache.tiles.autotag.freemarker.test", suite, clazz, null,
+                           "org.apache.tiles.autotag.freemarker.test.Runtime");
 
         expected = getClass()
                 .getResourceAsStream(
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
index d4b6726..9d81a1d 100644
--- 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
@@ -4,16 +4,19 @@
 import java.util.Map;
 
 import org.apache.tiles.autotag.core.runtime.ModelBody;
-import org.apache.tiles.autotag.freemarker.runtime.BodyFMModel;
-import org.apache.tiles.autotag.freemarker.runtime.FreemarkerUtil;
+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 extends BodyFMModel {
+public class DoStuffFMModel implements TemplateDirectiveModel {
 
     /**
      * The template model.
@@ -31,12 +34,20 @@
     }
 
     /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
     @Override
-    public void execute(Map<String, TemplateModel> parms, Request request, ModelBody modelBody) throws IOException {
+    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) FreemarkerUtil.getAsObject(parms.get("one"), null),
-            (java.lang.Integer) FreemarkerUtil.getAsObject(parms.get("two"), 0),
-            (java.lang.Boolean) FreemarkerUtil.getAsObject(parms.get("three"), false),
+            (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
index 3141f34..375dcc3 100644
--- 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
@@ -3,16 +3,19 @@
 import java.io.IOException;
 import java.util.Map;
 
-import org.apache.tiles.autotag.freemarker.runtime.BodylessFMModel;
-import org.apache.tiles.autotag.freemarker.runtime.FreemarkerUtil;
+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 extends BodylessFMModel {
+public class DoStuffNoBodyFMModel implements TemplateDirectiveModel {
 
     /**
      * The template model.
@@ -30,12 +33,19 @@
     }
 
     /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
     @Override
-    public void execute(Map<String, TemplateModel> parms, Request request) throws IOException {
+    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) FreemarkerUtil.getAsObject(parms.get("one"), null),
-            (java.lang.Float) FreemarkerUtil.getAsObject(parms.get("two"), 0.0f),
-            (java.util.Date) FreemarkerUtil.getAsObject(parms.get("three"), null),
+            (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-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/BodyTag.java b/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/BodyTag.java
deleted file mode 100644
index 6c52040..0000000
--- a/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/BodyTag.java
+++ /dev/null
@@ -1,60 +0,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.
- */
-package org.apache.tiles.autotag.jsp.runtime;
-
-import java.io.IOException;
-
-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.request.Request;
-import org.apache.tiles.request.jsp.JspRequest;
-
-/**
- * Base class for a tag with body.
- *
- * @version $Rev$ $Date$
- */
-public abstract class BodyTag extends SimpleTagSupport {
-
-    @Override
-    public void doTag() throws IOException {
-        JspContext pageContext = getJspContext();
-        Request request = JspRequest.createServletJspRequest(
-                org.apache.tiles.request.jsp.JspUtil
-                        .getApplicationContext(pageContext),
-                (PageContext) pageContext);
-        ModelBody modelBody = new JspModelBody(getJspBody(), pageContext);
-        execute(request, modelBody);
-    }
-
-    /**
-     * Executes the tag.
-     *
-     * @param request The request.
-     * @param modelBody The body.
-     * @throws IOException If something goes wrong.
-     */
-    protected abstract void execute(Request request, ModelBody modelBody)
-            throws IOException;
-}
diff --git a/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/BodylessTag.java b/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/BodylessTag.java
deleted file mode 100644
index daaf22d..0000000
--- a/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/BodylessTag.java
+++ /dev/null
@@ -1,56 +0,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.
- */
-package org.apache.tiles.autotag.jsp.runtime;
-
-import java.io.IOException;
-
-import javax.servlet.jsp.JspContext;
-import javax.servlet.jsp.PageContext;
-import javax.servlet.jsp.tagext.SimpleTagSupport;
-
-import org.apache.tiles.request.Request;
-import org.apache.tiles.request.jsp.JspRequest;
-
-/**
- * Base class for a tag without body.
- *
- * @version $Rev$ $Date$
- */
-public abstract class BodylessTag extends SimpleTagSupport {
-
-    @Override
-    public void doTag() throws IOException {
-        JspContext pageContext = getJspContext();
-        Request request = JspRequest.createServletJspRequest(
-                org.apache.tiles.request.jsp.JspUtil
-                        .getApplicationContext(pageContext),
-                (PageContext) pageContext);
-        execute(request);
-    }
-
-    /**
-     * Executes the tag.
-     *
-     * @param request The request.
-     * @throws IOException If something goes wrong.
-     */
-    protected abstract void execute(Request request) throws IOException;
-}
diff --git a/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/JspAutotagRuntime.java b/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/JspAutotagRuntime.java
new file mode 100644
index 0000000..c7e74cf
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp-runtime/src/main/java/org/apache/tiles/autotag/jsp/runtime/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.autotag.jsp.runtime;
+
+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-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/BodyTagTest.java b/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/BodyTagTest.java
deleted file mode 100644
index 576ac91..0000000
--- a/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/BodyTagTest.java
+++ /dev/null
@@ -1,73 +0,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.
- */
-package org.apache.tiles.autotag.jsp.runtime;
-
-import static org.easymock.EasyMock.*;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.jsp.JspWriter;
-import javax.servlet.jsp.PageContext;
-import javax.servlet.jsp.tagext.JspFragment;
-
-import org.apache.tiles.request.ApplicationContext;
-import org.apache.tiles.request.jsp.JspRequest;
-import org.apache.tiles.request.util.ApplicationAccess;
-import org.junit.Test;
-
-/**
- * Tests {@link BodyTag}.
- *
- * @version $Rev$ $Date$
- */
-public class BodyTagTest {
-
-    /**
-     * Test method for {@link org.apache.tiles.autotag.jsp.runtime.BodyTag#doTag()}.
-     * @throws IOException If something goes wrong.
-     */
-    @Test
-    public void testDoTag() throws IOException {
-        PageContext pageContext = createMock(PageContext.class);
-        JspFragment jspBody = createMock(JspFragment.class);
-        BodyTag tag = createMockBuilder(BodyTag.class).createMock();
-        ApplicationContext applicationContext = createMock(ApplicationContext.class);
-        HttpServletRequest httpServletRequest = createMock(HttpServletRequest.class);
-        HttpServletResponse httpServletResponse = createMock(HttpServletResponse.class);
-        JspWriter jspWriter = createMock(JspWriter.class);
-
-        expect(pageContext.getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE,
-                PageContext.APPLICATION_SCOPE)).andReturn(applicationContext);
-        expect(pageContext.getRequest()).andReturn(httpServletRequest);
-        expect(pageContext.getResponse()).andReturn(httpServletResponse);
-        expect(pageContext.getOut()).andReturn(jspWriter);
-        tag.execute(isA(JspRequest.class), isA(JspModelBody.class));
-
-        replay(pageContext, jspBody, tag, applicationContext, httpServletRequest, httpServletResponse, jspWriter);
-        tag.setJspContext(pageContext);
-        tag.setJspBody(jspBody);
-        tag.doTag();
-        verify(pageContext, jspBody, tag, applicationContext, httpServletRequest, httpServletResponse, jspWriter);
-    }
-
-}
diff --git a/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/BodylessTagTest.java b/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/BodylessTagTest.java
deleted file mode 100644
index f6a14aa..0000000
--- a/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/BodylessTagTest.java
+++ /dev/null
@@ -1,67 +0,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.
- */
-package org.apache.tiles.autotag.jsp.runtime;
-
-import static org.easymock.EasyMock.*;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.jsp.PageContext;
-
-import org.apache.tiles.request.ApplicationContext;
-import org.apache.tiles.request.jsp.JspRequest;
-import org.apache.tiles.request.util.ApplicationAccess;
-import org.junit.Test;
-
-/**
- * Tests {@link BodylessTag}.
- *
- * @version $Rev$ $Date$
- */
-public class BodylessTagTest {
-
-    /**
-     * Test method for {@link org.apache.tiles.autotag.jsp.runtime.BodylessTag#doTag()}.
-     * @throws IOException If something goes wrong.
-     */
-    @Test
-    public void testDoTag() throws IOException {
-        PageContext pageContext = createMock(PageContext.class);
-        BodylessTag tag = createMockBuilder(BodylessTag.class).createMock();
-        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);
-        tag.execute(isA(JspRequest.class));
-
-        replay(pageContext, tag, applicationContext, httpServletRequest, httpServletResponse);
-        tag.setJspContext(pageContext);
-        tag.doTag();
-        verify(pageContext, tag, applicationContext, httpServletRequest, httpServletResponse);
-    }
-
-}
diff --git a/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/JspAutotagRuntimeTest.java b/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/JspAutotagRuntimeTest.java
new file mode 100644
index 0000000..d7eedd1
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-jsp-runtime/src/test/java/org/apache/tiles/autotag/jsp/runtime/JspAutotagRuntimeTest.java
@@ -0,0 +1,78 @@
+package org.apache.tiles.autotag.jsp.runtime;
+
+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.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.jsp.JspRequest;
+import org.apache.tiles.request.util.ApplicationAccess;
+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-autotag/tiles-autotag-jsp/pom.xml b/tiles-autotag/tiles-autotag-jsp/pom.xml
index 1941420..73dbe82 100644
--- a/tiles-autotag/tiles-autotag-jsp/pom.xml
+++ b/tiles-autotag/tiles-autotag-jsp/pom.xml
@@ -12,12 +12,6 @@
   <description>Generates JSP tags automatically from templates.</description>
   <dependencies>
     <dependency>
-      <groupId>org.apache.tiles</groupId>
-      <artifactId>tiles-request-jsp</artifactId>
-      <version>1.0-SNAPSHOT</version>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.7</version>
@@ -31,11 +25,6 @@
     </dependency>
     <dependency>
     	<groupId>org.apache.tiles</groupId>
-    	<artifactId>tiles-request-freemarker</artifactId>
-    	<version>1.0-SNAPSHOT</version>
-    </dependency>
-    <dependency>
-    	<groupId>org.apache.tiles</groupId>
     	<artifactId>tiles-autotag-core</artifactId>
     	<version>1.0-SNAPSHOT</version>
     </dependency>
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
index 1d9f5b8..17b02bc 100644
--- 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
@@ -46,19 +46,22 @@
 
     @Override
     protected String getDirectoryName(File directory, String packageName,
-            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters) {
+            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) {
+            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) {
+            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/resources/org/apache/tiles/autotag/jsp/bodyTag.vm b/tiles-autotag/tiles-autotag-jsp/src/main/resources/org/apache/tiles/autotag/jsp/bodyTag.vm
index 50ef87b..4c08334 100644
--- 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
@@ -21,10 +21,13 @@
  *#
 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.jsp.runtime.Body#if(!${clazz.hasBody()})less#{end}Tag;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
 import org.apache.tiles.request.Request;
 
 /**
@@ -32,7 +35,7 @@
  * ${line}
 #end
  */
-public class ${clazz.tagClassPrefix}Tag extends Body#if(!${clazz.hasBody()})less#{end}Tag {
+public class ${clazz.tagClassPrefix}Tag extends SimpleTagSupport {
 
     /**
      * The template model.
@@ -76,7 +79,19 @@
 #end
     /** {@inheritDoc} */
     @Override
-    public void execute(Request request#if(${clazz.hasBody()}), ModelBody modelBody#end) throws IOException {
+    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},
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
index 7a417ca..cbf2245 100644
--- 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
@@ -92,7 +92,8 @@
                 "doStuff", "DoStuff", executeMethod);
         clazz.setDocumentation("Documentation of the DoStuff class.");
 
-        generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters);
+        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");
@@ -124,7 +125,8 @@
 
         suite.addTemplateClass(clazz);
 
-        generator.generate(file, "org.apache.tiles.autotag.jsp.test", suite, clazz, parameters);
+        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");
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
index 2f5caa5..03c7300 100644
--- 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
@@ -2,13 +2,16 @@
 
 import java.io.IOException;
 
-import org.apache.tiles.autotag.jsp.runtime.BodylessTag;
+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 BodylessTag {
+public class DoStuffNoBodyTag extends SimpleTagSupport {
 
     /**
      * The template model.
@@ -92,7 +95,16 @@
 
     /** {@inheritDoc} */
     @Override
-    public void execute(Request request) throws IOException {
+    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,
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
index 98ef615..02c22ef 100644
--- 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
@@ -2,14 +2,17 @@
 
 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.jsp.runtime.BodyTag;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
 import org.apache.tiles.request.Request;
 
 /**
  * Documentation of the DoStuff class.
  */
-public class DoStuffTag extends BodyTag {
+public class DoStuffTag extends SimpleTagSupport {
 
     /**
      * The template model.
@@ -93,7 +96,17 @@
 
     /** {@inheritDoc} */
     @Override
-    public void execute(Request request, ModelBody modelBody) throws IOException {
+    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,
diff --git a/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/BodyDirective.java b/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/BodyDirective.java
deleted file mode 100644
index 5d56445..0000000
--- a/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/BodyDirective.java
+++ /dev/null
@@ -1,87 +0,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.
- */
-
-package org.apache.tiles.autotag.velocity.runtime;
-
-import java.io.IOException;
-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.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.Node;
-import org.apache.velocity.tools.view.ViewContext;
-
-/**
- * Base abstract directive for those models who need to evaluate and use a
- * body.
- *
- * @version $Rev$ $Date$
- * @since 3.0.0
- */
-public abstract class BodyDirective extends Directive {
-
-    /** {@inheritDoc} */
-    @Override
-    public int getType() {
-        return BLOCK;
-    }
-
-    /** {@inheritDoc} */
-
-    @Override
-    public boolean render(InternalContextAdapter context, Writer writer, Node node)
-            throws IOException {
-        ViewContext viewContext = (ViewContext) context
-                .getInternalUserContext();
-        Map<String, Object> params = VelocityUtil.getParameters(context, node);
-        HttpServletRequest request = viewContext.getRequest();
-        HttpServletResponse response = viewContext.getResponse();
-        ServletContext servletContext = viewContext.getServletContext();
-        Request currentRequest = VelocityRequest.createVelocityRequest(
-                ServletUtil.getApplicationContext(servletContext), request,
-                response, context, writer);
-        ASTBlock block = (ASTBlock) node.jjtGetChild(1);
-        ModelBody modelBody = new VelocityModelBody(context, block, writer);
-        execute(params, currentRequest, modelBody);
-        return true;
-    }
-
-    /**
-     * Executes the directive.
-     *
-     * @param params The parameters.
-     * @param request The request.
-     * @param modelBody The body.
-     * @throws IOException If something goes wrong.
-     */
-    protected abstract void execute(Map<String, Object> params,
-            Request request, ModelBody modelBody) throws IOException;
-}
diff --git a/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/BodylessDirective.java b/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/BodylessDirective.java
deleted file mode 100644
index 41826fc..0000000
--- a/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/BodylessDirective.java
+++ /dev/null
@@ -1,82 +0,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.
- */
-
-package org.apache.tiles.autotag.velocity.runtime;
-
-import java.io.IOException;
-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.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.Node;
-import org.apache.velocity.tools.view.ViewContext;
-
-/**
- * Base abstract directive for those models who need to evaluate and use a
- * body.
- *
- * @version $Rev$ $Date$
- * @since 3.0.0
- */
-public abstract class BodylessDirective extends Directive {
-
-    /** {@inheritDoc} */
-    @Override
-    public int getType() {
-        return LINE;
-    }
-
-    /** {@inheritDoc} */
-
-    @Override
-    public boolean render(InternalContextAdapter context, Writer writer, Node node)
-            throws IOException {
-        ViewContext viewContext = (ViewContext) context
-                .getInternalUserContext();
-        Map<String, Object> params = VelocityUtil.getParameters(context, node);
-        HttpServletRequest request = viewContext.getRequest();
-        HttpServletResponse response = viewContext.getResponse();
-        ServletContext servletContext = viewContext.getServletContext();
-        Request currentRequest = VelocityRequest.createVelocityRequest(
-                ServletUtil.getApplicationContext(servletContext), request,
-                response, context, writer);
-        execute(params, currentRequest);
-        return true;
-    }
-
-    /**
-     * Executes the directive.
-     *
-     * @param params The parameters.
-     * @param request The request.
-     * @throws IOException If something goes wrong.
-     */
-    protected abstract void execute(Map<String, Object> params,
-            Request request) throws IOException;
-}
diff --git a/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/VelocityAutotagRuntime.java b/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/VelocityAutotagRuntime.java
new file mode 100644
index 0000000..4ed71ce
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity-runtime/src/main/java/org/apache/tiles/autotag/velocity/runtime/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.autotag.velocity.runtime;
+
+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-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/BodyDirectiveTest.java b/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/BodyDirectiveTest.java
deleted file mode 100644
index 2755c6e..0000000
--- a/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/BodyDirectiveTest.java
+++ /dev/null
@@ -1,116 +0,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.
- */
-
-package org.apache.tiles.autotag.velocity.runtime;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-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.request.ApplicationContext;
-import org.apache.tiles.request.util.ApplicationAccess;
-import org.apache.tiles.request.velocity.VelocityRequest;
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.runtime.directive.DirectiveConstants;
-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.Before;
-import org.junit.Test;
-
-/**
- * Tests {@link BodyDirective}.
- *
- * @version $Rev$ $Date$
- */
-public class BodyDirectiveTest {
-
-    /**
-     * The directive to test.
-     */
-    private BodyDirective directive;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() {
-        directive = createMockBuilder(BodyDirective.class).createMock();
-    }
-
-    /**
-     * Test method for {@link org.apache.tiles.velocity.template.BlockDirective#getType()}.
-     */
-    @Test
-    public void testGetType() {
-        replay(directive);
-        assertEquals(DirectiveConstants.BLOCK, directive.getType());
-        verify(directive);
-    }
-
-    /**
-     * Test method for {@link BlockDirective#render(InternalContextAdapter, Writer, Node)}.
-     * @throws IOException If something goes wrong.
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testRenderInternalContextAdapterWriterNode() throws IOException {
-        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);
-        ASTMap astMap = createMock(ASTMap.class);
-        ASTBlock block = createMock(ASTBlock.class);
-        Map<String, Object> params = createMock(Map.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(node.jjtGetChild(0)).andReturn(astMap);
-        expect(astMap.value(context)).andReturn(params);
-        expect(node.jjtGetChild(1)).andReturn(block);
-        expect(servletContext.getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE))
-                .andReturn(applicationContext);
-
-        directive.execute(eq(params), isA(VelocityRequest.class), isA(VelocityModelBody.class));
-
-        replay(directive, context, writer, node, viewContext,
-                applicationContext, servletContext, request, response, astMap,
-                params, block);
-        directive.render(context, writer, node);
-        verify(directive, context, writer, node, viewContext,
-                applicationContext, servletContext, request, response, astMap,
-                params, block);
-    }
-}
diff --git a/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/BodylessDirectiveTest.java b/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/BodylessDirectiveTest.java
deleted file mode 100644
index 6e1adc4..0000000
--- a/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/BodylessDirectiveTest.java
+++ /dev/null
@@ -1,113 +0,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.
- */
-
-package org.apache.tiles.autotag.velocity.runtime;
-
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-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.request.ApplicationContext;
-import org.apache.tiles.request.util.ApplicationAccess;
-import org.apache.tiles.request.velocity.VelocityRequest;
-import org.apache.velocity.context.InternalContextAdapter;
-import org.apache.velocity.runtime.directive.DirectiveConstants;
-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.Before;
-import org.junit.Test;
-
-/**
- * Tests {@link BodylessDirective}.
- *
- * @version $Rev$ $Date$
- */
-public class BodylessDirectiveTest {
-
-    /**
-     * The directive to test.
-     */
-    private BodylessDirective directive;
-
-    /**
-     * @throws java.lang.Exception
-     */
-    @Before
-    public void setUp() {
-        directive = createMockBuilder(BodylessDirective.class).createMock();
-    }
-
-    /**
-     * Test method for {@link org.apache.tiles.velocity.template.BlockDirective#getType()}.
-     */
-    @Test
-    public void testGetType() {
-        replay(directive);
-        assertEquals(DirectiveConstants.LINE, directive.getType());
-        verify(directive);
-    }
-
-    /**
-     * Test method for {@link BlockDirective#render(InternalContextAdapter, Writer, Node)}.
-     * @throws IOException If something goes wrong.
-     */
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testRenderInternalContextAdapterWriterNode() throws IOException {
-        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);
-        ASTMap astMap = createMock(ASTMap.class);
-        Map<String, Object> params = createMock(Map.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(node.jjtGetChild(0)).andReturn(astMap);
-        expect(astMap.value(context)).andReturn(params);
-        expect(servletContext.getAttribute(ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE))
-                .andReturn(applicationContext);
-
-        directive.execute(eq(params), isA(VelocityRequest.class));
-
-        replay(directive, context, writer, node, viewContext,
-                applicationContext, servletContext, request, response, astMap,
-                params);
-        directive.render(context, writer, node);
-        verify(directive, context, writer, node, viewContext,
-                applicationContext, servletContext, request, response, astMap,
-                params);
-    }
-}
diff --git a/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/VelocityAutotagRuntimeTest.java b/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/VelocityAutotagRuntimeTest.java
new file mode 100644
index 0000000..41c91c6
--- /dev/null
+++ b/tiles-autotag/tiles-autotag-velocity-runtime/src/test/java/org/apache/tiles/autotag/velocity/runtime/VelocityAutotagRuntimeTest.java
@@ -0,0 +1,88 @@
+package org.apache.tiles.autotag.velocity.runtime;
+
+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.ApplicationContext;
+import org.apache.tiles.request.Request;
+import org.apache.tiles.request.util.ApplicationAccess;
+import org.apache.tiles.request.velocity.VelocityRequest;
+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-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
index 5169d55..8493fc3 100644
--- 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
@@ -46,19 +46,22 @@
 
     @Override
     protected String getDirectoryName(File directory, String packageName,
-            TemplateSuite suite, TemplateClass clazz, Map<String, String> parameters) {
+            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) {
+            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) {
+            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/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm b/tiles-autotag/tiles-autotag-velocity/src/main/resources/org/apache/tiles/autotag/velocity/velocityDirective.vm
index e3aaceb..f628c37 100644
--- 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
@@ -20,21 +20,23 @@
  * under the License.
  *#
 import java.io.IOException;
-import java.util.Map;
+import java.io.Writer;
 
 #if(${clazz.hasBody()})
 import org.apache.tiles.autotag.core.runtime.ModelBody;
 #end
-import org.apache.tiles.autotag.velocity.runtime.Body#if(!${clazz.hasBody()})less#{end}Directive;
-import org.apache.tiles.autotag.velocity.runtime.VelocityUtil;
+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 Body#if(!${clazz.hasBody()})less#{end}Directive {
+public class ${clazz.tagClassPrefix}Directive extends Directive {
 
     /**
      * The template model.
@@ -49,13 +51,29 @@
 
     /** {@inheritDoc} */
     @Override
-    protected void execute(Map<String, Object> params, Request request#if(${clazz.hasBody()}), ModelBody modelBody#end) throws IOException {
+    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})) VelocityUtil.getObject(params.get("${parameter.exportedName}"), $stringTool.getDefaultValue(${parameter.type}, ${parameter.defaultValue})),
+            ($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/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
index 2d8dbb7..9806199 100644
--- 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
@@ -89,7 +89,8 @@
                 "doStuff", "DoStuff", executeMethod);
         clazz.setDocumentation("Documentation of the DoStuff class.");
 
-        generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null);
+        generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null,
+                           "org.apache.tiles.autotag.velocity.test.Runtime");
 
         InputStream expected = getClass()
                 .getResourceAsStream(
@@ -123,7 +124,8 @@
 
         suite.addTemplateClass(clazz);
 
-        generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null);
+        generator.generate(file, "org.apache.tiles.autotag.velocity.test", suite, clazz, null,
+                           "org.apache.tiles.autotag.velocity.test.Runtime");
 
         expected = getClass()
                 .getResourceAsStream(
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
index c1837a1..6572915 100644
--- 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
@@ -1,17 +1,19 @@
 package org.apache.tiles.autotag.velocity.test;
 
 import java.io.IOException;
-import java.util.Map;
+import java.io.Writer;
 
 import org.apache.tiles.autotag.core.runtime.ModelBody;
-import org.apache.tiles.autotag.velocity.runtime.BodyDirective;
-import org.apache.tiles.autotag.velocity.runtime.VelocityUtil;
+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 BodyDirective {
+public class DoStuffDirective extends Directive {
 
     /**
      * The template model.
@@ -26,12 +28,26 @@
 
     /** {@inheritDoc} */
     @Override
-    protected void execute(Map<String, Object> params, Request request, ModelBody modelBody) throws IOException {
+    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) VelocityUtil.getObject(params.get("one"), null),
-            (java.lang.Integer) VelocityUtil.getObject(params.get("two"), 0),
-            (java.lang.Boolean) VelocityUtil.getObject(params.get("three"), false),
+            (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
index 5cb102a..2cd4308 100644
--- 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
@@ -1,16 +1,18 @@
 package org.apache.tiles.autotag.velocity.test;
 
 import java.io.IOException;
-import java.util.Map;
+import java.io.Writer;
 
-import org.apache.tiles.autotag.velocity.runtime.BodylessDirective;
-import org.apache.tiles.autotag.velocity.runtime.VelocityUtil;
+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 BodylessDirective {
+public class DoStuffNoBodyDirective extends Directive {
 
     /**
      * The template model.
@@ -25,12 +27,25 @@
 
     /** {@inheritDoc} */
     @Override
-    protected void execute(Map<String, Object> params, Request request) throws IOException {
+    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) VelocityUtil.getObject(params.get("one"), null),
-            (java.lang.Float) VelocityUtil.getObject(params.get("two"), 0.0f),
-            (java.util.Date) VelocityUtil.getObject(params.get("three"), null),
+            (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-parent/tiles-freemarker/pom.xml b/tiles-parent/tiles-freemarker/pom.xml
index 11b9167..518fb8d 100644
--- a/tiles-parent/tiles-freemarker/pom.xml
+++ b/tiles-parent/tiles-freemarker/pom.xml
@@ -45,6 +45,7 @@
                 </goals>
                 <configuration>
                     <packageName>org.apache.tiles.freemarker.template</packageName>
+                    <freemarkerRuntime>org.apache.tiles.autotag.freemarker.runtime.FreemarkerAutotagRuntime</freemarkerRuntime>
                 </configuration>
             </execution>
         </executions>
diff --git a/tiles-parent/tiles-jsp/pom.xml b/tiles-parent/tiles-jsp/pom.xml
index bdfddbf..29eddb8 100644
--- a/tiles-parent/tiles-jsp/pom.xml
+++ b/tiles-parent/tiles-jsp/pom.xml
@@ -90,6 +90,7 @@
                 <configuration>
                     <taglibURI>http://tiles.apache.org/tags-tiles</taglibURI>
                     <packageName>org.apache.tiles.jsp.taglib</packageName>
+                    <jspRuntime>org.apache.tiles.autotag.jsp.runtime.JspAutotagRuntime</jspRuntime>
                 </configuration>
             </execution>
         </executions>
diff --git a/tiles-parent/tiles-jsp/src/main/java/org/apache/tiles/jsp/taglib/UseAttributeTag.java b/tiles-parent/tiles-jsp/src/main/java/org/apache/tiles/jsp/taglib/UseAttributeTag.java
index 42ff7c8..0032484 100644
--- a/tiles-parent/tiles-jsp/src/main/java/org/apache/tiles/jsp/taglib/UseAttributeTag.java
+++ b/tiles-parent/tiles-jsp/src/main/java/org/apache/tiles/jsp/taglib/UseAttributeTag.java
@@ -21,11 +21,14 @@
 
 package org.apache.tiles.jsp.taglib;
 
+import java.io.IOException;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.SimpleTagSupport;
 import javax.servlet.jsp.tagext.TagData;
 import javax.servlet.jsp.tagext.TagExtraInfo;
 import javax.servlet.jsp.tagext.VariableInfo;
 
-import org.apache.tiles.autotag.jsp.runtime.BodylessTag;
+import org.apache.tiles.autotag.core.runtime.AutotagRuntime;
 import org.apache.tiles.request.Request;
 import org.apache.tiles.template.ImportAttributeModel;
 
@@ -35,7 +38,7 @@
  * @since Tiles 1.0
  * @version $Rev$ $Date$
  */
-public class UseAttributeTag extends BodylessTag {
+public class UseAttributeTag extends SimpleTagSupport {
 
     /**
      * The template model.
@@ -173,7 +176,16 @@
 
     /** {@inheritDoc} */
     @Override
-    public void execute(Request request) {
+    public void doTag() throws JspException, IOException {
+        AutotagRuntime runtime = new org.apache.tiles.autotag.jsp.runtime.JspAutotagRuntime();
+        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(name, scopeName, id, ignore, request);
     }
 
diff --git a/tiles-parent/tiles-jsp/src/test/java/org/apache/tiles/jsp/taglib/UseAttributeTagTest.java b/tiles-parent/tiles-jsp/src/test/java/org/apache/tiles/jsp/taglib/UseAttributeTagTest.java
index 39137a0..40e4100 100644
--- a/tiles-parent/tiles-jsp/src/test/java/org/apache/tiles/jsp/taglib/UseAttributeTagTest.java
+++ b/tiles-parent/tiles-jsp/src/test/java/org/apache/tiles/jsp/taglib/UseAttributeTagTest.java
@@ -24,9 +24,15 @@
 import static org.easymock.classextension.EasyMock.*;
 import static org.junit.Assert.*;
 
-import java.util.HashMap;
+import java.io.IOException;
 import java.util.Map;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.tagext.JspFragment;
+import javax.servlet.jsp.tagext.JspTag;
 import javax.servlet.jsp.tagext.TagData;
 import javax.servlet.jsp.tagext.VariableInfo;
 
@@ -35,7 +41,9 @@
 import org.apache.tiles.TilesContainer;
 import org.apache.tiles.access.TilesAccess;
 import org.apache.tiles.request.ApplicationContext;
-import org.apache.tiles.request.Request;
+import org.apache.tiles.request.jsp.JspRequest;
+import org.apache.tiles.request.scope.ReflectionContextResolver;
+import org.apache.tiles.request.util.ApplicationAccess;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -61,36 +69,48 @@
 
     /**
      * Test method for {@link org.apache.tiles.jsp.taglib.UseAttributeTag#execute(org.apache.tiles.request.Request)}.
+     * @throws IOException 
+     * @throws JspException 
      */
-    @SuppressWarnings("unchecked")
     @Test
-    public void testExecute() {
-        Request request = createMock(Request.class);
+    public void testExecute() throws JspException, IOException {
+        JspFragment jspBody = createMock(JspFragment.class);
+        PageContext pageContext = createMock(PageContext.class);
+        JspTag parent = createMock(JspTag.class);
         ApplicationContext applicationContext = createMock(ApplicationContext.class);
-        Map<String, Object> requestScope = createMock(Map.class);
-        Map<String, Object> scope = createMock(Map.class);
+        HttpServletRequest httpServletRequest = createMock(HttpServletRequest.class);
+        HttpServletResponse httpServletResponse = createMock(HttpServletResponse.class);
+        @SuppressWarnings("unchecked")
+        Map<String, Object> applicationScope = createMock(Map.class);
         TilesContainer container = createMock(TilesContainer.class);
         AttributeContext attributeContext = createMock(AttributeContext.class);
         Attribute attribute = createMock(Attribute.class);
-
-        expect(request.getApplicationContext()).andReturn(applicationContext);
-        expect(request.getContext("request")).andReturn(requestScope);
-        expect(requestScope.get(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME)).andReturn(container);
-        expect(container.getAttributeContext(request)).andReturn(attributeContext);
+        expect(pageContext.getAttribute(
+                ApplicationAccess.APPLICATION_CONTEXT_ATTRIBUTE,
+                PageContext.APPLICATION_SCOPE)).andReturn(applicationContext);
+        expect(applicationContext.getApplicationScope()).andReturn(applicationScope).anyTimes();
+        expect(applicationScope.get(ApplicationAccess.CONTEXT_RESOLVER_ATTRIBUTE)).andReturn(new ReflectionContextResolver()).anyTimes();
+        expect(pageContext.getRequest()).andReturn(httpServletRequest);
+        expect(pageContext.getResponse()).andReturn(httpServletResponse);
+        expect(pageContext.getAttribute(TilesAccess.CURRENT_CONTAINER_ATTRIBUTE_NAME, PageContext.REQUEST_SCOPE)).andReturn(container);
+        expect(container.getAttributeContext(isA(JspRequest.class))).andReturn(attributeContext);
         expect(attributeContext.getAttribute("name")).andReturn(attribute);
-        expect(container.evaluate(attribute, request)).andReturn(new Integer(1));
-        expect(request.getContext("scope")).andReturn(scope);
-        Map<String, Object> toImport = new HashMap<String, Object>();
-        toImport.put("id", new Integer(1));
-        scope.putAll(toImport);
-
-        replay(request, applicationContext, requestScope, container, attributeContext, attribute, scope);
+        expect(container.evaluate(isA(Attribute.class), isA(JspRequest.class))).andReturn(new Integer(1));
+        pageContext.setAttribute("id", new Integer(1), PageContext.PAGE_SCOPE);
+        replay(jspBody, pageContext, parent, 
+               applicationContext, httpServletRequest, httpServletResponse, 
+               applicationScope, container, attributeContext, attribute);
         tag.setName("name");
-        tag.setScope("scope");
+        tag.setScope("page");
         tag.setId("id");
         tag.setIgnore(false);
-        tag.execute(request);
-        verify(request, applicationContext, requestScope, container, attributeContext, attribute, scope);
+        tag.setJspContext(pageContext);
+        tag.setJspBody(jspBody);
+        tag.setParent(parent);
+        tag.doTag();
+        verify(jspBody, pageContext, parent, 
+               applicationContext, httpServletRequest, httpServletResponse, 
+               container, attributeContext, attribute);
     }
 
     /**
diff --git a/tiles-parent/tiles-velocity/pom.xml b/tiles-parent/tiles-velocity/pom.xml
index 905b051..3ff728f 100644
--- a/tiles-parent/tiles-velocity/pom.xml
+++ b/tiles-parent/tiles-velocity/pom.xml
@@ -46,6 +46,7 @@
                 </goals>
                 <configuration>
                     <packageName>org.apache.tiles.velocity.template</packageName>
+                    <velocityRuntime>org.apache.tiles.autotag.velocity.runtime.VelocityAutotagRuntime</velocityRuntime>
                 </configuration>
             </execution>
         </executions>