/*
* Copyright 2012-2016 Luca Zanconato
*
* 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 net.nharyes.drivecopy.biz.wfm;
import com.google.inject.Singleton;
import net.nharyes.drivecopy.biz.bo.DirectoryBO;
import net.nharyes.drivecopy.biz.exc.WorkflowManagerException;
import java.io.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@Singleton
public class DirectoryCompressorWorkflowManagerImpl extends BaseWorkflowManager<DirectoryBO> implements DirectoryCompressorWorkflowManager {
/*
* Constants
*/
private final int BUFFER = 2048;
public DirectoryBO handleWorkflow(DirectoryBO businessObject, int action) throws WorkflowManagerException {
switch (action) {
case ACTION_COMPRESS:
return compress(businessObject);
case ACTION_DECOMPRESS:
return decompress(businessObject);
default:
throw new WorkflowManagerException("Action not found");
}
}
private DirectoryBO compress(DirectoryBO directory) throws WorkflowManagerException {
try {
// log action
logger.finer("Compress directory");
// create temporary file
File tempFile = File.createTempFile("drivecopy" + System.currentTimeMillis(), "temp");
logger.finer(String.format("Created temporary file '%s'", tempFile.getAbsolutePath()));
// create output stream
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(tempFile));
ZipOutputStream zout = new ZipOutputStream(bout);
zout.setLevel(directory.getLevel());
// process file and subdirectories
DirectoryBO dirBO = new DirectoryBO();
String filePath = directory.getFile().getAbsolutePath();
processFile(new File(filePath), zout, filePath, dirBO.getNotCompressed());
// close output stream
zout.close();
// return created file
dirBO.setFile(tempFile);
dirBO.setLevel(directory.getLevel());
return dirBO;
} catch (IOException ex) {
// re-throw exception
throw new WorkflowManagerException(ex.getMessage(), ex);
}
}
private DirectoryBO decompress(DirectoryBO directory) throws WorkflowManagerException {
try {
// log action
logger.finer("Decompress directory");
// output stream
FileInputStream fin = new FileInputStream(directory.getFile());
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fin));
// create directory if not present
if (!directory.getDestinationDirectory().mkdirs())
throw new IOException(String.format("Unable to create directories structure '%s'", directory.getDestinationDirectory().getAbsolutePath()));
// process zip entries
int count;
byte data[] = new byte[BUFFER];
ZipEntry entry;
BufferedOutputStream dest;
while ((entry = zis.getNextEntry()) != null) {
// status
logger.fine(String.format("Decompressing '%s'", entry.getName().substring(entry.getName().lastIndexOf(File.separator) + 1)));
// in case create subdirectories for file
String f = directory.getDestinationDirectory().getAbsolutePath() + File.separator + entry.getName();
File fl = new File(f);
if (entry.getName().contains(File.separator)) {
File fDir = new File(f.substring(0, f.lastIndexOf(File.separator)));
if (!fDir.mkdirs())
throw new IOException(String.format("Unable to create directories structure '%s'", fDir.getAbsolutePath()));
}
// check if file can be written
if (!fl.createNewFile()) {
// notify UI
logger.warning(String.format("Unable to decompress '%s'", fl.getAbsolutePath()));
// read entry from stream
while (zis.read(data, 0, BUFFER) != -1) {
data[0] = 0;
}
} else {
// write the file to the disk
FileOutputStream fos = new FileOutputStream(fl);
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
logger.finer("file data written");
}
}
zis.close();
// return the same BO
return directory;
} catch (IOException ex) {
// re-throw exception
throw new WorkflowManagerException(ex.getMessage(), ex);
}
}
private void processFile(File f, ZipOutputStream zout, String path, List<File> notCompressed) throws IOException {
// check if file can be read
if (!f.canRead()) {
// notify UI
logger.warning(String.format("Unable to compress '%s'", f.getAbsolutePath()));
// add to not compressed files
notCompressed.add(f);
return;
}
byte data[] = new byte[BUFFER];
// check if file is directory
if (f.isDirectory()) {
// process all files contained
File[] files = f.listFiles();
assert files != null;
for (File fl : files)
processFile(fl, zout, path, notCompressed);
} else {
// extract entry name
String entryName = f.getAbsolutePath().substring(f.getAbsolutePath().indexOf(path) + path.length() + 1);
// status
logger.fine(String.format("Compressing '%s'", f.getName()));
// create input stream
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(f), BUFFER);
// create entry
ZipEntry entry = new ZipEntry(entryName);
zout.putNextEntry(entry);
int count;
while ((count = bin.read(data, 0, BUFFER)) != -1) {
zout.write(data, 0, count);
}
bin.close();
logger.finer("ZIP entry created");
}
}
}