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 + -
显示快捷键?