struts-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From musa...@apache.org
Subject svn commit: r799681 [19/24] - in /struts/sandbox/trunk/struts2-jsp-plugin: ./ src/main/java/org/apache/struts/ src/main/java/org/apache/struts2/ src/main/java/org/apache/struts2/compiler/ src/main/java/org/apache/struts2/jasper/ src/main/java/org/apach...
Date Fri, 31 Jul 2009 18:12:51 GMT
Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JasperLoader.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JasperLoader.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JasperLoader.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JasperLoader.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts2.jasper.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.CodeSource;
+import java.security.PermissionCollection;
+
+import org.apache.struts2.jasper.Constants;
+
+/**
+ * Class loader for loading servlet class files (corresponding to JSP files) 
+ * and tag handler class files (corresponding to tag files).
+ *
+ * @author Anil K. Vijendran
+ * @author Harish Prabandham
+ * @author Jean-Francois Arcand
+ */
+public class JasperLoader extends URLClassLoader {
+
+    private PermissionCollection permissionCollection;
+    private ClassLoader parent;
+    private SecurityManager securityManager;
+
+    public JasperLoader(URL[] urls, ClassLoader parent,
+			PermissionCollection permissionCollection,
+			CodeSource codeSource) {
+	super(urls, parent);
+	this.permissionCollection = permissionCollection;
+	this.parent = parent;
+	this.securityManager = System.getSecurityManager();
+    }
+
+    /**
+     * Load the class with the specified name.  This method searches for
+     * classes in the same manner as <code>loadClass(String, boolean)</code>
+     * with <code>false</code> as the second argument.
+     *
+     * @param name Name of the class to be loaded
+     *
+     * @exception ClassNotFoundException if the class was not found
+     */
+    public Class loadClass(String name) throws ClassNotFoundException {
+
+        return (loadClass(name, false));
+    }
+
+    /**
+     * Load the class with the specified name, searching using the following
+     * algorithm until it finds and returns the class.  If the class cannot
+     * be found, returns <code>ClassNotFoundException</code>.
+     * <ul>
+     * <li>Call <code>findLoadedClass(String)</code> to check if the
+     *     class has already been loaded.  If it has, the same
+     *     <code>Class</code> object is returned.</li>
+     * <li>If the <code>delegate</code> property is set to <code>true</code>,
+     *     call the <code>loadClass()</code> method of the parent class
+     *     loader, if any.</li>            
+     * <li>Call <code>findClass()</code> to find this class in our locally
+     *     defined repositories.</li>      
+     * <li>Call the <code>loadClass()</code> method of our parent
+     *     class loader, if any.</li>      
+     * </ul>
+     * If the class was found using the above steps, and the
+     * <code>resolve</code> flag is <code>true</code>, this method will then
+     * call <code>resolveClass(Class)</code> on the resulting Class object.
+     *                                     
+     * @param name Name of the class to be loaded
+     * @param resolve If <code>true</code> then resolve the class
+     *                                     
+     * @exception ClassNotFoundException if the class was not found
+     */                                    
+    public Class loadClass(final String name, boolean resolve)
+        throws ClassNotFoundException {
+
+        Class clazz = null;                
+                                           
+        // (0) Check our previously loaded class cache
+        clazz = findLoadedClass(name);     
+        if (clazz != null) {               
+            if (resolve)                   
+                resolveClass(clazz);       
+            return (clazz);        
+        }                          
+                          
+        // (.5) Permission to access this class when using a SecurityManager
+        if (securityManager != null) {     
+            int dot = name.lastIndexOf('.');
+            if (dot >= 0) {                
+                try {        
+                    // Do not call the security manager since by default, we grant that package.
+                    if (!"org.apache.struts2.jasper.runtime".equalsIgnoreCase(name.substring(0,dot))){
+                        securityManager.checkPackageAccess(name.substring(0,dot));
+                    }
+                } catch (SecurityException se) {
+                    String error = "Security Violation, attempt to use " +
+                        "Restricted Class: " + name;
+                    se.printStackTrace();
+                    throw new ClassNotFoundException(error);
+                }                          
+            }                              
+        }
+
+	if( !name.startsWith(Constants.JSP_PACKAGE_NAME) ) {
+            // Class is not in org.apache.jsp, therefore, have our
+            // parent load it
+            clazz = parent.loadClass(name);            
+	    if( resolve )
+		resolveClass(clazz);
+	    return clazz;
+	}
+
+	return findClass(name);
+    }
+
+    
+    /**
+     * Delegate to parent
+     * 
+     * @see java.lang.ClassLoader#getResourceAsStream(java.lang.String)
+     */
+    public InputStream getResourceAsStream(String name) {
+        InputStream is = parent.getResourceAsStream(name);
+        if (is == null) {
+            URL url = findResource(name);
+            if (url != null) {
+                try {
+                    is = url.openStream();
+                } catch (IOException e) {
+                    is = null;
+                }
+            }
+        }
+        return is;
+    }
+    
+    
+    /**
+     * Get the Permissions for a CodeSource.
+     *
+     * Since this ClassLoader is only used for a JSP page in
+     * a web application context, we just return our preset
+     * PermissionCollection for the web app context.
+     *
+     * @param codeSource Code source where the code was loaded from
+     * @return PermissionCollection for CodeSource
+     */
+    public final PermissionCollection getPermissions(CodeSource codeSource) {
+        return permissionCollection;
+    }
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspCServletContext.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,402 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts2.jasper.servlet;
+
+
+import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+
+/**
+ * Simple <code>ServletContext</code> implementation without
+ * HTTP-specific methods.
+ *
+ * @author Peter Rossbach (pr@webapp.de)
+ */
+
+public class JspCServletContext implements ServletContext {
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * Servlet context attributes.
+     */
+    protected Hashtable myAttributes;
+
+
+    /**
+     * The log writer we will write log messages to.
+     */
+    protected PrintWriter myLogWriter;
+
+    private ClassLoaderInterface classLoaderInterface;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Create a new instance of this ServletContext implementation.
+     *
+     * @param aLogWriter PrintWriter which is used for <code>log()</code> calls
+     */
+    public JspCServletContext(PrintWriter aLogWriter, ClassLoaderInterface classLoaderInterface) {
+
+        myAttributes = new Hashtable();
+        myLogWriter = aLogWriter;
+        this.classLoaderInterface = classLoaderInterface;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Return the specified context attribute, if any.
+     *
+     * @param name Name of the requested attribute
+     */
+    public Object getAttribute(String name) {
+
+        return (myAttributes.get(name));
+
+    }
+
+
+    /**
+     * Return an enumeration of context attribute names.
+     */
+    public Enumeration getAttributeNames() {
+
+        return (myAttributes.keys());
+
+    }
+
+
+    /**
+     * Return the servlet context for the specified path.
+     *
+     * @param uripath Server-relative path starting with '/'
+     */
+    public ServletContext getContext(String uripath) {
+
+        return (null);
+
+    }
+
+
+    /**
+     * Return the specified context initialization parameter.
+     *
+     * @param name Name of the requested parameter
+     */
+    public String getInitParameter(String name) {
+
+        return (null);
+
+    }
+
+
+    /**
+     * Return an enumeration of the names of context initialization
+     * parameters.
+     */
+    public Enumeration getInitParameterNames() {
+
+        return (new Vector().elements());
+
+    }
+
+
+    /**
+     * Return the Servlet API major version number.
+     */
+    public int getMajorVersion() {
+
+        return (2);
+
+    }
+
+
+    /**
+     * Return the MIME type for the specified filename.
+     *
+     * @param file Filename whose MIME type is requested
+     */
+    public String getMimeType(String file) {
+
+        return (null);
+
+    }
+
+
+    /**
+     * Return the Servlet API minor version number.
+     */
+    public int getMinorVersion() {
+
+        return (3);
+
+    }
+
+
+    /**
+     * Return a request dispatcher for the specified servlet name.
+     *
+     * @param name Name of the requested servlet
+     */
+    public RequestDispatcher getNamedDispatcher(String name) {
+
+        return (null);
+
+    }
+
+
+    /**
+     * Return the real path for the specified context-relative
+     * virtual path.
+     *
+     * @param path The context-relative virtual path to resolve
+     */
+    public String getRealPath(String path) {
+        try {
+            return
+                (getResource(path).getFile().replace('/', File.separatorChar));
+        } catch (Throwable t) {
+            return (null);
+        }
+
+    }
+            
+            
+    /**
+     * Return a request dispatcher for the specified context-relative path.
+     *
+     * @param path Context-relative path for which to acquire a dispatcher
+     */
+    public RequestDispatcher getRequestDispatcher(String path) {
+
+        return (null);
+
+    }
+
+
+    /**
+     * Return a URL object of a resource that is mapped to the
+     * specified context-relative path.
+     *
+     * @param path Context-relative path of the desired resource
+     *
+     * @exception MalformedURLException if the resource path is
+     *  not properly formed
+     */
+    public URL getResource(String path) throws MalformedURLException {
+        return classLoaderInterface.getResource(path);
+    }
+
+
+    /**
+     * Return an InputStream allowing access to the resource at the
+     * specified context-relative path.
+     *
+     * @param path Context-relative path of the desired resource
+     */
+    public InputStream getResourceAsStream(String path) {
+
+        try {
+            return classLoaderInterface.getResourceAsStream(path);
+        } catch (Throwable t) {
+            return (null);
+        }
+
+    }
+
+
+    /**
+     * Return the set of resource paths for the "directory" at the
+     * specified context path.
+     *
+     * @param path Context-relative base path
+     */
+    public Set getResourcePaths(String path) {
+
+        Set thePaths = new HashSet();
+        if (!path.endsWith("/"))
+            path += "/";
+        String basePath = getRealPath(path);
+        if (basePath == null)
+            return (thePaths);
+        File theBaseDir = new File(basePath);
+        if (!theBaseDir.exists() || !theBaseDir.isDirectory())
+            return (thePaths);
+        String theFiles[] = theBaseDir.list();
+        for (int i = 0; i < theFiles.length; i++) {
+            File testFile = new File(basePath + File.separator + theFiles[i]);
+            if (testFile.isFile())
+                thePaths.add(path + theFiles[i]);
+            else if (testFile.isDirectory())
+                thePaths.add(path + theFiles[i] + "/");
+        }
+        return (thePaths);
+
+    }
+
+
+    /**
+     * Return descriptive information about this server.
+     */
+    public String getServerInfo() {
+
+        return ("JspCServletContext/1.0");
+
+    }
+
+
+    /**
+     * Return a null reference for the specified servlet name.
+     *
+     * @param name Name of the requested servlet
+     *
+     * @deprecated This method has been deprecated with no replacement
+     */
+    public Servlet getServlet(String name) throws ServletException {
+
+        return (null);
+
+    }
+
+
+    /**
+     * Return the name of this servlet context.
+     */
+    public String getServletContextName() {
+
+        return (getServerInfo());
+
+    }
+
+
+    /**
+     * Return an empty enumeration of servlet names.
+     *
+     * @deprecated This method has been deprecated with no replacement
+     */
+    public Enumeration getServletNames() {
+
+        return (new Vector().elements());
+
+    }
+
+
+    /**
+     * Return an empty enumeration of servlets.
+     *
+     * @deprecated This method has been deprecated with no replacement
+     */
+    public Enumeration getServlets() {
+
+        return (new Vector().elements());
+
+    }
+
+
+    /**
+     * Log the specified message.
+     *
+     * @param message The message to be logged
+     */
+    public void log(String message) {
+
+        myLogWriter.println(message);
+
+    }
+
+
+    /**
+     * Log the specified message and exception.
+     *
+     * @param exception The exception to be logged
+     * @param message The message to be logged
+     *
+     * @deprecated Use log(String,Throwable) instead
+     */
+    public void log(Exception exception, String message) {
+
+        log(message, exception);
+
+    }
+
+
+    /**
+     * Log the specified message and exception.
+     *
+     * @param message The message to be logged
+     * @param exception The exception to be logged
+     */
+    public void log(String message, Throwable exception) {
+
+        myLogWriter.println(message);
+        exception.printStackTrace(myLogWriter);
+
+    }
+
+
+    /**
+     * Remove the specified context attribute.
+     *
+     * @param name Name of the attribute to remove
+     */
+    public void removeAttribute(String name) {
+
+        myAttributes.remove(name);
+
+    }
+
+
+    /**
+     * Set or replace the specified context attribute.
+     *
+     * @param name Name of the context attribute to set
+     * @param value Corresponding attribute value
+     */
+    public void setAttribute(String name, Object value) {
+
+        myAttributes.put(name, value);
+
+    }
+
+
+
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServlet.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,333 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts2.jasper.servlet;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Enumeration;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.struts2.jasper.Constants;
+import org.apache.struts2.jasper.EmbeddedServletOptions;
+import org.apache.struts2.jasper.Options;
+import org.apache.struts2.jasper.compiler.JspRuntimeContext;
+import org.apache.struts2.jasper.compiler.Localizer;
+
+/**
+ * The JSP engine (a.k.a Jasper).
+ *
+ * The servlet container is responsible for providing a
+ * URLClassLoader for the web application context Jasper
+ * is being used in. Jasper will try get the Tomcat
+ * ServletContext attribute for its ServletContext class
+ * loader, if that fails, it uses the parent class loader.
+ * In either case, it must be a URLClassLoader.
+ *
+ * @author Anil K. Vijendran
+ * @author Harish Prabandham
+ * @author Remy Maucherat
+ * @author Kin-man Chung
+ * @author Glenn Nielsen
+ */
+public class JspServlet extends HttpServlet {
+
+    // Logger
+    private Log log = LogFactory.getLog(JspServlet.class);
+
+    private ServletContext context;
+    private ServletConfig config;
+    private Options options;
+    private JspRuntimeContext rctxt;
+
+
+    /*
+     * Initializes this JspServlet.
+     */
+    public void init(ServletConfig config) throws ServletException {
+        
+        super.init(config);
+        this.config = config;
+        this.context = config.getServletContext();
+        
+        // Initialize the JSP Runtime Context
+        // Check for a custom Options implementation
+        String engineOptionsName = 
+            config.getInitParameter("engineOptionsClass");
+        if (engineOptionsName != null) {
+            // Instantiate the indicated Options implementation
+            try {
+                ClassLoader loader = Thread.currentThread()
+                        .getContextClassLoader();
+                Class engineOptionsClass = loader.loadClass(engineOptionsName);
+                Class[] ctorSig = { ServletConfig.class, ServletContext.class };
+                Constructor ctor = engineOptionsClass.getConstructor(ctorSig);
+                Object[] args = { config, context };
+                options = (Options) ctor.newInstance(args);
+            } catch (Throwable e) {
+                // Need to localize this.
+                log.warn("Failed to load engineOptionsClass", e);
+                // Use the default Options implementation
+                options = new EmbeddedServletOptions(config, context);
+            }
+        } else {
+            // Use the default Options implementation
+            options = new EmbeddedServletOptions(config, context);
+        }
+        rctxt = new JspRuntimeContext(context, options);
+        
+        if (log.isDebugEnabled()) {
+            log.debug(Localizer.getMessage("jsp.message.scratch.dir.is",
+                    options.getScratchDir().toString()));
+            log.debug(Localizer.getMessage("jsp.message.dont.modify.servlets"));
+        }
+    }
+
+
+    /**
+     * Returns the number of JSPs for which JspServletWrappers exist, i.e.,
+     * the number of JSPs that have been loaded into the webapp with which
+     * this JspServlet is associated.
+     *
+     * <p>This info may be used for monitoring purposes.
+     *
+     * @return The number of JSPs that have been loaded into the webapp with
+     * which this JspServlet is associated
+     */
+    public int getJspCount() {
+        return this.rctxt.getJspCount();
+    }
+
+
+    /**
+     * Resets the JSP reload counter.
+     *
+     * @param count Value to which to reset the JSP reload counter
+     */
+    public void setJspReloadCount(int count) {
+        this.rctxt.setJspReloadCount(count);
+    }
+
+
+    /**
+     * Gets the number of JSPs that have been reloaded.
+     *
+     * <p>This info may be used for monitoring purposes.
+     *
+     * @return The number of JSPs (in the webapp with which this JspServlet is
+     * associated) that have been reloaded
+     */
+    public int getJspReloadCount() {
+        return this.rctxt.getJspReloadCount();
+    }
+
+
+    /**
+     * <p>Look for a <em>precompilation request</em> as described in
+     * Section 8.4.2 of the JSP 1.2 Specification.  <strong>WARNING</strong> -
+     * we cannot use <code>request.getParameter()</code> for this, because
+     * that will trigger parsing all of the request parameters, and not give
+     * a servlet the opportunity to call
+     * <code>request.setCharacterEncoding()</code> first.</p>
+     *
+     * @param request The servlet requset we are processing
+     *
+     * @exception ServletException if an invalid parameter value for the
+     *  <code>jsp_precompile</code> parameter name is specified
+     */
+    boolean preCompile(HttpServletRequest request) throws ServletException {
+
+        String queryString = request.getQueryString();
+        if (queryString == null) {
+            return (false);
+        }
+        int start = queryString.indexOf(Constants.PRECOMPILE);
+        if (start < 0) {
+            return (false);
+        }
+        queryString =
+            queryString.substring(start + Constants.PRECOMPILE.length());
+        if (queryString.length() == 0) {
+            return (true);             // ?jsp_precompile
+        }
+        if (queryString.startsWith("&")) {
+            return (true);             // ?jsp_precompile&foo=bar...
+        }
+        if (!queryString.startsWith("=")) {
+            return (false);            // part of some other name or value
+        }
+        int limit = queryString.length();
+        int ampersand = queryString.indexOf("&");
+        if (ampersand > 0) {
+            limit = ampersand;
+        }
+        String value = queryString.substring(1, limit);
+        if (value.equals("true")) {
+            return (true);             // ?jsp_precompile=true
+        } else if (value.equals("false")) {
+            // Spec says if jsp_precompile=false, the request should not
+            // be delivered to the JSP page; the easiest way to implement
+            // this is to set the flag to true, and precompile the page anyway.
+            // This still conforms to the spec, since it says the
+            // precompilation request can be ignored.
+            return (true);             // ?jsp_precompile=false
+        } else {
+            throw new ServletException("Cannot have request parameter " +
+                                       Constants.PRECOMPILE + " set to " +
+                                       value);
+        }
+
+    }
+    
+
+    public void service (HttpServletRequest request, 
+                         HttpServletResponse response)
+                throws ServletException, IOException {
+
+        String jspUri = null;
+
+        String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
+        if (jspFile != null) {
+            // JSP is specified via <jsp-file> in <servlet> declaration
+            jspUri = jspFile;
+        } else {
+            /*
+             * Check to see if the requested JSP has been the target of a
+             * RequestDispatcher.include()
+             */
+            jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH);
+            if (jspUri != null) {
+                /*
+                 * Requested JSP has been target of
+                 * RequestDispatcher.include(). Its path is assembled from the
+                 * relevant javax.servlet.include.* request attributes
+                 */
+                String pathInfo = (String) request.getAttribute(
+                                    "javax.servlet.include.path_info");
+                if (pathInfo != null) {
+                    jspUri += pathInfo;
+                }
+            } else {
+                /*
+                 * Requested JSP has not been the target of a 
+                 * RequestDispatcher.include(). Reconstruct its path from the
+                 * request's getServletPath() and getPathInfo()
+                 */
+                jspUri = request.getServletPath();
+                String pathInfo = request.getPathInfo();
+                if (pathInfo != null) {
+                    jspUri += pathInfo;
+                }
+            }
+        }
+
+        if (log.isDebugEnabled()) {
+            log.debug("JspEngine --> " + jspUri);
+            log.debug("\t     ServletPath: " + request.getServletPath());
+            log.debug("\t        PathInfo: " + request.getPathInfo());
+            log.debug("\t        RealPath: " + context.getRealPath(jspUri));
+            log.debug("\t      RequestURI: " + request.getRequestURI());
+            log.debug("\t     QueryString: " + request.getQueryString());
+            log.debug("\t  Request Params: ");
+            Enumeration e = request.getParameterNames();
+            while (e.hasMoreElements()) {
+                String name = (String) e.nextElement();
+                log.debug("\t\t " + name + " = " 
+                          + request.getParameter(name));
+            }
+        }
+
+        try {
+            boolean precompile = preCompile(request);
+            serviceJspFile(request, response, jspUri, null, precompile);
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (ServletException e) {
+            throw e;
+        } catch (IOException e) {
+            throw e;
+        } catch (Throwable e) {
+            throw new ServletException(e);
+        }
+
+    }
+
+    public void destroy() {
+        if (log.isDebugEnabled()) {
+            log.debug("JspServlet.destroy()");
+        }
+
+        rctxt.destroy();
+    }
+
+
+    // -------------------------------------------------------- Private Methods
+
+    private void serviceJspFile(HttpServletRequest request,
+                                HttpServletResponse response, String jspUri,
+                                Throwable exception, boolean precompile)
+        throws ServletException, IOException {
+
+        JspServletWrapper wrapper =
+            (JspServletWrapper) rctxt.getWrapper(jspUri);
+        if (wrapper == null) {
+            synchronized(this) {
+                wrapper = (JspServletWrapper) rctxt.getWrapper(jspUri);
+                if (wrapper == null) {
+                    // Check if the requested JSP page exists, to avoid
+                    // creating unnecessary directories and files.
+                    if (null == context.getResource(jspUri)) {
+                        String includeRequestUri = (String)
+                        request.getAttribute("javax.servlet.include.request_uri");
+                        if (includeRequestUri != null) {
+                            // This file was included. Throw an exception as
+                            // a response.sendError() will be ignored
+                            throw new ServletException(Localizer.getMessage(
+                                    "jsp.error.file.not.found",jspUri));
+                        } else {
+                            try {
+                                response.sendError(HttpServletResponse.SC_NOT_FOUND,
+                                        request.getRequestURI());
+                        } catch (IllegalStateException ise) {
+                            log.error(Localizer.getMessage("jsp.error.file.not.found",
+                                   jspUri));
+                        }
+                    }
+                        return;
+                    }
+                    boolean isErrorPage = exception != null;
+                    wrapper = new JspServletWrapper(config, options, jspUri,
+                                                    isErrorPage, rctxt);
+                    rctxt.addWrapper(jspUri,wrapper);
+                }
+            }
+        }
+
+        wrapper.service(request, response, precompile);
+
+    }
+
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/JspServletWrapper.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,465 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.struts2.jasper.servlet;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.SingleThreadModel;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.jsp.tagext.TagInfo;
+
+import org.apache.struts2.jasper.JasperException;
+import org.apache.struts2.jasper.JspCompilationContext;
+import org.apache.struts2.jasper.Options;
+import org.apache.struts2.jasper.compiler.ErrorDispatcher;
+import org.apache.struts2.jasper.compiler.JavacErrorDetail;
+import org.apache.struts2.jasper.compiler.JspRuntimeContext;
+import org.apache.struts2.jasper.compiler.Localizer;
+import org.apache.struts2.jasper.runtime.JspSourceDependent;
+
+/**
+ * The JSP engine (a.k.a Jasper).
+ *
+ * The servlet container is responsible for providing a
+ * URLClassLoader for the web application context Jasper
+ * is being used in. Jasper will try get the Tomcat
+ * ServletContext attribute for its ServletContext class
+ * loader, if that fails, it uses the parent class loader.
+ * In either case, it must be a URLClassLoader.
+ *
+ * @author Anil K. Vijendran
+ * @author Harish Prabandham
+ * @author Remy Maucherat
+ * @author Kin-man Chung
+ * @author Glenn Nielsen
+ * @author Tim Fennell
+ */
+
+public class JspServletWrapper {
+
+    private Servlet theServlet;
+    private String jspUri;
+    private Class servletClass;
+    private Class tagHandlerClass;
+    private JspCompilationContext ctxt;
+    private long available = 0L;
+    private ServletConfig config;
+    private Options options;
+    private boolean firstTime = true;
+    private boolean reload = true;
+    private boolean isTagFile;
+    private int tripCount;
+    private JasperException compileException;
+    private long servletClassLastModifiedTime;
+    private long lastModificationTest = 0L;
+
+    /*
+     * JspServletWrapper for JSP pages.
+     */
+    JspServletWrapper(ServletConfig config, Options options, String jspUri,
+                      boolean isErrorPage, JspRuntimeContext rctxt)
+            throws JasperException {
+
+	this.isTagFile = false;
+        this.config = config;
+        this.options = options;
+        this.jspUri = jspUri;
+        ctxt = new JspCompilationContext(jspUri, isErrorPage, options,
+					 config.getServletContext(),
+					 this, rctxt);
+    }
+
+    /*
+     * JspServletWrapper for tag files.
+     */
+    public JspServletWrapper(ServletContext servletContext,
+			     Options options,
+			     String tagFilePath,
+			     TagInfo tagInfo,
+			     JspRuntimeContext rctxt,
+			     URL tagFileJarUrl)
+	    throws JasperException {
+
+	this.isTagFile = true;
+        this.config = null;	// not used
+        this.options = options;
+	this.jspUri = tagFilePath;
+	this.tripCount = 0;
+        ctxt = new JspCompilationContext(jspUri, tagInfo, options,
+					 servletContext, this, rctxt,
+					 tagFileJarUrl);
+    }
+
+    public JspCompilationContext getJspEngineContext() {
+        return ctxt;
+    }
+
+    public void setReload(boolean reload) {
+        this.reload = reload;
+    }
+
+    public Servlet getServlet()
+        throws ServletException, IOException, FileNotFoundException
+    {
+        if (reload) {
+            synchronized (this) {
+                // Synchronizing on jsw enables simultaneous loading
+                // of different pages, but not the same page.
+                if (reload) {
+                    // This is to maintain the original protocol.
+                    destroy();
+                    
+                    Servlet servlet = null;
+                    try {
+                        servletClass = ctxt.load();
+                        servlet = (Servlet) servletClass.newInstance();
+                    } catch( IllegalAccessException ex1 ) {
+                        throw new JasperException( ex1 );
+                    } catch( InstantiationException ex ) {
+                        throw new JasperException( ex );
+                    }
+                    
+                    servlet.init(config);
+
+                    if (!firstTime) {
+                        ctxt.getRuntimeContext().incrementJspReloadCount();
+                    }
+
+                    theServlet = servlet;
+                    reload = false;
+                }
+            }    
+        }
+        return theServlet;
+    }
+
+    public ServletContext getServletContext() {
+        return config.getServletContext();
+    }
+
+    /**
+     * Sets the compilation exception for this JspServletWrapper.
+     *
+     * @param je The compilation exception
+     */
+    public void setCompilationException(JasperException je) {
+        this.compileException = je;
+    }
+
+    /**
+     * Sets the last-modified time of the servlet class file associated with
+     * this JspServletWrapper.
+     *
+     * @param lastModified Last-modified time of servlet class
+     */
+    public void setServletClassLastModifiedTime(long lastModified) {
+        if (this.servletClassLastModifiedTime < lastModified) {
+            synchronized (this) {
+                if (this.servletClassLastModifiedTime < lastModified) {
+                    this.servletClassLastModifiedTime = lastModified;
+                    reload = true;
+                }
+            }
+        }
+    }
+
+    /**
+     * Compile (if needed) and load a tag file
+     */
+    public Class loadTagFile() throws JasperException {
+
+        try {
+            if (ctxt.isRemoved()) {
+                throw new FileNotFoundException(jspUri);
+            }
+            if (options.getDevelopment() || firstTime ) {
+                synchronized (this) {
+                    firstTime = false;
+                    ctxt.compile();
+                }
+            } else {
+                if (compileException != null) {
+                    throw compileException;
+                }
+            }
+
+            if (reload) {
+                tagHandlerClass = ctxt.load();
+                reload = false;
+            }
+        } catch (FileNotFoundException ex) {
+            throw new JasperException(ex);
+	}
+
+	return tagHandlerClass;
+    }
+
+    /**
+     * Compile and load a prototype for the Tag file.  This is needed
+     * when compiling tag files with circular dependencies.  A prototpe
+     * (skeleton) with no dependencies on other other tag files is
+     * generated and compiled.
+     */
+    public Class loadTagFilePrototype() throws JasperException {
+
+	ctxt.setPrototypeMode(true);
+	try {
+	    return loadTagFile();
+	} finally {
+	    ctxt.setPrototypeMode(false);
+	}
+    }
+
+    /**
+     * Get a list of files that the current page has source dependency on.
+     */
+    public java.util.List getDependants() {
+	try {
+	    Object target;
+	    if (isTagFile) {
+                if (reload) {
+                    tagHandlerClass = ctxt.load();
+                    reload = false;
+                }
+		target = tagHandlerClass.newInstance();
+	    } else {
+		target = getServlet();
+	    }
+	    if (target != null && target instanceof JspSourceDependent) {
+            return ((java.util.List) ((JspSourceDependent) target).getDependants());
+	    }
+	} catch (Throwable ex) {
+	}
+	return null;
+    }
+
+    public boolean isTagFile() {
+	return this.isTagFile;
+    }
+
+    public int incTripCount() {
+	return tripCount++;
+    }
+
+    public int decTripCount() {
+	return tripCount--;
+    }
+
+    public void service(HttpServletRequest request, 
+                        HttpServletResponse response,
+                        boolean precompile)
+	    throws ServletException, IOException, FileNotFoundException {
+        try {
+
+            if (ctxt.isRemoved()) {
+                throw new FileNotFoundException(jspUri);
+            }
+
+            if ((available > 0L) && (available < Long.MAX_VALUE)) {
+                if (available > System.currentTimeMillis()) {
+                    response.setDateHeader("Retry-After", available);
+                    response.sendError
+                        (HttpServletResponse.SC_SERVICE_UNAVAILABLE,
+                         Localizer.getMessage("jsp.error.unavailable"));
+                    return;
+                } else {
+                    // Wait period has expired. Reset.
+                    available = 0;
+                }
+            }
+
+            /*
+             * (1) Compile
+             */
+            if (options.getDevelopment() || firstTime ) {
+                synchronized (this) {
+                    firstTime = false;
+
+                    // The following sets reload to true, if necessary
+                    ctxt.compile();
+                }
+            } else {
+                if (compileException != null) {
+                    // Throw cached compilation exception
+                    throw compileException;
+                }
+            }
+
+            /*
+             * (2) (Re)load servlet class file
+             */
+            getServlet();
+
+            // If a page is to be precompiled only, return.
+            if (precompile) {
+                return;
+            }
+
+            /*
+             * (3) Service request
+             */
+            if (theServlet instanceof SingleThreadModel) {
+               // sync on the wrapper so that the freshness
+               // of the page is determined right before servicing
+               synchronized (this) {
+                   theServlet.service(request, response);
+                }
+            } else {
+                theServlet.service(request, response);
+            }
+
+        } catch (UnavailableException ex) {
+            String includeRequestUri = (String)
+                request.getAttribute("javax.servlet.include.request_uri");
+            if (includeRequestUri != null) {
+                // This file was included. Throw an exception as
+                // a response.sendError() will be ignored by the
+                // servlet engine.
+                throw ex;
+            } else {
+                int unavailableSeconds = ex.getUnavailableSeconds();
+                if (unavailableSeconds <= 0) {
+                    unavailableSeconds = 60;        // Arbitrary default
+                }
+                available = System.currentTimeMillis() +
+                    (unavailableSeconds * 1000L);
+                response.sendError
+                    (HttpServletResponse.SC_SERVICE_UNAVAILABLE, 
+                     ex.getMessage());
+            }
+        } catch (ServletException ex) {
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw ex;
+            }
+        } catch (IOException ex) {
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw ex;
+            }
+        } catch (IllegalStateException ex) {
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw ex;
+            }
+        } catch (Exception ex) {
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw new JasperException(ex);
+            }
+        }
+    }
+
+    public void destroy() {
+        if (theServlet != null) {
+            theServlet.destroy();
+        }
+    }
+
+    /**
+     * @return Returns the lastModificationTest.
+     */
+    public long getLastModificationTest() {
+        return lastModificationTest;
+    }
+    /**
+     * @param lastModificationTest The lastModificationTest to set.
+     */
+    public void setLastModificationTest(long lastModificationTest) {
+        this.lastModificationTest = lastModificationTest;
+    }
+
+    /**
+     * <p>Attempts to construct a JasperException that contains helpful information
+     * about what went wrong. Uses the JSP compiler system to translate the line
+     * number in the generated servlet that originated the exception to a line
+     * number in the JSP.  Then constructs an exception containing that
+     * information, and a snippet of the JSP to help debugging.
+     * Please see http://issues.apache.org/bugzilla/show_bug.cgi?id=37062 and
+     * http://www.tfenne.com/jasper/ for more details.
+     *</p>
+     *
+     * @param ex the exception that was the cause of the problem.
+     * @return a JasperException with more detailed information
+     */
+    protected JasperException handleJspException(Exception ex) {
+        try {
+            Throwable realException = ex;
+            if (ex instanceof ServletException) {
+                realException = ((ServletException) ex).getRootCause();
+            }
+
+            // First identify the stack frame in the trace that represents the JSP
+            StackTraceElement[] frames = realException.getStackTrace();
+            StackTraceElement jspFrame = null;
+
+            for (int i=0; i<frames.length; ++i) {
+                if ( frames[i].getClassName().equals(this.getServlet().getClass().getName()) ) {
+                    jspFrame = frames[i];
+                    break;
+                }
+            }
+
+            if (jspFrame == null) {
+                // If we couldn't find a frame in the stack trace corresponding
+                // to the generated servlet class, we can't really add anything
+                return new JasperException(ex);
+            }
+            else {
+                int javaLineNumber = jspFrame.getLineNumber();
+                JavacErrorDetail detail = ErrorDispatcher.createJavacError(
+                        jspFrame.getMethodName(),
+                        this.ctxt.getCompiler().getPageNodes(),
+                        null,
+                        javaLineNumber,
+                        this.ctxt);
+
+                // If the line number is less than one we couldn't find out
+                // where in the JSP things went wrong
+                int jspLineNumber = detail.getJspBeginLineNumber();
+                if (jspLineNumber < 1) {
+                    throw new JasperException(ex);
+                }
+
+                return new JasperException("Exception in JSP: " +
+                        detail.getJspFileName() + ":" + jspLineNumber + "\n\n" +
+                        detail.getJspExtract() + "\n\nStacktrace:", ex);
+            }
+        } catch (Exception je) {
+            // If anything goes wrong, just revert to the original behaviour
+            if (ex instanceof JasperException) {
+                return (JasperException) ex;
+            } else {
+                return new JasperException(ex);
+            }
+        }
+    }
+
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/mbeans-descriptors.xml
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/mbeans-descriptors.xml?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/mbeans-descriptors.xml (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/servlet/mbeans-descriptors.xml Fri Jul 31 18:12:48 2009
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<mbeans-descriptors>
+
+  <mbean         name="JspMonitor"
+          description="JSP Monitoring"
+               domain="Catalina"
+                group="Monitoring"
+                 type="org.apache.struts2.jasper.servlet.JspServlet">
+
+    <attribute   name="jspCount"
+          description="The number of JSPs that have been loaded into a webapp"
+                 type="int"/>
+
+    <attribute   name="jspReloadCount"
+          description="The number of JSPs that have been reloaded"
+                 type="int"/>
+
+  </mbean>
+
+</mbeans-descriptors>
\ No newline at end of file

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/Util.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts2.jasper.tagplugins.jstl;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Locale;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspTagException;
+import javax.servlet.jsp.PageContext;
+
+/**
+ * Util contains some often used consts, static methods and embedded class
+ * to support the JSTL tag plugin.
+ */
+
+public class Util {
+    
+    public static final String VALID_SCHEME_CHAR = 
+        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-";
+    
+    public static final String DEFAULT_ENCODING = 
+        "ISO-8859-1";
+    
+    public static final int HIGHEST_SPECIAL = '>';
+    
+    public static char[][] specialCharactersRepresentation = new char[HIGHEST_SPECIAL + 1][];
+    
+    static {
+        specialCharactersRepresentation['&'] = "&amp;".toCharArray();
+        specialCharactersRepresentation['<'] = "&lt;".toCharArray();
+        specialCharactersRepresentation['>'] = "&gt;".toCharArray();
+        specialCharactersRepresentation['"'] = "&#034;".toCharArray();
+        specialCharactersRepresentation['\''] = "&#039;".toCharArray();
+    }
+    
+    /**
+     * Converts the given string description of a scope to the corresponding
+     * PageContext constant.
+     *
+     * The validity of the given scope has already been checked by the
+     * appropriate TLV.
+     *
+     * @param scope String description of scope
+     *
+     * @return PageContext constant corresponding to given scope description
+     * 
+     * taken from org.apache.taglibs.standard.tag.common.core.Util  
+     */
+    public static int getScope(String scope){
+        int ret = PageContext.PAGE_SCOPE;
+        
+        if("request".equalsIgnoreCase(scope)){
+            ret = PageContext.REQUEST_SCOPE;
+        }else if("session".equalsIgnoreCase(scope)){
+            ret = PageContext.SESSION_SCOPE;
+        }else if("application".equalsIgnoreCase(scope)){
+            ret = PageContext.APPLICATION_SCOPE;
+        }
+        
+        return ret;
+    }
+    
+    /**
+     * Returns <tt>true</tt> if our current URL is absolute,
+     * <tt>false</tt> otherwise.
+     * taken from org.apache.taglibs.standard.tag.common.core.ImportSupport
+     */
+    public static boolean isAbsoluteUrl(String url){
+        if(url == null){
+            return false;
+        }
+        
+        int colonPos = url.indexOf(":");
+        if(colonPos == -1){
+            return false;
+        }
+        
+        for(int i=0;i<colonPos;i++){
+            if(VALID_SCHEME_CHAR.indexOf(url.charAt(i)) == -1){
+                return false;
+            }
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Get the value associated with a content-type attribute.
+     * Syntax defined in RFC 2045, section 5.1.
+     * taken from org.apache.taglibs.standard.tag.common.core.Util
+     */
+    public static String getContentTypeAttribute(String input, String name) {
+        int begin;
+        int end;
+        int index = input.toUpperCase().indexOf(name.toUpperCase());
+        if (index == -1) return null;
+        index = index + name.length(); // positioned after the attribute name
+        index = input.indexOf('=', index); // positioned at the '='
+        if (index == -1) return null;
+        index += 1; // positioned after the '='
+        input = input.substring(index).trim();
+        
+        if (input.charAt(0) == '"') {
+            // attribute value is a quoted string
+            begin = 1;
+            end = input.indexOf('"', begin);
+            if (end == -1) return null;
+        } else {
+            begin = 0;
+            end = input.indexOf(';');
+            if (end == -1) end = input.indexOf(' ');
+            if (end == -1) end = input.length();
+        }
+        return input.substring(begin, end).trim();
+    }
+    
+    /**
+     * Strips a servlet session ID from <tt>url</tt>.  The session ID
+     * is encoded as a URL "path parameter" beginning with "jsessionid=".
+     * We thus remove anything we find between ";jsessionid=" (inclusive)
+     * and either EOS or a subsequent ';' (exclusive).
+     * 
+     * taken from org.apache.taglibs.standard.tag.common.core.ImportSupport
+     */
+    public static String stripSession(String url) {
+        StringBuffer u = new StringBuffer(url);
+        int sessionStart;
+        while ((sessionStart = u.toString().indexOf(";jsessionid=")) != -1) {
+            int sessionEnd = u.toString().indexOf(";", sessionStart + 1);
+            if (sessionEnd == -1)
+                sessionEnd = u.toString().indexOf("?", sessionStart + 1);
+            if (sessionEnd == -1) 				// still
+                sessionEnd = u.length();
+            u.delete(sessionStart, sessionEnd);
+        }
+        return u.toString();
+    }
+    
+    
+    /**
+     * Performs the following substring replacements
+     * (to facilitate output to XML/HTML pages):
+     *
+     *    & -> &amp;
+     *    < -> &lt;
+     *    > -> &gt;
+     *    " -> &#034;
+     *    ' -> &#039;
+     *
+     * See also OutSupport.writeEscapedXml().
+     * 
+     * taken from org.apache.taglibs.standard.tag.common.core.Util
+     */
+    public static String escapeXml(String buffer) {
+        int start = 0;
+        int length = buffer.length();
+        char[] arrayBuffer = buffer.toCharArray();
+        StringBuffer escapedBuffer = null;
+        
+        for (int i = 0; i < length; i++) {
+            char c = arrayBuffer[i];
+            if (c <= HIGHEST_SPECIAL) {
+                char[] escaped = specialCharactersRepresentation[c];
+                if (escaped != null) {
+                    // create StringBuffer to hold escaped xml string
+                    if (start == 0) {
+                        escapedBuffer = new StringBuffer(length + 5);
+                    }
+                    // add unescaped portion
+                    if (start < i) {
+                        escapedBuffer.append(arrayBuffer,start,i-start);
+                    }
+                    start = i + 1;
+                    // add escaped xml
+                    escapedBuffer.append(escaped);
+                }
+            }
+        }
+        // no xml escaping was necessary
+        if (start == 0) {
+            return buffer;
+        }
+        // add rest of unescaped portion
+        if (start < length) {
+            escapedBuffer.append(arrayBuffer,start,length-start);
+        }
+        return escapedBuffer.toString();
+    }
+    
+    /** Utility methods
+     * taken from org.apache.taglibs.standard.tag.common.core.UrlSupport
+     */
+    public static String resolveUrl(
+            String url, String context, PageContext pageContext)
+    throws JspException {
+        // don't touch absolute URLs
+        if (isAbsoluteUrl(url))
+            return url;
+        
+        // normalize relative URLs against a context root
+        HttpServletRequest request =
+            (HttpServletRequest) pageContext.getRequest();
+        if (context == null) {
+            if (url.startsWith("/"))
+                return (request.getContextPath() + url);
+            else
+                return url;
+        } else {
+            if (!context.startsWith("/") || !url.startsWith("/")) {
+                throw new JspTagException(
+                "In URL tags, when the \"context\" attribute is specified, values of both \"context\" and \"url\" must start with \"/\".");
+            }
+            if (context.equals("/")) {
+                // Don't produce string starting with '//', many
+                // browsers interpret this as host name, not as
+                // path on same host.
+                return url;
+            } else {
+                return (context + url);
+            }
+        }
+    }
+    
+    /** Wraps responses to allow us to retrieve results as Strings. 
+     * mainly taken from org.apache.taglibs.standard.tag.common.core.importSupport 
+     */
+    public static class ImportResponseWrapper extends HttpServletResponseWrapper{
+        
+        private StringWriter sw = new StringWriter();
+        private ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        private ServletOutputStream sos = new ServletOutputStream() {
+            public void write(int b) throws IOException {
+                bos.write(b);
+            }
+        };
+        private boolean isWriterUsed;
+        private boolean isStreamUsed;
+        private int status = 200;
+        private String charEncoding;
+        
+        public ImportResponseWrapper(HttpServletResponse arg0) {
+            super(arg0);
+            // TODO Auto-generated constructor stub
+        }
+        
+        public PrintWriter getWriter() {
+            if (isStreamUsed)
+                throw new IllegalStateException("Unexpected internal error during &lt;import&gt: " +
+                "Target servlet called getWriter(), then getOutputStream()");
+            isWriterUsed = true;
+            return new PrintWriter(sw);
+        }
+        
+        public ServletOutputStream getOutputStream() {
+            if (isWriterUsed)
+                throw new IllegalStateException("Unexpected internal error during &lt;import&gt: " +
+                "Target servlet called getOutputStream(), then getWriter()");
+            isStreamUsed = true;
+            return sos;
+        }
+        
+        /** Has no effect. */
+        public void setContentType(String x) {
+            // ignore
+        }
+        
+        /** Has no effect. */
+        public void setLocale(Locale x) {
+            // ignore
+        }
+        
+        public void setStatus(int status) {
+            this.status = status;
+        }
+        
+        public int getStatus() {
+            return status;
+        }
+        
+        public String getCharEncoding(){
+            return this.charEncoding;
+        }
+        
+        public void setCharEncoding(String ce){
+            this.charEncoding = ce;
+        }
+        
+        public String getString() throws UnsupportedEncodingException {
+            if (isWriterUsed)
+                return sw.toString();
+            else if (isStreamUsed) {
+                if (this.charEncoding != null && !this.charEncoding.equals(""))
+                    return bos.toString(charEncoding);
+                else
+                    return bos.toString("ISO-8859-1");
+            } else
+                return "";		// target didn't write anything
+        }
+    }
+    
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Catch.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Catch.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Catch.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Catch.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts2.jasper.tagplugins.jstl.core;
+
+import org.apache.struts2.jasper.compiler.tagplugin.TagPlugin;
+import org.apache.struts2.jasper.compiler.tagplugin.TagPluginContext;
+
+public class Catch implements TagPlugin {
+    
+    public void doTag(TagPluginContext ctxt) {
+        
+        //flag for the existence of the var attribute
+        boolean hasVar = ctxt.isAttributeSpecified("var");
+        
+        //temp name for exception and caught
+        String exceptionName = ctxt.getTemporaryVariableName();
+        String caughtName = ctxt.getTemporaryVariableName();
+        
+        //main part to generate code
+        ctxt.generateJavaSource("boolean " + caughtName + " = false;");
+        ctxt.generateJavaSource("try{");
+        ctxt.generateBody();
+        ctxt.generateJavaSource("}");
+        
+        //do catch
+        ctxt.generateJavaSource("catch(Throwable " + exceptionName + "){");
+        
+        //if the var specified, the exception object should 
+        //be set to the attribute "var" defines in page scope 
+        if(hasVar){
+            String strVar = ctxt.getConstantAttribute("var");
+            ctxt.generateJavaSource("    pageContext.setAttribute(\"" + strVar + "\", " 
+                    + exceptionName + ", PageContext.PAGE_SCOPE);");
+        }
+        
+        //whenever there's exception caught, 
+        //the flag caught should be set true;
+        ctxt.generateJavaSource("    " + caughtName + " = true;");
+        ctxt.generateJavaSource("}");
+        
+        //do finally
+        ctxt.generateJavaSource("finally{");
+        
+        //if var specified, the attribute it defines 
+        //in page scope should be removed
+        if(hasVar){
+            String strVar = ctxt.getConstantAttribute("var");
+            ctxt.generateJavaSource("    if(!" + caughtName + "){");
+            ctxt.generateJavaSource("        pageContext.removeAttribute(\"" + strVar + "\", PageContext.PAGE_SCOPE);");
+            ctxt.generateJavaSource("    }");
+        }
+        
+        ctxt.generateJavaSource("}");
+    }
+    
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Choose.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Choose.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Choose.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/Choose.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts2.jasper.tagplugins.jstl.core;
+
+import org.apache.struts2.jasper.compiler.tagplugin.*;
+
+public final class Choose implements TagPlugin {
+    
+    public void doTag(TagPluginContext ctxt) {
+        
+        // Not much to do here, much of the work will be done in the
+        // containing tags, <c:when> and <c:otherwise>.
+        
+        ctxt.generateBody();
+        // See comments in When.java for the reason "}" is generated here.
+        ctxt.generateJavaSource("}");
+    }
+}

Added: struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/ForEach.java
URL: http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/ForEach.java?rev=799681&view=auto
==============================================================================
--- struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/ForEach.java (added)
+++ struts/sandbox/trunk/struts2-jsp-plugin/src/main/java/org/apache/struts2/jasper/tagplugins/jstl/core/ForEach.java Fri Jul 31 18:12:48 2009
@@ -0,0 +1,344 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.struts2.jasper.tagplugins.jstl.core;
+
+import org.apache.struts2.jasper.compiler.tagplugin.*;
+
+public final class ForEach implements TagPlugin {
+    
+    private boolean hasVar, hasBegin, hasEnd, hasStep;
+    
+    public void doTag(TagPluginContext ctxt) {
+        
+        String index = null;
+        
+        boolean hasVarStatus = ctxt.isAttributeSpecified("varStatus");
+        if (hasVarStatus) {
+            ctxt.dontUseTagPlugin();
+            return;
+        }
+        
+        hasVar = ctxt.isAttributeSpecified("var");
+        hasBegin = ctxt.isAttributeSpecified("begin");
+        hasEnd = ctxt.isAttributeSpecified("end");
+        hasStep = ctxt.isAttributeSpecified("step");
+        
+        boolean hasItems = ctxt.isAttributeSpecified("items");
+        if (hasItems) {
+            doCollection(ctxt);
+            return;
+        }
+        
+        // We must have a begin and end attributes
+        index = ctxt.getTemporaryVariableName();
+        ctxt.generateJavaSource("for (int " + index + " = ");
+        ctxt.generateAttribute("begin");
+        ctxt.generateJavaSource("; " + index + " <= ");
+        ctxt.generateAttribute("end");
+        if (hasStep) {
+            ctxt.generateJavaSource("; " + index + "+=");
+            ctxt.generateAttribute("step");
+            ctxt.generateJavaSource(") {");
+        }
+        else {
+            ctxt.generateJavaSource("; " + index + "++) {");
+        }
+        
+        // If var is specified and the body contains an EL, then sycn
+        // the var attribute
+        if (hasVar /* && ctxt.hasEL() */) {
+            ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
+            ctxt.generateAttribute("var");
+            ctxt.generateJavaSource(", String.valueOf(" + index + "));");
+        }
+        ctxt.generateBody();
+        ctxt.generateJavaSource("}");
+    }
+    
+    /**
+     * Generate codes for Collections
+     * The pseudo code is:
+     */
+    private void doCollection(TagPluginContext ctxt) {
+        
+        ctxt.generateImport("java.util.*");
+        generateIterators(ctxt);
+        
+        String itemsV = ctxt.getTemporaryVariableName();
+        ctxt.generateJavaSource("Object " + itemsV + "= ");
+        ctxt.generateAttribute("items");
+        ctxt.generateJavaSource(";");
+        
+        String indexV=null, beginV=null, endV=null, stepV=null;
+        if (hasBegin) {
+            beginV = ctxt.getTemporaryVariableName();
+            ctxt.generateJavaSource("int " + beginV + " = ");
+            ctxt.generateAttribute("begin");
+            ctxt.generateJavaSource(";");
+        }
+        if (hasEnd) {
+            indexV = ctxt.getTemporaryVariableName();
+            ctxt.generateJavaSource("int " + indexV + " = 0;");
+            endV = ctxt.getTemporaryVariableName();
+            ctxt.generateJavaSource("int " + endV + " = ");
+            ctxt.generateAttribute("end");
+            ctxt.generateJavaSource(";");
+        }
+        if (hasStep) {
+            stepV = ctxt.getTemporaryVariableName();
+            ctxt.generateJavaSource("int " + stepV + " = ");
+            ctxt.generateAttribute("step");
+            ctxt.generateJavaSource(";");
+        }
+        
+        String iterV = ctxt.getTemporaryVariableName();
+        ctxt.generateJavaSource("Iterator " + iterV + " = null;");
+        // Object[]
+        ctxt.generateJavaSource("if (" + itemsV + " instanceof Object[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((Object[])" + itemsV + ");");
+        // boolean[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof boolean[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((boolean[])" + itemsV + ");");
+        // byte[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof byte[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((byte[])" + itemsV + ");");
+        // char[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof char[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((char[])" + itemsV + ");");
+        // short[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof short[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((short[])" + itemsV + ");");
+        // int[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof int[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((int[])" + itemsV + ");");
+        // long[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof long[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((long[])" + itemsV + ");");
+        // float[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof float[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((float[])" + itemsV + ");");
+        // double[]
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof double[])");
+        ctxt.generateJavaSource(iterV + "=toIterator((double[])" + itemsV + ");");
+        
+        // Collection
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof Collection)");
+        ctxt.generateJavaSource(iterV + "=((Collection)" + itemsV + ").iterator();");
+        
+        // Iterator
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof Iterator)");
+        ctxt.generateJavaSource(iterV + "=(Iterator)" + itemsV + ";");
+        
+        // Enumeration
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof Enumeration)");
+        ctxt.generateJavaSource(iterV + "=toIterator((Enumeration)" + itemsV + ");");
+        
+        // Map
+        ctxt.generateJavaSource("else if (" + itemsV + " instanceof Map)");
+        ctxt.generateJavaSource(iterV + "=((Map)" + itemsV + ").entrySet().iterator();");
+        
+        if (hasBegin) {
+            String tV = ctxt.getTemporaryVariableName();
+            ctxt.generateJavaSource("for (int " + tV + "=" + beginV + ";" +
+                    tV + ">0 && " + iterV + ".hasNext(); " +
+                    tV + "--)");
+            ctxt.generateJavaSource(iterV + ".next();");
+        }
+        
+        ctxt.generateJavaSource("while (" + iterV + ".hasNext()){");
+        if (hasVar) {
+            ctxt.generateJavaSource("_jspx_page_context.setAttribute(");
+            ctxt.generateAttribute("var");
+            ctxt.generateJavaSource(", " + iterV + ".next());");
+        }
+        
+        ctxt.generateBody();
+        
+        if (hasStep) {
+            String tV = ctxt.getTemporaryVariableName();
+            ctxt.generateJavaSource("for (int " + tV + "=" + stepV + "-1;" +
+                    tV + ">0 && " + iterV + ".hasNext(); " +
+                    tV + "--)");
+            ctxt.generateJavaSource(iterV + ".next();");
+        }
+        if (hasEnd) {
+            if (hasStep) {
+                ctxt.generateJavaSource(indexV + "+=" + stepV + ";");
+            }
+            else {
+                ctxt.generateJavaSource(indexV + "++;");
+            }
+            if (hasBegin) {
+                ctxt.generateJavaSource("if(" + beginV + "+" + indexV +
+                        ">"+ endV + ")");
+            }
+            else {
+                ctxt.generateJavaSource("if(" + indexV + ">" + endV + ")");
+            }
+            ctxt.generateJavaSource("break;");
+        }
+        ctxt.generateJavaSource("}");	// while
+    }
+    
+    /**
+     * Generate iterators for data types supported in items
+     */
+    private void generateIterators(TagPluginContext ctxt) {
+        
+        // Object[]
+        ctxt.generateDeclaration("ObjectArrayIterator", 
+                "private Iterator toIterator(final Object[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return a[index++];}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // boolean[]
+        ctxt.generateDeclaration("booleanArrayIterator", 
+                "private Iterator toIterator(final boolean[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Boolean(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // byte[]
+        ctxt.generateDeclaration("byteArrayIterator", 
+                "private Iterator toIterator(final byte[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Byte(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // char[]
+        ctxt.generateDeclaration("charArrayIterator", 
+                "private Iterator toIterator(final char[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Character(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // short[]
+        ctxt.generateDeclaration("shortArrayIterator", 
+                "private Iterator toIterator(final short[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Short(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // int[]
+        ctxt.generateDeclaration("intArrayIterator", 
+                "private Iterator toIterator(final int[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Integer(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // long[]
+        ctxt.generateDeclaration("longArrayIterator", 
+                "private Iterator toIterator(final long[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Long(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // float[]
+        ctxt.generateDeclaration("floatArrayIterator",
+                "private Iterator toIterator(final float[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Float(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // double[]
+        ctxt.generateDeclaration("doubleArrayIterator",
+                "private Iterator toIterator(final double[] a){\n" +
+                "  return (new Iterator() {\n" +
+                "    int index=0;\n" +
+                "    public boolean hasNext() {\n" +
+                "      return index < a.length;}\n" +
+                "    public Object next() {\n" +
+                "      return new Double(a[index++]);}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+        // Enumeration
+        ctxt.generateDeclaration("enumIterator",
+                "private Iterator toIterator(final Enumeration e){\n" +
+                "  return (new Iterator() {\n" +
+                "    public boolean hasNext() {\n" +
+                "      return e.hasMoreElements();}\n" +
+                "    public Object next() {\n" +
+                "      return e.nextElement();}\n" +
+                "    public void remove() {}\n" +
+                "  });\n" +
+                "}"
+        );
+        
+    }
+}



Mime
View raw message