📄 cachefilter.java
字号:
// CacheFilter.java// $Id: CacheFilter.java,v 1.12 2000/08/16 21:37:36 ylafon Exp $// (c) COPYRIGHT MIT and INRIA, 1996.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.jigsaw.filters ;import java.util.Dictionary;import java.util.Hashtable;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.PrintStream;import java.net.URL ;import org.w3c.tools.resources.Attribute;import org.w3c.tools.resources.AttributeRegistry;import org.w3c.tools.resources.FilterInterface;import org.w3c.tools.resources.IntegerAttribute;import org.w3c.tools.resources.ProtocolException;import org.w3c.tools.resources.ReplyInterface;import org.w3c.tools.resources.RequestInterface;import org.w3c.tools.resources.Resource;import org.w3c.tools.resources.ResourceFilter;import org.w3c.tools.resources.ProtocolException;import org.w3c.www.http.HTTP;import org.w3c.www.http.HttpEntityMessage;import org.w3c.www.http.HttpEntityTag;import org.w3c.www.http.HttpMessage;import org.w3c.www.http.HttpReplyMessage;import org.w3c.www.http.HttpRequestMessage;import org.w3c.util.AsyncLRUList;import org.w3c.util.LRUList;import org.w3c.util.LRUNode;import org.w3c.jigsaw.http.Reply;import org.w3c.jigsaw.http.Request;class CacheException extends Exception { public CacheException(String msg) { super(msg) ; }}class CacheEntry extends LRUNode { /** The normalized url. (Ready to be used as key) */ private String url ; /** The actual cached content */ byte[] content ; /** The model reply */ Reply reply ; /** The maximum allowed age */ private int maxage ; public String toString() { return "[\"" + url + "\" " + maxage + "]" ; } public final String getURL() { return url ; } public final int getSize() { return content.length ; } private void readContent(Reply reply) throws IOException { ByteArrayOutputStream out = null ; InputStream in = reply.openStream() ; if(reply.hasContentLength()) out = new ByteArrayOutputStream(reply.getContentLength()) ; else out = new ByteArrayOutputStream(8192) ; byte[] buf = new byte[4096] ; int len = 0 ; while( (len = in.read(buf)) != -1) out.write(buf,0,len) ; in.close() ; out.close() ; content = out.toByteArray() ; reply.setStream(new ByteArrayInputStream(content)) ; } /** * Construct a CacheEntry from the given reply, * maybe using the given default max age */ CacheEntry(Request request, Reply reply, int defMaxAge) throws CacheException { url = Cache.getNormalizedURL(request) ; try { readContent(reply) ; } catch(IOException ex) { throw new CacheException("cannot read reply content") ; } this.reply = (Reply) reply.getClone() ; this.reply.setStream((InputStream) null) ; // Set the date artificially, since Jigsaw only sets the date // header on ultimate emission of the reply. long date = this.reply.getDate() ; if(date == -1) { date = System.currentTimeMillis() ; date -= date % 1000 ; this.reply.setDate(date) ; } setMaxAge(reply,defMaxAge) ; } /** * Sets this entry's maxage from available data, or * falls back to the specified default. */ private void setMaxAge(Reply reply, int def) { if( ( maxage = reply.getMaxAge() ) == -1 ) { long exp = reply.getExpires() ; long date = reply.getDate() ; if(exp != -1 && date != -1) { maxage = (int) (reply.getExpires() - reply.getDate()) ; if(maxage<0) maxage = 0 ; } else { maxage = def ; } } } /** * Sets this entry's maxage from available data, or * leaves it unchanged if reply doesn't say anything. */ private void setMaxAge(Reply reply) { setMaxAge(reply,maxage) ; } /** * Make a reply for this entry. */ Reply getReply(Request request) { Reply newReply = (Reply) reply.getClone() ; int age = getAge() ; if(age!=-1) newReply.setAge(age) ; boolean notMod = false ; HttpEntityTag[] etags = request.getIfNoneMatch() ; HttpEntityTag tag = this.reply.getETag() ; if(etags != null && tag != null) { boolean noneMatch = true ; String sTag = tag.getTag() ; for(int i=0;i<etags.length;i++) { if(sTag.equals(etags[i].getTag())) { noneMatch = false ; break ; } } notMod = !noneMatch ; } else { long ims = request.getIfModifiedSince() ; long lmd = this.reply.getLastModified() ; if(ims != -1 && lmd != -1) notMod = lmd > ims ; } if(notMod) { System.out.println("**** replying NOT_MODIFIED") ; newReply.setStatus(HTTP.NOT_MODIFIED) ; } else if(! request.getMethod().equals("HEAD")) newReply.setStream(new ByteArrayInputStream(content)) ; else newReply.setStream((InputStream) null) ; return newReply ; } /** * Returns the age of this entry in seconds, * or -1 if age cannot be determined. */ int getAge() { int age1 = reply.getAge() ; long age2 = -1 ; long date = reply.getDate() ; if(date != -1 ) { age2 = System.currentTimeMillis() ; age2 -= date ; age2 /= 1000 ; } return age1>=age2 ? age1 : (int) age2 ; } /** * Make a reply for this entry, which was validated * by the server with the given reply. */ final Reply getReply(Request request, Reply servReply) { System.out.println("**** Validated entry") ; setMaxAge(servReply) ; long date = servReply.getDate() ; if(date == -1) { date = System.currentTimeMillis() ; date -= date % 1000 ; } this.reply.setDate(date) ; return getReply(request) ; } /** * Turn the given request into a conditional request, * using the appropriate validators (if any). */ void makeConditional(Request request) { System.out.println("**** Making conditional request for validation") ; HttpEntityTag[] et = { reply.getETag() } ; if(et[0] != null) request.setIfNoneMatch(et) ; long lm = reply.getLastModified() ; if(lm != -1) request.setIfModifiedSince(lm) ; } /** * Is this entry fresh, according to the requirements * of the request? */ boolean isFresh(Request request) { int age = getAge() ; System.out.println("**** age: "+age+" maxage: "+maxage) ; return age != -1 ? (maxage > age) : (maxage > 0) ; }}class Cache { private static final String STATE_NORM_URL = "org.w3c.jigsaw.filters.Cache.normURL" ; /** Our maximum size in bytes */ private int maxSize ; /** Our maximum size in entries */ private int maxEntries ; /** Current size in bytes */ private int size ; /** The default max age */ private int defaultMaxAge ; /** * This maps URLs (maybe processed) vs entries */ Dictionary /*<String,CacheEntry>*/ entries ; /** * This keeps track of LRU entries */ LRUList /*<CacheEntry>*/ lruList ; public Cache(int maxSize, int maxEntries, int defaultMaxAge) { this.maxSize = maxSize ; this.maxEntries = maxEntries ; this.defaultMaxAge = defaultMaxAge ; this.size = 0 ; lruList = new AsyncLRUList() ; entries = new Hashtable(20) ; } /** * Stores a new reply in a CacheEntry. * Takes care of handling the LRU list, and of possible overwriting * @exception CacheException fixme doc */ public void store(Request request, Reply reply) throws CacheException { System.out.println("**** Storing reply in cache") ; // Enforce maxEntries if(maxEntries > 0 && entries.size() == maxEntries) flushLRU() ; // Try to enforce maxSize if(maxSize > 0 && reply.hasContentLength()) { int maxEntSize = maxSize - reply.getContentLength() ; while(entries.size() > maxEntSize) if(!flushLRU()) break ; } CacheEntry ce = new CacheEntry(request, reply, defaultMaxAge) ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -