All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.refcodes.filesystem.InMemoryFileSystem Maven / Gradle / Ivy

There is a newer version: 3.3.9
Show newest version
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// =============================================================================
// This code is copyright (c) by Siegfried Steiner, Munich, Germany, distributed
// on an "AS IS" BASIS WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, and licen-
// sed under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// =============================================================================
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// together with the GPL linking exception applied; as being applied by the GNU
// Classpath ("http://www.gnu.org/software/classpath/license.html")
// =============================================================================
// Apache License, v2.0 ("http://www.apache.org/licenses/TEXT-2.0")
// =============================================================================
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.filesystem;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.refcodes.exception.Trap;
import org.refcodes.filesystem.FileHandle.MutableFileHandle;

/**
 * An in-memory {@link FileSystem} using an {@link ConcurrentHashMap} for
 * implementation.
 */
public class InMemoryFileSystem implements FileSystem {

	private static final Logger LOGGER = Logger.getLogger( InMemoryFileSystem.class.getName() );

	// /////////////////////////////////////////////////////////////////////////
	// VARIABLES:
	// /////////////////////////////////////////////////////////////////////////

	private final Map _fileSystemMap = new ConcurrentHashMap<>();

	// /////////////////////////////////////////////////////////////////////////
	// CONSTRUCTORS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Constructs an in-memory {@link FileSystem}.
	 */
	public InMemoryFileSystem() {}

	// /////////////////////////////////////////////////////////////////////////
	// METHODS:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean hasFile( String aKey ) throws IllegalKeyException, NoListAccessException, UnknownFileSystemException, IOException {
		return _fileSystemMap.containsKey( new FileHandleImpl( aKey ) );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean hasFile( String aPath, String aName ) throws IllegalPathException, IllegalNameException, NoListAccessException, UnknownFileSystemException, IOException {
		return _fileSystemMap.containsKey( new FileHandleImpl( aPath, aName ) );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean hasFile( FileHandle aFileHandle ) throws NoListAccessException, UnknownFileSystemException, IOException, IllegalFileException {
		return _fileSystemMap.containsKey( aFileHandle );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public FileHandle createFile( String aKey ) throws FileAlreadyExistsException, NoCreateAccessException, IllegalKeyException, UnknownFileSystemException, IOException, NoListAccessException {
		final Date theDate = new Date();
		final FileHandle theFileHandle = new FileHandleImpl( FileSystemUtility.getPath( aKey ), FileSystemUtility.getName( aKey ), 0, theDate, theDate );
		if ( _fileSystemMap.containsKey( theFileHandle ) ) {
			throw new FileAlreadyExistsException( aKey, "The file with the key \"" + aKey + "\" already exists." );
		}
		_fileSystemMap.put( theFileHandle, new byte[] {} );
		return theFileHandle;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public FileHandle createFile( String aPath, String aName ) throws FileAlreadyExistsException, NoCreateAccessException, IllegalNameException, IllegalPathException, UnknownFileSystemException, IOException, NoListAccessException {
		final Date theDate = new Date();
		final FileHandle theFileHandle = new FileHandleImpl( aPath, aName, 0, theDate, theDate );
		if ( _fileSystemMap.containsKey( theFileHandle ) ) {
			throw new FileAlreadyExistsException( theFileHandle.toKey(), "The file with the key \"" + theFileHandle.toKey() + "\" already exists." );
		}
		_fileSystemMap.put( theFileHandle, new byte[] {} );
		return theFileHandle;

	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public FileHandle getFileHandle( String aKey ) throws NoListAccessException, IllegalKeyException, UnknownFileSystemException, IOException, UnknownKeyException {
		FileHandle theFileHandle = new FileHandleImpl( aKey );
		theFileHandle = toFileHandle( theFileHandle );
		if ( theFileHandle == null ) {
			throw new UnknownKeyException( "The file with the key \"" + aKey + "\" does not exist.", aKey );
		}
		return theFileHandle;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public FileHandle getFileHandle( String aPath, String aName ) throws NoListAccessException, IllegalNameException, IllegalPathException, UnknownFileSystemException, IOException, UnknownKeyException {
		final FileHandle theFileHandle = new FileHandleImpl( aPath, aName );
		for ( FileHandle eFileHandle : _fileSystemMap.keySet() ) {
			if ( eFileHandle.equals( theFileHandle ) ) {
				return eFileHandle;
			}
		}
		throw new UnknownKeyException( "The file with the path \"" + aPath + "\" and name \"" + aName + "\" ( = key \"" + FileSystemUtility.toKey( aPath, aName ) + "\") does not exist.", FileSystemUtility.toKey( aPath, aName ) );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void fromFile( FileHandle aFromFileHandle, OutputStream aOutputStream ) throws ConcurrentAccessException, UnknownFileException, NoReadAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		final byte[] theBuffer = _fileSystemMap.get( aFromFileHandle );
		if ( theBuffer == null ) {
			throw new UnknownFileException( aFromFileHandle, "The (from) file with the key \"" + aFromFileHandle.toKey() + "\" does not exist." );
		}
		aOutputStream.write( theBuffer );
		aOutputStream.flush();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public synchronized void toFile( FileHandle aToFileHandle, InputStream aInputStream ) throws ConcurrentAccessException, UnknownFileException, NoWriteAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		if ( !hasFile( aToFileHandle ) ) {
			throw new UnknownFileException( aToFileHandle, "The (to) file with the key \"" + aToFileHandle.toKey() + "\" does not exist." );
		}
		final byte[] theBuffer = aInputStream.readAllBytes();
		final MutableFileHandle theMutableToFileHandle = aToFileHandle.toMutableFileHandle();
		theMutableToFileHandle.setFileSize( theBuffer.length );
		_fileSystemMap.put( theMutableToFileHandle.toFileHandle(), theBuffer );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public synchronized InputStream fromFile( FileHandle aFromFileHandle ) throws ConcurrentAccessException, UnknownFileException, NoReadAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		final byte[] theBuffer = _fileSystemMap.get( aFromFileHandle );
		if ( theBuffer == null ) {
			throw new UnknownFileException( aFromFileHandle, "The (from) file with the key \"" + aFromFileHandle.toKey() + "\" does not exist." );
		}
		return new ByteArrayInputStream( theBuffer );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public OutputStream toFile( final FileHandle aToFileHandle ) throws ConcurrentAccessException, UnknownFileException, NoWriteAccessException, UnknownFileSystemException, IOException, IllegalFileException {
		if ( !_fileSystemMap.containsKey( aToFileHandle ) ) {
			throw new UnknownFileException( aToFileHandle, "The (to) file with the key \"" + aToFileHandle.toKey() + "\" does not exist." );
		}

		final PipedInputStream thePipedInputStream = new PipedInputStream();
		final PipedOutputStream thePipedOutputStream = new PipedOutputStream( thePipedInputStream );
		final Thread t = new Thread() {

			/**
			 * {@inheritDoc}
			 */
			@Override
			public void run() {
				try {
					final byte[] theBuffer = thePipedInputStream.readAllBytes();
					final MutableFileHandle theMutableToFileHandle = aToFileHandle.toMutableFileHandle();
					theMutableToFileHandle.setFileSize( theBuffer.length );
					_fileSystemMap.put( theMutableToFileHandle.toFileHandle(), theBuffer );
				}
				catch ( IOException e ) {
					LOGGER.log( Level.WARNING, "Unable to write the output stream to the file with key \"" + aToFileHandle.toKey() + "\" as of: " + Trap.asMessage( e ), e );
				}
				finally {}
			}
		};
		t.start();
		return thePipedOutputStream;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void fromFile( FileHandle aFromFileHandle, File aToFile ) throws ConcurrentAccessException, UnknownFileException, NoReadAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		final byte[] theBuffer = _fileSystemMap.get( aFromFileHandle );
		if ( theBuffer == null ) {
			throw new UnknownFileException( aFromFileHandle, "The (from) file with the key \"" + aFromFileHandle.toKey() + "\" does not exist." );
		}
		try ( OutputStream theOutputStream = new FileOutputStream( aToFile ) ) {
			new ByteArrayInputStream( theBuffer ).transferTo( theOutputStream );
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void toFile( FileHandle aToFileHandle, File aFromFile ) throws ConcurrentAccessException, UnknownFileException, NoWriteAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		if ( !_fileSystemMap.containsKey( aToFileHandle ) ) {
			throw new UnknownFileException( aToFileHandle, "The (to) file with the key \"" + aToFileHandle.toKey() + "\" does not exist." );
		}
		try ( FileInputStream theFileInputStream = new FileInputStream( aFromFile ) ) {
			final byte[] theBuffer = theFileInputStream.readAllBytes();
			_fileSystemMap.put( aToFileHandle, theBuffer );
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void toFile( FileHandle aToFileHandle, byte[] aBuffer ) throws ConcurrentAccessException, UnknownFileException, NoWriteAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		if ( !_fileSystemMap.containsKey( aToFileHandle ) ) {
			throw new UnknownFileException( aToFileHandle, "The (to) file with the key \"" + aToFileHandle.toKey() + "\" does not exist." );
		}
		final MutableFileHandle theMutableToFileHandle = aToFileHandle.toMutableFileHandle();
		theMutableToFileHandle.setFileSize( aBuffer.length );
		_fileSystemMap.put( theMutableToFileHandle.toFileHandle(), aBuffer );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public synchronized FileHandle renameFile( FileHandle aFileHandle, String aNewName ) throws UnknownFileException, ConcurrentAccessException, FileAlreadyExistsException, NoCreateAccessException, NoDeleteAccessException, IllegalNameException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		final FileHandle theFileHandle = toFileHandle( aFileHandle );
		if ( theFileHandle == null ) {
			throw new UnknownFileException( aFileHandle, "The file with the key \"" + aFileHandle.toKey() + "\" does not exist." );
		}
		final MutableFileHandle theMutableNewFileHandle = theFileHandle.toMutableFileHandle();
		theMutableNewFileHandle.setName( FileSystemUtility.getName( aNewName ) );
		final FileHandle theNewFileHandle = theMutableNewFileHandle.toFileHandle();
		if ( _fileSystemMap.containsKey( theNewFileHandle ) ) {
			throw new FileAlreadyExistsException( theNewFileHandle.toKey(), "The file with the key \"" + theNewFileHandle.toKey() + "\" already exist." );
		}
		final byte[] theBuffer = _fileSystemMap.remove( theFileHandle );
		_fileSystemMap.put( theNewFileHandle, theBuffer );
		return theNewFileHandle;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public synchronized FileHandle moveFile( FileHandle aFileHandle, String aNewKey ) throws UnknownFileException, ConcurrentAccessException, FileAlreadyExistsException, NoCreateAccessException, NoDeleteAccessException, IllegalKeyException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		final FileHandle theFileHandle = toFileHandle( aFileHandle );
		if ( theFileHandle == null ) {
			throw new UnknownFileException( aFileHandle, "The file with the key \"" + aFileHandle.toKey() + "\" does not exist." );
		}
		final MutableFileHandle theMutableNewFileHandle = theFileHandle.toMutableFileHandle();
		theMutableNewFileHandle.setPath( FileSystemUtility.getPath( aNewKey ) );
		theMutableNewFileHandle.setName( FileSystemUtility.getName( aNewKey ) );

		final FileHandle theNewFileHandle = theMutableNewFileHandle.toFileHandle();
		if ( _fileSystemMap.containsKey( theNewFileHandle ) ) {
			throw new FileAlreadyExistsException( theNewFileHandle.toKey(), "The file with the key \"" + aFileHandle.toKey() + "\" already exist." );
		}
		final byte[] theBuffer = _fileSystemMap.remove( theFileHandle );
		_fileSystemMap.put( theNewFileHandle, theBuffer );
		return theNewFileHandle;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void deleteFile( FileHandle aFileHandle ) throws ConcurrentAccessException, UnknownFileException, NoDeleteAccessException, UnknownFileSystemException, IOException, NoListAccessException, IllegalFileException {
		final FileHandle theFileHandle = toFileHandle( aFileHandle );
		if ( theFileHandle == null ) {
			throw new UnknownFileException( aFileHandle, "The file with the key \"" + aFileHandle.toKey() + "\" does not exist." );
		}
		_fileSystemMap.remove( theFileHandle );
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean hasFiles( String aPath, boolean isRecursively ) throws NoListAccessException, IllegalPathException, UnknownFileSystemException, IOException {
		for ( FileHandle eFileHandle : _fileSystemMap.keySet() ) {
			if ( isRecursively ) {
				if ( eFileHandle.getPath().equals( aPath ) || eFileHandle.getPath().startsWith( aPath + PATH_DELIMITER ) ) {
					return true;
				}
			}
			else {
				if ( eFileHandle.getPath().equals( aPath ) ) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public List getFileHandles( String aPath, boolean isRecursively ) throws NoListAccessException, UnknownPathException, IllegalPathException, UnknownFileSystemException, IOException {

		final List theFileHandles = new ArrayList<>();

		for ( FileHandle eFileHandle : _fileSystemMap.keySet() ) {
			if ( isRecursively ) {
				if ( eFileHandle.getPath().equals( aPath ) || eFileHandle.getPath().startsWith( aPath + PATH_DELIMITER ) ) {
					theFileHandles.add( eFileHandle );
				}
			}
			else {
				if ( eFileHandle.getPath().equals( aPath ) ) {
					theFileHandles.add( eFileHandle );
				}
			}
		}
		return theFileHandles;
	}

	// /////////////////////////////////////////////////////////////////////////
	// COMPONENT:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void destroy() {
		_fileSystemMap.clear();
	}

	// /////////////////////////////////////////////////////////////////////////
	// HELPER:
	// /////////////////////////////////////////////////////////////////////////

	/**
	 * Retrieves the actual managed {@link FileHandle} equal to the provided
	 * one.
	 * 
	 * @param aFileHandle The {@link FileHandle} for which to get the managed
	 *        one.
	 * 
	 * @return The managed {@link FileHandle} or null if none equal file handl
	 *         was found in the internal map.
	 */
	private FileHandle toFileHandle( FileHandle aFileHandle ) {
		for ( FileHandle eFileHandle : _fileSystemMap.keySet() ) {
			if ( eFileHandle.equals( aFileHandle ) ) {
				return eFileHandle;
			}
		}
		return null;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy