Mercurial Hosting > nabble
diff src/cachingfilter/FileHandler.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cachingfilter/FileHandler.java Thu Mar 21 19:15:52 2019 -0600 @@ -0,0 +1,138 @@ +package cachingfilter; + +import java.io.File; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import javax.servlet.ServletOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.eclipse.jetty.io.nio.DirectNIOBuffer; +import org.eclipse.jetty.server.AbstractHttpConnection; + + +public abstract class FileHandler { + abstract void close(); + abstract InputStream getInputStream(); + abstract void writeTo(ServletOutputStream out) throws IOException; + + public interface Factory { + public FileHandler newInstance(File file) throws IOException; + } + + private static final Logger logger = LoggerFactory.getLogger(FileHandler.class); + + private static abstract class BufferedFactory implements Factory { + abstract DirectNIOBuffer getDirectNIOBuffer(File file) throws IOException; + + public FileHandler newInstance(File file) throws IOException { + final DirectNIOBuffer fileBuffer = getDirectNIOBuffer(file); + + return new FileHandler() { + + void close() {} + + InputStream getInputStream() { + return new BufferInputStream(fileBuffer); + } + + void writeTo(ServletOutputStream out) throws IOException { + if (out instanceof AbstractHttpConnection.Output) { + logger.trace("sendFileContent using AbstractHttpConnection.Output"); + ((AbstractHttpConnection.Output)out).sendContent(fileBuffer); + } else { + fileBuffer.writeTo(out); + } + } + }; + } + } + + public static final Factory mappedFile = new BufferedFactory() { + + private MappedByteBuffer map(File file) throws IOException { + FileInputStream fis = new FileInputStream(file); + try { + return fis.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length()); + } finally { + fis.close(); + } + } + + DirectNIOBuffer getDirectNIOBuffer(File file) throws IOException { + return new DirectNIOBuffer(map(file),true); + } + + }; + + public static final Factory memFile = new BufferedFactory() { + + DirectNIOBuffer getDirectNIOBuffer(File file) throws IOException { + int len = (int)file.length(); + DirectNIOBuffer buffer = new DirectNIOBuffer(len); + InputStream is = new FileInputStream(file); + buffer.readFrom(is,len); + is.close(); + return buffer; + } + + }; + + public static final Factory ioFile = new Factory() { + + public FileHandler newInstance(File file) throws IOException { + final InputStream in = new BufferedInputStream(new FileInputStream(file)); + + return new FileHandler() { + + void close() { + try { + in.close(); + } catch(IOException e) { + logger.error("",e); + } + } + + InputStream getInputStream() { + return in; + } + + void writeTo(ServletOutputStream out) throws IOException { + byte[] a = new byte[8192]; + while(true) { + int n; + try { + n = in.read(a); + } catch(IOException e) { + throw new RuntimeException(e); + } + if( n == -1 ) + break; + out.write(a,0,n); + } + } + }; + } + + }; + + public static final Factory mappedOrIoFile = new Factory() { + + public FileHandler newInstance(File file) throws IOException { + try { + return mappedFile.newInstance(file); + } catch(IOException e) { + if( !"Operation not permitted".equals(e.getMessage()) ) + throw e; + logger.warn("couldn't map "+file+" length="+file.length(),e); + return ioFile.newInstance(file); + } + } + + }; + + public static Factory factory = mappedFile; // change for other implementations +}