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    }