MVCApplication.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.util.mvc.xpage;

  35. import fr.paris.lutece.portal.service.security.AccessLogService;
  36. import java.io.IOException;
  37. import java.io.OutputStream;
  38. import java.io.PrintWriter;
  39. import java.lang.reflect.InvocationTargetException;
  40. import java.lang.reflect.Method;
  41. import java.util.ArrayList;
  42. import java.util.HashMap;
  43. import java.util.List;
  44. import java.util.Locale;
  45. import java.util.Map;
  46. import java.util.Map.Entry;
  47. import java.util.Set;

  48. import javax.servlet.http.HttpServletRequest;
  49. import javax.servlet.http.HttpServletResponse;
  50. import javax.validation.ConstraintViolation;

  51. import org.apache.logging.log4j.Logger;
  52. import org.springframework.util.ReflectionUtils;

  53. import fr.paris.lutece.portal.service.i18n.I18nService;
  54. import fr.paris.lutece.portal.service.message.SiteMessageException;
  55. import fr.paris.lutece.portal.service.plugin.Plugin;
  56. import fr.paris.lutece.portal.service.security.AccessLoggerConstants;
  57. import fr.paris.lutece.portal.service.security.LuteceUser;
  58. import fr.paris.lutece.portal.service.security.SecurityService;
  59. import fr.paris.lutece.portal.service.security.UserNotSignedException;
  60. import fr.paris.lutece.portal.service.template.AppTemplateService;
  61. import fr.paris.lutece.portal.service.util.AppException;
  62. import fr.paris.lutece.portal.service.util.AppLogService;
  63. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  64. import fr.paris.lutece.portal.util.mvc.utils.MVCMessage;
  65. import fr.paris.lutece.portal.util.mvc.utils.MVCMessageBox;
  66. import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
  67. import fr.paris.lutece.portal.util.mvc.xpage.annotations.Controller;
  68. import fr.paris.lutece.portal.web.LocalVariables;
  69. import fr.paris.lutece.portal.web.l10n.LocaleService;
  70. import fr.paris.lutece.portal.web.xpages.XPage;
  71. import fr.paris.lutece.portal.web.xpages.XPageApplication;
  72. import fr.paris.lutece.util.ErrorMessage;
  73. import fr.paris.lutece.util.bean.BeanUtil;
  74. import fr.paris.lutece.util.beanvalidation.BeanValidationUtil;
  75. import fr.paris.lutece.util.html.HtmlTemplate;
  76. import fr.paris.lutece.util.url.UrlItem;

  77. /**
  78.  * MVC XPage Application
  79.  */
  80. public abstract class MVCApplication implements XPageApplication
  81. {
  82.     private static final long serialVersionUID = 6093635383465830355L;

  83.     // markers
  84.     private static final String MARK_ERRORS = "errors";
  85.     private static final String MARK_INFOS = "infos";
  86.     private static final String MARK_WARNINGS = "warnings";
  87.     private static final String MARK_MESSAGE_BOX = "messageBox";

  88.     // constants
  89.     private static final String URL_PORTAL = "Portal.jsp";
  90.     private static final String PATH_PORTAL = "jsp/site/";
  91.     private static final String VIEW_MESSAGEBOX = "messageBox";
  92.     private static final String CONTENT_TYPE_JSON = "application/json";
  93.     private static final String CONTENT_TYPE_XML = "application/xml";

  94.     // instance vars
  95.     private static Logger _logger = MVCUtils.getLogger( );
  96.     private List<ErrorMessage> _listErrors = new ArrayList<>( );
  97.     private List<ErrorMessage> _listInfos = new ArrayList<>( );
  98.     private List<ErrorMessage> _listWarnings = new ArrayList<>( );
  99.     private MVCMessageBox _messageBox;
  100.     private Controller _controller = getClass( ).getAnnotation( Controller.class );

  101.     /**
  102.      * Returns the content of the page
  103.      *
  104.      * @param request
  105.      *            The http request
  106.      * @param nMode
  107.      *            The current mode
  108.      * @param plugin
  109.      *            The plugin object
  110.      * @return The XPage
  111.      * @throws fr.paris.lutece.portal.service.message.SiteMessageException
  112.      *             Message displayed if an exception occurs
  113.      * @throws UserNotSignedException
  114.      *             if an authentication is required by a view
  115.      */
  116.     @Override
  117.     public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin ) throws SiteMessageException, UserNotSignedException
  118.     {
  119.         return processController( request );
  120.     }

  121.     // //////////////////////////////////////////////////////////////////////////
  122.     // Controller

  123.     /**
  124.      * XPage controller
  125.      *
  126.      * @param request
  127.      *            The HTTP request
  128.      * @return The XPage
  129.      * @throws UserNotSignedException
  130.      *             if an authentication is required by a view
  131.      * @throws SiteMessageException
  132.      *             if a message is thrown by an action
  133.      */
  134.     private XPage processController( HttpServletRequest request ) throws UserNotSignedException, SiteMessageException
  135.     {
  136.         Method [ ] methods = ReflectionUtils.getAllDeclaredMethods( getClass( ) );

  137.         try
  138.         {
  139.             if ( isMessageBox( request ) )
  140.             {
  141.                 return messageBox( request );
  142.             }

  143.             LuteceUser registredUser = getRegistredUser( request );

  144.             // Process views
  145.             Method m = MVCUtils.findViewAnnotedMethod( request, methods );

  146.             if ( m != null )
  147.             {
  148.                 AccessLogService.getInstance( ).trace( AccessLoggerConstants.EVENT_TYPE_READ, m.getName( ), registredUser,
  149.                         request.getRequestURL( ) + "?" + request.getQueryString( ), AccessLogService.ACCESS_LOG_FO );
  150.                 return (XPage) m.invoke( this, request );
  151.             }

  152.             // Process actions
  153.             m = MVCUtils.findActionAnnotedMethod( request, methods );

  154.             if ( m != null )
  155.             {
  156.                 AccessLogService.getInstance( ).debug( AccessLoggerConstants.EVENT_TYPE_ACTION, m.getName( ), registredUser,
  157.                         request.getRequestURL( ) + "?" + request.getQueryString( ), AccessLogService.ACCESS_LOG_FO );
  158.                 return (XPage) m.invoke( this, request );
  159.             }

  160.             // No view or action found so display the default view
  161.             m = MVCUtils.findDefaultViewMethod( methods );

  162.             AccessLogService.getInstance( ).trace( AccessLoggerConstants.EVENT_TYPE_ACTION, m.getName( ), registredUser,
  163.                     request.getRequestURL( ) + "?" + request.getQueryString( ), AccessLogService.ACCESS_LOG_FO );
  164.             return (XPage) m.invoke( this, request );
  165.         }
  166.         catch( InvocationTargetException e )
  167.         {
  168.             if ( e.getTargetException( ) instanceof UserNotSignedException )
  169.             {
  170.                 throw (UserNotSignedException) e.getTargetException( );
  171.             }

  172.             if ( e.getTargetException( ) instanceof SiteMessageException )
  173.             {
  174.                 throw (SiteMessageException) e.getTargetException( );
  175.             }

  176.             if ( e.getTargetException( ) instanceof RuntimeException )
  177.             {
  178.                 throw new AppException( "MVC Error dispaching view and action ", (RuntimeException) e.getTargetException( ) );
  179.             }

  180.             throw new AppException( "MVC Error dispaching view and action ", e );
  181.         }
  182.         catch( IllegalAccessException e )
  183.         {
  184.             throw new AppException( "MVC Error dispaching view and action ", e );
  185.         }
  186.     }

  187.     /**
  188.      * Returns the XPage name
  189.      *
  190.      * @return The XPage name
  191.      */
  192.     protected String getXPageName( )
  193.     {
  194.         return _controller.xpageName( );
  195.     }

  196.     /**
  197.      * Returns the default page title
  198.      *
  199.      * @param locale
  200.      *            The locale
  201.      * @return The default page title
  202.      */
  203.     protected String getDefaultPageTitle( Locale locale )
  204.     {
  205.         if ( !_controller.pageTitleProperty( ).equals( "" ) )
  206.         {
  207.             return AppPropertiesService.getProperty( _controller.pageTitleProperty( ) );
  208.         }
  209.         else
  210.             if ( !_controller.pageTitleI18nKey( ).equals( "" ) )
  211.             {
  212.                 return I18nService.getLocalizedString( _controller.pageTitleI18nKey( ), locale );
  213.             }

  214.         return _controller.xpageName( );
  215.     }

  216.     /**
  217.      * Returns the default page path
  218.      *
  219.      * @param locale
  220.      *            The locale
  221.      * @return The default pagepath
  222.      */
  223.     protected String getDefaultPagePath( Locale locale )
  224.     {
  225.         if ( !_controller.pagePathProperty( ).equals( "" ) )
  226.         {
  227.             return AppPropertiesService.getProperty( _controller.pagePathProperty( ) );
  228.         }
  229.         else
  230.             if ( !_controller.pagePathI18nKey( ).equals( "" ) )
  231.             {
  232.                 return I18nService.getLocalizedString( _controller.pagePathI18nKey( ), locale );
  233.             }

  234.         return _controller.xpageName( );
  235.     }

  236.     // //////////////////////////////////////////////////////////////////////////
  237.     // XPage utils

  238.     /**
  239.      * Returns a new XPage object with default values
  240.      *
  241.      * @return An XPage Object
  242.      */
  243.     protected XPage getXPage( )
  244.     {
  245.         XPage page = new XPage( );

  246.         page.setTitle( getDefaultPageTitle( LocaleService.getDefault( ) ) );
  247.         page.setPathLabel( getDefaultPagePath( LocaleService.getDefault( ) ) );

  248.         return page;
  249.     }

  250.     /**
  251.      * Returns a new XPage object with default values and the content filled by a template
  252.      *
  253.      * @param strTemplate
  254.      *            The template
  255.      * @return An XPage Object
  256.      */
  257.     protected XPage getXPage( String strTemplate )
  258.     {
  259.         XPage page = getXPage( );

  260.         HtmlTemplate t = AppTemplateService.getTemplate( strTemplate );
  261.         page.setContent( t.getHtml( ) );

  262.         return page;
  263.     }

  264.     /**
  265.      * Returns a new XPage object with default values and the content filled by a template using a default model and for a given locale
  266.      *
  267.      * @param strTemplate
  268.      *            The template
  269.      * @param locale
  270.      *            The locale
  271.      * @return An XPage Object
  272.      */
  273.     protected XPage getXPage( String strTemplate, Locale locale )
  274.     {
  275.         return getXPage( strTemplate, locale, getModel( ) );
  276.     }

  277.     /**
  278.      * Returns a new XPage object with default values and the content filled by a template using a given model and for a given locale
  279.      *
  280.      * @param strTemplate
  281.      *            The template
  282.      * @param locale
  283.      *            The locale
  284.      * @param model
  285.      *            The model
  286.      *
  287.      * @return An XPage Object
  288.      */
  289.     protected XPage getXPage( String strTemplate, Locale locale, Map<String, Object> model )
  290.     {
  291.         XPage page = getXPage( );

  292.         HtmlTemplate t = AppTemplateService.getTemplate( strTemplate, locale, model );
  293.         page.setContent( t.getHtml( ) );
  294.         page.setTitle( getDefaultPageTitle( locale ) );
  295.         page.setPathLabel( getDefaultPagePath( locale ) );

  296.         return page;
  297.     }

  298.     /**
  299.      * Get a model Object filled with default values
  300.      *
  301.      * @return The model
  302.      */
  303.     protected Map<String, Object> getModel( )
  304.     {
  305.         Map<String, Object> model = new HashMap<>( );
  306.         fillCommons( model );

  307.         return model;
  308.     }

  309.     // //////////////////////////////////////////////////////////////////////////
  310.     // Bean processing

  311.     /**
  312.      * Populate a bean using parameters in http request
  313.      *
  314.      * @param bean
  315.      *            bean to populate
  316.      * @param request
  317.      *            http request
  318.      */
  319.     protected void populate( Object bean, HttpServletRequest request )
  320.     {
  321.         BeanUtil.populate( bean, request, null );
  322.     }

  323.     /**
  324.      * Populate a bean using parameters in http request, with locale date format controls
  325.      *
  326.      * @param bean
  327.      *            bean to populate
  328.      * @param request
  329.      *            http request
  330.      * @param locale
  331.      *            the locale
  332.      */
  333.     protected void populate( Object bean, HttpServletRequest request, Locale locale )
  334.     {
  335.         BeanUtil.populate( bean, request, locale );
  336.     }

  337.     /**
  338.      * Validate a bean. If the validation failed, error messages of this MVCApplication are updated.<br>
  339.      * This method should be used only if error messages of constraints of the bean are NOT i18n Keys. If they are I18n keys, the method
  340.      * {@link #validateBean(Object, Locale)} should be used instead.
  341.      *
  342.      * @param <T>
  343.      *            The bean class
  344.      * @param bean
  345.      *            The bean
  346.      * @return true if validated otherwise false
  347.      */
  348.     protected <T> boolean validateBean( T bean )
  349.     {
  350.         Set<ConstraintViolation<T>> errors = BeanValidationUtil.validate( bean );

  351.         if ( errors.isEmpty( ) )
  352.         {
  353.             return true;
  354.         }

  355.         for ( ConstraintViolation<T> constraint : errors )
  356.         {
  357.             MVCMessage error = new MVCMessage( );
  358.             error.setMessage( constraint.getMessage( ) );
  359.             _listErrors.add( error );
  360.         }

  361.         return false;
  362.     }

  363.     /**
  364.      * Validate a bean. If the validation failed, error messages of this MVCApplication are updated.<br>
  365.      * This method should be used only if error messages of constraints of the bean are i18n Keys. If they are not I18n keys, the method
  366.      * {@link #validateBean(Object)} should be used instead.
  367.      *
  368.      * @param <T>
  369.      *            The bean class
  370.      * @param bean
  371.      *            The bean
  372.      * @param locale
  373.      *            The locale
  374.      * @return true if validated otherwise false
  375.      */
  376.     protected <T> boolean validateBean( T bean, Locale locale )
  377.     {
  378.         Set<ConstraintViolation<T>> errors = BeanValidationUtil.validate( bean );

  379.         if ( errors.isEmpty( ) )
  380.         {
  381.             return true;
  382.         }

  383.         for ( ConstraintViolation<T> constraint : errors )
  384.         {
  385.             MVCMessage error = new MVCMessage( );
  386.             error.setMessage( I18nService.getLocalizedString( constraint.getMessage( ), locale ) );
  387.             _listErrors.add( error );
  388.         }

  389.         return false;
  390.     }

  391.     /**
  392.      * Add an error message. The error message must NOT be an I18n key.
  393.      *
  394.      * @param strMessage
  395.      *            The message
  396.      */
  397.     protected void addError( String strMessage )
  398.     {
  399.         _listErrors.add( new MVCMessage( strMessage ) );
  400.     }
  401.    
  402.     /**
  403.      * Add an error message. The error message must NOT be an I18n key.
  404.      *
  405.      * @param strMessage
  406.      *            The message
  407.      * @param  strFieldName the field name          
  408.      */
  409.     protected void addError( String strMessage, String strFieldName )
  410.     {
  411.         _listErrors.add( new MVCMessage( strMessage,strFieldName ) );
  412.     }

  413.     /**
  414.      * Add an error message. The error message must be an I18n key.
  415.      *
  416.      * @param strMessageKey
  417.      *            The message
  418.      * @param locale
  419.      *            The locale to display the message in
  420.      */
  421.     protected void addError( String strMessageKey, Locale locale )
  422.     {
  423.         _listErrors.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
  424.     }

  425.    
  426.     /**
  427.      * Add an warning message. The warning message must NOT be an I18n key.
  428.      *
  429.      * @param strMessage
  430.      *            The message
  431.      */
  432.     protected void addWarning( String strMessage )
  433.     {
  434.         _listWarnings.add( new MVCMessage( strMessage ) );
  435.     }
  436.    
  437.     /**
  438.      * Add an warning message. The warning message must NOT be an I18n key.
  439.      *
  440.      * @param strMessage
  441.      *            The message
  442.      *            
  443.      * @param  strFieldName the field name            
  444.      *            
  445.      */
  446.     protected void addWarning( String strMessage, String strFieldName  )
  447.     {
  448.         _listWarnings.add( new MVCMessage( strMessage,strFieldName ) );
  449.     }
  450.    


  451.     /**
  452.      * Add an warning message. The warning message must be an I18n key.
  453.      *
  454.      * @param strMessageKey
  455.      *            The message
  456.      * @param locale
  457.      *            The locale to display the message in
  458.      */
  459.     protected void addWarning( String strMessageKey, Locale locale )
  460.     {
  461.         _listWarnings.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
  462.     }

  463.     /**
  464.      * Add an info message. The info message must NOT be an I18n key.
  465.      *
  466.      * @param strMessage
  467.      *            The message
  468.      */
  469.     protected void addInfo( String strMessage )
  470.     {
  471.         _listInfos.add( new MVCMessage( strMessage ) );
  472.     }
  473.    
  474.     /**
  475.      * Add an info message. The info message must NOT be an I18n key.
  476.      *
  477.      * @param strMessage
  478.      *            The message
  479.      * @param  strFieldName the field name            
  480.      */
  481.     protected void addInfo( String strMessage, String strFieldName )
  482.     {
  483.         _listInfos.add( new MVCMessage( strMessage,strFieldName )  );
  484.     }

  485.     /**
  486.      * Add an info message. The info message must be an I18n key.
  487.      *
  488.      * @param strMessageKey
  489.      *            The message key
  490.      * @param locale
  491.      *            The locale to display the message in
  492.      */
  493.     protected void addInfo( String strMessageKey, Locale locale )
  494.     {
  495.         _listInfos.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
  496.     }

  497.     /**
  498.      * Fill the model with commons objects used in templates
  499.      *
  500.      * @param model
  501.      *            The model
  502.      */
  503.     protected void fillCommons( Map<String, Object> model )
  504.     {
  505.         List<ErrorMessage> listErrors = new ArrayList<>( _listErrors );
  506.         List<ErrorMessage> listInfos = new ArrayList<>( _listInfos );
  507.         List<ErrorMessage> listWarnings = new ArrayList<>( _listWarnings );
  508.         model.put( MARK_ERRORS, listErrors );
  509.         model.put( MARK_INFOS, listInfos );
  510.         model.put( MARK_WARNINGS, listWarnings );
  511.         _listErrors.clear( );
  512.         _listInfos.clear( );
  513.         _listWarnings.clear( );
  514.     }

  515.     // //////////////////////////////////////////////////////////////////////////
  516.     // Redirect utils

  517.     /**
  518.      * Redirect to requested page
  519.      *
  520.      * @param request
  521.      *            the http request
  522.      * @param strTarget
  523.      *            the targeted page
  524.      * @return the page requested
  525.      */
  526.     protected XPage redirect( HttpServletRequest request, String strTarget )
  527.     {
  528.         HttpServletResponse response = LocalVariables.getResponse( );

  529.         try
  530.         {
  531.             _logger.debug( "Redirect :{}", strTarget );
  532.             response.sendRedirect( strTarget );
  533.         }
  534.         catch( IOException e )
  535.         {
  536.             _logger.error( "Unable to redirect : {} : {}", strTarget, e.getMessage( ), e );
  537.         }
  538.         XPage xpage=new XPage();
  539.         xpage.setSendRedirect(true);
  540.         return xpage;
  541.     }

  542.     /**
  543.      * Redirect to an url defined by given parameters
  544.      *
  545.      * @param request
  546.      *            The HTTP request
  547.      * @param strView
  548.      *            The View name
  549.      * @param strParameter
  550.      *            The additional parameter
  551.      * @param nValue
  552.      *            The additional parameter's value
  553.      * @return The XPage redirected
  554.      */
  555.     protected XPage redirect( HttpServletRequest request, String strView, String strParameter, int nValue )
  556.     {
  557.         UrlItem url = new UrlItem( getViewUrl( strView ) );
  558.         url.addParameter( strParameter, nValue );

  559.         return redirect( request, url.getUrl( ) );
  560.     }

  561.     /**
  562.      * Redirect to an url defined by given parameters
  563.      *
  564.      * @param request
  565.      *            The HTTP request
  566.      * @param strView
  567.      *            The View name
  568.      * @param strParameter1
  569.      *            The first additional parameter
  570.      * @param nValue1
  571.      *            The first additional parameter's value
  572.      * @param strParameter2
  573.      *            The second additionnal parameter
  574.      * @param nValue2
  575.      *            The second additionnal parameter's value
  576.      * @return The XPage redirected
  577.      */
  578.     protected XPage redirect( HttpServletRequest request, String strView, String strParameter1, int nValue1, String strParameter2, int nValue2 )
  579.     {
  580.         UrlItem url = new UrlItem( getViewUrl( strView ) );
  581.         url.addParameter( strParameter1, nValue1 );
  582.         url.addParameter( strParameter2, nValue2 );

  583.         return redirect( request, url.getUrl( ) );
  584.     }

  585.     /**
  586.      * Redirect to an url defined by given parameters
  587.      *
  588.      * @param request
  589.      *            The HTTP request
  590.      * @param strView
  591.      *            The View name
  592.      * @param additionalParameters
  593.      *            A map containing parameters to add to the URL. Keys of the map are parameters name, and values are parameters values
  594.      * @return The XPage redirected
  595.      */
  596.     protected XPage redirect( HttpServletRequest request, String strView, Map<String, String> additionalParameters )
  597.     {
  598.         UrlItem url = new UrlItem( getViewUrl( strView ) );

  599.         if ( additionalParameters != null )
  600.         {
  601.             for ( Entry<String, String> entry : additionalParameters.entrySet( ) )
  602.             {
  603.                 url.addParameter( entry.getKey( ), entry.getValue( ) );
  604.             }
  605.         }

  606.         return redirect( request, url.getUrl( ) );
  607.     }

  608.     /**
  609.      * Redirect to requested view
  610.      *
  611.      * @param request
  612.      *            the http request
  613.      * @param strView
  614.      *            the targeted view
  615.      * @return the page requested
  616.      */
  617.     protected XPage redirectView( HttpServletRequest request, String strView )
  618.     {
  619.         return redirect( request, getViewUrl( strView ) );
  620.     }

  621.     /**
  622.      * Get a View URL
  623.      *
  624.      * @param strView
  625.      *            The view name
  626.      * @return The URL
  627.      */
  628.     protected String getViewUrl( String strView )
  629.     {
  630.         UrlItem url = new UrlItem( URL_PORTAL );
  631.         url.addParameter( MVCUtils.PARAMETER_PAGE, getXPageName( ) );
  632.         url.addParameter( MVCUtils.PARAMETER_VIEW, strView );

  633.         return url.getUrl( );
  634.     }

  635.     /**
  636.      * Gets the view URL with the JSP path
  637.      *
  638.      * @param strView
  639.      *            The view
  640.      * @return The URL
  641.      */
  642.     protected String getViewFullUrl( String strView )
  643.     {
  644.         return PATH_PORTAL + getViewUrl( strView );
  645.     }

  646.     /**
  647.      * Get Action URL
  648.      *
  649.      * @param strAction
  650.      *            The view name
  651.      * @return The URL
  652.      */
  653.     protected String getActionUrl( String strAction )
  654.     {
  655.         UrlItem url = new UrlItem( URL_PORTAL );
  656.         url.addParameter( MVCUtils.PARAMETER_PAGE, getXPageName( ) );
  657.         url.addParameter( MVCUtils.PARAMETER_ACTION, strAction );

  658.         return url.getUrl( );
  659.     }

  660.     /**
  661.      * Get Action URL
  662.      *
  663.      * @param strAction
  664.      *            The view name
  665.      * @return The URL
  666.      */
  667.     protected String getActionFullUrl( String strAction )
  668.     {
  669.         return PATH_PORTAL + getActionUrl( strAction );
  670.     }

  671.     /**
  672.      * Initiates a file download
  673.      *
  674.      * @param strData
  675.      *            Data of the file to download
  676.      * @param strFilename
  677.      *            Name of file
  678.      * @param strContentType
  679.      *            content type to set to the response
  680.      * @return The page requested
  681.      */
  682.     protected XPage download( String strData, String strFilename, String strContentType )
  683.     {
  684.         HttpServletResponse response = LocalVariables.getResponse( );
  685.         PrintWriter out = null;
  686.         response.setHeader( "Content-Disposition", "attachment; filename=\"" + strFilename + "\";" );
  687.         MVCUtils.addDownloadHeaderToResponse( response, strFilename, strContentType );

  688.         try
  689.         {
  690.             out = response.getWriter( );
  691.             out.print( strData );
  692.         }
  693.         catch( IOException e )
  694.         {
  695.             AppLogService.error( e.getStackTrace( ), e );
  696.         }
  697.         finally
  698.         {
  699.             if ( out != null )
  700.             {
  701.                 out.close( );
  702.             }
  703.         }

  704.         return new XPage( );
  705.     }

  706.     /**
  707.      * Initiates a download of a byte array
  708.      *
  709.      * @param data
  710.      *            Data to download
  711.      * @param strFilename
  712.      *            Name of the downloaded file
  713.      * @param strContentType
  714.      *            Content type to set to the response
  715.      * @return The page requested
  716.      */
  717.     protected XPage download( byte [ ] data, String strFilename, String strContentType )
  718.     {
  719.         HttpServletResponse response = LocalVariables.getResponse( );
  720.         OutputStream os;
  721.         MVCUtils.addDownloadHeaderToResponse( response, strFilename, strContentType );

  722.         try
  723.         {
  724.             os = response.getOutputStream( );
  725.             os.write( data );
  726.             os.close( );
  727.         }
  728.         catch( IOException e )
  729.         {
  730.             AppLogService.error( e.getStackTrace( ), e );
  731.         }

  732.         return new XPage( );
  733.     }

  734.     /**
  735.      * Return a response as JSON content
  736.      *
  737.      * @param strJSON
  738.      *            The JSON
  739.      * @return An unused XPage
  740.      */
  741.     protected XPage responseJSON( String strJSON )
  742.     {
  743.         HttpServletResponse response = LocalVariables.getResponse( );
  744.         response.setContentType( CONTENT_TYPE_JSON );

  745.         try
  746.         {
  747.             PrintWriter out = response.getWriter( );
  748.             out.print( strJSON );
  749.             out.flush( );
  750.             out.close( );
  751.         }
  752.         catch( IOException e )
  753.         {
  754.             AppLogService.error( e.getStackTrace( ), e );
  755.         }

  756.         return new XPage( );
  757.     }

  758.     /**
  759.      * Return a response as XML content
  760.      *
  761.      * @param strXML
  762.      *            The XML
  763.      * @return An unused XPage
  764.      */
  765.     protected XPage responseXML( String strXML )
  766.     {
  767.         HttpServletResponse response = LocalVariables.getResponse( );
  768.         response.setContentType( CONTENT_TYPE_XML );

  769.         try
  770.         {
  771.             PrintWriter out = response.getWriter( );
  772.             out.print( strXML );
  773.             out.flush( );
  774.             out.close( );
  775.         }
  776.         catch( IOException e )
  777.         {
  778.             AppLogService.error( e.getStackTrace( ), e );
  779.         }

  780.         return new XPage( );
  781.     }

  782.     // //////////////////////////////////////////////////////////////////////////
  783.     // MESSAGE BOX MANAGEMENT

  784.     /**
  785.      * Redirect to a Message Box page
  786.      *
  787.      * @param request
  788.      *            The HTTP request
  789.      * @param messageBox
  790.      *            The MessageBox infos
  791.      * @return A redirect XPage
  792.      */
  793.     protected XPage redirectMessageBox( HttpServletRequest request, MVCMessageBox messageBox )
  794.     {
  795.         _messageBox = messageBox;

  796.         return redirectView( request, VIEW_MESSAGEBOX );
  797.     }

  798.     /**
  799.      * Check if a message box is asked for
  800.      *
  801.      * @param request
  802.      *            The HTTP request
  803.      * @return If a message box is asked
  804.      */
  805.     private boolean isMessageBox( HttpServletRequest request )
  806.     {
  807.         String strView = request.getParameter( MVCUtils.PARAMETER_VIEW );

  808.         return ( ( strView != null ) && ( strView.equals( VIEW_MESSAGEBOX ) ) );
  809.     }

  810.     /**
  811.      * Default getLocale() implementation. Could be overriden
  812.      *
  813.      * @param request
  814.      *            The HTTP request
  815.      * @return The Locale
  816.      */
  817.     protected Locale getLocale( HttpServletRequest request )
  818.     {
  819.         return LocaleService.getContextUserLocale( request );
  820.     }

  821.     /**
  822.      * Display the Message BOX
  823.      *
  824.      * @param request
  825.      *            The HTTP request
  826.      * @return The message box
  827.      */
  828.     private XPage messageBox( HttpServletRequest request )
  829.     {
  830.         _messageBox.localize( getLocale( request ) );

  831.         Map<String, Object> model = getModel( );
  832.         model.put( MARK_MESSAGE_BOX, _messageBox );

  833.         return getXPage( _messageBox.getTemplate( ), getLocale( request ), model );
  834.     }

  835.     /**
  836.      * get the registred User
  837.      *
  838.      * @param request
  839.      * @return the lutece user if registred, null otherwise
  840.      */
  841.     protected LuteceUser getRegistredUser( HttpServletRequest request )
  842.     {
  843.         // get authenticated user if authentication is enable
  844.         if ( SecurityService.isAuthenticationEnable( ) )
  845.         {
  846.             LuteceUser luteceUser = SecurityService.getInstance( ).getRegisteredUser( request );
  847.             if ( luteceUser != null )
  848.             {
  849.                 return luteceUser;
  850.             }
  851.         }

  852.         return null;
  853.     }
  854. }