jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/io FilesystemImpl.java,1.5,1.6
Leo Simons <[email protected]>
| Newsgroups | gmane.comp.java.jicarilla.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/jicarilla/jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/io
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20979/platform/components/http/impl/src/java/org/jicarilla/io
Modified Files:
FilesystemImpl.java
Log Message:
seperate plumbing material from the basic HTTP logic, and work on solidifying the I/O code.
Index: FilesystemImpl.java
===================================================================
RCS file: /cvsroot/jicarilla/jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/io/FilesystemImpl.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- FilesystemImpl.java 23 Mar 2004 13:37:50 -0000 1.5
+++ FilesystemImpl.java 31 Mar 2004 12:10:59 -0000 1.6
@@ -59,7 +59,7 @@
final File root = new File( rootDirectory );
setRootDirectory( root );
- m_openFiles = new WeakHashMap();
+ setOpenFiles( new WeakHashMap() );
}
// ----------------------------------------------------------------------
@@ -72,10 +72,10 @@
protected synchronized void setRootDirectory( final File root )
{
- Assert.assertNotNull( root );
- Assert.assertTrue( root.exists() );
- Assert.assertTrue( root.canRead() );
- Assert.assertTrue( root.isDirectory() );
+ Assert.assertNotNull( "root argument may not be null", root );
+ Assert.assertTrue( "root must exist", root.exists() );
+ Assert.assertTrue( "root must be readable", root.canRead() );
+ Assert.assertTrue( "root must be a directory", root.isDirectory() );
m_rootDirectory = root;
}
@@ -87,42 +87,155 @@
protected synchronized void setOpenFiles( final Map openFiles )
{
+ Assert.assertNotNull( "openFiles argument may not be null",
+ openFiles );
m_openFiles = openFiles;
}
// ----------------------------------------------------------------------
// Interface: Filesystem
// ----------------------------------------------------------------------
- public synchronized ReadableByteChannel getFile( final String relativePath )
+ public synchronized ReadableByteChannel getFile(
+ final String relativePath )
throws FileNotFoundException
{
- final String path;
- if( relativePath.charAt(0) != File.separatorChar )
- path = m_rootDirectory.getAbsolutePath() + File.separator + relativePath;
+ final File file = getFileFromRelativePath( relativePath );
+ final FileChannel fileChannel = getFileChannel( file );
+ return fileChannel;
+ }
+
+ public synchronized void returnFile( final ReadableByteChannel channel )
+ {
+ if(! (channel instanceof FileChannel) )
+ return;
+
+ final FileChannel fileChannel = (FileChannel)channel;
+ returnChannel( fileChannel );
+ }
+
+ // ----------------------------------------------------------------------
+ // Helper Methods
+ // ----------------------------------------------------------------------
+ /**
+ * Tries to make sure that the provided path lives somewhere inside
+ * @link m_rootDirectory}.
+ *
+ * @param absolutePath the path to check for location validity.
+ * @throws SecurityException if the file does not live inside
+ * the root directory.
+ */
+ protected void checkPathIsAllowed( String absolutePath )
+ {
+ final String rootPath = getRootDirectory().getAbsolutePath();
+ final boolean startsWithRootPath = rootPath.equals(
+ absolutePath.substring(
+ 0, rootPath.length()
+ )
+ );
+ if( !startsWithRootPath )
+ throw new SecurityException(
+ "Access denied to: " + absolutePath );
+ }
+
+ /**
+ * Transform a path relative to the root directory to an absolute path.
+ *
+ * @param relativePath the path to transform.
+ * @return an absolute path to the same location.
+ * @throws SecurityException if access to the file is denied.
+ */
+ protected String getFullPath( final String relativePath )
+ {
+ // handle optional '/' and '\'
+ String path;
+ if( relativePath.charAt(0) != File.separatorChar &&
+ relativePath.charAt(0) != '/' &&
+ relativePath.charAt(0) != '\\' )
+ path = getRootDirectory().getAbsolutePath() + File.separator +
+ relativePath;
else
- path = m_rootDirectory.getAbsolutePath() + relativePath;
+ path = getRootDirectory().getAbsolutePath() + relativePath;
+
+ // convert '/' and '\'
+ path.replaceAll( "/", File.separator );
+ path.replaceAll( "\\\\", File.separator );
+
+ // check against stuff like '../../../..'
+ checkPathIsAllowed( path );
+
+ return path;
+ }
+ /**
+ * Transform a path relative to the root directory to a {@link File}.
+ *
+ * @param relativePath the path to transform.
+ * @return a <code>File</code> instance pointing to the specified path.
+ * @throws FileNotFoundException if the specified file cannot be found,
+ * the provided path points to a directory or to a file from which
+ * cannot be read.
+ * @throws SecurityException if access to the file is denied.
+ */
+ protected File getFileFromRelativePath( final String relativePath )
+ throws FileNotFoundException
+ {
+ final String path = getFullPath( relativePath );
final File file = new File( path );
- if( !file.exists() )
- throw new FileNotFoundException(path);
- Assert.assertTrue( file.canRead() );
- Assert.assertFalse( file.isDirectory() );
+ if( !file.exists() || !file.canRead() || !file.isDirectory() )
+ throw new FileNotFoundException( path );
+
+ return file;
+ }
+
+ /**
+ * Retrieve a {@link FileChannel} pointing to the provided file.
+ *
+ * @param file the file to retrieve the associated <code>FileChannel</code>
+ * for.
+ * @return the {@link FileChannel} pointing to the provided file.
+ * @throws FileNotFoundException if the specified file cannot be found,
+ * the provided path points to a directory or to a file from which
+ * cannot be read.
+ * @throws SecurityException if access to the file is denied.
+ */
+ protected FileChannel getFileChannel( final File file )
+ throws FileNotFoundException
+ {
final FileInputStream fis = new FileInputStream( file );
- final FileChannel fc = fis.getChannel();
- getOpenFiles().put( fc, fis );
- return fc;
+ final FileChannel fileChannel = fis.getChannel();
+ addOpenFile( fileChannel, fis );
+ return fileChannel;
}
- public synchronized void returnFile( final ReadableByteChannel channel )
+ /**
+ * Keep a reference to the provided {@link FileInputStream} around in order
+ * to be able to close it when it is fed to
+ * {@link #returnFile(ReadableByteChannel)}.
+ *
+ * @param fc the channel associated with the stream.
+ * @param fis the stream to keep around.
+ */
+ protected void addOpenFile( final FileChannel fc,
+ final FileInputStream fis )
{
- if(! (channel instanceof FileChannel) )
- return;
+ final FileChannelWrapper key = new FileChannelWrapper(fc);
+ getOpenFiles().put( key, fis );
+ }
- final FileChannel fc = (FileChannel)channel;
- if( getOpenFiles().containsKey( fc ) )
+ /**
+ * Remove the reference to the provided {@link FileInputStream} and close
+ * it if it existed before.
+ *
+ * @param fc the channel associated with the stream.
+ */
+ protected void returnChannel( final FileChannel fc )
+ {
+ final FileChannelWrapper key = new FileChannelWrapper(fc);
+ if( getOpenFiles().containsKey( key ) )
{
- final FileInputStream fs = (FileInputStream)getOpenFiles().remove( fc );
+ final FileInputStream fs =
+ (FileInputStream)getOpenFiles().remove( fc );
try
{
fs.close();
@@ -130,4 +243,18 @@
catch( IOException e ) {}
}
}
+
+ /**
+ * Helper class to make sure a channel is put into the cache every time
+ * one is requested, and no entries are overridden.
+ */
+ protected static class FileChannelWrapper
+ {
+ public FileChannel channel;
+
+ public FileChannelWrapper( FileChannel channel )
+ {
+ this.channel = channel;
+ }
+ }
}
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click