SiteMapApp.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.web.xpages;

  35. import fr.paris.lutece.portal.business.XmlContent;
  36. import fr.paris.lutece.portal.business.page.Page;
  37. import fr.paris.lutece.portal.business.page.PageHome;
  38. import fr.paris.lutece.portal.business.portalcomponent.PortalComponentHome;
  39. import fr.paris.lutece.portal.business.style.ModeHome;
  40. import fr.paris.lutece.portal.business.stylesheet.StyleSheet;
  41. import fr.paris.lutece.portal.service.html.XmlTransformerService;
  42. import fr.paris.lutece.portal.service.i18n.I18nService;
  43. import fr.paris.lutece.portal.service.plugin.Plugin;
  44. import fr.paris.lutece.portal.service.portal.PortalService;
  45. import fr.paris.lutece.portal.service.security.LuteceUser;
  46. import fr.paris.lutece.portal.service.security.SecurityService;
  47. import fr.paris.lutece.portal.service.util.AppLogService;
  48. import fr.paris.lutece.portal.service.util.AppPathService;
  49. import fr.paris.lutece.portal.web.admin.AdminPageJspBean;
  50. import fr.paris.lutece.util.xml.XmlUtil;

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

  52. import java.util.Arrays;
  53. import java.util.HashMap;
  54. import java.util.HashSet;
  55. import java.util.Locale;
  56. import java.util.Map;
  57. import java.util.Properties;
  58. import java.util.Set;

  59. import javax.servlet.http.HttpServletRequest;

  60. /**
  61.  * This class provides the map of the pages on the site
  62.  */
  63. public class SiteMapApp implements XPageApplication
  64. {
  65.     /**
  66.      * Serial version UID
  67.      */
  68.     private static final long serialVersionUID = 1799476496018552101L;
  69.     private static final int PORTAL_COMPONENT_SITE_MAP_ID = 6;
  70.     private static final int MODE_NORMAL = 0;
  71.     private static final int MODE_ADMIN = 1;
  72.     private static final String PARAMETER_SITE_PATH = "site-path";
  73.     private static final String MARKER_TARGET = "target";
  74.     private static final String TARGET_TOP = "target='_top'";
  75.     private static final String PROPERTY_SERVICE_NAME = "portal.site.serviceName.siteMapService";
  76.     private static final String PROPERTY_PATH_LABEL = "portal.site.site_map.pathLabel";
  77.     private static final String PROPERTY_PAGE_TITLE = "portal.site.site_map.pageTitle";

  78.     /**
  79.      * Creates a new SiteMapPage object
  80.      */
  81.     public SiteMapApp( )
  82.     {
  83.         // Ctor
  84.     }

  85.     /**
  86.      * Returns the localized service name
  87.      *
  88.      * @param locale
  89.      *            The locale
  90.      * @return The localized service name
  91.      */
  92.     public String getName( Locale locale )
  93.     {
  94.         return I18nService.getLocalizedString( PROPERTY_SERVICE_NAME, locale );
  95.     }

  96.     /**
  97.      * Build or get in the cache the page which contains the site map depending on the mode
  98.      *
  99.      * @param request
  100.      *            The Http request
  101.      * @param nMode
  102.      *            The selected mode
  103.      * @param plugin
  104.      *            The plugin
  105.      * @return The content of the site map
  106.      */
  107.     @Override
  108.     public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin )
  109.     {
  110.         XPage page = new XPage( );
  111.         String strKey = getKey( nMode, request );

  112.         Locale locale = request.getLocale( );

  113.         SiteMapCacheService siteMapCacheService = SiteMapCacheService.getInstance( );

  114.         // Check the key in the cache
  115.         String strCachedPage = siteMapCacheService.isCacheEnable( ) ? (String) siteMapCacheService.getFromCache( strKey ) : null;

  116.         if ( strCachedPage == null )
  117.         {
  118.             // Build the HTML document
  119.             String strPage = buildPageContent( nMode, request );

  120.             // Add it to the cache
  121.             if ( siteMapCacheService.isCacheEnable( ) )
  122.             {
  123.                 synchronized( strKey )
  124.                 {
  125.                     siteMapCacheService.putInCache( strKey, strPage );
  126.                 }
  127.             }

  128.             page.setPathLabel( I18nService.getLocalizedString( PROPERTY_PATH_LABEL, locale ) );
  129.             page.setTitle( I18nService.getLocalizedString( PROPERTY_PAGE_TITLE, locale ) );
  130.             page.setContent( strPage );

  131.             return page;
  132.         }

  133.         // The document exist in the cache
  134.         page.setPathLabel( I18nService.getLocalizedString( PROPERTY_PATH_LABEL, locale ) );
  135.         page.setTitle( I18nService.getLocalizedString( PROPERTY_PAGE_TITLE, locale ) );
  136.         page.setContent( strCachedPage );

  137.         return page;
  138.     }

  139.     /**
  140.      * Gets the cache key
  141.      *
  142.      * @param nMode
  143.      *            The mode
  144.      * @param request
  145.      *            The HTTP request
  146.      * @return The key
  147.      */
  148.     private String getKey( int nMode, HttpServletRequest request )
  149.     {
  150.         String strRoles = "-";

  151.         if ( SecurityService.isAuthenticationEnable( ) )
  152.         {
  153.             LuteceUser user = SecurityService.getInstance( ).getRegisteredUser( request );

  154.             if ( ( user != null ) && ( user.getRoles( ) != null ) )
  155.             {
  156.                 String [ ] roles = user.getRoles( );
  157.                 Arrays.sort( roles );
  158.                 strRoles = StringUtils.join( roles, ',' );
  159.             }
  160.         }

  161.         return "[m:" + nMode + "][roles:" + strRoles + "]";
  162.     }

  163.     /**
  164.      * Build an XML document containing the arborescence of the site pages and transform it with the stylesheet combined with the mode
  165.      *
  166.      * @param nMode
  167.      *            The selected mode
  168.      * @param request
  169.      *            The HttpServletRequest
  170.      * @return The content of the site map
  171.      */
  172.     private String buildPageContent( int nMode, HttpServletRequest request )
  173.     {
  174.         StringBuffer strArborescenceXml = new StringBuffer( );
  175.         strArborescenceXml.append( XmlUtil.getXmlHeader( ) );

  176.         int nLevel = 0;
  177.         findPages( strArborescenceXml, PortalService.getRootPageId( ), nLevel, new HashSet<>( ), request );

  178.         // Added in v1.3
  179.         // Use the same stylesheet for normal or admin mode
  180.         StyleSheet xslSource;

  181.         switch( nMode )
  182.         {
  183.             case MODE_NORMAL:
  184.             case MODE_ADMIN:
  185.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_SITE_MAP_ID, MODE_NORMAL );

  186.                 break;

  187.             default:
  188.                 xslSource = PortalComponentHome.getXsl( PORTAL_COMPONENT_SITE_MAP_ID, nMode );

  189.                 break;
  190.         }

  191.         // Added in v1.3
  192.         // Add a path param for choose url to use in admin or normal mode
  193.         Map<String, String> mapParamRequest = new HashMap<>( );

  194.         if ( nMode != MODE_ADMIN )
  195.         {
  196.             mapParamRequest.put( PARAMETER_SITE_PATH, AppPathService.getPortalUrl( ) );
  197.         }
  198.         else
  199.         {
  200.             mapParamRequest.put( PARAMETER_SITE_PATH, AppPathService.getAdminPortalUrl( ) );
  201.             mapParamRequest.put( MARKER_TARGET, TARGET_TOP );
  202.         }

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

  204.         XmlTransformerService xmlTransformerService = new XmlTransformerService( );

  205.         return xmlTransformerService.transformBySourceWithXslCache( strArborescenceXml.toString( ), xslSource, mapParamRequest, outputProperties );
  206.     }

  207.     /**
  208.      * Build recursively the XML document containing the arborescence of the site pages
  209.      *
  210.      * @param strXmlArborescence
  211.      *            The buffer in which adding the current page of the arborescence
  212.      * @param nPageId
  213.      *            The current page of the recursive course
  214.      * @param nLevel
  215.      *            The depth level of the page in the arborescence
  216.      * @param request
  217.      *            The HttpServletRequest
  218.      */
  219.     private void findPages( StringBuffer strXmlArborescence, int nPageId, int nLevel, Set<Integer> seenPages, HttpServletRequest request )
  220.     {
  221.         if ( !seenPages.add( nPageId ) )
  222.         {
  223.             AppLogService.error( "SiteMapApp : A cycle exists in pages; page id {} was already processed", nPageId );
  224.             return;
  225.         }
  226.         Page page = PageHome.getPage( nPageId );

  227.         if ( page.isVisible( request ) )
  228.         {
  229.             XmlUtil.beginElement( strXmlArborescence, XmlContent.TAG_PAGE );
  230.             XmlUtil.addElement( strXmlArborescence, XmlContent.TAG_PAGE_ID, page.getId( ) );
  231.             XmlUtil.addElementHtml( strXmlArborescence, XmlContent.TAG_PAGE_NAME, page.getName( ) );
  232.             XmlUtil.addElement( strXmlArborescence, XmlContent.TAG_PAGE_DESCRIPTION, page.getDescription( ) );
  233.             XmlUtil.addElement( strXmlArborescence, XmlContent.TAG_PAGE_LEVEL, nLevel );

  234.             AdminPageJspBean adminPage = new AdminPageJspBean( );

  235.             if ( page.getImageContent( ) != null )
  236.             {
  237.                 int nImageLength = page.getImageContent( ).length;

  238.                 if ( nImageLength >= 1 )
  239.                 {
  240.                     String strPageId = Integer.toString( page.getId( ) );
  241.                     XmlUtil.addElement( strXmlArborescence, XmlContent.TAG_PAGE_IMAGE, adminPage.getResourceImagePage( page, strPageId ) );
  242.                 }
  243.             }

  244.             XmlUtil.beginElement( strXmlArborescence, XmlContent.TAG_CHILD_PAGES_LIST );

  245.             for ( Page pageChild : PageHome.getChildPagesMinimalData( nPageId ) )
  246.             {
  247.                 findPages( strXmlArborescence, pageChild.getId( ), nLevel + 1, seenPages, request );
  248.             }

  249.             XmlUtil.endElement( strXmlArborescence, XmlContent.TAG_CHILD_PAGES_LIST );
  250.             XmlUtil.endElement( strXmlArborescence, XmlContent.TAG_PAGE );
  251.         }
  252.     }
  253. }