blob: b5fbceef80dcb71b902cc50b632b9fc84fdda06f [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:
* Jan Finis - initial API and implementation
******************************************************************************/
package org.eclipse.emf.emfstore.internal.client.model.filetransfer;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import org.eclipse.emf.emfstore.internal.client.model.Configuration;
import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace;
import org.eclipse.emf.emfstore.internal.client.provider.XMIClientURIConverter;
import org.eclipse.emf.emfstore.internal.common.model.util.FileUtil;
import org.eclipse.emf.emfstore.internal.server.exceptions.FileTransferException;
import org.eclipse.emf.emfstore.internal.server.model.FileIdentifier;
/**
* This class manages the locally cached files for file transfers. A cache
* manager instance is contained in every FileTransferManager. No other cache
* managers should be created.
*
* @author jfinis
*/
public class FileTransferCacheManager {
/**
* Temporary folder for file uploads to server.
*/
public static final String TEMP_FOLDER = "tmp"; //$NON-NLS-1$
/**
* project folder prefix.
*/
public static final String PROJECT_FOLDER_PREFIX = "project-"; //$NON-NLS-1$
/**
* Attachment folder for uploads and downloads.
*/
public static final String ATTACHMENT_FOLDER = "attachment"; //$NON-NLS-1$
/**
* The delimiter that separates file attachment id, file version and file
* name in an uploaded file.
*/
public static final String FILE_NAME_DELIMITER = "_"; //$NON-NLS-1$
/**
* The associated project space.
*/
private final ProjectSpace projectSpace;
/**
* The cache folder, constructed from the identifier of the project space.
*/
private final File cacheFolder;
/**
* The temp folder is a folder where unfinished file downloads are stored.
*/
private final File tempCacheFolder;
/**
* Default constructor for a specific project space.
*
* @param projectSpaceImpl
* the project space to which this cache belongs.
*/
public FileTransferCacheManager(ProjectSpace projectSpaceImpl) {
projectSpace = projectSpaceImpl;
cacheFolder = new File(getCacheFolder(projectSpace));
tempCacheFolder = new File(cacheFolder, "temp"); //$NON-NLS-1$
mkdirs();
}
/**
* Returns the default file cache folder of a given projectspace.
*
* @param projectSpace the projectSpace
* @return the name of the cache folder
*/
public static String getCacheFolder(ProjectSpace projectSpace) {
return Configuration.getFileInfo().getWorkspaceDirectory()
+ XMIClientURIConverter.PROJECT_SAPCE_DIRECTORY_PREFIX
+ projectSpace.getIdentifier()
+ File.separatorChar
+ "files" + File.separatorChar; //$NON-NLS-1$
}
/**
* Returns true iff a file with this identifier is present in the cache.
* After this method has returned true, it is guaranteed that the
* getCachedFile method finds the file and does not throw an exception.
*
* @param identifier
* the identifier of the file
* @return if the file is present in the cache
*/
public boolean hasCachedFile(FileIdentifier identifier) {
final File f = getFileFromId(cacheFolder, identifier);
return f.exists();
}
/**
* Returns a cached file with a given identifier. If the file does not
* exist, a FileTransferException is thrown.
*
* @param identifier
* the identifier of the file
* @return the file
* @throws FileTransferException
* if the file is not present in the cache
*/
public File getCachedFile(FileIdentifier identifier) throws FileTransferException {
final File f = getFileFromId(cacheFolder, identifier);
if (!f.exists()) {
throw new FileTransferException(
MessageFormat.format(
Messages.FileTransferCacheManager_FileNotInCache, identifier));
}
return f;
}
/**
* Adds a file to the cache using a given id. If a file with the given id is
* already in the cache, it is overwritten.
*
* @param input
* the file to be cached
* @param id
* the id to be used for the file.
* @return the file in the cache folder
* @throws IOException
* any IO Exception that can occur during copying a file
*/
public File cacheFile(File input, FileIdentifier id) throws IOException {
mkdirs();
final File destination = new File(cacheFolder, id.getIdentifier());
FileUtil.copyFile(input, destination);
return destination;
}
/**
* Creates a file in the temporary cache folder for a specified file id and
* returns it. If the file already exists, it is deleted and newly created.
*
* @param id
* the file id for which to create a temporary file
* @return the temporary file
* @throws FileTransferException
* if an IO exception occurred during the creation of a new file
*/
public File createTempFile(FileIdentifier id) throws FileTransferException {
mkdirs();
final File cacheFile = getFileFromId(tempCacheFolder, id);
if (cacheFile.exists()) {
cacheFile.delete();
}
try {
cacheFile.createNewFile();
} catch (final IOException e) {
throw new FileTransferException(Messages.FileTransferCacheManager_CreateTempFileFailed);
}
return cacheFile;
}
/**
* This method moves a file from the temporary folder into the cache. It should
* be called after a temporary file was written successfully. A file
* transfer exception is thrown in the following cases: - The file does not
* exist in the temporary folder - The file already exists in the cache folder -
* The file cannot be moved to the cache folder (the rename operation fails)
*
* @param id
* the id of the file which is to be moved
* @return the new location of the file after moving it
* @throws FileTransferException
* thrown if the temporary file does not exist, the final file
* already exists, or if the rename operation which moves the
* file fails
*/
public File moveTempFileToCache(FileIdentifier id) throws FileTransferException {
return moveTempFileToCache(id, false);
}
/**
* This method moves a file from the temporary folder into the cache. It should
* be called after a temporary file was written successfully. A file
* transfer exception is thrown in the following cases: - The file does not
* exist in the temporary folder - The file already exists in the cache folder -
* The file cannot be moved to the cache folder (the rename operation fails)
*
* @param id
* the id of the file which is to be moved
* @param overwrite
* whether to overwrite an existing file, if one with the given id is found
* @return the new location of the file after moving it
* @throws FileTransferException
* thrown if the temporary file does not exist, the final file
* already exists, or if the rename operation which moves the
* file fails
*/
public File moveTempFileToCache(FileIdentifier id, boolean overwrite) throws FileTransferException {
mkdirs();
final File cacheFile = getFileFromId(cacheFolder, id);
final File tmpFile = getFileFromId(tempCacheFolder, id);
if (!tmpFile.exists()) {
throw new FileTransferException(
Messages.FileTransferCacheManager_MoveToCacheFailed_FileMissing
+ id.getIdentifier());
}
if (cacheFile.exists() && overwrite) {
cacheFile.delete();
}
if (cacheFile.exists()) {
throw new FileTransferException(
Messages.FileTransferCacheManager_MoveToCacheFailed_Exists
+ id.getIdentifier());
}
if (!tmpFile.renameTo(cacheFile)) {
throw new FileTransferException(Messages.FileTransferCacheManager_MoveToCacheFailed_MoveFailed);
}
return cacheFile;
}
/**
* Builds a file from a cache folder and a file identifier.
*
* @param folder
* the base folder in which the file is
* @param id
* the file identifier of that file
* @return the assembled file
*/
private File getFileFromId(File folder, FileIdentifier id) {
return new File(folder, id.getIdentifier());
}
/**
* Creates all necessary directories (cache and temp).
*/
private void mkdirs() {
cacheFolder.mkdirs();
tempCacheFolder.mkdirs();
}
/**
* Removes a file from the cache. Does nothing if no such file is cached.
* Returns true if the file was successfully deleted from cache, otherwise
* false.
*
* @param fileIdentifier
* the identifier of the file to be removed
* @return true iff the file was deleted successfully
*/
public boolean removeCachedFile(FileIdentifier fileIdentifier) {
final File toRemove = getFileFromId(cacheFolder, fileIdentifier);
if (toRemove.exists()) {
return toRemove.delete();
}
return false;
}
}