    001package org.apache.turbine.services.pull.tools;
    002
    003
    004/*
    005 * Licensed to the Apache Software Foundation (ASF) under one
    006 * or more contributor license agreements.  See the NOTICE file
    007 * distributed with this work for additional information
    008 * regarding copyright ownership.  The ASF licenses this file
    009 * to you under the Apache License, Version 2.0 (the
    010 * "License"); you may not use this file except in compliance
    011 * with the License.  You may obtain a copy of the License at
    012 *
    013 *   http://www.apache.org/licenses/LICENSE-2.0
    014 *
    015 * Unless required by applicable law or agreed to in writing,
    016 * software distributed under the License is distributed on an
    017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    018 * KIND, either express or implied.  See the License for the
    019 * specific language governing permissions and limitations
    020 * under the License.
    021 */
    022
    023
    024import org.apache.commons.configuration.Configuration;
    025import org.apache.commons.logging.Log;
    026import org.apache.commons.logging.LogFactory;
    027import org.apache.fulcrum.parser.ParameterParser;
    028import org.apache.turbine.Turbine;
    029import org.apache.turbine.pipeline.PipelineData;
    030import org.apache.turbine.services.pull.ApplicationTool;
    031import org.apache.turbine.util.RunData;
    032import org.apache.turbine.util.uri.TemplateURI;
    033
    034/**
    035 * This is a pull to to be used in Templates to convert links in
    036 * Templates into the correct references.
    037 *
    038 * The pull service might insert this tool into the Context.
    039 * in templates.  Here's an example of its Velocity use:
    040 *
    041 * <p><code>
    042 * $link.setPage("index.vm").addPathInfo("hello","world")
    043 * This would return: http://foo.com/Turbine/template/index.vm/hello/world
    044 * </code>
    045 *
    046 * <p>
    047 *
    048 * This is an application pull tool for the template system. You should <b>not</b>
    049 * use it in a normal application!
    050 *
    051 * @author <a href="mbryson@mont.mindspring.com">Dave Bryson</a>
    052 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
    053 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    054 * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    055 * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
    056 * @version $Id: TemplateLink.java 1706239 2015-10-01 13:18:35Z tv $
    057 */
    058
    059public class TemplateLink
    060    implements ApplicationTool
    061{
    062    /** Prefix for Parameters for this tool */
    063    public static final String TEMPLATE_LINK_PREFIX = "tool.link";
    064
    065    /** Should this tool return relative URIs or absolute? Default: Absolute. */
    066    public static final String TEMPLATE_LINK_RELATIVE_KEY = "want.relative";
    067
    068    /** Default Value for TEMPLATE_LINK_RELATIVE_KEY */
    069    public static final boolean TEMPLATE_LINK_RELATIVE_DEFAULT = false;
    070
    071
    072    /** Do we want a relative link? */
    073    protected boolean wantRelative = false;
    074
    075    /** cache of the template name for getPage() */
    076    protected String template = null;
    077
    078    /** TemplateURI used as backend for this object */
    079    protected TemplateURI templateURI = null;
    080
    081    /** Logging */
    082    private static Log log = LogFactory.getLog(TemplateLink.class);
    083
    084    /**
    085     * Default constructor
    086     * <p>
    087     * The init method must be called before use.
    088     */
    089    public TemplateLink()
    090    {
    091        // empty
    092    }
    093
    094    /*
    095     * ========================================================================
    096     *
    097     * Application Tool Interface
    098     *
    099     * ========================================================================
    100     *
    101     */
    102
    103    /**
    104     * This will initialize a TemplateLink object that was
    105     * constructed with the default constructor (ApplicationTool
    106     * method).
    107     *
    108     * @param data assumed to be a PipelineData object
    109     */
    110    @Override
    111    public void init(Object data)
    112    {
    113        // we just blithely cast to RunData as if another object
    114        // or null is passed in we'll throw an appropriate runtime
    115        // exception.
    116        if (data instanceof PipelineData)
    117        {
    118            PipelineData pipelineData = (PipelineData) data;
    119            RunData runData = (RunData)pipelineData;
    120            templateURI = new TemplateURI(runData);
    121        }
    122        else
    123        {
    124            templateURI = new TemplateURI((RunData) data);
    125        }
    126
    127        Configuration conf =
    128                Turbine.getConfiguration().subset(TEMPLATE_LINK_PREFIX);
    129
    130        if (conf != null)
    131        {
    132            wantRelative = conf.getBoolean(TEMPLATE_LINK_RELATIVE_KEY,
    133                    TEMPLATE_LINK_RELATIVE_DEFAULT);
    134        }
    135
    136    }
    137
    138    /**
    139     * Refresh method - does nothing
    140     */
    141    @Override
    142    public void refresh()
    143    {
    144        // empty
    145    }
    146
    147    /*
    148     * ========================================================================
    149     *
    150     * getter/setter
    151     *
    152     * All setter return "this" so you can "chain" them together in the Context
    153     *
    154     * ========================================================================
    155     */
    156
    157    /**
    158     * This will turn off the execution of res.encodeURL()
    159     * by making res == null. This is a hack for cases
    160     * where you don't want to see the session information
    161     *
    162     * @return A <code>TemplateLink</code> (self).
    163     */
    164    public TemplateLink setEncodeURLOff()
    165    {
    166        templateURI.clearResponse();
    167        return this;
    168    }
    169
    170    /**
    171     * Sets the template variable used by the Template Service.
    172     *
    173     * @param template A String with the template name.
    174     * @return A TemplateLink.
    175     */
    176    public TemplateLink setPage(String template)
    177    {
    178        log.debug("setPage(" + template + ")");
    179        this.template = template;
    180        templateURI.setTemplate(template);
    181        return this;
    182    }
    183
    184    /**
    185     * Gets the template variable used by the Template Service.
    186     * It is only available after setPage() has been called.
    187     *
    188     * @return The template name.
    189     */
    190    public String getPage()
    191    {
    192        return template;
    193    }
    194
    195    /**
    196     * Sets the action= value for this URL.
    197     *
    198     * By default it adds the information to the path_info instead
    199     * of the query data.
    200     *
    201     * @param action A String with the action value.
    202     * @return A <code>TemplateLink</code> (self).
    203     */
    204    public TemplateLink setAction(String action)
    205    {
    206        log.debug("setAction(" + action + ")");
    207        templateURI.setAction(action);
    208        return this;
    209    }
    210
    211    /**
    212     * Sets the action= and eventSubmit= values for this URL.
    213     *
    214     * By default it adds the information to the path_info instead
    215     * of the query data.
    216     *
    217     * @param action A String with the action value.
    218     * @param event A string with the event name.
    219     * @return A <code>TemplateLink</code> (self).
    220     */
    221    public TemplateLink setActionEvent(String action, String event)
    222    {
    223        log.debug("setActionEvent(" + action + ", "+ event +")");
    224        templateURI.setActionEvent(action, event);
    225        return this;
    226    }
    227
    228    /**
    229     * Sets the screen= value for this URL.
    230     *
    231     * By default it adds the information to the path_info instead
    232     * of the query data.
    233     *
    234     * @param screen A String with the screen value.
    235     * @return A <code>TemplateLink</code> (self).
    236     */
    237    public TemplateLink setScreen(String screen)
    238    {
    239        log.debug("setScreen(" + screen + ")");
    240        templateURI.setScreen(screen);
    241        return this;
    242    }
    243
    244    /**
    245     * Sets a reference anchor (#ref).
    246     *
    247     * @param reference A String containing the reference.
    248     * @return A <code>TemplateLink</code> (self).
    249     */
    250    public TemplateLink setReference(String reference)
    251    {
    252        templateURI.setReference(reference);
    253        return this;
    254    }
    255
    256    /**
    257     * Returns the current reference anchor.
    258     *
    259     * @return A String containing the reference.
    260     */
    261    public String getReference()
    262    {
    263        return templateURI.getReference();
    264    }
    265
    266    /*
    267     * ========================================================================
    268     *
    269     * Adding and removing Data from the Path Info and Query Data
    270     *
    271     * ========================================================================
    272     */
    273
    274
    275    /**
    276     * Adds a name=value pair for every entry in a ParameterParser
    277     * object to the path_info string.
    278     *
    279     * @param pp A ParameterParser.
    280     * @return A <code>TemplateLink</code> (self).
    281     */
    282    public TemplateLink addPathInfo(ParameterParser pp)
    283    {
    284        templateURI.addPathInfo(pp);
    285        return this;
    286    }
    287
    288    /**
    289     * Adds a name=value pair to the path_info string.
    290     *
    291     * @param name A String with the name to add.
    292     * @param value An Object with the value to add.
    293     * @return A <code>TemplateLink</code> (self).
    294     */
    295    public TemplateLink addPathInfo(String name, Object value)
    296    {
    297        templateURI.addPathInfo(name, value);
    298        return this;
    299    }
    300
    301    /**
    302     * Adds a name=value pair to the path_info string.
    303     *
    304     * @param name A String with the name to add.
    305     * @param value A String with the value to add.
    306     * @return A <code>TemplateLink</code> (self).
    307     */
    308    public TemplateLink addPathInfo(String name, String value)
    309    {
    310        templateURI.addPathInfo(name, value);
    311        return this;
    312    }
    313
    314    /**
    315     * Adds a name=value pair to the path_info string.
    316     *
    317     * @param name A String with the name to add.
    318     * @param value A double with the value to add.
    319     * @return A <code>TemplateLink</code> (self).
    320     */
    321    public TemplateLink addPathInfo(String name, double value)
    322    {
    323        templateURI.addPathInfo(name, value);
    324        return this;
    325    }
    326
    327    /**
    328     * Adds a name=value pair to the path_info string.
    329     *
    330     * @param name A String with the name to add.
    331     * @param value An int with the value to add.
    332     * @return A <code>TemplateLink</code> (self).
    333     */
    334    public TemplateLink addPathInfo(String name, int value)
    335    {
    336        templateURI.addPathInfo(name, value);
    337        return this;
    338    }
    339
    340    /**
    341     * Adds a name=value pair to the path_info string.
    342     *
    343     * @param name A String with the name to add.
    344     * @param value A long with the value to add.
    345     * @return A <code>TemplateLink</code> (self).
    346     */
    347    public TemplateLink addPathInfo(String name, long value)
    348    {
    349        templateURI.addPathInfo(name, value);
    350        return this;
    351    }
    352
    353    /**
    354     * Adds a name=value pair to the query string.
    355     *
    356     * @param name A String with the name to add.
    357     * @param value An Object with the value to add.
    358     * @return A <code>TemplateLink</code> (self).
    359     */
    360    public TemplateLink addQueryData(String name, Object value)
    361    {
    362        templateURI.addQueryData(name, value);
    363        return this;
    364    }
    365
    366    /**
    367     * Adds a name=value pair to the query string.
    368     *
    369     * @param name A String with the name to add.
    370     * @param value A String with the value to add.
    371     * @return A <code>TemplateLink</code> (self).
    372     */
    373    public TemplateLink addQueryData(String name, String value)
    374    {
    375        templateURI.addQueryData(name, value);
    376        return this;
    377    }
    378
    379    /**
    380     * Adds a name=value pair to the query string.
    381     *
    382     * @param name A String with the name to add.
    383     * @param value A double with the value to add.
    384     * @return A <code>TemplateLink</code> (self).
    385     */
    386    public TemplateLink addQueryData(String name, double value)
    387    {
    388        templateURI.addQueryData(name, value);
    389        return this;
    390    }
    391
    392    /**
    393     * Adds a name=value pair to the query string.
    394     *
    395     * @param name A String with the name to add.
    396     * @param value An int with the value to add.
    397     * @return A <code>TemplateLink</code> (self).
    398     */
    399    public TemplateLink addQueryData(String name, int value)
    400    {
    401        templateURI.addQueryData(name, value);
    402        return this;
    403    }
    404
    405    /**
    406     * Adds a name=value pair to the query string.
    407     *
    408     * @param name A String with the name to add.
    409     * @param value A long with the value to add.
    410     * @return A <code>TemplateLink</code> (self).
    411     */
    412    public TemplateLink addQueryData(String name, long value)
    413    {
    414        templateURI.addQueryData(name, value);
    415        return this;
    416    }
    417
    418    /**
    419     * Adds a name=value pair for every entry in a ParameterParser
    420     * object to the query string.
    421     *
    422     * @param pp A ParameterParser.
    423     * @return A <code>TemplateLink</code> (self).
    424     */
    425    public TemplateLink addQueryData(ParameterParser pp)
    426    {
    427        templateURI.addQueryData(pp);
    428        return this;
    429    }
    430
    431    /**
    432     * Removes all the path info elements.
    433     *
    434     * @return A <code>TemplateLink</code> (self).
    435     */
    436    public TemplateLink removePathInfo()
    437    {
    438        templateURI.removePathInfo();
    439        return this;
    440    }
    441
    442    /**
    443     * Removes a name=value pair from the path info.
    444     *
    445     * @param name A String with the name to be removed.
    446     * @return A <code>TemplateLink</code> (self).
    447     */
    448    public TemplateLink removePathInfo(String name)
    449    {
    450        templateURI.removePathInfo(name);
    451        return this;
    452    }
    453
    454    /**
    455     * Removes all the query string elements.
    456     *
    457     * @return A <code>TemplateLink</code> (self).
    458     */
    459    public TemplateLink removeQueryData()
    460    {
    461        templateURI.removeQueryData();
    462        return this;
    463    }
    464
    465    /**
    466     * Removes a name=value pair from the query string.
    467     *
    468     * @param name A String with the name to be removed.
    469     * @return A <code>TemplateLink</code> (self).
    470     */
    471    public TemplateLink removeQueryData(String name)
    472    {
    473        templateURI.removeQueryData(name);
    474        return this;
    475    }
    476
    477    /**
    478     * Builds the URL with all of the data URL-encoded as well as
    479     * encoded using HttpServletResponse.encodeUrl(). The resulting
    480     * URL is absolute; it starts with http/https...
    481     *
    482     * <p>
    483     * <code><pre>
    484     * TemplateURI tui = new TemplateURI (data, "UserScreen");
    485     * tui.addPathInfo("user","jon");
    486     * tui.getAbsoluteLink();
    487     * </pre></code>
    488     *
    489     *  The above call to absoluteLink() would return the String:
    490     *
    491     * <p>
    492     * http://www.server.com/servlets/Turbine/screen/UserScreen/user/jon
    493     *
    494     * <p>
    495     * After rendering the URI, it clears the
    496     * pathInfo and QueryString portions of the TemplateURI. So you can
    497     * use the $link reference multiple times on a page and start over
    498     * with a fresh object every time.
    499     *
    500     * @return A String with the built URL.
    501     */
    502    public String getAbsoluteLink()
    503    {
    504        String output = templateURI.getAbsoluteLink();
    505
    506        // This was added to use $link multiple times on a page and start
    507        // over with a fresh set of data every time.
    508        templateURI.removePathInfo();
    509        templateURI.removeQueryData();
    510
    511        return output;
    512    }
    513
    514
    515    /**
    516     * Builds the URL with all of the data URL-encoded as well as
    517     * encoded using HttpServletResponse.encodeUrl(). The resulting
    518     * URL is relative to the webserver root.
    519     *
    520     * <p>
    521     * <code><pre>
    522     * TemplateURI tui = new TemplateURI (data, "UserScreen");
    523     * tui.addPathInfo("user","jon");
    524     * tui.getRelativeLink();
    525     * </pre></code>
    526     *
    527     *  The above call to absoluteLink() would return the String:
    528     *
    529     * <p>
    530     * /servlets/Turbine/screen/UserScreen/user/jon
    531     *
    532     * <p>
    533     * After rendering the URI, it clears the
    534     * pathInfo and QueryString portions of the TemplateURI. So you can
    535     * use the $link reference multiple times on a page and start over
    536     * with a fresh object every time.
    537     *
    538     * @return A String with the built URL.
    539     */
    540    public String getRelativeLink()
    541    {
    542        String output = templateURI.getRelativeLink();
    543
    544        // This was added to use $link multiple times on a page and start
    545        // over with a fresh set of data every time.
    546        templateURI.removePathInfo();
    547        templateURI.removeQueryData();
    548
    549        return output;
    550    }
    551
    552    /**
    553     * Returns the URI. After rendering the URI, it clears the
    554     * pathInfo and QueryString portions of the TemplateURI.
    555     *
    556     * @return A String with the URI in the form
    557     * http://foo.com/Turbine/template/index.wm/hello/world
    558     */
    559    public String getLink()
    560    {
    561        return wantRelative ?
    562                getRelativeLink() : getAbsoluteLink();
    563    }
    564
    565    /**
    566     * Returns the relative URI leaving the source intact. Use this
    567     * if you need the path_info and query data multiple times.
    568     * This is equivalent to $link.Link or just $link,
    569     * but does not reset the path_info and query data.
    570     *
    571     * @return A String with the URI in the form
    572     * http://foo.com/Turbine/template/index.wm/hello/world
    573     */
    574    public String getURI()
    575    {
    576        return wantRelative ?
    577                templateURI.getRelativeLink() : templateURI.getAbsoluteLink();
    578    }
    579
    580    /**
    581     * Returns the absolute URI leaving the source intact. Use this
    582     * if you need the path_info and query data multiple times.
    583     * This is equivalent to $link.AbsoluteLink but does not reset
    584     * the path_info and query data.
    585     *
    586     * @return A String with the URI in the form
    587     * http://foo.com/Turbine/template/index.wm/hello/world
    588     */
    589    public String getAbsoluteURI()
    590    {
    591        return templateURI.getAbsoluteLink();
    592    }
    593
    594    /**
    595     * Returns the relative URI leaving the source intact. Use this
    596     * if you need the path_info and query data multiple times.
    597     * This is equivalent to $link.RelativeLink but does not reset
    598     * the path_info and query data.
    599     *
    600     * @return A String with the URI in the form
    601     * http://foo.com/Turbine/template/index.wm/hello/world
    602     */
    603    public String getRelativeURI()
    604    {
    605        return templateURI.getRelativeLink();
    606    }
    607
    608    /**
    609     * Same as getLink().
    610     *
    611     * @return A String with the URI represented by this object.
    612     *
    613     */
    614    @Override
    615    public String toString()
    616    {
    617        return getLink();
    618    }
    619}