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.configuration2.Configuration;
025import org.apache.fulcrum.parser.ParameterParser;
026import org.apache.logging.log4j.LogManager;
027import org.apache.logging.log4j.Logger;
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$
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 final Logger log = LogManager.getLogger(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     * <pre>
483     * TemplateURI tui = new TemplateURI (data, "UserScreen");
484     * tui.addPathInfo("user","jon");
485     * tui.getAbsoluteLink();
486     * </pre>
487     *
488     * The above call to absoluteLink() would return the String:
489     * <p>
490     * http://www.server.com/servlets/Turbine/screen/UserScreen/user/jon
491     * <p>
492     * After rendering the URI, it clears the
493     * pathInfo and QueryString portions of the TemplateURI. So you can
494     * use the $link reference multiple times on a page and start over
495     * with a fresh object every time.
496     *
497     * @return A String with the built URL.
498     */
499    public String getAbsoluteLink()
500    {
501        String output = templateURI.getAbsoluteLink();
502
503        // This was added to use $link multiple times on a page and start
504        // over with a fresh set of data every time.
505        templateURI.removePathInfo();
506        templateURI.removeQueryData();
507
508        return output;
509    }
510
511
512    /**
513     * Builds the URL with all of the data URL-encoded as well as
514     * encoded using HttpServletResponse.encodeUrl(). The resulting
515     * URL is relative to the webserver root.
516     *
517     * <pre>
518     * TemplateURI tui = new TemplateURI (data, "UserScreen");
519     * tui.addPathInfo("user","jon");
520     * tui.getRelativeLink();
521     * </pre>
522     *
523     * The above call to relativeLink() would return the String:
524     * <p>
525     * /servlets/Turbine/screen/UserScreen/user/jon
526     * <p>
527     * After rendering the URI, it clears the
528     * pathInfo and QueryString portions of the TemplateURI. So you can
529     * use the $link reference multiple times on a page and start over
530     * with a fresh object every time.
531     *
532     * @return A String with the built URL.
533     */
534    public String getRelativeLink()
535    {
536        String output = templateURI.getRelativeLink();
537
538        // This was added to use $link multiple times on a page and start
539        // over with a fresh set of data every time.
540        templateURI.removePathInfo();
541        templateURI.removeQueryData();
542
543        return output;
544    }
545
546    /**
547     * Returns the URI. After rendering the URI, it clears the
548     * pathInfo and QueryString portions of the TemplateURI.
549     *
550     * @return A String with the URI in the form
551     * http://foo.com/Turbine/template/index.wm/hello/world
552     */
553    public String getLink()
554    {
555        return wantRelative ?
556                getRelativeLink() : getAbsoluteLink();
557    }
558
559    /**
560     * Returns the relative URI leaving the source intact. Use this
561     * if you need the path_info and query data multiple times.
562     * This is equivalent to $link.Link or just $link,
563     * but does not reset the path_info and query data.
564     *
565     * @return A String with the URI in the form
566     * http://foo.com/Turbine/template/index.wm/hello/world
567     */
568    public String getURI()
569    {
570        return wantRelative ?
571                templateURI.getRelativeLink() : templateURI.getAbsoluteLink();
572    }
573
574    /**
575     * Returns the absolute URI leaving the source intact. Use this
576     * if you need the path_info and query data multiple times.
577     * This is equivalent to $link.AbsoluteLink but does not reset
578     * the path_info and query data.
579     *
580     * @return A String with the URI in the form
581     * http://foo.com/Turbine/template/index.wm/hello/world
582     */
583    public String getAbsoluteURI()
584    {
585        return templateURI.getAbsoluteLink();
586    }
587
588    /**
589     * Returns the relative URI leaving the source intact. Use this
590     * if you need the path_info and query data multiple times.
591     * This is equivalent to $link.RelativeLink but does not reset
592     * the path_info and query data.
593     *
594     * @return A String with the URI in the form
595     * http://foo.com/Turbine/template/index.wm/hello/world
596     */
597    public String getRelativeURI()
598    {
599        return templateURI.getRelativeLink();
600    }
601
602    /**
603     * Same as getLink().
604     *
605     * @return A String with the URI represented by this object.
606     *
607     */
608    @Override
609    public String toString()
610    {
611        return getLink();
612    }
613}