Author: lgawron
Date: Thu Dec  9 04:38:49 2004
New Revision: 111375

URL: http://svn.apache.org/viewcvs?view=rev&rev=111375
Log:
moved Jonas' template solution to o.a.c.template.v2
refactored JXTemplate generator introduced as 
o.a.c.template.jxtg.JXTemplateGenerator
Added:
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/JXTemplateGenerator.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/TransformerAdapter.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ErrorHolder.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JSIntrospector.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXCacheKey.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXSourceValidity.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/LocatorFacade.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/MyVariables.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ValueHelper.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/JXTExpression.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Literal.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/MyJexlContext.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Subst.java
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/Parser.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/AttributeEvent.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Characters.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/CopyAttribute.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndCDATA.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDTD.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDocument.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndElement.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndEntity.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndInstruction.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndPrefixMapping.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Event.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/IgnorableWhitespace.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/LoopTagStatus.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/ProcessingInstruction.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SkippedEntity.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartCDATA.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartChoose.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartComment.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDTD.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDefine.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDocument.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartElement.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEntity.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEval.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEvalBody.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartForEach.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatDate.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatNumber.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartIf.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartImport.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartInstruction.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOtherwise.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOut.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartParameter.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartPrefixMapping.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartSet.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartTemplate.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartWhen.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SubstituteAttribute.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/TextEvent.java
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/generation/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/generation/TemplateGenerator.java
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AbstractToken.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AttributeToken.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/CharactersToken.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ElementToken.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ExpressionToken.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/PlainElementToken.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Script.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptCompiler.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptContext.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptInvoker.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/TagRepository.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Token.java
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/AbstractTag.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/Tag.java
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/samples/
   
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/samples/DuplicateTag.java
Removed:
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/generation/
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/script/
   cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/tag/
Modified:
   
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java
   
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java
   
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/JXTemplateGenerator.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/JXTemplateGenerator.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/JXTemplateGenerator.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,1230 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg;
+
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.components.flow.FlowHelper;
+import org.apache.cocoon.components.flow.WebContinuation;
+import 
org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptFlowHelper;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.generation.ServiceableGenerator;
+import org.apache.cocoon.template.jxtg.environment.ErrorHolder;
+import org.apache.cocoon.template.jxtg.environment.JSIntrospector;
+import org.apache.cocoon.template.jxtg.environment.JXCacheKey;
+import org.apache.cocoon.template.jxtg.environment.JXSourceValidity;
+import org.apache.cocoon.template.jxtg.environment.LocatorFacade;
+import org.apache.cocoon.template.jxtg.environment.MyVariables;
+import org.apache.cocoon.template.jxtg.environment.ValueHelper;
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.cocoon.template.jxtg.expression.Literal;
+import org.apache.cocoon.template.jxtg.expression.MyJexlContext;
+import org.apache.cocoon.template.jxtg.expression.Subst;
+import org.apache.cocoon.template.jxtg.script.Parser;
+import org.apache.cocoon.template.jxtg.script.event.*;
+import org.apache.cocoon.xml.IncludeXMLConsumer;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.cocoon.xml.dom.DOMBuilder;
+import org.apache.cocoon.xml.dom.DOMStreamer;
+import org.apache.commons.jexl.Expression;
+import org.apache.commons.jexl.JexlContext;
+import org.apache.commons.jexl.util.Introspector;
+import org.apache.commons.jexl.util.introspection.Info;
+import org.apache.commons.jxpath.CompiledExpression;
+import org.apache.commons.jxpath.DynamicPropertyHandler;
+import org.apache.commons.jxpath.JXPathBeanInfo;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.jxpath.JXPathContextFactory;
+import org.apache.commons.jxpath.JXPathIntrospector;
+import org.apache.commons.jxpath.Pointer;
+import org.apache.commons.jxpath.Variables;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.mozilla.javascript.NativeArray;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.LocatorImpl;
+
+/**
+ * @cocoon.sitemap.component.documentation Provides a generic page template 
with
+ *                                         embedded JSTL and XPath expression
+ *                                         substitution to access data sent by
+ *                                         Cocoon Flowscripts.
+ * 
+ * @cocoon.sitemap.component.name jx
+ * @cocoon.sitemap.component.label content
+ * @cocoon.sitemap.component.logger sitemap.generator.jx
+ * 
+ * @cocoon.sitemap.component.pooling.min 2
+ * @cocoon.sitemap.component.pooling.max 16
+ * @cocoon.sitemap.component.pooling.grow 2
+ * 
+ * 
+ * @version CVS $Id: JXTemplateGenerator.java 106437 2004-11-24 17:35:45Z 
unico $
+ */
+public class JXTemplateGenerator extends ServiceableGenerator implements
+        CacheableProcessingComponent {
+    /** The namespace used by this generator */
+    public final static String NS = 
"http://apache.org/cocoon/templates/jx/1.0";;
+
+    private static final JXPathContextFactory jxpathContextFactory = 
JXPathContextFactory
+            .newInstance();
+    private static final Attributes EMPTY_ATTRS = new AttributesImpl();
+
+    private static final Iterator EMPTY_ITER = new Iterator() {
+        public boolean hasNext() {
+            return false;
+        }
+
+        public Object next() {
+            return null;
+        }
+
+        public void remove() {
+            // EMPTY
+        }
+    };
+
+    private static final Iterator NULL_ITER = new Iterator() {
+        public boolean hasNext() {
+            return true;
+        }
+
+        public Object next() {
+            return null;
+        }
+
+        public void remove() {
+            // EMPTY
+        }
+    };
+
+    public static final Locator NULL_LOCATOR = new LocatorImpl();
+
+    public final static String CACHE_KEY = "cache-key";
+    public final static String VALIDITY = "cache-validity";
+
+    private JXPathContext jxpathContext;
+    private MyJexlContext globalJexlContext;
+    private Variables variables;
+    private static Map cache = new HashMap();
+    private Source inputSource;
+    private Map definitions;
+    private Map cocoon;
+
+    static {
+        // Hack: there's no _nice_ way to add my introspector to Jexl right now
+        try {
+            Field field = Introspector.class.getDeclaredField("uberSpect");
+            field.setAccessible(true);
+            field.set(null, new JSIntrospector());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public XMLConsumer getConsumer() {
+        return this.xmlConsumer;
+    }
+
+    public JXPathContext getJXPathContext() {
+        return jxpathContext;
+    }
+
+    public MyJexlContext getJexlContext() {
+        return globalJexlContext;
+    }
+
+    public void recycle() {
+        if (this.resolver != null) {
+            this.resolver.release(this.inputSource);
+        }
+        this.inputSource = null;
+        this.jxpathContext = null;
+        this.globalJexlContext = null;
+        this.variables = null;
+        this.definitions = null;
+        this.cocoon = null;
+        super.recycle();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see 
org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver,
+     *      java.util.Map, java.lang.String,
+     *      org.apache.avalon.framework.parameters.Parameters)
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src,
+            Parameters parameters) throws ProcessingException, SAXException,
+            IOException {
+
+        super.setup(resolver, objectModel, src, parameters);
+        if (src != null) {
+            try {
+                this.inputSource = resolver.resolveURI(src);
+            } catch (SourceException se) {
+                throw SourceUtil.handle("Error during resolving of '" + src
+                        + "'.", se);
+            }
+            final String uri = inputSource.getURI();
+            boolean regenerate = false;
+            StartDocument startEvent = null;
+            synchronized (cache) {
+                startEvent = (StartDocument) cache.get(uri);
+                if (startEvent != null) {
+                    int valid = SourceValidity.UNKNOWN;
+                    if (startEvent.getCompileTime() != null) {
+                        valid = startEvent.getCompileTime().isValid();
+                    }
+                    if (valid == SourceValidity.UNKNOWN
+                            && startEvent.getCompileTime() != null) {
+                        SourceValidity validity = inputSource.getValidity();
+                        valid = startEvent.getCompileTime().isValid(validity);
+                    }
+                    if (valid != SourceValidity.VALID) {
+                        cache.remove(uri);
+                        regenerate = true;
+                    }
+                } else {
+                    regenerate = true;
+                }
+            }
+            if (regenerate) {
+                Parser parser = new Parser();
+                SourceUtil.parse(this.manager, this.inputSource, parser);
+                startEvent = parser.getStartEvent();
+                startEvent.setCompileTime(this.inputSource.getValidity());
+                synchronized (cache) {
+                    cache.put(uri, startEvent);
+                }
+            }
+        }
+        Object bean = FlowHelper.getContextObject(objectModel);
+        WebContinuation kont = FlowHelper.getWebContinuation(objectModel);
+        setContexts(bean, kont, parameters, objectModel);
+        this.definitions = new HashMap();
+    }
+
+    private void fillContext(Object contextObject, Map map) {
+        if (contextObject != null) {
+            // Hack: I use jxpath to populate the context object's properties
+            // in the jexl context
+            final JXPathBeanInfo bi = JXPathIntrospector
+                    .getBeanInfo(contextObject.getClass());
+            if (bi.isDynamic()) {
+                Class cl = bi.getDynamicPropertyHandlerClass();
+                try {
+                    DynamicPropertyHandler h = (DynamicPropertyHandler) cl
+                            .newInstance();
+                    String[] result = h.getPropertyNames(contextObject);
+                    int len = result.length;
+                    for (int i = 0; i < len; i++) {
+                        try {
+                            map.put(result[i], h.getProperty(contextObject,
+                                    result[i]));
+                        } catch (Exception exc) {
+                            exc.printStackTrace();
+                        }
+                    }
+                } catch (Exception ignored) {
+                    ignored.printStackTrace();
+                }
+            } else {
+                PropertyDescriptor[] props = bi.getPropertyDescriptors();
+                int len = props.length;
+                for (int i = 0; i < len; i++) {
+                    try {
+                        Method read = props[i].getReadMethod();
+                        if (read != null) {
+                            map.put(props[i].getName(), read.invoke(
+                                    contextObject, null));
+                        }
+                    } catch (Exception ignored) {
+                        ignored.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
+    private void setContexts(Object contextObject, WebContinuation kont,
+            Parameters parameters, Map objectModel) {
+        final Request request = ObjectModelHelper.getRequest(objectModel);
+        final Object session = request.getSession(false);
+        final Object app = ObjectModelHelper.getContext(objectModel);
+        cocoon = new HashMap();
+        cocoon.put("request", FOM_JavaScriptFlowHelper
+                .getFOM_Request(objectModel));
+        if (session != null) {
+            cocoon.put("session", FOM_JavaScriptFlowHelper
+                    .getFOM_Session(objectModel));
+        }
+        cocoon.put("context", FOM_JavaScriptFlowHelper
+                .getFOM_Context(objectModel));
+        cocoon.put("continuation", FOM_JavaScriptFlowHelper
+                .getFOM_WebContinuation(objectModel));
+        cocoon.put("parameters", Parameters.toProperties(parameters));
+        this.variables = new MyVariables(cocoon, contextObject, kont, request,
+                session, app, parameters);
+        Map map;
+        if (contextObject instanceof Map) {
+            map = (Map) contextObject;
+        } else {
+            map = new HashMap();
+            fillContext(contextObject, map);
+        }
+        jxpathContext = jxpathContextFactory.newContext(null, contextObject);
+        jxpathContext.setVariables(variables);
+        jxpathContext.setLenient(parameters.getParameterAsBoolean(
+                "lenient-xpath", false));
+        globalJexlContext = new MyJexlContext();
+        globalJexlContext.setVars(map);
+        map = globalJexlContext.getVars();
+        map.put("cocoon", cocoon);
+        if (contextObject != null) {
+            map.put("flowContext", contextObject);
+            // FIXME (VG): Is this required (what it's used for - examples)?
+            // Here I use Rhino's live-connect objects to allow Jexl to call
+            // java constructors
+            Object javaPkg = FOM_JavaScriptFlowHelper
+                    .getJavaPackage(objectModel);
+            Object pkgs = FOM_JavaScriptFlowHelper.getPackages(objectModel);
+            map.put("java", javaPkg);
+            map.put("Packages", pkgs);
+        }
+        if (kont != null) {
+            map.put("continuation", kont);
+        }
+        map.put("request", request);
+        map.put("context", app);
+        map.put("parameters", parameters);
+        if (session != null) {
+            map.put("session", session);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.cocoon.generation.Generator#generate()
+     */
+    public void generate() throws IOException, SAXException,
+            ProcessingException {
+        final String cacheKey = this.inputSource.getURI();
+
+        StartDocument startEvent;
+        synchronized (cache) {
+            startEvent = (StartDocument) cache.get(cacheKey);
+        }
+        performGeneration(this.xmlConsumer, globalJexlContext, jxpathContext,
+                null, startEvent, null);
+    }
+
+    public void performGeneration(final XMLConsumer consumer,
+            MyJexlContext jexlContext, JXPathContext jxpathContext,
+            StartElement macroCall, Event startEvent, Event endEvent)
+            throws SAXException {
+        cocoon.put("consumer", consumer);
+        execute(this.xmlConsumer, globalJexlContext, jxpathContext, null,
+                startEvent, null);
+    }
+
+    interface CharHandler {
+        public void characters(char[] ch, int offset, int length)
+                throws SAXException;
+    }
+
+    private void characters(JexlContext jexlContext,
+            JXPathContext jxpathContext, TextEvent event, CharHandler handler)
+            throws SAXException {
+        Iterator iter = event.getSubstitutions().iterator();
+        while (iter.hasNext()) {
+            Object subst = iter.next();
+            char[] chars;
+            if (subst instanceof char[]) {
+                chars = (char[]) subst;
+            } else {
+                JXTExpression expr = (JXTExpression) subst;
+                try {
+                    Object val = ValueHelper.getValue(expr, jexlContext,
+                            jxpathContext);
+                    chars = val != null ? val.toString().toCharArray()
+                            : ArrayUtils.EMPTY_CHAR_ARRAY;
+                } catch (Exception e) {
+                    throw new SAXParseException(e.getMessage(), event
+                            .getLocation(), e);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), event
+                            .getLocation(), new ErrorHolder(err));
+                }
+            }
+            handler.characters(chars, 0, chars.length);
+        }
+    }
+
+    /**
+     * dump a DOM document, using an IncludeXMLConsumer to filter out start/end
+     * document events
+     */
+    private void executeDOM(final XMLConsumer consumer,
+            MyJexlContext jexlContext, JXPathContext jxpathContext, Node node)
+            throws SAXException {
+        IncludeXMLConsumer includer = new IncludeXMLConsumer(consumer);
+        DOMStreamer streamer = new DOMStreamer(includer);
+        streamer.stream(node);
+    }
+
+    private void call(Locator location, StartElement macroCall,
+            final XMLConsumer consumer, MyJexlContext jexlContext,
+            JXPathContext jxpathContext, Event startEvent, Event endEvent)
+            throws SAXException {
+        try {
+            execute(consumer, jexlContext, jxpathContext, macroCall,
+                    startEvent, endEvent);
+        } catch (SAXParseException exc) {
+            throw new SAXParseException(macroCall.getLocalName() + ": "
+                    + exc.getMessage(), location, exc);
+        }
+    }
+
+    private void execute(final XMLConsumer consumer, MyJexlContext jexlContext,
+            JXPathContext jxpathContext, StartElement macroCall,
+            Event startEvent, Event endEvent) throws SAXException {
+        Event ev = startEvent;
+        LocatorFacade loc = new LocatorFacade(ev.getLocation());
+        consumer.setDocumentLocator(loc);
+        while (ev != endEvent) {
+            loc.setDocumentLocator(ev.getLocation());
+            if (ev instanceof Characters) {
+                TextEvent text = (TextEvent) ev;
+                Iterator iter = text.getSubstitutions().iterator();
+                while (iter.hasNext()) {
+                    Object subst = iter.next();
+                    char[] chars;
+                    if (subst instanceof char[]) {
+                        chars = (char[]) subst;
+                    } else {
+                        JXTExpression expr = (JXTExpression) subst;
+                        try {
+                            Object val = ValueHelper.getNode(expr, jexlContext,
+                                    jxpathContext);
+                            if (val instanceof Node) {
+                                executeDOM(consumer, jexlContext,
+                                        jxpathContext, (Node) val);
+                                continue;
+                            } else if (val instanceof NodeList) {
+                                NodeList nodeList = (NodeList) val;
+                                int len = nodeList.getLength();
+                                for (int i = 0; i < len; i++) {
+                                    Node n = nodeList.item(i);
+                                    executeDOM(consumer, jexlContext,
+                                            jxpathContext, n);
+                                }
+                                continue;
+                            } else if (val instanceof Node[]) {
+                                Node[] nodeList = (Node[]) val;
+                                int len = nodeList.length;
+                                for (int i = 0; i < len; i++) {
+                                    Node n = nodeList[i];
+                                    executeDOM(consumer, jexlContext,
+                                            jxpathContext, n);
+                                }
+                                continue;
+                            } else if (val instanceof XMLizable) {
+                                ((XMLizable) val).toSAX(new IncludeXMLConsumer(
+                                        consumer));
+                                continue;
+                            }
+                            chars = val != null ? val.toString().toCharArray()
+                                    : ArrayUtils.EMPTY_CHAR_ARRAY;
+                        } catch (Exception e) {
+                            throw new SAXParseException(e.getMessage(), ev
+                                    .getLocation(), e);
+                        } catch (Error err) {
+                            throw new SAXParseException(err.getMessage(), ev
+                                    .getLocation(), new ErrorHolder(err));
+                        }
+                    }
+                    consumer.characters(chars, 0, chars.length);
+                }
+            } else if (ev instanceof EndElement) {
+                EndElement endElement = (EndElement) ev;
+                StartElement startElement = endElement.getStartElement();
+                consumer.endElement(startElement.getNamespaceURI(),
+                        startElement.getLocalName(), startElement.getRaw());
+            } else if (ev instanceof EndPrefixMapping) {
+                EndPrefixMapping endPrefixMapping = (EndPrefixMapping) ev;
+                consumer.endPrefixMapping(endPrefixMapping.getPrefix());
+            } else if (ev instanceof IgnorableWhitespace) {
+                TextEvent text = (TextEvent) ev;
+                characters(jexlContext, jxpathContext, text, new CharHandler() 
{
+                    public void characters(char[] ch, int offset, int len)
+                            throws SAXException {
+                        consumer.ignorableWhitespace(ch, offset, len);
+                    }
+                });
+            } else if (ev instanceof SkippedEntity) {
+                SkippedEntity skippedEntity = (SkippedEntity) ev;
+                consumer.skippedEntity(skippedEntity.getName());
+            } else if (ev instanceof StartIf) {
+                StartIf startIf = (StartIf) ev;
+                Object val;
+                try {
+                    val = ValueHelper.getValue(startIf.getTest(), jexlContext,
+                            jxpathContext, Boolean.TRUE);
+                } catch (Exception e) {
+                    throw new SAXParseException(e.getMessage(), ev
+                            .getLocation(), e);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), ev
+                            .getLocation(), new ErrorHolder(err));
+                }
+                boolean result = false;
+                if (val instanceof Boolean) {
+                    result = ((Boolean) val).booleanValue();
+                } else {
+                    result = (val != null);
+                }
+                if (!result) {
+                    ev = startIf.getEndInstruction().getNext();
+                    continue;
+                }
+            } else if (ev instanceof StartForEach) {
+                StartForEach startForEach = (StartForEach) ev;
+                final Object items = startForEach.getItems();
+                Iterator iter = null;
+                int begin, end, step;
+                String var, varStatus;
+                try {
+                    if (items != null) {
+                        JXTExpression expr = (JXTExpression) items;
+                        if (expr.getCompiledExpression() instanceof 
CompiledExpression) {
+                            CompiledExpression compiledExpression = 
(CompiledExpression) expr
+                                    .getCompiledExpression();
+                            Object val = compiledExpression.getPointer(
+                                    jxpathContext, expr.getRaw()).getNode();
+                            // FIXME: workaround for JXPath bug
+                            iter = val instanceof NativeArray ? new 
JSIntrospector.NativeArrayIterator(
+                                    (NativeArray) val)
+                                    : compiledExpression
+                                            .iteratePointers(jxpathContext);
+                        } else if (expr.getCompiledExpression() instanceof 
Expression) {
+                            Expression e = (Expression) expr
+                                    .getCompiledExpression();
+                            Object result = e.evaluate(jexlContext);
+                            if (result != null) {
+                                iter = Introspector.getUberspect().getIterator(
+                                        result,
+                                        new Info(
+                                                ev.getLocation().getSystemId(),
+                                                ev.getLocation()
+                                                        .getLineNumber(), ev
+                                                        .getLocation()
+                                                        .getColumnNumber()));
+                            }
+                            if (iter == null) {
+                                iter = EMPTY_ITER;
+                            }
+                        } else {
+                            // literal value
+                            iter = new Iterator() {
+                                Object val = items;
+
+                                public boolean hasNext() {
+                                    return val != null;
+                                }
+
+                                public Object next() {
+                                    Object res = val;
+                                    val = null;
+                                    return res;
+                                }
+
+                                public void remove() {
+                                    // EMPTY
+                                }
+                            };
+                        }
+                    } else {
+                        iter = NULL_ITER;
+                    }
+                    begin = startForEach.getBegin() == null ? 0 : ValueHelper
+                            .getIntValue(startForEach.getBegin(), jexlContext,
+                                    jxpathContext);
+                    end = startForEach.getEnd() == null ? Integer.MAX_VALUE
+                            : ValueHelper.getIntValue(startForEach.getEnd(),
+                                    jexlContext, jxpathContext);
+                    step = startForEach.getStep() == null ? 1 : ValueHelper
+                            .getIntValue(startForEach.getStep(), jexlContext,
+                                    jxpathContext);
+                    var = ValueHelper.getStringValue(startForEach.getVar(),
+                            jexlContext, jxpathContext);
+                    varStatus = ValueHelper.getStringValue(startForEach
+                            .getVarStatus(), jexlContext, jxpathContext);
+                } catch (Exception exc) {
+                    throw new SAXParseException(exc.getMessage(), ev
+                            .getLocation(), exc);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), ev
+                            .getLocation(), new ErrorHolder(err));
+                }
+                MyJexlContext localJexlContext = new 
MyJexlContext(jexlContext);
+                MyVariables localJXPathVariables = new MyVariables(
+                        (MyVariables) jxpathContext.getVariables());
+                int i = 0;
+                // Move to the begin row
+                while (i < begin && iter.hasNext()) {
+                    iter.next();
+                    i++;
+                }
+                LoopTagStatus status = null;
+                if (varStatus != null) {
+                    status = new LoopTagStatus();
+                    status.setBegin(begin);
+                    status.setEnd(end);
+                    status.setStep(step);
+                    status.setFirst(true);
+                    localJexlContext.put(varStatus, status);
+                    localJXPathVariables.declareVariable(varStatus, status);
+                }
+                int skipCounter, count = 1;
+                JXPathContext localJXPathContext = null;
+                while (i <= end && iter.hasNext()) {
+                    Object value = iter.next();
+                    if (value instanceof Pointer) {
+                        Pointer ptr = (Pointer) value;
+                        localJXPathContext = jxpathContext
+                                .getRelativeContext(ptr);
+                        try {
+                            value = ptr.getNode();
+                        } catch (Exception exc) {
+                            throw new SAXParseException(exc.getMessage(), ev
+                                    .getLocation(), null);
+                        }
+                    } else {
+                        localJXPathContext = jxpathContextFactory.newContext(
+                                jxpathContext, value);
+                    }
+                    localJXPathContext.setVariables(localJXPathVariables);
+                    if (var != null) {
+                        localJexlContext.put(var, value);
+                    }
+                    if (status != null) {
+                        status.setIndex(i);
+                        status.setCount(count);
+                        status.setFirst(i == begin);
+                        status.setCurrent(value);
+                        status.setLast((i == end || !iter.hasNext()));
+                    }
+                    execute(consumer, localJexlContext, localJXPathContext,
+                            macroCall, startForEach.getNext(), startForEach
+                                    .getEndInstruction());
+                    // Skip rows
+                    skipCounter = step;
+                    while (--skipCounter > 0 && iter.hasNext()) {
+                        iter.next();
+                    }
+                    // Increase index
+                    i += step;
+                    count++;
+                }
+                ev = startForEach.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartChoose) {
+                StartChoose startChoose = (StartChoose) ev;
+                StartWhen startWhen = startChoose.getFirstChoice();
+                while (startWhen != null) {
+                    Object val;
+                    try {
+                        val = ValueHelper.getValue(startWhen.getTest(), 
jexlContext,
+                                jxpathContext, Boolean.TRUE);
+                    } catch (Exception e) {
+                        throw new SAXParseException(e.getMessage(), ev
+                                .getLocation(), e);
+                    }
+                    boolean result;
+                    if (val instanceof Boolean) {
+                        result = ((Boolean) val).booleanValue();
+                    } else {
+                        result = (val != null);
+                    }
+                    if (result) {
+                        execute(consumer, jexlContext, jxpathContext,
+                                macroCall, startWhen.getNext(), startWhen
+                                        .getEndInstruction());
+                        break;
+                    }
+                    startWhen = startWhen.getNextChoice();
+                }
+                if (startWhen == null && startChoose.getOtherwise() != null) {
+                    execute(consumer, jexlContext, jxpathContext, macroCall,
+                            startChoose.getOtherwise().getNext(), startChoose
+                                    .getOtherwise().getEndInstruction());
+                }
+                ev = startChoose.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartSet) {
+                StartSet startSet = (StartSet) ev;
+                Object value = null;
+                String var = null;
+                try {
+                    if (startSet.getVar() != null) {
+                        var = ValueHelper.getStringValue(startSet.getVar(),
+                                jexlContext, jxpathContext);
+                    }
+                    if (startSet.getValue() != null) {
+                        value = ValueHelper.getNode(startSet.getValue(),
+                                jexlContext, jxpathContext);
+                    }
+                } catch (Exception exc) {
+                    throw new SAXParseException(exc.getMessage(), ev
+                            .getLocation(), exc);
+                }
+                if (value == null) {
+                    NodeList nodeList = toDOMNodeList("set", startSet,
+                            jexlContext, macroCall);
+                    // JXPath doesn't handle NodeList, so convert it to an 
array
+                    int len = nodeList.getLength();
+                    Node[] nodeArr = new Node[len];
+                    for (int i = 0; i < len; i++) {
+                        nodeArr[i] = nodeList.item(i);
+                    }
+                    value = nodeArr;
+                }
+                if (var != null) {
+                    jxpathContext.getVariables().declareVariable(var, value);
+                    jexlContext.put(var, value);
+                }
+                ev = startSet.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartElement) {
+                StartElement startElement = (StartElement) ev;
+                StartDefine def = (StartDefine) definitions.get(startElement
+                        .getQname());
+                if (def != null) {
+                    Map attributeMap = new HashMap();
+                    Iterator i = startElement.getAttributeEvents().iterator();
+                    while (i.hasNext()) {
+                        String attributeName;
+                        Object attributeValue;
+                        AttributeEvent attrEvent = (AttributeEvent) i.next();
+                        attributeName = attrEvent.getLocalName();
+                        if (attrEvent instanceof CopyAttribute) {
+                            CopyAttribute copy = (CopyAttribute) attrEvent;
+                            attributeValue = copy.getValue();
+                        } else if (attrEvent instanceof SubstituteAttribute) {
+                            SubstituteAttribute substEvent = 
(SubstituteAttribute) attrEvent;
+                            if (substEvent.getSubstitutions().size() == 1
+                                    && substEvent.getSubstitutions().get(0) 
instanceof JXTExpression) {
+                                JXTExpression expr = (JXTExpression) substEvent
+                                        .getSubstitutions().get(0);
+                                Object val;
+                                try {
+                                    val = ValueHelper.getNode(expr,
+                                            jexlContext, jxpathContext);
+                                } catch (Exception e) {
+                                    throw new SAXParseException(e.getMessage(),
+                                            ev.getLocation(), e);
+                                } catch (Error err) {
+                                    throw new SAXParseException(err
+                                            .getMessage(), ev.getLocation(),
+                                            new ErrorHolder(err));
+                                }
+                                attributeValue = val != null ? val : "";
+                            } else {
+                                StringBuffer buf = new StringBuffer();
+                                Iterator iterSubst = substEvent
+                                        .getSubstitutions().iterator();
+                                while (iterSubst.hasNext()) {
+                                    Subst subst = (Subst) iterSubst.next();
+                                    if (subst instanceof Literal) {
+                                        Literal lit = (Literal) subst;
+                                        buf.append(lit.getValue());
+                                    } else if (subst instanceof JXTExpression) 
{
+                                        JXTExpression expr = (JXTExpression) 
subst;
+                                        Object val;
+                                        try {
+                                            val = ValueHelper.getValue(expr,
+                                                    jexlContext, 
jxpathContext);
+                                        } catch (Exception e) {
+                                            throw new SAXParseException(e
+                                                    .getMessage(), ev
+                                                    .getLocation(), e);
+                                        } catch (Error err) {
+                                            throw new SAXParseException(err
+                                                    .getMessage(), ev
+                                                    .getLocation(),
+                                                    new ErrorHolder(err));
+                                        }
+                                        buf.append(val != null ? val.toString()
+                                                : "");
+                                    }
+                                }
+                                attributeValue = buf.toString();
+                            }
+                        } else {
+                            throw new Error("this shouldn't have happened");
+                        }
+                        attributeMap.put(attributeName, attributeValue);
+                    }
+                    MyVariables parent = (MyVariables) jxpathContext
+                            .getVariables();
+                    MyVariables vars = new MyVariables(parent);
+                    MyJexlContext localJexlContext = new MyJexlContext(
+                            jexlContext);
+                    HashMap macro = new HashMap();
+                    macro.put("body", startElement);
+                    macro.put("arguments", attributeMap);
+                    localJexlContext.put("macro", macro);
+                    vars.declareVariable("macro", macro);
+                    Iterator iter = def.getParameters().entrySet().iterator();
+                    while (iter.hasNext()) {
+                        Map.Entry e = (Map.Entry) iter.next();
+                        String key = (String) e.getKey();
+                        StartParameter startParam = (StartParameter) e
+                                .getValue();
+                        Object default_ = startParam.getDefaultValue();
+                        Object val = attributeMap.get(key);
+                        if (val == null) {
+                            val = default_;
+                        }
+                        localJexlContext.put(key, val);
+                        vars.declareVariable(key, val);
+                    }
+                    JXPathContext localJXPathContext = jxpathContextFactory
+                            .newContext(null, jxpathContext.getContextBean());
+                    localJXPathContext.setVariables(vars);
+                    call(ev.getLocation(), startElement, consumer,
+                            localJexlContext, localJXPathContext,
+                            def.getBody(), def.getEndInstruction());
+                    ev = startElement.getEndElement().getNext();
+                    continue;
+                }
+                Iterator i = startElement.getAttributeEvents().iterator();
+                AttributesImpl attrs = new AttributesImpl();
+                while (i.hasNext()) {
+                    AttributeEvent attrEvent = (AttributeEvent) i.next();
+                    if (attrEvent instanceof CopyAttribute) {
+                        CopyAttribute copy = (CopyAttribute) attrEvent;
+                        attrs.addAttribute(copy.getNamespaceURI(), copy
+                                .getLocalName(), copy.getRaw(), copy.getType(),
+                                copy.getValue());
+                    } else if (attrEvent instanceof SubstituteAttribute) {
+                        StringBuffer buf = new StringBuffer();
+                        SubstituteAttribute substEvent = (SubstituteAttribute) 
attrEvent;
+                        Iterator iterSubst = substEvent.getSubstitutions()
+                                .iterator();
+                        while (iterSubst.hasNext()) {
+                            Subst subst = (Subst) iterSubst.next();
+                            if (subst instanceof Literal) {
+                                Literal lit = (Literal) subst;
+                                buf.append(lit.getValue());
+                            } else if (subst instanceof JXTExpression) {
+                                JXTExpression expr = (JXTExpression) subst;
+                                Object val;
+                                try {
+                                    val = ValueHelper.getValue(expr,
+                                            jexlContext, jxpathContext);
+                                } catch (Exception e) {
+                                    throw new SAXParseException(e.getMessage(),
+                                            ev.getLocation(), e);
+                                } catch (Error err) {
+                                    throw new SAXParseException(err
+                                            .getMessage(), ev.getLocation(),
+                                            new ErrorHolder(err));
+                                }
+                                buf.append(val != null ? val.toString() : "");
+                            }
+                        }
+                        attrs.addAttribute(attrEvent.getNamespaceURI(),
+                                attrEvent.getLocalName(), attrEvent.getRaw(),
+                                attrEvent.getType(), buf.toString());
+                    }
+                }
+                consumer.startElement(startElement.getNamespaceURI(),
+                        startElement.getLocalName(), startElement.getRaw(),
+                        attrs);
+            } else if (ev instanceof StartFormatNumber) {
+                StartFormatNumber startFormatNumber = (StartFormatNumber) ev;
+                try {
+                    String result = startFormatNumber.format(jexlContext,
+                            jxpathContext);
+                    if (result != null) {
+                        char[] chars = result.toCharArray();
+                        consumer.characters(chars, 0, chars.length);
+                    }
+                } catch (Exception e) {
+                    throw new SAXParseException(e.getMessage(), ev
+                            .getLocation(), e);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), ev
+                            .getLocation(), new ErrorHolder(err));
+                }
+            } else if (ev instanceof StartFormatDate) {
+                StartFormatDate startFormatDate = (StartFormatDate) ev;
+                try {
+                    String result = startFormatDate.format(jexlContext,
+                            jxpathContext);
+                    if (result != null) {
+                        char[] chars = result.toCharArray();
+                        consumer.characters(chars, 0, chars.length);
+                    }
+                } catch (Exception e) {
+                    throw new SAXParseException(e.getMessage(), ev
+                            .getLocation(), e);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), ev
+                            .getLocation(), new ErrorHolder(err));
+                }
+            } else if (ev instanceof StartPrefixMapping) {
+                StartPrefixMapping startPrefixMapping = (StartPrefixMapping) 
ev;
+                consumer.startPrefixMapping(startPrefixMapping.getPrefix(),
+                        startPrefixMapping.getUri());
+            } else if (ev instanceof StartComment) {
+                StartComment startJXComment = (StartComment) ev;
+                // Parse the body of the comment
+                NodeList nodeList = toDOMNodeList("comment", startJXComment,
+                        jexlContext, macroCall);
+                // JXPath doesn't handle NodeList, so convert it to an array
+                int len = nodeList.getLength();
+                final StringBuffer buf = new StringBuffer();
+                Properties omit = XMLUtils.createPropertiesForXML(true);
+                for (int i = 0; i < len; i++) {
+                    try {
+                        String str = XMLUtils.serializeNode(nodeList.item(i),
+                                omit);
+                        buf.append(StringUtils.substringAfter(str, ">")); // 
cut
+                        // the
+                        // XML
+                        // header
+                    } catch (ProcessingException e) {
+                        throw new SAXParseException(e.getMessage(),
+                                startJXComment.getLocation(), e);
+                    }
+                }
+                char[] chars = new char[buf.length()];
+                buf.getChars(0, chars.length, chars, 0);
+                consumer.comment(chars, 0, chars.length);
+                ev = startJXComment.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof EndCDATA) {
+                consumer.endCDATA();
+            } else if (ev instanceof EndDTD) {
+                consumer.endDTD();
+            } else if (ev instanceof EndEntity) {
+                consumer.endEntity(((EndEntity) ev).getName());
+            } else if (ev instanceof StartCDATA) {
+                consumer.startCDATA();
+            } else if (ev instanceof StartDTD) {
+                StartDTD startDTD = (StartDTD) ev;
+                consumer.startDTD(startDTD.getName(), startDTD.getPublicId(),
+                        startDTD.getSystemId());
+            } else if (ev instanceof StartEntity) {
+                consumer.startEntity(((StartEntity) ev).getName());
+            } else if (ev instanceof StartOut) {
+                StartOut startOut = (StartOut) ev;
+                Object val;
+                try {
+                    val = ValueHelper.getNode(startOut.getCompiledExpression(),
+                            jexlContext, jxpathContext, startOut.getLenient());
+                    if (val instanceof Node) {
+                        executeDOM(consumer, jexlContext, jxpathContext,
+                                (Node) val);
+                    } else if (val instanceof NodeList) {
+                        NodeList nodeList = (NodeList) val;
+                        int len = nodeList.getLength();
+                        for (int i = 0; i < len; i++) {
+                            Node n = nodeList.item(i);
+                            executeDOM(consumer, jexlContext, jxpathContext, 
n);
+                        }
+                    } else if (val instanceof Node[]) {
+                        Node[] nodeList = (Node[]) val;
+                        int len = nodeList.length;
+                        for (int i = 0; i < len; i++) {
+                            Node n = nodeList[i];
+                            executeDOM(consumer, jexlContext, jxpathContext, 
n);
+                        }
+                    } else if (val instanceof XMLizable) {
+                        ((XMLizable) val)
+                                .toSAX(new IncludeXMLConsumer(consumer));
+                    } else {
+                        char[] ch = val == null ? ArrayUtils.EMPTY_CHAR_ARRAY
+                                : val.toString().toCharArray();
+                        consumer.characters(ch, 0, ch.length);
+                    }
+                } catch (Exception e) {
+                    throw new SAXParseException(e.getMessage(), ev
+                            .getLocation(), e);
+                }
+            } else if (ev instanceof StartTemplate) {
+                // EMPTY
+            } else if (ev instanceof StartEval) {
+                StartEval startEval = (StartEval) ev;
+                JXTExpression expr = startEval.getValue();
+                try {
+                    Object val = ValueHelper.getNode(expr, jexlContext,
+                            jxpathContext);
+                    if (!(val instanceof StartElement)) {
+                        throw new Exception(
+                                "macro invocation required instead of: " + 
val);
+                    }
+                    StartElement call = (StartElement) val;
+                    execute(consumer, jexlContext, jxpathContext, call, call
+                            .getNext(), call.getEndElement());
+                } catch (Exception exc) {
+                    throw new SAXParseException(exc.getMessage(), ev
+                            .getLocation(), exc);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), ev
+                            .getLocation(), new ErrorHolder(err));
+                }
+                ev = startEval.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartEvalBody) {
+                StartEvalBody startEval = (StartEvalBody) ev;
+                try {
+                    execute(consumer, jexlContext, jxpathContext, null,
+                            macroCall.getNext(), macroCall.getEndElement());
+                } catch (Exception exc) {
+                    throw new SAXParseException(exc.getMessage(), ev
+                            .getLocation(), exc);
+                } catch (Error err) {
+                    throw new SAXParseException(err.getMessage(), ev
+                            .getLocation(), new ErrorHolder(err));
+                }
+                ev = startEval.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartDefine) {
+                StartDefine startDefine = (StartDefine) ev;
+                definitions.put(startDefine.getQname(), startDefine);
+                ev = startDefine.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartImport) {
+                StartImport startImport = (StartImport) ev;
+                String uri;
+                AttributeEvent e = startImport.getUri();
+                if (e instanceof CopyAttribute) {
+                    CopyAttribute copy = (CopyAttribute) e;
+                    uri = copy.getValue();
+                } else {
+                    StringBuffer buf = new StringBuffer();
+                    SubstituteAttribute substAttr = (SubstituteAttribute) e;
+                    Iterator i = substAttr.getSubstitutions().iterator();
+                    while (i.hasNext()) {
+                        Subst subst = (Subst) i.next();
+                        if (subst instanceof Literal) {
+                            Literal lit = (Literal) subst;
+                            buf.append(lit.getValue());
+                        } else if (subst instanceof JXTExpression) {
+                            JXTExpression expr = (JXTExpression) subst;
+                            Object val;
+                            try {
+                                val = ValueHelper.getValue(expr, jexlContext,
+                                        jxpathContext);
+                            } catch (Exception exc) {
+                                throw new SAXParseException(exc.getMessage(),
+                                        ev.getLocation(), exc);
+                            } catch (Error err) {
+                                throw new SAXParseException(err.getMessage(),
+                                        ev.getLocation(), new 
ErrorHolder(err));
+                            }
+                            buf.append(val != null ? val.toString() : "");
+                        }
+                    }
+                    uri = buf.toString();
+                }
+                Source input = null;
+                StartDocument doc;
+                try {
+                    input = resolver.resolveURI(uri);
+                    SourceValidity validity = null;
+                    synchronized (cache) {
+                        doc = (StartDocument) cache.get(input.getURI());
+                        if (doc != null) {
+                            boolean recompile = false;
+                            if (doc.getCompileTime() == null) {
+                                recompile = true;
+                            } else {
+                                int valid = doc.getCompileTime().isValid();
+                                if (valid == SourceValidity.UNKNOWN) {
+                                    validity = input.getValidity();
+                                    valid = doc.getCompileTime().isValid(
+                                            validity);
+                                }
+                                if (valid != SourceValidity.VALID) {
+                                    recompile = true;
+                                }
+                            }
+                            if (recompile) {
+                                doc = null; // recompile
+                            }
+                        }
+                    }
+                    if (doc == null) {
+                        Parser parser = new Parser();
+                        // call getValidity before using the stream is faster 
if
+                        // the source is a SitemapSource
+                        if (validity == null) {
+                            validity = input.getValidity();
+                        }
+                        SourceUtil.parse(this.manager, input, parser);
+                        doc = parser.getStartEvent();
+                        doc.setCompileTime(validity);
+                        synchronized (cache) {
+                            cache.put(input.getURI(), doc);
+                        }
+                    }
+                } catch (Exception exc) {
+                    throw new SAXParseException(exc.getMessage(), ev
+                            .getLocation(), exc);
+                } finally {
+                    resolver.release(input);
+                }
+                JXPathContext selectJXPath = jxpathContext;
+                MyJexlContext selectJexl = jexlContext;
+                if (startImport.getSelect() != null) {
+                    try {
+                        Object obj = ValueHelper.getValue(startImport
+                                .getSelect(), jexlContext, jxpathContext);
+                        selectJXPath = jxpathContextFactory.newContext(null,
+                                obj);
+                        selectJXPath.setVariables(variables);
+                        selectJexl = new MyJexlContext(jexlContext);
+                        fillContext(obj, selectJexl);
+                    } catch (Exception exc) {
+                        throw new SAXParseException(exc.getMessage(), ev
+                                .getLocation(), exc);
+                    } catch (Error err) {
+                        throw new SAXParseException(err.getMessage(), ev
+                                .getLocation(), new ErrorHolder(err));
+                    }
+                }
+                try {
+                    execute(consumer, selectJexl, selectJXPath, macroCall, doc
+                            .getNext(), doc.getEndDocument());
+                } catch (Exception exc) {
+                    throw new SAXParseException(
+                            "Exception occurred in imported template " + uri
+                                    + ": " + exc.getMessage(),
+                            ev.getLocation(), exc);
+                }
+                ev = startImport.getEndInstruction().getNext();
+                continue;
+            } else if (ev instanceof StartDocument) {
+                if (((StartDocument) ev).getEndDocument() != null) {
+                    // if this isn't a document fragment
+                    consumer.startDocument();
+                }
+            } else if (ev instanceof EndDocument) {
+                consumer.endDocument();
+            } else if (ev instanceof ProcessingInstruction) {
+                ProcessingInstruction pi = (ProcessingInstruction) ev;
+                consumer.processingInstruction(pi.getTarget(), pi.getData());
+            }
+            ev = ev.getNext();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.cocoon.caching.CacheableProcessingComponent#getKey()
+     */
+    public Serializable getKey() {
+        JXTExpression cacheKeyExpr = (JXTExpression) 
getCurrentTemplateProperty(JXTemplateGenerator.CACHE_KEY);
+        try {
+            final Serializable templateKey = (Serializable) ValueHelper
+                    .getValue(cacheKeyExpr, globalJexlContext, jxpathContext);
+            if (templateKey != null) {
+                return new JXCacheKey(this.inputSource.getURI(), templateKey);
+            }
+        } catch (Exception e) {
+            getLogger().error("error evaluating cache key", e);
+        }
+        return null;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see 
org.apache.cocoon.caching.CacheableProcessingComponent#getValidity()
+     */
+    public SourceValidity getValidity() {
+        JXTExpression validityExpr = (JXTExpression) 
getCurrentTemplateProperty(JXTemplateGenerator.VALIDITY);
+        try {
+            final SourceValidity sourceValidity = this.inputSource
+                    .getValidity();
+            final SourceValidity templateValidity = (SourceValidity) 
ValueHelper
+                    .getValue(validityExpr, globalJexlContext, jxpathContext);
+            if (sourceValidity != null && templateValidity != null) {
+                return new JXSourceValidity(sourceValidity, templateValidity);
+            }
+        } catch (Exception e) {
+            getLogger().error("error evaluating cache validity", e);
+        }
+        return null;
+    }
+
+    private Object getCurrentTemplateProperty(String propertyName) {
+        final String uri = this.inputSource.getURI();
+        StartDocument startEvent;
+        synchronized (cache) {
+            startEvent = (StartDocument) cache.get(uri);
+        }
+        return (startEvent != null) ? startEvent.getTemplateProperties().get(
+                propertyName) : null;
+    }
+
+    private NodeList toDOMNodeList(String elementName, StartInstruction si,
+            MyJexlContext jexlContext, StartElement macroCall)
+            throws SAXException {
+        DOMBuilder builder = new DOMBuilder();
+        builder.startDocument();
+        builder.startElement(NS, elementName, elementName, EMPTY_ATTRS);
+        execute(builder, jexlContext, jxpathContext, macroCall, si.getNext(),
+                si.getEndInstruction());
+        builder.endElement(NS, elementName, elementName);
+        builder.endDocument();
+        Node node = builder.getDocument().getDocumentElement();
+        return node.getChildNodes();
+    }
+
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/TransformerAdapter.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/TransformerAdapter.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/TransformerAdapter.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.template.jxtg.script.Parser;
+import org.apache.cocoon.transformation.ServiceableTransformer;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Adapter that makes this generator usable as a transformer
+ * (Note there is a performance penalty for this however:
+ * you effectively recompile the template for every instance document)
+ */
+public class TransformerAdapter extends ServiceableTransformer {
+    static class TemplateConsumer extends Parser implements XMLConsumer {
+
+        public TemplateConsumer() {
+            this.gen = new JXTemplateGenerator();
+        }
+
+        public void setup(SourceResolver resolver, Map objectModel, String 
src, Parameters parameters) 
+            throws ProcessingException, SAXException, IOException {
+            this.gen.setup(resolver, objectModel, null, parameters);
+        }
+
+        public void service(ServiceManager manager) 
+            throws ServiceException {
+            this.gen.service(manager);
+        }
+
+        public void endDocument() throws SAXException {
+            super.endDocument();
+            gen.performGeneration(gen.getConsumer(), gen.getJexlContext(), 
gen.getJXPathContext(), null, getStartEvent(), null);
+        }
+
+        void setConsumer(XMLConsumer consumer) {
+            gen.setConsumer(consumer);
+        }
+
+        protected void recycle() {
+            super.recycle();
+            gen.recycle();
+        }
+
+        JXTemplateGenerator gen;
+    }
+
+    TemplateConsumer templateConsumer = new TemplateConsumer();
+
+    public void recycle() {
+        super.recycle();
+        templateConsumer.recycle();
+    }
+
+    public void setup(SourceResolver resolver, Map objectModel, String src, 
Parameters parameters)
+        throws ProcessingException, SAXException, IOException {
+        super.setup(resolver, objectModel, src, parameters);
+        templateConsumer.setup(resolver, objectModel, src, parameters);
+    }
+
+    public void service(ServiceManager manager) 
+        throws ServiceException {
+        super.service(manager);
+        templateConsumer.service(manager);
+    }
+
+    public void setConsumer(XMLConsumer xmlConsumer) {
+        super.setConsumer(templateConsumer);
+        templateConsumer.setConsumer(xmlConsumer);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ErrorHolder.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ErrorHolder.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ErrorHolder.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,47 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+
+public class ErrorHolder extends Exception {
+
+    private Error err;
+
+    public ErrorHolder(Error err) {
+        super(err.getMessage());
+        this.err = err;
+    }
+
+    public void printStackTrace(PrintStream ps) {
+        err.printStackTrace(ps);
+    }
+
+    public void printStackTrace(PrintWriter pw) {
+        err.printStackTrace(pw);
+    }
+
+    public void printStackTrace() {
+        err.printStackTrace();
+    }
+
+    public Error getError() {
+        return err;
+    }
+
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JSIntrospector.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JSIntrospector.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JSIntrospector.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,318 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import org.apache.commons.jexl.util.introspection.Info;
+import org.apache.commons.jexl.util.introspection.UberspectImpl;
+import org.apache.commons.jexl.util.introspection.VelMethod;
+import org.apache.commons.jexl.util.introspection.VelPropertyGet;
+import org.apache.commons.jexl.util.introspection.VelPropertySet;
+import org.apache.commons.lang.StringUtils;
+import org.mozilla.javascript.*;
+
+
+/**
+ * Jexl Introspector that supports Rhino JavaScript objects
+ * as well as Java Objects
+ */
+public class JSIntrospector extends UberspectImpl {
+
+    static class JSMethod implements VelMethod {
+
+        Scriptable scope;
+        String name;
+
+        public JSMethod(Scriptable scope, String name) {
+            this.scope = scope;
+            this.name = name;
+        }
+
+        public Object invoke(Object thisArg, Object[] args) throws Exception {
+            Context cx = Context.enter();
+            try {
+                Object result;
+                Scriptable thisObj = !(thisArg instanceof Scriptable) ?
+                        Context.toObject(thisArg, scope) : (Scriptable)thisArg;
+                result = ScriptableObject.getProperty(thisObj, name);
+                Object[] newArgs = null;
+                if (args != null) {
+                    newArgs = new Object[args.length];
+                    int len = args.length;
+                    for (int i = 0; i < len; i++) {
+                        newArgs[i] = args[i];
+                        if (args[i] != null &&
+                            !(args[i] instanceof Number) &&
+                            !(args[i] instanceof Boolean) &&
+                            !(args[i] instanceof String) &&
+                            !(args[i] instanceof Scriptable)) {
+                            newArgs[i] = Context.toObject(args[i], scope);
+                        }
+                    }
+                }
+                result = ScriptRuntime.call(cx, result, thisObj, newArgs, 
scope);
+                if (result == Undefined.instance || result == 
Scriptable.NOT_FOUND) {
+                    result = null;
+                } else if (!(result instanceof NativeJavaClass)) {
+                    while (result instanceof Wrapper) {
+                        result = ((Wrapper)result).unwrap();
+                    }
+                }
+                return result;
+            } catch (JavaScriptException e) {
+                throw new java.lang.reflect.InvocationTargetException(e);
+            } finally {
+                Context.exit();
+            }
+        }
+
+        public boolean isCacheable() {
+            return false;
+        }
+
+        public String getMethodName() {
+            return name;
+        }
+
+        public Class getReturnType() {
+            return Object.class;
+        }
+
+    }
+
+    static class JSPropertyGet implements VelPropertyGet {
+
+        Scriptable scope;
+        String name;
+
+        public JSPropertyGet(Scriptable scope, String name) {
+            this.scope = scope;
+            this.name = name;
+        }
+
+        public Object invoke(Object thisArg) throws Exception {
+            Context cx = Context.enter();
+            try {
+                Scriptable thisObj = !(thisArg instanceof Scriptable) ?
+                        Context.toObject(thisArg, scope) : (Scriptable)thisArg;
+                Object result = ScriptableObject.getProperty(thisObj, name);
+                if (result == Scriptable.NOT_FOUND) {
+                    result = ScriptableObject.getProperty(thisObj, "get" + 
StringUtils.capitalize(name));
+                    if (result != Scriptable.NOT_FOUND && result instanceof 
Function) {
+                        try {
+                            result = ((Function)result).call(
+                                    cx, 
ScriptableObject.getTopLevelScope(thisObj), thisObj, new Object[] {});
+                        } catch (JavaScriptException exc) {
+                            exc.printStackTrace();
+                            result = null;
+                        }
+                    }
+                }
+                if (result == Scriptable.NOT_FOUND || result == 
Undefined.instance) {
+                    result = null;
+                } else if (result instanceof Wrapper && !(result instanceof 
NativeJavaClass)) {
+                    result = ((Wrapper)result).unwrap();
+                }
+                return result;
+            } finally {
+                Context.exit();
+            }
+        }
+
+        public boolean isCacheable() {
+            return false;
+        }
+
+        public String getMethodName() {
+            return name;
+        }
+    }
+
+    static class JSPropertySet implements VelPropertySet {
+
+        Scriptable scope;
+        String name;
+
+        public JSPropertySet(Scriptable scope, String name) {
+            this.scope = scope;
+            this.name = name;
+        }
+
+        public Object invoke(Object thisArg, Object rhs) throws Exception {
+            Context.enter();
+            try {
+                Scriptable thisObj;
+                Object arg = rhs;
+                if (!(thisArg instanceof Scriptable)) {
+                    thisObj = Context.toObject(thisArg, scope);
+                } else {
+                    thisObj = (Scriptable)thisArg;
+                }
+                if (arg != null &&
+                    !(arg instanceof Number) &&
+                    !(arg instanceof Boolean) &&
+                    !(arg instanceof String) &&
+                    !(arg instanceof Scriptable)) {
+                    arg = Context.toObject(arg, scope);
+                }
+                ScriptableObject.putProperty(thisObj, name, arg);
+                return rhs;
+            } finally {
+                Context.exit();
+            }
+        }
+
+        public boolean isCacheable() {
+            return false;
+        }
+
+        public String getMethodName() {
+            return name;
+        }
+    }
+
+    public static class NativeArrayIterator implements Iterator {
+
+        NativeArray arr;
+        int index;
+
+        public NativeArrayIterator(NativeArray arr) {
+            this.arr = arr;
+            this.index = 0;
+        }
+
+        public boolean hasNext() {
+            return index < (int)arr.jsGet_length();
+        }
+
+        public Object next() {
+            Context.enter();
+            try {
+                Object result = arr.get(index++, arr);
+                if (result == Undefined.instance ||
+                    result == Scriptable.NOT_FOUND) {
+                    result = null;
+                } else {
+                    if (!(result instanceof NativeJavaClass)) {
+                        while (result instanceof Wrapper) {
+                            result = ((Wrapper)result).unwrap();
+                        }
+                    }
+                }
+                return result;
+            } finally {
+                Context.exit();
+            }
+        }
+
+        public void remove() {
+            arr.delete(index);
+        }
+    }
+
+    static class ScriptableIterator implements Iterator {
+
+        Scriptable scope;
+        Object[] ids;
+        int index;
+
+        public ScriptableIterator(Scriptable scope) {
+            this.scope = scope;
+            this.ids = scope.getIds();
+            this.index = 0;
+        }
+
+        public boolean hasNext() {
+            return index < ids.length;
+        }
+
+        public Object next() {
+            Context.enter();
+            try {
+                Object result = ScriptableObject.getProperty(scope, 
ids[index++].toString());
+                if (result == Undefined.instance || result == 
Scriptable.NOT_FOUND) {
+                    result = null;
+                } else if (!(result instanceof NativeJavaClass)) {
+                    while (result instanceof Wrapper) {
+                        result = ((Wrapper)result).unwrap();
+                    }
+                }
+                return result;
+            } finally {
+                Context.exit();
+            }
+        }
+
+        public void remove() {
+            Context.enter();
+            try {
+                scope.delete(ids[index].toString());
+            } finally {
+                Context.exit();
+            }
+        }
+    }
+
+    public Iterator getIterator(Object obj, Info i) throws Exception {
+        if (!(obj instanceof Scriptable)) {
+            // support Enumeration
+            if (obj instanceof Enumeration) {
+                final Enumeration e = (Enumeration)obj;
+                return new Iterator() {
+
+                        public boolean hasNext() {
+                            return e.hasMoreElements();
+                        }
+
+                        public Object next() {
+                            return e.nextElement();
+                        }
+
+                        public void remove() {
+                            // no action
+                        }
+
+                    };
+            }
+            if (obj instanceof Iterator) {
+                // support Iterator
+                return (Iterator)obj;
+            }
+            return super.getIterator(obj, i);
+        }
+        if (obj instanceof NativeArray) {
+            return new NativeArrayIterator((NativeArray)obj);
+        }
+        return new ScriptableIterator((Scriptable)obj);
+    }
+
+    public VelMethod getMethod(Object obj, String methodName, Object[] args, 
Info i) throws Exception {
+        return !(obj instanceof Scriptable) ?
+                super.getMethod(obj, methodName, args, i) : new 
JSMethod((Scriptable)obj, methodName);
+    }
+
+    public VelPropertyGet getPropertyGet(Object obj, String identifier, Info 
i) throws Exception {
+        return !(obj instanceof Scriptable) ?
+                super.getPropertyGet(obj, identifier, i) : new 
JSPropertyGet((Scriptable)obj, identifier);
+    }
+
+    public VelPropertySet getPropertySet(Object obj, String identifier, Object 
arg, Info i) throws Exception {
+        return !(obj instanceof Scriptable) ?
+                super.getPropertySet(obj, identifier, arg, i) : new 
JSPropertySet((Scriptable)obj, identifier);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXCacheKey.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXCacheKey.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXCacheKey.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,45 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import java.io.Serializable;
+
+public final class JXCacheKey implements Serializable {
+    private final String templateUri;
+    private final Serializable templateKey;
+
+    public JXCacheKey(String templateUri, Serializable templateKey) {
+        this.templateUri = templateUri;
+        this.templateKey = templateKey;
+    }
+
+    public int hashCode() {
+        return templateUri.hashCode() + templateKey.hashCode();
+    }
+
+    public String toString() {
+        return "TK:" + templateUri + "_" + templateKey;
+    }
+
+    public boolean equals(Object o) {
+        if (o instanceof JXCacheKey) {
+            JXCacheKey jxck = (JXCacheKey) o;
+            return this.templateUri.equals(jxck.templateUri)
+                    && this.templateKey.equals(jxck.templateKey);
+        }
+        return false;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXSourceValidity.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXSourceValidity.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/JXSourceValidity.java
     Thu Dec  9 04:38:49 2004
@@ -0,0 +1,70 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import java.io.Serializable;
+
+import org.apache.excalibur.source.SourceValidity;
+
+public final class JXSourceValidity implements SourceValidity, Serializable {
+    private final SourceValidity sourceValidity;
+    private final SourceValidity templateValidity;
+
+    public JXSourceValidity(SourceValidity sourceValidity,
+            SourceValidity templateValidity) {
+        this.sourceValidity = sourceValidity;
+        this.templateValidity = templateValidity;
+    }
+
+    public int isValid() {
+        switch (sourceValidity.isValid()) {
+        case SourceValidity.INVALID:
+            return SourceValidity.INVALID;
+        case SourceValidity.UNKNOWN: {
+            if (templateValidity.isValid() == SourceValidity.INVALID) {
+                return SourceValidity.INVALID;
+            } else {
+                return SourceValidity.UNKNOWN;
+            }
+        }
+        case SourceValidity.VALID:
+            return templateValidity.isValid();
+        }
+        return SourceValidity.UNKNOWN;
+    }
+
+    public int isValid(SourceValidity otherValidity) {
+        if (otherValidity instanceof JXSourceValidity) {
+            JXSourceValidity otherJXValidity = (JXSourceValidity) 
otherValidity;
+            switch (sourceValidity.isValid(otherJXValidity.sourceValidity)) {
+            case SourceValidity.INVALID:
+                return SourceValidity.INVALID;
+            case SourceValidity.UNKNOWN: {
+                if (templateValidity.isValid(otherJXValidity.templateValidity) 
== SourceValidity.INVALID) {
+                    return SourceValidity.INVALID;
+                } else {
+                    return SourceValidity.UNKNOWN;
+                }
+            }
+            case SourceValidity.VALID:
+                return templateValidity
+                        .isValid(otherJXValidity.templateValidity);
+            }
+        }
+        return 0;
+    }
+
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/LocatorFacade.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/LocatorFacade.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/LocatorFacade.java
        Thu Dec  9 04:38:49 2004
@@ -0,0 +1,50 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import org.xml.sax.Locator;
+
+/**
+ * Facade to the Locator to be set on the consumer prior to sending other
+ * events, location member changeable
+ */
+public class LocatorFacade implements Locator {
+    private Locator locator;
+
+    public LocatorFacade(Locator initialLocator) {
+        this.locator = initialLocator;
+    }
+
+    public void setDocumentLocator(Locator newLocator) {
+        this.locator = newLocator;
+    }
+
+    public int getColumnNumber() {
+        return this.locator.getColumnNumber();
+    }
+
+    public int getLineNumber() {
+        return this.locator.getLineNumber();
+    }
+
+    public String getPublicId() {
+        return this.locator.getPublicId();
+    }
+
+    public String getSystemId() {
+        return this.locator.getSystemId();
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/MyVariables.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/MyVariables.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/MyVariables.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cocoon.components.flow.WebContinuation;
+import org.apache.commons.jxpath.Variables;
+
+public class MyVariables implements Variables {
+    MyVariables closure;
+    Map localVariables = new HashMap();
+
+    static final String[] VARIABLES = new String[] { "cocoon", "continuation",
+            "flowContext", "request", "response", "context", "session",
+            "parameters" };
+
+    Object cocoon;
+
+    // backward compatibility
+    Object bean, kont, request, response, session, context, parameters;
+
+    public MyVariables(Object cocoon, Object bean, WebContinuation kont,
+            Object request, Object session, Object context, Object parameters) 
{
+        this.cocoon = cocoon;
+        this.bean = bean;
+        this.kont = kont;
+        this.request = request;
+        this.session = session;
+        this.context = context;
+        this.parameters = parameters;
+    }
+
+    public MyVariables(MyVariables parent) {
+        this.closure = parent;
+    }
+
+    public boolean isDeclaredVariable(String varName) {
+        int len = VARIABLES.length;
+        for (int i = 0; i < len; i++) {
+            if (varName.equals(VARIABLES[i])) {
+                return true;
+            }
+        }
+        if (localVariables.containsKey(varName)) {
+            return true;
+        }
+        if (closure != null) {
+            return closure.isDeclaredVariable(varName);
+        }
+        return false;
+    }
+
+    public Object getVariable(String varName) {
+        Object result = localVariables.get(varName);
+        if (result != null) {
+            return result;
+        }
+        if (closure != null) {
+            return closure.getVariable(varName);
+        }
+        if (varName.equals("cocoon")) {
+            return cocoon;
+        }
+        // backward compatibility
+        if (varName.equals("continuation")) {
+            return kont;
+        } else if (varName.equals("flowContext")) {
+            return bean;
+        } else if (varName.equals("request")) {
+            return request;
+        } else if (varName.equals("session")) {
+            return session;
+        } else if (varName.equals("context")) {
+            return context;
+        } else if (varName.equals("parameters")) {
+            return parameters;
+        }
+        return null;
+    }
+
+    public void declareVariable(String varName, Object value) {
+        localVariables.put(varName, value);
+    }
+
+    public void undeclareVariable(String varName) {
+        localVariables.remove(varName);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ValueHelper.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ValueHelper.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/environment/ValueHelper.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,185 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.environment;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.commons.jexl.Expression;
+import org.apache.commons.jexl.JexlContext;
+import org.apache.commons.jxpath.CompiledExpression;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.jxpath.Pointer;
+import org.apache.commons.lang.StringUtils;
+import org.w3c.dom.Node;
+
+/**
+ */
+public class ValueHelper {
+
+    public static Locale parseLocale(String locale, String variant) {
+        Locale ret = null;
+        String language = locale;
+        String country = null;
+        int index = StringUtils.indexOfAny(locale, "-_");
+    
+        if (index > -1) {
+            language = locale.substring(0, index);
+            country = locale.substring(index + 1);
+        }
+        if (StringUtils.isEmpty(language)) {
+            throw new IllegalArgumentException("No language in locale");
+        }
+        if (country == null) {
+            ret = variant != null ? new Locale(language, "", variant) : new 
Locale(language, ""); 
+        } else if (country.length() > 0) {
+            ret = variant != null ? new Locale(language, country, variant) : 
new Locale(language, country); 
+        } else {
+            throw new IllegalArgumentException("Empty country in locale");
+        }
+        return ret;
+    }
+
+    // Hack: try to prevent JXPath from converting result to a String
+    public static Object getNode(JXTExpression expr, JexlContext jexlContext, 
JXPathContext jxpathContext, Boolean lenient)
+               throws Exception {
+        try {
+            Object compiled = expr.getCompiledExpression();
+            if (compiled instanceof CompiledExpression) {
+                CompiledExpression e = (CompiledExpression)compiled;
+                boolean oldLenient = jxpathContext.isLenient();
+                if (lenient != null) 
jxpathContext.setLenient(lenient.booleanValue());
+                try {
+                    Iterator iter = e.iteratePointers(jxpathContext);
+                    if (iter.hasNext()) {
+                        Pointer first = (Pointer)iter.next();
+                        if (iter.hasNext()) {
+                           List result = new LinkedList();
+                           result.add(first.getNode());
+                           boolean dom = (first.getNode() instanceof Node);
+                           while (iter.hasNext()) {
+                               Object obj = ((Pointer)iter.next()).getNode();
+                               dom = dom && (obj instanceof Node);
+                               result.add(obj);
+                           }
+                           Object[] arr;
+                           if (dom) {
+                               arr = new Node[result.size()];
+                           } else {
+                               arr = new Object[result.size()];
+                           }
+                           result.toArray(arr);
+                           return arr;
+                       }
+                       return first.getNode();                    
+                    }
+                    return null;
+                } finally {
+                    jxpathContext.setLenient(oldLenient);
+                }
+            } else if (compiled instanceof Expression) {
+                Expression e = (Expression)compiled;
+                return e.evaluate(jexlContext);
+            }
+            return expr.getRaw();
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            if (t instanceof Exception) {
+                throw (Exception)t;
+            }
+            throw (Error)t;
+        }
+    }
+
+    public static Object getNode(JXTExpression expr, JexlContext jexlContext, 
JXPathContext jxpathContext) throws Exception {
+        return getNode(expr, jexlContext, jxpathContext, null);
+    }
+
+    public static Boolean getBooleanValue(JXTExpression expr, JexlContext 
jexlContext,
+                                    JXPathContext jxpathContext) throws 
Exception {
+        Object res = ValueHelper.getValue(expr, jexlContext, jxpathContext);
+        return res instanceof Boolean ? (Boolean)res : null;
+    }
+
+    public static String getStringValue(JXTExpression expr, JexlContext 
jexlContext,
+                                JXPathContext jxpathContext) throws Exception {
+        Object res = ValueHelper.getValue(expr, jexlContext, jxpathContext);
+        if (res != null) {
+            return res.toString();
+        }
+        if (expr != null && expr.getCompiledExpression() == null) {
+            return expr.getRaw();
+        }
+        return null;
+    }
+
+    public static Number getNumberValue(JXTExpression expr, JexlContext 
jexlContext, JXPathContext jxpathContext) throws Exception {
+        Object res = ValueHelper.getValue(expr, jexlContext, jxpathContext);
+        if (res instanceof Number) {
+            return (Number)res;
+        }
+        if (res != null) {
+            return Double.valueOf(res.toString());
+        }
+        return null;
+    }
+
+    public static int getIntValue(JXTExpression expr, JexlContext jexlContext, 
JXPathContext jxpathContext) throws Exception {
+        Object res = ValueHelper.getValue(expr, jexlContext, jxpathContext);
+        return res instanceof Number ? ((Number)res).intValue() : 0;
+    }
+
+    public static Object getValue(JXTExpression expr, JexlContext jexlContext, 
JXPathContext jxpathContext) throws Exception {
+        return ValueHelper.getValue(expr, jexlContext, jxpathContext, null);
+    }
+
+    public static Object getValue(JXTExpression expr, JexlContext jexlContext,
+            JXPathContext jxpathContext, Boolean lenient) throws Exception {
+        if (expr != null) {
+            Object compiled = expr.getCompiledExpression();
+            try {
+                if (compiled instanceof CompiledExpression) {
+                    CompiledExpression e = (CompiledExpression) compiled;
+                    boolean oldLenient = jxpathContext.isLenient();
+                    if (lenient != null) {
+                        jxpathContext.setLenient(lenient.booleanValue());
+                    }
+                    try {
+                        return e.getValue(jxpathContext);
+                    } finally {
+                        jxpathContext.setLenient(oldLenient);
+                    }
+                } else if (compiled instanceof Expression) {
+                    Expression e = (Expression) compiled;
+                    return e.evaluate(jexlContext);
+                }
+                return compiled;
+            } catch (InvocationTargetException e) {
+                Throwable t = e.getTargetException();
+                if (t instanceof Exception) {
+                    throw (Exception) t;
+                }
+                throw (Error) t;
+            }
+        } else {
+            return null;
+        }
+    }
+}

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/JXTExpression.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/JXTExpression.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/JXTExpression.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.expression;
+
+
+public class JXTExpression extends Subst {
+    public JXTExpression(String raw, Object expr) {
+        this.raw = raw;
+        this.compiledExpression = expr;
+    }
+
+    String raw;
+    Object compiledExpression;
+
+    public Object getCompiledExpression() {
+        return compiledExpression;
+    }
+
+    public void setCompiledExpression(Object compiledExpression) {
+        this.compiledExpression = compiledExpression;
+    }
+
+    public String getRaw() {
+        return raw;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Literal.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Literal.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Literal.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,28 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.expression;
+
+public class Literal extends Subst {
+    public Literal(String val) {
+        this.value = val;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    private final String value;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/MyJexlContext.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/MyJexlContext.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/MyJexlContext.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.expression;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.jexl.JexlContext;
+
+public class MyJexlContext extends HashMap implements JexlContext {
+    private MyJexlContext closure;
+
+    public MyJexlContext() {
+        this(null);
+    }
+
+    public MyJexlContext(MyJexlContext closure) {
+        this.closure = closure;
+    }
+
+    public Map getVars() {
+        return this;
+    }
+
+    public void setVars(Map map) {
+        putAll(map);
+    }
+
+    public boolean containsKey(Object key) {
+        return this.get(key) != null;
+    }
+
+    public Object get(Object key) {
+        if (key.equals("this")) {
+            return this;
+        }
+        Object result = super.get(key);
+        if (result == null && closure != null) {
+            result = closure.get(key);
+        }
+        return result;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Subst.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Subst.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/expression/Subst.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,20 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.expression;
+
+public class Subst {
+    // VOID
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/Parser.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/Parser.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/Parser.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,585 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Iterator;
+import java.util.Stack;
+
+import org.apache.cocoon.template.jxtg.JXTemplateGenerator;
+import org.apache.cocoon.template.jxtg.environment.ErrorHolder;
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.cocoon.template.jxtg.script.event.*;
+import org.apache.commons.jexl.ExpressionFactory;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.lang.StringUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.helpers.LocatorImpl;
+
+public class Parser implements ContentHandler, LexicalHandler {
+
+    StartDocument startEvent;
+    Event lastEvent;
+    Stack stack = new Stack();
+    Locator locator;
+    Locator charLocation;
+    StringBuffer charBuf;
+
+    final static String TEMPLATE = "template";
+    final static String FOR_EACH = "forEach";
+    final static String IF = "if";
+    final static String CHOOSE = "choose";
+    final static String WHEN = "when";
+    final static String OTHERWISE = "otherwise";
+    final static String OUT = "out";
+    final static String IMPORT = "import";
+    final static String SET = "set";
+    final static String MACRO = "macro";
+    final static String EVALBODY = "evalBody";
+    final static String EVAL = "eval";
+    final static String PARAMETER = "parameter";
+    final static String FORMAT_NUMBER = "formatNumber";
+    final static String FORMAT_DATE = "formatDate";
+    final static String COMMENT = "comment";
+
+    public Parser() {
+        // EMPTY
+    }
+
+    public StartDocument getStartEvent() {
+        return this.startEvent;
+    }
+
+    protected void recycle() {
+        startEvent = null;
+        lastEvent = null;
+        stack.clear();
+        locator = null;
+        charLocation = null;
+        charBuf = null;
+    }
+
+    private void addEvent(Event ev) throws SAXException {
+        if (ev != null) {
+            if (lastEvent == null) {
+                lastEvent = startEvent = new StartDocument(locator);
+            } else {
+                flushChars();
+            }
+            lastEvent.setNext(ev);
+            lastEvent = ev;
+        } else {
+            throw new NullPointerException("null event");
+        }
+    }
+
+    void flushChars() throws SAXException {
+        if (charBuf != null) {
+            char[] chars = new char[charBuf.length()];
+            charBuf.getChars(0, charBuf.length(), chars, 0);
+            Characters ev = new Characters(charLocation, chars, 0, 
chars.length);
+            lastEvent.setNext(ev);
+            lastEvent = ev;
+            charLocation = null;
+            charBuf = null;
+        }
+    }
+
+    public void characters(char[] ch, int start, int length)
+            throws SAXException {
+        if (charBuf == null) {
+            charBuf = new StringBuffer(length);
+            charLocation = locator != null ? new LocatorImpl(locator)
+                    : JXTemplateGenerator.NULL_LOCATOR;
+        }
+        charBuf.append(ch, start, length);
+    }
+
+    public void endDocument() throws SAXException {
+        StartDocument startDoc = (StartDocument) stack.pop();
+        EndDocument endDoc = new EndDocument(locator);
+        startDoc.setEndDocument(endDoc);
+        addEvent(endDoc);
+    }
+
+    public void endElement(String namespaceURI, String localName, String raw)
+            throws SAXException {
+        Event start = (Event) stack.pop();
+        Event newEvent = null;
+        if (JXTemplateGenerator.NS.equals(namespaceURI)) {
+            StartInstruction startInstruction = (StartInstruction) start;
+            EndInstruction endInstruction = new EndInstruction(locator,
+                    startInstruction);
+            newEvent = endInstruction;
+            if (start instanceof StartWhen) {
+                StartWhen startWhen = (StartWhen) start;
+                StartChoose startChoose = (StartChoose) stack.peek();
+                if (startChoose.getFirstChoice() != null) {
+                    StartWhen w = startChoose.getFirstChoice();
+                    while (w.getNextChoice() != null) {
+                        w = w.getNextChoice();
+                    }
+                    w.setNextChoice(startWhen);
+                } else {
+                    startChoose.setFirstChoice(startWhen);
+                }
+            } else if (start instanceof StartOtherwise) {
+                StartOtherwise startOtherwise = (StartOtherwise) start;
+                StartChoose startChoose = (StartChoose) stack.peek();
+                startChoose.setOtherwise(startOtherwise);
+            }
+        } else {
+            StartElement startElement = (StartElement) start;
+            newEvent = new EndElement(locator, startElement);
+            startElement.setEndElement((EndElement) newEvent);
+        }
+        addEvent(newEvent);
+        if (start instanceof StartDefine) {
+            StartDefine startDefine = (StartDefine) start;
+            startDefine.finish();
+        }
+    }
+
+    public void endPrefixMapping(String prefix) throws SAXException {
+        EndPrefixMapping endPrefixMapping = new EndPrefixMapping(locator,
+                prefix);
+        addEvent(endPrefixMapping);
+    }
+
+    public void ignorableWhitespace(char[] ch, int start, int length)
+            throws SAXException {
+        Event ev = new IgnorableWhitespace(locator, ch, start, length);
+        addEvent(ev);
+    }
+
+    public void processingInstruction(String target, String data)
+            throws SAXException {
+        Event pi = new ProcessingInstruction(locator, target, data);
+        addEvent(pi);
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        this.locator = locator;
+    }
+
+    public void skippedEntity(String name) throws SAXException {
+        addEvent(new SkippedEntity(locator, name));
+    }
+
+    public void startDocument() {
+        startEvent = new StartDocument(locator);
+        lastEvent = startEvent;
+        stack.push(lastEvent);
+    }
+
+    public void startElement(String namespaceURI, String localName,
+            String qname, Attributes attrs) throws SAXException {
+        Event newEvent = null;
+        AttributesImpl elementAttributes = new AttributesImpl(attrs);
+        int attributeCount = elementAttributes.getLength();
+        for (int i = 0; i < attributeCount; i++) {
+            String attributeURI = elementAttributes.getURI(i);
+            if (StringUtils.equals(attributeURI, JXTemplateGenerator.NS)) {
+                getStartEvent().getTemplateProperties().put(
+                        elementAttributes.getLocalName(i),
+                        compileExpr(elementAttributes.getValue(i), null,
+                                locator));
+                elementAttributes.removeAttribute(i--);
+            }
+        }
+        StartElement startElement = new StartElement(locator, namespaceURI,
+                localName, qname, elementAttributes);
+        if (JXTemplateGenerator.NS.equals(namespaceURI)) {
+            if (localName.equals(FOR_EACH)) {
+                String items = attrs.getValue("items");
+                String select = attrs.getValue("select");
+                JXTExpression begin = compileInt(attrs.getValue("begin"),
+                        FOR_EACH, locator);
+                JXTExpression end = compileInt(attrs.getValue("end"), FOR_EACH,
+                        locator);
+                JXTExpression step = compileInt(attrs.getValue("step"),
+                        FOR_EACH, locator);
+                JXTExpression var = compileExpr(attrs.getValue("var"), null,
+                        locator);
+                JXTExpression varStatus = compileExpr(attrs
+                        .getValue("varStatus"), null, locator);
+                if (items == null) {
+                    if (select == null && (begin == null || end == null)) {
+                        throw new SAXParseException(
+                                "forEach: \"select\", \"items\", or both 
\"begin\" and \"end\" must be specified",
+                                locator, null);
+                    }
+                } else if (select != null) {
+                    throw new SAXParseException(
+                            "forEach: only one of \"select\" or \"items\" may 
be specified",
+                            locator, null);
+                }
+                JXTExpression expr = compileExpr(
+                        items == null ? select : items, null, locator);
+                String lenientValue = attrs.getValue("lenient");
+                Boolean lenient = (lenientValue == null) ? null : Boolean
+                        .valueOf(lenientValue);
+                StartForEach startForEach = new StartForEach(startElement,
+                        expr, var, varStatus, begin, end, step, lenient);
+                newEvent = startForEach;
+            } else if (localName.equals(FORMAT_NUMBER)) {
+                JXTExpression value = compileExpr(attrs.getValue("value"),
+                        null, locator);
+                JXTExpression type = compileExpr(attrs.getValue("type"), null,
+                        locator);
+                JXTExpression pattern = compileExpr(attrs.getValue("pattern"),
+                        null, locator);
+                JXTExpression currencyCode = compileExpr(attrs
+                        .getValue("currencyCode"), null, locator);
+                JXTExpression currencySymbol = compileExpr(attrs
+                        .getValue("currencySymbol"), null, locator);
+                JXTExpression isGroupingUsed = compileBoolean(attrs
+                        .getValue("isGroupingUsed"), null, locator);
+                JXTExpression maxIntegerDigits = compileInt(attrs
+                        .getValue("maxIntegerDigits"), null, locator);
+                JXTExpression minIntegerDigits = compileInt(attrs
+                        .getValue("minIntegerDigits"), null, locator);
+                JXTExpression maxFractionDigits = compileInt(attrs
+                        .getValue("maxFractionDigits"), null, locator);
+                JXTExpression minFractionDigits = compileInt(attrs
+                        .getValue("minFractionDigits"), null, locator);
+                JXTExpression var = compileExpr(attrs.getValue("var"), null,
+                        locator);
+                JXTExpression locale = compileExpr(attrs.getValue("locale"),
+                        null, locator);
+                StartFormatNumber startFormatNumber = new StartFormatNumber(
+                        startElement, var, value, type, pattern, currencyCode,
+                        currencySymbol, isGroupingUsed, maxIntegerDigits,
+                        minIntegerDigits, maxFractionDigits, minFractionDigits,
+                        locale);
+                newEvent = startFormatNumber;
+            } else if (localName.equals(FORMAT_DATE)) {
+                JXTExpression var = compileExpr(attrs.getValue("var"), null,
+                        locator);
+                JXTExpression value = compileExpr(attrs.getValue("value"),
+                        null, locator);
+                JXTExpression type = compileExpr(attrs.getValue("type"), null,
+                        locator);
+                JXTExpression pattern = compileExpr(attrs.getValue("pattern"),
+                        null, locator);
+                JXTExpression timeZone = compileExpr(
+                        attrs.getValue("timeZone"), null, locator);
+                JXTExpression dateStyle = compileExpr(attrs
+                        .getValue("dateStyle"), null, locator);
+                JXTExpression timeStyle = compileExpr(attrs
+                        .getValue("timeStyle"), null, locator);
+                JXTExpression locale = compileExpr(attrs.getValue("locale"),
+                        null, locator);
+                StartFormatDate startFormatDate = new StartFormatDate(
+                        startElement, var, value, type, pattern, timeZone,
+                        dateStyle, timeStyle, locale);
+                newEvent = startFormatDate;
+            } else if (localName.equals(CHOOSE)) {
+                StartChoose startChoose = new StartChoose(startElement);
+                newEvent = startChoose;
+            } else if (localName.equals(WHEN)) {
+                if (stack.size() == 0 || !(stack.peek() instanceof 
StartChoose)) {
+                    throw new SAXParseException(
+                            "<when> must be within <choose>", locator, null);
+                }
+                String test = attrs.getValue("test");
+                if (test != null) {
+                    JXTExpression expr = compileExpr(test, "when: \"test\": ",
+                            locator);
+                    StartWhen startWhen = new StartWhen(startElement, expr);
+                    newEvent = startWhen;
+                } else {
+                    throw new SAXParseException("when: \"test\" is required",
+                            locator, null);
+                }
+            } else if (localName.equals(OUT)) {
+                String value = attrs.getValue("value");
+                if (value != null) {
+                    JXTExpression expr = compileExpr(value, "out: \"value\": ",
+                            locator);
+                    String lenientValue = attrs.getValue("lenient");
+                    Boolean lenient = lenientValue == null ? null : Boolean
+                            .valueOf(lenientValue);
+                    newEvent = new StartOut(startElement, expr, lenient);
+                } else {
+                    throw new SAXParseException("out: \"value\" is required",
+                            locator, null);
+                }
+            } else if (localName.equals(OTHERWISE)) {
+                if (stack.size() != 0 && (stack.peek() instanceof 
StartChoose)) {
+                    StartOtherwise startOtherwise = new StartOtherwise(
+                            startElement);
+                    newEvent = startOtherwise;
+                } else {
+                    throw new SAXParseException(
+                            "<otherwise> must be within <choose>", locator,
+                            null);
+                }
+            } else if (localName.equals(IF)) {
+                String test = attrs.getValue("test");
+                if (test != null) {
+                    JXTExpression expr = compileExpr(test, "if: \"test\": ",
+                            locator);
+                    StartIf startIf = new StartIf(startElement, expr);
+                    newEvent = startIf;
+                } else {
+                    throw new SAXParseException("if: \"test\" is required",
+                            locator, null);
+                }
+            } else if (localName.equals(MACRO)) {
+                // <macro name="myTag" targetNamespace="myNamespace">
+                // <parameter name="paramName" required="Boolean"
+                // default="value"/>
+                // body
+                // </macro>
+                String namespace = StringUtils.defaultString(attrs
+                        .getValue("targetNamespace"));
+                String name = attrs.getValue("name");
+                if (name != null) {
+                    StartDefine startDefine = new StartDefine(startElement,
+                            namespace, name);
+                    newEvent = startDefine;
+                } else {
+                    throw new SAXParseException("macro: \"name\" is required",
+                            locator, null);
+                }
+            } else if (localName.equals(PARAMETER)) {
+                if (stack.size() == 0 || !(stack.peek() instanceof 
StartDefine)) {
+                    throw new SAXParseException("<parameter> not allowed here",
+                            locator, null);
+                } else {
+                    String name = attrs.getValue("name");
+                    String optional = attrs.getValue("optional");
+                    String default_ = attrs.getValue("default");
+                    if (name != null) {
+                        StartParameter startParameter = new StartParameter(
+                                startElement, name, optional, default_);
+                        newEvent = startParameter;
+                    } else {
+                        throw new SAXParseException(
+                                "parameter: \"name\" is required", locator,
+                                null);
+                    }
+                }
+            } else if (localName.equals(EVALBODY)) {
+                newEvent = new StartEvalBody(startElement);
+            } else if (localName.equals(EVAL)) {
+                String value = attrs.getValue("select");
+                JXTExpression valueExpr = compileExpr(value,
+                        "eval: \"select\":", locator);
+                newEvent = new StartEval(startElement, valueExpr);
+            } else if (localName.equals(SET)) {
+                String var = attrs.getValue("var");
+                String value = attrs.getValue("value");
+                JXTExpression varExpr = null;
+                JXTExpression valueExpr = null;
+                if (var != null) {
+                    varExpr = compileExpr(var, "set: \"var\":", locator);
+                }
+                if (value != null) {
+                    valueExpr = compileExpr(value, "set: \"value\":", locator);
+                }
+                StartSet startSet = new StartSet(startElement, varExpr,
+                        valueExpr);
+                newEvent = startSet;
+            } else if (localName.equals(IMPORT)) {
+                // <import uri="${root}/foo/bar.xml" context="${foo}"/>
+                AttributeEvent uri = null;
+                Iterator iter = startElement.getAttributeEvents().iterator();
+                while (iter.hasNext()) {
+                    AttributeEvent e = (AttributeEvent) iter.next();
+                    if (e.getLocalName().equals("uri")) {
+                        uri = e;
+                        break;
+                    }
+                }
+                if (uri != null) {
+                    // If "context" is present then its value will be used
+                    // as the context object in the imported template
+                    String select = attrs.getValue("context");
+                    JXTExpression expr = null;
+                    if (select != null) {
+                        expr = compileExpr(select, "import: \"context\": ",
+                                locator);
+                    }
+                    StartImport startImport = new StartImport(startElement,
+                            uri, expr);
+                    newEvent = startImport;
+                } else {
+                    throw new SAXParseException("import: \"uri\" is required",
+                            locator, null);
+                }
+            } else if (localName.equals(TEMPLATE)) {
+                StartTemplate startTemplate = new StartTemplate(startElement);
+                newEvent = startTemplate;
+            } else if (localName.equals(COMMENT)) {
+                // <jx:comment>This will be parsed</jx:comment>
+                StartComment startJXComment = new StartComment(startElement);
+                newEvent = startJXComment;
+            } else {
+                throw new SAXParseException("unrecognized tag: " + localName,
+                        locator, null);
+            }
+        } else {
+            newEvent = startElement;
+        }
+        stack.push(newEvent);
+        addEvent(newEvent);
+    }
+
+    public void startPrefixMapping(String prefix, String uri)
+            throws SAXException {
+        addEvent(new StartPrefixMapping(locator, prefix, uri));
+    }
+
+    public void comment(char ch[], int start, int length) throws SAXException {
+        //DO NOTHING
+    }
+
+    public void endCDATA() throws SAXException {
+        addEvent(new EndCDATA(locator));
+    }
+
+    public void endDTD() throws SAXException {
+        addEvent(new EndDTD(locator));
+    }
+
+    public void endEntity(String name) throws SAXException {
+        addEvent(new EndEntity(locator, name));
+    }
+
+    public void startCDATA() throws SAXException {
+        addEvent(new StartCDATA(locator));
+    }
+
+    public void startDTD(String name, String publicId, String systemId)
+            throws SAXException {
+        addEvent(new StartDTD(locator, name, publicId, systemId));
+    }
+
+    public void startEntity(String name) throws SAXException {
+        addEvent(new StartEntity(locator, name));
+    }
+
+    public static JXTExpression compile(final String variable, boolean xpath)
+            throws Exception {
+        Object compiled;
+        if (xpath) {
+            compiled = JXPathContext.compile(variable);
+        } else {
+            compiled = ExpressionFactory.createExpression(variable);
+        }
+        return new JXTExpression(variable, compiled);
+    }
+
+    public static JXTExpression compileBoolean(String val, String msg,
+            Locator location) throws SAXException {
+        JXTExpression res = compileExpr(val, msg, location);
+        if (res != null) {
+            if (res.getCompiledExpression() == null) {
+                res.setCompiledExpression(Boolean.valueOf(res.getRaw()));
+            }
+            return res;
+        }
+        return null;
+    }
+
+    /*
+     * Compile an integer expression (returns either a Compiled Expression or 
an
+     * Integer literal)
+     */
+    public static JXTExpression compileInt(String val, String msg,
+            Locator location) throws SAXException {
+        JXTExpression res = compileExpr(val, msg, location);
+        if (res != null) {
+            if (res.getCompiledExpression() == null) {
+                res.setCompiledExpression(Integer.valueOf(res.getRaw()));
+            }
+            return res;
+        }
+        return null;
+    }
+
+    public static JXTExpression compileExpr(String inStr) throws Exception {
+        try {
+            if (inStr == null) {
+                return null;
+            }
+            StringReader in = new StringReader(inStr.trim());
+            int ch;
+            boolean xpath = false;
+            boolean inExpr = false;
+            StringBuffer expr = new StringBuffer();
+            while ((ch = in.read()) != -1) {
+                char c = (char) ch;
+                if (inExpr) {
+                    if (c == '\\') {
+                        ch = in.read();
+                        expr.append((ch == -1) ? '\\' : (char) ch);
+                    } else if (c == '}') {
+                        return compile(expr.toString(), xpath);
+                    } else {
+                        expr.append(c);
+                    }
+                } else {
+                    if (c == '$' || c == '#') {
+                        ch = in.read();
+                        if (ch == '{') {
+                            inExpr = true;
+                            xpath = c == '#';
+                            continue;
+                        }
+                    }
+                    // hack: invalid expression?
+                    // just return the original and swallow exception
+                    return new JXTExpression(inStr, null);
+                }
+            }
+            if (inExpr) {
+                // unclosed #{} or ${}
+                throw new Exception("Unterminated " + (xpath ? "#" : "$") + 
"{");
+            }
+        } catch (IOException ignored) {
+            ignored.printStackTrace();
+        }
+        return new JXTExpression(inStr, null);
+    }
+
+    /**
+     * Compile a single Jexl expr (contained in ${}) or XPath expression
+     * (contained in #{})
+     */
+
+    public static JXTExpression compileExpr(String expr, String errorPrefix,
+            Locator location) throws SAXParseException {
+        try {
+            return compileExpr(expr);
+        } catch (Exception exc) {
+            throw new SAXParseException(errorPrefix + exc.getMessage(),
+                    location, exc);
+        } catch (Error err) {
+            throw new SAXParseException(errorPrefix + err.getMessage(),
+                    location, new ErrorHolder(err));
+        }
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/AttributeEvent.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/AttributeEvent.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/AttributeEvent.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,48 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public abstract class AttributeEvent {
+    public AttributeEvent(String namespaceURI, String localName, String raw,
+            String type) {
+        this.namespaceURI = namespaceURI;
+        this.localName = localName;
+        this.raw = raw;
+        this.type = type;
+    }
+
+    final String namespaceURI;
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    public String getRaw() {
+        return raw;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    final String localName;
+    final String raw;
+    final String type;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Characters.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Characters.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Characters.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,26 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+public class Characters extends TextEvent {
+    public Characters(Locator location, char[] chars, int start, int length)
+            throws SAXException {
+        super(location, chars, start, length);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/CopyAttribute.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/CopyAttribute.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/CopyAttribute.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class CopyAttribute extends AttributeEvent {
+    public CopyAttribute(String namespaceURI, String localName, String raw,
+            String type, String value) {
+        super(namespaceURI, localName, raw, type);
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    private final String value;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndCDATA.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndCDATA.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndCDATA.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,24 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndCDATA extends Event {
+    public EndCDATA(Locator location) {
+        super(location);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDTD.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDTD.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDTD.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,24 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndDTD extends Event {
+    public EndDTD(Locator location) {
+        super(location);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDocument.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDocument.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndDocument.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,24 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndDocument extends Event {
+    public EndDocument(Locator location) {
+        super(location);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndElement.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndElement.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndElement.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndElement extends Event {
+    public EndElement(Locator location, StartElement startElement) {
+        super(location);
+        this.startElement = startElement;
+    }
+
+    final StartElement startElement;
+
+    public StartElement getStartElement() {
+        return startElement;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndEntity.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndEntity.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndEntity.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndEntity extends Event {
+    public EndEntity(Locator location, String name) {
+        super(location);
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    private final String name;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndInstruction.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndInstruction.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndInstruction.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,32 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndInstruction extends Event {
+    public EndInstruction(Locator locator, StartInstruction startInstruction) {
+        super(locator);
+        this.startInstruction = startInstruction;
+        startInstruction.setEndInstruction(this);
+    }
+
+    final StartInstruction startInstruction;
+
+    public StartInstruction getStartInstruction() {
+        return startInstruction;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndPrefixMapping.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndPrefixMapping.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/EndPrefixMapping.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class EndPrefixMapping extends Event {
+    public EndPrefixMapping(Locator location, String prefix) {
+        super(location);
+        this.prefix = prefix;
+    }
+
+    final String prefix;
+
+    public String getPrefix() {
+        return prefix;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Event.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Event.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/Event.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,56 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.JXTemplateGenerator;
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.LocatorImpl;
+
+public class Event {
+    protected final Locator location;
+    protected Event next; // in document order
+
+    public Event(Locator locator) {
+        this.location = locator != null ? new LocatorImpl(locator)
+                : JXTemplateGenerator.NULL_LOCATOR;
+    }
+
+    public final Locator getLocation() {
+        return location;
+    }
+
+    public Event getNext() {
+        return next;
+    }
+
+    public void setNext(Event next) {
+        this.next = next;
+    }
+
+    public String locationString() {
+        StringBuffer buf = new StringBuffer();
+        buf.append(location.getSystemId());
+        if (buf.length() > 0) {
+            buf.append(", ");
+        }
+        buf.append("Line " + location.getLineNumber());
+        int col = location.getColumnNumber();
+        if (col > 0) {
+            buf.append("." + col);
+        }
+        return buf.toString();
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/IgnorableWhitespace.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/IgnorableWhitespace.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/IgnorableWhitespace.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,26 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+public class IgnorableWhitespace extends TextEvent {
+    public IgnorableWhitespace(Locator location, char[] chars, int start,
+            int length) throws SAXException {
+        super(location, chars, start, length);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/LoopTagStatus.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/LoopTagStatus.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/LoopTagStatus.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,76 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+
+public class LoopTagStatus {
+    private Object current;
+    private int index;
+    private int count;
+    private boolean first;
+    private boolean last;
+    private int begin;
+    private int end;
+    private int step;
+    public void setBegin(int begin) {
+        this.begin = begin;
+    }
+    public int getBegin() {
+        return begin;
+    }
+    public void setEnd(int end) {
+        this.end = end;
+    }
+    public int getEnd() {
+        return end;
+    }
+    public void setStep(int step) {
+        this.step = step;
+    }
+    public int getStep() {
+        return step;
+    }
+    public void setFirst(boolean first) {
+        this.first = first;
+    }
+    public boolean isFirst() {
+        return first;
+    }
+    public void setIndex(int index) {
+        this.index = index;
+    }
+    public int getIndex() {
+        return index;
+    }
+    public void setCount(int count) {
+        this.count = count;
+    }
+    public int getCount() {
+        return count;
+    }
+    public void setCurrent(Object current) {
+        this.current = current;
+    }
+    public Object getCurrent() {
+        return current;
+    }
+    public void setLast(boolean last) {
+        this.last = last;
+    }
+    public boolean isLast() {
+        return last;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/ProcessingInstruction.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/ProcessingInstruction.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/ProcessingInstruction.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class ProcessingInstruction extends Event {
+    public ProcessingInstruction(Locator location, String target, String data) 
{
+        super(location);
+        this.target = target;
+        this.data = data;
+    }
+
+    public String getData() {
+        return data;
+    }
+
+    public String getTarget() {
+        return target;
+    }
+
+    private final String target;
+    private final String data;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SkippedEntity.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SkippedEntity.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SkippedEntity.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class SkippedEntity extends Event {
+    public SkippedEntity(Locator location, String name) {
+        super(location);
+        this.name = name;
+    }
+
+    final String name;
+
+    public String getName() {
+        return name;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartCDATA.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartCDATA.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartCDATA.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,24 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class StartCDATA extends Event {
+    public StartCDATA(Locator location) {
+        super(location);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartChoose.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartChoose.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartChoose.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class StartChoose extends StartInstruction {
+    public StartChoose(StartElement raw) {
+        super(raw);
+    }
+
+    public void setFirstChoice(StartWhen firstChoice) {
+        this.firstChoice = firstChoice;
+    }
+
+    public StartWhen getFirstChoice() {
+        return firstChoice;
+    }
+
+    public void setOtherwise(StartOtherwise otherwise) {
+        this.otherwise = otherwise;
+    }
+
+    public StartOtherwise getOtherwise() {
+        return otherwise;
+    }
+
+    private StartWhen firstChoice;
+    private StartOtherwise otherwise;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartComment.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartComment.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartComment.java
        Thu Dec  9 04:38:49 2004
@@ -0,0 +1,22 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class StartComment extends StartInstruction {
+    public StartComment(StartElement raw) {
+        super(raw);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDTD.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDTD.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDTD.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class StartDTD extends Event {
+    public StartDTD(Locator location, String name, String publicId,
+            String systemId) {
+        super(location);
+        this.name = name;
+        this.publicId = publicId;
+        this.systemId = systemId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getPublicId() {
+        return publicId;
+    }
+
+    public String getSystemId() {
+        return systemId;
+    }
+
+    private final String name;
+    private final String publicId;
+    private final String systemId;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDefine.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDefine.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDefine.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,100 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class StartDefine extends StartInstruction {
+    public StartDefine(StartElement raw, String namespace, String name) {
+        super(raw);
+        this.namespace = namespace;
+        this.name = name;
+        this.qname = "{" + namespace + "}" + name;
+        this.parameters = new HashMap();
+    }
+
+    final String name;
+    final String namespace;
+    private final String qname;
+    private final Map parameters;
+    private Event body;
+
+    public void finish() throws SAXException {
+        Event e = next;
+        boolean params = true;
+        while (e != this.endInstruction) {
+            if (e instanceof StartParameter) {
+                StartParameter startParam = (StartParameter) e;
+                if (!params) {
+                    throw new SAXParseException(
+                            "<parameter> not allowed here: \""
+                                    + startParam.name + "\"", startParam
+                                    .getLocation(), null);
+                }
+                Object prev = getParameters().put(startParam.name, startParam);
+                if (prev != null) {
+                    throw new SAXParseException("duplicate parameter: \""
+                            + startParam.name + "\"", location, null);
+                }
+                e = startParam.endInstruction;
+            } else if (e instanceof IgnorableWhitespace) {
+                // EMPTY
+            } else if (e instanceof Characters) {
+                // check for whitespace
+                char[] ch = ((TextEvent) e).getRaw();
+                int len = ch.length;
+                for (int i = 0; i < len; i++) {
+                    if (!Character.isWhitespace(ch[i])) {
+                        if (params) {
+                            params = false;
+                            setBody(e);
+                        }
+                        break;
+                    }
+                }
+            } else {
+                if (params) {
+                    params = false;
+                    setBody(e);
+                }
+            }
+            e = e.getNext();
+        }
+        if (this.getBody() == null) {
+            this.setBody(this.endInstruction);
+        }
+    }
+
+    public Map getParameters() {
+        return parameters;
+    }
+
+    void setBody(Event body) {
+        this.body = body;
+    }
+
+    public Event getBody() {
+        return body;
+    }
+
+    public String getQname() {
+        return qname;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDocument.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDocument.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartDocument.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,61 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.excalibur.source.SourceValidity;
+import org.xml.sax.Locator;
+
+public class StartDocument extends Event {
+    public StartDocument(Locator location) {
+        super(location);
+        templateProperties = new HashMap();
+    }
+
+    private SourceValidity compileTime;
+    EndDocument endDocument; // null if document fragment
+    Map templateProperties;
+
+    public EndDocument getEndDocument() {
+        return endDocument;
+    }
+
+    public void setEndDocument(EndDocument endDoc) {
+        this.endDocument = endDoc;
+    }
+
+    public Map getTemplateProperties() {
+        return templateProperties;
+    }
+
+    /**
+     * @param compileTime
+     *            The compileTime to set.
+     */
+    public void setCompileTime(SourceValidity compileTime) {
+        this.compileTime = compileTime;
+    }
+
+    /**
+     * @return Returns the compileTime.
+     */
+    public SourceValidity getCompileTime() {
+        return compileTime;
+    }
+
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartElement.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartElement.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartElement.java
        Thu Dec  9 04:38:49 2004
@@ -0,0 +1,174 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.cocoon.template.jxtg.environment.ErrorHolder;
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.cocoon.template.jxtg.expression.Literal;
+import org.apache.cocoon.template.jxtg.script.Parser;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributesImpl;
+
+public class StartElement extends Event {
+    public StartElement(Locator location, String namespaceURI,
+            String localName, String raw, Attributes attrs) throws 
SAXException {
+        super(location);
+        this.namespaceURI = namespaceURI;
+        this.localName = localName;
+        this.raw = raw;
+        this.qname = "{" + namespaceURI + "}" + localName;
+        StringBuffer buf = new StringBuffer();
+        int len = attrs.getLength();
+        for (int i = 0; i < len; i++) {
+            String uri = attrs.getURI(i);
+            String local = attrs.getLocalName(i);
+            String qname = attrs.getQName(i);
+            String type = attrs.getType(i);
+            String value = attrs.getValue(i);
+            StringReader in = new StringReader(value);
+            int ch;
+            buf.setLength(0);
+            boolean inExpr = false;
+            List substEvents = new LinkedList();
+            boolean xpath = false;
+            try {
+                top: while ((ch = in.read()) != -1) {
+                    char c = (char) ch;
+                    processChar: while (true) {
+                        if (inExpr) {
+                            if (c == '\\') {
+                                ch = in.read();
+                                buf.append(ch == -1 ? '\\' : (char) ch);
+                            } else if (c == '}') {
+                                String str = buf.toString();
+                                JXTExpression compiledExpression;
+                                try {
+                                    compiledExpression = Parser.compile(str,
+                                            xpath);
+                                } catch (Exception exc) {
+                                    throw new SAXParseException(exc
+                                            .getMessage(), location, exc);
+                                } catch (Error err) {
+                                    throw new SAXParseException(err
+                                            .getMessage(), location,
+                                            new ErrorHolder(err));
+                                }
+                                substEvents.add(compiledExpression);
+                                buf.setLength(0);
+                                inExpr = false;
+                            } else {
+                                buf.append(c);
+                            }
+                        } else if (c == '$' || c == '#') {
+                            ch = in.read();
+                            if (ch == '{') {
+                                if (buf.length() > 0) {
+                                    substEvents
+                                            .add(new Literal(buf.toString()));
+                                    buf.setLength(0);
+                                }
+                                inExpr = true;
+                                xpath = c == '#';
+                                continue top;
+                            }
+                            buf.append(c);
+                            if (ch != -1) {
+                                c = (char) ch;
+                                continue processChar;
+                            }
+                        } else {
+                            buf.append(c);
+                        }
+                        break;
+                    }
+                }
+            } catch (IOException ignored) {
+                ignored.printStackTrace();
+            }
+            if (inExpr) {
+                // unclosed #{} or ${}
+                String msg = "Unterminated " + (xpath ? "#" : "$") + "{";
+                throw new SAXParseException(msg, location, null);
+            }
+            if (buf.length() > 0) {
+                if (substEvents.size() == 0) {
+                    getAttributeEvents().add(
+                            new CopyAttribute(uri, local, qname, type, value));
+                } else {
+                    substEvents.add(new Literal(buf.toString()));
+                    getAttributeEvents().add(
+                            new SubstituteAttribute(uri, local, qname, type,
+                                    substEvents));
+                }
+            } else {
+                if (substEvents.size() > 0) {
+                    getAttributeEvents().add(
+                            new SubstituteAttribute(uri, local, qname, type,
+                                    substEvents));
+                } else {
+                    getAttributeEvents().add(
+                            new CopyAttribute(uri, local, qname, type, ""));
+                }
+            }
+        }
+        this.attributes = new AttributesImpl(attrs);
+    }
+
+    final String namespaceURI;
+    final String localName;
+    final String raw;
+    private final String qname;
+    private final List attributeEvents = new LinkedList();
+    final Attributes attributes;
+    EndElement endElement;
+
+    public EndElement getEndElement() {
+        return endElement;
+    }
+
+    public String getLocalName() {
+        return localName;
+    }
+
+    public String getNamespaceURI() {
+        return namespaceURI;
+    }
+
+    public String getRaw() {
+        return raw;
+    }
+
+    public String getQname() {
+        return qname;
+    }
+
+    public List getAttributeEvents() {
+        return attributeEvents;
+    }
+
+    public void setEndElement(EndElement endElement) {
+        this.endElement = endElement;
+
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEntity.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEntity.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEntity.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class StartEntity extends Event {
+    public StartEntity(Locator location, String name) {
+        super(location);
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    private final String name;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEval.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEval.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEval.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartEval extends StartInstruction {
+    public StartEval(StartElement raw, JXTExpression value) {
+        super(raw);
+        this.value = value;
+    }
+
+    public JXTExpression getValue() {
+        return value;
+    }
+
+    private final JXTExpression value;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEvalBody.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEvalBody.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartEvalBody.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,22 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class StartEvalBody extends StartInstruction {
+    public StartEvalBody(StartElement raw) {
+        super(raw);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartForEach.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartForEach.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartForEach.java
        Thu Dec  9 04:38:49 2004
@@ -0,0 +1,69 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartForEach extends StartInstruction {
+    public StartForEach(StartElement raw, JXTExpression items,
+            JXTExpression var, JXTExpression varStatus, JXTExpression begin,
+            JXTExpression end, JXTExpression step, Boolean lenient) {
+        super(raw);
+        this.items = items;
+        this.var = var;
+        this.varStatus = varStatus;
+        this.begin = begin;
+        this.end = end;
+        this.step = step;
+        this.lenient = lenient;
+    }
+
+    final JXTExpression items;
+    final JXTExpression var;
+    final JXTExpression varStatus;
+    final JXTExpression begin;
+    final JXTExpression end;
+    final JXTExpression step;
+    final Boolean lenient;
+
+    public JXTExpression getBegin() {
+        return begin;
+    }
+
+    public JXTExpression getEnd() {
+        return end;
+    }
+
+    public JXTExpression getItems() {
+        return items;
+    }
+
+    public Boolean getLenient() {
+        return lenient;
+    }
+
+    public JXTExpression getStep() {
+        return step;
+    }
+
+    public JXTExpression getVar() {
+        return var;
+    }
+
+    public JXTExpression getVarStatus() {
+        return varStatus;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatDate.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatDate.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatDate.java
     Thu Dec  9 04:38:49 2004
@@ -0,0 +1,164 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.apache.cocoon.template.jxtg.environment.ValueHelper;
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.commons.jexl.JexlContext;
+import org.apache.commons.jxpath.JXPathContext;
+
+public class StartFormatDate extends StartInstruction {
+
+    private static final String DATE = "date";
+    private static final String TIME = "time";
+    private static final String DATETIME = "both";
+
+    JXTExpression var;
+    JXTExpression value;
+    JXTExpression type;
+    JXTExpression pattern;
+    JXTExpression timeZone;
+    JXTExpression dateStyle;
+    JXTExpression timeStyle;
+    JXTExpression locale;
+
+    public StartFormatDate(StartElement raw, JXTExpression var,
+            JXTExpression value, JXTExpression type, JXTExpression pattern,
+            JXTExpression timeZone, JXTExpression dateStyle,
+            JXTExpression timeStyle, JXTExpression locale) {
+        super(raw);
+        this.var = var;
+        this.value = value;
+        this.type = type;
+        this.pattern = pattern;
+        this.timeZone = timeZone;
+        this.dateStyle = dateStyle;
+        this.timeStyle = timeStyle;
+        this.locale = locale;
+    }
+
+    public String format(JexlContext jexl, JXPathContext jxp) throws Exception 
{
+        String var = ValueHelper.getStringValue(this.var, jexl, jxp);
+        Object value = ValueHelper.getValue(this.value, jexl, jxp);
+        Object locVal = ValueHelper.getValue(this.locale, jexl, jxp);
+        String pattern = ValueHelper.getStringValue(this.pattern, jexl,
+                jxp);
+        Object timeZone = ValueHelper
+                .getValue(this.timeZone, jexl, jxp);
+
+        String type = ValueHelper.getStringValue(this.type, jexl, jxp);
+        String timeStyle = ValueHelper.getStringValue(this.timeStyle,
+                jexl, jxp);
+        String dateStyle = ValueHelper.getStringValue(this.dateStyle,
+                jexl, jxp);
+
+        String formatted = null;
+
+        // Create formatter
+        Locale locale;
+        if (locVal != null) {
+            locale = locVal instanceof Locale ? (Locale) locVal
+                    : ValueHelper.parseLocale(locVal.toString(), null);
+        } else {
+            locale = Locale.getDefault();
+        }
+        DateFormat formatter = createFormatter(locale, type, dateStyle,
+                timeStyle);
+        // Apply pattern, if present
+        if (pattern != null) {
+            try {
+                ((SimpleDateFormat) formatter).applyPattern(pattern);
+            } catch (ClassCastException cce) {
+                formatter = new SimpleDateFormat(pattern, locale);
+            }
+        }
+        // Set time zone
+        TimeZone tz = null;
+        if ((timeZone instanceof String) && ((String) timeZone).equals("")) {
+            timeZone = null;
+        }
+        if (timeZone != null) {
+            if (timeZone instanceof String) {
+                tz = TimeZone.getTimeZone((String) timeZone);
+            } else if (timeZone instanceof TimeZone) {
+                tz = (TimeZone) timeZone;
+            } else {
+                throw new IllegalArgumentException("Illegal timeZone value: \""
+                        + timeZone + "\"");
+            }
+        }
+        if (tz != null) {
+            formatter.setTimeZone(tz);
+        }
+        formatted = formatter.format(value);
+        if (var != null) {
+            jexl.getVars().put(var, formatted);
+            jxp.getVariables().declareVariable(var, formatted);
+            return null;
+        }
+        return formatted;
+    }
+
+    private DateFormat createFormatter(Locale loc, String type,
+            String dateStyle, String timeStyle) throws Exception {
+        DateFormat formatter = null;
+        if ((type == null) || DATE.equalsIgnoreCase(type)) {
+            formatter = DateFormat.getDateInstance(getStyle(dateStyle), loc);
+        } else if (TIME.equalsIgnoreCase(type)) {
+            formatter = DateFormat.getTimeInstance(getStyle(timeStyle), loc);
+        } else if (DATETIME.equalsIgnoreCase(type)) {
+            formatter = DateFormat.getDateTimeInstance(getStyle(dateStyle),
+                    getStyle(timeStyle), loc);
+        } else {
+            throw new IllegalArgumentException("Invalid type: \"" + type + 
"\"");
+        }
+        return formatter;
+    }
+
+    private static final String DEFAULT = "default";
+    private static final String SHORT = "short";
+    private static final String MEDIUM = "medium";
+    private static final String LONG = "long";
+    private static final String FULL = "full";
+
+    private int getStyle(String style) {
+        int ret = DateFormat.DEFAULT;
+        if (style != null) {
+            if (DEFAULT.equalsIgnoreCase(style)) {
+                ret = DateFormat.DEFAULT;
+            } else if (SHORT.equalsIgnoreCase(style)) {
+                ret = DateFormat.SHORT;
+            } else if (MEDIUM.equalsIgnoreCase(style)) {
+                ret = DateFormat.MEDIUM;
+            } else if (LONG.equalsIgnoreCase(style)) {
+                ret = DateFormat.LONG;
+            } else if (FULL.equalsIgnoreCase(style)) {
+                ret = DateFormat.FULL;
+            } else {
+                throw new IllegalArgumentException(
+                        "Invalid style: \""
+                                + style
+                                + "\": should be \"default\" or \"short\" or 
\"medium\" or \"long\" or \"full\"");
+            }
+        }
+        return ret;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatNumber.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatNumber.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartFormatNumber.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,253 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.lang.reflect.Method;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import org.apache.cocoon.template.jxtg.environment.ValueHelper;
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.commons.jexl.JexlContext;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.lang.StringUtils;
+
+public class StartFormatNumber extends StartInstruction {
+
+    JXTExpression value;
+    JXTExpression type;
+    JXTExpression pattern;
+    JXTExpression currencyCode;
+    JXTExpression currencySymbol;
+    JXTExpression isGroupingUsed;
+    JXTExpression maxIntegerDigits;
+    JXTExpression minIntegerDigits;
+    JXTExpression maxFractionDigits;
+    JXTExpression minFractionDigits;
+    JXTExpression locale;
+
+    JXTExpression var;
+
+    private static Class currencyClass;
+    private static final String NUMBER = "number";
+    private static final String CURRENCY = "currency";
+    private static final String PERCENT = "percent";
+
+    static {
+        try {
+            currencyClass = Class.forName("java.util.Currency");
+            // container's runtime is J2SE 1.4 or greater
+        } catch (Exception cnfe) {
+            // EMPTY
+        }
+    }
+
+    public StartFormatNumber(StartElement raw, JXTExpression var,
+            JXTExpression value, JXTExpression type, JXTExpression pattern,
+            JXTExpression currencyCode, JXTExpression currencySymbol,
+            JXTExpression isGroupingUsed, JXTExpression maxIntegerDigits,
+            JXTExpression minIntegerDigits, JXTExpression maxFractionDigits,
+            JXTExpression minFractionDigits, JXTExpression locale) {
+        super(raw);
+        this.var = var;
+        this.value = value;
+        this.type = type;
+        this.pattern = pattern;
+        this.currencyCode = currencyCode;
+        this.currencySymbol = currencySymbol;
+        this.isGroupingUsed = isGroupingUsed;
+        this.maxIntegerDigits = maxIntegerDigits;
+        this.minIntegerDigits = minIntegerDigits;
+        this.maxFractionDigits = maxFractionDigits;
+        this.minFractionDigits = minFractionDigits;
+        this.locale = locale;
+    }
+
+    public String format(JexlContext jexl, JXPathContext jxp) throws Exception 
{
+        // Determine formatting locale
+        String var = ValueHelper.getStringValue(this.var, jexl, jxp);
+        Number input = ValueHelper
+                .getNumberValue(this.value, jexl, jxp);
+        String type = ValueHelper.getStringValue(this.type, jexl, jxp);
+        String pattern = ValueHelper.getStringValue(this.pattern, jexl,
+                jxp);
+        String currencyCode = ValueHelper.getStringValue(
+                this.currencyCode, jexl, jxp);
+        String currencySymbol = ValueHelper.getStringValue(
+                this.currencySymbol, jexl, jxp);
+        Boolean isGroupingUsed = ValueHelper.getBooleanValue(
+                this.isGroupingUsed, jexl, jxp);
+        Number maxIntegerDigits = ValueHelper.getNumberValue(
+                this.maxIntegerDigits, jexl, jxp);
+        Number minIntegerDigits = ValueHelper.getNumberValue(
+                this.minIntegerDigits, jexl, jxp);
+        Number maxFractionDigits = ValueHelper.getNumberValue(
+                this.maxFractionDigits, jexl, jxp);
+        Number minFractionDigits = ValueHelper.getNumberValue(
+                this.minFractionDigits, jexl, jxp);
+        String localeStr = ValueHelper.getStringValue(this.locale,
+                jexl, jxp);
+        Locale loc = localeStr != null ? ValueHelper.parseLocale(
+                localeStr, null) : Locale.getDefault();
+        String formatted;
+        if (loc != null) {
+            // Create formatter
+            NumberFormat formatter = null;
+            if (StringUtils.isNotEmpty(pattern)) {
+                // if 'pattern' is specified, 'type' is ignored
+                DecimalFormatSymbols symbols = new DecimalFormatSymbols(loc);
+                formatter = new DecimalFormat(pattern, symbols);
+            } else {
+                formatter = createFormatter(loc, type);
+            }
+            if (StringUtils.isNotEmpty(pattern)
+                    || CURRENCY.equalsIgnoreCase(type)) {
+                setCurrency(formatter, currencyCode, currencySymbol);
+            }
+            configureFormatter(formatter, isGroupingUsed, maxIntegerDigits,
+                    minIntegerDigits, maxFractionDigits, minFractionDigits);
+            formatted = formatter.format(input);
+        } else {
+            // no formatting locale available, use toString()
+            formatted = input.toString();
+        }
+        if (var != null) {
+            jexl.getVars().put(var, formatted);
+            jxp.getVariables().declareVariable(var, formatted);
+            return null;
+        }
+        return formatted;
+    }
+
+    private NumberFormat createFormatter(Locale loc, String type)
+            throws Exception {
+        NumberFormat formatter = null;
+        if ((type == null) || NUMBER.equalsIgnoreCase(type)) {
+            formatter = NumberFormat.getNumberInstance(loc);
+        } else if (CURRENCY.equalsIgnoreCase(type)) {
+            formatter = NumberFormat.getCurrencyInstance(loc);
+        } else if (PERCENT.equalsIgnoreCase(type)) {
+            formatter = NumberFormat.getPercentInstance(loc);
+        } else {
+            throw new IllegalArgumentException("Invalid type: \"" + type
+                    + "\": should be \"number\" or \"currency\" or 
\"percent\"");
+        }
+        return formatter;
+    }
+
+    /*
+     * Applies the 'groupingUsed', 'maxIntegerDigits', 'minIntegerDigits',
+     * 'maxFractionDigits', and 'minFractionDigits' attributes to the given
+     * formatter.
+     */
+    private void configureFormatter(NumberFormat formatter,
+            Boolean isGroupingUsed, Number maxIntegerDigits,
+            Number minIntegerDigits, Number maxFractionDigits,
+            Number minFractionDigits) {
+        if (isGroupingUsed != null)
+            formatter.setGroupingUsed(isGroupingUsed.booleanValue());
+        if (maxIntegerDigits != null)
+            formatter.setMaximumIntegerDigits(maxIntegerDigits.intValue());
+        if (minIntegerDigits != null)
+            formatter.setMinimumIntegerDigits(minIntegerDigits.intValue());
+        if (maxFractionDigits != null)
+            formatter.setMaximumFractionDigits(maxFractionDigits.intValue());
+        if (minFractionDigits != null)
+            formatter.setMinimumFractionDigits(minFractionDigits.intValue());
+    }
+
+    /*
+     * Override the formatting locale's default currency symbol with the
+     * specified currency code (specified via the "currencyCode" attribute) or
+     * currency symbol (specified via the "currencySymbol" attribute).
+     * 
+     * If both "currencyCode" and "currencySymbol" are present, "currencyCode"
+     * takes precedence over "currencySymbol" if the java.util.Currency class 
is
+     * defined in the container's runtime (that is, if the container's runtime
+     * is J2SE 1.4 or greater), and "currencySymbol" takes precendence over
+     * "currencyCode" otherwise.
+     * 
+     * If only "currencyCode" is given, it is used as a currency symbol if
+     * java.util.Currency is not defined.
+     * 
+     * Example:
+     * 
+     * JDK "currencyCode" "currencySymbol" Currency symbol being displayed
+     * -----------------------------------------------------------------------
+     * all --- --- Locale's default currency symbol
+     * 
+     * <1.4 EUR --- EUR >=1.4 EUR --- Locale's currency symbol for Euro
+     * 
+     * all --- \u20AC \u20AC
+     * 
+     * <1.4 EUR \u20AC \u20AC >=1.4 EUR \u20AC Locale's currency symbol for 
Euro
+     */
+    private void setCurrency(NumberFormat formatter, String currencyCode,
+            String currencySymbol) throws Exception {
+        String code = null;
+        String symbol = null;
+
+        if (currencyCode == null) {
+            if (currencySymbol == null) {
+                return;
+            }
+            symbol = currencySymbol;
+        } else if (currencySymbol != null) {
+            if (currencyClass != null) {
+                code = currencyCode;
+            } else {
+                symbol = currencySymbol;
+            }
+        } else if (currencyClass != null) {
+            code = currencyCode;
+        } else {
+            symbol = currencyCode;
+        }
+        if (code != null) {
+            Object[] methodArgs = new Object[1];
+
+            /*
+             * java.util.Currency.getInstance()
+             */
+            Method m = currencyClass.getMethod("getInstance",
+                    new Class[] { String.class });
+
+            methodArgs[0] = code;
+            Object currency = m.invoke(null, methodArgs);
+
+            /*
+             * java.text.NumberFormat.setCurrency()
+             */
+            Class[] paramTypes = new Class[1];
+            paramTypes[0] = currencyClass;
+            Class numberFormatClass = Class.forName("java.text.NumberFormat");
+            m = numberFormatClass.getMethod("setCurrency", paramTypes);
+            methodArgs[0] = currency;
+            m.invoke(formatter, methodArgs);
+        } else {
+            /*
+             * Let potential ClassCastException propagate up (will almost never
+             * happen)
+             */
+            DecimalFormat df = (DecimalFormat) formatter;
+            DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
+            dfs.setCurrencySymbol(symbol);
+            df.setDecimalFormatSymbols(dfs);
+        }
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartIf.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartIf.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartIf.java
     Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartIf extends StartInstruction {
+    public StartIf(StartElement raw, JXTExpression test) {
+        super(raw);
+        this.test = test;
+    }
+
+    final JXTExpression test;
+
+    public JXTExpression getTest() {
+        return test;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartImport.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartImport.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartImport.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartImport extends StartInstruction {
+    public StartImport(StartElement raw, AttributeEvent uri,
+            JXTExpression select) {
+        super(raw);
+        this.uri = uri;
+        this.select = select;
+    }
+
+    public AttributeEvent getUri() {
+        return uri;
+    }
+
+    public JXTExpression getSelect() {
+        return select;
+    }
+
+    private final AttributeEvent uri;
+    private final JXTExpression select;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartInstruction.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartInstruction.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartInstruction.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,35 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+
+public class StartInstruction extends Event {
+    StartInstruction(StartElement startElement) {
+        super(startElement.getLocation());
+        this.startElement = startElement;
+    }
+
+    final StartElement startElement;
+    EndInstruction endInstruction;
+
+    public EndInstruction getEndInstruction() {
+        return endInstruction;
+    }
+
+    public void setEndInstruction(EndInstruction endInstruction) {
+        this.endInstruction = endInstruction;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOtherwise.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOtherwise.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOtherwise.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,22 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class StartOtherwise extends StartInstruction {
+    public StartOtherwise(StartElement raw) {
+        super(raw);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOut.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOut.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartOut.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartOut extends StartInstruction {
+    public StartOut(StartElement raw, JXTExpression expr, Boolean lenient) {
+        super(raw);
+        this.compiledExpression = expr;
+        this.lenient = lenient;
+    }
+
+    public JXTExpression getCompiledExpression() {
+        return compiledExpression;
+    }
+
+    public Boolean getLenient() {
+        return lenient;
+    }
+
+    private final JXTExpression compiledExpression;
+    private final Boolean lenient;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartParameter.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartParameter.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartParameter.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,34 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class StartParameter extends StartInstruction {
+    public StartParameter(StartElement raw, String name, String optional,
+            String defaultValue) {
+        super(raw);
+        this.name = name;
+        this.optional = optional;
+        this.defaultValue = defaultValue;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+
+    final String name;
+    final String optional;
+    private final String defaultValue;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartPrefixMapping.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartPrefixMapping.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartPrefixMapping.java
  Thu Dec  9 04:38:49 2004
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.xml.sax.Locator;
+
+public class StartPrefixMapping extends Event {
+    public StartPrefixMapping(Locator location, String prefix, String uri) {
+        super(location);
+        this.prefix = prefix;
+        this.uri = uri;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    private final String prefix;
+    private final String uri;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartSet.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartSet.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartSet.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartSet extends StartInstruction {
+    public StartSet(StartElement raw, JXTExpression var, JXTExpression value) {
+        super(raw);
+        this.var = var;
+        this.value = value;
+    }
+
+    public JXTExpression getVar() {
+        return var;
+    }
+
+    public JXTExpression getValue() {
+        return value;
+    }
+
+    private final JXTExpression var;
+    private final JXTExpression value;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartTemplate.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartTemplate.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartTemplate.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,22 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+public class StartTemplate extends StartInstruction {
+    public StartTemplate(StartElement raw) {
+        super(raw);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartWhen.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartWhen.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/StartWhen.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+
+public class StartWhen extends StartInstruction {
+    public StartWhen(StartElement raw, JXTExpression test) {
+        super(raw);
+        this.test = test;
+    }
+
+    public JXTExpression getTest() {
+        return test;
+    }
+
+    public void setNextChoice(StartWhen nextChoice) {
+        this.nextChoice = nextChoice;
+    }
+
+    public StartWhen getNextChoice() {
+        return nextChoice;
+    }
+
+    private final JXTExpression test;
+    private StartWhen nextChoice;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SubstituteAttribute.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SubstituteAttribute.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/SubstituteAttribute.java
 Thu Dec  9 04:38:49 2004
@@ -0,0 +1,33 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.util.List;
+
+
+public class SubstituteAttribute extends AttributeEvent {
+    public SubstituteAttribute(String namespaceURI, String localName,
+            String raw, String type, List substs) {
+        super(namespaceURI, localName, raw, type);
+        this.substitutions = substs;
+    }
+
+    public List getSubstitutions() {
+        return substitutions;
+    }
+
+    private final List substitutions;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/TextEvent.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/TextEvent.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/jxtg/script/event/TextEvent.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,132 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.jxtg.script.event;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.cocoon.template.jxtg.environment.ErrorHolder;
+import org.apache.cocoon.template.jxtg.expression.JXTExpression;
+import org.apache.commons.jexl.ExpressionFactory;
+import org.apache.commons.jxpath.JXPathContext;
+import org.apache.commons.lang.ArrayUtils;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class TextEvent extends Event {
+    public TextEvent(Locator location, char[] chars, int start, int length)
+            throws SAXException {
+        super(location);
+        StringBuffer buf = new StringBuffer();
+        this.raw = new char[length];
+        System.arraycopy(chars, start, this.raw, 0, length);
+        CharArrayReader in = new CharArrayReader(chars, start, length);
+        int ch;
+        boolean inExpr = false;
+        boolean xpath = false;
+        try {
+            top: while ((ch = in.read()) != -1) {
+                // column++;
+                char c = (char) ch;
+                processChar: while (true) {
+                    if (inExpr) {
+                        if (c == '\\') {
+                            ch = in.read();
+                            buf.append(ch == -1 ? '\\' : (char) ch);
+                        } else if (c == '}') {
+                            String str = buf.toString();
+                            Object compiledExpression;
+                            try {
+                                if (xpath) {
+                                    compiledExpression = JXPathContext
+                                            .compile(str);
+                                } else {
+                                    compiledExpression = ExpressionFactory
+                                            .createExpression(str);
+                                }
+                            } catch (Exception exc) {
+                                throw new SAXParseException(exc.getMessage(),
+                                        this.getLocation(), exc);
+                            } catch (Error err) {
+                                throw new SAXParseException(err.getMessage(),
+                                        this.getLocation(),
+                                        new ErrorHolder(err));
+
+                            }
+                            substitutions.add(new JXTExpression(str,
+                                    compiledExpression));
+                            buf.setLength(0);
+                            inExpr = false;
+                        } else {
+                            buf.append(c);
+                        }
+                    } else if (c == '$' || c == '#') {
+                        ch = in.read();
+                        if (ch == '{') {
+                            xpath = c == '#';
+                            inExpr = true;
+                            if (buf.length() > 0) {
+                                char[] charArray = new char[buf.length()];
+
+                                buf.getChars(0, buf.length(), charArray, 0);
+                                substitutions.add(charArray);
+                                buf.setLength(0);
+                            }
+                            continue top;
+                        }
+                        buf.append(c);
+                        if (ch != -1) {
+                            c = (char) ch;
+                            continue processChar;
+                        }
+                    } else {
+                        buf.append(c);
+                    }
+                    break;
+                }
+            }
+        } catch (IOException ignored) {
+            // won't happen
+            ignored.printStackTrace();
+        }
+        if (inExpr) {
+            // unclosed #{} or ${}
+            buf.insert(0, (xpath ? "#" : "$") + "{");
+        }
+        if (buf.length() > 0) {
+            char[] charArray = new char[buf.length()];
+
+            buf.getChars(0, buf.length(), charArray, 0);
+            substitutions.add(charArray);
+        } else if (substitutions.isEmpty()) {
+            substitutions.add(ArrayUtils.EMPTY_CHAR_ARRAY);
+        }
+    }
+
+    final List substitutions = new LinkedList();
+    final char[] raw;
+
+    public char[] getRaw() {
+        return raw;
+    }
+
+    public List getSubstitutions() {
+        return substitutions;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/generation/TemplateGenerator.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/generation/TemplateGenerator.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/generation/TemplateGenerator.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,95 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.generation;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.el.ExpressionCompiler;
+import org.apache.cocoon.el.GenericExpressionCompiler;
+import org.apache.cocoon.generation.ServiceableGenerator;
+import org.apache.cocoon.template.v2.script.Script;
+import org.apache.cocoon.template.v2.script.ScriptCompiler;
+import org.apache.cocoon.template.v2.script.ScriptContext;
+import org.apache.cocoon.template.v2.script.ScriptInvoker;
+import org.apache.cocoon.template.v2.script.TagRepository;
+import org.apache.cocoon.util.IncludingConfiguration;
+import org.apache.excalibur.source.Source;
+import org.xml.sax.SAXException;
+
+public class TemplateGenerator extends ServiceableGenerator implements
+        Configurable {
+    static HashMap cache = new HashMap();
+
+    TagRepository tagRepository = new TagRepository();
+
+    ExpressionCompiler expressionCompiler = GenericExpressionCompiler
+            .getInstance();
+
+    public void enableLogging(Logger logger) {
+        super.enableLogging(logger);
+        tagRepository.enableLogging(logger);
+    }
+
+    public void configure(Configuration conf) throws ConfigurationException {
+        IncludingConfiguration newConf = new IncludingConfiguration(conf,
+                manager);
+        tagRepository.configure(newConf);
+    }
+
+    public TagRepository getTagRepository() {
+        return tagRepository;
+    }
+
+    public void generate() throws IOException, SAXException,
+            ProcessingException {
+        try {
+            Source inputSource = resolver.resolveURI(source);
+
+            Script script = null;
+            synchronized (cache) {
+                script = (Script) cache.get(inputSource.getURI());
+                if (script == null) {
+                    script = compileScript(inputSource);
+                    cache.put(inputSource.getURI(), script);
+                }
+            }
+
+            ScriptContext context = new ScriptContext();
+            context.setConsumer(xmlConsumer);
+
+            // TODO: populate context
+
+            ScriptInvoker scriptInvoker = new ScriptInvoker(script, context);
+            scriptInvoker.invoke();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected Script compileScript(Source inputSource) throws Exception {
+        ScriptCompiler compiler = new ScriptCompiler(tagRepository,
+                expressionCompiler);
+        SourceUtil.parse(manager, inputSource, compiler);
+        return compiler.getScript();
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AbstractToken.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AbstractToken.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AbstractToken.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,38 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+public abstract class AbstractToken implements Token {
+    protected int start;
+    protected int end;
+
+    public int getStart() {
+        return start;
+    }
+
+    public void setStart(int start) {
+        this.start = start;
+    }
+
+    public int getEnd() {
+        return end;
+    }
+
+    public void setEnd(int end) {
+        this.end = end;
+    }
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AttributeToken.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AttributeToken.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/AttributeToken.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,41 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+public class AttributeToken extends AbstractToken {
+    String namespace;
+    String lname;
+    String qname;
+
+    public void setup(String namespace, String lname, String qname) {
+        this.namespace = namespace;
+        this.lname = lname;
+        this.qname = qname;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public String getLName() {
+        return lname;
+    }
+
+    public String getQName() {
+        return qname;
+    }
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/CharactersToken.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/CharactersToken.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/CharactersToken.java
     Thu Dec  9 04:38:49 2004
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+public class CharactersToken extends AbstractToken {
+    char[] characters;
+
+    public void setup(CharSequence characters) {
+        // TODO: this should be done better
+        this.characters = characters.toString().toCharArray();
+    }
+
+    public char[] getCharacters() {
+        return characters;
+    }
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ElementToken.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ElementToken.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ElementToken.java
        Thu Dec  9 04:38:49 2004
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+public interface ElementToken extends Token {
+    public int getBodyStart();
+
+    public void setBodyStart(int bodyStart);
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ExpressionToken.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ExpressionToken.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ExpressionToken.java
     Thu Dec  9 04:38:49 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+import org.apache.cocoon.el.Expression;
+
+public class ExpressionToken extends AbstractToken {
+    Expression expression;
+
+    public void setup(Expression expression) {
+        this.expression = expression;
+    }
+
+    public Expression getExpression() {
+        return expression;
+    }
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/PlainElementToken.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/PlainElementToken.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/PlainElementToken.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,50 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+public class PlainElementToken extends AbstractToken implements ElementToken {
+    protected String namespace;
+    protected String lname;
+    protected String qname;
+    protected int bodyStart;
+
+    public void setup(String namespace, String lname, String qname) {
+        this.namespace = namespace;
+        this.lname = lname;
+        this.qname = qname;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public String getLName() {
+        return lname;
+    }
+
+    public String getQName() {
+        return qname;
+    }
+
+    public int getBodyStart() {
+        return bodyStart;
+    }
+
+    public void setBodyStart(int bodyStart) {
+        this.bodyStart = bodyStart;
+    }
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Script.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Script.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Script.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,45 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Script {
+    ArrayList tokens = new ArrayList();
+
+    public void add(Token token) {
+        token.setStart(size());
+        tokens.add(token);
+    }
+
+    public void addAtom(Token token) {
+        add(token);
+        token.setEnd(size());
+    }
+
+    public Token get(int i) {
+        return (Token) tokens.get(i);
+    }
+
+    public int size() {
+        return tokens.size();
+    }
+
+    public List getTokens() {
+        return tokens;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptCompiler.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptCompiler.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptCompiler.java
      Thu Dec  9 04:38:49 2004
@@ -0,0 +1,97 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+import java.nio.CharBuffer;
+import java.util.Stack;
+
+import org.apache.cocoon.el.ExpressionCompiler;
+import org.apache.cocoon.el.util.ELUtils;
+import org.apache.cocoon.el.util.ParseHandler;
+import org.apache.cocoon.xml.AbstractXMLConsumer;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+public class ScriptCompiler extends AbstractXMLConsumer {
+    static final int TEXT = 1;
+    static final int EXPRESSION = 2;
+    Script script = new Script();
+    TextParseHandler parseHandler = new TextParseHandler();
+    Stack openedTokens = new Stack();
+    TagRepository tagRepository;
+    ExpressionCompiler expressionCompiler;
+
+    public ScriptCompiler(TagRepository tagRepository,
+            ExpressionCompiler expressionCompiler) {
+        this.tagRepository = tagRepository;
+        this.expressionCompiler = expressionCompiler;
+    }
+
+    public Script getScript() {
+        return script;
+    }
+
+    public void startElement(String namespace, String lname, String qname,
+            Attributes atts) throws SAXException {
+        ElementToken token;
+
+        if (tagRepository.contains(namespace, lname)) {
+            token = tagRepository.getTag(namespace, lname);
+        } else {
+            token = new PlainElementToken();
+            ((PlainElementToken) token).setup(namespace, lname, qname);
+        }
+
+        script.add(token);
+        openedTokens.push(token);
+
+        for (int i = 0; i < atts.getLength(); i++) {
+            AttributeToken attrToken = new AttributeToken();
+            attrToken.setup(atts.getURI(i), atts.getLocalName(i), atts
+                    .getQName(i));
+            script.add(attrToken);
+            ELUtils.parse(CharBuffer.wrap(atts.getValue(i)), parseHandler);
+            attrToken.setEnd(script.size());
+        }
+
+        token.setBodyStart(script.size());
+    }
+
+    public void endElement(String namespace, String lname, String qname)
+            throws SAXException {
+        Token token = (Token) openedTokens.pop();
+        token.setEnd(script.size());
+    }
+
+    public void characters(char ch[], int start, int length)
+            throws SAXException {
+        ELUtils.parse(CharBuffer.wrap(ch, start, length), parseHandler);
+    }
+
+    public class TextParseHandler implements ParseHandler {
+        public void handleExpression(CharSequence characters) {
+            ExpressionToken token = new ExpressionToken();
+            token.setup(expressionCompiler.compile(characters.toString()));
+            script.addAtom(token);
+        }
+
+        public void handleText(CharSequence characters) {
+            CharactersToken token = new CharactersToken();
+            token.setup(characters);
+            script.addAtom(token);
+        }
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptContext.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptContext.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptContext.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,40 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+import org.apache.cocoon.el.DefaultContext;
+import org.apache.cocoon.xml.XMLConsumer;
+
+public class ScriptContext extends DefaultContext {
+    XMLConsumer consumer;
+    ScriptInvoker scriptInvoker;
+
+    public XMLConsumer getConsumer() {
+        return consumer;
+    }
+
+    public void setConsumer(XMLConsumer consumer) {
+        this.consumer = consumer;
+    }
+
+    public ScriptInvoker getScriptInvoker() {
+        return scriptInvoker;
+    }
+
+    public void setScriptInvoker(ScriptInvoker scriptInvoker) {
+        this.scriptInvoker = scriptInvoker;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptInvoker.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptInvoker.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/ScriptInvoker.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,117 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+import org.apache.cocoon.template.v2.tag.Tag;
+import org.apache.cocoon.xml.XMLConsumer;
+import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+
+public class ScriptInvoker {
+
+    public static final String CDATA = "CDATA";
+
+    Script script;
+
+    ScriptContext context;
+
+    XMLConsumer consumer;
+
+    public ScriptInvoker(Script script, ScriptContext context) {
+        this.script = script;
+        this.context = context;
+        this.consumer = context.getConsumer();
+        context.setScriptInvoker(this);
+    }
+
+    public void invoke() throws Exception {
+        consumer.startDocument();
+        invoke(0, script.size());
+        consumer.endDocument();
+    }
+
+    public void invoke(int start, int end) throws Exception {
+
+        for (int i = start; i < end;) {
+            Token tok = script.get(i);
+
+            if (tok instanceof PlainElementToken) {
+                PlainElementToken token = (PlainElementToken) tok;
+                Attributes attributes = getElementAttributes(
+                        token.getStart() + 1, token.getBodyStart());
+                consumer.startElement(token.getNamespace(), token.getLName(),
+                        token.getQName(), attributes);
+                invoke(token.getBodyStart(), token.getEnd());
+                consumer.endElement(token.getNamespace(), token.getLName(),
+                        token.getQName());
+
+            } else if (tok instanceof Tag) {
+                ((Tag) tok).invoke(context);
+
+            } else if (tok instanceof CharactersToken) {
+                char[] characters = ((CharactersToken) tok).getCharacters();
+                consumer.characters(characters, 0, characters.length);
+
+            } else if (tok instanceof ExpressionToken) {
+                char[] value = ((ExpressionToken) tok).getExpression()
+                        .toCharArray(context);
+                consumer.characters(value, 0, value.length);
+
+            } else {
+                throw new RuntimeException("Illegal token");
+            }
+
+            i = tok.getEnd();
+        }
+    }
+
+    public Attributes getElementAttributes(int start, int end) throws 
Exception {
+        AttributesImpl attributes = new AttributesImpl();
+
+        for (int i = start; i < end;) {
+            Token tok = script.get(i);
+
+            if (tok instanceof AttributeToken) {
+                AttributeToken token = (AttributeToken) tok;
+                String value = getText(token.getStart() + 1, token.getEnd());
+                attributes.addAttribute(token.getNamespace(), token.getLName(),
+                        token.getQName(), CDATA, value);
+                i = token.getEnd();
+            } else {
+                throw new RuntimeException("Illegal token");
+            }
+        }
+
+        return attributes;
+    }
+
+    public String getText(int start, int end) throws Exception {
+        StringBuffer text = new StringBuffer();
+
+        for (int i = start; i < end; i++) {
+            Token token = script.get(i);
+
+            if (token instanceof CharactersToken)
+                text.append(((CharactersToken) token).getCharacters());
+            else if (token instanceof ExpressionToken)
+                text.append(((ExpressionToken) token).getExpression().toString(
+                        context));
+            else
+                throw new RuntimeException("Illegal token");
+        }
+        return text.toString();
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/TagRepository.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/TagRepository.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/TagRepository.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,73 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+import java.util.HashMap;
+
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.cocoon.template.v2.tag.Tag;
+
+public class TagRepository extends AbstractLogEnabled implements Configurable {
+    HashMap tagMap = new HashMap();
+
+    public void configure(Configuration conf) throws ConfigurationException {
+        configureTags(conf.getChildren("tag"));
+    }
+
+    public void configureTags(Configuration[] confs)
+            throws ConfigurationException {
+        for (int i = 0; i < confs.length; i++) {
+            registerTag(confs[i].getAttribute("namespace"), confs[i]
+                    .getAttribute("name"), confs[i].getAttribute("src"));
+        }
+    }
+
+    public void registerTag(String namespace, String name, String src) {
+        try {
+            registerTag(namespace, name, Class.forName(src));
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException("Class not found", e);
+        }
+
+    }
+
+    public void registerTag(String namespace, String name, Class clazz) {
+        tagMap.put(createKey(namespace, name), clazz);
+        if (getLogger().isInfoEnabled())
+            getLogger().info("Registered tag: namespace=" + namespace + ", 
name="
+                    + name + ", src=" + clazz.getName());
+    }
+
+    public Tag getTag(String namespace, String name) {
+        try {
+            Class type = (Class) tagMap.get(createKey(namespace, name));
+            return (Tag) type.newInstance();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public boolean contains(String namespace, String name) {
+        return tagMap.containsKey(createKey(namespace, name));
+    }
+
+    protected String createKey(String namespace, String name) {
+        return namespace + " " + name;
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Token.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Token.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/script/Token.java
       Thu Dec  9 04:38:49 2004
@@ -0,0 +1,27 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.script;
+
+public interface Token {
+    public int getStart();
+
+    public void setStart(int start);
+
+    public int getEnd();
+
+    public void setEnd(int end);
+}
+

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/AbstractTag.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/AbstractTag.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/AbstractTag.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,39 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.tag;
+
+import org.apache.cocoon.template.v2.script.AbstractToken;
+import org.apache.cocoon.template.v2.script.ElementToken;
+import org.apache.cocoon.template.v2.script.ScriptContext;
+
+public abstract class AbstractTag extends AbstractToken implements
+        ElementToken, Tag {
+    protected int bodyStart;
+
+    public int getBodyStart() {
+        return bodyStart;
+    }
+
+    public void setBodyStart(int bodyStart) {
+        this.bodyStart = bodyStart;
+    }
+
+    public abstract void invoke(ScriptContext context) throws Exception;
+
+    public void invokeBody(ScriptContext context) throws Exception {
+        context.getScriptInvoker().invoke(bodyStart, end);
+    }
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/Tag.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/Tag.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/Tag.java
    Thu Dec  9 04:38:49 2004
@@ -0,0 +1,23 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.tag;
+
+import org.apache.cocoon.template.v2.script.ElementToken;
+import org.apache.cocoon.template.v2.script.ScriptContext;
+
+public interface Tag extends ElementToken {
+    public void invoke(ScriptContext context) throws Exception;
+}
\ No newline at end of file

Added: 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/samples/DuplicateTag.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/samples/DuplicateTag.java?view=auto&rev=111375
==============================================================================
--- (empty file)
+++ 
cocoon/trunk/src/blocks/template/java/org/apache/cocoon/template/v2/tag/samples/DuplicateTag.java
   Thu Dec  9 04:38:49 2004
@@ -0,0 +1,26 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.template.v2.tag.samples;
+
+import org.apache.cocoon.template.v2.script.ScriptContext;
+import org.apache.cocoon.template.v2.tag.AbstractTag;
+
+public class DuplicateTag extends AbstractTag {
+    public void invoke(ScriptContext context) throws Exception {
+        invokeBody(context);
+        invokeBody(context);
+    }
+}
\ No newline at end of file

Modified: 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java?view=diff&rev=111375&p1=cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java&r1=111374&p2=cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java&r2=111375
==============================================================================
--- 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java
  (original)
+++ 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/generation/TemplateGeneratorTestCase.java
  Thu Dec  9 04:38:49 2004
@@ -18,7 +18,8 @@
 import org.apache.avalon.framework.logger.ConsoleLogger;
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.cocoon.ExtendedSitemapComponentTestCase;
-import org.apache.cocoon.template.tag.samples.DuplicateTag;
+import org.apache.cocoon.template.v2.generation.TemplateGenerator;
+import org.apache.cocoon.template.v2.tag.samples.DuplicateTag;
 import org.apache.cocoon.xml.dom.DOMBuilder;
 
 public class TemplateGeneratorTestCase extends 
ExtendedSitemapComponentTestCase {

Modified: 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java?view=diff&rev=111375&p1=cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java&r1=111374&p2=cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java&r2=111375
==============================================================================
--- 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java
 (original)
+++ 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptCompilerTestCase.java
 Thu Dec  9 04:38:49 2004
@@ -19,7 +19,15 @@
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.cocoon.ExtendedSitemapComponentTestCase;
 import org.apache.cocoon.el.GenericExpressionCompiler;
-import org.apache.cocoon.template.tag.AbstractTag;
+import org.apache.cocoon.template.v2.script.AttributeToken;
+import org.apache.cocoon.template.v2.script.CharactersToken;
+import org.apache.cocoon.template.v2.script.ExpressionToken;
+import org.apache.cocoon.template.v2.script.PlainElementToken;
+import org.apache.cocoon.template.v2.script.Script;
+import org.apache.cocoon.template.v2.script.ScriptCompiler;
+import org.apache.cocoon.template.v2.script.ScriptContext;
+import org.apache.cocoon.template.v2.script.TagRepository;
+import org.apache.cocoon.template.v2.tag.AbstractTag;
 import org.xml.sax.helpers.AttributesImpl;
 
 public class ScriptCompilerTestCase extends ExtendedSitemapComponentTestCase {

Modified: 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java
Url: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java?view=diff&rev=111375&p1=cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java&r1=111374&p2=cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java&r2=111375
==============================================================================
--- 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java
  (original)
+++ 
cocoon/trunk/src/blocks/template/test/org/apache/cocoon/template/script/ScriptInvokerTestCase.java
  Thu Dec  9 04:38:49 2004
@@ -19,7 +19,12 @@
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.cocoon.ExtendedSitemapComponentTestCase;
 import org.apache.cocoon.el.GenericExpressionCompiler;
-import org.apache.cocoon.template.tag.samples.DuplicateTag;
+import org.apache.cocoon.template.v2.script.Script;
+import org.apache.cocoon.template.v2.script.ScriptCompiler;
+import org.apache.cocoon.template.v2.script.ScriptContext;
+import org.apache.cocoon.template.v2.script.ScriptInvoker;
+import org.apache.cocoon.template.v2.script.TagRepository;
+import org.apache.cocoon.template.v2.tag.samples.DuplicateTag;
 import org.apache.cocoon.xml.XMLConsumer;
 import org.apache.cocoon.xml.dom.DOMBuilder;
 

Reply via email to