⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linktool.java

📁 一个用于java web页面开发的开源包
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package org.apache.velocity.tools.view.tools;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
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.velocity.tools.generic.ValueParser;
import org.apache.velocity.tools.view.context.ViewContext;
import org.apache.velocity.tools.view.servlet.ServletUtils;

/**
 * View tool to make building URIs pleasant and fun!
 * <p><pre>
 * Template example(s):
 *   #set( $base = $link.relative('MyPage.vm').anchor('view') )
 *   &lt;a href="$base.param('select','this')"&gt;this&lt;/a&gt;
 *   &lt;a href="$base.param('select','that')"&gt;that&lt;/a&gt;
 *
 * Toolbox configuration:
 * &lt;tool&gt;
 *   &lt;key&gt;link&lt;/key&gt;
 *   &lt;scope&gt;request&lt;/scope&gt;
 *   &lt;class&gt;org.apache.velocity.tools.view.tools.LinkTool&lt;/class&gt;
 * &lt;/tool&gt;
 * </pre></p>
 *
 * <p>This tool should only be used in the request scope.</p>
 *
 * @author <a href="mailto:sidler@teamup.com">Gabe Sidler</a>
 * @author Nathan Bubna
 * @since VelocityTools 1.0
 * @version $Id: LinkTool.java 485175 2006-12-10 12:52:56Z henning $
 */
public class LinkTool implements Cloneable
{
    protected static final Log LOG = LogFactory.getLog(LinkTool.class);

    /**
     * Parameter key for configuring {@link #setSelfAbsolute} state
     * @since VelocityTools 1.3
     */
    public static final String SELF_ABSOLUTE_KEY = "self-absolute";

    /**
     * Parameter key for configuring {@link #setSelfIncludeParameters} state
     * @since VelocityTools 1.3
     */
    public static final String SELF_INCLUDE_PARAMETERS_KEY = "self-include-parameters";

    /** Standard HTML delimiter for query data ('&') */
    public static final String HTML_QUERY_DELIMITER = "&";

    /** XHTML delimiter for query data ('&amp;amp;') */
    public static final String XHTML_QUERY_DELIMITER = "&amp;";


    /** A reference to the ServletContext */
    protected ServletContext application;

    /** A reference to the HttpServletRequest. */
    protected HttpServletRequest request;

    /** A reference to the HttpServletResponse. */
    protected HttpServletResponse response;


    /** The URI reference set for this link. */
    private String uri;

    /** The anchor set for this link. */
    private String anchor;

    /** A list of query string parameters. */
    private ArrayList queryData;

    /** The current delimiter for query data */
    private String queryDataDelim;

    /** The self-absolute status */
    private boolean selfAbsolute;

    /** The self-include-parameters status */
    private boolean selfParams;


    /** Java 1.4 encode method to use instead of deprecated 1.3 version. */
    private static Method encode = null;

    /* Initialize the encode variable with the 1.4 method if available.
     * this code was adapted from org.apache.struts.utils.RequestUtils */
    static
    {
        try
        {
            /* get version of encode method with two String args  */
            Class[] args = new Class[] { String.class, String.class };
            encode = URLEncoder.class.getMethod("encode", args);
        }
        catch (NoSuchMethodException e)
        {
            LOG.debug("Can't find JDK 1.4 encode method. Using JDK 1.3 version.");
        }
    }


    /**
     * Default constructor. Tool must be initialized before use.
     */
    public LinkTool()
    {
        uri = null;
        anchor = null;
        queryData = null;
        queryDataDelim = HTML_QUERY_DELIMITER;
        selfAbsolute = false;
        selfParams = false;
    }


    // --------------------------------------- Protected Methods -------------

    /**
     * <p>Controls the delimiter used for separating query data pairs.
     *    By default, the standard '&' character is used.</p>
     * <p>This is not exposed to templates as this decision is best not
     *    made at that level.</p>
     * <p>Subclasses may easily override the init() method to set this
     *    appropriately and then call super.init()</p>
     *
     * @param useXhtml if true, the XHTML query data delimiter ('&amp;amp;')
     *        will be used.  if false, then '&' will be used.
     * @see <a href="http://www.w3.org/TR/xhtml1/#C_12">Using Ampersands in Attribute Values (and Elsewhere)</a>
     */
    protected void setXhtml(boolean useXhtml)
    {
        queryDataDelim =
            (useXhtml) ? XHTML_QUERY_DELIMITER : HTML_QUERY_DELIMITER;
    }

    /**
     * <p>Controls whether or not the {@link #getSelf()} method will return
     *    a duplicate with a URI in absolute or relative form.</p>
     *
     * @param selfAbsolute if true, the {@link #getSelf()} method will return
     *        a duplicate of this tool with an absolute self-referencing URI;
     *        if false, a duplicate with a relative self-referencing URI will
     *        be returned
     * @see #getSelf()
     * @since VelocityTools 1.3
     */
    protected void setSelfAbsolute(boolean selfAbsolute)
    {
        this.selfAbsolute = selfAbsolute;
    }

    /**
     * <p>Controls whether or not the {@link #getSelf()} method will return
     *    a duplicate that includes current request parameters.</p>
     *
     * @param selfParams if true, the {@link #getSelf()} method will return
     *        a duplicate of this tool that includes current request parameters
     * @see #getSelf()
     * @since VelocityTools 1.3
     */
    protected void setSelfIncludeParameters(boolean selfParams)
    {
        this.selfParams = selfParams;
    }


    /**
     * For internal use.
     *
     * Copies 'that' LinkTool into this one and adds the new query data.
     *
     * @param pair the query parameter to add
     */
    protected LinkTool copyWith(QueryPair pair)
    {
        LinkTool copy = duplicate();
        if (copy.queryData != null)
        {
            // set the copy's query data to a shallow clone of
            // the current query data array
            copy.queryData = (ArrayList)this.queryData.clone();
        }
        else
        {
            copy.queryData = new ArrayList();
        }
        //add new pair to this LinkTool's query data
        copy.queryData.add(pair);
        return copy;
    }


    /**
     * For internal use.
     *
     * Copies 'that' LinkTool into this one and adds the new query data.
     *
     * @param newQueryData the query parameters to add
     * @since VelocityTools 1.3
     */
    protected LinkTool copyWith(Map newQueryData)
    {
        LinkTool copy = duplicate();
        if (copy.queryData != null)
        {
            // set the copy's query data to a shallow clone of
            // the current query data array
            copy.queryData = (ArrayList)this.queryData.clone();
        }
        else
        {
            copy.queryData = new ArrayList();
        }
        for (Iterator i = newQueryData.keySet().iterator(); i.hasNext(); )
        {
            Object key = i.next();
            Object value = newQueryData.get(key);
            copy.queryData.add(new QueryPair(String.valueOf(key), value));
        }
        return copy;
    }


    /**
     * For internal use.
     *
     * Copies 'that' LinkTool into this one and sets the new URI.
     *
     * @param uri uri string
     */
    protected LinkTool copyWith(String uri)
    {
        LinkTool copy = duplicate();
        copy.uri = uri;
        return copy;
    }


    /**
     * For internal use.
     *
     * Copies 'that' LinkTool into this one and sets the new
     * anchor for the link.
     *
     * @param anchor URI string
     */
    protected LinkTool copyWithAnchor(String anchor)
    {
        LinkTool copy = duplicate();
        copy.anchor = anchor;
        return copy;
    }


    /**
     * This is just to avoid duplicating this code for both copyWith() methods
     */
    protected LinkTool duplicate()
    {
        try
        {
            return (LinkTool)this.clone();
        }
        catch (CloneNotSupportedException e)
        {
            LOG.warn("Could not properly clone " + getClass() + " - " + e);

            // "clone" manually
            LinkTool copy;
            try
            {
                // one last try for a subclass instance...
                copy = (LinkTool)getClass().newInstance();
            }
            catch (Exception ee)
            {
                // fine, we'll use the base class
                copy = new LinkTool();
            }
            copy.application = this.application;
            copy.request = this.request;
            copy.response = this.response;
            copy.uri = this.uri;
            copy.anchor = this.anchor;
            copy.queryData = this.queryData;
            copy.queryDataDelim = this.queryDataDelim;
            copy.selfAbsolute = this.selfAbsolute;
            copy.selfParams = this.selfParams;
            return copy;
        }
    }


    // --------------------------------------- Toolbox Methods -------------

    /**
     * Configures this tool
     *
     * @param params Map of configuration parameters
     * @since VelocityTools 1.3
     */
    public void configure(Map params)
    {
        ValueParser parser = new ValueParser(params);
        Boolean selfAbsolute = parser.getBoolean(SELF_ABSOLUTE_KEY);
        if (selfAbsolute != null)
        {
            setSelfAbsolute(selfAbsolute.booleanValue());
        }
        Boolean selfParams = parser.getBoolean(SELF_INCLUDE_PARAMETERS_KEY);
        if (selfParams != null)
        {
            setSelfIncludeParameters(selfParams.booleanValue());
        }
    }

    /**
     * Initializes this tool.
     *
     * @param obj the current ViewContext
     * @throws IllegalArgumentException if the param is not a ViewContext
     */
    public void init(Object obj)
    {
        if (!(obj instanceof ViewContext))
        {
            throw new IllegalArgumentException("Tool can only be initialized with a ViewContext");
        }

        ViewContext context = (ViewContext)obj;
        this.request = context.getRequest();
        this.response = context.getResponse();
        this.application = context.getServletContext();
        Boolean b = (Boolean)context.getAttribute(ViewContext.XHTML);
        if (b != null)
        {
            setXhtml(b.booleanValue());
        }
    }


    // --------------------------------------------- Template Methods -----------

    /**
     * <p>Returns a copy of the link with the specified anchor to be
     *    added to the end of the generated hyperlink.</p>
     *
     * Example:<br>
     * <code>&lt;a href='$link.setAnchor("foo")'&gt;Foo&lt;/a&gt;</code><br>
     * produces something like</br>
     * <code>&lt;a href="#foo"&gt;Foo&lt;/a&gt;</code><br>
     *
     * @param anchor an internal document reference
     *
     * @return a new instance of LinkTool with the set anchor
     */
    public LinkTool setAnchor(String anchor)
    {
        return copyWithAnchor(anchor);
    }

    /**
     * Convenience method equivalent to {@link #setAnchor}.
     * @since VelocityTools 1.3
     */
    public LinkTool anchor(String anchor)
    {
        return setAnchor(anchor);
    }

    /**
     * Returns the anchor (internal document reference) set for this link.
     */
    public String getAnchor()
    {
        return anchor;
    }


    /**
     * <p>Returns a copy of the link with the specified context-relative
     * URI reference converted to a server-relative URI reference. This
     * method will overwrite any previous URI reference settings but will
     * copy the query string.</p>
     *
     * Example:<br>
     * <code>&lt;a href='$link.setRelative("/templates/login/index.vm")'&gt;Login Page&lt;/a&gt;</code><br>
     * produces something like</br>
     * <code>&lt;a href="/myapp/templates/login/index.vm"&gt;Login Page&lt;/a&gt;</code><br>
     *
     * @param uri A context-relative URI reference. A context-relative URI
     * is a URI that is relative to the root of this web application.
     *
     * @return a new instance of LinkTool with the specified URI
     */
    public LinkTool setRelative(String uri)
    {
        String ctxPath = request.getContextPath();
        /* if the context path is the webapp root */
        if (ctxPath.equals("/"))
        {
            /* then don't append anything for it */
            ctxPath = "";
        }
        if (uri.startsWith("/"))
        {
            return copyWith(ctxPath + uri);
        }
        else
        {
            return copyWith(ctxPath + '/' + uri);
        }
    }

    /**
     * Convenience method equivalent to {@link #setRelative}.
     * @since VelocityTools 1.3
     */
    public LinkTool relative(String uri)
    {
        return setRelative(uri);
    }


    /**
     * <p>Returns a copy of the link with the specified URI reference
     * either used as or converted to an absolute (non-relative)
     * URI reference. This method will overwrite any previous URI
     * reference settings but will copy the query string.</p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -