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 java.util.ArrayList;
37  import java.util.Collection;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Locale;
41  import java.util.Map;
42  import java.util.Properties;
43  
44  import javax.servlet.http.HttpServletRequest;
45  
46  import org.apache.commons.lang3.StringUtils;
47  
48  import fr.paris.lutece.portal.business.XmlContent;
49  import fr.paris.lutece.portal.business.page.Page;
50  import fr.paris.lutece.portal.business.page.PageHome;
51  import fr.paris.lutece.portal.business.portalcomponent.PortalComponentHome;
52  import fr.paris.lutece.portal.business.portlet.Portlet;
53  import fr.paris.lutece.portal.business.portlet.PortletHome;
54  import fr.paris.lutece.portal.business.style.ModeHome;
55  import fr.paris.lutece.portal.business.stylesheet.StyleSheet;
56  import fr.paris.lutece.portal.service.cache.IPathCacheService;
57  import fr.paris.lutece.portal.service.content.ContentService;
58  import fr.paris.lutece.portal.service.content.PageData;
59  import fr.paris.lutece.portal.service.datastore.DatastoreService;
60  import fr.paris.lutece.portal.service.html.XmlTransformerService;
61  import fr.paris.lutece.portal.service.includes.PageInclude;
62  import fr.paris.lutece.portal.service.includes.PageIncludeService;
63  import fr.paris.lutece.portal.service.message.SiteMessageException;
64  import fr.paris.lutece.portal.service.page.IPageService;
65  import fr.paris.lutece.portal.service.plugin.PluginService;
66  import fr.paris.lutece.portal.service.security.LuteceUser;
67  import fr.paris.lutece.portal.service.security.SecurityService;
68  import fr.paris.lutece.portal.service.spring.SpringContextService;
69  import fr.paris.lutece.portal.service.template.AppTemplateService;
70  import fr.paris.lutece.portal.service.util.AppPathService;
71  import fr.paris.lutece.portal.service.util.AppPropertiesService;
72  import fr.paris.lutece.portal.web.constants.Markers;
73  import fr.paris.lutece.portal.web.constants.Parameters;
74  import fr.paris.lutece.portal.web.l10n.LocaleService;
75  import fr.paris.lutece.util.date.DateUtil;
76  import fr.paris.lutece.util.html.HtmlTemplate;
77  import fr.paris.lutece.util.xml.XmlUtil;
78  
79  /**
80   * This class provides methods to build the pages of the portal and manage the cache
81   */
82  public final class PortalService
83  {
84      // //////////////////////////////////////////////////////////////////////////
85      // Constants
86      private static final int PORTAL_COMPONENT_PAGE_PATH_ID = 5;
87  
88      // Properties
89      private static final String PROPERTY_HOME_PAGE_HEADER = "home.page.header.mode";
90      private static final String PROPERTY_INTERNAL_PAGE_HEADER = "internal.page.header.mode";
91      private static final String PROPERTY_PAGE_TOOLS_MENU = "page.tools.menu.mode";
92      private static final String PROPERTY_PORTAL_FOOTER = "page.portal.footer.mode";
93      private static final String PROPERTY_PATH_ON_ROOT = "lutece.root.path";
94      private static final String PROPERTY_ENCODING = "lutece.encoding";
95      private static final String PROPERTY_ENCODING_DEFAULT = "UTF-8";
96  
97      // Datastore keys
98      private static final String KEY_SITE_NAME = "portal.site.site_property.name";
99      private static final String KEY_WEBMASTER_EMAIL = "portal.site.site_property.email";
100 
101     // Templates
102     private static final String TEMPLATE_PAGE_FRAMESET = "skin/site/page_frameset.html";
103     private static final String TEMPLATE_HOME_PAGE_HEADER = "skin/site/page_header_home.html";
104     private static final String TEMPLATE_INTERNAL_PAGE_HEADER = "skin/site/page_header_internal.html";
105     private static final String TEMPLATE_PAGE_TOOLS_MENU = "skin/site/page_menu_tools.html";
106     private static final String TEMPLATE_PAGE_PATH = "skin/site/page_path.html";
107     private static final String TEMPLATE_PORTAL_FOOTER = "skin/site/portal_footer.html";
108     private static final String TEMPLATE_ADMIN_CSS_LINKS = "admin/stylesheet_link.html";
109 
110     // Markers
111     private static final String MARKER_TARGET = "target";
112     private static final String MARKER_PAGE_DATA = "data";
113     private static final String PLUGIN_EXTEND_NAME = "extend";
114     private static final String PLUGIN_CONTACT_NAME = "contact";
115     private static final String MARK_IS_EXTEND_INSTALLED = "isExtendInstalled";
116     private static final String MARK_IS_CONTACT_INSTALLED = "isContactInstalled";
117     private static final String MARK_LUTECE_USER = "lutece_user";
118     private static final String TARGET_TOP = "target='_top'";
119     private static final String BOOKMARK_BASE_URL = "@base_url@";
120     private static final String MARK_LAST_MODIFIED = "last_modified";
121     private static final String MARK_DISPLAY_LAST_MODIFIED = "display_last_modified";
122 
123     // Added in v1.3
124     private static final int MODE_NORMAL = 0;
125     private static final int MODE_ADMIN = 1;
126     private static final String PARAMETER_SITE_PATH = "site-path";
127 
128     // Content Service registry
129     private static Map<String, ContentService> _mapContentServicesRegistry = new HashMap<>( );
130     private static IPageService _pageService = SpringContextService.getBean( "pageService" );
131 
132     /**
133      * Private Constructor
134      */
135     private PortalService( )
136     {
137     }
138 
139     /**
140      * Analyzes request's parameters to find the ContentService that should handle the request
141      *
142      * @param request
143      *            The HTTP request
144      * @return ContentService that should handle the request
145      */
146     public static ContentService getInvokedContentService( HttpServletRequest request )
147     {
148         for ( ContentService cs : getContentServicesList( ) )
149         {
150             if ( cs.isInvoked( request ) )
151             {
152                 return cs;
153             }
154         }
155 
156         return null;
157     }
158 
159     /**
160      * Registers a new ContentService
161      * 
162      * @param strName
163      *            The name
164      * @param cs
165      *            The ContentService
166      */
167     public static void registerContentService( String strName, ContentService cs )
168     {
169         _mapContentServicesRegistry.put( strName, cs );
170     }
171 
172     /**
173      * Returns all registered Content services
174      *
175      * @return A collection containing all registered Content services
176      */
177     public static Collection<ContentService> getContentServicesList( )
178     {
179         return _mapContentServicesRegistry.values( );
180     }
181 
182     /**
183      * Returns the identifier of the root page of the portal read in the lutece.properties file
184      *
185      * @return The identifier of the root page
186      */
187     public static int getRootPageId( )
188     {
189         return AppPropertiesService.getPropertyInt( "lutece.page.root", 1 );
190     }
191 
192     /**
193      * Return the default page of the portal (the home page)
194      * 
195      * @param request
196      *            The request
197      * @param nMode
198      *            the mode id
199      * @return default page as a String
200      * @throws SiteMessageException
201      *             occurs when a site message need to be displayed
202      */
203     public static String getDefaultPage( HttpServletRequest request, int nMode ) throws SiteMessageException
204     {
205         return _pageService.getPage( String.valueOf( getRootPageId( ) ), nMode, request );
206     }
207 
208     /**
209      * Return the xml content of the pages contained in the list specified in parameter
210      *
211      * @param listPages
212      *            The pages list
213      * @return the xml code for the content page
214      */
215     public static String getXmlPagesList( Collection<Page> listPages )
216     {
217         StringBuffer strXml = new StringBuffer( );
218         strXml.append( XmlUtil.getXmlHeader( ) );
219         XmlUtil.beginElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );
220 
221         for ( Page page : listPages )
222         {
223             XmlUtil.beginElement( strXml, XmlContent.TAG_PAGE );
224             XmlUtil.addElement( strXml, XmlContent.TAG_PAGE_ID, page.getId( ) );
225             XmlUtil.addElementHtml( strXml, XmlContent.TAG_PAGE_NAME, page.getName( ) );
226             XmlUtil.endElement( strXml, XmlContent.TAG_PAGE );
227         }
228 
229         XmlUtil.endElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );
230 
231         return strXml.toString( );
232     }
233 
234     // //////////////////////////////////////////////////////////////////////////
235     // pages builder
236 
237     /**
238      * Returns the html code which represents the page content
239      * 
240      * @param data
241      *            The structure which contains the informations about the page
242      * @param nMode
243      *            The mode in which displaying the page : normal or administration
244      * @param request
245      *            The request
246      * @return The html code of a page
247      */
248     public static String buildPageContent( PageData data, int nMode, HttpServletRequest request )
249     {
250         return buildPageContent( getRootPageId( ), data, nMode, request );
251     }
252 
253     /**
254      * Returns the html code which represents the page content
255      * 
256      * @param nCurrentPageId
257      *            the current page id
258      * @param data
259      *            The structure which contains the informations about the page
260      * @param nMode
261      *            The mode in which displaying the page : normal or administration
262      * @param request
263      *            The request
264      * @return The html code of a page
265      */
266     public static String buildPageContent( int nCurrentPageId, PageData data, int nMode, HttpServletRequest request )
267     {
268         Locale locale = null;
269         HashMap<String, Object> model = new HashMap<>( );
270         LuteceUser user = null;
271         String strWebmasterEmail = DatastoreService.getDataValue( KEY_WEBMASTER_EMAIL, "" );
272         model.put( Markers.WEBMASTER_EMAIL, strWebmasterEmail );
273 
274         locale = LocaleService.getContextUserLocale( request );
275 
276         if ( request != null )
277         {
278             user = SecurityService.getInstance( ).getRegisteredUser( request );
279             if ( nMode != MODE_ADMIN )
280             {
281                 model.put( MARK_LUTECE_USER, user );
282             }
283         }
284 
285         List<PageInclude> listIncludes = PageIncludeService.getIncludes( );
286 
287         for ( PageInclude pic : listIncludes )
288         {
289             pic.fillTemplate( model, data, nMode, request );
290         }
291 
292         String strHeader = data.isHomePage( ) ? AppPropertiesService.getProperty( PROPERTY_HOME_PAGE_HEADER + nMode, TEMPLATE_HOME_PAGE_HEADER )
293                 : AppPropertiesService.getProperty( PROPERTY_INTERNAL_PAGE_HEADER + nMode, TEMPLATE_INTERNAL_PAGE_HEADER );
294         HtmlTemplate tHeader = AppTemplateService.getTemplate( strHeader, locale, model );
295 
296         String strFooter = AppPropertiesService.getProperty( PROPERTY_PORTAL_FOOTER + nMode, TEMPLATE_PORTAL_FOOTER );
297         String strToolsMenu = AppPropertiesService.getProperty( PROPERTY_PAGE_TOOLS_MENU + nMode, TEMPLATE_PAGE_TOOLS_MENU );
298         model.put( MARK_IS_CONTACT_INSTALLED, isContactActivated( ) );
299 
300         boolean bDisplayLastModified = data.getDisplayDateUpdate( );
301         model.put( MARK_DISPLAY_LAST_MODIFIED, bDisplayLastModified );
302 
303         if ( request != null )
304         {
305             String strLastModified = DateUtil.getDateString( data.getDateUpdate( ), locale );
306             model.put( MARK_LAST_MODIFIED, strLastModified );
307         }
308         HtmlTemplate tFooter = AppTemplateService.getTemplate( strFooter, locale, model );
309 
310         HtmlTemplate tToolsMenu = AppTemplateService.getTemplate( strToolsMenu, locale, model );
311         model.put( Markers.PAGE_HEADER, tHeader.getHtml( ) );
312         model.put( MARKER_PAGE_DATA, data );
313         model.put( Markers.PAGE_NAME, data.getName( ) == null ? "" : data.getName( ) );
314         model.put( Markers.PAGE_CONTENT, data.getContent( ) == null ? "" : data.getContent( ) );
315         model.put( Markers.PAGE_PATH, data.getPagePath( ) == null ? "" : data.getPagePath( ) );
316         model.put( Markers.PAGE_TOOLS_MENU, tToolsMenu.getHtml( ) );
317         model.put( Markers.PAGE_ID, nCurrentPageId );
318 
319         model.put( Markers.PAGE_FOOTER, tFooter.getHtml( ) );
320 
321         String strBaseUrl = request != null ? AppPathService.getBaseUrl( request ) : ""; // request could be null
322                                                                                          // (method called by daemons
323                                                                                          // or batch)
324 
325         // for link service
326         model.put( Markers.WEBAPP_PATH_FOR_LINKSERVICE, strBaseUrl );
327         model.put( Markers.BASE_URL, strBaseUrl );
328 
329         String strEncoding = AppPropertiesService.getProperty( PROPERTY_ENCODING, PROPERTY_ENCODING_DEFAULT );
330 
331         if ( strEncoding == null || strEncoding.equals( "" ) )
332         {
333             strEncoding = PROPERTY_ENCODING_DEFAULT;
334         }
335 
336         model.put( Markers.ENCODING, strEncoding );
337 
338         model.put( Markers.USER_CONTEXT_LANGUAGE, locale );
339 
340         model.put( MARK_IS_EXTEND_INSTALLED, isExtendActivated( ) );
341 
342         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_PAGE_FRAMESET, locale, model );
343 
344         template.substitute( BOOKMARK_BASE_URL, request != null ? AppPathService.getBaseUrl( request ) : "" ); // request
345                                                                                                                // could
346                                                                                                                // be
347                                                                                                                // null
348                                                                                                                // (method
349                                                                                                                // called
350                                                                                                                // by
351                                                                                                                // daemons
352                                                                                                                // or
353                                                                                                                // batch)
354 
355         return template.getHtml( );
356     }
357 
358     // //////////////////////////////////////////////////////////////////////////
359     // Management of the pages path
360 
361     /**
362      * Returns the formated path of the site page whose identifier is specified in parameter
363      *
364      * @param nPageId
365      *            The identifier of the page
366      * @param nMode
367      *            The mode to use for the formatting
368      * @param request
369      *            The HTTP request
370      * @return the formated path
371      */
372     public static String getPagePathContent( int nPageId, int nMode, HttpServletRequest request )
373     {
374         String strPathOnRoot = AppPropertiesService.getProperty( PROPERTY_PATH_ON_ROOT );
375 
376         // If the current page is the home page or the string strPathOnRoot equals
377         // false, not display the path
378         if ( nPageId == getRootPageId( ) && ( strPathOnRoot == null || strPathOnRoot.equalsIgnoreCase( "false" ) ) )
379         {
380             return "";
381         }
382 
383         // Selection of the XSL stylesheet
384         // Added in v1.3
385         // Use the same stylesheet for normal or admin mode
386         StyleSheet xslSource;
387 
388         switch( nMode )
389         {
390             case MODE_NORMAL:
391             case MODE_ADMIN:
392                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, MODE_NORMAL );
393 
394                 break;
395 
396             default:
397                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, nMode );
398 
399                 break;
400         }
401 
402         String strXml = getXmlPagesList( getPagePath( nPageId ) );
403 
404         Properties outputProperties = ModeHome.getOuputXslProperties( nMode );
405 
406         // Added in v1.3
407         // Add a path param for choose url to use in admin or normal mode
408         Map<String, String> mapParamRequest = new HashMap<>( );
409         setXslPortalPath( mapParamRequest, nMode );
410 
411         XmlTransformerServicervice.html#XmlTransformerService">XmlTransformerService xmlTransformerService = new XmlTransformerService( );
412         String strPath = xmlTransformerService.transformBySourceWithXslCache( strXml, xslSource, mapParamRequest, outputProperties );
413 
414         return formatPath( strPath, nMode, request );
415     }
416 
417     /**
418      * Returns the formated path of a xpage (ex : result of a seek)
419      *
420      * @param strXPageName
421      *            The xpage name
422      * @param nMode
423      *            The mode to use for the formatting
424      * @param request
425      *            The HTTP request
426      * @return the formated path
427      */
428     public static String getXPagePathContent( String strXPageName, int nMode, HttpServletRequest request )
429     {
430         final IPathCacheService pathCacheService = SpringContextService.getBean( IPathCacheService.BEAN_NAME );
431 
432         final String strKey = pathCacheService.getKey( strXPageName, nMode, request );
433 
434         String strRes = pathCacheService.getFromCache( strKey );
435 
436         if ( strRes != null )
437         {
438             return strRes;
439         }
440 
441         // Added in v1.3
442         StyleSheet xslSource;
443 
444         // Selection of the XSL stylesheet
445         switch( nMode )
446         {
447             case MODE_NORMAL:
448             case MODE_ADMIN:
449                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, MODE_NORMAL );
450 
451                 break;
452 
453             default:
454                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, nMode );
455 
456                 break;
457         }
458 
459         String strXml = StringUtils.EMPTY;
460         String strPageId = request.getParameter( Parameters.PAGE_ID );
461 
462         if ( StringUtils.isNotBlank( strPageId ) && StringUtils.isNumeric( strPageId ) )
463         {
464             int nPageId = Integer.parseInt( strPageId );
465             strXml = getXmlPagesList( getXPagePath( strXPageName, nPageId ) );
466         }
467         else
468         {
469             String strPortletId = request.getParameter( Parameters.PORTLET_ID );
470 
471             if ( StringUtils.isNotBlank( strPortletId ) && StringUtils.isNumeric( strPortletId ) )
472             {
473                 int nPortletId = Integer.parseInt( strPortletId );
474                 Portlet portlet = PortletHome.findByPrimaryKey( nPortletId );
475 
476                 if ( portlet != null )
477                 {
478                     int nPageId = portlet.getPageId( );
479                     strXml = getXmlPagesList( getXPagePath( strXPageName, nPageId ) );
480                 }
481             }
482         }
483 
484         if ( StringUtils.isBlank( strXml ) )
485         {
486             strXml = getXmlPagesList( getXPagePath( strXPageName ) );
487         }
488 
489         Properties outputProperties = ModeHome.getOuputXslProperties( nMode );
490 
491         // Added in v1.3
492         // Add a path param for choose url to use in admin or normal mode
493         Map<String, String> mapXslParams = new HashMap<>( );
494         setXslPortalPath( mapXslParams, nMode );
495 
496         XmlTransformerServicervice.html#XmlTransformerService">XmlTransformerService xmlTransformerService = new XmlTransformerService( );
497         String strPath = xmlTransformerService.transformBySourceWithXslCache( strXml, xslSource, mapXslParams, outputProperties );
498 
499         strRes = formatPath( strPath, nMode, request );
500 
501         pathCacheService.putInCache( strKey, strRes );
502 
503         return strRes;
504     }
505 
506     /**
507      * Builds a collection of pages corresponding to the path of the page specified in parameter
508      *
509      * @param nPageId
510      *            The identifier of the page
511      * @return A collection of pages from the home page to the specified page
512      */
513     public static Collection<Page> getPagePath( int nPageId )
514     {
515         ArrayList<Page> list = new ArrayList<>( );
516         Page page = PageHome.getPage( nPageId );
517         int nParentPageId = page.getParentPageId( );
518         list.add( page );
519 
520         while ( nParentPageId != 0 )
521         {
522             Page parentPage = PageHome.getPage( nParentPageId );
523 
524             // Insert the page in the begin of the list
525             list.add( 0, parentPage );
526             nParentPageId = parentPage.getParentPageId( );
527         }
528 
529         return list;
530     }
531 
532     /**
533      * Builds a collection of pages corresponding to the path of a xpage
534      *
535      * @param strXPageName
536      *            The xpage name
537      * @return A collection of pages made by the home page and the xpage
538      */
539     private static Collection<Page> getXPagePath( String strXPageName )
540     {
541         ArrayList<Page> list = new ArrayList<>( );
542         Page homePage = PageHome.getPage( getRootPageId( ) );
543         list.add( homePage );
544 
545         Pagetal/business/page/Page.html#Page">Page xPage = new Page( );
546         xPage.setName( strXPageName );
547         list.add( xPage );
548 
549         return list;
550     }
551 
552     /**
553      * Builds a collection of pages corresponding to the path of a xpage
554      *
555      * @param strXPageName
556      *            The xpage name
557      * @param nPageId
558      *            The Page's ID
559      * @return A collection of pages made by the home page and the xpage
560      */
561     private static Collection<Page> getXPagePath( String strXPageName, int nPageId )
562     {
563         List<Page> list = new ArrayList<>( );
564         Page page = PageHome.getPage( nPageId );
565 
566         if ( page != null )
567         {
568             int nParentPageId = page.getParentPageId( );
569 
570             while ( ( nParentPageId > 0 ) && ( nParentPageId != getRootPageId( ) ) )
571             {
572                 Page parentPage = PageHome.getPage( nParentPageId );
573 
574                 if ( parentPage != null )
575                 {
576                     // Insert the page at the beginning of the list
577                     list.add( 0, parentPage );
578                     nParentPageId = parentPage.getParentPageId( );
579                 }
580             }
581 
582             if ( nPageId != getRootPageId( ) )
583             {
584                 list.add( page );
585             }
586         }
587 
588         // Insert the home page at the beginning of the list
589         Page homePage = PageHome.getPage( getRootPageId( ) );
590         list.add( 0, homePage );
591 
592         // Insert the XPage at the end of the list
593         Pagetal/business/page/Page.html#Page">Page xPage = new Page( );
594         xPage.setName( strXPageName );
595         xPage.setId( nPageId );
596         list.add( xPage );
597 
598         return list;
599     }
600 
601     // //////////////////////////////////////////////////////////////////////////
602 
603     /**
604      * Formats the path specified in parameter and returns it
605      *
606      * @param strPath
607      *            The path to format
608      * @param nMode
609      *            The mode to use for the formatting
610      * @param request
611      *            The HTTP request
612      * @return the html code to display the path
613      */
614     public static String formatPath( String strPath, int nMode, HttpServletRequest request )
615     {
616         HashMap<String, Object> model = new HashMap<>( );
617         model.put( Markers.PAGE_PATH, strPath );
618 
619         List<PageInclude> listIncludes = PageIncludeService.getIncludes( );
620         PageData/service/content/PageData.html#PageData">PageData data = new PageData( );
621 
622         for ( PageInclude pic : listIncludes )
623         {
624             pic.fillTemplate( model, data, nMode, request );
625         }
626 
627         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_PAGE_PATH, ( request == null ) ? null : request.getLocale( ), model );
628 
629         return template.getHtml( );
630     }
631 
632     /**
633      * Return the xml content of the pages specified by the xml code. This is called when using the Extended Xml path Label.
634      *
635      * @param strXmlExtend
636      *            The xml code to append to the path
637      * @return the xml code for the content page
638      */
639     private static String getXmlPagesListExtended( String strXmlExtend )
640     {
641         StringBuffer strXml = new StringBuffer( );
642         strXml.append( XmlUtil.getXmlHeader( ) );
643         XmlUtil.beginElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );
644 
645         Page homePage = PageHome.getPage( getRootPageId( ) );
646 
647         XmlUtil.beginElement( strXml, XmlContent.TAG_PAGE );
648         XmlUtil.addElement( strXml, XmlContent.TAG_PAGE_ID, homePage.getId( ) );
649         XmlUtil.addElementHtml( strXml, XmlContent.TAG_PAGE_NAME, homePage.getName( ) );
650         XmlUtil.endElement( strXml, XmlContent.TAG_PAGE );
651 
652         strXml.append( strXmlExtend );
653 
654         XmlUtil.endElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );
655 
656         return strXml.toString( );
657     }
658 
659     /**
660      * Returns the formated extended path of an xpage. This method is used when giving the list of elements in the path as a Xml code. This is called when using
661      * the Extended Xml path Label.
662      *
663      * @param strXPageName
664      *            The xpage name
665      * @param nMode
666      *            The mode to use for the formatting
667      * @param strTitlesUrls
668      *            list of links (url and titles)
669      * @param request
670      *            The HTTP request
671      * @return the formatted path
672      */
673     public static String getXPagePathContent( String strXPageName, int nMode, String strTitlesUrls, HttpServletRequest request )
674     {
675         final IPathCacheService pathCacheService = SpringContextService.getBean( IPathCacheService.BEAN_NAME );
676 
677         final String strKey = pathCacheService.getKey( strXPageName, nMode, strTitlesUrls, request );
678 
679         String strRes = pathCacheService.getFromCache( strKey );
680 
681         if ( strRes != null )
682         {
683             return strRes;
684         }
685 
686         // Selection of the XSL stylesheet
687         StyleSheet xslSource;
688 
689         // Selection of the XSL stylesheet
690         switch( nMode )
691         {
692             case MODE_NORMAL:
693             case MODE_ADMIN:
694                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, MODE_NORMAL );
695 
696                 break;
697 
698             default:
699                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, nMode );
700 
701                 break;
702         }
703 
704         String strXml = getXmlPagesListExtended( strTitlesUrls );
705 
706         Properties outputProperties = ModeHome.getOuputXslProperties( nMode );
707 
708         // Added in v1.3
709         // Add a path param for choose url to use in admin or normal mode
710         Map<String, String> mapXslParams = new HashMap<>( );
711         setXslPortalPath( mapXslParams, nMode );
712 
713         XmlTransformerServicervice.html#XmlTransformerService">XmlTransformerService xmlTransformerService = new XmlTransformerService( );
714         String strPath = xmlTransformerService.transformBySourceWithXslCache( strXml, xslSource, mapXslParams, outputProperties );
715 
716         strRes = formatPath( strPath, nMode, request );
717 
718         pathCacheService.putInCache( strKey, strRes );
719 
720         return strRes;
721     }
722 
723     /**
724      * Sets XSL portal path
725      * 
726      * @param mapParameters
727      *            Parameters as a map
728      * @param nMode
729      *            The mode
730      */
731     public static void setXslPortalPath( Map<String, String> mapParameters, int nMode )
732     {
733         if ( nMode != MODE_ADMIN )
734         {
735             mapParameters.put( PARAMETER_SITE_PATH, AppPathService.getPortalUrl( ) );
736         }
737         else
738         {
739             mapParameters.put( PARAMETER_SITE_PATH, AppPathService.getAdminPortalUrl( ) );
740             mapParameters.put( MARKER_TARGET, TARGET_TOP );
741         }
742     }
743 
744     /**
745      * Returns the site name
746      * 
747      * @return The site name
748      */
749     public static String getSiteName( )
750     {
751         return DatastoreService.getDataValue( KEY_SITE_NAME, StringUtils.EMPTY );
752     }
753 
754     /**
755      * Check if the extend plugin is activated
756      * 
757      * @return True if the plugin is activated, false otherwise
758      */
759     public static boolean isExtendActivated( )
760     {
761         return PluginService.isPluginEnable( PLUGIN_EXTEND_NAME );
762     }
763 
764     /**
765      * Check if the cotnact plugin is activated
766      * 
767      * @return True if the plugin is activated, false otherwise
768      */
769     public static boolean isContactActivated( )
770     {
771         return PluginService.isPluginEnable( PLUGIN_CONTACT_NAME );
772     }
773 
774     /**
775      * Get the list of CSS links for session less pages
776      * 
777      * @return The HTML code providing the list of CSS links.
778      */
779     public static String getAdminCssLinks( )
780     {
781         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_CSS_LINKS );
782         return template.getHtml( );
783     }
784 }