⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplecachefilter.java

📁 很棒的web服务器源代码
💻 JAVA
字号:
// SimpleCacheFilter.java// $Id: SimpleCacheFilter.java,v 1.11 2000/08/17 12:27:12 ylafon Exp $  // (c) COPYRIGHT MIT and INRIA, 1997.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.jigsaw.filters ;import java.io.ByteArrayOutputStream;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.OutputStream;import java.net.URL ;import java.util.Dictionary;import java.util.Hashtable;import org.w3c.tools.resources.Attribute;import org.w3c.tools.resources.AttributeHolder;import org.w3c.tools.resources.AttributeRegistry;import org.w3c.tools.resources.BooleanAttribute;import org.w3c.tools.resources.FilterInterface;import org.w3c.tools.resources.FramedResource;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.ResourceFilter;import org.w3c.www.http.HTTP;import org.w3c.www.http.HttpMessage;import org.w3c.www.http.HttpReplyMessage;import org.w3c.www.http.HttpRequestMessage;import org.w3c.jigsaw.http.Client;import org.w3c.jigsaw.http.Reply;import org.w3c.jigsaw.http.Request;import org.w3c.util.LRUNode;import org.w3c.util.LRUList;import org.w3c.util.AsyncLRUList;final class SimpleCacheException extends Exception {    public SimpleCacheException(String msg) { super(msg) ; }}final class SimpleCacheEntry extends LRUNode {    /** The cache that we belong to */    SimpleCacheFilter filter ;    /** The stripped URL to be used as key */    private String url ;    /** The actual cached reply     * (status line, headers, and content) */    private byte[] replyText ;    /** The date of caching */    protected long date ;    public String toString()    {	return "[\"" + url + "\"]" ;    }	    public final String getURL()    {	return url ;    }    SimpleCacheEntry(Request request,Reply reply, SimpleCacheFilter filter)	throws SimpleCacheException    {	url = SimpleCache.getNormalizedURL(request) ;	this.filter = filter ;	try {	    readReply(reply) ;	} catch(IOException ex) {	    throw new SimpleCacheException("cannot read reply content") ;	}		date = System.currentTimeMillis() ;	date -= date % 1000 ;    }    boolean isFresh() {	int freshness = (int) ((System.currentTimeMillis() - date) / 1000 ) ;	return freshness < filter.getDefaultMaxAge() ;    }	        public final int getSize()    {	return replyText.length ;    }    private void readReply(Reply reply)	throws IOException    {	int len = -1 ;	if(reply.hasContentLength()) 	    len = reply.getContentLength() + 500 ;	else 	    len = 8192 ;	ByteArrayOutputStream out = new ByteArrayOutputStream(len) ;		reply.dump(out) ;	out.close() ;	replyText = out.toByteArray() ;	reply.setStatus(HTTP.NOHEADER) ;	reply.setStream(new ByteArrayInputStream(replyText)) ;    }    public final void dump(OutputStream out)	throws IOException    {	out.write(replyText) ;    }}final class SimpleCache {    /** The filter that owns this cache */    private SimpleCacheFilter filter ;    /** Current stored size, in bytes */    private int size ;    /** This maps stripped URLs vs entries */    private Dictionary /*<String,SimpleCacheEntry*/ entries ;    /** This keeps track of LRU entries */    private LRUList /*<SimpleCacheEntry>*/ lruList ;    public SimpleCache(SimpleCacheFilter filter) {	this.filter = filter ;	this.size = 0 ;	lruList = new AsyncLRUList() ;	entries = new Hashtable(20) ;    }    public SimpleCacheEntry store(Request request,Reply reply)	throws SimpleCacheException    {	if(SimpleCacheFilter.debug)	    System.out.println("**** Storing reply in cache") ;	// Enforce maxEntries	int maxEntries = filter.getMaxEntries() ;	if(maxEntries > 0 && entries.size() == maxEntries)	    flushLRU() ;	SimpleCacheEntry ce = new SimpleCacheEntry(request,reply,filter) ;	// Enforce maxSize (sort of)	int ceSize = ce.getSize() ;	int maxSize = filter.getMaxSize() ;	if(maxSize > 0) {	    if(ceSize > maxSize) return null ;	    int maxEntSize = maxSize - ceSize ;	    while(entries.size() > maxEntSize)		if(!flushLRU()) break ;	}	synchronized(this) {	    size += ceSize ;	    SimpleCacheEntry old = (SimpleCacheEntry)		entries.put(ce.getURL(),ce) ;	    if(old!=null) lruList.remove(old) ;	    lruList.toHead(ce) ;	}	return ce ;    }    public SimpleCacheEntry retrieve(Request request)    {	String url = getNormalizedURL(request) ;	SimpleCacheEntry ce = (SimpleCacheEntry) entries.get(url) ;	if(ce==null) return null ;	if(!ce.isFresh()) {	    lruList.remove(ce) ;	    entries.remove(url) ;	}	lruList.toHead(ce) ;	return ce ;    }    public synchronized void remove(Request request)    {	if(SimpleCacheFilter.debug)	    System.out.println("**** Removing from cache") ;	SimpleCacheEntry ce = (SimpleCacheEntry)	    entries.remove(getNormalizedURL(request)) ;	if(ce==null) return ;	lruList.remove(ce) ;    }    private synchronized final boolean flushLRU()    {	if(entries.size() == 0) return false ;	if(SimpleCacheFilter.debug)	    System.out.println("**** flushing LRU entry") ;	SimpleCacheEntry ce = (SimpleCacheEntry)	    lruList.removeTail() ;	entries.remove(ce.getURL()) ;	size -= ce.getSize() ;		return true ;    }	    static final String getNormalizedURL(Request request)    {	return request.getURL().getFile() ;    }}public class SimpleCacheFilter extends ResourceFilter {    static final boolean debug = true ;     protected SimpleCache cache = null ;    protected final static String STATE_TAG	= "org.w3c.jigsaw.filter.SimpleCacheFilter.tag" ;    protected static int ATTR_MAX_SIZE = -1 ;    protected static int ATTR_MAX_ENTRIES = -1 ;    protected static int ATTR_DEFAULT_MAX_AGE = -1 ;    protected static int ATTR_FLUSH = -1 ;    static {	Attribute a   = null;	Class     cls = null;		try {	    cls = Class.forName("org.w3c.jigsaw.filters.SimpleCacheFilter");	} catch (Exception ex) {	    ex.printStackTrace();	    System.exit(1);	}	// Declare the maximum cache size attribute:	a = new IntegerAttribute("maxSize"				 , new Integer(8192)				 , Attribute.EDITABLE);	ATTR_MAX_SIZE= AttributeRegistry.registerAttribute(cls, a);	// Declare the maximum number of entries attribute:	a = new IntegerAttribute("maxEntries"				 , new Integer(-1)				 , Attribute.EDITABLE);	ATTR_MAX_ENTRIES = AttributeRegistry.registerAttribute(cls, a);	// Declare the default maxage attribute	a = new IntegerAttribute("defaultMaxAge"				 , new Integer(300) // 5min				 , Attribute.EDITABLE);	ATTR_DEFAULT_MAX_AGE = AttributeRegistry.registerAttribute(cls, a);	// Declare flush flag attribute	a = new BooleanAttribute("flush"				 , Boolean.FALSE				 , Attribute.EDITABLE) ;	ATTR_FLUSH = AttributeRegistry.registerAttribute(cls, a) ;    }    public int getMaxSize()    {	return getInt(ATTR_MAX_SIZE, 8192);    }    public int getMaxEntries()    {	return getInt(ATTR_MAX_ENTRIES, -1);    }    public int getDefaultMaxAge()     {	return getInt(ATTR_DEFAULT_MAX_AGE, 300);    }	    public boolean getFlushFlag()    {	return getBoolean(ATTR_DEFAULT_MAX_AGE, false) ;    }    private final void tag(Request request)    {	request.setState(STATE_TAG,Boolean.TRUE) ;    }    private final boolean isTagged(Request request)    {	return request.hasState(STATE_TAG) ;    }    private Reply applyIn(Request request,			  FilterInterface[] filters,			  int fidx)	throws ProtocolException    {	// Apply remaining ingoing filters	Reply fr = null ;	for(int i = fidx+1 ;	    i<filters.length && filters[i] != null ;	    ++i) {	    fr = (Reply) (filters[i].ingoingFilter(request, filters, i)) ;	    if(fr != null) 		return fr ;	}	return null ;    }    private Reply applyOut(Request request,			   Reply reply,			   FilterInterface[] filters,			   int fidx)	throws ProtocolException    {	Reply fr = null ;	for(int i=fidx-1;	    i>=0 && filters[i] != null;	    i--) {	    fr = (Reply) (filters[i].outgoingFilter(request,reply,filters,i)) ;	    if(fr != null)		return fr ;	}	return null ;    }    /**     * Apply outgoing filters, except the skipth one     */    private Reply applyOutSkip(Request request,			       Reply reply,			       FilterInterface[] filters,			       int skip)	throws ProtocolException    {	Reply fr = null ;	for(int i = filters.length-1 ;	    i>=0 && i!=skip && filters[i] != null ;	    i--) {	    fr = (Reply) (filters[i].outgoingFilter(request,reply,filters,i)) ;	    if(fr != null)		return fr ;	}	return null ;    }    /**     * @return A Reply instance, if the filter did know how to answer     * the request without further processing, <strong>null</strong>      * otherwise.      * @exception org.w3c.tools.resources.ProtocolException      * If processing should be interrupted,     * because an abnormal situation occured.      */     public ReplyInterface ingoingFilter(RequestInterface req,					FilterInterface[] filters,					int fidx)	throws ProtocolException    {	Request request = (Request) req;	String method = request.getMethod() ;		if(! method.equals("GET") )	    return null ;		tag(request) ;		if(isCachable(request)) {	    SimpleCacheEntry ent = cache.retrieve(request) ;	    if(ent != null) {		Reply fRep = null ;		fRep = applyIn(request,filters,fidx) ;		if(fRep != null) return fRep ;				Reply reply = request.makeReply(HTTP.NOHEADER) ;				fRep = applyOutSkip(request,reply,filters,fidx) ;		if(fRep != null) return fRep ;				try {		    ent.dump(request.getClient().getOutputStream()) ;		} catch(IOException ex) {		    return null ;		}		return reply ;	    }	}		return null ;    }    /**     * @param request The original request.     * @param reply It's original reply.      * @return A Reply instance, or <strong>null</strong> if processing      * should continue normally.      * @exception ProtocolException If processing should be interrupted,       * because an abnormal situation occured.      */    public ReplyInterface outgoingFilter(RequestInterface req,					 ReplyInterface rep,					 FilterInterface[] filters,					 int fidx)	throws ProtocolException    {	Request request = (Request) req;	Reply   reply   = (Reply) rep;	if(!isTagged(request))	    return null ;		if(isCachable(reply)) {	    switch(reply.getStatus()) {	    case HTTP.OK:	    case HTTP.NO_CONTENT:	    case HTTP.MULTIPLE_CHOICE:	    case HTTP.MOVED_PERMANENTLY:		try {		    SimpleCacheEntry ce = cache.store(request,reply) ;		    if(ce != null) {			// storing a reply changes it, so this must be done:			Reply fRep = applyOut(request,reply,filters,fidx) ;			if(fRep != null) return fRep ;			else return reply ;		    }		} catch(SimpleCacheException ex) {		    cache.remove(request) ;		}		break ;	    default:		cache.remove(request) ;	    }	} else {	    cache.remove(request) ;	}			return null ;    }	        private boolean isCachable(HttpMessage hmsg)    {	if(hmsg.getCacheControl() != null) return false ;	String prgm[] = hmsg.getPragma() ;	if(prgm!=null)	    for(int i=0;i<prgm.length;i++)		if(prgm[i].equals("no-cache")) return false ;		return true ;    }						       public void initialize(Object values[]) {	super.initialize(values) ;	cache = new SimpleCache(this) ;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -