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.security.AccessLogService;
37 import java.io.IOException;
38 import java.io.OutputStream;
39 import java.io.PrintWriter;
40 import java.lang.reflect.InvocationTargetException;
41 import java.lang.reflect.Method;
42 import java.util.ArrayList;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Locale;
46 import java.util.Map;
47 import java.util.Map.Entry;
48 import java.util.Set;
49
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52 import javax.validation.ConstraintViolation;
53
54 import org.apache.logging.log4j.Logger;
55 import org.springframework.util.ReflectionUtils;
56
57 import fr.paris.lutece.portal.service.i18n.I18nService;
58 import fr.paris.lutece.portal.service.message.SiteMessageException;
59 import fr.paris.lutece.portal.service.plugin.Plugin;
60 import fr.paris.lutece.portal.service.security.AccessLoggerConstants;
61 import fr.paris.lutece.portal.service.security.LuteceUser;
62 import fr.paris.lutece.portal.service.security.SecurityService;
63 import fr.paris.lutece.portal.service.security.UserNotSignedException;
64 import fr.paris.lutece.portal.service.template.AppTemplateService;
65 import fr.paris.lutece.portal.service.util.AppException;
66 import fr.paris.lutece.portal.service.util.AppLogService;
67 import fr.paris.lutece.portal.service.util.AppPropertiesService;
68 import fr.paris.lutece.portal.util.mvc.utils.MVCMessage;
69 import fr.paris.lutece.portal.util.mvc.utils.MVCMessageBox;
70 import fr.paris.lutece.portal.util.mvc.utils.MVCUtils;
71 import fr.paris.lutece.portal.util.mvc.xpage.annotations.Controller;
72 import fr.paris.lutece.portal.web.LocalVariables;
73 import fr.paris.lutece.portal.web.l10n.LocaleService;
74 import fr.paris.lutece.portal.web.xpages.XPage;
75 import fr.paris.lutece.portal.web.xpages.XPageApplication;
76 import fr.paris.lutece.util.ErrorMessage;
77 import fr.paris.lutece.util.bean.BeanUtil;
78 import fr.paris.lutece.util.beanvalidation.BeanValidationUtil;
79 import fr.paris.lutece.util.html.HtmlTemplate;
80 import fr.paris.lutece.util.url.UrlItem;
81
82
83
84
85 public abstract class MVCApplication implements XPageApplication
86 {
87 private static final long serialVersionUID = 6093635383465830355L;
88
89
90 private static final String MARK_ERRORS = "errors";
91 private static final String MARK_INFOS = "infos";
92 private static final String MARK_WARNINGS = "warnings";
93 private static final String MARK_MESSAGE_BOX = "messageBox";
94
95
96 private static final String URL_PORTAL = "Portal.jsp";
97 private static final String PATH_PORTAL = "jsp/site/";
98 private static final String VIEW_MESSAGEBOX = "messageBox";
99 private static final String CONTENT_TYPE_JSON = "application/json";
100 private static final String CONTENT_TYPE_XML = "application/xml";
101
102
103 private static Logger _logger = MVCUtils.getLogger( );
104 private List<ErrorMessage> _listErrors = new ArrayList<>( );
105 private List<ErrorMessage> _listInfos = new ArrayList<>( );
106 private List<ErrorMessage> _listWarnings = new ArrayList<>( );
107 private MVCMessageBox _messageBox;
108 private Controller _controller = getClass( ).getAnnotation( Controller.class );
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 @Override
126 public XPage getPage( HttpServletRequest request, int nMode, Plugin plugin ) throws SiteMessageException, UserNotSignedException
127 {
128 return processController( request );
129 }
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 private XPage processController( HttpServletRequest request ) throws UserNotSignedException, SiteMessageException
146 {
147 Method [ ] methods = ReflectionUtils.getAllDeclaredMethods( getClass( ) );
148
149 try
150 {
151 if ( isMessageBox( request ) )
152 {
153 return messageBox( request );
154 }
155
156 LuteceUser registredUser = getRegistredUser( request );
157
158
159 Method m = MVCUtils.findViewAnnotedMethod( request, methods );
160
161 if ( m != null )
162 {
163 AccessLogService.getInstance( ).trace( AccessLoggerConstants.EVENT_TYPE_READ, m.getName( ), registredUser,
164 request.getRequestURL( ) + "?" + request.getQueryString( ), AccessLogService.ACCESS_LOG_FO );
165 return (XPage) m.invoke( this, request );
166 }
167
168
169 m = MVCUtils.findActionAnnotedMethod( request, methods );
170
171 if ( m != null )
172 {
173 AccessLogService.getInstance( ).debug( AccessLoggerConstants.EVENT_TYPE_ACTION, m.getName( ), registredUser,
174 request.getRequestURL( ) + "?" + request.getQueryString( ), AccessLogService.ACCESS_LOG_FO );
175 return (XPage) m.invoke( this, request );
176 }
177
178
179 m = MVCUtils.findDefaultViewMethod( methods );
180
181 AccessLogService.getInstance( ).trace( AccessLoggerConstants.EVENT_TYPE_ACTION, m.getName( ), registredUser,
182 request.getRequestURL( ) + "?" + request.getQueryString( ), AccessLogService.ACCESS_LOG_FO );
183 return (XPage) m.invoke( this, request );
184 }
185 catch( InvocationTargetException e )
186 {
187 if ( e.getTargetException( ) instanceof UserNotSignedException )
188 {
189 throw (UserNotSignedException) e.getTargetException( );
190 }
191
192 if ( e.getTargetException( ) instanceof SiteMessageException )
193 {
194 throw (SiteMessageException) e.getTargetException( );
195 }
196
197 if ( e.getTargetException( ) instanceof RuntimeException )
198 {
199 throw new AppException( "MVC Error dispaching view and action ", (RuntimeException) e.getTargetException( ) );
200 }
201
202 throw new AppException( "MVC Error dispaching view and action ", e );
203 }
204 catch( IllegalAccessException e )
205 {
206 throw new AppException( "MVC Error dispaching view and action ", e );
207 }
208 }
209
210
211
212
213
214
215 protected String getXPageName( )
216 {
217 return _controller.xpageName( );
218 }
219
220
221
222
223
224
225
226
227 protected String getDefaultPageTitle( Locale locale )
228 {
229 if ( !_controller.pageTitleProperty( ).equals( "" ) )
230 {
231 return AppPropertiesService.getProperty( _controller.pageTitleProperty( ) );
232 }
233 else
234 if ( !_controller.pageTitleI18nKey( ).equals( "" ) )
235 {
236 return I18nService.getLocalizedString( _controller.pageTitleI18nKey( ), locale );
237 }
238
239 return _controller.xpageName( );
240 }
241
242
243
244
245
246
247
248
249 protected String getDefaultPagePath( Locale locale )
250 {
251 if ( !_controller.pagePathProperty( ).equals( "" ) )
252 {
253 return AppPropertiesService.getProperty( _controller.pagePathProperty( ) );
254 }
255 else
256 if ( !_controller.pagePathI18nKey( ).equals( "" ) )
257 {
258 return I18nService.getLocalizedString( _controller.pagePathI18nKey( ), locale );
259 }
260
261 return _controller.xpageName( );
262 }
263
264
265
266
267
268
269
270
271
272 protected XPage getXPage( )
273 {
274 XPageportal/web/xpages/XPage.html#XPage">XPage page = new XPage( );
275
276 page.setTitle( getDefaultPageTitle( LocaleService.getDefault( ) ) );
277 page.setPathLabel( getDefaultPagePath( LocaleService.getDefault( ) ) );
278
279 return page;
280 }
281
282
283
284
285
286
287
288
289 protected XPage getXPage( String strTemplate )
290 {
291 XPage page = getXPage( );
292
293 HtmlTemplate t = AppTemplateService.getTemplate( strTemplate );
294 page.setContent( t.getHtml( ) );
295
296 return page;
297 }
298
299
300
301
302
303
304
305
306
307
308 protected XPage getXPage( String strTemplate, Locale locale )
309 {
310 return getXPage( strTemplate, locale, getModel( ) );
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325 protected XPage getXPage( String strTemplate, Locale locale, Map<String, Object> model )
326 {
327 XPage page = getXPage( );
328
329 HtmlTemplate t = AppTemplateService.getTemplate( strTemplate, locale, model );
330 page.setContent( t.getHtml( ) );
331 page.setTitle( getDefaultPageTitle( locale ) );
332 page.setPathLabel( getDefaultPagePath( locale ) );
333
334 return page;
335 }
336
337
338
339
340
341
342 protected Map<String, Object> getModel( )
343 {
344 Map<String, Object> model = new HashMap<>( );
345 fillCommons( model );
346
347 return model;
348 }
349
350
351
352
353
354
355
356
357
358
359
360
361 protected void populate( Object bean, HttpServletRequest request )
362 {
363 BeanUtil.populate( bean, request, null );
364 }
365
366
367
368
369
370
371
372
373
374
375
376 protected void populate( Object bean, HttpServletRequest request, Locale locale )
377 {
378 BeanUtil.populate( bean, request, locale );
379 }
380
381
382
383
384
385
386
387
388
389
390
391
392 protected <T> boolean validateBean( T bean )
393 {
394 Set<ConstraintViolation<T>> errors = BeanValidationUtil.validate( bean );
395
396 if ( errors.isEmpty( ) )
397 {
398 return true;
399 }
400
401 for ( ConstraintViolation<T> constraint : errors )
402 {
403 MVCMessage/util/mvc/utils/MVCMessage.html#MVCMessage">MVCMessage error = new MVCMessage( );
404 error.setMessage( constraint.getMessage( ) );
405 _listErrors.add( error );
406 }
407
408 return false;
409 }
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424 protected <T> boolean validateBean( T bean, Locale locale )
425 {
426 Set<ConstraintViolation<T>> errors = BeanValidationUtil.validate( bean );
427
428 if ( errors.isEmpty( ) )
429 {
430 return true;
431 }
432
433 for ( ConstraintViolation<T> constraint : errors )
434 {
435 MVCMessage/util/mvc/utils/MVCMessage.html#MVCMessage">MVCMessage error = new MVCMessage( );
436 error.setMessage( I18nService.getLocalizedString( constraint.getMessage( ), locale ) );
437 _listErrors.add( error );
438 }
439
440 return false;
441 }
442
443
444
445
446
447
448
449 protected void addError( String strMessage )
450 {
451 _listErrors.add( new MVCMessage( strMessage ) );
452 }
453
454
455
456
457
458
459
460
461 protected void addError( String strMessage, String strFieldName )
462 {
463 _listErrors.add( new MVCMessage( strMessage,strFieldName ) );
464 }
465
466
467
468
469
470
471
472
473
474 protected void addError( String strMessageKey, Locale locale )
475 {
476 _listErrors.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
477 }
478
479
480
481
482
483
484
485
486 protected void addWarning( String strMessage )
487 {
488 _listWarnings.add( new MVCMessage( strMessage ) );
489 }
490
491
492
493
494
495
496
497
498
499
500 protected void addWarning( String strMessage, String strFieldName )
501 {
502 _listWarnings.add( new MVCMessage( strMessage,strFieldName ) );
503 }
504
505
506
507
508
509
510
511
512
513
514
515 protected void addWarning( String strMessageKey, Locale locale )
516 {
517 _listWarnings.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
518 }
519
520
521
522
523
524
525
526 protected void addInfo( String strMessage )
527 {
528 _listInfos.add( new MVCMessage( strMessage ) );
529 }
530
531
532
533
534
535
536
537
538 protected void addInfo( String strMessage, String strFieldName )
539 {
540 _listInfos.add( new MVCMessage( strMessage,strFieldName ) );
541 }
542
543
544
545
546
547
548
549
550
551 protected void addInfo( String strMessageKey, Locale locale )
552 {
553 _listInfos.add( new MVCMessage( I18nService.getLocalizedString( strMessageKey, locale ) ) );
554 }
555
556
557
558
559
560
561
562 protected void fillCommons( Map<String, Object> model )
563 {
564 List<ErrorMessage> listErrors = new ArrayList<>( _listErrors );
565 List<ErrorMessage> listInfos = new ArrayList<>( _listInfos );
566 List<ErrorMessage> listWarnings = new ArrayList<>( _listWarnings );
567 model.put( MARK_ERRORS, listErrors );
568 model.put( MARK_INFOS, listInfos );
569 model.put( MARK_WARNINGS, listWarnings );
570 _listErrors.clear( );
571 _listInfos.clear( );
572 _listWarnings.clear( );
573 }
574
575
576
577
578
579
580
581
582
583
584
585
586
587 protected XPage redirect( HttpServletRequest request, String strTarget )
588 {
589 HttpServletResponse response = LocalVariables.getResponse( );
590
591 try
592 {
593 _logger.debug( "Redirect :{}", strTarget );
594 response.sendRedirect( strTarget );
595 }
596 catch( IOException e )
597 {
598 _logger.error( "Unable to redirect : {} : {}", strTarget, e.getMessage( ), e );
599 }
600 XPage/portal/web/xpages/XPage.html#XPage">XPage xpage=new XPage();
601 xpage.setSendRedirect(true);
602 return xpage;
603 }
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618 protected XPage redirect( HttpServletRequest request, String strView, String strParameter, int nValue )
619 {
620 UrlItemtil/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( getViewUrl( strView ) );
621 url.addParameter( strParameter, nValue );
622
623 return redirect( request, url.getUrl( ) );
624 }
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643 protected XPage redirect( HttpServletRequest request, String strView, String strParameter1, int nValue1, String strParameter2, int nValue2 )
644 {
645 UrlItemtil/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( getViewUrl( strView ) );
646 url.addParameter( strParameter1, nValue1 );
647 url.addParameter( strParameter2, nValue2 );
648
649 return redirect( request, url.getUrl( ) );
650 }
651
652
653
654
655
656
657
658
659
660
661
662
663 protected XPage redirect( HttpServletRequest request, String strView, Map<String, String> additionalParameters )
664 {
665 UrlItemtil/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( getViewUrl( strView ) );
666
667 if ( additionalParameters != null )
668 {
669 for ( Entry<String, String> entry : additionalParameters.entrySet( ) )
670 {
671 url.addParameter( entry.getKey( ), entry.getValue( ) );
672 }
673 }
674
675 return redirect( request, url.getUrl( ) );
676 }
677
678
679
680
681
682
683
684
685
686
687 protected XPage redirectView( HttpServletRequest request, String strView )
688 {
689 return redirect( request, getViewUrl( strView ) );
690 }
691
692
693
694
695
696
697
698
699 protected String getViewUrl( String strView )
700 {
701 UrlItemtil/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( URL_PORTAL );
702 url.addParameter( MVCUtils.PARAMETER_PAGE, getXPageName( ) );
703 url.addParameter( MVCUtils.PARAMETER_VIEW, strView );
704
705 return url.getUrl( );
706 }
707
708
709
710
711
712
713
714
715 protected String getViewFullUrl( String strView )
716 {
717 return PATH_PORTAL + getViewUrl( strView );
718 }
719
720
721
722
723
724
725
726
727 protected String getActionUrl( String strAction )
728 {
729 UrlItemtil/url/UrlItem.html#UrlItem">UrlItem url = new UrlItem( URL_PORTAL );
730 url.addParameter( MVCUtils.PARAMETER_PAGE, getXPageName( ) );
731 url.addParameter( MVCUtils.PARAMETER_ACTION, strAction );
732
733 return url.getUrl( );
734 }
735
736
737
738
739
740
741
742
743 protected String getActionFullUrl( String strAction )
744 {
745 return PATH_PORTAL + getActionUrl( strAction );
746 }
747
748
749
750
751
752
753
754
755
756
757
758
759 protected XPage download( String strData, String strFilename, String strContentType )
760 {
761 HttpServletResponse response = LocalVariables.getResponse( );
762 PrintWriter out = null;
763 response.setHeader( "Content-Disposition", "attachment; filename=\"" + strFilename + "\";" );
764 MVCUtils.addDownloadHeaderToResponse( response, strFilename, strContentType );
765
766 try
767 {
768 out = response.getWriter( );
769 out.print( strData );
770 }
771 catch( IOException e )
772 {
773 AppLogService.error( e.getStackTrace( ), e );
774 }
775 finally
776 {
777 if ( out != null )
778 {
779 out.close( );
780 }
781 }
782
783 return new XPage( );
784 }
785
786
787
788
789
790
791
792
793
794
795
796
797 protected XPage download( byte [ ] data, String strFilename, String strContentType )
798 {
799 HttpServletResponse response = LocalVariables.getResponse( );
800 OutputStream os;
801 MVCUtils.addDownloadHeaderToResponse( response, strFilename, strContentType );
802
803 try
804 {
805 os = response.getOutputStream( );
806 os.write( data );
807 os.close( );
808 }
809 catch( IOException e )
810 {
811 AppLogService.error( e.getStackTrace( ), e );
812 }
813
814 return new XPage( );
815 }
816
817
818
819
820
821
822
823
824 protected XPage responseJSON( String strJSON )
825 {
826 HttpServletResponse response = LocalVariables.getResponse( );
827 response.setContentType( CONTENT_TYPE_JSON );
828
829 try
830 {
831 PrintWriter out = response.getWriter( );
832 out.print( strJSON );
833 out.flush( );
834 out.close( );
835 }
836 catch( IOException e )
837 {
838 AppLogService.error( e.getStackTrace( ), e );
839 }
840
841 return new XPage( );
842 }
843
844
845
846
847
848
849
850
851 protected XPage responseXML( String strXML )
852 {
853 HttpServletResponse response = LocalVariables.getResponse( );
854 response.setContentType( CONTENT_TYPE_XML );
855
856 try
857 {
858 PrintWriter out = response.getWriter( );
859 out.print( strXML );
860 out.flush( );
861 out.close( );
862 }
863 catch( IOException e )
864 {
865 AppLogService.error( e.getStackTrace( ), e );
866 }
867
868 return new XPage( );
869 }
870
871
872
873
874
875
876
877
878
879
880
881
882
883 protected XPage redirectMessageBox( HttpServletRequest request, MVCMessageBox messageBox )
884 {
885 _messageBox = messageBox;
886
887 return redirectView( request, VIEW_MESSAGEBOX );
888 }
889
890
891
892
893
894
895
896
897 private boolean isMessageBox( HttpServletRequest request )
898 {
899 String strView = request.getParameter( MVCUtils.PARAMETER_VIEW );
900
901 return ( ( strView != null ) && ( strView.equals( VIEW_MESSAGEBOX ) ) );
902 }
903
904
905
906
907
908
909
910
911 protected Locale getLocale( HttpServletRequest request )
912 {
913 return LocaleService.getContextUserLocale( request );
914 }
915
916
917
918
919
920
921
922
923 private XPage messageBox( HttpServletRequest request )
924 {
925 _messageBox.localize( getLocale( request ) );
926
927 Map<String, Object> model = getModel( );
928 model.put( MARK_MESSAGE_BOX, _messageBox );
929
930 return getXPage( _messageBox.getTemplate( ), getLocale( request ), model );
931 }
932
933
934
935
936
937
938
939 protected LuteceUser getRegistredUser( HttpServletRequest request )
940 {
941
942 if ( SecurityService.isAuthenticationEnable( ) )
943 {
944 LuteceUser luteceUser = SecurityService.getInstance( ).getRegisteredUser( request );
945 if ( luteceUser != null )
946 {
947 return luteceUser;
948 }
949 }
950
951 return null;
952 }
953 }