Quadcap Embeddable Server

com/quadcap/http/servlets/file/HttpFile.java

Go to the documentation of this file.
00001 package com.quadcap.http.servlets.file; 00002 00003 /* Copyright 1998 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.File; 00042 import java.io.FileInputStream; 00043 import java.io.FileNotFoundException; 00044 import java.io.InputStream; 00045 import java.io.IOException; 00046 import java.io.OutputStream; 00047 00048 import java.net.URL; 00049 import java.net.URLConnection; 00050 00051 import javax.servlet.ServletContext; 00052 00053 import javax.servlet.http.HttpServletRequest; 00054 import javax.servlet.http.HttpServletResponse; 00055 00056 import com.quadcap.util.collections.Cacheable; 00057 00058 import com.quadcap.io.IO; 00059 00060 import com.quadcap.io.dir.Directory; 00061 import com.quadcap.io.dir.Entry; 00062 00063 import com.quadcap.util.Debug; 00064 import com.quadcap.util.Util; 00065 00066 /** 00067 * This class represents a single cached file. 00068 * 00069 * @author Stan Bailes 00070 */ 00071 public class HttpFile extends Cacheable { 00072 ServletContext context; 00073 String contentType = "text/plain"; 00074 File file; 00075 URL url; 00076 long lastMod; 00077 long lastCheck = -1; 00078 byte[] buf = null; 00079 00080 static int MAX_CACHED = 16 * 1024; 00081 00082 /** 00083 * Default constructor 00084 */ 00085 public HttpFile() {} 00086 00087 public void init(Object store, Object key) throws IOException { 00088 super.init(store, key); 00089 FileServlet fs = (FileServlet)store; 00090 this.context = fs.getServletContext(); 00091 String path = key.toString(); 00092 this.contentType = context.getMimeType(path); 00093 this.file = new File(path); 00094 if (!file.exists()) { 00095 this.file = null; 00096 this.url = fs.getURL(path); 00097 if (url == null) { 00098 throw new FileNotFoundException("Not found: " + path); 00099 } 00100 } 00101 compile(); 00102 } 00103 00104 public synchronized void compile() throws IOException { 00105 if (file != null) { 00106 if (!file.exists()) { 00107 throw new FileNotFoundException("Not found: " + file); 00108 } 00109 if (file.isDirectory()) { 00110 File g = new File(file, "index.html"); 00111 if (g.canRead()) { 00112 file = g; 00113 contentType = "text/html"; 00114 } else { 00115 throw new FileNotFoundException("Not found: " + file); 00116 } 00117 } 00118 if (file.canRead() && file.length() < MAX_CACHED) { 00119 buf = new byte[(int)file.length()]; 00120 FileInputStream is = new FileInputStream(file); 00121 try { 00122 IO.readFully(is, buf); 00123 } finally { 00124 is.close(); 00125 } 00126 this.lastMod = file.lastModified(); 00127 } else { 00128 buf = null; 00129 } 00130 } else { 00131 URLConnection conn = url.openConnection(); 00132 long len = conn.getContentLength(); 00133 if (len < MAX_CACHED) { 00134 buf = new byte[(int)len]; 00135 try { 00136 this.lastMod = conn.getLastModified(); 00137 InputStream is = conn.getInputStream(); 00138 try { 00139 IO.readFully(is, buf); 00140 } finally { 00141 is.close(); 00142 } 00143 } catch (IOException e) { 00144 buf = null; 00145 throw e; 00146 } 00147 } else { 00148 buf = null; 00149 } 00150 } 00151 } 00152 00153 public synchronized void service(HttpServletRequest req, 00154 HttpServletResponse res) 00155 throws IOException 00156 { 00157 //Jni j = new Jni("file"); 00158 res.setContentType(contentType); 00159 //j.dump("setContentType"); 00160 OutputStream os = res.getOutputStream(); 00161 //j.dump("getOutputStream"); 00162 if (buf != null) { 00163 res.setContentLength(buf.length); 00164 //j.dump("setContentLength"); 00165 os.write(buf); 00166 //j.dump("os.write(buf)"); 00167 } else if (file != null) { 00168 res.setContentLength((int)file.length()); 00169 try { 00170 FileInputStream is = new FileInputStream(file); 00171 try { 00172 IO.copyStream(is, os); 00173 } finally { 00174 is.close(); 00175 } 00176 } catch (FileNotFoundException fe) { 00177 res.sendError(res.SC_NOT_FOUND, "Not found: " + 00178 file.getName()); 00179 } 00180 } else { 00181 URLConnection conn = url.openConnection(); 00182 res.setContentLength(conn.getContentLength()); 00183 InputStream is = conn.getInputStream(); 00184 try { 00185 IO.copyStream(is, os); 00186 } finally { 00187 is.close(); 00188 } 00189 } 00190 //j.dump("done"); 00191 } 00192 00193 public synchronized void checkModified() throws Exception { 00194 long now = System.currentTimeMillis(); 00195 if (now - lastCheck > 2000) { 00196 lastCheck = now; 00197 if (file != null) { 00198 if (file.lastModified() > lastMod) { 00199 compile(); 00200 } 00201 } else { 00202 URLConnection conn = url.openConnection(); 00203 if (conn.getLastModified() > lastMod) { 00204 compile(); 00205 } 00206 } 00207 } 00208 } 00209 00210 public Object getData() { 00211 return this; 00212 } 00213 00214 public void setData(Object obj) { 00215 throw new RuntimeException("not implemented"); 00216 } 00217 }