View Javadoc
1   /*
2    * Copyright (C) 2003-2009 eXo Platform SAS.
3    *
4    * This program is free software; you can redistribute it and/or
5    * modify it under the terms of the GNU Affero General Public License
6    * as published by the Free Software Foundation; either version 3
7    * of the License, or (at your option) any later version.
8    *
9    * This program is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   * GNU General Public License for more details.
13   *
14   * You should have received a copy of the GNU General Public License
15   * along with this program; if not, see<http://www.gnu.org/licenses/>.
16   */
17  package org.exoplatform.wcm.connector;
18  
19  import java.io.BufferedInputStream;
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.text.DateFormat;
23  import java.text.SimpleDateFormat;
24  import java.util.Date;
25  import java.util.GregorianCalendar;
26  import java.util.HashSet;
27  import java.util.Hashtable;
28  import java.util.Locale;
29  import java.util.Map;
30  import java.util.ResourceBundle;
31  import java.util.Set;
32  
33  import javax.jcr.ItemExistsException;
34  import javax.jcr.Node;
35  import javax.servlet.http.HttpServletRequest;
36  import javax.ws.rs.core.CacheControl;
37  import javax.ws.rs.core.MediaType;
38  import javax.ws.rs.core.Response;
39  import javax.xml.parsers.DocumentBuilder;
40  import javax.xml.parsers.DocumentBuilderFactory;
41  import javax.xml.transform.dom.DOMSource;
42  
43  import com.ibm.icu.text.Transliterator;
44  import org.apache.commons.lang.StringUtils;
45  import org.exoplatform.common.http.HTTPStatus;
46  import org.exoplatform.ecm.connector.fckeditor.FCKMessage;
47  import org.exoplatform.ecm.connector.fckeditor.FCKUtils;
48  import org.exoplatform.ecm.utils.lock.LockUtil;
49  import org.exoplatform.ecm.utils.text.Text;
50  import org.exoplatform.services.cms.documents.AutoVersionService;
51  import org.exoplatform.services.cms.impl.Utils;
52  import org.exoplatform.services.cms.jcrext.activity.ActivityCommonService;
53  import org.exoplatform.services.cms.mimetype.DMSMimeTypeResolver;
54  import org.exoplatform.services.cms.templates.TemplateService;
55  import org.exoplatform.services.listener.ListenerService;
56  import org.exoplatform.services.log.ExoLogger;
57  import org.exoplatform.services.log.Log;
58  import org.exoplatform.services.resources.ResourceBundleService;
59  import org.exoplatform.services.wcm.core.NodetypeConstant;
60  import org.exoplatform.services.wcm.publication.WCMPublicationService;
61  import org.exoplatform.services.wcm.utils.WCMCoreUtils;
62  import org.exoplatform.upload.UploadResource;
63  import org.exoplatform.upload.UploadService;
64  import org.exoplatform.upload.UploadService.UploadLimit;
65  import org.json.JSONObject;
66  import org.w3c.dom.Document;
67  import org.w3c.dom.Element;
68  
69  /**
70   * Created by The eXo Platform SAS
71   * Author : Tran Nguyen Ngoc
72   * ngoc.tran@exoplatform.com
73   * Sep 4, 2009
74   */
75  public class FileUploadHandler {
76  
77    /** Logger */  
78    private static final Log LOG = ExoLogger.getLogger(FileUploadHandler.class.getName());
79  
80    /** The Constant UPLOAD_ACTION. */
81    public final static String UPLOAD_ACTION = "upload";
82  
83    /** The Constant PROGRESS_ACTION. */
84    public final static String PROGRESS_ACTION = "progress";
85  
86    /** The Constant ABORT_ACTION. */
87    public final static String ABORT_ACTION = "abort";
88  
89    /** The Constant DELETE_ACTION. */
90    public final static String DELETE_ACTION = "delete";
91  
92    /** The Constant SAVE_ACTION. */
93    public final static String SAVE_ACTION = "save";
94    
95    /** The Constant SAVE_NEW_VERSION_ACTION. */
96    public final static String SAVE_NEW_VERSION_ACTION = "saveNewVersion";
97    
98    /** The Constant CHECK_EXIST. */
99    public final static String CHECK_EXIST= "exist";
100   
101   /** The Constant REPLACE. */
102   public final static String REPLACE= "replace";
103 
104   public final static String CREATE_VERSION = "createVersion";
105 
106   /** The Constant KEEP_BOTH. */
107   public final static String KEEP_BOTH= "keepBoth";
108 
109   /** The Constant LAST_MODIFIED_PROPERTY. */
110   private static final String LAST_MODIFIED_PROPERTY = "Last-Modified";
111 
112   /** The Constant IF_MODIFIED_SINCE_DATE_FORMAT. */
113   private static final String IF_MODIFIED_SINCE_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z";
114   
115   public final static String POST_CREATE_CONTENT_EVENT = "CmsService.event.postCreate";
116 
117   private final String CONNECTOR_BUNDLE_LOCATION                 = "locale.wcm.resources.WCMResourceBundleConnector";
118   private final String AUTOVERSION_ERROR_MIME_TYPE                  = "DocumentAutoVersion.msg.WrongMimeType";
119 
120   /** The upload service. */
121   private UploadService uploadService;
122   
123   /** The listener service. */
124   ListenerService listenerService;
125   
126   private ActivityCommonService   activityService;
127 
128   /** The fck message. */
129   private FCKMessage fckMessage;
130   
131   /** The uploadIds - time Map */
132   private Map<String, Long> uploadIdTimeMap;
133   
134   /** The maximal life time for an upload */
135   private long UPLOAD_LIFE_TIME;
136 
137   /**
138    * Instantiates a new file upload handler.
139    */
140   public FileUploadHandler() {
141     uploadService = WCMCoreUtils.getService(UploadService.class);
142     listenerService = WCMCoreUtils.getService(ListenerService.class);
143     activityService = WCMCoreUtils.getService(ActivityCommonService.class);
144     fckMessage = new FCKMessage();
145     uploadIdTimeMap = new Hashtable<String, Long>();
146     UPLOAD_LIFE_TIME = System.getProperty("MULTI_UPLOAD_LIFE_TIME") == null ? 600 ://10 minutes
147                                         Long.parseLong(System.getProperty("MULTI_UPLOAD_LIFE_TIME"));
148   }
149 
150   /**
151    * Upload
152    * @param servletRequest The request to upload file
153    * @param uploadId Upload Id
154    * @param limit Limit size of upload file
155    * @return
156    * @throws Exception
157    */
158   public Response upload(HttpServletRequest servletRequest, String uploadId, Integer limit) throws Exception{
159     uploadService.addUploadLimit(uploadId, limit);
160     uploadService.createUploadResource(servletRequest);
161     uploadIdTimeMap.put(uploadId, System.currentTimeMillis());
162     CacheControl cacheControl = new CacheControl();
163     cacheControl.setNoCache(true);
164     cacheControl.setNoStore(true);
165     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
166     
167     //create ret
168     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
169     DocumentBuilder builder = factory.newDocumentBuilder();
170     Document doc = builder.newDocument();
171     Element rootElement = doc.createElement("html");
172     Element head = doc.createElement("head");
173     Element body = doc.createElement("body");
174     rootElement.appendChild(head);
175     rootElement.appendChild(body);
176     doc.appendChild(rootElement);
177     
178     return Response.ok(new DOMSource(doc), MediaType.TEXT_XML)
179                    .cacheControl(cacheControl)
180                    .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
181                    .build();
182   }
183   
184   /**
185    * Check status of uploaded file.
186    * If any problem while uploading, error message is returned.
187    * Returning null means no problem happen.
188    * 
189    * @param uploadId upload ID
190    * @param language language for getting message
191    * @return Response message is returned if any problem while uploading.
192    * @throws Exception
193    */
194   public Response checkStatus(String uploadId, String language) throws Exception {
195     CacheControl cacheControl = new CacheControl();
196     cacheControl.setNoCache(true);
197     cacheControl.setNoStore(true);
198     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
199     
200     if ((StringUtils.isEmpty(uploadId)) || (uploadService.getUploadResource(uploadId) == null)) return null;
201     
202     // If file size exceed limit, return message
203     if (UploadResource.FAILED_STATUS == uploadService.getUploadResource(uploadId).getStatus()) {
204       
205       // Remove upload Id
206       uploadService.removeUploadResource(uploadId);
207       uploadIdTimeMap.remove(uploadId);
208       // Get message warning upload exceed limit
209       String uploadLimit = String.valueOf(uploadService.getUploadLimits().get(uploadId).getLimit());
210       Document fileExceedLimit =
211           fckMessage.createMessage(FCKMessage.FILE_EXCEED_LIMIT,
212                                    FCKMessage.ERROR,
213                                    language,
214                                    new String[]{uploadLimit});
215       
216       return Response.ok(new DOMSource(fileExceedLimit), MediaType.TEXT_XML)
217                       .cacheControl(cacheControl)
218                       .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
219                       .build();
220     }
221     
222     return null;
223   }
224   
225   /**
226    * Control.
227    *
228    * @param uploadId the upload id
229    * @param action the action
230    *
231    * @return the response
232    *
233    * @throws Exception the exception
234    */
235   public Response control(String uploadId, String action) throws Exception {
236     CacheControl cacheControl = new CacheControl();
237     cacheControl.setNoCache(true);
238     cacheControl.setNoStore(true);
239     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
240     
241     if (FileUploadHandler.PROGRESS_ACTION.equals(action)) {
242       Document currentProgress = getProgress(uploadId);
243       return Response.ok(new DOMSource(currentProgress), MediaType.TEXT_XML)
244                      .cacheControl(cacheControl)
245                      .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
246                      .build();
247     } else if (FileUploadHandler.ABORT_ACTION.equals(action)) {
248       uploadService.removeUploadResource(uploadId);
249       uploadIdTimeMap.remove(uploadId);
250       return Response.ok(null, MediaType.TEXT_XML)
251                      .cacheControl(cacheControl)
252                      .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
253                      .build();
254     } else if (FileUploadHandler.DELETE_ACTION.equals(action)) {
255       uploadService.removeUploadResource(uploadId);
256       uploadIdTimeMap.remove(uploadId);
257       return Response.ok(null, MediaType.TEXT_XML)
258                      .cacheControl(cacheControl)
259                      .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
260                      .build();
261     }
262     return Response.status(HTTPStatus.BAD_REQUEST)
263                    .cacheControl(cacheControl)
264                    .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
265                    .build();
266   }
267 
268   /**
269    * checks if file already existed in parent folder
270    *
271    * @param parent the parent
272    * @param fileName the file name
273    * @return the response
274    *
275    * @throws Exception the exception
276    */
277   public Response checkExistence(Node parent, String fileName) throws Exception {
278     DMSMimeTypeResolver resolver = DMSMimeTypeResolver.getInstance();
279     CacheControl cacheControl = new CacheControl();
280     cacheControl.setNoCache(true);
281     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
282     
283     //create ret
284     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
285     DocumentBuilder builder = factory.newDocumentBuilder();
286     Document fileExistence = builder.newDocument();
287     fileName = Utils.cleanNameWithAccents(fileName);
288     Element rootElement = fileExistence.createElement(
289                               parent.hasNode(fileName) ? "Existed" : "NotExisted");
290     if(parent.hasNode(fileName)){
291       Node existNode = parent.getNode(fileName);
292       if(existNode.isNodeType(NodetypeConstant.MIX_VERSIONABLE)){
293         rootElement.appendChild(fileExistence.createElement("Versioned"));
294       }
295     }
296     if(parent.isNodeType(NodetypeConstant.NT_FILE) && 
297         resolver.getMimeType(parent.getName()).equals(resolver.getMimeType(fileName))){
298       rootElement.appendChild(fileExistence.createElement("CanVersioning"));
299     }
300     fileExistence.appendChild(rootElement);
301     //return ret;
302     return Response.ok(new DOMSource(fileExistence), MediaType.TEXT_XML)
303                    .cacheControl(cacheControl)
304                    .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
305                    .build();
306   }
307   
308   /**
309    * Clean name using Transliterator
310    * @param fileName original file name
311    * 
312    * @return Response
313    */
314   public Response cleanName(String fileName) throws Exception {
315     CacheControl cacheControl = new CacheControl();
316     cacheControl.setNoCache(true);
317     DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
318     
319     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
320     DocumentBuilder builder = factory.newDocumentBuilder();
321     Document cleanedFilename = builder.newDocument(); 
322     fileName = Utils.cleanNameWithAccents(fileName);
323     Element rootElement = cleanedFilename.createElement("name");
324     cleanedFilename.appendChild(rootElement);
325     rootElement.setTextContent(fileName);
326     return Response.ok(new DOMSource(cleanedFilename), MediaType.TEXT_XML)
327             .cacheControl(cacheControl)
328             .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
329             .build();
330   }
331   
332   /**
333    * Save as nt file.
334    *
335    * @param parent the parent
336    * @param uploadId the upload id
337    * @param fileName the file name
338    * @param language the language
339    *
340    * @return the response
341    *
342    * @throws Exception the exception
343    */
344   public Response saveAsNTFile(Node parent,
345                                String uploadId,
346                                String fileName,
347                                String language,
348                                String siteName,
349                                String userId) throws Exception {
350     return saveAsNTFile(parent, uploadId, fileName, language, siteName, userId, KEEP_BOTH); 
351   }
352   
353   /**
354    * Save as nt file.
355    *
356    * @param parent the parent
357    * @param uploadId the upload id
358    * @param fileName the file name
359    * @param language the language
360    *
361    * @return the response
362    *
363    * @throws Exception the exception
364    */
365   public Response saveAsNTFile(Node parent,
366                                String uploadId,
367                                String fileName,
368                                String language,
369                                String siteName,
370                                String userId,
371                                String existenceAction) throws Exception {
372     return saveAsNTFile(parent, uploadId, fileName, language, siteName, userId, existenceAction,false);
373   }
374   /**
375    * Save as nt file.
376    *
377    * @param parent the parent
378    * @param uploadId the upload id
379    * @param fileName the file name
380    * @param language the language
381    *
382    * @return the response
383    *
384    * @throws Exception the exception
385    */
386   public Response saveAsNTFile(Node parent,
387                                String uploadId,
388                                String fileName,
389                                String language,
390                                String siteName,
391                                String userId,
392                                String existenceAction,
393                                boolean isNewVersion) throws Exception {
394     try {
395       CacheControl cacheControl = new CacheControl();
396       cacheControl.setNoCache(true);
397       UploadResource resource = uploadService.getUploadResource(uploadId);
398       DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
399       if (parent == null) {
400         Document fileNotUploaded = fckMessage.createMessage(FCKMessage.FILE_NOT_UPLOADED,
401                                                             FCKMessage.ERROR,
402                                                             language,
403                                                             null);
404         return Response.ok(new DOMSource(fileNotUploaded), MediaType.TEXT_XML)
405                        .cacheControl(cacheControl)
406                        .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
407                        .build();
408       }
409       if (!FCKUtils.hasAddNodePermission(parent)) {
410         Object[] args = { parent.getPath() };
411         Document message = fckMessage.createMessage(FCKMessage.FILE_UPLOAD_RESTRICTION,
412                                                     FCKMessage.ERROR,
413                                                     language,
414                                                     args);
415         return Response.ok(new DOMSource(message), MediaType.TEXT_XML)
416                        .cacheControl(cacheControl)
417                        .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
418                        .build();
419       }
420       if ((fileName == null) || (fileName.length() == 0)) {
421         fileName = resource.getFileName();
422       }
423       //add lock token
424       if(parent.isLocked()) {
425         parent.getSession().addLockToken(LockUtil.getLockToken(parent));
426       }
427       if (parent.hasNode(fileName)) {
428   //      Object args[] = { fileName, parent.getPath() };
429   //      Document fileExisted = fckMessage.createMessage(FCKMessage.FILE_EXISTED,
430   //                                                      FCKMessage.ERROR,
431   //                                                      language,
432   //                                                      args);
433   //      return Response.ok(new DOMSource(fileExisted), MediaType.TEXT_XML)
434   //                     .cacheControl(cacheControl)
435   //                     .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
436   //                     .build();
437         if (REPLACE.equals(existenceAction)) {
438           //Broadcast the event when user move node to Trash
439           ListenerService listenerService =  WCMCoreUtils.getService(ListenerService.class);
440           listenerService.broadcast(ActivityCommonService.FILE_REMOVE_ACTIVITY, parent, parent.getNode(fileName));
441           parent.getNode(fileName).remove();
442           parent.save();        
443         }
444       }
445       AutoVersionService autoVersionService = WCMCoreUtils.getService(AutoVersionService.class);
446       String location = resource.getStoreLocation();
447       //save node with name=fileName
448       Node file = null;
449       Node jcrContent=null;
450       boolean fileCreated = false;
451       String exoTitle = fileName;
452       
453       fileName = Utils.cleanNameWithAccents(fileName);
454       DMSMimeTypeResolver mimeTypeResolver = DMSMimeTypeResolver.getInstance();
455       String mimetype = mimeTypeResolver.getMimeType(resource.getFileName());
456       String nodeName = fileName;
457       int count = 0;
458       if(!CREATE_VERSION.equals(existenceAction) ||
459               (!parent.hasNode(fileName) && !CREATE_VERSION.equals(existenceAction))) {
460         if(parent.isNodeType(NodetypeConstant.NT_FILE)){
461           String mimeTypeParent = mimeTypeResolver.getMimeType(parent.getName());
462           if(mimetype != mimeTypeParent){
463             ResourceBundleService resourceBundleService = WCMCoreUtils.getService(ResourceBundleService.class);
464             ResourceBundle resourceBundle = resourceBundleService.getResourceBundle(CONNECTOR_BUNDLE_LOCATION, new Locale(language));
465             String errorMsg = resourceBundle.getString(AUTOVERSION_ERROR_MIME_TYPE);
466             errorMsg = errorMsg.replace("{0}", StringUtils.escape("<span style='font-weight:bold;'>" + parent.getName() + "</span>"));
467             JSONObject jsonObject = new JSONObject();
468             jsonObject.put("error_type", "ERROR_MIMETYPE");
469             jsonObject.put("error_message", errorMsg);
470             return Response.serverError().entity(jsonObject.toString()).build();
471           }
472           parent = parent.getParent();
473         }
474         do {
475           try {
476             file = parent.addNode(nodeName, FCKUtils.NT_FILE);
477             fileCreated = true;
478           } catch (ItemExistsException e) {//sameNameSibling is not allowed
479             nodeName = increaseName(fileName, ++count);
480           }
481         } while (!fileCreated);
482         //--------------------------------------------------------
483         if(!file.isNodeType(NodetypeConstant.MIX_REFERENCEABLE)) {
484           file.addMixin(NodetypeConstant.MIX_REFERENCEABLE);
485         }
486 
487         if(!file.isNodeType(NodetypeConstant.MIX_COMMENTABLE))
488           file.addMixin(NodetypeConstant.MIX_COMMENTABLE);
489 
490         if(!file.isNodeType(NodetypeConstant.MIX_VOTABLE))
491           file.addMixin(NodetypeConstant.MIX_VOTABLE);
492 
493         if(!file.isNodeType(NodetypeConstant.MIX_I18N))
494           file.addMixin(NodetypeConstant.MIX_I18N);
495 
496         if(!file.hasProperty(NodetypeConstant.EXO_TITLE)) {
497           file.setProperty(NodetypeConstant.EXO_TITLE, exoTitle);
498         }
499         jcrContent = file.addNode("jcr:content","nt:resource");
500       }else if(parent.hasNode(nodeName)){
501         file = parent.getNode(nodeName);
502         autoVersionService.autoVersion(file,isNewVersion);
503         jcrContent = file.hasNode("jcr:content")?file.getNode("jcr:content"):file.addNode("jcr:content","nt:resource");
504       }else if(parent.isNodeType(NodetypeConstant.NT_FILE)){
505         file = parent;
506         autoVersionService.autoVersion(file,isNewVersion);
507         jcrContent = file.hasNode("jcr:content")?file.getNode("jcr:content"):file.addNode("jcr:content","nt:resource");
508       }
509 
510       jcrContent.setProperty("jcr:lastModified", new GregorianCalendar());
511       jcrContent.setProperty("jcr:data", new BufferedInputStream(new FileInputStream(new File(location))));
512       jcrContent.setProperty("jcr:mimeType", mimetype);
513       if(fileCreated) {
514         file.getParent().save();
515         autoVersionService.autoVersion(file,isNewVersion);
516       }
517       //parent.getSession().refresh(true); // Make refreshing data
518       //parent.save();
519       uploadService.removeUploadResource(uploadId);
520       uploadIdTimeMap.remove(uploadId);
521       WCMPublicationService wcmPublicationService = WCMCoreUtils.getService(WCMPublicationService.class);
522       wcmPublicationService.updateLifecyleOnChangeContent(file, siteName, userId);
523      
524       if (activityService.isBroadcastNTFileEvents(file) && !CREATE_VERSION.equals(existenceAction)) {
525         listenerService.broadcast(ActivityCommonService.FILE_CREATED_ACTIVITY, null, file);
526       }
527       file.save();
528       return Response.ok(createDOMResponse("Result", mimetype), MediaType.TEXT_XML)
529           .cacheControl(cacheControl)
530           .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
531           .build();
532     } catch (Exception exc) {
533       LOG.error(exc.getMessage(), exc);
534       return Response.serverError().entity(exc.getMessage()).build();
535     }
536   }
537   
538   public boolean isDocumentNodeType(Node node) throws Exception {
539     TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
540     return templateService.isManagedNodeType(node.getPrimaryNodeType().getName());
541   }
542   
543   /**
544    * increase the file name (not extension).
545    * @param origin the original name
546    * @param count the number add to file name
547    * @return the new increased file name
548    */
549   private String increaseName(String origin, int count) {
550     int index = origin.indexOf('.');
551     if (index == -1) return origin + count;
552     return origin.substring(0, index) + count + origin.substring(index);
553   }
554   
555   /**
556    * get number of files uploading 
557    * @return number of files uploading
558    */
559   public long getUploadingFileCount() {
560     removeDeadUploads();
561     return uploadIdTimeMap.size();
562   }
563 
564   /**
565    * removes dead uploads
566    */
567   private void removeDeadUploads() {
568     Set<String> removedIds = new HashSet<String>();
569     for (String id : uploadIdTimeMap.keySet()) {
570       if ((System.currentTimeMillis() - uploadIdTimeMap.get(id)) > UPLOAD_LIFE_TIME * 1000) {
571         removedIds.add(id);
572       }
573     }
574     for (String id : removedIds) {
575       uploadIdTimeMap.remove(id);
576     }
577   }
578   /**
579    * Gets the progress.
580    *
581    * @param uploadId the upload id
582    *
583    * @return the progress
584    *
585    * @throws Exception the exception
586    */
587   private Document getProgress(String uploadId) throws Exception {
588     UploadResource resource = uploadService.getUploadResource(uploadId);
589     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
590     DocumentBuilder builder = factory.newDocumentBuilder();
591     Document doc = builder.newDocument();
592     Double percent = 0.0;
593     if(resource != null) {
594       if (resource.getStatus() == UploadResource.UPLOADING_STATUS) {
595         percent = (resource.getUploadedSize() * 100) / resource.getEstimatedSize();
596       } else {
597         percent = 100.0;
598       }
599     }
600     Element rootElement = doc.createElement("UploadProgress");
601     rootElement.setAttribute("uploadId", uploadId);
602     rootElement.setAttribute("fileName", resource == null ? "" : resource.getFileName());
603     rootElement.setAttribute("percent", percent.intValue() + "");
604     rootElement.setAttribute("uploadedSize", resource == null ? "0" : resource.getUploadedSize() + "");
605     rootElement.setAttribute("totalSize", resource == null ? "0" : resource.getEstimatedSize() + "");
606     rootElement.setAttribute("fileType", resource == null ? "null" : resource.getMimeType() + "");
607     UploadLimit limit = uploadService.getUploadLimits().get(uploadId);
608     if (limit != null) {
609       rootElement.setAttribute("limit", limit.getLimit() + "");
610       rootElement.setAttribute("unit", limit.getUnit() + "");
611     }
612     doc.appendChild(rootElement);
613     return doc;
614   }
615   
616   /**
617    * returns a DOMSource object containing given message
618    * @param name the message
619    * @return DOMSource object
620    * @throws Exception
621    */
622   private DOMSource createDOMResponse(String name, String mimeType) throws Exception {
623     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
624     DocumentBuilder builder = factory.newDocumentBuilder();
625     Document doc = builder.newDocument();
626     Element rootElement = doc.createElement(name);
627     rootElement.setAttribute("mimetype", mimeType);
628     doc.appendChild(rootElement);
629     return new DOMSource(doc);
630   }
631   
632 }