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