Java tutorial
/* ############################################################################### # # # Copyright (C) 2011-2012 OpenMEAP, Inc. # # Credits to Jonathan Schang & Robert Thacher # # # # Released under the LGPLv3 # # # # OpenMEAP is free software: you can redistribute it and/or modify # # it under the terms of the GNU Lesser General Public License as published # # by the Free Software Foundation, either version 3 of the License, or # # (at your option) any later version. # # # # OpenMEAP is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU Lesser General Public License for more details. # # # # You should have received a copy of the GNU Lesser General Public License # # along with OpenMEAP. If not, see <http://www.gnu.org/licenses/>. # # # ############################################################################### */ package com.openmeap.file; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.commons.transaction.file.FileResourceManager; import org.apache.commons.transaction.file.ResourceManagerException; import org.apache.commons.transaction.file.ResourceManagerSystemException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.openmeap.model.ModelManager; import com.openmeap.model.ModelService; import com.openmeap.model.dto.GlobalSettings; import com.openmeap.util.SLF4JLoggerFacade; import com.openmeap.util.Utils; /** * FileOperationManager for transaction safe file operations. * Essentially just a thin-wrapper over org.apache.commons.transaction.file * * @author schang */ public class FileOperationManagerImpl implements FileOperationManager { Logger logger = LoggerFactory.getLogger(FileOperationManagerImpl.class); ModelService modelService; FileResourceManager fileResourceManager; Map<Thread, Object> activeTransactions = Collections.synchronizedMap(new HashMap<Thread, Object>()); public void setFileResourceManager(FileResourceManager fileResourceManager) { this.fileResourceManager = fileResourceManager; } public void setModelService(ModelService modelService) { this.modelService = modelService; } @Override public void deleteDir(String path) throws FileOperationException { String storeDir = this.fileResourceManager.getStoreDir(); String workDir = this.fileResourceManager.getWorkDir(); _deleteDir(storeDir, storeDir + File.separator + path); _deleteDir(workDir, workDir + File.separator + path); delete(path); } @Override public void delete(String path) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); logger.trace("Marking delete for {}", path); try { fileResourceManager.deleteResource(txId, path, true); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public boolean exists(String path) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); try { return fileResourceManager.resourceExists(txId, path) || new File(fileResourceManager.getStoreDir() + File.separator + path).exists(); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public void create(String path) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); try { fileResourceManager.createResource(txId, path, false); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public void copy(String src, String dest) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); try { fileResourceManager.copyResource(txId, src, dest, false); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public void move(String src, String dest) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); try { fileResourceManager.moveResource(txId, src, dest, false); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public InputStream read(String path) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); try { return fileResourceManager.readResource(txId, path); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public OutputStream write(String path) throws FileOperationException { Object txId = activeTransactions.get(Thread.currentThread()); try { return fileResourceManager.writeResource(txId, path); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public void begin() throws FileOperationException { _setup(); Object txId; try { fileResourceManager.start(); txId = fileResourceManager.generatedUniqueTxId(); fileResourceManager.startTransaction(txId); } catch (ResourceManagerSystemException e) { throw new FileOperationException(e); } catch (ResourceManagerException e) { throw new FileOperationException(e); } activeTransactions.put(Thread.currentThread(), txId); } @Override public void commit() throws FileOperationException { try { fileResourceManager.commitTransaction(activeTransactions.get(Thread.currentThread())); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public void rollback() throws FileOperationException { try { fileResourceManager.rollbackTransaction(activeTransactions.get(Thread.currentThread())); } catch (ResourceManagerException e) { throw new FileOperationException(e); } } @Override public void unzipFile(ZipFile zipFile, String destinationDir) throws FileOperationException { try { int BUFFER = 1024; BufferedOutputStream dest = null; BufferedInputStream is = null; OutputStream fos = null; ZipEntry entry; Enumeration e = zipFile.entries(); while (e.hasMoreElements()) { try { entry = (ZipEntry) e.nextElement(); is = new BufferedInputStream(zipFile.getInputStream(entry)); String newFile = destinationDir + File.separator + entry.getName(); if (entry.isDirectory()) { continue; // skip directories, resource manager will create for us } else { fos = write(newFile); dest = new BufferedOutputStream(fos, BUFFER); Utils.pipeInputStreamIntoOutputStream(is, dest); } } finally { if (dest != null) { dest.close(); } if (fos != null) { fos.close(); } if (is != null) { is.close(); } } } } catch (IOException ioe) { throw new FileOperationException(ioe); } } private void _deleteDir(String prefix, String absolutePath) throws FileOperationException { File absFile = new File(absolutePath); String absPath = absFile.getAbsolutePath(); String superPrefix = absFile.getAbsolutePath().substring(0, absPath.length() - absolutePath.length() - 1); if (absFile.exists() && absFile.isDirectory()) { File[] files = absFile.listFiles(); if (files == null) { return; } for (File thisFile : files) { String fullPath = thisFile.getAbsolutePath(); String relativePath = fullPath.substring(superPrefix.length() + prefix.length() + 2); if (thisFile.isDirectory()) { _deleteDir(prefix, prefix + File.separator + relativePath); } else { delete(relativePath); } } } } private void _setup() throws FileOperationException { if (fileResourceManager != null) { return; } GlobalSettings settings = (GlobalSettings) modelService.findByPrimaryKey(GlobalSettings.class, 1L); if (settings.getTemporaryStoragePath() == null || !new File(settings.getTemporaryStoragePath()).exists()) { String msg = "The storage path has not been set in GlobalSettings. Use the settings page to fix this."; logger.error(msg); throw new FileOperationException(msg); } FileResourceManager resMgr = new FileResourceManager(settings.getTemporaryStoragePath(), settings.getTemporaryStoragePath() + "/tmp", false, new SLF4JLoggerFacade(LoggerFactory.getLogger(FileResourceManager.class))); fileResourceManager = resMgr; } @Override public boolean isTransactionActive() throws FileOperationException { return activeTransactions.get(Thread.currentThread()) != null; } }