001/* 002 * (C) Copyright 2006-2013 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Andreas Kalogeropoulos 016 * Anahide Tchertchian 017 * Thierry Delprat 018 * Florent Guillaume 019 */ 020package org.nuxeo.ecm.webapp.filemanager; 021 022import java.io.File; 023import java.io.FileNotFoundException; 024import java.io.IOException; 025import java.io.InputStream; 026import java.util.ArrayList; 027import java.util.Collection; 028import java.util.HashMap; 029import java.util.List; 030import java.util.Map; 031 032import javax.faces.context.ExternalContext; 033import javax.faces.context.FacesContext; 034import javax.faces.event.ActionEvent; 035 036import org.apache.commons.collections.CollectionUtils; 037import org.apache.commons.io.FilenameUtils; 038import org.apache.commons.lang.StringUtils; 039import org.apache.commons.logging.Log; 040import org.apache.commons.logging.LogFactory; 041import org.jboss.seam.ScopeType; 042import org.jboss.seam.annotations.In; 043import org.jboss.seam.annotations.Install; 044import org.jboss.seam.annotations.Name; 045import org.jboss.seam.annotations.Scope; 046import org.jboss.seam.annotations.remoting.WebRemote; 047import org.jboss.seam.core.Events; 048import org.jboss.seam.faces.FacesMessages; 049import org.jboss.seam.international.StatusMessage; 050import org.nuxeo.common.utils.Base64; 051import org.nuxeo.ecm.core.api.Blob; 052import org.nuxeo.ecm.core.api.Blobs; 053import org.nuxeo.ecm.core.api.CoreSession; 054import org.nuxeo.ecm.core.api.DocumentModel; 055import org.nuxeo.ecm.core.api.DocumentRef; 056import org.nuxeo.ecm.core.api.IdRef; 057import org.nuxeo.ecm.core.api.NuxeoException; 058import org.nuxeo.ecm.core.api.RecoverableClientException; 059import org.nuxeo.ecm.core.api.impl.blob.FileBlob; 060import org.nuxeo.ecm.core.api.security.SecurityConstants; 061import org.nuxeo.ecm.core.schema.FacetNames; 062import org.nuxeo.ecm.platform.filemanager.api.FileManager; 063import org.nuxeo.ecm.platform.types.TypeManager; 064import org.nuxeo.ecm.platform.ui.web.api.NavigationContext; 065import org.nuxeo.ecm.platform.ui.web.api.UserAction; 066import org.nuxeo.ecm.platform.ui.web.util.files.FileUtils; 067import org.nuxeo.ecm.platform.web.common.exceptionhandling.ExceptionHelper; 068import org.nuxeo.ecm.webapp.clipboard.ClipboardActions; 069import org.nuxeo.ecm.webapp.contentbrowser.DocumentActions; 070import org.nuxeo.ecm.webapp.helpers.EventManager; 071import org.nuxeo.ecm.webapp.helpers.EventNames; 072import org.nuxeo.runtime.api.Framework; 073import org.richfaces.event.FileUploadEvent; 074import org.richfaces.model.UploadedFile; 075 076@Name("FileManageActions") 077@Scope(ScopeType.EVENT) 078@Install(precedence = Install.FRAMEWORK) 079public class FileManageActionsBean implements FileManageActions { 080 081 private static final Log log = LogFactory.getLog(FileManageActionsBean.class); 082 083 public static final String TRANSF_ERROR = "TRANSF_ERROR"; 084 085 public static final String SECURITY_ERROR = "SECURITY_ERROR"; 086 087 public static final String MOVE_ERROR = "MOVE_ERROR"; 088 089 public static final String COPY_ERROR = "COPY_ERROR"; 090 091 public static final String PASTE_ERROR = "PASTE_ERROR"; 092 093 public static final String MOVE_IMPOSSIBLE = "MOVE_IMPOSSIBLE"; 094 095 public static final String MOVE_PUBLISH = "MOVE_PUBLISH"; 096 097 public static final String MOVE_OK = "MOVE_OK"; 098 099 protected static final String FILES_SCHEMA = "files"; 100 101 protected static final String FILES_PROPERTY = FILES_SCHEMA + ":files"; 102 103 // TODO NXP-13568: this should not be hardcoded on the doc type 104 protected static final String SECTION_DOCTYPE = "Section"; 105 106 @In(create = true, required = false) 107 protected CoreSession documentManager; 108 109 @In(create = true) 110 protected TypeManager typeManager; 111 112 @In(create = true) 113 protected NavigationContext navigationContext; 114 115 @In(create = true) 116 protected transient DocumentActions documentActions; 117 118 @In(create = true) 119 protected ClipboardActions clipboardActions; 120 121 @In(create = true, required = false) 122 protected UploadItemHolder fileUploadHolder; 123 124 @In(create = true, required = false) 125 protected UploadItemHolderCycleManager fileUploadHolderCycle; 126 127 /** 128 * Helper field to get the filename to remove. 129 * 130 * @since 5.9.2 131 */ 132 protected String fileToRemove; 133 134 @In(create = true, required = false) 135 protected FacesMessages facesMessages; 136 137 @In(create = true) 138 protected Map<String, String> messages; 139 140 protected FileManager fileManager; 141 142 /** 143 * Used to keep track of the path of the uploaded file (NXP-16745) 144 */ 145 protected List<String> tmpFilePaths = new ArrayList<String>(); 146 147 protected FileManager getFileManagerService() { 148 if (fileManager == null) { 149 fileManager = Framework.getService(FileManager.class); 150 } 151 return fileManager; 152 } 153 154 @Override 155 public String display() { 156 return "view_documents"; 157 } 158 159 /** 160 * Creates a document from the file held in the fileUploadHolder. Takes responsibility for the fileUploadHolder 161 * temporary file. 162 */ 163 @Override 164 public String addFile() { 165 NxUploadedFile uploadedFile = fileUploadHolder.getUploadedFiles().iterator().next(); 166 Blob blob = uploadedFile.getBlob(); 167 if (blob == null || blob.getFilename() == null) { 168 facesMessages.add(StatusMessage.Severity.ERROR, messages.get("fileImporter.error.nullUploadedFile")); 169 return navigationContext.getActionResult(navigationContext.getCurrentDocument(), UserAction.AFTER_CREATE); 170 } 171 FileUtils.configureFileBlob(blob); 172 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 173 String path = currentDocument.getPathAsString(); 174 DocumentModel createdDoc = null; 175 try { 176 createdDoc = getFileManagerService().createDocumentFromBlob(documentManager, blob, path, true, 177 blob.getFilename()); 178 } catch (IOException e) { 179 throw new NuxeoException("Can not write blob for" + blob.getFilename(), e); 180 } 181 EventManager.raiseEventsOnDocumentSelected(createdDoc); 182 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, currentDocument); 183 184 facesMessages.add(StatusMessage.Severity.INFO, messages.get("document_saved"), 185 messages.get(createdDoc.getType())); 186 return navigationContext.getActionResult(createdDoc, UserAction.AFTER_CREATE); 187 } 188 189 @Override 190 @Deprecated 191 // TODO: update the Seam remoting-based desktop plugins to stop calling 192 // this method 193 @WebRemote 194 public boolean canWrite() { 195 // let the FolderImporter and FileImporter plugin handle the security 196 // checks to avoid hardcoded behavior 197 return true; 198 } 199 200 protected String getErrorMessage(String errorType, String errorInfo) { 201 return getErrorMessage(errorType, errorInfo, "message.operation.fails.generic"); 202 } 203 204 protected String getErrorMessage(String errorType, String errorInfo, String errorLabel) { 205 return String.format("%s |(%s)| %s", errorType, errorInfo, messages.get(errorLabel)); 206 } 207 208 /** 209 * @deprecated use addBinaryFileFromPlugin with a Blob argument API to avoid loading the content in memory 210 */ 211 @Override 212 @Deprecated 213 @WebRemote 214 public String addFileFromPlugin(String content, String mimetype, String fullName, String morePath, 215 Boolean UseBase64) { 216 byte[] bcontent; 217 if (UseBase64.booleanValue()) { 218 bcontent = Base64.decode(content); 219 } else { 220 bcontent = content.getBytes(); 221 } 222 return addBinaryFileFromPlugin(bcontent, mimetype, fullName, morePath); 223 } 224 225 @Override 226 @WebRemote 227 public String addBinaryFileFromPlugin(Blob blob, String fullName, String morePath) { 228 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 229 String curPath = currentDocument.getPathAsString(); 230 231 String path = curPath + morePath; 232 return createDocumentFromBlob(blob, fullName, path); 233 } 234 235 @Override 236 @WebRemote 237 public String addBinaryFileFromPlugin(Blob blob, String fullName, DocumentModel targetContainer) 238 { 239 return createDocumentFromBlob(blob, fullName, targetContainer.getPathAsString()); 240 } 241 242 protected String createDocumentFromBlob(Blob blob, String fullName, String path) { 243 DocumentModel createdDoc; 244 try { 245 createdDoc = getFileManagerService().createDocumentFromBlob(documentManager, blob, path, true, fullName); 246 } catch (NuxeoException | IOException t) { 247 Throwable unwrappedError = ExceptionHelper.unwrapException(t); 248 if (ExceptionHelper.isSecurityError(unwrappedError)) { 249 // security check failed 250 log.debug("No permissions creating " + fullName); 251 return getErrorMessage(SECURITY_ERROR, fullName, "Error.Insuffisant.Rights"); 252 } else { 253 // log error stack trace for server side debugging while giving 254 // a generic and localized error message to the client 255 log.error("Error importing " + fullName, t); 256 return getErrorMessage(TRANSF_ERROR, fullName); 257 } 258 } 259 if (createdDoc == null) { 260 log.error("could not create the document " + fullName); 261 return getErrorMessage(TRANSF_ERROR, fullName); 262 } 263 // update the context, raise events to update the seam context 264 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 265 if (currentDocument.getRef().equals(createdDoc.getRef())) { 266 navigationContext.updateDocumentContext(createdDoc); 267 } 268 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, currentDocument); 269 EventManager.raiseEventsOnDocumentSelected(createdDoc); 270 return createdDoc.getName(); 271 } 272 273 /** 274 * @deprecated Use addBinaryFileFromPlugin(Blob, String, String) to avoid loading the data in memory as a Bytes 275 * array 276 */ 277 @Deprecated 278 public String addBinaryFileFromPlugin(byte[] content, String mimetype, String fullName, String morePath) 279 { 280 Blob blob = Blobs.createBlob(content); 281 return addBinaryFileFromPlugin(blob, fullName, morePath); 282 } 283 284 @Override 285 @WebRemote 286 public String addFolderFromPlugin(String fullName, String morePath) { 287 try { 288 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 289 290 String curPath = currentDocument.getPathAsString(); 291 if (!currentDocument.isFolder()) { 292 curPath = curPath.substring(0, curPath.lastIndexOf('/')); 293 } 294 String path = curPath + morePath; 295 296 DocumentModel createdDoc; 297 try { 298 createdDoc = getFileManagerService().createFolder(documentManager, fullName, path); 299 } catch (NuxeoException | IOException t) { 300 Throwable unwrappedError = ExceptionHelper.unwrapException(t); 301 if (ExceptionHelper.isSecurityError(unwrappedError)) { 302 // security check failed 303 log.debug("No permissions creating folder " + fullName); 304 return getErrorMessage(SECURITY_ERROR, fullName, "Error.Insuffisant.Rights"); 305 } else { 306 log.error("Couldn't create the folder " + fullName); 307 return getErrorMessage(TRANSF_ERROR, fullName); 308 } 309 } 310 311 if (createdDoc == null) { 312 log.error("Couldn't create the folder " + fullName); 313 return getErrorMessage(TRANSF_ERROR, fullName); 314 } 315 316 EventManager.raiseEventsOnDocumentSelected(createdDoc); 317 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, currentDocument); 318 return createdDoc.getName(); 319 } catch (RecoverableClientException e) { 320 throw e; 321 } catch (NuxeoException e) { 322 throw new RecoverableClientException("Cannot validate, caught exception", "error.db.fs", null, e); 323 } 324 } 325 326 @WebRemote 327 protected String checkMoveAllowed(DocumentRef docRef, DocumentRef containerRef) { 328 329 DocumentModel doc = documentManager.getDocument(docRef); 330 DocumentModel container = documentManager.getDocument(containerRef); 331 332 // check that we are not trying to move a folder inside itself 333 334 if ((container.getPathAsString() + "/").startsWith(doc.getPathAsString() + "/")) { 335 facesMessages.add(StatusMessage.Severity.WARN, messages.get("move_impossible")); 336 return MOVE_IMPOSSIBLE; 337 } 338 if (!doc.isProxy() && container.hasFacet(FacetNames.PUBLISH_SPACE) && !doc.hasFacet(FacetNames.PUBLISH_SPACE)) { 339 // we try to do a publication check browse in sections 340 if (!documentManager.hasPermission(containerRef, SecurityConstants.ADD_CHILDREN)) { 341 // only publish via D&D if this can be done directly (no wf) 342 // => need to have write access 343 facesMessages.add(StatusMessage.Severity.WARN, messages.get("move_insuffisant_rights")); 344 // TODO: this should be PUBLISH_IMPOSSIBLE 345 return MOVE_IMPOSSIBLE; 346 } 347 348 if (doc.hasFacet(FacetNames.PUBLISHABLE)) { 349 return MOVE_PUBLISH; 350 } else { 351 facesMessages.add(StatusMessage.Severity.WARN, messages.get("publish_impossible")); 352 // TODO: this should be PUBLISH_IMPOSSIBLE 353 return MOVE_IMPOSSIBLE; 354 } 355 } 356 // this is a real move operation (not a publication) 357 358 // check the right to remove the document from the source container 359 if (!documentManager.hasPermission(doc.getParentRef(), SecurityConstants.REMOVE_CHILDREN) 360 || !documentManager.hasPermission(doc.getRef(), SecurityConstants.REMOVE)) { 361 facesMessages.add(StatusMessage.Severity.WARN, messages.get("move_impossible")); 362 return MOVE_IMPOSSIBLE; 363 } 364 365 // check that we have the right to create the copy in the target 366 if (!documentManager.hasPermission(containerRef, SecurityConstants.ADD_CHILDREN)) { 367 facesMessages.add(StatusMessage.Severity.WARN, messages.get("move_insuffisant_rights")); 368 return MOVE_IMPOSSIBLE; 369 } 370 371 if (doc.isProxy()) { 372 if (!container.hasFacet(FacetNames.PUBLISH_SPACE)) { 373 // do not allow to move a published document back in a 374 // workspace 375 facesMessages.add(StatusMessage.Severity.WARN, messages.get("move_impossible")); 376 return MOVE_IMPOSSIBLE; 377 } 378 } else { 379 // check allowed content types constraints for non-proxy documents 380 if (!typeManager.isAllowedSubType(doc.getType(), container.getType(), container)) { 381 facesMessages.add(StatusMessage.Severity.WARN, messages.get("move_impossible")); 382 return MOVE_IMPOSSIBLE; 383 } 384 } 385 386 return MOVE_OK; 387 } 388 389 @Override 390 @WebRemote 391 public String moveWithId(String docId, String containerId) { 392 try { 393 String debug = "move " + docId + " into " + containerId; 394 log.debug(debug); 395 if (docId.startsWith("docRef:")) { 396 docId = docId.split("docRef:")[1]; 397 } 398 if (docId.startsWith("docClipboardRef:")) { 399 docId = docId.split("docClipboardRef:")[1]; 400 } 401 DocumentRef srcRef = new IdRef(docId); 402 String dst = containerId; 403 if (dst.startsWith("docRef:")) { 404 dst = dst.split("docRef:")[1]; 405 } 406 if (dst.startsWith("nodeRef:")) { 407 dst = dst.split("nodeRef:")[1]; 408 } 409 DocumentRef dstRef = new IdRef(dst); 410 411 String moveStatus = checkMoveAllowed(srcRef, dstRef); 412 413 if (moveStatus.equals(MOVE_IMPOSSIBLE)) { 414 return debug; 415 } 416 417 String action = "document_moved"; 418 419 if (moveStatus.equals(MOVE_PUBLISH)) { 420 DocumentModel srcDoc = documentManager.getDocument(srcRef); 421 DocumentModel dstDoc = documentManager.getDocument(dstRef); 422 documentManager.publishDocument(srcDoc, dstDoc); 423 action = "document_published"; 424 } else { 425 documentManager.move(srcRef, dstRef, null); 426 } 427 428 // delCopyWithId(docId); 429 documentManager.save(); 430 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 431 EventManager.raiseEventsOnDocumentChildrenChange(currentDocument); 432 433 // notify current container 434 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, currentDocument); 435 // notify the other container 436 DocumentModel otherContainer = documentManager.getDocument(dstRef); 437 Events.instance().raiseEvent(EventNames.DOCUMENT_CHILDREN_CHANGED, otherContainer); 438 439 facesMessages.add(StatusMessage.Severity.INFO, messages.get(action), 440 messages.get(documentManager.getDocument(srcRef).getType())); 441 442 return debug; 443 } catch (RecoverableClientException e) { 444 throw e; 445 } catch (NuxeoException e) { 446 throw new RecoverableClientException("Cannot validate, caught exception", "message.operation.fails.generic", 447 null, e); 448 } 449 } 450 451 @Override 452 @WebRemote 453 public String copyWithId(String docId) { 454 try { 455 String debug = "copying " + docId; 456 log.debug(debug); 457 if (docId.startsWith("docRef:")) { 458 docId = docId.split("docRef:")[1]; 459 } 460 if (docId.startsWith("docClipboardRef:")) { 461 docId = docId.split("docClipboardRef:")[1]; 462 } 463 DocumentRef srcRef = new IdRef(docId); 464 DocumentModel srcDoc = documentManager.getDocument(srcRef); 465 List<DocumentModel> docsToAdd = new ArrayList<DocumentModel>(); 466 docsToAdd.add(srcDoc); 467 clipboardActions.putSelectionInWorkList(docsToAdd, Boolean.TRUE); 468 return debug; 469 } catch (RecoverableClientException e) { 470 throw e; 471 } catch (NuxeoException e) { 472 throw new RecoverableClientException("Cannot validate, caught exception", "message.operation.fails.generic", 473 null, e); 474 } 475 476 } 477 478 @Override 479 @WebRemote 480 public String pasteWithId(String docId) { 481 try { 482 String debug = "pasting " + docId; 483 log.debug(debug); 484 if (docId.startsWith("pasteRef_")) { 485 docId = docId.split("pasteRef_")[1]; 486 } 487 if (docId.startsWith("docClipboardRef:")) { 488 docId = docId.split("docClipboardRef:")[1]; 489 } 490 DocumentRef srcRef = new IdRef(docId); 491 DocumentModel srcDoc = documentManager.getDocument(srcRef); 492 List<DocumentModel> pasteDocs = new ArrayList<DocumentModel>(); 493 pasteDocs.add(srcDoc); 494 clipboardActions.pasteDocumentList(pasteDocs); 495 return debug; 496 } catch (RecoverableClientException e) { 497 throw e; 498 } catch (NuxeoException e) { 499 throw new RecoverableClientException("Cannot validate, caught exception", "message.operation.fails.generic", 500 null, e); 501 } 502 } 503 504 public void processUpload(FileUploadEvent uploadEvent) { 505 try { 506 if (fileUploadHolder != null) { 507 FileBlob blob = getBlob(uploadEvent); 508 tmpFilePaths.add(blob.getFile().getPath()); 509 fileUploadHolder.getUploadedFiles().add(new NxUploadedFile(blob)); 510 } else { 511 log.error("Unable to reach fileUploadHolder"); 512 } 513 } catch (IOException e) { 514 log.error(e, e); 515 } 516 } 517 518 protected static String getJSFUploadTmpDirPath() { 519 String jstTmpFileDir = Framework.getProperty(NUXEO_JSF_TMP_DIR_PROP); 520 if (StringUtils.isBlank(jstTmpFileDir)) { 521 jstTmpFileDir = null; 522 } 523 return jstTmpFileDir; 524 } 525 526 public static FileBlob getBlob(FileUploadEvent uploadEvent) throws IOException { 527 // copy to a temporary file we own 528 // TODO check how we can reuse RichFaces' temporary file 529 String jstTmpFileDir = getJSFUploadTmpDirPath(); 530 File tmpDir = null; 531 if (jstTmpFileDir != null) { 532 tmpDir = new File(jstTmpFileDir); 533 } 534 UploadedFile uploadedFile = uploadEvent.getUploadedFile(); 535 try (InputStream in = uploadedFile.getInputStream()) { 536 FileBlob blob = new FileBlob(in, uploadedFile.getContentType(), null, tmpDir); 537 blob.setFilename(uploadedFile.getName()); 538 return blob; 539 } 540 } 541 542 public void validateMultiplesUpload() throws FileNotFoundException, IOException { 543 DocumentModel current = navigationContext.getCurrentDocument(); 544 validateMultipleUploadForDocument(current); 545 } 546 547 @SuppressWarnings({ "unchecked", "rawtypes" }) 548 public void validateMultipleUploadForDocument(DocumentModel current) throws FileNotFoundException, 549 IOException { 550 if (!current.hasSchema(FILES_SCHEMA)) { 551 return; 552 } 553 Collection<NxUploadedFile> nxuploadFiles = getUploadedFiles(); 554 try { 555 ArrayList files = (ArrayList) current.getPropertyValue(FILES_PROPERTY); 556 if (nxuploadFiles != null) { 557 for (NxUploadedFile uploadItem : nxuploadFiles) { 558 Blob blob = uploadItem.getBlob(); 559 FileUtils.configureFileBlob(blob); 560 HashMap<String, Object> fileMap = new HashMap<String, Object>(2); 561 fileMap.put("file", blob); 562 fileMap.put("filename", blob.getFilename()); 563 if (!files.contains(fileMap)) { 564 files.add(fileMap); 565 } 566 } 567 } 568 current.setPropertyValue(FILES_PROPERTY, files); 569 documentActions.updateDocument(current, Boolean.TRUE); 570 } finally { 571 if (nxuploadFiles != null) { 572 for (NxUploadedFile uploadItem : nxuploadFiles) { 573 File tempFile = uploadItem.getFile(); 574 // Tmp file that have been moved are assumed to not be temporary anymore 575 if (tempFile != null && tempFile.exists() && tmpFilePaths.contains(tempFile.getPath())) { 576 Framework.trackFile(tempFile, tempFile); 577 } 578 } 579 } 580 tmpFilePaths.clear(); 581 } 582 } 583 584 @SuppressWarnings({ "rawtypes" }) 585 public void performAction(ActionEvent event) { 586 FacesContext context = FacesContext.getCurrentInstance(); 587 ExternalContext eContext = context.getExternalContext(); 588 String index = eContext.getRequestParameterMap().get("index"); 589 590 try { 591 DocumentModel current = navigationContext.getCurrentDocument(); 592 if (!current.hasSchema(FILES_SCHEMA)) { 593 return; 594 } 595 ArrayList files = (ArrayList) current.getPropertyValue(FILES_PROPERTY); 596 Object file = CollectionUtils.get(files, Integer.valueOf(index).intValue()); 597 files.remove(file); 598 current.setPropertyValue(FILES_PROPERTY, files); 599 documentActions.updateDocument(current, Boolean.TRUE); 600 } catch (IndexOutOfBoundsException | NuxeoException e) { 601 log.error(e, e); 602 throw e; 603 } 604 } 605 606 public String validate() { 607 608 NxUploadedFile uploadedFile; 609 if (fileUploadHolder == null || fileUploadHolder.getUploadedFiles().isEmpty() 610 || (uploadedFile = fileUploadHolder.getUploadedFiles().iterator().next()) == null) { 611 facesMessages.add(StatusMessage.Severity.ERROR, messages.get("fileImporter.error.nullUploadedFile")); 612 return null; 613 } 614 try { 615 return addFile(); 616 } catch (RecoverableClientException e) { 617 throw e; 618 } catch (NuxeoException e) { 619 throw new RecoverableClientException("Cannot validate, caught exception", "message.operation.fails.generic", 620 null, e); 621 } finally { 622 if (uploadedFile != null && uploadedFile.getFile().exists()) { 623 Framework.trackFile(uploadedFile.getFile(), uploadedFile.getFile()); 624 } 625 } 626 } 627 628 @Override 629 public InputStream getFileUpload() { 630 if (fileUploadHolder != null) { 631 return fileUploadHolder.getFileUpload(); 632 } else { 633 return null; 634 } 635 } 636 637 @Override 638 public void setFileUpload(InputStream fileUpload) { 639 if (fileUploadHolder != null) { 640 fileUploadHolder.setFileUpload(fileUpload); 641 } 642 } 643 644 @Override 645 public String getFileName() { 646 if (fileUploadHolder != null) { 647 return fileUploadHolder.getFileName(); 648 } 649 return null; 650 } 651 652 @Override 653 public void setFileName(String fileName) { 654 if (fileUploadHolder != null) { 655 fileUploadHolder.setFileName(fileName); 656 } 657 } 658 659 public DocumentModel getChangeableDocument() { 660 return navigationContext.getChangeableDocument(); 661 } 662 663 public void setChangeableDocument(DocumentModel changeableDocument) { 664 navigationContext.setChangeableDocument(changeableDocument); 665 } 666 667 public Collection<NxUploadedFile> getUploadedFiles() { 668 if (fileUploadHolder != null) { 669 return fileUploadHolder.getUploadedFiles(); 670 } else { 671 return null; 672 } 673 } 674 675 public void setUploadedFiles(Collection<NxUploadedFile> uploadedFiles) { 676 if (fileUploadHolder != null) { 677 fileUploadHolder.setUploadedFiles(uploadedFiles); 678 } 679 tmpFilePaths.clear(); 680 if (uploadedFiles != null) { 681 for (NxUploadedFile file : uploadedFiles) { 682 tmpFilePaths.add(file.getFile().getPath()); 683 } 684 } 685 } 686 687 @Override 688 @WebRemote 689 public String removeSingleUploadedFile() { 690 return removeAllUploadedFile(); 691 } 692 693 @Override 694 public void setFileToRemove(String fileToRemove) { 695 this.fileToRemove = fileToRemove; 696 } 697 698 @Override 699 public String removeOneOrAllUploadedFiles(ActionEvent action) { 700 if (StringUtils.isBlank(fileToRemove)) { 701 return removeAllUploadedFile(); 702 } else { 703 return removeUploadedFile(fileToRemove); 704 } 705 } 706 707 @Override 708 @WebRemote 709 public String removeAllUploadedFile() { 710 if (fileUploadHolder != null) { 711 Collection<NxUploadedFile> files = getUploadedFiles(); 712 if (files != null) { 713 for (NxUploadedFile item : files) { 714 item.getFile().delete(); 715 } 716 } 717 setUploadedFiles(new ArrayList<NxUploadedFile>()); 718 } 719 return ""; 720 } 721 722 @Override 723 @WebRemote 724 public String removeUploadedFile(String fileName) { 725 NxUploadedFile fileToDelete = null; 726 727 // Retrieve only the real filename 728 // IE stores the full path of the file as the filename (ie. 729 // Z:\\path\\to\\file) 730 fileName = FilenameUtils.getName(fileName); 731 Collection<NxUploadedFile> files = getUploadedFiles(); 732 if (files != null) { 733 for (NxUploadedFile file : files) { 734 String uploadedFileName = file.getName(); 735 if (fileName.equals(uploadedFileName)) { 736 fileToDelete = file; 737 break; 738 } 739 } 740 } 741 if (fileToDelete != null) { 742 fileToDelete.getFile().delete(); 743 files.remove(fileToDelete); 744 setUploadedFiles(files); 745 } 746 return ""; 747 } 748 749}