PortalService.java

  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. import java.util.ArrayList;
  36. import java.util.Collection;
  37. import java.util.HashMap;
  38. import java.util.List;
  39. import java.util.Locale;
  40. import java.util.Map;
  41. import java.util.Properties;

  42. import javax.servlet.http.HttpServletRequest;

  43. import org.apache.commons.lang3.StringUtils;

  44. import fr.paris.lutece.portal.business.XmlContent;
  45. import fr.paris.lutece.portal.business.page.Page;
  46. import fr.paris.lutece.portal.business.page.PageHome;
  47. import fr.paris.lutece.portal.business.portalcomponent.PortalComponentHome;
  48. import fr.paris.lutece.portal.business.portlet.Portlet;
  49. import fr.paris.lutece.portal.business.portlet.PortletHome;
  50. import fr.paris.lutece.portal.business.style.ModeHome;
  51. import fr.paris.lutece.portal.business.stylesheet.StyleSheet;
  52. import fr.paris.lutece.portal.service.cache.IPathCacheService;
  53. import fr.paris.lutece.portal.service.content.ContentService;
  54. import fr.paris.lutece.portal.service.content.PageData;
  55. import fr.paris.lutece.portal.service.datastore.DatastoreService;
  56. import fr.paris.lutece.portal.service.html.XmlTransformerService;
  57. import fr.paris.lutece.portal.service.includes.PageInclude;
  58. import fr.paris.lutece.portal.service.includes.PageIncludeService;
  59. import fr.paris.lutece.portal.service.message.SiteMessageException;
  60. import fr.paris.lutece.portal.service.page.IPageService;
  61. import fr.paris.lutece.portal.service.plugin.PluginService;
  62. import fr.paris.lutece.portal.service.security.LuteceUser;
  63. import fr.paris.lutece.portal.service.security.SecurityService;
  64. import fr.paris.lutece.portal.service.spring.SpringContextService;
  65. import fr.paris.lutece.portal.service.template.AppTemplateService;
  66. import fr.paris.lutece.portal.service.util.AppPathService;
  67. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  68. import fr.paris.lutece.portal.web.constants.Markers;
  69. import fr.paris.lutece.portal.web.constants.Parameters;
  70. import fr.paris.lutece.portal.web.l10n.LocaleService;
  71. import fr.paris.lutece.util.date.DateUtil;
  72. import fr.paris.lutece.util.html.HtmlTemplate;
  73. import fr.paris.lutece.util.xml.XmlUtil;

  74. /**
  75.  * This class provides methods to build the pages of the portal and manage the cache
  76.  */
  77. public final class PortalService
  78. {
  79.     // //////////////////////////////////////////////////////////////////////////
  80.     // Constants
  81.     private static final int PORTAL_COMPONENT_PAGE_PATH_ID = 5;

  82.     // Properties
  83.     private static final String PROPERTY_HOME_PAGE_HEADER = "home.page.header.mode";
  84.     private static final String PROPERTY_INTERNAL_PAGE_HEADER = "internal.page.header.mode";
  85.     private static final String PROPERTY_PAGE_TOOLS_MENU = "page.tools.menu.mode";
  86.     private static final String PROPERTY_PORTAL_FOOTER = "page.portal.footer.mode";
  87.     private static final String PROPERTY_PATH_ON_ROOT = "lutece.root.path";
  88.     private static final String PROPERTY_ENCODING = "lutece.encoding";
  89.     private static final String PROPERTY_ENCODING_DEFAULT = "UTF-8";

  90.     // Datastore keys
  91.     private static final String KEY_SITE_NAME = "portal.site.site_property.name";
  92.     private static final String KEY_WEBMASTER_EMAIL = "portal.site.site_property.email";

  93.     // Templates
  94.     private static final String TEMPLATE_PAGE_FRAMESET = "skin/site/page_frameset.html";
  95.     private static final String TEMPLATE_HOME_PAGE_HEADER = "skin/site/page_header_home.html";
  96.     private static final String TEMPLATE_INTERNAL_PAGE_HEADER = "skin/site/page_header_internal.html";
  97.     private static final String TEMPLATE_PAGE_TOOLS_MENU = "skin/site/page_menu_tools.html";
  98.     private static final String TEMPLATE_PAGE_PATH = "skin/site/page_path.html";
  99.     private static final String TEMPLATE_PORTAL_FOOTER = "skin/site/portal_footer.html";
  100.     private static final String TEMPLATE_ADMIN_CSS_LINKS = "admin/stylesheet_link.html";

  101.     // Markers
  102.     private static final String MARKER_TARGET = "target";
  103.     private static final String MARKER_PAGE_DATA = "data";
  104.     private static final String PLUGIN_EXTEND_NAME = "extend";
  105.     private static final String PLUGIN_CONTACT_NAME = "contact";
  106.     private static final String MARK_IS_EXTEND_INSTALLED = "isExtendInstalled";
  107.     private static final String MARK_IS_CONTACT_INSTALLED = "isContactInstalled";
  108.     private static final String MARK_LUTECE_USER = "lutece_user";
  109.     private static final String TARGET_TOP = "target='_top'";
  110.     private static final String BOOKMARK_BASE_URL = "@base_url@";
  111.     private static final String MARK_LAST_MODIFIED = "last_modified";
  112.     private static final String MARK_DISPLAY_LAST_MODIFIED = "display_last_modified";

  113.     // Added in v1.3
  114.     private static final int MODE_NORMAL = 0;
  115.     private static final int MODE_ADMIN = 1;
  116.     private static final String PARAMETER_SITE_PATH = "site-path";

  117.     // Content Service registry
  118.     private static Map<String, ContentService> _mapContentServicesRegistry = new HashMap<>( );
  119.     private static IPageService _pageService = SpringContextService.getBean( "pageService" );

  120.     /**
  121.      * Private Constructor
  122.      */
  123.     private PortalService( )
  124.     {
  125.     }

  126.     /**
  127.      * Analyzes request's parameters to find the ContentService that should handle the request
  128.      *
  129.      * @param request
  130.      *            The HTTP request
  131.      * @return ContentService that should handle the request
  132.      */
  133.     public static ContentService getInvokedContentService( HttpServletRequest request )
  134.     {
  135.         for ( ContentService cs : getContentServicesList( ) )
  136.         {
  137.             if ( cs.isInvoked( request ) )
  138.             {
  139.                 return cs;
  140.             }
  141.         }

  142.         return null;
  143.     }

  144.     /**
  145.      * Registers a new ContentService
  146.      *
  147.      * @param strName
  148.      *            The name
  149.      * @param cs
  150.      *            The ContentService
  151.      */
  152.     public static void registerContentService( String strName, ContentService cs )
  153.     {
  154.         _mapContentServicesRegistry.put( strName, cs );
  155.     }

  156.     /**
  157.      * Returns all registered Content services
  158.      *
  159.      * @return A collection containing all registered Content services
  160.      */
  161.     public static Collection<ContentService> getContentServicesList( )
  162.     {
  163.         return _mapContentServicesRegistry.values( );
  164.     }

  165.     /**
  166.      * Returns the identifier of the root page of the portal read in the lutece.properties file
  167.      *
  168.      * @return The identifier of the root page
  169.      */
  170.     public static int getRootPageId( )
  171.     {
  172.         return AppPropertiesService.getPropertyInt( "lutece.page.root", 1 );
  173.     }

  174.     /**
  175.      * Return the default page of the portal (the home page)
  176.      *
  177.      * @param request
  178.      *            The request
  179.      * @param nMode
  180.      *            the mode id
  181.      * @return default page as a String
  182.      * @throws SiteMessageException
  183.      *             occurs when a site message need to be displayed
  184.      */
  185.     public static String getDefaultPage( HttpServletRequest request, int nMode ) throws SiteMessageException
  186.     {
  187.         return _pageService.getPage( String.valueOf( getRootPageId( ) ), nMode, request );
  188.     }

  189.     /**
  190.      * Return the xml content of the pages contained in the list specified in parameter
  191.      *
  192.      * @param listPages
  193.      *            The pages list
  194.      * @return the xml code for the content page
  195.      */
  196.     public static String getXmlPagesList( Collection<Page> listPages )
  197.     {
  198.         StringBuffer strXml = new StringBuffer( );
  199.         strXml.append( XmlUtil.getXmlHeader( ) );
  200.         XmlUtil.beginElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );

  201.         for ( Page page : listPages )
  202.         {
  203.             XmlUtil.beginElement( strXml, XmlContent.TAG_PAGE );
  204.             XmlUtil.addElement( strXml, XmlContent.TAG_PAGE_ID, page.getId( ) );
  205.             XmlUtil.addElementHtml( strXml, XmlContent.TAG_PAGE_NAME, page.getName( ) );
  206.             XmlUtil.endElement( strXml, XmlContent.TAG_PAGE );
  207.         }

  208.         XmlUtil.endElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );

  209.         return strXml.toString( );
  210.     }

  211.     // //////////////////////////////////////////////////////////////////////////
  212.     // pages builder

  213.     /**
  214.      * Returns the html code which represents the page content
  215.      *
  216.      * @param data
  217.      *            The structure which contains the informations about the page
  218.      * @param nMode
  219.      *            The mode in which displaying the page : normal or administration
  220.      * @param request
  221.      *            The request
  222.      * @return The html code of a page
  223.      */
  224.     public static String buildPageContent( PageData data, int nMode, HttpServletRequest request )
  225.     {
  226.         return buildPageContent( getRootPageId( ), data, nMode, request );
  227.     }

  228.     /**
  229.      * Returns the html code which represents the page content
  230.      *
  231.      * @param nCurrentPageId
  232.      *            the current page id
  233.      * @param data
  234.      *            The structure which contains the informations about the page
  235.      * @param nMode
  236.      *            The mode in which displaying the page : normal or administration
  237.      * @param request
  238.      *            The request
  239.      * @return The html code of a page
  240.      */
  241.     public static String buildPageContent( int nCurrentPageId, PageData data, int nMode, HttpServletRequest request )
  242.     {
  243.         Locale locale = null;
  244.         HashMap<String, Object> model = new HashMap<>( );
  245.         LuteceUser user = null;
  246.         String strWebmasterEmail = DatastoreService.getDataValue( KEY_WEBMASTER_EMAIL, "" );
  247.         model.put( Markers.WEBMASTER_EMAIL, strWebmasterEmail );

  248.         locale = LocaleService.getContextUserLocale( request );

  249.         if ( request != null )
  250.         {
  251.             user = SecurityService.getInstance( ).getRegisteredUser( request );
  252.             if ( nMode != MODE_ADMIN )
  253.             {
  254.                 model.put( MARK_LUTECE_USER, user );
  255.             }
  256.         }

  257.         List<PageInclude> listIncludes = PageIncludeService.getIncludes( );

  258.         for ( PageInclude pic : listIncludes )
  259.         {
  260.             pic.fillTemplate( model, data, nMode, request );
  261.         }

  262.         String strHeader = data.isHomePage( ) ? AppPropertiesService.getProperty( PROPERTY_HOME_PAGE_HEADER + nMode, TEMPLATE_HOME_PAGE_HEADER )
  263.                 : AppPropertiesService.getProperty( PROPERTY_INTERNAL_PAGE_HEADER + nMode, TEMPLATE_INTERNAL_PAGE_HEADER );
  264.         HtmlTemplate tHeader = AppTemplateService.getTemplate( strHeader, locale, model );

  265.         String strFooter = AppPropertiesService.getProperty( PROPERTY_PORTAL_FOOTER + nMode, TEMPLATE_PORTAL_FOOTER );
  266.         String strToolsMenu = AppPropertiesService.getProperty( PROPERTY_PAGE_TOOLS_MENU + nMode, TEMPLATE_PAGE_TOOLS_MENU );
  267.         model.put( MARK_IS_CONTACT_INSTALLED, isContactActivated( ) );

  268.         boolean bDisplayLastModified = data.getDisplayDateUpdate( );
  269.         model.put( MARK_DISPLAY_LAST_MODIFIED, bDisplayLastModified );

  270.         if ( request != null )
  271.         {
  272.             String strLastModified = DateUtil.getDateString( data.getDateUpdate( ), locale );
  273.             model.put( MARK_LAST_MODIFIED, strLastModified );
  274.         }
  275.         HtmlTemplate tFooter = AppTemplateService.getTemplate( strFooter, locale, model );

  276.         HtmlTemplate tToolsMenu = AppTemplateService.getTemplate( strToolsMenu, locale, model );
  277.         model.put( Markers.PAGE_HEADER, tHeader.getHtml( ) );
  278.         model.put( MARKER_PAGE_DATA, data );
  279.         model.put( Markers.PAGE_NAME, data.getName( ) == null ? "" : data.getName( ) );
  280.         model.put( Markers.PAGE_CONTENT, data.getContent( ) == null ? "" : data.getContent( ) );
  281.         model.put( Markers.PAGE_PATH, data.getPagePath( ) == null ? "" : data.getPagePath( ) );
  282.         model.put( Markers.PAGE_TOOLS_MENU, tToolsMenu.getHtml( ) );
  283.         model.put( Markers.PAGE_ID, nCurrentPageId );

  284.         model.put( Markers.PAGE_FOOTER, tFooter.getHtml( ) );

  285.         String strBaseUrl = request != null ? AppPathService.getBaseUrl( request ) : ""; // request could be null
  286.                                                                                          // (method called by daemons
  287.                                                                                          // or batch)

  288.         // for link service
  289.         model.put( Markers.WEBAPP_PATH_FOR_LINKSERVICE, strBaseUrl );
  290.         model.put( Markers.BASE_URL, strBaseUrl );

  291.         String strEncoding = AppPropertiesService.getProperty( PROPERTY_ENCODING, PROPERTY_ENCODING_DEFAULT );

  292.         if ( strEncoding == null || strEncoding.equals( "" ) )
  293.         {
  294.             strEncoding = PROPERTY_ENCODING_DEFAULT;
  295.         }

  296.         model.put( Markers.ENCODING, strEncoding );

  297.         model.put( Markers.USER_CONTEXT_LANGUAGE, locale );

  298.         model.put( MARK_IS_EXTEND_INSTALLED, isExtendActivated( ) );

  299.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_PAGE_FRAMESET, locale, model );

  300.         template.substitute( BOOKMARK_BASE_URL, request != null ? AppPathService.getBaseUrl( request ) : "" ); // request
  301.                                                                                                                // could
  302.                                                                                                                // be
  303.                                                                                                                // null
  304.                                                                                                                // (method
  305.                                                                                                                // called
  306.                                                                                                                // by
  307.                                                                                                                // daemons
  308.                                                                                                                // or
  309.                                                                                                                // batch)

  310.         return template.getHtml( );
  311.     }

  312.     // //////////////////////////////////////////////////////////////////////////
  313.     // Management of the pages path

  314.     /**
  315.      * Returns the formated path of the site page whose identifier is specified in parameter
  316.      *
  317.      * @param nPageId
  318.      *            The identifier of the page
  319.      * @param nMode
  320.      *            The mode to use for the formatting
  321.      * @param request
  322.      *            The HTTP request
  323.      * @return the formated path
  324.      */
  325.     public static String getPagePathContent( int nPageId, int nMode, HttpServletRequest request )
  326.     {
  327.         String strPathOnRoot = AppPropertiesService.getProperty( PROPERTY_PATH_ON_ROOT );

  328.         // If the current page is the home page or the string strPathOnRoot equals
  329.         // false, not display the path
  330.         if ( nPageId == getRootPageId( ) && ( strPathOnRoot == null || strPathOnRoot.equalsIgnoreCase( "false" ) ) )
  331.         {
  332.             return "";
  333.         }

  334.         // Selection of the XSL stylesheet
  335.         // Added in v1.3
  336.         // Use the same stylesheet for normal or admin mode
  337.         StyleSheet xslSource;

  338.         switch( nMode )
  339.         {
  340.             case MODE_NORMAL:
  341.             case MODE_ADMIN:
  342.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, MODE_NORMAL );

  343.                 break;

  344.             default:
  345.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, nMode );

  346.                 break;
  347.         }

  348.         String strXml = getXmlPagesList( getPagePath( nPageId ) );

  349.         Properties outputProperties = ModeHome.getOuputXslProperties( nMode );

  350.         // Added in v1.3
  351.         // Add a path param for choose url to use in admin or normal mode
  352.         Map<String, String> mapParamRequest = new HashMap<>( );
  353.         setXslPortalPath( mapParamRequest, nMode );

  354.         XmlTransformerService xmlTransformerService = new XmlTransformerService( );
  355.         String strPath = xmlTransformerService.transformBySourceWithXslCache( strXml, xslSource, mapParamRequest, outputProperties );

  356.         return formatPath( strPath, nMode, request );
  357.     }

  358.     /**
  359.      * Returns the formated path of a xpage (ex : result of a seek)
  360.      *
  361.      * @param strXPageName
  362.      *            The xpage name
  363.      * @param nMode
  364.      *            The mode to use for the formatting
  365.      * @param request
  366.      *            The HTTP request
  367.      * @return the formated path
  368.      */
  369.     public static String getXPagePathContent( String strXPageName, int nMode, HttpServletRequest request )
  370.     {
  371.         final IPathCacheService pathCacheService = SpringContextService.getBean( IPathCacheService.BEAN_NAME );

  372.         final String strKey = pathCacheService.getKey( strXPageName, nMode, request );

  373.         String strRes = pathCacheService.getFromCache( strKey );

  374.         if ( strRes != null )
  375.         {
  376.             return strRes;
  377.         }

  378.         // Added in v1.3
  379.         StyleSheet xslSource;

  380.         // Selection of the XSL stylesheet
  381.         switch( nMode )
  382.         {
  383.             case MODE_NORMAL:
  384.             case MODE_ADMIN:
  385.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, MODE_NORMAL );

  386.                 break;

  387.             default:
  388.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, nMode );

  389.                 break;
  390.         }

  391.         String strXml = StringUtils.EMPTY;
  392.         String strPageId = request.getParameter( Parameters.PAGE_ID );

  393.         if ( StringUtils.isNotBlank( strPageId ) && StringUtils.isNumeric( strPageId ) )
  394.         {
  395.             int nPageId = Integer.parseInt( strPageId );
  396.             strXml = getXmlPagesList( getXPagePath( strXPageName, nPageId ) );
  397.         }
  398.         else
  399.         {
  400.             String strPortletId = request.getParameter( Parameters.PORTLET_ID );

  401.             if ( StringUtils.isNotBlank( strPortletId ) && StringUtils.isNumeric( strPortletId ) )
  402.             {
  403.                 int nPortletId = Integer.parseInt( strPortletId );
  404.                 Portlet portlet = PortletHome.findByPrimaryKey( nPortletId );

  405.                 if ( portlet != null )
  406.                 {
  407.                     int nPageId = portlet.getPageId( );
  408.                     strXml = getXmlPagesList( getXPagePath( strXPageName, nPageId ) );
  409.                 }
  410.             }
  411.         }

  412.         if ( StringUtils.isBlank( strXml ) )
  413.         {
  414.             strXml = getXmlPagesList( getXPagePath( strXPageName ) );
  415.         }

  416.         Properties outputProperties = ModeHome.getOuputXslProperties( nMode );

  417.         // Added in v1.3
  418.         // Add a path param for choose url to use in admin or normal mode
  419.         Map<String, String> mapXslParams = new HashMap<>( );
  420.         setXslPortalPath( mapXslParams, nMode );

  421.         XmlTransformerService xmlTransformerService = new XmlTransformerService( );
  422.         String strPath = xmlTransformerService.transformBySourceWithXslCache( strXml, xslSource, mapXslParams, outputProperties );

  423.         strRes = formatPath( strPath, nMode, request );

  424.         pathCacheService.putInCache( strKey, strRes );

  425.         return strRes;
  426.     }

  427.     /**
  428.      * Builds a collection of pages corresponding to the path of the page specified in parameter
  429.      *
  430.      * @param nPageId
  431.      *            The identifier of the page
  432.      * @return A collection of pages from the home page to the specified page
  433.      */
  434.     public static Collection<Page> getPagePath( int nPageId )
  435.     {
  436.         ArrayList<Page> list = new ArrayList<>( );
  437.         Page page = PageHome.getPage( nPageId );
  438.         int nParentPageId = page.getParentPageId( );
  439.         list.add( page );

  440.         while ( nParentPageId != 0 )
  441.         {
  442.             Page parentPage = PageHome.getPage( nParentPageId );

  443.             // Insert the page in the begin of the list
  444.             list.add( 0, parentPage );
  445.             nParentPageId = parentPage.getParentPageId( );
  446.         }

  447.         return list;
  448.     }

  449.     /**
  450.      * Builds a collection of pages corresponding to the path of a xpage
  451.      *
  452.      * @param strXPageName
  453.      *            The xpage name
  454.      * @return A collection of pages made by the home page and the xpage
  455.      */
  456.     private static Collection<Page> getXPagePath( String strXPageName )
  457.     {
  458.         ArrayList<Page> list = new ArrayList<>( );
  459.         Page homePage = PageHome.getPage( getRootPageId( ) );
  460.         list.add( homePage );

  461.         Page xPage = new Page( );
  462.         xPage.setName( strXPageName );
  463.         list.add( xPage );

  464.         return list;
  465.     }

  466.     /**
  467.      * Builds a collection of pages corresponding to the path of a xpage
  468.      *
  469.      * @param strXPageName
  470.      *            The xpage name
  471.      * @param nPageId
  472.      *            The Page's ID
  473.      * @return A collection of pages made by the home page and the xpage
  474.      */
  475.     private static Collection<Page> getXPagePath( String strXPageName, int nPageId )
  476.     {
  477.         List<Page> list = new ArrayList<>( );
  478.         Page page = PageHome.getPage( nPageId );

  479.         if ( page != null )
  480.         {
  481.             int nParentPageId = page.getParentPageId( );

  482.             while ( ( nParentPageId > 0 ) && ( nParentPageId != getRootPageId( ) ) )
  483.             {
  484.                 Page parentPage = PageHome.getPage( nParentPageId );

  485.                 if ( parentPage != null )
  486.                 {
  487.                     // Insert the page at the beginning of the list
  488.                     list.add( 0, parentPage );
  489.                     nParentPageId = parentPage.getParentPageId( );
  490.                 }
  491.             }

  492.             if ( nPageId != getRootPageId( ) )
  493.             {
  494.                 list.add( page );
  495.             }
  496.         }

  497.         // Insert the home page at the beginning of the list
  498.         Page homePage = PageHome.getPage( getRootPageId( ) );
  499.         list.add( 0, homePage );

  500.         // Insert the XPage at the end of the list
  501.         Page xPage = new Page( );
  502.         xPage.setName( strXPageName );
  503.         xPage.setId( nPageId );
  504.         list.add( xPage );

  505.         return list;
  506.     }

  507.     // //////////////////////////////////////////////////////////////////////////

  508.     /**
  509.      * Formats the path specified in parameter and returns it
  510.      *
  511.      * @param strPath
  512.      *            The path to format
  513.      * @param nMode
  514.      *            The mode to use for the formatting
  515.      * @param request
  516.      *            The HTTP request
  517.      * @return the html code to display the path
  518.      */
  519.     public static String formatPath( String strPath, int nMode, HttpServletRequest request )
  520.     {
  521.         HashMap<String, Object> model = new HashMap<>( );
  522.         model.put( Markers.PAGE_PATH, strPath );

  523.         List<PageInclude> listIncludes = PageIncludeService.getIncludes( );
  524.         PageData data = new PageData( );

  525.         for ( PageInclude pic : listIncludes )
  526.         {
  527.             pic.fillTemplate( model, data, nMode, request );
  528.         }

  529.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_PAGE_PATH, ( request == null ) ? null : request.getLocale( ), model );

  530.         return template.getHtml( );
  531.     }

  532.     /**
  533.      * Return the xml content of the pages specified by the xml code. This is called when using the Extended Xml path Label.
  534.      *
  535.      * @param strXmlExtend
  536.      *            The xml code to append to the path
  537.      * @return the xml code for the content page
  538.      */
  539.     private static String getXmlPagesListExtended( String strXmlExtend )
  540.     {
  541.         StringBuffer strXml = new StringBuffer( );
  542.         strXml.append( XmlUtil.getXmlHeader( ) );
  543.         XmlUtil.beginElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );

  544.         Page homePage = PageHome.getPage( getRootPageId( ) );

  545.         XmlUtil.beginElement( strXml, XmlContent.TAG_PAGE );
  546.         XmlUtil.addElement( strXml, XmlContent.TAG_PAGE_ID, homePage.getId( ) );
  547.         XmlUtil.addElementHtml( strXml, XmlContent.TAG_PAGE_NAME, homePage.getName( ) );
  548.         XmlUtil.endElement( strXml, XmlContent.TAG_PAGE );

  549.         strXml.append( strXmlExtend );

  550.         XmlUtil.endElement( strXml, XmlContent.TAG_CHILD_PAGES_LIST );

  551.         return strXml.toString( );
  552.     }

  553.     /**
  554.      * 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
  555.      * the Extended Xml path Label.
  556.      *
  557.      * @param strXPageName
  558.      *            The xpage name
  559.      * @param nMode
  560.      *            The mode to use for the formatting
  561.      * @param strTitlesUrls
  562.      *            list of links (url and titles)
  563.      * @param request
  564.      *            The HTTP request
  565.      * @return the formatted path
  566.      */
  567.     public static String getXPagePathContent( String strXPageName, int nMode, String strTitlesUrls, HttpServletRequest request )
  568.     {
  569.         final IPathCacheService pathCacheService = SpringContextService.getBean( IPathCacheService.BEAN_NAME );

  570.         final String strKey = pathCacheService.getKey( strXPageName, nMode, strTitlesUrls, request );

  571.         String strRes = pathCacheService.getFromCache( strKey );

  572.         if ( strRes != null )
  573.         {
  574.             return strRes;
  575.         }

  576.         // Selection of the XSL stylesheet
  577.         StyleSheet xslSource;

  578.         // Selection of the XSL stylesheet
  579.         switch( nMode )
  580.         {
  581.             case MODE_NORMAL:
  582.             case MODE_ADMIN:
  583.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, MODE_NORMAL );

  584.                 break;

  585.             default:
  586.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_PAGE_PATH_ID, nMode );

  587.                 break;
  588.         }

  589.         String strXml = getXmlPagesListExtended( strTitlesUrls );

  590.         Properties outputProperties = ModeHome.getOuputXslProperties( nMode );

  591.         // Added in v1.3
  592.         // Add a path param for choose url to use in admin or normal mode
  593.         Map<String, String> mapXslParams = new HashMap<>( );
  594.         setXslPortalPath( mapXslParams, nMode );

  595.         XmlTransformerService xmlTransformerService = new XmlTransformerService( );
  596.         String strPath = xmlTransformerService.transformBySourceWithXslCache( strXml, xslSource, mapXslParams, outputProperties );

  597.         strRes = formatPath( strPath, nMode, request );

  598.         pathCacheService.putInCache( strKey, strRes );

  599.         return strRes;
  600.     }

  601.     /**
  602.      * Sets XSL portal path
  603.      *
  604.      * @param mapParameters
  605.      *            Parameters as a map
  606.      * @param nMode
  607.      *            The mode
  608.      */
  609.     public static void setXslPortalPath( Map<String, String> mapParameters, int nMode )
  610.     {
  611.         if ( nMode != MODE_ADMIN )
  612.         {
  613.             mapParameters.put( PARAMETER_SITE_PATH, AppPathService.getPortalUrl( ) );
  614.         }
  615.         else
  616.         {
  617.             mapParameters.put( PARAMETER_SITE_PATH, AppPathService.getAdminPortalUrl( ) );
  618.             mapParameters.put( MARKER_TARGET, TARGET_TOP );
  619.         }
  620.     }

  621.     /**
  622.      * Returns the site name
  623.      *
  624.      * @return The site name
  625.      */
  626.     public static String getSiteName( )
  627.     {
  628.         return DatastoreService.getDataValue( KEY_SITE_NAME, StringUtils.EMPTY );
  629.     }

  630.     /**
  631.      * Check if the extend plugin is activated
  632.      *
  633.      * @return True if the plugin is activated, false otherwise
  634.      */
  635.     public static boolean isExtendActivated( )
  636.     {
  637.         return PluginService.isPluginEnable( PLUGIN_EXTEND_NAME );
  638.     }

  639.     /**
  640.      * Check if the cotnact plugin is activated
  641.      *
  642.      * @return True if the plugin is activated, false otherwise
  643.      */
  644.     public static boolean isContactActivated( )
  645.     {
  646.         return PluginService.isPluginEnable( PLUGIN_CONTACT_NAME );
  647.     }

  648.     /**
  649.      * Get the list of CSS links for session less pages
  650.      *
  651.      * @return The HTML code providing the list of CSS links.
  652.      */
  653.     public static String getAdminCssLinks( )
  654.     {
  655.         HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_ADMIN_CSS_LINKS );
  656.         return template.getHtml( );
  657.     }
  658. }