1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.portal.util.mvc.xpage;
35
36 import fr.paris.lutece.portal.service.i18n.I18nService;
37 import fr.paris.lutece.portal.service.message.SiteMessageException;
38 import fr.paris.lutece.portal.service.plugin.Plugin;
39 import fr.paris.lutece.portal.service.security.UserNotSignedException;
40 import fr.paris.lutece.portal.service.template.AppTemplateService;
41 import fr.paris.lutece.portal.service.util.AppException;
42 import fr.paris.lutece.portal.service.util.AppLogService;
43 import fr.paris.lutece.portal.service.util.AppPropertiesService;
44 import fr.paris.lutece.portal.util.mvc.utils.MVCMessage;
45 import fr.paris.lutece.portal.util.mvc.utils.MVCMessageBox;
46 import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
47 import fr.paris.lutece.portal.util.mvc.xpage.annotations.Controller;
48 import fr.paris.lutece.portal.web.LocalVariables;
49 import fr.paris.lutece.portal.web.xpages.XPage;
50 import fr.paris.lutece.portal.web.xpages.XPageApplication;
51 import fr.paris.lutece.util.ErrorMessage;
52 import fr.paris.lutece.util.bean.BeanUtil;
53 import fr.paris.lutece.util.beanvalidation.BeanValidationUtil;
54 import fr.paris.lutece.util.html.HtmlTemplate;
55 import fr.paris.lutece.util.url.UrlItem;
56
57 import java.io.IOException;
58 import java.io.OutputStream;
59 import java.io.PrintWriter;
60 import java.lang.reflect.InvocationTargetException;
61 import java.lang.reflect.Method;
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 import java.util.Set;
69
70 import javax.servlet.http.HttpServletRequest;
71 import javax.servlet.http.HttpServletResponse;
72 import javax.validation.ConstraintViolation;
73
74 import org.apache.log4j.Logger;
75 import org.springframework.util.ReflectionUtils;
76
77
78
79
80
81 public abstract class MVCApplication implements XPageApplication
82 {
83 private static final String MARK_ERRORS = "errors";
84 private static final String MARK_INFOS = "infos";
85 private static final String MARK_MESSAGE_BOX = "messageBox";
86 private static final String URL_PORTAL = "Portal.jsp";
87 private static final String PATH_PORTAL = "jsp/site/";
88 private static final String VIEW_MESSAGEBOX = "messageBox";
89 private static Logger _logger = MVCUtils.getLogger( );
90 private List<ErrorMessage> _listErrors = new ArrayList<ErrorMessage>( );
91 private List<ErrorMessage> _listInfos = new ArrayList<ErrorMessage>( );
92 private MVCMessageBox _messageBox;
93 private Controller _controller = getClass( ).getAnnotation( Controller.class );
94
95
96
97
98
99
100
101
102
103
104
105
106 @Override
107 public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin )
108 throws SiteMessageException, UserNotSignedException
109 {
110 return processController( request );
111 }
112
113
114
115
116
117
118
119
120
121
122
123 private XPage processController( HttpServletRequest request )
124 throws UserNotSignedException, SiteMessageException
125 {
126 Method[] methods = ReflectionUtils.getAllDeclaredMethods( getClass( ) );
127
128 try
129 {
130 if ( isMessageBox( request ) )
131 {
132 return messageBox( request );
133 }
134
135
136 Method m = MVCUtils.findViewAnnotedMethod( request, methods );
137
138 if ( m != null )
139 {
140 return (XPage) m.invoke( this, request );
141 }
142
143
144 m = MVCUtils.findActionAnnotedMethod( request, methods );
145
146 if ( m != null )
147 {
148 return (XPage) m.invoke( this, request );
149 }
150
151
152 m = MVCUtils.findDefaultViewMethod( methods );
153
154 return (XPage) m.invoke( this, request );
155 }
156 catch ( InvocationTargetException e )
157 {
158 if ( e.getTargetException( ) instanceof UserNotSignedException )
159 {
160 throw (UserNotSignedException) e.getTargetException( );
161 }
162
163 if ( e.getTargetException( ) instanceof SiteMessageException )
164 {
165 throw (SiteMessageException) e.getTargetException( );
166 }
167
168 throw new AppException( "MVC Error dispaching view and action ", e );
169 }
170 catch ( IllegalAccessException e )
171 {
172 throw new AppException( "MVC Error dispaching view and action ", e );
173 }
174 }
175
176
177
178
179
180 protected String getXPageName( )
181 {
182 return _controller.xpageName( );
183 }
184
185
186
187
188
189
190 protected String getDefaultPageTitle( Locale locale )
191 {
192 if ( !_controller.pageTitleProperty( ).equals( "" ) )
193 {
194 return AppPropertiesService.getProperty( _controller.pageTitleProperty( ) );
195 }
196 else if ( !_controller.pageTitleI18nKey( ).equals( "" ) )
197 {
198 return I18nService.getLocalizedString( _controller.pageTitleI18nKey( ), locale );
199 }
200
201 return _controller.xpageName( );
202 }
203
204
205
206
207
208
209 protected String getDefaultPagePath( Locale locale )
210 {
211 if ( !_controller.pagePathProperty( ).equals( "" ) )
212 {
213 return AppPropertiesService.getProperty( _controller.pagePathProperty( ) );
214 }
215 else if ( !_controller.pagePathI18nKey( ).equals( "" ) )
216 {
217 return I18nService.getLocalizedString( _controller.pagePathI18nKey( ), locale );
218 }
219
220 return _controller.xpageName( );
221 }
222
223
224
225
226
227
228
229
230 protected XPage getXPage( )
231 {
232 XPage page = new XPage( );
233
234 page.setTitle( getDefaultPageTitle( Locale.getDefault( ) ) );
235 page.setPathLabel( getDefaultPagePath( Locale.getDefault( ) ) );
236
237 return page;
238 }
239
240
241
242
243
244
245
246 protected XPage getXPage( String strTemplate )
247 {
248 XPage page = getXPage( );
249
250 HtmlTemplate t = AppTemplateService.getTemplate( strTemplate );
251 page.setContent( t.getHtml( ) );
252
253 return page;
254 }
255
256
257
258
259
260
261
262
263 protected XPage getXPage( String strTemplate, Locale locale )
264 {
265 return getXPage( strTemplate, locale, getModel( ) );
266 }
267
268
269
270
271
272
273
274
275
276
277 protected XPage getXPage( String strTemplate, Locale locale, Map<String, Object> model )
278 {
279 XPage page = getXPage( );
280
281 HtmlTemplate t = AppTemplateService.getTemplate( strTemplate, locale, model );
282 page.setContent( t.getHtml( ) );
283 page.setTitle( getDefaultPageTitle( locale ) );
284 page.setPathLabel( getDefaultPagePath( locale ) );
285
286 return page;
287 }
288
289
290
291
292
293 protected Map<String, Object> getModel( )
294 {
295 Map<String, Object> model = new HashMap<String, Object>( );
296 fillCommons( model );
297
298 return model;
299 }
300
301
302
303
304
305
306
307
308
309 protected void populate( Object bean, HttpServletRequest request )
310 {
311 BeanUtil.populate( bean, request );
312 }
313
314
315
316
317
318
319
320
321
322
323
324 protected <T> boolean validateBean( T bean )
325 {
326 Set<ConstraintViolation<T>> errors = BeanValidationUtil.validate( bean );
327
328 if ( errors.isEmpty( ) )
329 {
330 return true;
331 }
332
333 for ( ConstraintViolation<T> constraint : errors )
334 {
335 MVCMessage error = new MVCMessage( );
336 error.setMessage( constraint.getMessage( ) );
337 _listErrors.add( error );
338 }
339
340 return false;
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354 protected <T> boolean validateBean( T bean, Locale locale )
355 {
356 Set<ConstraintViolation<T>> errors = BeanValidationUtil.validate( bean );
357
358 if ( errors.isEmpty( ) )
359 {
360 return true;
361 }
362
363 for ( ConstraintViolation<T> constraint : errors )
364 {
365 MVCMessage error = new MVCMessage( );
366 error.setMessage( I18nService.getLocalizedString( constraint.getMessage( ), locale ) );
367 _listErrors.add( error );
368 }
369
370 return false;
371 }
372
373
374
375
376
377 protected void addError( String strMessage )
378 {
379 _listErrors.add( new MVCMessage( strMessage ) );
380 }
381
382
383
384
385
386
387 protected void addError( String strMessageKey, Locale locale )
388 {
389 _listErrors.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
390 }
391
392
393
394
395
396 protected void addInfo( String strMessage )
397 {
398 _listInfos.add( new MVCMessage( strMessage ) );
399 }
400
401
402
403
404
405
406 protected void addInfo( String strMessageKey, Locale locale )
407 {
408 _listInfos.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
409 }
410
411
412
413
414
415 protected void fillCommons( Map<String, Object> model )
416 {
417 List<ErrorMessage> listErrors = new ArrayList<ErrorMessage>( _listErrors );
418 List<ErrorMessage> listInfos = new ArrayList<ErrorMessage>( _listInfos );
419 model.put( MARK_ERRORS, listErrors );
420 model.put( MARK_INFOS, listInfos );
421 _listErrors.clear( );
422 _listInfos.clear( );
423 }
424
425
426
427
428
429
430
431
432
433
434
435 protected XPage redirect( HttpServletRequest request, String strTarget )
436 {
437 HttpServletResponse response = LocalVariables.getResponse( );
438
439 try
440 {
441 _logger.debug( "Redirect :" + strTarget );
442 response.sendRedirect( strTarget );
443 }
444 catch ( IOException e )
445 {
446 _logger.error( "Unable to redirect : " + strTarget + " : " + e.getMessage( ), e );
447 }
448
449 return new XPage( );
450 }
451
452
453
454
455
456
457
458
459
460 protected XPage redirect( HttpServletRequest request, String strView, String strParameter, int nValue )
461 {
462 UrlItem url = new UrlItem( getViewUrl( strView ) );
463 url.addParameter( strParameter, nValue );
464
465 return redirect( request, url.getUrl( ) );
466 }
467
468
469
470
471
472
473
474
475
476
477
478 protected XPage redirect( HttpServletRequest request, String strView, String strParameter1, int nValue1,
479 String strParameter2, int nValue2 )
480 {
481 UrlItem url = new UrlItem( getViewUrl( strView ) );
482 url.addParameter( strParameter1, nValue1 );
483 url.addParameter( strParameter2, nValue2 );
484
485 return redirect( request, url.getUrl( ) );
486 }
487
488
489
490
491
492
493
494
495
496
497 protected XPage redirect( HttpServletRequest request, String strView, Map<String, String> additionalParameters )
498 {
499 UrlItem url = new UrlItem( getViewUrl( strView ) );
500
501 if ( additionalParameters != null )
502 {
503 for ( Entry<String, String> entry : additionalParameters.entrySet( ) )
504 {
505 url.addParameter( entry.getKey( ), entry.getValue( ) );
506 }
507 }
508 return redirect( request, url.getUrl( ) );
509 }
510
511
512
513
514
515
516
517
518 protected XPage redirectView( HttpServletRequest request, String strView )
519 {
520 return redirect( request, getViewUrl( strView ) );
521 }
522
523
524
525
526
527
528 protected String getViewUrl( String strView )
529 {
530 UrlItem url = new UrlItem( URL_PORTAL );
531 url.addParameter( MVCUtils.PARAMETER_PAGE, getXPageName( ) );
532 url.addParameter( MVCUtils.PARAMETER_VIEW, strView );
533
534 return url.getUrl( );
535 }
536
537
538
539
540
541
542 protected String getViewFullUrl( String strView )
543 {
544 return PATH_PORTAL + getViewUrl( strView );
545 }
546
547
548
549
550
551
552 protected String getActionUrl( String strAction )
553 {
554 UrlItem url = new UrlItem( URL_PORTAL );
555 url.addParameter( MVCUtils.PARAMETER_PAGE, getXPageName( ) );
556 url.addParameter( MVCUtils.PARAMETER_ACTION, strAction );
557
558 return url.getUrl( );
559 }
560
561
562
563
564
565
566 protected String getActionFullUrl( String strAction )
567 {
568 return PATH_PORTAL + getActionUrl( strAction );
569 }
570
571
572
573
574
575
576
577
578 protected XPage download( String strData, String strFilename, String strContentType )
579 {
580 HttpServletResponse response = LocalVariables.getResponse( );
581 PrintWriter out = null;
582 response.setHeader( "Content-Disposition", "attachment; filename=\"" + strFilename + "\";" );
583 addDownloadHeaderToResponse( response, strFilename, strContentType );
584
585 try
586 {
587 out = response.getWriter( );
588 out.print( strData );
589 }
590 catch ( IOException e )
591 {
592 AppLogService.error( e.getStackTrace( ), e );
593 }
594 finally
595 {
596 if ( out != null )
597 {
598 out.close( );
599 }
600 }
601
602 return new XPage( );
603 }
604
605
606
607
608
609
610
611
612 protected XPage download( byte[] data, String strFilename, String strContentType )
613 {
614 HttpServletResponse response = LocalVariables.getResponse( );
615 OutputStream os;
616 addDownloadHeaderToResponse( response, strFilename, strContentType );
617
618 try
619 {
620 os = response.getOutputStream( );
621 os.write( data );
622 os.close( );
623 }
624 catch ( IOException e )
625 {
626 AppLogService.error( e.getStackTrace( ), e );
627 }
628
629 return new XPage( );
630 }
631
632
633
634
635
636
637
638 private void addDownloadHeaderToResponse( HttpServletResponse response, String strFilename, String strContentType )
639 {
640 response.setHeader( "Content-Disposition", "attachment; filename=\"" + strFilename + "\";" );
641 response.setHeader( "Content-type", strContentType );
642 response.addHeader( "Content-Encoding", "UTF-8" );
643 response.addHeader( "Pragma", "public" );
644 response.addHeader( "Expires", "0" );
645 response.addHeader( "Cache-Control", "must-revalidate,post-check=0,pre-check=0" );
646 }
647
648
649
650
651
652
653
654
655
656
657 protected XPage redirectMessageBox( HttpServletRequest request, MVCMessageBox messageBox )
658 {
659 _messageBox = messageBox;
660
661 return redirectView( request, VIEW_MESSAGEBOX );
662 }
663
664
665
666
667
668
669 private boolean isMessageBox( HttpServletRequest request )
670 {
671 String strView = request.getParameter( MVCUtils.PARAMETER_VIEW );
672
673 return ( ( strView != null ) && ( strView.equals( VIEW_MESSAGEBOX ) ) );
674 }
675
676
677
678
679
680
681 protected Locale getLocale( HttpServletRequest request )
682 {
683 return request.getLocale( );
684 }
685
686
687
688
689
690
691 private XPage messageBox( HttpServletRequest request )
692 {
693 _messageBox.localize( getLocale( request ) );
694
695 Map<String, Object> model = getModel( );
696 model.put( MARK_MESSAGE_BOX, _messageBox );
697
698 return getXPage( _messageBox.getTemplate( ), getLocale( request ), model );
699 }
700 }