    001    package 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
    024    import org.apache.commons.configuration.Configuration;
    025    import org.apache.commons.logging.Log;
    026    import org.apache.commons.logging.LogFactory;
    027    import org.apache.fulcrum.parser.ParameterParser;
    028    import org.apache.turbine.Turbine;
    029    import org.apache.turbine.pipeline.PipelineData;
    030    import org.apache.turbine.services.pull.ApplicationTool;
    031    import org.apache.turbine.util.RunData;
    032    import 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 1129102 2011-05-30 10:01:17Z tv $
    057     */
    058
    059    public 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 initialise a TemplateLink object that was
    105         * constructed with the default constructor (ApplicationTool
    106         * method).
    107         *
    108         * @param data assumed to be a RunData object
    109         */
    110        public void init(Object data)
    111        {
    112            // we just blithely cast to RunData as if another object
    113            // or null is passed in we'll throw an appropriate runtime
    114            // exception.
    115            if (data instanceof PipelineData)
    116            {
    117                PipelineData pipelineData = (PipelineData) data;
    118                RunData runData = (RunData)pipelineData;
    119                templateURI = new TemplateURI(runData);
    120            }
    121            else
    122            {
    123                templateURI = new TemplateURI((RunData) data);
    124            }
    125
    126            Configuration conf =
    127                    Turbine.getConfiguration().subset(TEMPLATE_LINK_PREFIX);
    128
    129            if (conf != null)
    130            {
    131                wantRelative = conf.getBoolean(TEMPLATE_LINK_RELATIVE_KEY,
    132                        TEMPLATE_LINK_RELATIVE_DEFAULT);
    133            }
    134
    135        }
    136
    137        /**
    138         * Refresh method - does nothing
    139         */
    140        public void refresh()
    141        {
    142            // empty
    143        }
    144
    145        /*
    146         * ========================================================================
    147         *
    148         * getter/setter
    149         *
    150         * All setter return "this" so you can "chain" them together in the Context
    151         *
    152         * ========================================================================
    153         */
    154
    155        /**
    156         * This will turn off the execution of res.encodeURL()
    157         * by making res == null. This is a hack for cases
    158         * where you don't want to see the session information
    159         *
    160         * @return A <code>TemplateLink</code> (self).
    161         */
    162        public TemplateLink setEncodeURLOff()
    163        {
    164            templateURI.clearResponse();
    165            return this;
    166        }
    167
    168        /**
    169         * Sets the template variable used by the Template Service.
    170         *
    171         * @param template A String with the template name.
    172         * @return A TemplateLink.
    173         */
    174        public TemplateLink setPage(String template)
    175        {
    176            log.debug("setPage(" + template + ")");
    177            this.template = template;
    178            templateURI.setTemplate(template);
    179            return this;
    180        }
    181
    182        /**
    183         * Gets the template variable used by the Template Service.
    184         * It is only available after setPage() has been called.
    185         *
    186         * @return The template name.
    187         */
    188        public String getPage()
    189        {
    190            return template;
    191        }
    192
    193        /**
    194         * Sets the action= value for this URL.
    195         *
    196         * By default it adds the information to the path_info instead
    197         * of the query data.
    198         *
    199         * @param action A String with the action value.
    200         * @return A <code>TemplateLink</code> (self).
    201         */
    202        public TemplateLink setAction(String action)
    203        {
    204            log.debug("setAction(" + action + ")");
    205            templateURI.setAction(action);
    206            return this;
    207        }
    208
    209        /**
    210         * Sets the action= and eventSubmit= values for this URL.
    211         *
    212         * By default it adds the information to the path_info instead
    213         * of the query data.
    214         *
    215         * @param action A String with the action value.
    216         * @param event A string with the event name.
    217         * @return A <code>TemplateLink</code> (self).
    218         */
    219        public TemplateLink setActionEvent(String action, String event)
    220        {
    221            log.debug("setActionEvent(" + action + ", "+ event +")");
    222            templateURI.setActionEvent(action, event);
    223            return this;
    224        }
    225
    226        /**
    227         * Sets the screen= value for this URL.
    228         *
    229         * By default it adds the information to the path_info instead
    230         * of the query data.
    231         *
    232         * @param screen A String with the screen value.
    233         * @return A <code>TemplateLink</code> (self).
    234         */
    235        public TemplateLink setScreen(String screen)
    236        {
    237            log.debug("setScreen(" + screen + ")");
    238            templateURI.setScreen(screen);
    239            return this;
    240        }
    241
    242        /**
    243         * Sets a reference anchor (#ref).
    244         *
    245         * @param reference A String containing the reference.
    246         * @return A <code>TemplateLink</code> (self).
    247         */
    248        public TemplateLink setReference(String reference)
    249        {
    250            templateURI.setReference(reference);
    251            return this;
    252        }
    253
    254        /**
    255         * Returns the current reference anchor.
    256         *
    257         * @return A String containing the reference.
    258         */
    259        public String getReference()
    260        {
    261            return templateURI.getReference();
    262        }
    263
    264        /*
    265         * ========================================================================
    266         *
    267         * Adding and removing Data from the Path Info and Query Data
    268         *
    269         * ========================================================================
    270         */
    271
    272
    273        /**
    274         * Adds a name=value pair for every entry in a ParameterParser
    275         * object to the path_info string.
    276         *
    277         * @param pp A ParameterParser.
    278         * @return A <code>TemplateLink</code> (self).
    279         */
    280        public TemplateLink addPathInfo(ParameterParser pp)
    281        {
    282            templateURI.addPathInfo(pp);
    283            return this;
    284        }
    285
    286        /**
    287         * Adds a name=value pair to the path_info string.
    288         *
    289         * @param name A String with the name to add.
    290         * @param value An Object with the value to add.
    291         * @return A <code>TemplateLink</code> (self).
    292         */
    293        public TemplateLink addPathInfo(String name, Object value)
    294        {
    295            templateURI.addPathInfo(name, value);
    296            return this;
    297        }
    298
    299        /**
    300         * Adds a name=value pair to the path_info string.
    301         *
    302         * @param name A String with the name to add.
    303         * @param value A String with the value to add.
    304         * @return A <code>TemplateLink</code> (self).
    305         */
    306        public TemplateLink addPathInfo(String name, String value)
    307        {
    308            templateURI.addPathInfo(name, value);
    309            return this;
    310        }
    311
    312        /**
    313         * Adds a name=value pair to the path_info string.
    314         *
    315         * @param name A String with the name to add.
    316         * @param value A double with the value to add.
    317         * @return A <code>TemplateLink</code> (self).
    318         */
    319        public TemplateLink addPathInfo(String name, double value)
    320        {
    321            templateURI.addPathInfo(name, value);
    322            return this;
    323        }
    324
    325        /**
    326         * Adds a name=value pair to the path_info string.
    327         *
    328         * @param name A String with the name to add.
    329         * @param value An int with the value to add.
    330         * @return A <code>TemplateLink</code> (self).
    331         */
    332        public TemplateLink addPathInfo(String name, int value)
    333        {
    334            templateURI.addPathInfo(name, value);
    335            return this;
    336        }
    337
    338        /**
    339         * Adds a name=value pair to the path_info string.
    340         *
    341         * @param name A String with the name to add.
    342         * @param value A long with the value to add.
    343         * @return A <code>TemplateLink</code> (self).
    344         */
    345        public TemplateLink addPathInfo(String name, long value)
    346        {
    347            templateURI.addPathInfo(name, value);
    348            return this;
    349        }
    350
    351        /**
    352         * Adds a name=value pair to the query string.
    353         *
    354         * @param name A String with the name to add.
    355         * @param value An Object with the value to add.
    356         * @return A <code>TemplateLink</code> (self).
    357         */
    358        public TemplateLink addQueryData(String name, Object value)
    359        {
    360            templateURI.addQueryData(name, value);
    361            return this;
    362        }
    363
    364        /**
    365         * Adds a name=value pair to the query string.
    366         *
    367         * @param name A String with the name to add.
    368         * @param value A String with the value to add.
    369         * @return A <code>TemplateLink</code> (self).
    370         */
    371        public TemplateLink addQueryData(String name, String value)
    372        {
    373            templateURI.addQueryData(name, value);
    374            return this;
    375        }
    376
    377        /**
    378         * Adds a name=value pair to the query string.
    379         *
    380         * @param name A String with the name to add.
    381         * @param value A double with the value to add.
    382         * @return A <code>TemplateLink</code> (self).
    383         */
    384        public TemplateLink addQueryData(String name, double value)
    385        {
    386            templateURI.addQueryData(name, value);
    387            return this;
    388        }
    389
    390        /**
    391         * Adds a name=value pair to the query string.
    392         *
    393         * @param name A String with the name to add.
    394         * @param value An int with the value to add.
    395         * @return A <code>TemplateLink</code> (self).
    396         */
    397        public TemplateLink addQueryData(String name, int value)
    398        {
    399            templateURI.addQueryData(name, value);
    400            return this;
    401        }
    402
    403        /**
    404         * Adds a name=value pair to the query string.
    405         *
    406         * @param name A String with the name to add.
    407         * @param value A long with the value to add.
    408         * @return A <code>TemplateLink</code> (self).
    409         */
    410        public TemplateLink addQueryData(String name, long value)
    411        {
    412            templateURI.addQueryData(name, value);
    413            return this;
    414        }
    415
    416        /**
    417         * Adds a name=value pair for every entry in a ParameterParser
    418         * object to the query string.
    419         *
    420         * @param pp A ParameterParser.
    421         * @return A <code>TemplateLink</code> (self).
    422         */
    423        public TemplateLink addQueryData(ParameterParser pp)
    424        {
    425            templateURI.addQueryData(pp);
    426            return this;
    427        }
    428
    429        /**
    430         * Removes all the path info elements.
    431         *
    432         * @return A <code>TemplateLink</code> (self).
    433         */
    434        public TemplateLink removePathInfo()
    435        {
    436            templateURI.removePathInfo();
    437            return this;
    438        }
    439
    440        /**
    441         * Removes a name=value pair from the path info.
    442         *
    443         * @param name A String with the name to be removed.
    444         * @return A <code>TemplateLink</code> (self).
    445         */
    446        public TemplateLink removePathInfo(String name)
    447        {
    448            templateURI.removePathInfo(name);
    449            return this;
    450        }
    451
    452        /**
    453         * Removes all the query string elements.
    454         *
    455         * @return A <code>TemplateLink</code> (self).
    456         */
    457        public TemplateLink removeQueryData()
    458        {
    459            templateURI.removeQueryData();
    460            return this;
    461        }
    462
    463        /**
    464         * Removes a name=value pair from the query string.
    465         *
    466         * @param name A String with the name to be removed.
    467         * @return A <code>TemplateLink</code> (self).
    468         */
    469        public TemplateLink removeQueryData(String name)
    470        {
    471            templateURI.removeQueryData(name);
    472            return this;
    473        }
    474
    475        /**
    476         * Builds the URL with all of the data URL-encoded as well as
    477         * encoded using HttpServletResponse.encodeUrl(). The resulting
    478         * URL is absolute; it starts with http/https...
    479         *
    480         * <p>
    481         * <code><pre>
    482         * TemplateURI tui = new TemplateURI (data, "UserScreen");
    483         * tui.addPathInfo("user","jon");
    484         * tui.getAbsoluteLink();
    485         * </pre></code>
    486         *
    487         *  The above call to absoluteLink() would return the String:
    488         *
    489         * <p>
    490         * http://www.server.com/servlets/Turbine/screen/UserScreen/user/jon
    491         *
    492         * <p>
    493         * After rendering the URI, it clears the
    494         * pathInfo and QueryString portions of the TemplateURI. So you can
    495         * use the $link reference multiple times on a page and start over
    496         * with a fresh object every time.
    497         *
    498         * @return A String with the built URL.
    499         */
    500        public String getAbsoluteLink()
    501        {
    502            String output = templateURI.getAbsoluteLink();
    503
    504            // This was added to use $link multiple times on a page and start
    505            // over with a fresh set of data every time.
    506            templateURI.removePathInfo();
    507            templateURI.removeQueryData();
    508
    509            return output;
    510        }
    511
    512
    513        /**
    514         * Builds the URL with all of the data URL-encoded as well as
    515         * encoded using HttpServletResponse.encodeUrl(). The resulting
    516         * URL is relative to the webserver root.
    517         *
    518         * <p>
    519         * <code><pre>
    520         * TemplateURI tui = new TemplateURI (data, "UserScreen");
    521         * tui.addPathInfo("user","jon");
    522         * tui.getRelativeLink();
    523         * </pre></code>
    524         *
    525         *  The above call to absoluteLink() would return the String:
    526         *
    527         * <p>
    528         * /servlets/Turbine/screen/UserScreen/user/jon
    529         *
    530         * <p>
    531         * After rendering the URI, it clears the
    532         * pathInfo and QueryString portions of the TemplateURI. So you can
    533         * use the $link reference multiple times on a page and start over
    534         * with a fresh object every time.
    535         *
    536         * @return A String with the built URL.
    537         */
    538        public String getRelativeLink()
    539        {
    540            String output = templateURI.getRelativeLink();
    541
    542            // This was added to use $link multiple times on a page and start
    543            // over with a fresh set of data every time.
    544            templateURI.removePathInfo();
    545            templateURI.removeQueryData();
    546
    547            return output;
    548        }
    549
    550        /**
    551         * Returns the URI. After rendering the URI, it clears the
    552         * pathInfo and QueryString portions of the TemplateURI.
    553         *
    554         * @return A String with the URI in the form
    555         * http://foo.com/Turbine/template/index.wm/hello/world
    556         */
    557        public String getLink()
    558        {
    559            return wantRelative ?
    560                    getRelativeLink() : getAbsoluteLink();
    561        }
    562
    563        /**
    564         * Returns the relative URI leaving the source intact. Use this
    565         * if you need the path_info and query data multiple times.
    566         * This is equivalent to $link.Link or just $link,
    567         * but does not reset the path_info and query data.
    568         *
    569         * @return A String with the URI in the form
    570         * http://foo.com/Turbine/template/index.wm/hello/world
    571         */
    572        public String getURI()
    573        {
    574            return wantRelative ?
    575                    templateURI.getRelativeLink() : templateURI.getAbsoluteLink();
    576        }
    577
    578        /**
    579         * Returns the absolute URI leaving the source intact. Use this
    580         * if you need the path_info and query data multiple times.
    581         * This is equivalent to $link.AbsoluteLink but does not reset
    582         * the path_info and query data.
    583         *
    584         * @return A String with the URI in the form
    585         * http://foo.com/Turbine/template/index.wm/hello/world
    586         */
    587        public String getAbsoluteURI()
    588        {
    589            return templateURI.getAbsoluteLink();
    590        }
    591
    592        /**
    593         * Returns the relative URI leaving the source intact. Use this
    594         * if you need the path_info and query data multiple times.
    595         * This is equivalent to $link.RelativeLink but does not reset
    596         * the path_info and query data.
    597         *
    598         * @return A String with the URI in the form
    599         * http://foo.com/Turbine/template/index.wm/hello/world
    600         */
    601        public String getRelativeURI()
    602        {
    603            return templateURI.getRelativeLink();
    604        }
    605
    606        /**
    607         * Same as getLink().
    608         *
    609         * @return A String with the URI represented by this object.
    610         *
    611         */
    612        @Override
    613        public String toString()
    614        {
    615            return getLink();
    616        }
    617    }