View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.jsr168.pluto.core;
35  
36  import org.apache.pluto.om.common.ObjectID;
37  import org.apache.pluto.portalImpl.om.window.impl.PortletWindowImpl;
38  
39  import java.net.URLEncoder;
40  
41  import java.util.Iterator;
42  import java.util.Map;
43  
44  import javax.portlet.PortletMode;
45  import javax.portlet.WindowState;
46  
47  import javax.servlet.http.HttpServletRequest;
48  
49  
50  /**
51   * Define
52   */
53  public class PortalURL
54  {
55      /**
56       * Prefix all parameters
57       */
58      public static final String PREFIX = "_";
59  
60      /**
61       * Portlet ID request parameter name
62       */
63      private static final String PORTLET_ID = "pid";
64  
65      /**
66       * Portlet mode request parameter name
67       */
68      private static final String MODE = "md";
69  
70      /**
71       * Window state request parameter name
72       */
73      private static final String STATE = "st";
74  
75      /**
76       * Indicate an URL action (request parameter name)
77       */
78      private static final String ACTION = "ac";
79  
80      /**
81       * Indicate if it's a portal action URL
82       */
83      private final boolean _bAction;
84  
85      /**
86       * Portlet mode associate to this portal URL
87       */
88      private final PortletMode _portletMode;
89  
90      /**
91       * Portlet state associate to this portal URL
92       */
93      private final WindowState _windowState;
94  
95      /**
96       * Construct a PortletURL instance<br>
97       *
98       * TODO need to extract render parameters?
99       *
100      * @param request A HTTP request who define action, mode and state
101      */
102     public PortalURL( HttpServletRequest request )
103     {
104         _bAction = extractAction( request );
105         _portletMode = extractMode( request );
106         _windowState = extractState( request );
107     }
108 
109     /**
110      * Return <code>true</code> to indicate an action URL.
111      *
112      * @return <code>true</code> to indicate an action URL
113      */
114     public boolean isAction(  )
115     {
116         return _bAction;
117     }
118 
119     /**
120      * Return the portlet mode associate to this URL.
121      *
122      * @return portlet mode associate to this URL
123      */
124     public PortletMode getPortletMode(  )
125     {
126         return _portletMode;
127     }
128 
129     /**
130      * Return the window state associate to this URL.
131      *
132      * @return window state associate to this URL
133      */
134     public WindowState getWindowState(  )
135     {
136         return _windowState;
137     }
138 
139     /**
140      * Fill a portlet window with state and mode values
141      *
142      * @param portletWindow The portlet window to fill with defined state and mode
143      */
144     public void fillWindowPortlet( PortletWindowImpl portletWindow )
145     {
146         if ( getPortletMode(  ) != null )
147         {
148             portletWindow.setPortletMode( getPortletMode(  ) );
149         }
150 
151         if ( getWindowState(  ) != null )
152         {
153             portletWindow.setWindowState( getWindowState(  ) );
154         }
155     }
156 
157     /**
158      * Build URL parameters list
159      *
160      * @param portletID Portlet ID of the portlet target
161      * @param bAction Indicate an action URL (vs a render URL)
162      * @param portletMode Current portlet mode
163      * @param windowState Current portlet window state
164      * @param parameters Map of parameters (the map must be typed &lt;String, String&gt; or &lt;String, String[]&gt;)
165      * @return The URL parameters fragment<br>
166      *                 for example:
167      *                 <li>Portlet ID: 15</li>
168      *                 <li>Ask for an action URL</li>
169      *                 <li>Parameters: value=&quot;295&quot;, action=&quot;set&quot;, field=&quot;day&quot;</li><br>
170      *                 will return the string&nbsp;: &quot;_pid=15&amp;_ac=1&amp;value=295&amp;action=set&amp;field=day&quot;
171      */
172     public static String buildParams( ObjectID portletID, boolean bAction, PortletMode portletMode,
173         WindowState windowState, Map parameters )
174     {
175         StringBuffer buf = new StringBuffer(  );
176         String sep = "";
177 
178         String portletIdParam = buildPortletIDParam( portletID );
179 
180         if ( ( portletIdParam != null ) && ( portletIdParam.length(  ) > 0 ) )
181         {
182             buf.append( sep ).append( portletIdParam );
183             sep = "&";
184         }
185 
186         String actionParam = buildActionParam( bAction );
187 
188         if ( ( actionParam != null ) && ( actionParam.length(  ) > 0 ) )
189         {
190             buf.append( sep ).append( actionParam );
191             sep = "&";
192         }
193 
194         String modeParam = buildModeParam( portletMode );
195 
196         if ( ( modeParam != null ) && ( modeParam.length(  ) > 0 ) )
197         {
198             buf.append( sep ).append( modeParam );
199             sep = "&";
200         }
201 
202         String stateParam = buildStateParam( windowState );
203 
204         if ( ( stateParam != null ) && ( stateParam.length(  ) > 0 ) )
205         {
206             buf.append( sep ).append( stateParam );
207             sep = "&";
208         }
209 
210         String renderParams = buildParameterParam( parameters );
211 
212         if ( ( renderParams != null ) && ( renderParams.length(  ) > 0 ) )
213         {
214             buf.append( sep ).append( renderParams );
215             sep = "&";
216         }
217 
218         return buf.toString(  );
219     }
220 
221     /**
222      * Extract the porlet ID from an HTTP request
223      *
224      * @param servletRequest The HTTP request
225      * @return the porlet ID defined by an HTTP request
226      */
227     public static String extractPortletId( HttpServletRequest servletRequest )
228     {
229         return servletRequest.getParameter( getPortletIdKey(  ) );
230     }
231 
232     /**
233      * Indicate if an HTTP request is an action
234      *
235      * @param servletRequest The HTTP request
236      * @return <code>true</code> if the HTTP request is a portlet action request
237      */
238     public static boolean isActionURL( HttpServletRequest servletRequest )
239     {
240         final String actionParam = servletRequest.getParameter( getActionKey(  ) );
241 
242         return ( actionParam != null );
243     }
244 
245     /**
246      * Build URL parameters fragment that contain the &quot;portlet ID&quot;
247      *
248      * @param portletID Portlet ID of the portlet target
249      * @return The URL fragment that contain portlet ID
250      */
251     private static String buildPortletIDParam( ObjectID portletID )
252     {
253         if ( portletID != null )
254         {
255             return getPortletIdKey(  ) + "=" + portletID;
256         }
257 
258         return null;
259     }
260 
261     /**
262      * Build URL parameters fragment that contain the indication of &quot;action portlet request&quot;
263      *
264      * @param bAction Indicate an action URL (vs a render URL)
265      * @return The URL fragment that contain action identification
266      */
267     private static String buildActionParam( final boolean bAction )
268     {
269         if ( bAction )
270         {
271             return getActionKey(  ) + "=" + 1;
272         }
273 
274         return null;
275     }
276 
277     /**
278      * Indicate if an HTTP request is an action portlet request
279      *
280      * @param servletRequest The HTTP request
281      * @return <code>true</code> if the request is an action portlet request
282      */
283     private static boolean extractAction( HttpServletRequest servletRequest )
284     {
285         String actionStr = servletRequest.getParameter( getActionKey(  ) );
286 
287         return ( actionStr != null );
288     }
289 
290     /**
291      * Build URL parameters fragment that contain the &quot;portlet mode&quot;
292      *
293      * @param portletMode Portlet mode to encode
294      * @return The URL fragment that contain the encoded portlet mode
295      */
296     private static String buildModeParam( PortletMode portletMode )
297     {
298         if ( portletMode != null )
299         {
300             return getModeKey(  ) + "=" + portletMode;
301         }
302 
303         return null;
304     }
305 
306     /**
307      * Extract portlet mode from an HTTP request
308      *
309      * @param servletRequest The HTTP request
310      * @return The portlet mode contained in HTTP request (<code>null</code> if no
311      * portlet mode is in URL)
312      */
313     private static PortletMode extractMode( HttpServletRequest servletRequest )
314     {
315         String mode = servletRequest.getParameter( getModeKey(  ) );
316 
317         if ( mode != null )
318         {
319             return new PortletMode( mode );
320         }
321 
322         return null;
323     }
324 
325     /**
326     * Build URL parameters fragment that contain the &quot;window state&quot;
327     *
328     * @param windowState Portlet mode to encode
329     * @return The URL fragment that contain the encoded window state
330      */
331     private static String buildStateParam( WindowState windowState )
332     {
333         if ( windowState != null )
334         {
335             return getStateKey(  ) + "=" + windowState;
336         }
337 
338         return null;
339     }
340 
341     /**
342      * Extract window state from an HTTP request
343      *
344      * @param servletRequest The HTTP request
345      * @return The window state contained in HTTP request (<code>null</code> if no
346      * window state is in URL)
347      */
348     private static WindowState extractState( HttpServletRequest servletRequest )
349     {
350         String state = servletRequest.getParameter( getStateKey(  ) );
351 
352         if ( state != null )
353         {
354             return new WindowState( state );
355         }
356 
357         return null;
358     }
359 
360     /**
361      * Build URL parameters for parameters contained in <code>renderParams</code>
362      *
363      * @param mapRenderParams The list of parameters
364      * @return URL of parameters list
365      */
366     private static String buildParameterParam( Map mapRenderParams )
367     {
368         String sep = "";
369         StringBuffer buf = new StringBuffer(  );
370         Iterator entriesIt = mapRenderParams.entrySet(  ).iterator(  );
371 
372         while ( entriesIt.hasNext(  ) )
373         {
374             Map.Entry entry = (Map.Entry) entriesIt.next(  );
375             Object key = entry.getKey(  );
376             Object val = entry.getValue(  );
377 
378             // si val est null tant pis, c'est a PortletWindowImpl
379             // d'assumer (ou de deleguer) le controle des parametres!
380             // idem si la valeur n'est pas de type String[].
381             // Vivement J2SE 1.5!
382             if ( ( key == null ) || !( key instanceof String ) )
383             {
384                 continue;
385             }
386 
387             if ( val == null )
388             {
389                 continue;
390             }
391 
392             final String encKey = URLEncoder.encode( (String) key );
393 
394             // TODO key is encoded... reading the key will be safe to decode the key (JSR 168 PLT.7.1) 
395             if ( val instanceof String )
396             {
397                 String vals = (String) val;
398                 String encVal = URLEncoder.encode( (String) vals );
399                 buf.append( sep ).append( encKey ).append( '=' ).append( encVal );
400                 sep = "&";
401             }
402             else if ( val instanceof String[] )
403             {
404                 String[] vals = (String[]) val;
405 
406                 for ( int i = 0; i < vals.length; ++i )
407                 {
408                     String encVal = URLEncoder.encode( (String) vals[i] );
409                     buf.append( sep ).append( encKey ).append( '=' ).append( encVal );
410                     sep = "&";
411                 }
412             }
413         }
414 
415         return buf.toString(  );
416     }
417 
418     /**
419      * Return the action URL parameter name
420      *
421      * @return the action URL parameter name
422      */
423     private static String getActionKey(  )
424     {
425         return PREFIX + ACTION;
426     }
427 
428     /**
429      * Return the portlet ID URL parameter name
430      *
431      * @return the portlet ID URL parameter name
432      */
433     private static String getPortletIdKey(  )
434     {
435         return PREFIX + PORTLET_ID;
436     }
437 
438     /**
439      * Return the portlet mode URL parameter name
440      *
441      * @return the portlet mode URL parameter name
442      */
443     private static String getModeKey(  )
444     {
445         return PREFIX + MODE;
446     }
447 
448     /**
449      * Return the window state URL parameter name
450      *
451      * @return the window state URL parameter name
452      */
453     private static String getStateKey(  )
454     {
455         return PREFIX + STATE;
456     }
457 }