ExtendableContentPostProcessor.java
/*
* Copyright (c) 2002-2021, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.extend.service.content;
import fr.paris.lutece.plugins.extend.business.extender.ResourceExtenderDTO;
import fr.paris.lutece.plugins.extend.service.converter.IStringMapper;
import fr.paris.lutece.plugins.extend.service.extender.IResourceExtenderService;
import fr.paris.lutece.portal.business.page.Page;
import fr.paris.lutece.portal.service.content.ContentPostProcessor;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.util.html.HtmlTemplate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
/**
*
* This content post processor replace all macro of type @Extender[idResource,resourceType,extenderType,parameters]@ to the associated extender content.
*
*/
public class ExtendableContentPostProcessor implements ContentPostProcessor, InitializingBean
{
/**
* Name of this bean
*/
public static final String BEAN_NAME = "extend.extendableContentPostProcessor";
private static final String NAME = "Extend content processor";
private static final String END_BODY = "</body>";
private static final String EXTEND_PARAMETERED_ID = "ExtendParameteredId";
// PROPERTIES
private static final String PROPERTY_CLIENT_SIDE = "extend.contentPostProcessor.clientSide";
// MARKS
private static final String MARK_REGEX_PATTERN = "extendRegexPattern";
private static final String MARK_BASE_URL = "baseUrl";
private static final String PARAM_PAGE = "page";
private static final String PARAM_PORTLET_ID = "portlet_id";
// TEMPLATES
private static final String TEMPLATE_CONTENT_POST_PROCESSOR = "skin/plugins/extend/extendable_content_post_processor.html";
@Inject
private IResourceExtenderService _extenderService;
@Inject
private IStringMapper<ResourceExtenderDTO> _mapper;
private String _strRegexPattern;
private Pattern _regexPattern;
private String _strExtenderParameterRegexPattern;
private Pattern _extendedParameterRegexPattern;
/**
* Sets the regex pattern.
*
* @param strRegexPattern
* the new regex pattern
*/
public void setRegexPattern( String strRegexPattern )
{
_strRegexPattern = strRegexPattern;
if ( _regexPattern == null || !_regexPattern.pattern( ).equals( strRegexPattern ) )
{
Pattern pattern = Pattern.compile( strRegexPattern );
_regexPattern = pattern;
}
}
/**
* Sets the regex pattern.
*
* @param strExtenderParameterRegexPattern
* the new regex pattern
*/
public void setExtenderParameterRegexPattern( String strExtenderParameterRegexPattern )
{
_strExtenderParameterRegexPattern = strExtenderParameterRegexPattern;
if ( _extendedParameterRegexPattern == null || !_extendedParameterRegexPattern.pattern( ).equals( strExtenderParameterRegexPattern ) )
{
Pattern pattern = Pattern.compile( strExtenderParameterRegexPattern );
_extendedParameterRegexPattern = pattern;
}
}
/**
* {@inheritDoc}
*/
@Override
public String getName( )
{
return NAME;
}
/**
* {@inheritDoc}
*/
@Override
public String process( HttpServletRequest request, String strContent )
{
String strHtmlContent = strContent;
// Check if the process is carried out in client or server side
boolean bClientSide = Boolean.valueOf( AppPropertiesService.getProperty( PROPERTY_CLIENT_SIDE, "false" ) );
if ( bClientSide )
{
// CLIENT SIDE
int nPos = strHtmlContent.indexOf( END_BODY );
if ( nPos < 0 )
{
AppLogService.error( "ExtendableContentPostProcessor Service : no BODY end tag found" );
return strHtmlContent;
}
Map<String, Object> model = new HashMap<String, Object>( );
model.put( MARK_BASE_URL, AppPathService.getBaseUrl( request ) );
model.put( MARK_REGEX_PATTERN, _strRegexPattern );
HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_CONTENT_POST_PROCESSOR, request.getLocale( ), model );
StringBuilder sb = new StringBuilder( );
sb.append( strHtmlContent.substring( 0, nPos ) );
sb.append( template.getHtml( ) );
sb.append( strHtmlContent.substring( nPos ) );
strHtmlContent = sb.toString( );
}
else
{
// SERVER SIDE
/**
* Replace all makers @Extender[<idResource>,<resourceType>,<extenderType>,<params>]@ to the correct HTML content of the extender. 1) First parse
* the content of the markers 2) Get all information (idResource, resourceType, extenderType, params) 3) Get the html content from the given
* information 4) Replace the markers by the html content
*/
// 1) First parse the content of the markers
Matcher match = _regexPattern.matcher( strHtmlContent );
Matcher parameterMatch = null;
StringBuffer strResultHTML = new StringBuffer( strHtmlContent.length( ) );
while ( match.find( ) )
{
String strMarker = match.group( );
// 2) Get all information (idResource, resourceType, extenderType, params)
ResourceExtenderDTO resourceExtender = _mapper.map( match.group( 1 ) );
boolean bParameteredId = StringUtils.equalsIgnoreCase( resourceExtender.getIdExtendableResource( ), EXTEND_PARAMETERED_ID );
if ( bParameteredId )
{
if ( parameterMatch == null )
{
parameterMatch = _extendedParameterRegexPattern.matcher( strHtmlContent );
}
else
{
parameterMatch.reset( );
}
while ( parameterMatch.find( ) )
{
ResourceExtenderDTO realResourceExtender = _mapper.map( parameterMatch.group( 1 ) );
if ( StringUtils.equals( realResourceExtender.getExtendableResourceType( ), resourceExtender.getExtendableResourceType( ) )
&& StringUtils.equals( realResourceExtender.getExtenderType( ), resourceExtender.getExtenderType( ) ) )
{
resourceExtender.setIdExtendableResource( realResourceExtender.getIdExtendableResource( ) );
break;
}
}
}
String strHtml = StringUtils.EMPTY;
if ( !bParameteredId || !StringUtils.equalsIgnoreCase( resourceExtender.getIdExtendableResource( ), EXTEND_PARAMETERED_ID ) )
{
// 3) Get the html content from the given information
if ( !StringUtils.equals( resourceExtender.getExtendableResourceType( ), Page.RESOURCE_TYPE )
|| ( StringUtils.isBlank( request.getParameter( PARAM_PAGE ) )
&& StringUtils.isBlank( request.getParameter( PARAM_PORTLET_ID ) ) ) )
{
strHtml = _extenderService.getContent( resourceExtender.getIdExtendableResource( ), resourceExtender.getExtendableResourceType( ),
resourceExtender.getExtenderType( ), resourceExtender.getParameters( ), request );
}
}
// 4) Replace the markers by the html content
match.appendReplacement( strResultHTML, Matcher.quoteReplacement( strHtml ) );
}
match.appendTail( strResultHTML );
strHtmlContent = strResultHTML.toString( );
}
if ( StringUtils.isNotBlank( _strExtenderParameterRegexPattern ) )
{
strHtmlContent = _extendedParameterRegexPattern.matcher( strHtmlContent ).replaceAll( "" );
}
return strHtmlContent;
}
/**
* {@inheritDoc}
*/
@Override
public void afterPropertiesSet( ) throws Exception
{
Assert.notNull( _strRegexPattern, "The property 'regexPattern' is required." );
}
}