View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de 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.admin;
35  
36  import fr.paris.lutece.portal.service.admin.AccessDeniedException;
37  import fr.paris.lutece.portal.service.i18n.I18nService;
38  import fr.paris.lutece.portal.service.template.AppTemplateService;
39  import fr.paris.lutece.portal.service.util.AppException;
40  import fr.paris.lutece.portal.service.util.AppLogService;
41  import fr.paris.lutece.portal.util.mvc.admin.annotations.Controller;
42  import fr.paris.lutece.portal.util.mvc.utils.MVCMessage;
43  import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
44  import fr.paris.lutece.portal.web.admin.PluginAdminPageJspBean;
45  import fr.paris.lutece.util.ErrorMessage;
46  import fr.paris.lutece.util.beanvalidation.ValidationError;
47  import fr.paris.lutece.util.html.HtmlTemplate;
48  import fr.paris.lutece.util.url.UrlItem;
49  
50  import org.apache.log4j.Logger;
51  
52  import org.springframework.util.ReflectionUtils;
53  
54  import java.io.IOException;
55  import java.io.OutputStream;
56  import java.io.PrintWriter;
57  import java.io.Serializable;
58  
59  import java.lang.reflect.InvocationTargetException;
60  import java.lang.reflect.Method;
61  
62  import java.util.ArrayList;
63  import java.util.HashMap;
64  import java.util.List;
65  import java.util.Locale;
66  import java.util.Map;
67  import java.util.Map.Entry;
68  
69  import javax.servlet.http.HttpServletRequest;
70  import javax.servlet.http.HttpServletResponse;
71  
72  
73  /**
74   * MVC Admin JspBean implementation let use MVC model to develop admin feature.
75   */
76  public abstract class MVCAdminJspBean extends PluginAdminPageJspBean implements Serializable
77  {
78      private static final String MARK_ERRORS = "errors";
79      private static final String MARK_INFOS = "infos";
80      private static Logger _logger = MVCUtils.getLogger(  );
81      private List<ErrorMessage> _listErrors = new ArrayList<ErrorMessage>(  );
82      private List<ErrorMessage> _listInfos = new ArrayList<ErrorMessage>(  );
83      private Controller _controller = getClass(  ).getAnnotation( Controller.class );
84      private HttpServletResponse _response;
85  
86      /**
87       * Process request as a controller
88       * @param request The HTTP request
89       * @param response The HTTP response
90       * @return The page content
91       * @throws AccessDeniedException If the user's has no right
92       */
93      public String processController( HttpServletRequest request, HttpServletResponse response )
94          throws AccessDeniedException
95      {
96          _response = response;
97          init( request, _controller.right(  ) );
98  
99          Method[] methods = ReflectionUtils.getAllDeclaredMethods( getClass(  ) );
100 
101         try
102         {
103             // Process views
104             Method m = MVCUtils.findViewAnnotedMethod( request, methods );
105 
106             if ( m != null )
107             {
108                 return (String) m.invoke( this, request );
109             }
110 
111             // Process actions
112             m = MVCUtils.findActionAnnotedMethod( request, methods );
113 
114             if ( m != null )
115             {
116                 return (String) m.invoke( this, request );
117             }
118 
119             // No view or action found so display the default view
120             m = MVCUtils.findDefaultViewMethod( methods );
121 
122             return (String) m.invoke( this, request );
123         }
124         catch ( InvocationTargetException e )
125         {
126             if ( e.getTargetException(  ) instanceof AccessDeniedException )
127             {
128                 throw (AccessDeniedException) e.getTargetException(  );
129             }
130 
131             throw new AppException( "MVC Error dispaching view and action ", e );
132         }
133         catch ( IllegalAccessException e )
134         {
135             throw new AppException( "MVC Error dispaching view and action ", e );
136         }
137     }
138 
139     ////////////////////////////////////////////////////////////////////////////
140     // Page utils 
141 
142     /**
143      * Add an error message
144      * @param strMessage The message
145      */
146     protected void addError( String strMessage )
147     {
148         _listErrors.add( new MVCMessage( strMessage ) );
149     }
150 
151     /**
152      * Add an error message
153      * @param strMessageKey The message
154      * @param locale The locale
155      */
156     protected void addError( String strMessageKey, Locale locale )
157     {
158         _listErrors.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
159     }
160 
161     /**
162      * Add an info message
163      * @param strMessage The message
164      */
165     protected void addInfo( String strMessage )
166     {
167         _listInfos.add( new MVCMessage( strMessage ) );
168     }
169 
170     /**
171      * Add an info message
172      * @param strMessageKey The message key
173      * @param locale The locale
174      */
175     protected void addInfo( String strMessageKey, Locale locale )
176     {
177         _listInfos.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
178     }
179 
180     /**
181     * Fill the model with commons objects used in templates
182     * @param model The model
183     */
184     protected void fillCommons( Map<String, Object> model )
185     {
186         List<ErrorMessage> listErrors = new ArrayList<ErrorMessage>( _listErrors );
187         List<ErrorMessage> listInfos = new ArrayList<ErrorMessage>( _listInfos );
188         model.put( MARK_ERRORS, listErrors );
189         model.put( MARK_INFOS, listInfos );
190         _listErrors.clear(  );
191         _listInfos.clear(  );
192     }
193 
194     /**
195      * Get a model Object filled with default values
196      * @return The model
197      */
198     protected Map<String, Object> getModel(  )
199     {
200         Map<String, Object> model = new HashMap<String, Object>(  );
201         fillCommons( model );
202 
203         return model;
204     }
205 
206     /**
207      * Return the page content
208      * @param strTemplate The template
209      * @return The page
210      */
211     protected String getPage( String strTemplate )
212     {
213         String strPageTitleProperty = _controller.pageTitleProperty(  );
214 
215         return getPage( strPageTitleProperty, strTemplate, getModel(  ) );
216     }
217 
218     /**
219      * Return the page content
220      * @param strPageTitleProperty The page title property
221      * @param strTemplate The template
222      * @return The page
223      */
224     protected String getPage( String strPageTitleProperty, String strTemplate )
225     {
226         return getPage( strPageTitleProperty, strTemplate, getModel(  ) );
227     }
228 
229     /**
230      * Return the page content
231      * @param strPageTitleProperty The page title property
232      * @param strTemplate The template
233      * @param model The model
234      * @return The page
235      */
236     protected String getPage( String strPageTitleProperty, String strTemplate, Map<String, Object> model )
237     {
238         setPageTitleProperty( strPageTitleProperty );
239 
240         HtmlTemplate template = AppTemplateService.getTemplate( strTemplate, getLocale(  ), model );
241 
242         return getAdminPage( template.getHtml(  ) );
243     }
244 
245     /**
246      * Validate a bean
247      * @param <T> The bean class
248      * @param bean The bean
249      * @param strPrefix The prefix
250      * @return true if validated otherwise false
251      */
252     protected <T> boolean validateBean( T bean, String strPrefix )
253     {
254         List<ValidationError> errors = validate( bean, strPrefix );
255 
256         if ( errors.isEmpty(  ) )
257         {
258             return true;
259         }
260 
261         for ( ValidationError errorValidation : errors )
262         {
263             MVCMessage error = new MVCMessage(  );
264             error.setMessage( errorValidation.getMessage(  ) );
265             _listErrors.add( error );
266         }
267 
268         return false;
269     }
270 
271     ////////////////////////////////////////////////////////////////////////////
272     // Redirect utils
273 
274     /**
275      * Return the JSP name used as controller
276      * @return The JSP name
277      */
278     protected String getControllerJsp(  )
279     {
280         return _controller.controllerJsp(  );
281     }
282 
283     /**
284      * Return the path of the JSP used as controller
285      * @return The controller path
286      */
287     protected String getControllerPath(  )
288     {
289         return _controller.controllerPath(  );
290     }
291 
292     /**
293      * Redirect to requested page
294      *
295      * @param request the http request
296      * @param strTarget the targeted page
297      * @return null. The page should be redirected
298      */
299     protected String redirect( HttpServletRequest request, String strTarget )
300     {
301         try
302         {
303             _logger.debug( "Redirect :" + strTarget );
304             _response.sendRedirect( strTarget );
305         }
306         catch ( IOException e )
307         {
308             _logger.error( "Unable to redirect : " + strTarget + " : " + e.getMessage(  ), e );
309         }
310 
311         return null;
312     }
313 
314     /**
315      * Redirect to an url defined by given parameters
316      * @param request The HTTP request
317      * @param strView The View name
318      * @param strParameter The additional parameter
319      * @param nValue The additional parameter's value
320      * @return The redirection result
321      */
322     protected String redirect( HttpServletRequest request, String strView, String strParameter, int nValue )
323     {
324         UrlItem url = new UrlItem( getViewUrl( strView ) );
325         url.addParameter( strParameter, nValue );
326 
327         return redirect( request, url.getUrl(  ) );
328     }
329 
330     /**
331      * Redirect to an url defined by given parameters
332      * @param request The HTTP request
333      * @param strView The View name
334      * @param strParameter1 The first additional parameter
335      * @param nValue1 The first additional parameter's value
336      * @param strParameter2 The second additionnal parameter
337      * @param nValue2 The second additionnal parameter's value
338      * @return The redirection result
339      */
340     protected String redirect( HttpServletRequest request, String strView, String strParameter1, int nValue1,
341         String strParameter2, int nValue2 )
342     {
343         UrlItem url = new UrlItem( getViewUrl( strView ) );
344         url.addParameter( strParameter1, nValue1 );
345         url.addParameter( strParameter2, nValue2 );
346 
347         return redirect( request, url.getUrl(  ) );
348     }
349 
350     /**
351      * Redirect to an url defined by given parameters
352      * @param request The HTTP request
353      * @param strView The View name
354      * @param additionalParameters A map containing parameters to add to the
355      *            URL. Keys of the map are parameters name, and values are
356      *            parameters values
357      * @return The XPage redirected
358      */
359     protected String redirect( HttpServletRequest request, String strView, Map<String, String> additionalParameters )
360     {
361         UrlItem url = new UrlItem( getViewUrl( strView ) );
362 
363         if ( additionalParameters != null )
364         {
365             for ( Entry<String, String> entry : additionalParameters.entrySet(  ) )
366             {
367                 url.addParameter( entry.getKey(  ), entry.getValue(  ) );
368             }
369         }
370 
371         return redirect( request, url.getUrl(  ) );
372     }
373 
374     /**
375      * Redirect to requested view
376      *
377      * @param request the http request
378      * @param strView the targeted view
379      * @return The redirection result
380      */
381     protected String redirectView( HttpServletRequest request, String strView )
382     {
383         return redirect( request, getViewUrl( strView ) );
384     }
385 
386     /**
387      * Get a View URL
388      * @param strView The view name
389      * @return The URL
390      */
391     protected String getViewUrl( String strView )
392     {
393         UrlItem url = new UrlItem( getControllerJsp(  ) );
394         url.addParameter( MVCUtils.PARAMETER_VIEW, strView );
395 
396         return url.getUrl(  );
397     }
398 
399     /**
400      * Gets the view URL with the JSP path
401      * @param strView The view
402      * @return The URL
403      */
404     protected String getViewFullUrl( String strView )
405     {
406         return getControllerPath(  ) + getViewUrl( strView );
407     }
408 
409     /**
410      * Get Action URL
411      * @param strAction The view name
412      * @return The URL
413      */
414     protected String getActionUrl( String strAction )
415     {
416         UrlItem url = new UrlItem( getControllerPath(  ) + getControllerJsp(  ) );
417         url.addParameter( MVCUtils.PARAMETER_ACTION, strAction );
418 
419         return url.getUrl(  );
420     }
421 
422     /**
423      * Initiates a file download
424      * @param strData Data of the file to download
425      * @param strFilename Name of file
426      * @param strContentType content type to set to the response
427      */
428     protected void download( String strData, String strFilename, String strContentType )
429     {
430         HttpServletResponse response = _response;
431         PrintWriter out = null;
432         response.setHeader( "Content-Disposition", "attachment; filename=\"" + strFilename + "\";" );
433         MVCUtils.addDownloadHeaderToResponse( response, strFilename, strContentType );
434 
435         try
436         {
437             out = response.getWriter(  );
438             out.print( strData );
439         }
440         catch ( IOException e )
441         {
442             AppLogService.error( e.getStackTrace(  ), e );
443         }
444         finally
445         {
446             if ( out != null )
447             {
448                 out.close(  );
449             }
450         }
451     }
452 
453     /**
454      * Initiates a download of a byte array
455      * @param data Data to download
456      * @param strFilename Name of the downloaded file
457      * @param strContentType Content type to set to the response
458      */
459     protected void download( byte[] data, String strFilename, String strContentType )
460     {
461         HttpServletResponse response = _response;
462         OutputStream os;
463         MVCUtils.addDownloadHeaderToResponse( response, strFilename, strContentType );
464 
465         try
466         {
467             os = response.getOutputStream(  );
468             os.write( data );
469             os.close(  );
470         }
471         catch ( IOException e )
472         {
473             AppLogService.error( e.getStackTrace(  ), e );
474         }
475     }
476 }