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.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   * This class provides the user interface to manage StyleSheet features
92   */
93  public class StyleSheetJspBean extends PluginAdminPageJspBean
94  {
95      ////////////////////////////////////////////////////////////////////////////
96      // Constants
97  
98      // Right
99      public static final String RIGHT_MANAGE_STYLESHEET = "FORMENGINE_STYLESHEET_MANAGEMENT";
100 
101     // Markers
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     // Templates files path
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     // Parameter
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     // Properties
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      * Key is form Id. Value is : fileName ==> StyleSheet
134      */
135     private Map<String, Map<String, StyleSheet>> _mapStyleSheet;
136 
137     /**
138      *
139      *{@inheritDoc}
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      * Inits the stylesheets map
151      * @see #_mapStyleSheet
152      */
153     private void initListStyleSheet(  )
154     {
155         if ( _mapStyleSheet == null )
156         {
157             // FORMELEMENT IS FORM PARENT XSL
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             // add forms stylesheets    		
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                     // key = fileName, value = styleSheet
180                     Map<String, StyleSheet> mapStyleSheetSubForm = new HashMap<String, StyleSheet>(  );
181 
182                     // get other xsl (like object_summary.xsl)
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      * Displays the stylesheets list
202      * @return the html code for displaying the stylesheets list
203      * @param request The request
204      */
205     public String getManageStyleSheet( HttpServletRequest request )
206     {
207         // Parameters processing
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      * Saves file to disk
281      * @param styleSheet the stylesheet
282      * @param request the request
283      * @return url if an error occurs
284      */
285     private String saveFileToDisk( StyleSheetWithFileItem styleSheet, HttpServletRequest request )
286     {
287         // getFileInfo
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             // close streams
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      * Reads stylesheet's data
326      * @param multipartRequest The request
327      * @param stylesheet The style sheet
328      * @return An error message URL or null if no error
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         // Check the XML validity of the XSL stylesheet
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      * Returns the form to update a stylesheet whose identifer is stored in the http request
353      * @param request The http request
354      * @return The html code
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      * Gets all stylesheets list
377      * @return list
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      * Filtered stylesheet list
393      * @param strFormId the form id
394      * @return list
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      * Gets the stylesheet from request
412      * @param request the request
413      * @return the stylesheet found, <code>null</code> otherwise.
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      * Processes the updating form of a stylesheet whose new parameters are stored in the
434      * http request
435      * @param request The http request
436      * @return The Jsp URL of the process result
437      */
438     public String doModifyStyleSheet( HttpServletRequest request )
439     {
440         if ( request.getParameter( PARAMETER_CANCEL ) != null )
441         {
442             return getHomeUrl( request );
443         }
444 
445         // FormsRegistrationService
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         // Update the stylesheet in database
474         strErrorUrl = saveFileToDisk( styleSheetWithFileItem, request );
475 
476         if ( strErrorUrl != null )
477         {
478             return strErrorUrl;
479         }
480 
481         // clear XSL cache
482         XmlTransformerService.clearXslCache(  );
483 
484         // Displays the management stylesheet page
485         return getHomeUrl( request );
486     }
487 
488     /**
489      * Downloads the xsl file
490      * @param request the request
491      * @param response the response
492      * @return home url if no file found, <code>null</code> otherwise.
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      * write the http header in the response
564      * @param request the httpServletRequest
565      * @param response the http response
566      * @param strFileName the name of the file who must insert in the response
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     // Private implementation
597 
598     /**
599      *  Use parsing for validate the modify xsl file
600      *
601      * @param baXslSource The XSL source
602      * @return the message exception when the validation is false
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      * Style sheet with an attribute fileItem
625      * @see StyleSheet
626      */
627     private static class StyleSheetWithFileItem extends StyleSheet
628     {
629         private FileItem _fileItem;
630 
631         /**
632                  * Empty constructor
633                  */
634         public StyleSheetWithFileItem(  )
635         {
636             // nothing
637         }
638 
639         /**
640          * Copies {@link StyleSheet} infos
641          * @param styleSheet the stylesheet to copy
642          * @throws IllegalAccessException if copy does not work
643          * @throws InvocationTargetException if copy does not work
644          */
645         public StyleSheetWithFileItem( StyleSheet styleSheet )
646             throws IllegalAccessException, InvocationTargetException
647         {
648             BeanUtils.copyProperties( this, styleSheet );
649         }
650 
651         /**
652          * "Getter method" for {@link #_fileItem}
653          * @return value of {@link #_fileItem}
654          */
655         public FileItem getFileItem(  )
656         {
657             return _fileItem;
658         }
659 
660         /**
661          * "Setter method" for {@link #_fileItem}
662          * @param item new value of {@link #_fileItem}
663          */
664         public void setFileItem( FileItem item )
665         {
666             _fileItem = item;
667         }
668     }
669 }