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.plugins.formengine.web.style;
35
36 import fr.paris.lutece.plugins.formengine.business.style.StyleSheet;
37 import fr.paris.lutece.plugins.formengine.service.FormsRegistrationService;
38 import fr.paris.lutece.plugins.formengine.web.Form;
39 import fr.paris.lutece.plugins.formengine.web.SubForm;
40 import fr.paris.lutece.portal.service.admin.AccessDeniedException;
41 import fr.paris.lutece.portal.service.html.XmlTransformerService;
42 import fr.paris.lutece.portal.service.message.AdminMessage;
43 import fr.paris.lutece.portal.service.message.AdminMessageService;
44 import fr.paris.lutece.portal.service.template.AppTemplateService;
45 import fr.paris.lutece.portal.service.util.AppException;
46 import fr.paris.lutece.portal.service.util.AppLogService;
47 import fr.paris.lutece.portal.service.util.AppPathService;
48 import fr.paris.lutece.portal.service.util.AppPropertiesService;
49 import fr.paris.lutece.portal.web.admin.PluginAdminPageJspBean;
50 import fr.paris.lutece.portal.web.constants.Parameters;
51 import fr.paris.lutece.portal.web.upload.MultipartHttpServletRequest;
52 import fr.paris.lutece.portal.web.util.LocalizedPaginator;
53 import fr.paris.lutece.util.ReferenceList;
54 import fr.paris.lutece.util.html.HtmlTemplate;
55 import fr.paris.lutece.util.html.Paginator;
56 import fr.paris.lutece.util.sort.AttributeComparator;
57 import fr.paris.lutece.util.url.UrlItem;
58
59 import org.apache.commons.beanutils.BeanUtils;
60 import org.apache.commons.fileupload.FileItem;
61 import org.apache.commons.lang.StringUtils;
62
63 import org.xml.sax.InputSource;
64
65 import java.io.ByteArrayInputStream;
66 import java.io.File;
67 import java.io.FileInputStream;
68 import java.io.FileNotFoundException;
69 import java.io.FileOutputStream;
70 import java.io.IOException;
71 import java.io.OutputStream;
72
73 import java.lang.reflect.InvocationTargetException;
74
75 import java.util.ArrayList;
76 import java.util.Collections;
77 import java.util.HashMap;
78 import java.util.List;
79 import java.util.Map;
80 import java.util.Map.Entry;
81 import java.util.Set;
82
83 import javax.servlet.http.HttpServletRequest;
84 import javax.servlet.http.HttpServletResponse;
85
86 import javax.xml.parsers.SAXParser;
87 import javax.xml.parsers.SAXParserFactory;
88
89
90
91
92
93 public class StyleSheetJspBean extends PluginAdminPageJspBean
94 {
95
96
97
98
99 public static final String RIGHT_MANAGE_STYLESHEET = "FORMENGINE_STYLESHEET_MANAGEMENT";
100
101
102 private static final String MARK_FORM_ID = "form";
103 private static final String MARK_FORM_LIST = "form_list";
104 private static final String MARK_STYLESHEET_LIST = "stylesheet_list";
105 private static final String MARK_STYLESHEET = "stylesheet";
106 private static final String MARK_PAGINATOR = "paginator";
107 private static final String MARK_NB_ITEMS_PER_PAGE = "nb_items_per_page";
108
109
110 private static final String TEMPLATE_MANAGE_STYLESHEETS = "admin/plugins/formengine/style/manage_stylesheets.html";
111 private static final String TEMPLATE_MODIFY_STYLESHEET = "admin/plugins/formengine/style/modify_stylesheet.html";
112
113
114 private static final String PARAMETER_FORM = "form";
115 private static final String PARAMETER_STYLESHEET_ID = "stylesheet_id";
116 private static final String PARAMETER_STYLESHEET_SOURCE = "stylesheet_source";
117 private static final String PARAMETER_CANCEL = "cancel";
118
119
120 private static final String PROPERTY_FORMENGINE_XSL_DIRECTORY = "formengine.xsl.directory";
121 private static final String PROPERTY_STYLESHEETS_PER_PAGE = "formengine.stylesheet.itemsPerPage";
122 private static final String PROPERTYMESSAGE_STYLESHEET_NOT_VALID = "portal.style.message.stylesheetNotValid";
123 private static final String PROPERTY_MESSAGE_ERROR_WRITE_FILE = "formengine.style.error.writeXSL";
124 private static final String CONSTANT_FORM_ELEMENT_XSL_FILE_NAME = "formelements.xsl";
125 private static final String CONSTANT_FORM_ELEMENT_XSL_FORM_NAME = "formengine";
126 private static final String CONSTANT_NO_FORM_SELECTED = "-1";
127 private int _nItemsPerPage;
128 private int _nDefaultItemsPerPage;
129 private String _strCurrentPageIndex;
130 private String _strForm;
131
132
133
134
135 private Map<String, Map<String, StyleSheet>> _mapStyleSheet;
136
137
138
139
140
141 @Override
142 public void init( HttpServletRequest request, String strRight )
143 throws AccessDeniedException
144 {
145 super.init( request, strRight );
146 initListStyleSheet( );
147 }
148
149
150
151
152
153 private void initListStyleSheet( )
154 {
155 if ( _mapStyleSheet == null )
156 {
157
158 _mapStyleSheet = new HashMap<String, Map<String, StyleSheet>>( );
159
160 StyleSheet formengineStyleSheet = new StyleSheet( );
161 formengineStyleSheet.setFile( CONSTANT_FORM_ELEMENT_XSL_FILE_NAME );
162 formengineStyleSheet.setForm( CONSTANT_FORM_ELEMENT_XSL_FORM_NAME );
163 formengineStyleSheet.setFormId( CONSTANT_FORM_ELEMENT_XSL_FORM_NAME );
164 formengineStyleSheet.setPath( AppPathService.getPath( PROPERTY_FORMENGINE_XSL_DIRECTORY ) + File.separator +
165 CONSTANT_FORM_ELEMENT_XSL_FILE_NAME );
166 _mapStyleSheet.put( CONSTANT_FORM_ELEMENT_XSL_FORM_NAME,
167 Collections.singletonMap( CONSTANT_FORM_ELEMENT_XSL_FILE_NAME, formengineStyleSheet ) );
168
169
170 for ( String strFormName : FormsRegistrationService.getForms( ) )
171 {
172 Form form = FormsRegistrationService.getForm( strFormName );
173
174 for ( Entry<String, SubForm> entrySubForm : (Set<Entry<String, SubForm>>) form.getSubForm( ).entrySet( ) )
175 {
176 SubForm subForm = entrySubForm.getValue( );
177 String strXSLDirectory = subForm.getParentForm( ).getXslDirectoryPath( ) + File.separator;
178
179
180 Map<String, StyleSheet> mapStyleSheetSubForm = new HashMap<String, StyleSheet>( );
181
182
183 for ( String strXslFileName : subForm.getXslFilesNames( ) )
184 {
185 StyleSheet styleSheet = new StyleSheet( );
186 styleSheet.setForm( subForm.getParentForm( ).getName( ) + "-" + subForm.getName( ) );
187 styleSheet.setPath( strXSLDirectory + strXslFileName );
188 styleSheet.setFile( strXslFileName );
189 mapStyleSheetSubForm.put( styleSheet.getFile( ), styleSheet );
190 styleSheet.setFormId( FormsRegistrationService.getIdForm( styleSheet.getForm( ) ) );
191 }
192
193 _mapStyleSheet.put( FormsRegistrationService.getIdForm( subForm.getParentForm( ).getName( ) +
194 "-" + subForm.getName( ) ), mapStyleSheetSubForm );
195 }
196 }
197 }
198 }
199
200
201
202
203
204
205 public String getManageStyleSheet( HttpServletRequest request )
206 {
207
208 ReferenceList listForm = FormsRegistrationService.getListForm( );
209 String strForm = request.getParameter( PARAMETER_FORM );
210
211 List<StyleSheet> listStyleSheets;
212
213 if ( CONSTANT_NO_FORM_SELECTED.equals( strForm ) )
214 {
215 _strForm = "";
216 listStyleSheets = getStyleSheetList( );
217 }
218 else
219 {
220 if ( StringUtils.isNotBlank( strForm ) )
221 {
222 _strForm = strForm;
223 }
224
225 if ( StringUtils.isNotBlank( _strForm ) )
226 {
227 listStyleSheets = getStyleSheetList( _strForm );
228 }
229 else
230 {
231 listStyleSheets = getStyleSheetList( );
232 }
233 }
234
235 String strSortedAttributeName = request.getParameter( Parameters.SORTED_ATTRIBUTE_NAME );
236 String strAscSort = null;
237
238 if ( strSortedAttributeName != null )
239 {
240 strAscSort = request.getParameter( Parameters.SORTED_ASC );
241
242 boolean bIsAscSort = Boolean.parseBoolean( strAscSort );
243
244 Collections.sort( listStyleSheets, new AttributeComparator( strSortedAttributeName, bIsAscSort ) );
245 }
246
247 _nDefaultItemsPerPage = AppPropertiesService.getPropertyInt( PROPERTY_STYLESHEETS_PER_PAGE, 50 );
248 _strCurrentPageIndex = Paginator.getPageIndex( request, Paginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex );
249 _nItemsPerPage = Paginator.getItemsPerPage( request, Paginator.PARAMETER_ITEMS_PER_PAGE, _nItemsPerPage,
250 _nDefaultItemsPerPage );
251
252 UrlItem urlItem = new UrlItem( getHomeUrl( request ) );
253
254 if ( strSortedAttributeName != null )
255 {
256 urlItem.addParameter( Parameters.SORTED_ATTRIBUTE_NAME, strSortedAttributeName );
257 }
258
259 if ( strAscSort != null )
260 {
261 urlItem.addParameter( Parameters.SORTED_ASC, strAscSort );
262 }
263
264 LocalizedPaginator<StyleSheet> paginator = new LocalizedPaginator<StyleSheet>( listStyleSheets, _nItemsPerPage,
265 urlItem.getUrl( ), Paginator.PARAMETER_PAGE_INDEX, _strCurrentPageIndex, getLocale( ) );
266
267 Map<String, Object> model = new HashMap<String, Object>( );
268 model.put( MARK_FORM_ID, ( _strForm == null ) ? "" : _strForm );
269 model.put( MARK_NB_ITEMS_PER_PAGE, "" + _nItemsPerPage );
270 model.put( MARK_PAGINATOR, paginator );
271 model.put( MARK_STYLESHEET_LIST, paginator.getPageItems( ) );
272 model.put( MARK_FORM_LIST, listForm );
273
274 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MANAGE_STYLESHEETS, getLocale( ), model );
275
276 return getAdminPage( template.getHtml( ) );
277 }
278
279
280
281
282
283
284
285 private String saveFileToDisk( StyleSheetWithFileItem styleSheet, HttpServletRequest request )
286 {
287
288 File fileXSL = new File( styleSheet.getPath( ) );
289
290 FileOutputStream fos = null;
291
292 try
293 {
294 fos = new FileOutputStream( fileXSL );
295
296 fos.write( styleSheet.getFileItem( ).get( ) );
297 }
298 catch ( IOException e )
299 {
300 AppLogService.error( e.getMessage( ), e );
301
302 return AdminMessageService.getMessageUrl( request, PROPERTY_MESSAGE_ERROR_WRITE_FILE,
303 new String[] { e.getMessage( ) }, AdminMessage.TYPE_ERROR );
304 }
305 finally
306 {
307
308 if ( fos != null )
309 {
310 try
311 {
312 fos.close( );
313 }
314 catch ( IOException e )
315 {
316 AppLogService.error( e.getMessage( ), e );
317 }
318 }
319 }
320
321 return null;
322 }
323
324
325
326
327
328
329
330 private String getData( MultipartHttpServletRequest multipartRequest, StyleSheetWithFileItem stylesheet )
331 {
332 String strErrorUrl = null;
333
334 FileItem fileSource = multipartRequest.getFile( PARAMETER_STYLESHEET_SOURCE );
335 byte[] baXslSource = fileSource.get( );
336
337
338 if ( isValid( baXslSource ) != null )
339 {
340 Object[] args = { isValid( baXslSource ) };
341
342 return AdminMessageService.getMessageUrl( multipartRequest, PROPERTYMESSAGE_STYLESHEET_NOT_VALID, args,
343 AdminMessage.TYPE_STOP );
344 }
345
346 stylesheet.setFileItem( fileSource );
347
348 return strErrorUrl;
349 }
350
351
352
353
354
355
356 public String getModifyStyleSheet( HttpServletRequest request )
357 {
358 StyleSheet styleSheet = getStyleSheetFromRequest( request );
359
360 if ( styleSheet == null )
361 {
362 throw new IllegalArgumentException( "Stylesheet does not exist" );
363 }
364
365 Map<String, Object> model = new HashMap<String, Object>( );
366 model.put( MARK_FORM_LIST, FormsRegistrationService.getListForm( ) );
367
368 model.put( MARK_STYLESHEET, styleSheet );
369
370 HtmlTemplate template = AppTemplateService.getTemplate( TEMPLATE_MODIFY_STYLESHEET, getLocale( ), model );
371
372 return getAdminPage( template.getHtml( ) );
373 }
374
375
376
377
378
379 private List<StyleSheet> getStyleSheetList( )
380 {
381 List<StyleSheet> listStyleSheets = new ArrayList<StyleSheet>( );
382
383 for ( Map<String, StyleSheet> mapsStyleSheet : _mapStyleSheet.values( ) )
384 {
385 listStyleSheets.addAll( mapsStyleSheet.values( ) );
386 }
387
388 return listStyleSheets;
389 }
390
391
392
393
394
395
396 private List<StyleSheet> getStyleSheetList( String strFormId )
397 {
398 List<StyleSheet> listStyleSheets = new ArrayList<StyleSheet>( );
399
400 Map<String, StyleSheet> mapsStyleSheet = _mapStyleSheet.get( strFormId );
401
402 if ( mapsStyleSheet != null )
403 {
404 listStyleSheets.addAll( mapsStyleSheet.values( ) );
405 }
406
407 return listStyleSheets;
408 }
409
410
411
412
413
414
415 private StyleSheet getStyleSheetFromRequest( HttpServletRequest request )
416 {
417 String strFormId = request.getParameter( PARAMETER_FORM );
418 String strStyleSheetId = request.getParameter( PARAMETER_STYLESHEET_ID );
419
420 Map<String, StyleSheet> mapStyleSheets = _mapStyleSheet.get( strFormId );
421
422 if ( mapStyleSheets == null )
423 {
424 AppLogService.error( "FORMENGINE : form not found for id=" + strFormId );
425
426 return null;
427 }
428
429 return mapStyleSheets.get( strStyleSheetId );
430 }
431
432
433
434
435
436
437
438 public String doModifyStyleSheet( HttpServletRequest request )
439 {
440 if ( request.getParameter( PARAMETER_CANCEL ) != null )
441 {
442 return getHomeUrl( request );
443 }
444
445
446 MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
447
448 StyleSheet stylesheet = getStyleSheetFromRequest( request );
449 StyleSheetWithFileItem styleSheetWithFileItem = null;
450
451 try
452 {
453 styleSheetWithFileItem = new StyleSheetWithFileItem( stylesheet );
454 }
455 catch ( IllegalAccessException e )
456 {
457 AppLogService.error( e.getMessage( ), e );
458 throw new AppException( e.getMessage( ), e );
459 }
460 catch ( InvocationTargetException e )
461 {
462 AppLogService.error( e.getMessage( ), e );
463 throw new AppException( e.getMessage( ), e );
464 }
465
466 String strErrorUrl = getData( multipartRequest, styleSheetWithFileItem );
467
468 if ( strErrorUrl != null )
469 {
470 return strErrorUrl;
471 }
472
473
474 strErrorUrl = saveFileToDisk( styleSheetWithFileItem, request );
475
476 if ( strErrorUrl != null )
477 {
478 return strErrorUrl;
479 }
480
481
482 XmlTransformerService.clearXslCache( );
483
484
485 return getHomeUrl( request );
486 }
487
488
489
490
491
492
493
494 public String doViewStyleSheet( HttpServletRequest request, HttpServletResponse response )
495 {
496 StyleSheet styleSheet = getStyleSheetFromRequest( request );
497
498 if ( styleSheet == null )
499 {
500 return getHomeUrl( request );
501 }
502
503 OutputStream os = null;
504 File fileXSL = new File( styleSheet.getPath( ) );
505 FileInputStream fis;
506
507 try
508 {
509 fis = new FileInputStream( fileXSL );
510 }
511 catch ( FileNotFoundException e1 )
512 {
513 return getHomeUrl( request );
514 }
515
516 try
517 {
518 String strFileName = styleSheet.getFile( );
519 addHeaderResponse( request, response, strFileName );
520 response.setContentLength( (int) fileXSL.length( ) );
521
522 os = response.getOutputStream( );
523
524 byte[] bytes = new byte[1024];
525
526 while ( fis.read( bytes ) != -1 )
527 {
528 os.write( bytes );
529 }
530 }
531 catch ( IOException e )
532 {
533 AppLogService.error( e );
534 }
535 finally
536 {
537 if ( os != null )
538 {
539 try
540 {
541 os.close( );
542 }
543 catch ( IOException e )
544 {
545 AppLogService.error( e );
546 }
547 }
548
549 try
550 {
551 fis.close( );
552 }
553 catch ( IOException e )
554 {
555 AppLogService.error( e );
556 }
557 }
558
559 return null;
560 }
561
562
563
564
565
566
567
568 private static void addHeaderResponse( HttpServletRequest request, HttpServletResponse response, String strFileName )
569 {
570 response.setHeader( "Content-Disposition", "attachment ;filename=\"" + strFileName + "\"" );
571
572 if ( strFileName.endsWith( "xsl" ) )
573 {
574 response.setContentType( "text/xml" );
575 }
576 else
577 {
578 String strMimeType = request.getSession( ).getServletContext( ).getMimeType( strFileName );
579
580 if ( strMimeType != null )
581 {
582 response.setContentType( strMimeType );
583 }
584 else
585 {
586 response.setContentType( "application/octet-stream" );
587 }
588 }
589
590 response.setHeader( "Pragma", "public" );
591 response.setHeader( "Expires", "0" );
592 response.setHeader( "Cache-Control", "must-revalidate,post-check=0,pre-check=0" );
593 }
594
595
596
597
598
599
600
601
602
603
604 private String isValid( byte[] baXslSource )
605 {
606 String strError = null;
607
608 try
609 {
610 SAXParserFactory factory = SAXParserFactory.newInstance( );
611 SAXParser analyzer = factory.newSAXParser( );
612 InputSource is = new InputSource( new ByteArrayInputStream( baXslSource ) );
613 analyzer.getXMLReader( ).parse( is );
614 }
615 catch ( Exception e )
616 {
617 strError = e.getMessage( );
618 }
619
620 return strError;
621 }
622
623
624
625
626
627 private static class StyleSheetWithFileItem extends StyleSheet
628 {
629 private FileItem _fileItem;
630
631
632
633
634 public StyleSheetWithFileItem( )
635 {
636
637 }
638
639
640
641
642
643
644
645 public StyleSheetWithFileItem( StyleSheet styleSheet )
646 throws IllegalAccessException, InvocationTargetException
647 {
648 BeanUtils.copyProperties( this, styleSheet );
649 }
650
651
652
653
654
655 public FileItem getFileItem( )
656 {
657 return _fileItem;
658 }
659
660
661
662
663
664 public void setFileItem( FileItem item )
665 {
666 _fileItem = item;
667 }
668 }
669 }