ssiframe.java

来自「很棒的web服务器源代码」· Java 代码 · 共 938 行 · 第 1/2 页

JAVA
938
字号
    /**     * Returns an instance of the given command registry class,     * either a new instance, or an old one if it exists in the dictionary.     * @exception SSIException If the operation can't be performed.     */    private CommandRegistry fetchRegistry(Class regClass)	throws SSIException    {	try {	    CommandRegistry reg = (CommandRegistry) regs.get(regClass) ;	    if(reg!=null) 		return reg;	    else {		reg = (CommandRegistry) regClass.newInstance();		regs.put(regClass,reg) ;		return reg;	    }	} catch(Exception ex) {	    throw new SSIException("Cannot fetch command registry: "+				   ex.getMessage()) ;	}    }    /** Reads the unparsed file into memory, if not already done */    private byte[] readUnparsed()	throws IOException    {	File file = fresource.getFile();	ByteArrayOutputStream out =	    new ByteArrayOutputStream((int)file.length()) ;		FileInputStream in = new FileInputStream(file);	byte[] buf = new byte[4096] ;	int len = 0;		while( (len = in.read(buf)) != -1) 	    out.write(buf,0,len);		in.close();	out.close();		byte[] unparsed = out.toByteArray() ;	return unparsed ;    }	    /**     * Does a first-time parse and sets the segment list attribute     * accordingly.     */    private void parseFirstTime()    {	if (debug)	    System.out.println("@@@ parseFirstTime");	cacheReplies = true;	byte[] unparsed = null ;	try {	    unparsed = readUnparsed() ;	} catch(IOException ex) {	    setValue(ATTR_SEGMENTS,null) ;	    return ;	}	// The parsing code was adapted from phttpd 		int byteIdx = 0, startInc, endInc, startParam, endParam, paramIdx,i ;	byte ch, quote ;	int max ,length = 0;	boolean valueFound ;		int unparsedSize = 0 ;		// For maintaining the segment list 	Vector buildSegments = new Vector(20) ;	StringBuffer cmdBuf = null ;	String cmdName = null ;	Vector /*<String>*/ parNames = null ;	Vector /*<String>*/ parValues = null ;	String name = null , value = null ;		// To store where the last segment ended	int lastSegEnd = 0;	do {	    byteIdx += 4;	    while(byteIdx < unparsed.length) {		if( (ch = unparsed[byteIdx]) == (byte) '#' )		    if(byteArrayNEquals(unparsed, byteIdx-4,					startPat, 0,					4)) {			break;		    }		// This is an ugly work-around to the		// absence of unsigned bytes in Java.		byteIdx += startIncrements[ch>=0 ? ch : 0];	    }	    if(++byteIdx >= unparsed.length)		break; // Nothing found	    	    // Record the start of the command name and parameter list	    startInc = (startParam = paramIdx = byteIdx) - 5 ;	    	    // Add the previous segment of unparsed text	    // (Unless empty)	    if(startInc > lastSegEnd) {		buildSegments.addElement(new Segment(lastSegEnd,						     startInc));		unparsedSize += startInc - lastSegEnd ;		lastSegEnd = startInc ;	    }	    // Now find the end of the comment	    byteIdx += 2;	    while(byteIdx < unparsed.length) {		if( (ch = unparsed[byteIdx]) == (byte) '>')		    if(unparsed[byteIdx-2] == (byte) '-' &&		       unparsed[byteIdx-1] == (byte) '-')			break;		// This is an ugly work-around to the absence of		// unsigned bytes in Java:		byteIdx += endIncrements[ch>=0 ? ch : 0] ;	    }	    if(++byteIdx >= unparsed.length)		break; // No end found	    // The end of the parameter list is 3 bytes earlier	    endParam = byteIdx - 3 ;	    	    // Record the nominal end of the command segment	    endInc = byteIdx ;	    // Skip white space before command 	    while(paramIdx < endParam && isSpace(unparsed[paramIdx]) )		paramIdx++;	    if( paramIdx >= endParam )		continue; // No command name	    	    max = endParam - paramIdx ;	    cmdName = parseCmdName(unparsed,paramIdx,max) ;	    // If not found, take this one as unparsed and	    // search for the next include.	    if(cmdName == null) {		buildSegments.addElement(new Segment(startInc,						     endInc));		unparsedSize += endInc - startInc ;		lastSegEnd = endInc ;		continue;	    }	    parNames = new Vector(5) ;	    parValues = new Vector(5) ;	    parseCmdParams(unparsed,			   paramIdx+cmdName.length(),			   endParam,			   parNames,parValues) ;	    buildSegments.addElement( new Segment(this,						  cmdName,						  new						  ArrayDictionary(parNames,								  parValues),						  lastSegEnd,						  endInc)) ;	    lastSegEnd = endInc ;	    	} while(byteIdx < unparsed.length) ;			// Add the last chunk of unparsed text as a segment	buildSegments.addElement(new Segment(lastSegEnd,					     unparsed.length));	unparsedSize += unparsed.length - lastSegEnd ;	setUnparsedSize(unparsedSize) ;		Segment[] segs = new Segment[buildSegments.size()] ;	buildSegments.copyInto(segs) ;	setValue(ATTR_SEGMENTS,segs) ;    }    private final String parseCmdName(byte[] unparsed,int start,int max)    {	StringBuffer cmdBuf = new StringBuffer(80) ;	char ch ;	for(int i=0;i<max;i++) {	    ch = (char) unparsed[start+i];	    if(Character.isWhitespace(ch)) break ;	    cmdBuf.append(ch) ;	}	return cmdBuf.length() == 0? null : cmdBuf.toString() ;    }    private final void parseCmdParams(byte[] unparsed,				      int start,int end,				      Vector names,Vector values)    {	String name = null ;	String value = null ;	int startParam = -1 ;	int paramIdx = start ;	while(paramIdx < end) {	    while(isSpace(unparsed[paramIdx++]))		;	    if(paramIdx >= end)		break;	    	    byte ch = unparsed[--paramIdx];	    startParam = paramIdx;	    while(paramIdx < end		  && !isSpace(ch)		  && ch != (byte) '=')		ch = unparsed[++paramIdx];	    	    int length = paramIdx - startParam ;	    if(length<=0) break;	    	    name = new String(unparsed,0,startParam,length) ;	    value =  emptyString ;	    	    boolean valueFound = false ;	    while(isSpace(ch)		  || ch == (byte) '=') {		if(ch == (byte) '=')		    valueFound = true ;		ch = unparsed[++paramIdx] ;	    }	    	    if(paramIdx >= end)		valueFound = false ;	    byte quote ;	    if(valueFound)		if(ch == '"' || ch == '\'' ) {		    quote = ch ;		    ch = unparsed[++paramIdx];		    		    startParam = paramIdx ;		    while(paramIdx < end && ch != quote )			ch = unparsed[++paramIdx];		    length = paramIdx - startParam ;		    value = new String(unparsed,				       0,				       startParam,				       length);		    paramIdx++ ;  		} else {		    startParam = paramIdx ;		    while(paramIdx < end			  && ! isSpace(ch))			ch = unparsed[++paramIdx];		    length = paramIdx - startParam ;		    value = new String (unparsed,					0,					startParam,					length);		}	    names.addElement(name) ;	    values.addElement(value) ;	}	    }	    /**     * Analogous to standard C's <code>strncmp</code>, for byte arrays.     * (Should be in some utility package, I'll put it here for now)     * @param ba1 the first byte array     * @param off1 where to start in the first array     * @param ba2 the second byte array     * @param off2 where to start in the second array     * @param n the length to compare up to     * @return <strong>true</strong> if both specified parts of the arrays are     *           equal, <strong>false</strong> if they aren't .     */    public static final boolean byteArrayNEquals(byte[] ba1, int off1,						 byte[] ba2, int off2,						 int n)    {	// So that only one addition is needed inside loop	int corr = off2 - off1;	int max = n+off1;	for(int i=off1;i<max;i++) 	    if(ba1[i] != ba2[i+corr])		return false;	return true;    }    /**     * Does the same as Character.isSpace, without need to cast the     * byte into a char.     * @param ch the character     * @return whether or not ch is ASCII white space     * @see java.lang.Character#isSpace     */    private final boolean isSpace(byte ch)    {	return ch==' ' || ch=='\t' || ch=='\n' || ch=='\r' ;    }    public long getLastModified()    //FIXME    {	long a = super.getLastModified() ;	return a - a % 1000 ;    }    public final Reply createDefaultReply(Request request, int status)    {	Reply reply = super.createDefaultReply(request,status) ;	reply.setHeaderValue(Reply.H_LAST_MODIFIED,null) ;	reply.setKeepConnection(false);	return reply ;    }    public final Reply createCommandReply(Request request, int status)    {	return createDefaultReply(request,status) ;    }    static {	// Initialize search increments first	for(int i=0;i<128;i++) {	    startIncrements[i] = 5 ;	    endIncrements[i] = 3 ;	}	startIncrements[(int)('<')] = 4;	startIncrements[(int)('!')] = 3;	startIncrements[(int)('-')] = 1;	endIncrements[(int)('-')] = 1;	// Initialize attributes	Attribute a = null;	Class cls = null;	Class regClass = null ;	try {	    cls = Class.forName("org.w3c.jigsaw.ssi.SSIFrame") ;	    regClass = 	  Class.forName("org.w3c.jigsaw.ssi.commands.DefaultCommandRegistry") ;	} catch (Exception ex) {	    ex.printStackTrace();	    System.exit(0);	}	// The maxDepth attribute	a = new IntegerAttribute("maxDepth"				 , new Integer(10)				 , Attribute.EDITABLE) ;	ATTR_MAX_DEPTH = AttributeRegistry.registerAttribute(cls,a) ;	// The secure attribute	a = new BooleanAttribute("secure"				 , Boolean.TRUE				 , Attribute.EDITABLE) ;	ATTR_SECURE = AttributeRegistry.registerAttribute(cls,a) ;	// The segments attribute	a = new SegmentArrayAttribute("segments"				      , null				      , Attribute.COMPUTED) ;	ATTR_SEGMENTS = AttributeRegistry.registerAttribute(cls,a) ;	// The unparsedSize attribute	a = new IntegerAttribute("unparsedSize"				 , null				 , Attribute.COMPUTED) ;	ATTR_UNPARSED_SIZE = AttributeRegistry.registerAttribute(cls,a) ;	// The registryClass attribute	a = new ClassAttribute("registryClass"			       , regClass			       , Attribute.EDITABLE ) ;	ATTR_REGISTRY_CLASS = AttributeRegistry.registerAttribute(cls,a) ;    }}/** * Merger classes are used to provide callbacks and make * header merging more uniform. (Though it may be overkill...) */abstract class Merger {    abstract HeaderValue merge(HeaderValue g,HeaderValue p) ;}class IntMaximizer extends Merger {    HeaderValue merge(HeaderValue g,HeaderValue p)    {	if(p != null) {	    if(g != null) {		((HttpInteger) g)		    .setValue(Math.max( ((Integer) g.getValue()).intValue() ,				      ((Integer) p.getValue()).intValue()  )) ;	    } else return p ;	}	return g ;    }}	    class IntMinimizer extends Merger {    HeaderValue merge(HeaderValue g,HeaderValue p)    {	if(p != null) {	    if(g != null) {		((HttpInteger) g)		    .setValue(Math.min(((Integer) g.getValue()).intValue() ,					((Integer) p.getValue()).intValue())) ;	    } else return p ;	}	return g ;    }}class IntAdder extends Merger {    HeaderValue merge(HeaderValue g,HeaderValue p) {	if(SSIFrame.debug)	    System.out.println("&&&& Adder: g="+g+", p="+p) ;	if(g != null) {	    if(p != null) {		int b = ((Integer) g.getValue()).intValue() +			       ((Integer) p.getValue()).intValue() ;		((HttpInteger) g)		    .setValue( b  ) ;	    } else return null ;	}	return g ;    }}class DateMinimizer extends Merger {    HeaderValue merge(HeaderValue g,HeaderValue p)    {	if(p != null) {	    if(g != null) {		((HttpDate) g)		    .setValue(Math.min(((Long) g.getValue()).longValue() ,				       ((Long) p.getValue()).longValue())) ;	    } else return p ;	}	return g ;    }}class DateMaximizer extends Merger {    HeaderValue merge(HeaderValue g,HeaderValue p)    {	if(p != null) {	    if(g != null) {	        ((HttpDate) g)		    .setValue(Math.max(  ((Long) g.getValue()).longValue() ,					 ((Long) p.getValue()).longValue())) ;	    } else return p ;	}	return g ;    }}	

⌨️ 快捷键说明

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