blob: 93639daac8cf3b19b27d966f49f50273ef56ff67 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2011 Chair for Applied Software Engineering,
* Technische Universitaet Muenchen.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* pfeifferc
******************************************************************************/
package org.eclipse.emf.emfstore.internal.server.filetransfer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import org.eclipse.emf.emfstore.internal.server.exceptions.FileTransferException;
/**
* File transfer utility class.
*
* @author pfeifferc
*/
public final class FilePartitionerUtil {
// chunk size. consider that changing this value means that old file transfers will fail.
private static final int CHUNK_SIZE = 100000;
// error messages
private static final String COULD_NOT_FIND_THE_FILE = "Could not find the file!";
private static final String COULD_NOT_READ_THE_FILE = "Could not read the file!";
private static final String COULD_NOT_CLOSE_THE_FILE = "Could not close the file!";
private FilePartitionerUtil() {
}
/**
* Writes a file chunk to a file.
*
* @param file file to be written to
* @param fileChunk file chunk
* @throws FileTransferException if any error occurs writing to the file.
*/
public static synchronized void writeChunk(File file, FileChunk fileChunk) throws FileTransferException {
try {
final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rws");
// skips to the position where the file chunk should be written
randomAccessFile.skipBytes(fileChunk.getChunkNumber() * CHUNK_SIZE);
randomAccessFile.write(fileChunk.getData());
// make sure everything is written instantly
randomAccessFile.close();
} catch (final FileNotFoundException e) {
throw new FileTransferException(COULD_NOT_FIND_THE_FILE, e);
} catch (final IOException e) {
throw new FileTransferException("Could not write to the file!", e);
}
}
/**
* Reads a file chunk from a file.
*
* @param file to be read from
* @param fileInformation containing file transfer attributes
* @return fileChunk
* @throws FileTransferException if any error occurs reading the file
*/
public static synchronized FileChunk readChunk(File file, FileTransferInformation fileInformation)
throws FileTransferException {
boolean end = false;
byte[] data;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
final int absoluteSize = fileInputStream.available();
// start reading the chunk from the position specified by the chunk number and chunk size
fileInputStream.skip(fileInformation.getChunkNumber() * CHUNK_SIZE);
final int remainingSize = fileInputStream.available();
// if the remaining size is chunk size or smaller, set end flag to true, which means this is the last chunk
if (remainingSize <= CHUNK_SIZE && remainingSize >= 0) {
end = true;
data = new byte[remainingSize];
} else {
data = new byte[CHUNK_SIZE];
}
fileInputStream.read(data);
fileInputStream.getChannel().close();
fileInformation.setFileSize(absoluteSize);
return new FileChunk(fileInformation, end, data);
} catch (final IOException e) {
throw new FileTransferException(COULD_NOT_READ_THE_FILE, e);
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (final IOException e) {
throw new FileTransferException(COULD_NOT_CLOSE_THE_FILE, e);
}
}
}
/**
* Returns the number of chunks for a given file.
*
* @param file file
* @return number of chunks
* @throws FileTransferException if any error occurs obtaining the file handle.
*/
public static int getNumberOfChunks(File file) throws FileTransferException {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
return (int) Math.ceil(fileInputStream.available() / (float) CHUNK_SIZE);
} catch (final FileNotFoundException e) {
throw new FileTransferException(COULD_NOT_FIND_THE_FILE, e);
} catch (final IOException e) {
throw new FileTransferException(COULD_NOT_READ_THE_FILE, e);
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (final IOException e) {
throw new FileTransferException(COULD_NOT_CLOSE_THE_FILE, e);
}
}
}
/**
* @param file file
* @return file size
* @throws FileTransferException if any error occurs reading file size
*/
public static int getFileSize(File file) throws FileTransferException {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(file);
return fileInputStream.available();
} catch (final FileNotFoundException e) {
throw new FileTransferException(COULD_NOT_FIND_THE_FILE, e);
} catch (final IOException e) {
throw new FileTransferException(COULD_NOT_READ_THE_FILE, e);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (final IOException e) {
throw new FileTransferException(COULD_NOT_CLOSE_THE_FILE, e);
}
}
}
}
/**
* @return the chunk size
*/
public static int getChunkSize() {
return CHUNK_SIZE;
}
}