View Javadoc
1   package org.apache.turbine.services.pull.tools;
2   
3   
4   /*
5    * Licensed to the Apache Software Foundation (ASF) under one
6    * or more contributor license agreements.  See the NOTICE file
7    * distributed with this work for additional information
8    * regarding copyright ownership.  The ASF licenses this file
9    * to you under the Apache License, Version 2.0 (the
10   * "License"); you may not use this file except in compliance
11   * with the License.  You may obtain a copy of the License at
12   *
13   *   http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing,
16   * software distributed under the License is distributed on an
17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18   * KIND, either express or implied.  See the License for the
19   * specific language governing permissions and limitations
20   * under the License.
21   */
22  
23  
24  import org.apache.commons.configuration2.Configuration;
25  import org.apache.fulcrum.parser.ParameterParser;
26  import org.apache.logging.log4j.LogManager;
27  import org.apache.logging.log4j.Logger;
28  import org.apache.turbine.Turbine;
29  import org.apache.turbine.pipeline.PipelineData;
30  import org.apache.turbine.services.pull.ApplicationTool;
31  import org.apache.turbine.util.RunData;
32  import org.apache.turbine.util.uri.TemplateURI;
33  
34  /**
35   * This is a pull to to be used in Templates to convert links in
36   * Templates into the correct references.
37   *
38   * The pull service might insert this tool into the Context.
39   * in templates.  Here's an example of its Velocity use:
40   *
41   * <p><code>
42   * $link.setPage("index.vm").addPathInfo("hello","world")
43   * This would return: http://foo.com/Turbine/template/index.vm/hello/world
44   * </code>
45   *
46   * <p>
47   *
48   * This is an application pull tool for the template system. You should <b>not</b>
49   * use it in a normal application!
50   *
51   * @author <a href="mbryson@mont.mindspring.com">Dave Bryson</a>
52   * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
53   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
54   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
55   * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
56   * @version $Id$
57   */
58  
59  public class TemplateLink
60      implements ApplicationTool
61  {
62      /** Prefix for Parameters for this tool */
63      public static final String TEMPLATE_LINK_PREFIX = "tool.link";
64  
65      /** Should this tool return relative URIs or absolute? Default: Absolute. */
66      public static final String TEMPLATE_LINK_RELATIVE_KEY = "want.relative";
67  
68      /** Default Value for TEMPLATE_LINK_RELATIVE_KEY */
69      public static final boolean TEMPLATE_LINK_RELATIVE_DEFAULT = false;
70  
71  
72      /** Do we want a relative link? */
73      protected boolean wantRelative = false;
74  
75      /** cache of the template name for getPage() */
76      protected String template = null;
77  
78      /** TemplateURI used as backend for this object */
79      protected TemplateURI templateURI = null;
80  
81      /** Logging */
82      private static final Logger log = LogManager.getLogger(TemplateLink.class);
83  
84      /**
85       * Default constructor
86       * <p>
87       * The init method must be called before use.
88       */
89      public TemplateLink()
90      {
91          // empty
92      }
93  
94      /*
95       * ========================================================================
96       *
97       * Application Tool Interface
98       *
99       * ========================================================================
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 }