/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program 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
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.operator.nio.file.compression;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.operator.nio.file.FileObject;
import com.rapidminer.tools.Tools;
/**
* @author Marius Helf
*
*/
public abstract class ArchiveFileObject extends FileObject {
public enum FuzzyCompressionLevel {
/** use compression level as configured in the archive file object */
DEFAULT,
/** use highest compression level */
BEST,
/** compress as fast as possible */
FASTEST,
/** don't compress at all */
NONE
}
public enum BufferType {
MEMORY, FILE
};
private static final long serialVersionUID = 1L;
private static final String TEMP_FILE_PREFIX = "rm_archivefile_";
private static final String TEMP_FILE_SUFFIX = ".dump";
/**
* The data stream to which the archived data is written.
*/
private OutputStream archiveDataStream;
private final BufferType bufferType;
private File tmpFile;
private FuzzyCompressionLevel compressionLevel = FuzzyCompressionLevel.DEFAULT;
public ArchiveFileObject() throws OperatorException {
bufferType = BufferType.FILE;
init();
}
public ArchiveFileObject(BufferType bufferType) throws OperatorException {
super();
this.bufferType = bufferType;
init();
}
private void init() throws OperatorException {
switch (bufferType) {
case FILE:
try {
tmpFile = File.createTempFile("rm_archivefile_", ".dump");
tmpFile.deleteOnExit();
archiveDataStream = new FileOutputStream(tmpFile);
} catch (IOException e) {
throw new OperatorException("303", e, tmpFile, e.getMessage());
}
break;
case MEMORY:
archiveDataStream = new ByteArrayOutputStream();
break;
default:
throw new RuntimeException("Unknown buffer type: " + bufferType);
}
}
public OutputStream getArchiveDataStream() {
return archiveDataStream;
}
protected void flush() throws IOException {
archiveDataStream.flush();
}
@Override
public InputStream openStream() throws OperatorException {
try {
flush();
} catch (IOException e) {
throw new OperatorException("archive_file.stream_error", e, new Object[0]);
}
switch (bufferType) {
case FILE:
try {
return new FileInputStream(tmpFile);
} catch (FileNotFoundException e) {
throw new OperatorException("301", e, tmpFile);
}
case MEMORY:
return new ByteArrayInputStream(((ByteArrayOutputStream) archiveDataStream).toByteArray());
default:
throw new RuntimeException("bufferType should never be null");
}
}
@Override
public File getFile() throws OperatorException {
if (tmpFile == null) {
try {
tmpFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
tmpFile.deleteOnExit();
} catch (IOException e) {
throw new OperatorException("303", e, "File in " + System.getProperty("java.io.tmpdir"), e.getMessage());
}
try (FileOutputStream fos = new FileOutputStream(tmpFile); InputStream in = openStream();) {
Tools.copyStreamSynchronously(in, fos, true);
} catch (IOException e) {
throw new OperatorException("303", e, tmpFile, e.getMessage());
}
} else {
try {
flush();
} catch (IOException e) {
throw new OperatorException("303", e, tmpFile, e.getMessage());
}
}
return tmpFile;
}
public void addEntry(FileObject fileObject, String directory) throws OperatorException {
addEntry(fileObject, directory, getCompressionLevel());
}
/**
* @param fileObject
* @param directory
* @param default1
* @throws OperatorException
*/
public abstract void addEntry(FileObject fileObject, String directory, FuzzyCompressionLevel localCompressionLevel)
throws OperatorException;
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
switch (bufferType) {
case FILE:
builder.append("File");
break;
case MEMORY:
builder.append("Memory");
break;
default:
throw new RuntimeException("Unknown buffer type: " + bufferType);
}
builder.append(" buffered ");
builder.append(getName());
return builder.toString();
}
@Override
protected void finalize() throws Throwable {
if (tmpFile != null) {
tmpFile.delete();
}
super.finalize();
}
public FuzzyCompressionLevel getCompressionLevel() {
return compressionLevel;
}
public void setCompressionLevel(FuzzyCompressionLevel compressionLevel) {
// TODO throw exception if compressionLevel is not supported
this.compressionLevel = compressionLevel;
}
public abstract Set<FuzzyCompressionLevel> getSupportedCompressionLevels();
}