Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You under the Apache License, Version 2.0
   *  (the "License"); you may not use this file except in compliance with
   *  the License.  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
  *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
 
 
 package org.apache.coyote.http11;
 
 import static org.jboss.web.CoyoteMessages.MESSAGES;
 
 
 
Implementation of InputBuffer which provides HTTP request header parsing as well as transfer decoding.

Author(s):
Remy Maucherat
 
 public class InternalAprInputBuffer implements InputBuffer {
 
 
     // ----------------------------------------------------------- Constructors
 

    
Alternate constructor.
 
     public InternalAprInputBuffer(Request requestint headerBufferSizeAprEndpoint endpoint) {
 
         this. = request;
         this. = endpoint;
          = request.getMimeHeaders();
 
          = new byte[headerBufferSize];
          = ByteBuffer.allocateDirect(headerBufferSize);
 
          = new SocketInputBuffer();
 
          = new InputFilter[0];
          = new InputFilter[0];
          = -1;
 
          = true;
          = true;
         
     }
 
 
     // ----------------------------------------------------- Instance Variables
 

    
Associated Coyote request.
 
     protected Request request;


    
Headers of the associated request.
 
     protected MimeHeaders headers;


    
State.
 
     protected boolean parsingHeader;


    
Swallow input ? (in the case of an expectation)
 
     protected boolean swallowInput;


    
Pointer to the current read buffer.
    protected byte[] buf;


    
Last valid byte.
    protected int lastValid;


    
Position in the buffer.
    protected int pos;


    
Pos of the end of the header in the buffer, which is also the start of the body.
    protected int end;


    
Direct byte buffer used to perform actual reading.
    protected ByteBuffer bbuf;


    
Underlying socket.
    protected long socket;


    
Underlying input buffer.
    protected InputBuffer inputStreamInputBuffer;


    
Filter library. Note: Filter[0] is always the "chunked" filter.
    protected InputFilter[] filterLibrary;


    
Active filters (in order).
    protected InputFilter[] activeFilters;


    
Index of the last active filter.
    protected int lastActiveFilter;


    
Non blocking mode.
    protected boolean nonBlocking = false;
    

    
Non blocking mode.
    protected boolean available = false;
    

    
Apr endpoint.
    protected AprEndpoint endpoint = null;
    
    // ------------------------------------------------------------- Properties


    
Set the underlying socket.
    public void setSocket(long socket) {
        this. = socket;
        Socket.setrbb(this.);
    }


    
Get the underlying socket input stream.
    public long getSocket() {
        return ;
    }


    
Set the non blocking flag.
    public void setNonBlocking(boolean nonBlocking) {
        this. = nonBlocking;
    }


    
Get the non blocking flag value.
    public boolean getNonBlocking() {
        return ;
    }


    
Add an input filter to the filter library.
    public void addFilter(InputFilter filter) {
        InputFilter[] newFilterLibrary = 
            new InputFilter[. + 1];
        for (int i = 0; i < .i++) {
            newFilterLibrary[i] = [i];
        }
        newFilterLibrary[.] = filter;
         = newFilterLibrary;
    }


    
Get filters.
    public InputFilter[] getFilters() {
        return ;
    }


    
Clear filters.
    public void clearFilters() {
         = new InputFilter[0];
         = -1;
    }


    
Add an input filter to the filter library.
    public void addActiveFilter(InputFilter filter) {
        if ( == -1) {
            filter.setBuffer();
        } else {
            for (int i = 0; i <= i++) {
                if ([i] == filter)
                    return;
            }
            filter.setBuffer([]);
        }
        [++] = filter;
        filter.setRequest();
    }
    public void removeActiveFilters() {
        // Recycle filters
        for (int i = 0; i <= i++) {
            [i].recycle();
        }
         = -1;
    }


    
Set the swallow input flag.
    public void setSwallowInput(boolean swallowInput) {
        this. = swallowInput;
    }
    // --------------------------------------------------------- Public Methods


    
Recycle the input buffer. This should be called when closing the connection.
    public void recycle() {
        // Recycle Request object
        .recycle();
         = 0;
         = 0;
         = 0;
         = -1;
         = true;
         = true;
         = false;
    }


    
End processing of current HTTP request. Note: All bytes of the current request should have been already consumed. This method only resets all the pointers so that we are ready to parse the next HTTP request.

Returns:
true if there is data left on input (most likely a pipelined request)
    public boolean nextRequest() {
        // Recycle Request object
        .recycle();
        // Copy leftover bytes to the beginning of the buffer
        if ( -  > 0 &&  > 0) {
            int npos = 0;
            int opos = ;
            while ( - opos > opos - npos) {
                System.arraycopy(oposnposopos - npos);
                npos += ;
                opos += ;
            }
            System.arraycopy(oposnpos - opos);
        }
        
        // Recycle filters
        for (int i = 0; i <= i++) {
            [i].recycle();
        }
        // Reset pointers
         =  - ;
         = 0;
         = -1;
         = true;
         = true;
         = false;
         = false;
        return ( > 0);
        
    }


    
End request (consumes leftover bytes).

Throws:
java.io.IOException an undelying I/O error occured
    public void endRequest()
        throws IOException {
        if ( && ( != -1)) {
            int extraBytes = (int[].end();
             =  - extraBytes;
        }
    }


    
Read the request line. This function is meant to be used during the HTTP request header parsing. Do NOT attempt to read the request body using it.

Returns:
true if data is properly fed; false if no data is available immediately and thread should be freed
Throws:
java.io.IOException If an exception occurs during the underlying socket read operations, or if the given buffer is not big enough to accomodate the whole line.
    public boolean parseRequestLine(boolean useAvailableData)
        throws IOException {
        int start = 0;
        //
        // Skipping blank lines
        //
        byte chr = 0;
        do {
            // Read new bytes if needed
            if ( >= ) {
                if (useAvailableData) {
                    return false;
                }
                if (!fill())
                    throw new EOFException(.eofError());
            }
            chr = [++];
        } while ((chr == .) || (chr == .));
        --;
        // Mark the current buffer position
        start = ;
        if ( >= ) {
            if (useAvailableData) {
                return false;
            }
            if (!fill())
                throw new EOFException(.eofError());
        }
        //
        // Reading the method name
        // Method name is always US-ASCII
        //
        boolean space = false;
        while (!space) {
            // Read new bytes if needed
            if ( >= ) {
                if (!fill())
                    throw new EOFException(.eofError());
            }
            // Spec says single SP but it also says be tolerant of HT
            if ([] == . || [] == .) {
                space = true;
                .method().setBytes(start - start);
            }
            ++;
        }
        // Spec says single SP but also says be tolerant of multiple and/or HT
        while (space) {
        	// Read new bytes if needed
        	if ( >= ) {
        		if (!fill())
        			throw new EOFException(.eofError());
        	}
        	if ([] == . || [] == .) {
        		++;
        	} else {
        		space = false;
        	}
        }
        // Mark the current buffer position
        start = ;
        int end = 0;
        int questionPos = -1;
        //
        // Reading the URI
        //
        boolean eol = false;
        while (!space) {
            // Read new bytes if needed
            if ( >= ) {
                if (!fill())
                    throw new EOFException(.eofError());
            }
            // Spec says single SP but it also says be tolerant of HT
            if ([] == . || [] == .) {
                space = true;
                end = ;
            } else if (([] == .
                       || ([] == .)) {
                // HTTP/0.9 style request
                eol = true;
                space = true;
                end = ;
            } else if (([] == .
                       && (questionPos == -1)) {
                questionPos = ;
            }
            ++;
        }
        .unparsedURI().setBytes(startend - start);
        if (questionPos >= 0) {
            .queryString().setBytes(questionPos + 1, 
                                           end - questionPos - 1);
            .requestURI().setBytes(startquestionPos - start);
        } else {
            .requestURI().setBytes(startend - start);
        }
        // Spec says single SP but also says be tolerant of multiple and/or HT
        while (space) {
        	// Read new bytes if needed
        	if ( >= ) {
        		if (!fill())
        			throw new EOFException(.eofError());
        	}
        	if ([] == . || [] == .) {
        		++;
        	} else {
        		space = false;
        	}
        }
        // Mark the current buffer position
        start = ;
        end = 0;
        //
        // Reading the protocol
        // Protocol is always US-ASCII
        //
        while (!eol) {
            // Read new bytes if needed
            if ( >= ) {
                if (!fill())
                    throw new EOFException(.eofError());
            }
            if ([] == .) {
                end = ;
            } else if ([] == .) {
                if (end == 0)
                    end = ;
                eol = true;
            }
            ++;
        }
        if ((end - start) > 0) {
            .protocol().setBytes(startend - start);
        } else {
            .protocol().setString("");
        }
        
        return true;
    }


    
Parse the HTTP headers.
    public void parseHeaders()
        throws IOException {
        while (parseHeader()) {
        }
         = false;
         = ;
    }


    
Parse an HTTP header.

Returns:
false after reading a blank line (which indicates that the HTTP header parsing is done
    public boolean parseHeader()
        throws IOException {
        //
        // Check for blank line
        //
        byte chr = 0;
        while (true) {
            // Read new bytes if needed
            if ( >= ) {
                if (!fill())
                    throw new EOFException(.eofError());
            }
            chr = [];
            if ((chr == .) || (chr == .)) {
                if (chr == .) {
                    ++;
                    return false;
                }
            } else {
                break;
            }
            ++;
        }
        // Mark the current buffer position
        int start = ;
        //
        // Reading the header name
        // Header name is always US-ASCII
        //
        boolean colon = false;
        MessageBytes headerValue = null;
        while (!colon) {
            // Read new bytes if needed
            if ( >= ) {
                if (!fill())
                    throw new EOFException(.eofError());
            }
            if ([] == .) {
                colon = true;
                headerValue = .addValue(start - start);
            }
            chr = [];
            if ((chr >= .) && (chr <= .)) {
                [] = (byte) (chr - .);
            }
            ++;
        }
        // Mark the current buffer position
        start = ;
        int realPos = ;
        //
        // Reading the header value (which can be spanned over multiple lines)
        //
        boolean eol = false;
        boolean validLine = true;
        while (validLine) {
            boolean space = true;
            // Skipping spaces
            while (space) {
                // Read new bytes if needed
                if ( >= ) {
                    if (!fill())
                        throw new EOFException(.eofError());
                }
                if (([] == .) || ([] == .)) {
                    ++;
                } else {
                    space = false;
                }
            }
            int lastSignificantChar = realPos;
            // Reading bytes until the end of the line
            while (!eol) {
                // Read new bytes if needed
                if ( >= ) {
                    if (!fill())
                        throw new EOFException(.eofError());
                }
                if ([] == .) {
                } else if ([] == .) {
                    eol = true;
                } else if ([] == .) {
                    [realPos] = [];
                    realPos++;
                } else {
                    [realPos] = [];
                    realPos++;
                    lastSignificantChar = realPos;
                }
                ++;
            }
            realPos = lastSignificantChar;
            // Checking the first character of the new line. If the character
            // is a LWS, then it's a multiline header
            // Read new bytes if needed
            if ( >= ) {
                if (!fill())
                    throw new EOFException(.eofError());
            }
            chr = [];
            if ((chr != .) && (chr != .)) {
                validLine = false;
            } else {
                eol = false;
                // Copying one extra space in the buffer (since there must
                // be at least one space inserted between the lines)
                [realPos] = chr;
                realPos++;
            }
        }
        // Set the header value
        headerValue.setBytes(startrealPos - start);
        return true;
    }

    
    
Available bytes (note that due to encoding, this may not correspond )
    public void useAvailable() {
         = true;
    }


    
Available bytes in the buffer ? (these may not translate to application readable data)
    public boolean available() {
        return ( -  > 0);
    }
    // ---------------------------------------------------- InputBuffer Methods


    
Read some bytes.
    public int doRead(ByteChunk chunkRequest req
        throws IOException {
        if ( == -1)
            return .doRead(chunkreq);
        else
            return [].doRead(chunk,req);
    }
    // ------------------------------------------------------ Protected Methods


    
Fill the internal buffer using data from the undelying input stream.

Returns:
false if at end of stream
    protected boolean fill()
        throws IOException {
        int nRead = 0;
        if () {
            if ( == .) {
                throw .requestHeaderTooLarge();
            }
            .clear();
            nRead = Socket.recvbb(, 0, . - );
            if (nRead > 0) {
                .limit(nRead);
                .get(nRead);
                 =  + nRead;
            } else {
                if ((-nRead) == .) {
                    return false;
                } else {
                    throw new IOException(.failedRead());
                }
            }
        } else {
            if (. -  < 4500) {
                // In this case, the request header was really large, so we allocate a 
                // brand new one; the old one will get GCed when subsequent requests
                // clear all references
                 = new byte[.];
                 = 0;
            }
             = ;
             = ;
            .clear();
            nRead = Socket.recvbb(, 0, . - );
            if (nRead > 0) {
                .limit(nRead);
                .get(nRead);
                 =  + nRead;
            } else if (nRead <= 0) {
                if ((-nRead) == . || (-nRead) == .) {
                    throw new SocketTimeoutException(.failedRead());
                } else if ((-nRead) == . && ) {
                    // As asynchronous reads are forbidden, this test is not useful
                    // && (Http11AprProcessor.containerThread.get() == Boolean.TRUE)
                    if () {
                        nRead = 0;
                    } else {
                        // In this specific situation, perform the read again in blocking mode (the user is not
                        // using available and simply wants to read all data)
                        nRead = Socket.recvbbt(, 0, . - .getSoTimeout() * 1000);
                        if (nRead > 0) {
                            .limit(nRead);
                            .get(nRead);
                             =  + nRead;
                        } else if (nRead <= 0) {
                            if ((-nRead) == . || (-nRead) == .) {
                                throw new SocketTimeoutException(.failedRead());
                            } else {
                                throw new IOException(.failedRead());
                            }
                        }
                    }
                } else {
                    throw new IOException(.failedRead());
                }
            }
             = false;
        }
        return (nRead >= 0);
    }
    // ------------------------------------- InputStreamInputBuffer Inner Class


    
This class is an input buffer which will read its data from an input stream.
    protected class SocketInputBuffer 
        implements InputBuffer {


        
Read bytes into the specified chunk.
        public int doRead(ByteChunk chunkRequest req ) 
            throws IOException {
            if ( >= ) {
                if (!fill())
                    return -1;
            }
            int length =  - ;
            chunk.setBytes(length);
             = ;
            return (length);
        }
    }
New to GrepCode? Check out our FAQ X