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