View Javadoc
1   /*
2    * Copyright (c) 2002-2014, 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.portal.service.util;
35  
36  import fr.paris.lutece.portal.service.datastore.DatastoreService;
37  import fr.paris.lutece.portal.service.message.SiteMessageService;
38  import fr.paris.lutece.portal.web.LocalVariables;
39  import fr.paris.lutece.portal.web.constants.Parameters;
40  import fr.paris.lutece.util.ReferenceList;
41  import fr.paris.lutece.util.string.StringUtil;
42  import fr.paris.lutece.util.url.UrlItem;
43  
44  import org.apache.commons.lang.StringUtils;
45  
46  import java.io.File;
47  import java.io.FileInputStream;
48  import java.io.IOException;
49  
50  import java.text.MessageFormat;
51  
52  import java.util.Enumeration;
53  import java.util.StringTokenizer;
54  
55  import javax.servlet.ServletContext;
56  import javax.servlet.http.HttpServletRequest;
57  import javax.servlet.http.HttpSession;
58  
59  
60  /**
61   * this class provides services for locate repository or url
62   */
63  public final class AppPathService
64  {
65      public static final String SESSION_BASE_URL = "base_url";
66      private static final String MSG_LOG_PROPERTY_NOT_FOUND = "Property {0} not found in the properties file ";
67      private static final int PORT_NUMBER_HTTP = 80;
68      private static final String PROPERTY_BASE_URL = "lutece.base.url";
69      private static final String PROPERTY_PORTAL_URL = "lutece.portal.path";
70      private static final String PROPERTY_SITE_MESSAGE_URL = "lutece.siteMessage.path";
71      private static final String PROPERTY_ADMIN_URL = "lutece.admin.path";
72      private static final String PROPERTY_ADMIN_MENU_URL = "lutece.admin.menu.url";
73      private static final String PROPERTY_PORTAL_REDIRECT_URL = "lutece.portal.redirect.url";
74      private static final String PROPERTY_VIRTUAL_HOST_KEYS = "virtualHostKeys";
75      private static final String PROPERTY_VIRTUAL_HOST_KEY_PARAMETER = "virtualHostKey.parameterName";
76      private static final String PROPERTY_VIRTUAL_HOST = "virtualHost.";
77      private static final String PROPERTY_PREFIX_URL = "url.";
78      private static final String PROPERTY_PROD_BASE_URL = "lutece.prod.url";
79      private static final String PROPERTY_INSTANCE = "lutece.webapp.instance";
80      private static final String INSTANCE_DEFAULT = "default";
81      private static final String SUFFIX_BASE_URL = ".baseUrl";
82      private static final String SUFFIX_DESCRIPTION = ".description";
83      private static final String SLASH = "/";
84      private static final String DOUBLE_POINTS = ":";
85  
86      // Datastore keys
87      private static final String KEY_ADMIN_HOME_URL = "portal.site.site_property.admin_home_url";
88      private static final String KEY_PORTAL_HOME_URL = "portal.site.site_property.home_url";
89      private static String _strWebAppPath;
90  
91      /**
92       * Creates a new AppPathService object.
93       */
94      private AppPathService(  )
95      {
96      }
97  
98      /**
99       * Initialize The path service
100      *
101      * @param context The servlet context
102      */
103     public static void init( ServletContext context )
104     {
105         String strRealPath = context.getRealPath( "/" );
106         _strWebAppPath = normalizeWebappPath( strRealPath );
107     }
108 
109     /**
110      * Initialize The webapppath
111      *
112      * @param strWebAppPath The Webapp path
113      */
114     public static void init( String strWebAppPath )
115     {
116         _strWebAppPath = strWebAppPath;
117     }
118 
119     /**
120      * Returns the absolute path of a repository from a relative definition in
121      * properties file
122      *
123      *
124      * @return the repository absolute path
125      * @param strKey the repository key definied in properties file
126      */
127     public static String getPath( String strKey )
128     {
129         // Adds relative path found from strKey
130         String strDirectory = AppPropertiesService.getProperty( strKey );
131 
132         if ( strDirectory == null )
133         {
134             Object[] propertyMissing = { strKey };
135             String strMsg = MessageFormat.format( MSG_LOG_PROPERTY_NOT_FOUND, propertyMissing );
136             throw new AppException( strMsg );
137         }
138 
139         return getWebAppPath(  ) + strDirectory;
140     }
141 
142     /**
143      * Returns the webapp path from the properties file
144      *
145      *
146      * @return the webapp path
147      */
148     public static String getWebAppPath(  )
149     {
150         return _strWebAppPath;
151     }
152 
153     /**
154      * Returns the absolute path of file from its relative definition in
155      * properties file.
156      *
157      * @param strKey the repository key defined in properties file
158      * @param strFilename The name of file
159      * @return the absolute path of file
160      */
161     public static String getPath( String strKey, String strFilename )
162     {
163         return getPath( strKey ) + SLASH + strFilename;
164     }
165 
166     /**
167      * Gets a file as stream
168      *
169      * @param strPath the path
170      * @param strFilename The name of file
171      * @return a FileInput Stream object
172      */
173     public static FileInputStream getResourceAsStream( String strPath, String strFilename )
174     {
175         String strFilePath = getWebAppPath(  ) + strPath + strFilename;
176 
177         try
178         {
179             File file = new File( strFilePath );
180             FileInputStream fis = new FileInputStream( file );
181 
182             return fis;
183         }
184         catch ( IOException e )
185         {
186             throw new AppException( "Unable to get file : " + strFilePath );
187         }
188     }
189 
190     /**
191      * Returns the absolute path of a repository from a relative path
192      *
193      *
194      * @return the repository absolute path
195      * @param strDirectory the relative path
196      */
197     public static String getAbsolutePathFromRelativePath( String strDirectory )
198     {
199         return _strWebAppPath + strDirectory;
200     }
201 
202     /**
203      * Return the url of the webapp, built from the request
204      *
205      * @param request The HttpServletRequest
206      * @return strBase the webapp url
207      */
208     public static String getBaseUrl( HttpServletRequest request )
209     {
210         if ( request == null )
211         {
212             return getBaseUrl(  );
213         }
214 
215         String strBase;
216 
217         // Search for a Virtual Host Base Url defined in the request
218         strBase = getVirtualHostBaseUrl( request );
219 
220         // If not found, get the base url from session
221         if ( ( strBase == null ) || strBase.equals( StringUtils.EMPTY ) )
222         {
223             HttpSession session = request.getSession( false );
224 
225             if ( session != null )
226             {
227                 Object oBase = session.getAttribute( SESSION_BASE_URL );
228 
229                 if ( oBase != null )
230                 {
231                     strBase = (String) oBase;
232                 }
233             }
234         }
235 
236         // If not found, get the base url from the config.properties
237         if ( ( strBase == null ) || ( strBase.equals( StringUtils.EMPTY ) ) )
238         {
239             strBase = AppPropertiesService.getProperty( PROPERTY_BASE_URL );
240         }
241 
242         if ( ( strBase == null ) || ( strBase.equals( StringUtils.EMPTY ) ) )
243         {
244             // Dynamic base URL if not defined in the properties
245             strBase = request.getScheme(  ) + DOUBLE_POINTS + SLASH + SLASH + request.getServerName(  );
246 
247             int nPort = request.getServerPort(  );
248 
249             if ( nPort != PORT_NUMBER_HTTP )
250             {
251                 strBase += ( DOUBLE_POINTS + nPort );
252             }
253 
254             strBase += request.getContextPath(  );
255         }
256 
257         if ( !strBase.endsWith( SLASH ) )
258         {
259             strBase += SLASH;
260         }
261 
262         return strBase;
263     }
264 
265     /**
266      * Return the url of the webapp. The method should only be used out of
267      * request context (by daemons for example). If there is a request context,
268      * use {@link AppPathService#getBaseUrl(HttpServletRequest)} instead.
269      *
270      * @return The webapp url, or null if the 'lutece.base.url' property has not
271      *         been set.
272      * @deprecated Use {@link AppPathService#getBaseUrl(HttpServletRequest)}
273      *             instead
274      */
275     @Deprecated
276     public static String getBaseUrl(  )
277     {
278         HttpServletRequest request = LocalVariables.getRequest(  );
279 
280         if ( request != null )
281         {
282             return getBaseUrl( request );
283         }
284 
285         // FIXME : lutece.base.url is only set when using WSSO
286         String strBaseUrl = AppPropertiesService.getProperty( PROPERTY_BASE_URL );
287 
288         if ( strBaseUrl == null )
289         {
290             strBaseUrl = StringUtils.EMPTY;
291         }
292         else
293         {
294             if ( !strBaseUrl.endsWith( SLASH ) )
295             {
296                 strBaseUrl += SLASH;
297             }
298         }
299 
300         return strBaseUrl;
301     }
302 
303     /**
304      * Return the webapp prod url (or the base url if no prod url has been
305      * definied).
306      *
307      * @param request The HTTP request
308      * @return The prod url
309      */
310     public static String getProdUrl( HttpServletRequest request )
311     {
312         String strBaseUrl = AppPropertiesService.getProperty( PROPERTY_PROD_BASE_URL );
313 
314         if ( StringUtils.isBlank( strBaseUrl ) )
315         {
316             strBaseUrl = getBaseUrl( request );
317         }
318 
319         if ( !strBaseUrl.endsWith( SLASH ) )
320         {
321             strBaseUrl += SLASH;
322         }
323 
324         return strBaseUrl;
325     }
326 
327     /**
328      * Return the webapp prod url (or the base url if no prod url has been
329      * definied)
330      *
331      * @return The prod url
332      * @deprecated Use {@link AppPathService#getProdUrl(String)} instead
333      */
334     @Deprecated
335     public static String getProdUrl(  )
336     {
337         return getProdUrl( getBaseUrl(  ) );
338     }
339 
340     /**
341      * Return the webapp prod url. If no prod URL has been defined, then the
342      * base URL is returned
343      *
344      * @param strBaseUrl The base URL
345      * @return The prod url
346      */
347     public static String getProdUrl( String strBaseUrl )
348     {
349         String strProdUrl = AppPropertiesService.getProperty( PROPERTY_PROD_BASE_URL );
350 
351         if ( StringUtils.isBlank( strProdUrl ) )
352         {
353             strProdUrl = strBaseUrl;
354         }
355 
356         if ( ( strProdUrl != null ) && !strProdUrl.endsWith( SLASH ) )
357         {
358             strProdUrl += SLASH;
359         }
360 
361         return strProdUrl;
362     }
363 
364     /**
365      * Return the url of the webapp, built from the request
366      *
367      * @param request The HttpServletRequest
368      * @return strBase the webapp url
369      */
370     public static String getSiteMessageUrl( HttpServletRequest request )
371     {
372         // Set the site message url
373         return SiteMessageService.setSiteMessageUrl( getBaseUrl( request ) + getSiteMessageUrl(  ) );
374     }
375 
376     /**
377      * Returns the portal page relative url (jsp/site/Portal.jsp) defined in
378      * lutece.properties
379      *
380      * @return the Portal Url
381      */
382     public static String getPortalUrl(  )
383     {
384         return AppPropertiesService.getProperty( PROPERTY_PORTAL_URL );
385     }
386 
387     /**
388      * Returns the forward URL for webapp's root path. Default is
389      * (jsp/site/Portal.jsp) defined in lutece.properties
390      *
391      * @return the Portal Root forward Url
392      */
393     public static String getRootForwardUrl(  )
394     {
395         return DatastoreService.getDataValue( KEY_PORTAL_HOME_URL,
396             AppPropertiesService.getProperty( PROPERTY_PORTAL_REDIRECT_URL ) );
397     }
398 
399     /**
400      * Returns the Site Message relative url (jsp/site/SiteMessage.jsp) defined
401      * in lutece.properties
402      *
403      * @return the SiteMessage Url
404      */
405     public static String getSiteMessageUrl(  )
406     {
407         return AppPropertiesService.getProperty( PROPERTY_SITE_MESSAGE_URL );
408     }
409 
410     /**
411      * Returns the admin portal page relative url (jsp/admin/site/AdminSite.jsp)
412      * defined in lutece.properties
413      *
414      * @return the Portal Url
415      */
416     public static String getAdminPortalUrl(  )
417     {
418         return AppPropertiesService.getProperty( PROPERTY_ADMIN_URL );
419     }
420 
421     /**
422      * Returns the admin menu page relative url (jsp/admin/site/AdminMenu.jsp)
423      * defined in lutece.properties
424      *
425      * @return the Admin Menu Url
426      */
427     public static String getAdminMenuUrl(  )
428     {
429         return DatastoreService.getDataValue( KEY_ADMIN_HOME_URL,
430             AppPropertiesService.getProperty( PROPERTY_ADMIN_MENU_URL ) );
431     }
432 
433     /**
434      * Normalizes the Webapp Path
435      *
436      * @param strPath The path to normalize
437      * @return The normalized path
438      */
439     private static String normalizeWebappPath( String strPath )
440     {
441         // convert Windows path separator if present
442         String strNormalized = StringUtil.substitute( strPath, "/", "\\" );
443 
444         // remove the ending separator if present
445         if ( strNormalized.endsWith( "/" ) )
446         {
447             strNormalized = strNormalized.substring( 0, strNormalized.length(  ) - 1 );
448         }
449 
450         return strNormalized;
451     }
452 
453     ////////////////////////////////////////////////////////////////////////////
454     // Multiple virtual hosts configuration management
455     /**
456      * Gets available virtual hosts defined in the config.properties
457      *
458      * @return A reference list containing the key and the description of each
459      *         virtual host configuration. The list is empty if there is no
460      *         configuration defined.
461      */
462     public static ReferenceList getAvailableVirtualHosts(  )
463     {
464         ReferenceList list = null;
465 
466         // Get keys list form config.properties
467         String strKeysList = AppPropertiesService.getProperty( PROPERTY_VIRTUAL_HOST_KEYS );
468 
469         if ( strKeysList != null )
470         {
471             list = new ReferenceList(  );
472 
473             // Extracts each key (separated by a comma)
474             StringTokenizer strTokens = new StringTokenizer( strKeysList, "," );
475 
476             while ( strTokens.hasMoreTokens(  ) )
477             {
478                 String strHostKey = strTokens.nextToken(  );
479                 String strHostKeyDescription = AppPropertiesService.getProperty( PROPERTY_VIRTUAL_HOST + strHostKey +
480                         SUFFIX_DESCRIPTION );
481                 list.addItem( strHostKey, strHostKeyDescription );
482             }
483         }
484 
485         return list;
486     }
487 
488     /**
489      * Gets a Virtual Host Key if the request contains a virtual host key
490      *
491      * @param request The HTTP request
492      * @return A Virtual Host Key if present, otherwise null.
493      */
494     public static String getVirtualHostKey( HttpServletRequest request )
495     {
496         String strVirtalHostKey = null;
497 
498         // Get from config.properties the parameter name for virtual host keys
499         String strVirtualHostKeyParameter = AppPropertiesService.getProperty( PROPERTY_VIRTUAL_HOST_KEY_PARAMETER );
500 
501         if ( ( request != null ) && ( strVirtualHostKeyParameter != null ) &&
502                 ( !strVirtualHostKeyParameter.equals( "" ) ) )
503         {
504             // Search for this parameter into the request
505             strVirtalHostKey = request.getParameter( strVirtualHostKeyParameter );
506         }
507 
508         return strVirtalHostKey;
509     }
510 
511     /**
512      * Gets a Base Url for a virtual host if the request contains a virtual host
513      * key
514      *
515      * @param request The HTTP request
516      * @return A virtual host base url if present, otherwise null.
517      */
518     private static String getVirtualHostBaseUrl( HttpServletRequest request )
519     {
520         String strBaseUrl = null;
521         String strVirtalHostKey = getVirtualHostKey( request );
522 
523         if ( ( strVirtalHostKey != null ) && ( !strVirtalHostKey.equals( "" ) ) )
524         {
525             // If found gets the Base url for this virtual host by its key
526             strBaseUrl = AppPropertiesService.getProperty( PROPERTY_VIRTUAL_HOST + strVirtalHostKey + SUFFIX_BASE_URL );
527         }
528 
529         return strBaseUrl;
530     }
531 
532     /**
533      * Build the url item to use for a url that includes the redirection
534      * parameter for reconnection.
535      *
536      * @param strRootUrl the root part of the url, to build an absolute url
537      * @param strUrlPropertySuffixKey The property suffix to retrieve the url
538      * @return an absolute url, completed with the redirectUrl parameter
539      *         (contains the relative part of the url), as an UrlItem
540      */
541     public static UrlItem buildRedirectUrlItem( String strRootUrl, String strUrlPropertySuffixKey )
542     {
543         String strUrl = AppPropertiesService.getProperty( PROPERTY_PREFIX_URL + strUrlPropertySuffixKey );
544         UrlItem url = new UrlItem( strRootUrl + strUrl );
545         url.addParameter( Parameters.REDIRECT_URL, strUrlPropertySuffixKey );
546 
547         return url;
548     }
549 
550     /**
551      * Retrieve the url to redirect to after login. It is given by the
552      * redirectUrl parameter if found. The request parameters are copied (except
553      * the login and acces code). This is to be used by the doLogin method of
554      * AdminLoginJspBean.
555      *
556      * @param request the http request
557      * @param strDefaultRedirectUrl the default url to go to after login
558      * @return an UrlItem corresponding to the url to redirect to after login.
559      */
560     public static UrlItem resolveRedirectUrl( HttpServletRequest request, String strDefaultRedirectUrl )
561     {
562         String strUrl = strDefaultRedirectUrl;
563 
564         String strUrlKey = request.getParameter( Parameters.REDIRECT_URL );
565         String strRedirectUrl = null;
566 
567         if ( strUrlKey != null )
568         {
569             strRedirectUrl = AppPropertiesService.getProperty( PROPERTY_PREFIX_URL + strUrlKey );
570         }
571 
572         if ( strRedirectUrl != null )
573         {
574             strUrl = strRedirectUrl;
575         }
576 
577         Enumeration enumParams = request.getParameterNames(  );
578         UrlItem url = new UrlItem( getBaseUrl( request ) + strUrl );
579 
580         String strParamName;
581 
582         while ( enumParams.hasMoreElements(  ) )
583         {
584             strParamName = (String) enumParams.nextElement(  );
585 
586             if ( !strParamName.equals( Parameters.REDIRECT_URL ) && !strParamName.equals( Parameters.ACCESS_CODE ) &&
587                     !strParamName.equals( Parameters.PASSWORD ) )
588             {
589                 url.addParameter( strParamName, request.getParameter( strParamName ) );
590             }
591         }
592 
593         return url;
594     }
595 
596     /**
597      * Returns the absolute url corresponding to the given one, if the later was
598      * found to be relative. An url starting with "http://" is absolute. A
599      * relative url should be given relatively to the webapp root.
600      *
601      * @param request the http request (provides the base path if needed)
602      * @param strUrl the url to transform
603      * @return the corresonding absolute url
604      *
605      *
606      */
607     public static String getAbsoluteUrl( HttpServletRequest request, String strUrl )
608     {
609         if ( ( strUrl != null ) && !strUrl.startsWith( "http://" ) && !strUrl.startsWith( "https://" ) )
610         {
611             return AppPathService.getBaseUrl( request ) + strUrl;
612         }
613 
614         return strUrl;
615     }
616 
617     /**
618      * Gets the webapp instance defined in the config.properties file with the
619      * key lutece.webapp.instance
620      *
621      * @return The instance name
622      * @since 4.1
623      */
624     public static String getWebappInstance(  )
625     {
626         String strInstance = AppPropertiesService.getProperty( PROPERTY_INSTANCE );
627 
628         if ( ( strInstance != null ) && ( !strInstance.equals( StringUtils.EMPTY ) ) )
629         {
630             return strInstance;
631         }
632 
633         return INSTANCE_DEFAULT;
634     }
635 
636     /**
637      * Returns whether the current instance is the default webapp instance
638      *
639      * @return true if default, otherwise false
640      */
641     public static boolean isDefaultWebappInstance(  )
642     {
643         return INSTANCE_DEFAULT.equals( getWebappInstance(  ) );
644     }
645 }