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}