/** * Copyright (C) 2012 Red Hat, Inc. and/or its affiliates * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jbpm.document.service.impl; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.jbpm.document.Document; import org.jbpm.document.service.DocumentStorageService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This a Sample Implementation of the DocumentStorageService saves the uploaded files on the File System on a folder (by default /docs) * and return the complete path to the file that will be stored in the form field property. * * Check that the user that is running the app has write permissions on the storage folder. */ public class DocumentStorageServiceImpl implements DocumentStorageService { private Logger log = LoggerFactory.getLogger(DocumentStorageServiceImpl.class); /** * This is the root folder where the files are going to be stored, please check that the user that is running the app has permissions to read/write inside */ private String storagePath = System.getProperty("org.jbpm.document.storage", ".docs"); private File storageFile; public DocumentStorageServiceImpl( String storagePath ) { this.storagePath = storagePath; this.storageFile = new File(storagePath); } public DocumentStorageServiceImpl() { this.storageFile = new File(this.storagePath); } @Override public Document buildDocument( String name, long size, Date lastModified, Map<String, String> params ) { String identifier = generateUniquePath(); String appURL = params.get("app.url"); if (appURL == null) appURL = ""; if (!appURL.isEmpty() && !appURL.endsWith("/")) appURL += "/"; // Generating a default download link, don't use this donwloader in real environments use it as an example String link = appURL + "Controller?_fb=fdch&_fp=download&content=" + identifier; return new DocumentImpl( identifier, name, size, lastModified, link ); } @Override public Document saveDocument(Document document, byte[] content) { if (StringUtils.isEmpty(document.getIdentifier())) { document.setIdentifier(generateUniquePath()); } File destination = getFileByPath( document.getIdentifier() + File.separator + document.getName() ); try { FileUtils.writeByteArrayToFile(destination, content); destination.getParentFile().setLastModified(document.getLastModified().getTime()); destination.setLastModified(document.getLastModified().getTime()); } catch (IOException e) { log.error("Error writing file {}: {}", document.getName(), e); } return document; } @Override public Document getDocument(String id) { File file = getFileByPath( id ); if (file.exists() && !file.isFile() && !ArrayUtils.isEmpty(file.listFiles())) { try { File destination = file.listFiles()[0]; Document doc = new DocumentImpl(id, destination.getName(), destination.length(), new Date(destination.lastModified())); doc.setContent(FileUtils.readFileToByteArray(destination)); return doc; } catch (IOException e) { log.error("Error loading document '{}': {}", id, e); } } return null; } @Override public boolean deleteDocument(String id) { if (StringUtils.isEmpty(id)) return true; return deleteDocument(getDocument(id)); } @Override public boolean deleteDocument(Document doc) { if (doc != null) { File rootDoc = getDocumentContent(doc); if (!ArrayUtils.isEmpty( rootDoc.listFiles() )) return deleteFile( rootDoc.listFiles()[0] ); return deleteFile(rootDoc); } return true; } public File getDocumentContent(Document doc) { if (doc != null) { return getFileByPath( doc.getIdentifier() ); } return null; } protected boolean deleteFile(File file) { try { if (file != null) { if (file.isFile()) { file.delete(); return deleteFile(file.getParentFile()); } else { if (!file.getName().equals(storagePath)) { String[] list = file.list(); if (list == null || list.length == 0) { file.delete(); return deleteFile(file.getParentFile()); } } } } } catch (Exception e) { log.error("Error deleting file: ", e); return false; } return true; } /** * Generates a random path to store the file to avoid overwritting files with the same name * @return A String containging the path where the document is going to be stored. */ protected String generateUniquePath() { File parent; String destinationPath; do { destinationPath = UUID.randomUUID().toString(); parent = getFileByPath( destinationPath ); } while ( parent.exists() ); return destinationPath; } protected File getFileByPath( String path ) { return new File( storagePath + File.separator + path ); } @Override public List<Document> listDocuments(Integer page, Integer pageSize) { List<Document> listOfDocs = new ArrayList<Document>(); int startIndex = page * pageSize; int endIndex = startIndex + pageSize; File[] documents = storageFile.listFiles(); // make sure the endIndex is not bigger then amount of files if (documents.length < endIndex) { endIndex = documents.length; } Arrays.sort(documents, new Comparator<File>() { public int compare(File f1, File f2) { return Long.compare(f1.lastModified(), f2.lastModified()); } }); for (int i = startIndex; i < endIndex; i++) { Document doc = getDocument(documents[i].getName()); listOfDocs.add(doc); } return listOfDocs; } }