After discussion with Howard Moore on struts-user ("FormTag Problem"), I 
have attached my copy of FormTag.java, based on revision 1.2.

This allows you to have jsps and actions in a subdirectory of the context 
root, i.e.

If http://<somehost>/myapp/admin/logon.jsp contains:
         <html:form action="logon.do" ...>
the action mapping becomes "/admin/logon", and 
the html contains: action="logon.do"

And if http://<somehost>/myapp/admin/logon.jsp contains:
         <html:form action="/admin/logon.do" ...>
the action mapping becomes "/admin/logon", and 
the html contains: action="/myapp/admin/logon.do"

Without the change, all jsps have to be in the root of the web app.

The change works for extension mapping but not prefix mapping as I don't 
believe there is a way for the tag to find out the prefix being used.

Chris Smith
/*
 * $Header: 
/home/cvspublic/jakarta-struts/src/share/org/apache/struts/taglib/html/FormTag.java,v 
1.2 2001/01/07 04:37:06 craigmcc Exp $
 * $Revision: 1.2 $
 * $Date: 2001/01/07 04:37:06 $
 *
 * ====================================================================
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact [EMAIL PROTECTED]
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */


package org.apache.struts.taglib.html;


import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionFormBean;
import org.apache.struts.action.ActionFormBeans;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMappings;
import org.apache.struts.util.BeanUtils;
import org.apache.struts.util.MessageResources;


/**
 * Custom tag that represents an input form, associated with a bean whose
 * properties correspond to the various fields of the form.
 *
 * @author Craig R. McClanahan
 * @version $Revision: 1.2 $ $Date: 2001/01/07 04:37:06 $
 */

public class FormTag extends TagSupport {


    // ----------------------------------------------------- Instance Variables


    /**
     * The action URL to which this form should be submitted, if any.
     */
    protected String action = null;


    /**
     * The content encoding to be used on a POST submit.
     */
    protected String enctype = null;

    public String getEnctype() {
        return (this.enctype);
    }

    public void setEnctype(String enctype) {
        this.enctype = enctype;
    }


    /**
     * The name of the field to receive focus, if any.
     */
    protected String focus = null;


    /**
     * The message resources for this package.
     */
    protected static MessageResources messages =
     MessageResources.getMessageResources(Constants.Package + ".LocalStrings");


    /**
     * The request method used when submitting this form.
     */
    protected String method = "POST";


    /**
     * The attribute key under which our associated bean is stored.
     */
    protected String name = null;


    /**
     * The onReset event script.
     */
    protected String onreset = null;


    /**
     * The onSubmit event script.
     */
    protected String onsubmit = null;


    /**
     * The scope (request or session) under which our associated bean
     * is stored.
     */
    protected String scope = "session";


    /**
     * The style attribute associated with this tag.
     */
    protected String style = null;


    /**
     * The style class associated with this tag.
     */
    protected String styleClass = null;


    /**
     * The window target.
     */
    protected String target = null;


    /**
     * The Java class name of the bean to be created, if necessary.
     */
    protected String type = null;


    // ------------------------------------------------------------- Properties

    /**
     * Returns a form action converted into an action mapping path.
     * Anything after a period (".") is considered a name extension and ignored.
     * If the action doesn't begin with a forward slash ("/"), the path part of 
     * the servlet path is prepended, giving you a path below the context path.
     */
    protected String getActionMappingName() {
        String retString = action;
        int period = action.lastIndexOf(".");
        if (period > -1) {
            retString = action.substring(0, period);
        }
        if (retString.charAt(0) != '/') {
            String servletPath = 
((HttpServletRequest)pageContext.getRequest()).getServletPath();
            int slash = servletPath.lastIndexOf("/");
            retString = servletPath.substring(0, slash + 1) + retString;
        }
        return retString;
    }

    /**
     * Returns a form action converted into a url.
     * If the action begins with a forward slash ("/"), the context path is 
     * prepended, otherwise the action is returned unchanged.
     */
    protected String getActionURL() {
        String retString = action;
        if (action.charAt(0) == '/') {
            retString = ((HttpServletRequest) 
pageContext.getRequest()).getContextPath() +
                retString;
        }
        return retString;
    }
    
    
    /**
     * Return the action URL to which this form should be submitted.
     */
    public String getAction() {

        return (this.action);

    }


    /**
     * Set the action URL to which this form should be submitted.
     *
     * @param action The new action URL
     */
    public void setAction(String action) {

        this.action = action;

    }


    /**
     * Return the focus field name for this form.
     */
    public String getFocus() {

        return (this.focus);

    }


    /**
     * Set the focus field name for this form.
     *
     * @param focus The new focus field name
     */
    public void setFocus(String focus) {

        this.focus = focus;

    }


    /**
     * Return the request method used when submitting this form.
     */
    public String getMethod() {

        return (this.method);

    }


    /**
     * Set the request method used when submitting this form.
     *
     * @param method The new request method
     */
    public void setMethod(String method) {

        this.method = method;

    }


    /**
     * Return the attribute key name of our bean.
     */
    public String getName() {

        return (this.name);

    }


    /**
     * Set the attribute key name of our bean.
     *
     * @param name The new attribute key name
     */
    public void setName(String name) {

        this.name = name;

    }


    /**
     * Return the onReset event script.
     */
    public String getOnreset() {

        return (this.onreset);

    }


    /**
     * Set the onReset event script.
     *
     * @param onReset The new event script
     */
    public void setOnreset(String onReset) {

        this.onreset = onReset;

    }


    /**
     * Return the onSubmit event script.
     */
    public String getOnsubmit() {

        return (this.onsubmit);

    }


    /**
     * Set the onSubmit event script.
     *
     * @param onSubmit The new event script
     */
    public void setOnsubmit(String onSubmit) {

        this.onsubmit = onSubmit;

    }


    /**
     * Return the attribute scope of our bean.
     */
    public String getScope() {

        return (this.scope);

    }


    /**
     * Set the attribute scope of our bean.
     *
     * @param scope The new attribute scope
     */
    public void setScope(String scope) {

        this.scope = scope;

    }


    /**
     * Return the style attribute for this tag.
     */
    public String getStyle() {

        return (this.style);

    }


    /**
     * Set the style attribute for this tag.
     *
     * @param style The new style attribute
     */
    public void setStyle(String style) {

        this.style = style;

    }


    /**
     * Return the style class for this tag.
     */
    public String getStyleClass() {

        return (this.styleClass);

    }


    /**
     * Set the style class for this tag.
     *
     * @param styleClass The new style class
     */
    public void setStyleClass(String styleClass) {

        this.styleClass = styleClass;

    }


    /**
     * Return the window target.
     */
    public String getTarget() {

        return (this.target);

    }


    /**
     * Set the window target.
     *
     * @param target The new window target
     */
    public void setTarget(String target) {

        this.target = target;

    }


    /**
     * Return the Java class of our bean.
     */
    public String getType() {

        return (this.type);

    }


    /**
     * Set the Java class of our bean.
     *
     * @param type The new Java class
     */
    public void setType(String type) {

        this.type = type;

    }


    // --------------------------------------------------------- Public Methods


    /**
     * Render the beginning of this form.
     *
     * @exception JspException if a JSP exception has occurred
     */
    public int doStartTag() throws JspException {

        //get unspecified values
        if ((name == null) || (type == null)) {
            //get ActionMapping specified by "action"
            ActionMappings mappings = (ActionMappings)
                 pageContext.getAttribute(Action.MAPPINGS_KEY,
                                          PageContext.APPLICATION_SCOPE);
            ActionFormBeans formBeans = (ActionFormBeans)
                pageContext.getAttribute(Action.FORM_BEANS_KEY,
                                         PageContext.APPLICATION_SCOPE);
            if ((mappings != null) && (formBeans != null)) {
              String actionMappingName = getActionMappingName();
              ActionMapping mapping = mappings.findMapping(actionMappingName); 
            
              if (mapping != null) {
                  this.scope = mapping.getScope();
                  if (name == null) {
                    this.name = mapping.getAttribute();
                  }
                  if (type == null) {
                    ActionFormBean formBean =
                        formBeans.findFormBean(mapping.getName());
                    if (formBean != null)
                        this.type = formBean.getType();
                  }
                }
                else {
                    throw new JspTagException("Cannot retrieve mapping for specified 
form " +
                        "action path \"" + actionMappingName + "\"");
                }
            }
            else {
                throw new JspTagException("Cannot retrieve ActionMappings under key 
\"" + 
                    Action.MAPPINGS_KEY + "\"");
            }
        }

        // Create an appropriate "form" element based on our parameters
        HttpServletResponse response =
          (HttpServletResponse) pageContext.getResponse();
        StringBuffer results = new StringBuffer("<form");
        results.append(" name=\"");
        results.append(name);
        results.append("\"");
        results.append(" method=\"");
        results.append(method);
        results.append("\"");
        if (action != null) {
            results.append(" action=\"");
            results.append(response.encodeURL(BeanUtils.filter(getActionURL())));
            results.append("\"");
        }
        if (styleClass != null) {
            results.append(" class=\"");
            results.append(styleClass);
            results.append("\"");
        }
        if (enctype != null) {
            results.append(" enctype=\"");
            results.append(enctype);
            results.append("\"");
        }
        if (onreset != null) {
            results.append(" onreset=\"");
            results.append(onreset);
            results.append("\"");
        }
        if (onsubmit != null) {
            results.append(" onsubmit=\"");
            results.append(onsubmit);
            results.append("\"");
        }
        if (style != null) {
            results.append(" style=\"");
            results.append(style);
            results.append("\"");
        }
        if (target != null) {
            results.append(" target=\"");
            results.append(target);
            results.append("\"");
        }
        results.append(">");

        // Add a transaction token (if present in our session)
        HttpSession session = pageContext.getSession();
        if (session != null) {
            String token =
                (String) session.getAttribute(Action.TRANSACTION_TOKEN_KEY);
            if (token != null) {
                results.append("<input type=\"hidden\" name=\"");
                results.append(Constants.TOKEN_KEY);
                results.append("\" value=\"");
                results.append(token);
                results.append("\">");
            }
        }

        // Print this field to our output writer
        JspWriter writer = pageContext.getOut();
        try {
            writer.print(results.toString());
        } catch (IOException e) {
            throw new JspException
                (messages.getMessage("common.io", e.toString()));
        }

        // Store this tag itself as a page attribute
        pageContext.setAttribute(Constants.FORM_KEY, this);
        
        // Locate or create the bean associated with our form
        int scope = PageContext.SESSION_SCOPE;
        if ("request".equals(this.scope))
            scope = PageContext.REQUEST_SCOPE;
        Object bean = pageContext.getAttribute(name, scope);
        if (bean == null) {
            if (type == null)
                throw new JspException
                    (messages.getMessage("getter.bean", name));
            try {
                Class clazz = Class.forName(type);
                bean = clazz.newInstance();
            } catch (Exception e) {
                throw new JspException
                    (messages.getMessage("formTag.create", type,
                                         e.toString()));
            }
            pageContext.setAttribute(name, bean, scope);
        }
        pageContext.setAttribute(Constants.BEAN_KEY, bean);

        // Continue processing this page
        return (EVAL_BODY_INCLUDE);

    }


    /**
     * Render the end of this form.
     *
     * @exception JspException if a JSP exception has occurred
     */
    public int doEndTag() throws JspException {

        // Remove the page scope attributes we created
        pageContext.removeAttribute(Constants.BEAN_KEY);
        pageContext.removeAttribute(Constants.FORM_KEY);

        // Render a tag representing the end of our current form
        StringBuffer results = new StringBuffer("</form>");
        if (focus != null) {
            results.append("\r\n");
            results.append("<script language=\"JavaScript\">\r\n");
            results.append("  <!--\r\n");
            results.append("    document.");
            results.append(name);
            results.append(".");
            results.append(focus);
            results.append(".focus()\r\n");
            results.append("  // -->\r\n");
            results.append("</script>\r\n");
        }

        // Print this value to our output writer
        JspWriter writer = pageContext.getOut();
        try {
            writer.print(results.toString());
        } catch (IOException e) {
            throw new JspException
                (messages.getMessage("common.io", e.toString()));
        }

        // Continue processing this page
        return (EVAL_PAGE);

    }


    /**
     * Release any acquired resources.
     */
    public void release() {

        super.release();
        action = null;
        enctype = null;
        focus = null;
        method = "POST";
        name = null;
        onreset = null;
        onsubmit = null;
        scope = "session";
        style = null;
        styleClass = null;
        target = null;
        type = null;

    }


}

Reply via email to