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