View Javadoc

1   package org.apache.jetspeed.util;
2   
3   /*
4    * Copyright 2000-2004 The Apache Software Foundation.
5    * 
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  //jetspeed support
20  import org.apache.jetspeed.portal.Portlet;
21  import org.apache.jetspeed.portal.PortletControl;
22  import org.apache.jetspeed.om.registry.PortletEntry;
23  import org.apache.jetspeed.services.Registry;
24  import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
25  import org.apache.jetspeed.services.logging.JetspeedLogger;
26  import org.apache.jetspeed.services.resources.JetspeedResources;
27  import org.apache.jetspeed.services.rundata.JetspeedRunData;
28  
29  //turbine
30  import org.apache.turbine.util.ParameterParser;
31  import org.apache.turbine.util.RunData;
32  import org.apache.turbine.util.template.TemplateLink;
33  
34  
35  /***
36   * <p>
37   * URI lookup related functions.
38   * </p>
39   * 
40   * <p>
41   *  Functions to get an URI based on a type like info, edit, save
42   *  and to identify the type of an URI.
43   * </p>
44   * 
45   * <p>
46   * To overwrite the default behaviour, specify one
47   * of the following parameters in the JR.p file. URILookup
48   * will then return the uri specified in the properties file.
49   * </p>
50   * <p>
51   * all possible property parameters:
52   * </p>
53   * 
54   * <UL>
55   * <LI>URILookup.home.uri</LI>
56   * <LI>URILookup.home.acceptlogin.uri</LI>
57   * <LI>URILookup.home.restore.uri</LI>
58   * <LI>URILookup.home.logout.uri</LI>
59   * </UL>
60   * <UL>
61   * <LI>URILookup.info.uri</LI>
62   * <LI>URILookup.info.mark.uri</LI>
63   * </UL>
64   * <UL>
65   * <LI>URILookup.login.uri</LI>
66   * </UL>
67   * <UL>
68   * <LI>URILookup.editaccount.uri</LI>
69   * <LI>URILookup.editaccount.mark.uri</LI>
70   * </UL>
71   * <UL>
72   * <LI>URILookup.back.uri</LI>
73   * </UL>
74   * <UL>
75   * <LI>URILookup.enrollment.uri</LI>
76   * </UL>
77   * <UL>
78   * <LI>URILookup.customizer.uri</LI>
79   * <LI>URILookup.customizer.save.uri</LI>
80   * </UL>
81   * 
82   * @author <A HREF="shesmer@raleigh.ibm.com">Stephan Hesmer</A>
83   * @author <A HREF="sgala@apache.org">Santiago Gala</A>
84   * @version $Id: URILookup.java,v 1.24 2004/02/23 03:23:42 jford Exp $
85   */
86  
87  public class URILookup 
88  {
89      /***
90       * Static initialization of the logger for this class
91       */    
92      private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(URILookup.class.getName());
93      /***
94       * <P>show Jetspeed Home page<BR>
95       * allowed Subtypes:<BR>
96       * <UL>
97       * <LI>SUBTYPE_NONE</LI>
98       * <LI>SUBTYPE_RESTORE</LI>
99       * <LI>SUBTYPE_MAXIMIZE</LI>
100      * <LI>SUBTYPE_LOGOUT</LI>
101      * <LI>SUBTYPE_ACCEPT_LOGIN</LI>
102      * </UL>
103      */
104     public static final int TYPE_HOME               = 0;
105     /***
106      * <P>show some additional information about the portlet</P>
107      * allowed Subtypes:<BR>
108      * <UL>
109      * <LI>SUBTYPE_NONE</LI>
110      * <LI>SUBTYPE_MARK</LI>
111      * </UL>
112      */
113     public static final int TYPE_INFO               = 1;
114 
115     /***
116      * <P>show the edit page of the account</P>
117      * allowed Subtypes:<BR>
118      * <UL>
119      * <LI>SUBTYPE_NONE</LI>
120      * <LI>SUBTYPE_MARK</LI>
121      * </UL>
122      */
123     public static final int TYPE_EDIT_ACCOUNT       = 3;
124     /***
125      * <P>show portlet customization</P>
126      * allowed Subtypes:<BR>
127      * <UL>
128      * <LI>SUBTYPE_NONE</LI>
129      * <LI>SUBTYPE_SAVE</LI>
130      * </UL>
131      */
132     public static final int TYPE_CUSTOMIZE          = 4;
133     /***
134      * <P>show login screen</P>
135      * allowed Subtypes:<BR>
136      * <UL>
137      * <LI>SUBTYPE_NONE</LI>
138      * </UL>
139      */
140     public static final int TYPE_LOGIN              = 5;
141     /***
142      * <P>show the marked page<BR>
143      * only used in function getURI, not in getURIType</P>
144      * allowed Subtypes:<BR>
145      * <UL>
146      * <LI>SUBTYPE_NONE</LI>
147      * </UL>
148      */
149     public static final int TYPE_BACK               = 6;
150 
151     /***
152      * <P>creates new account<BR>
153      * allowed Subtypes:<BR>
154      * <UL>
155      * <LI>SUBTYPE_NONE</LI>
156      * </UL>
157      */
158     public static final int TYPE_ENROLLMENT         = 7;
159 
160     /***
161      * apply no subtype to the url
162      */
163     public static final int SUBTYPE_NONE            = 0;
164     /***
165      * restore portlet to default size
166      */
167     public static final int SUBTYPE_RESTORE         = 1;
168     /***
169      * show the current portlet maximized<BR>
170      * additionally, the current page is marked for restoring
171      */
172     public static final int SUBTYPE_MAXIMIZE        = 2;
173     /***
174      * mark the current page before processing portlet
175      */
176     public static final int SUBTYPE_MARK            = 3;
177     /***
178      * logs out the user
179      */
180     public static final int SUBTYPE_LOGOUT          = 4;
181     /***
182      * trues to login, after entering username and password
183      */
184     public static final int SUBTYPE_ACCEPT_LOGIN    = 5;
185     /***
186      * save user settings before processing portlet
187      */
188     public static final int SUBTYPE_SAVE            = 6;
189 
190     /***
191      * Gets the URI for the specified type
192      * 
193      * @param aType    type of the URI
194      * @param aSubType subtype of the URI
195      * @param rundata  the RunData object
196      * @return the URI
197      * @exception JetspeedException
198      */
199     public static String getURI(int aType,
200                                 int aSubType,
201                                 RunData rundata)
202         throws JetspeedException
203     {
204         return getURI(aType, 
205                       aSubType,
206                       null,
207                       (String)null,
208                       rundata);
209     }
210 
211     /***
212      * Gets the URI of the specified portlet with the specified type
213      * 
214      * @param aType    type of the URI
215      * @param aSubType subtype of the URI
216      * @param aPortlet Portlet the URI points to
217      * @param rundata  the RunData object
218      * @return the URI
219      */
220     public static String getURI(int aType, 
221                                 int aSubType, 
222                                 Portlet aPortlet, 
223                                 RunData rundata)
224         throws JetspeedException
225     {
226         return getURI(aType,
227                       aSubType,
228                       null,
229                       aPortlet, 
230                       rundata);
231     }
232 
233     /***
234      * Gets the URI of the specified portlet with the specified type
235      * 
236      * @param aType    type of the URI
237      * @param aSubType subtype of the URI
238      * @param aPortletName Portlet the URI points to
239      * @param rundata  the RunData object
240      * @return the URI
241      */
242     public static String getURI(int aType,
243                                 int aSubType,
244                                 String aPortletName,
245                                 RunData rundata)
246         throws JetspeedException
247     {
248         return getURI(aType,
249                       aSubType,
250                       null,
251                       aPortletName,
252                       rundata);
253     }
254 
255     /***
256      * Gets the URI of the specified portlet with the specified type and adds
257      * given user data.
258      * 
259      * @param aType    type of the URI
260      * @param aSubType subtype of the URI
261      * @param userData string which should be added to the URL
262      * @param aPortlet Portlet the URI points to
263      * @param rundata  the RunData object
264      * @return the URI
265      */
266     public static String getURI(int aType,
267                                 int aSubType,
268                                 String userData,
269                                 Portlet aPortlet,
270                                 RunData rundata)
271         throws JetspeedException
272     {
273         if (aPortlet!=null) {
274             aPortlet = getRealPortlet(aPortlet);
275             return getURI(aType,
276                           aSubType,
277                           userData,
278                           aPortlet.getName(),
279                           rundata);
280         }
281         else {
282             return getURI(aType,
283                           aSubType,
284                           userData,
285                           (String)null,
286                           rundata);
287         }
288     }
289 
290     /***
291      * Gets the URI of the specified portlet with the specified type and adds
292      * given user data.
293      * 
294      * @param aType    type of the URI
295      * @param aSubType subtype of the URI
296      * @param userData string which should be added to the URL
297      * @param aPortletName Portlet the URI points to
298      * @param rundata  the RunData object
299      * @return the URI
300      */
301     public static String getURI(int aType,
302                                 int aSubType,
303                                 String userData,
304                                 String aPortletName,
305                                 RunData rundata)
306         throws JetspeedException
307     {
308         String newURI = null;
309 
310         String propertiesParameter = "URILookup.";
311 
312         TemplateLink uri = new TemplateLink( rundata );
313 
314         if (aType==TYPE_HOME)
315         {
316             propertiesParameter += "home.";
317             
318             if (aSubType==SUBTYPE_RESTORE)
319             {
320                 propertiesParameter += "restore.";
321 
322                 newURI = getMarkedPage( rundata );
323             }
324             else if (aSubType==SUBTYPE_MAXIMIZE)
325             {
326                 propertiesParameter += "maximize.";
327                 
328                 if (aPortletName==null)
329                 {
330                     throw new JetspeedException( "A portlet is required to return an URI." );
331                 }
332                 uri.setAction( ACTION_MARKPAGE );
333                 uri.addPathInfo( "portlet", aPortletName );
334             }
335             else if (aSubType==SUBTYPE_LOGOUT)
336             {
337                 propertiesParameter += "logout.";
338 
339                 uri.setAction( ACTION_LOGOUT );
340             }
341             else if (aSubType==SUBTYPE_ACCEPT_LOGIN)
342             {
343                 propertiesParameter += "acceptlogin.";
344 
345                 uri.setAction( ACTION_ACCEPT_LOGIN );
346             }
347             else if (aSubType!=SUBTYPE_NONE)
348             {
349                 throw new JetspeedException( "Incorrect Type / Subtype combination." );
350             }
351         }
352         else if (aType==TYPE_INFO)
353         {
354             propertiesParameter += "info.";
355             
356             if (aPortletName==null)
357             {
358                 throw new JetspeedException( "A portlet is required to return an URI." );
359             }
360             
361             uri.setPage( SCREEN_INFO );
362             uri.addPathInfo( "portlet", aPortletName );
363 
364             if (aSubType==SUBTYPE_MARK)
365             {
366                 propertiesParameter += "mark.";
367 
368                 uri.setAction( ACTION_MARKPAGE );
369             }
370             else if (aSubType!=SUBTYPE_NONE)
371             {
372                 throw new JetspeedException( "Incorrect Type / Subtype combination." );
373             }
374         }
375         else if (aType==TYPE_EDIT_ACCOUNT)
376         {
377             propertiesParameter += "editaccount.";
378             
379             uri.setPage( SCREEN_EDIT_ACCOUNT );
380 
381             if (aSubType==SUBTYPE_NONE)
382             {
383                 uri.setAction( ACTION_PREPARE_SCREEN_EDIT_ACCOUNT );
384             }
385             else if (aSubType==SUBTYPE_MARK)
386             {
387                 propertiesParameter += "mark.";
388                 
389                 if (aPortletName==null) 
390                 {
391                     throw new JetspeedException( "A portlet is required to return an URI." );
392                 }
393 
394                 // FIX ME: how can we add a prepare action and a mark action at the same time?
395                 //         But I think this branch is never used anyway. (?)
396                 uri.setAction( ACTION_MARKPAGE );
397                 uri.addPathInfo( "portlet", aPortletName );
398             }
399             else
400             {
401                 throw new JetspeedException( "Incorrect Type / Subtype combination." );
402             }
403         }
404         else if (aType==TYPE_CUSTOMIZE)
405         {
406             propertiesParameter += "customize.";
407             
408             uri.setPage( SCREEN_CUSTOMIZE );
409             
410             if( aPortletName != null )
411             {
412                 uri.addPathInfo( "portlet", aPortletName );
413             }
414             if (aSubType==SUBTYPE_NONE)
415             {
416                 if (ACTION_CUSTOMIZER!=null) uri.setAction( ACTION_CUSTOMIZER );
417             }
418             else if (aSubType==SUBTYPE_SAVE)
419             {
420                 propertiesParameter += "save.";
421                 
422                 uri.setAction( ACTION_CUSTOMIZER_SAVE );
423             }
424             else
425             {
426                 throw new JetspeedException( "Incorrect Type / Subtype combination." );
427             }
428         }
429         else if (aType==TYPE_LOGIN)
430         {
431             propertiesParameter += "login.";
432             
433             if (aSubType==SUBTYPE_NONE)
434             {
435                 uri.setPage( SCREEN_LOGIN );
436             }
437             else
438             {
439                 throw new JetspeedException( "Incorrect Type / Subtype combination." );
440             }
441         }
442         else if (aType==TYPE_BACK)
443         {
444             propertiesParameter += "back.";
445             
446             if (aSubType==SUBTYPE_NONE)
447             {
448                 newURI = getMarkedPage( rundata );
449             }
450             else
451             {
452                 throw new JetspeedException( "Incorrect Type / Subtype combination." );
453             }
454         }
455         else if (aType==TYPE_ENROLLMENT)
456         {
457             propertiesParameter += "enrollment.";
458             uri.setPage( SCREEN_NEWACCOUNT );
459         }
460         else
461         {
462             throw new JetspeedException( "Incorrect Type / Subtype combination." );
463         }
464 
465         if (newURI==null)
466         {
467             newURI = uri.toString();
468         }
469 
470         propertiesParameter += "uri";
471         String propertiesParameterValue = JetspeedResources.getString( propertiesParameter, null );
472 
473         if (propertiesParameterValue!=null)
474         {
475             // found the parameter value, so replace the newURI with this one
476             if ( logger.isInfoEnabled() )
477             {
478                 logger.info("URILookup: replaced uri "+newURI+" with "+propertiesParameterValue);
479             }
480             newURI = propertiesParameterValue;
481         }
482 
483         if (userData!=null)
484         {
485             newURI = addURIParameter(newURI, userData);
486         }
487 
488         // remove sessionid, if exists
489         if (newURI.indexOf(";jsessionid")!=-1)
490         {
491             newURI = newURI.substring(0,newURI.indexOf(";jsessionid"));
492         }
493 
494         // adds sessionid if necessary
495         newURI = rundata.getResponse().encodeURL( newURI );
496 
497         // remove starting slash, so that the URI is relative, and the Base-Tag is used
498         // Note: if there is no starting slash, the function encodeURL inserts one slash in front of the URI
499         if (newURI.startsWith("/"))
500         {
501             newURI = newURI.substring(1);
502         }
503 
504         return newURI;
505     }
506 
507     /***
508      * Gets the type of the URI (e.g. TYPE_INFO, TYPE_EDIT).
509      * 
510      * @param rundata the RunData object
511      * @return the type
512      */
513     public static int getURIType(RunData rundata)
514     {
515         return getURIType( null, rundata );
516     }
517 
518     /***
519      * Gets the type of the URI (e.g. TYPE_INFO, TYPE_EDIT).
520      * The default return value is TYPE_HOME
521      * <P>Hint:<BR>
522      * Portlets should check for TYPE_EDIT_PORTLET and in any other case render the content</P>
523      * 
524      * @param aPortlet the associated portlet
525      * @param rundata  the RunData object
526      * @return the type
527      */
528     public static int getURIType(Portlet aPortlet, RunData rundata)
529     {
530         if (aPortlet!=null)
531         {
532             aPortlet = getRealPortlet(aPortlet);
533 
534             if (aPortlet.getName().equals(((JetspeedRunData)rundata).getPortlet()))
535             {
536                 if (rundata.getScreen()!=null)
537                 {
538                     if (rundata.getScreen().equals(SCREEN_INFO)) return TYPE_INFO;
539                 }
540             }
541         }
542         
543         if (rundata.getScreen()!=null)
544         {
545             if (rundata.getScreen().equals(SCREEN_CUSTOMIZE)) return TYPE_CUSTOMIZE;
546             else if (rundata.getScreen().equals(SCREEN_NEWACCOUNT)) return TYPE_ENROLLMENT;
547             else if (rundata.getScreen().equals(SCREEN_EDIT_ACCOUNT)) return TYPE_EDIT_ACCOUNT;
548             else if (rundata.getScreen().equals(SCREEN_LOGIN)) return TYPE_LOGIN;
549         }
550 
551         return TYPE_HOME;
552     }
553 
554     /***
555      * <P>Gets the subtype of the URI (e.g. SUBTYPE_SAVE).</P>
556      * returns only the values<BR>
557      * <UL>
558      * <LI>SUBTYPE_NONE</LI>
559      * <LI>SUBTYPE_MAXIMIZE</LI>
560      * <LI>SUBTYPE_SAVE</LI>
561      * </UL>
562      * 
563      * @param aPortlet the related portlet
564      * @param rundata  the RunData object
565      * @return the type
566      * @exception JetspeedException
567      */
568     public static int getURISubType(Portlet aPortlet, RunData rundata)
569         throws JetspeedException
570     {
571         if (rundata.getAction()!=null)
572         {
573             if (rundata.getAction().equals(ACTION_ACCEPT_LOGIN)) return SUBTYPE_ACCEPT_LOGIN;
574             else if (rundata.getAction().equals(ACTION_LOGOUT)) return SUBTYPE_LOGOUT;
575         }
576 
577         String value = (String)rundata.getRequest().getParameter("type");
578 
579         if (value!=null)
580         {
581             if (value.equalsIgnoreCase("save")) return SUBTYPE_SAVE;
582         }
583 
584         if (aPortlet==null) throw new JetspeedException( "A portlet is required." );
585         
586         aPortlet = getRealPortlet(aPortlet);
587 
588         if (aPortlet.getName().equals(((JetspeedRunData)rundata).getPortlet()))
589         {
590             if ((rundata.getScreen()==null) || // no screen
591                 ( SCREEN_HOME.equals(rundata.getScreen())) ) // or Home-screen
592             {
593                 return SUBTYPE_MAXIMIZE;
594             }
595         }
596 
597         return SUBTYPE_NONE;
598     }
599 
600     /***
601      * Gets the user specific data stored in the URI.
602      * 
603      * @param rundata the RunData object
604      * @return the previous added user data
605      * @see #getURI
606      */
607     public static String getURIUserData(RunData rundata)
608     {
609         return rundata.getParameters().getString("info");
610     }
611 
612     /***
613      * returns the WebApplication base directory.
614      * 
615      * @param rundata the rundata object
616      * @return the URI
617      */
618     public static String getWebAppBaseDirURI(RunData rundata)
619     {
620         String ctxtPath = JetspeedResources.getString( JetspeedResources.CONTENT_ROOT_URL_KEY, "");
621         // Add port only if it is not default port for protocol
622         String port = "";
623         if( "http".equals( rundata.getServerScheme() ) &&
624             rundata.getServerPort() != 80 ) {
625             port += ":" + rundata.getServerPort();
626         }
627         if( "https".equals( rundata.getServerScheme() ) &&
628             rundata.getServerPort() != 443 ) {
629             port += ":" + rundata.getServerPort();
630         }
631         try {
632            ctxtPath = rundata.getRequest().getContextPath()+ctxtPath;
633         } catch (Exception e) {
634             // not servlet 2.2
635             logger.error( "Servlet container probably not 2.2", e );
636         }
637         return rundata.getServerScheme()+"://"+
638                rundata.getServerName()+
639                port + ctxtPath;
640     }
641 
642     /***
643      * Marks the current URI and stores it internally for later usage.
644      *
645      * @param rundata the RunData object
646      */
647     public static void markCurrentPage(RunData rundata)
648     {
649         javax.servlet.http.HttpSession session = rundata.getSession();
650         if (session != null) {
651             // delete action, if exists
652             String uri = replaceTurbineURIParameter(rundata.getRequest().getRequestURI(), "action", null );
653             
654             session.setAttribute("URILookup_MarkedPage",uri);
655 // for servlet api 2.0
656 //            session.putValue("URILookup_MarkedPage",uri);
657         }
658     }
659 
660     /***
661      * Marks the URI and stores it internally for later usage.
662      *
663      * @param aURI    the URI to store
664      * @param rundata the RunData object
665      */
666     public static void markPage(String aURI, RunData rundata)
667     {
668         javax.servlet.http.HttpSession session = rundata.getSession();
669         if (session != null) {
670            // delete action, if exists
671            aURI = replaceTurbineURIParameter(aURI, "action", null );
672 
673             session.setAttribute("URILookup_MarkedPage",aURI);
674 // for servlet api 2.0
675 //            session.putValue("URILookup_MarkedPage",aURI);
676         }
677     }
678 
679     /***
680      * Gets the previous marked page as relative url.<br>
681      * If no page was marked, the Jetspeed Home page is returned.
682      * 
683      * @return the marked page URI
684      */
685     public static String getMarkedPage(RunData rundata)
686     {
687         return getMarkedPage( rundata, true );
688     }
689 
690     /***
691      * Gets the previous marked page.<br>
692      * If no page was marked, the Jetspeed Home page is returned.
693      * 
694      * @param relative specifies whether the returing URI should be relative
695      * @return the marked page URI
696      */
697     public static String getMarkedPage(RunData rundata, boolean relative)
698     {
699         javax.servlet.http.HttpSession session = rundata.getSession();
700         if (session != null) {
701             String markedPage = (String)session.getAttribute("URILookup_MarkedPage");
702 // for servlet api 2.0
703 //            String markedPage = (String)session.getValue("URILookup_MarkedPage");
704             if ((markedPage!=null) && (relative)) {
705                 // check if the URL is absolute. If so, than make it relative
706                 int idx = markedPage.indexOf("://");
707                 if (idx!=-1) { // found it
708                     idx = markedPage.indexOf("/",idx+3); // search the next slash
709                     if (idx!=-1) { // this is the slash after host and port
710                         idx = markedPage.indexOf("/",idx+1); // search the next slash
711                         if (idx!=-1) { // this is the slash after context
712                             markedPage = markedPage.substring(idx);
713                         }
714                     }
715                 }
716             }
717             return markedPage;
718         }
719         return null;
720     }
721 
722     /***
723     <p>
724     Given a ParameterParser, get a PortletEntry.  This is used so that when you have a
725     URI created from PortletURIManager you can get back the PortletEntry that created
726     it originally.
727     </p>
728     <p>
729     Return null if we aren't able to figure out the PortletEntry
730     </p>
731     */
732     public static final PortletEntry getEntry( ParameterParser params ) throws Exception
733     {
734 
735         String name = params.getString("portlet");
736 
737         return (PortletEntry)Registry.getEntry(Registry.PORTLET, name );
738 
739     }
740 
741     /***
742     * <p>
743     * Checks that a Portlet is not a PortletControl. If it's a Control returns
744     * the non-controlled Portlet entry.
745     * </p>
746     *
747     * @return the portlet
748     */
749     private static Portlet getRealPortlet( Portlet portlet )
750     {
751 
752         while (portlet instanceof PortletControl) {
753             portlet = ((PortletControl)portlet).getPortlet();
754         }
755 
756         return portlet;
757     }
758 
759     /***
760      * Replaces a turbine-based parameter in the URI.<BR>
761      * /paramater/value/paramater/value/...
762      * 
763      * @param uri       the URI to modify
764      * @param parameter the parameter to be replaced
765      * @param value     the value
766      * @return the new URI
767      */
768     private static String replaceTurbineURIParameter( String uri, String parameter, String value)
769     {
770         int idx = uri.indexOf("/" + parameter + "/");
771         if (idx!=-1) {
772             int idx2 = uri.indexOf("/",idx+parameter.length()+2);
773             if (idx2==-1) // end of string
774               idx2 = uri.length();
775             uri = uri.substring(0,idx) + uri.substring(idx2);
776         }
777         if (value!=null) {
778             if (!uri.endsWith("/")) uri += "/";
779             uri += parameter + "/" + value;
780         }
781         return uri;
782     }
783 
784     /***
785      * removes all parameters of the URI (after the questionmark)<BR>
786      * (i.e. http://localhost/jetspeed?type=save to http://localhost/jetspeed)
787      * 
788      * @param uri    the URI t be modified
789      * @return the URI
790      */
791     private static String resetURIParameter( String uri )
792     {
793         if (uri.indexOf("?")!=-1) {
794             uri = uri.substring(0,uri.indexOf("?"));
795         }
796         return uri;
797     }
798 
799     /***
800      * appends the parameter/value pair to the URI
801      * 
802      * @param uri       the URI to be modified
803      * @param parameter the parameter to be added
804      * @param value     the parameter value
805      * @return the modified URI
806      */
807     private static String addURIParameter( String uri, String parameter, String value)
808     {
809         parameter = URIEncoder.encode( parameter );
810         value = URIEncoder.encode( value );
811         if (uri.indexOf("?")!=-1) {
812             int idx = uri.indexOf( parameter + "=", uri.indexOf("?"));
813             if (idx!=-1) { // parameter already in URI. remove it
814                 int idx2 = uri.indexOf("&", idx);
815                 if (idx2==-1) // end of string
816                     idx2 = uri.length();
817                 uri = uri.substring(0,idx) + uri.substring(idx2);
818             }
819         }
820         return addURIParameter( uri, parameter + "=" + value );
821     }
822 
823     /***
824      * appends the parameter/value pair to the URI
825      * 
826      * @param uri  the URI to be modified
827      * @param data the data to be added (has to be the correct format - paramater=value)    
828      * @return the modified URI
829      */
830     private static String addURIParameter( String uri,
831                                            String data)
832     {
833         if (uri.indexOf("?")!=-1) uri += "&";
834         else uri += "?";
835         uri += data;
836         return uri;
837     }
838     
839     private static final String SCREEN_INFO                        = "Info";
840     private static final String SCREEN_HOME                        = JetspeedResources.getString( "template.homepage" );
841 //    private static final String SCREEN_CUSTOMIZE                   = "Customize";
842     private static final String SCREEN_CUSTOMIZE                   = JetspeedResources.getString( "customizer.screen" );
843     private static final String SCREEN_LOGIN                       = JetspeedResources.getString( "template.login" );
844     private static final String SCREEN_NEWACCOUNT                  = "NewAccount";
845     private static final String SCREEN_EDIT_ACCOUNT                = "EditAccount";
846 
847     private static final String ACTION_CUSTOMIZER                  = JetspeedResources.getString( "customizer.action" );
848     private static final String ACTION_MARKPAGE                    = "MarkRefPage";
849     private static final String ACTION_LOGOUT                      = JetspeedResources.getString( "action.logout" );
850     private static final String ACTION_ACCEPT_LOGIN                = JetspeedResources.getString( "action.login" );
851     private static final String ACTION_CUSTOMIZER_SAVE             = "SavePageConfig";
852     private static final String ACTION_PREPARE_SCREEN_EDIT_ACCOUNT = "PrepareScreenEditAccount";
853 }