View Javadoc
1   /*
2    * Copyright (c) 2002-2022, City of 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.portal;
35  
36  import fr.paris.lutece.portal.service.content.ContentService;
37  import fr.paris.lutece.portal.service.content.PageData;
38  import fr.paris.lutece.portal.service.content.XPageAppService;
39  import fr.paris.lutece.portal.service.includes.PageInclude;
40  import fr.paris.lutece.portal.service.includes.PageIncludeService;
41  import fr.paris.lutece.portal.service.message.SiteMessage;
42  import fr.paris.lutece.portal.service.message.SiteMessageException;
43  import fr.paris.lutece.portal.service.message.SiteMessageService;
44  import fr.paris.lutece.portal.service.security.UserNotSignedException;
45  import fr.paris.lutece.portal.service.template.AppTemplateService;
46  import fr.paris.lutece.portal.service.util.AppLogService;
47  import fr.paris.lutece.portal.service.util.AppPathService;
48  import fr.paris.lutece.portal.web.constants.Markers;
49  import fr.paris.lutece.portal.web.xpages.XPage;
50  import fr.paris.lutece.portal.web.xpages.XPageApplication;
51  import fr.paris.lutece.portal.web.xpages.XPageApplicationEntry;
52  import fr.paris.lutece.util.html.HtmlTemplate;
53  import fr.paris.lutece.util.http.SecurityUtil;
54  
55  import java.io.File;
56  
57  import java.util.Collection;
58  import java.util.HashMap;
59  
60  import javax.servlet.http.HttpServletRequest;
61  
62  /**
63   * This class delivers Extra pages (xpages) to web components. An XPage is a page where the content is provided by a specific class, but should be integrated
64   * into the portal struture and design. XPageApps are identified by a key name. To display an XPage into the portal just call the following url :<br>
65   * <code>
66   * RunStandaloneApp.jsp?page=<i>keyname</i>&amp;param1=value1&amp; ...&amp;paramN=valueN </code>
67   *
68   * @see fr.paris.lutece.portal.web.xpages.XPage
69   */
70  public class StandaloneAppService extends ContentService
71  {
72      public static final String PARAM_STANDALONE_APP = "page";
73      private static final String PROPERTY_PATH_LUTECE_PLUGINS = "path.lutece.plugins";
74      private static final String TEMPLATE_PAGE_FRAMESET = "page_frameset.html";
75      private static final String TEMPLATE_STANDALONE_PAGE_FRAMESET = "skin/site/standalone_app_frameset.html";
76      private static final String CONTENT_SERVICE_NAME = "StandaloneAppService";
77      private static final String MESSAGE_ERROR_APP_BODY = "portal.util.message.errorXpageApp";
78  
79      /**
80       * Returns the Content Service name
81       *
82       * @return The name as a String
83       */
84      @Override
85      public String getName( )
86      {
87          return CONTENT_SERVICE_NAME;
88      }
89  
90      /**
91       * Analyzes request parameters to see if the request should be handled by the current Content Service
92       *
93       * @param request
94       *            The HTTP request
95       * @return true if this ContentService should handle this request
96       */
97      @Override
98      public boolean isInvoked( HttpServletRequest request )
99      {
100         String strStandaloneApp = request.getParameter( PARAM_STANDALONE_APP );
101 
102         return ( strStandaloneApp != null ) && ( strStandaloneApp.length( ) > 0 );
103     }
104 
105     /**
106      * Enable or disable the cache feature.
107      *
108      * @param bCache
109      *            true to enable the cache, false to disable
110      */
111     public void setCache( boolean bCache )
112     {
113         // Do nothing
114     }
115 
116     /**
117      * Gets the current cache status.
118      *
119      * @return true if enable, otherwise false
120      */
121     @Override
122     public boolean isCacheEnable( )
123     {
124         return false;
125     }
126 
127     /**
128      * Reset the cache.
129      */
130     @Override
131     public void resetCache( )
132     {
133         // Do nothing
134     }
135 
136     /**
137      * Gets the number of item currently in the cache.
138      *
139      * @return the number of item currently in the cache.
140      */
141     @Override
142     public int getCacheSize( )
143     {
144         return 0;
145     }
146 
147     /**
148      * Build the XPage content.
149      *
150      * @param request
151      *            The HTTP request.
152      * @param nMode
153      *            The current mode.
154      * @return The HTML code of the page.
155      * @throws UserNotSignedException
156      *             a userNotSignedException
157      * @throws SiteMessageException
158      *             occurs when a site message need to be displayed
159      */
160     @Override
161     public String getPage( HttpServletRequest request, int nMode ) throws UserNotSignedException, SiteMessageException
162     {
163         // Gets XPage info from the lutece.properties
164         String strName = request.getParameter( PARAM_STANDALONE_APP );
165 
166         if ( ( strName == null ) || ( strName.length( ) <= 0 ) )
167         {
168             // Return the welcome page
169             return null;
170         }
171 
172         PageData/service/content/PageData.html#PageData">PageData data = new PageData( );
173         XPageApplicationEntry entry = XPageAppService.getApplicationEntry( strName );
174 
175         if ( ( entry != null ) && ( entry.isEnable( ) ) )
176         {
177             XPageApplication app = XPageAppService.getApplicationInstance( entry );
178             XPage page = app.getPage( request, nMode, entry.getPlugin( ) );
179             data.setContent( page.getContent( ) );
180             data.setName( page.getTitle( ) );
181         }
182         else
183         {
184             AppLogService.error( "The specified Xpage '{}' cannot be retrieved. Check installation of your Xpage application.",
185                     ( ) -> SecurityUtil.logForgingProtect( strName ) );
186             SiteMessageService.setMessage( request, MESSAGE_ERROR_APP_BODY, SiteMessage.TYPE_ERROR );
187         }
188 
189         return buildPageContent( data, nMode, strName, request );
190     }
191 
192     /**
193      * Returns the html code which represents the page content
194      *
195      * @param data
196      *            The structure which contains the informations about the page
197      * @param nMode
198      *            The mode in which displaying the page : normal or administration
199      * @param strPluginName
200      *            The name of the plugin
201      * @param request
202      *            TheHttpServletRequest
203      * @return The html code of a page
204      */
205     private static String buildPageContent( PageData data, int nMode, String strPluginName, HttpServletRequest request )
206     {
207         HtmlTemplate template;
208         String strFileName = strPluginName + "/" + TEMPLATE_PAGE_FRAMESET;
209         String strFilePath = AppPathService.getPath( PROPERTY_PATH_LUTECE_PLUGINS, strFileName );
210         File file = new File( strFilePath );
211         String strPluginPath = "skin/plugins/";
212 
213         // Load of the templates
214         HashMap<String, Object> model = new HashMap<>( );
215         model.put( Markers.BASE_URL, AppPathService.getBaseUrl( request ) );
216         model.put( Markers.PAGE_NAME, data.getName( ) );
217         model.put( Markers.PAGE_CONTENT, data.getContent( ) );
218 
219         Collection<PageInclude> colIncludes = PageIncludeService.getIncludes( );
220 
221         for ( PageInclude pic : colIncludes )
222         {
223             pic.fillTemplate( model, data, nMode, request );
224         }
225 
226         if ( file.exists( ) )
227         {
228             template = AppTemplateService.getTemplate( strPluginPath + strFileName, request.getLocale( ), model );
229         }
230         else
231         {
232             template = AppTemplateService.getTemplate( TEMPLATE_STANDALONE_PAGE_FRAMESET, request.getLocale( ), model );
233         }
234 
235         return template.getHtml( );
236     }
237 }