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
+}