Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2013 Red Hat, Inc., and individual contributors
   * as indicated by the @author tags.
   *
   * Licensed 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;
 
 import  java.nio.channels.CompletionHandler;
 
InternalNioOutputBuffer Created on Dec 16, 2011 at 9:15:05 AM

Author(s):
Nabil Benothman
 
 public class InternalNioOutputBuffer implements OutputBuffer {

    
Associated Coyote response.
 
     protected Response response;

    
Headers of the associated request.
 
     protected MimeHeaders headers;

    
Committed flag.
 
     protected boolean committed;

    
Finished flag.
 
     protected boolean finished;

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

    
Position in the buffer.
 
     protected int pos;

    
Underlying output buffer.
 
     protected OutputBuffer outputBuffer;

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

    
Active filter (which is actually the top of the pipeline).
 
     protected OutputFilter[] activeFilters;

    
Index of the last active filter.
 
    protected int lastActiveFilter;

    
Direct byte buffer used for writing.
    protected ByteBuffer bbuf = null;

    
Leftover bytes which could not be written during a non blocking write.
    protected ByteChunk leftover = null;

    
Non blocking mode.
    protected boolean nonBlocking = false;

    
Write timeout
    protected int writeTimeout = -1;

Underlying channel.
	protected NioChannel channel;

NIO endpoint.
	protected NioEndpoint endpoint;

    
NIO processor.
    protected Http11NioProcessor processor;

The completion handler used for asynchronous write operations
	private CompletionHandler<IntegerNioChannelcompletionHandler;

    
Semaphore used for waiting for completion handler.
    private Semaphore semaphore = new Semaphore(1);

    
Associated write listener for upgrade mode.
    private WriteListener listener = null;
    
Create a new instance of InternalNioOutputBuffer

Parameters:
response
headerBufferSize
endpoint
	public InternalNioOutputBuffer(Http11NioProcessor processorResponse responseint headerBufferSizeNioEndpoint endpoint) {
        this. = response;
        this. = response.getMimeHeaders();
         = new byte[headerBufferSize];
         = ByteBuffer.allocateDirect(headerBufferSize);
         = new OutputBufferImpl();
         = new OutputFilter[0];
         = new OutputFilter[0];
         = -1;
         = false;
         = false;
         = new ByteChunk();
         = false;
        this. = endpoint;
        this. = processor;
        // Initialize the input buffer
        this.init();
        // Cause loading of HttpMessages
        HttpMessages.getMessage(200);
        // Cause loading of constants
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.apache.coyote.http11.AbstractInternalOutputBuffer#init()
	 */
	protected void init() {
		this. = new CompletionHandler<IntegerNioChannel>() {
			public void completed(Integer nBytesNioChannel attachment) {
                if (nBytes < 0) {
                    failed(new IOException(.failedWrite()), attachment);
                    return;
                }
                boolean notify = false;
                boolean write = false;
                synchronized () {
                    if (!bbuf.hasRemaining()) {
                        bbuf.clear();
                        if (leftover.getLength() > 0) {
                            int n = Math.min(leftover.getLength(), bbuf.remaining());
                            bbuf.put(leftover.getBuffer(), leftover.getOffset(), n).flip();
                            leftover.setOffset(leftover.getOffset() + n);
                            write = true;
                        } else {
                            response.setLastWrite(nBytes);
                            leftover.recycle();
                            semaphore.release();
                            if (processor.getWriteNotification()) {
                                notify = true;
                            }
                        }
                    } else {
                        write = true;
                    }
                }
                if (write) {
                    attachment.write(.attachmentthis);
                }
                if (notify) {
                    if ( == null) {
                        if (!.processChannel(attachment.)) {
                            .closeChannel(attachment);
                        }
                    } else {
                        Thread thread = Thread.currentThread();
                        ClassLoader originalClassLoader = thread.getContextClassLoader();
                        try {
                            thread.setContextClassLoader(.getClass().getClassLoader());
                            synchronized (.getWriteLock()) {
                                .onWritePossible();
                            }
                        } catch (Exception e) {
                            .getResponse().setErrorException(e);
                            .removeEventChannel(attachment);
                            if (!.processChannel(attachment.)) {
                                .closeChannel(attachment);
                            }
                        } finally {
                            thread.setContextClassLoader(originalClassLoader);
                        }
                    }
                }
			}
			public void failed(Throwable excNioChannel attachment) {
                .getResponse().setErrorException(exc);
                .release();
				if (!.processChannel(attachment.)) {
				    .closeChannel(attachment);
				}
			}
		};
	}

Set the underlying socket.

Parameters:
channel
	public void setChannel(NioChannel channel) {
		this. = channel;
	}

Get the underlying socket input stream.

Returns:
the channel
	public NioChannel getChannel() {
		return ;
	}

Close the channel

Parameters:
channel
	private void close(NioChannel channel) {
	}

Perform a blocking write operation

Parameters:
buffer the buffer containing the data to write
timeout a timeout for the operation
unit The time unit
Returns:
the number of bytes written, -1 in case of errors
	private int blockingWrite(long timeoutTimeUnit unit) {
		int nw = 0;
		try {
			nw = this..writeBytes(this.timeoutunit);
			if (nw < 0) {
			}
catch (Throwable t) {
	             ..errorWithBlockingWrite(t);
			}
		}
		return nw;
	}

    
Perform a write operation. The operation may be blocking or non-blocking depending on the value of nonBlocking flag.

Parameters:
timeout a timeout for the operation
unit The time unit of the timeout
Returns:
	protected int write(final long timeoutfinal TimeUnit unit) {
		return blockingWrite(timeoutunit);
	}

    
Send an acknowledgment.

Throws:
Exception
	public void sendAck() throws Exception {
		if (!) {
			this..clear();
			if (this.write(.) < 0) {
			}
		}
	}

    
Write the contents of a byte chunk.

Parameters:
chunk byte chunk
Returns:
number of bytes written
Throws:
IOException an undelying I/O error occured
	public int doWrite(ByteChunk chunkResponse resthrows IOException {
		if (!) {
			// Send the connector a request for commit. The connector should
			// then validate the headers, send them (using sendHeaders) and
			// set the filters accordingly.
		}
		if ( == -1) {
			return .doWrite(chunkres);
else {
			return [].doWrite(chunkres);
		}
	}

    
Callback to write data from the buffer.
	protected void flushBuffer() throws IOException {
		int res = 0;
		if (! && .position() > 0) {
			while (.hasRemaining()) {
			    if (res <= 0) {
			        break;
			    }
			}
			if (res < 0) {
			}
		}
	}

   
Set the non blocking flag.

Parameters:
nonBlocking
    public void setNonBlocking(boolean nonBlocking) {
        this. = nonBlocking;
    }

    
Get the non blocking flag value.

Returns:
non blocking
    public boolean getNonBlocking() {
        return ;
    }

    
Set the associated write listener for upgrade mode.
    public void setWriteListener(WriteListener listener) {
        this. = listener;
    }

    
Add an output filter to the filter library.

Parameters:
filter
    public void addFilter(OutputFilter filter) {
        OutputFilter[] newFilterLibrary = new OutputFilter[. + 1];
        for (int i = 0; i < .i++) {
            newFilterLibrary[i] = [i];
        }
        newFilterLibrary[.] = filter;
         = newFilterLibrary;
    }

    
Get filters.

Returns:
the list of filters
    public OutputFilter[] getFilters() {
        return ;
    }

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

    
Add an output filter to the filter library.

Parameters:
filter
    public void addActiveFilter(OutputFilter filter) {
        if ( == -1) {
            filter.setBuffer();
        } else {
            for (int i = 0; i <= i++) {
                if ([i] == filter)
                    return;
            }
            filter.setBuffer([]);
        }
        [++] = filter;
        filter.setResponse();
    }
    public void removeActiveFilters() {
        // Recycle filters
        for (int i = 0; i <= i++) {
            [i].recycle();
        }
         = -1;
         = .;
    }

    
Flush the response.

Throws:
IOException an undelying I/O error occured
    public void flush() throws IOException {
        if (!) {
            // Send the connector a request for commit. The connector should
            // then validate the headers, send them (using sendHeader) and
            // set the filters accordingly.
            .action(.null);
        }
        // Flush the current buffer
        flushBuffer();
    }


    
Recycle this object
    public void recycle() {
         = null;
        // Recycle Request object
        .recycle();
         = 0;
         = -1;
         = false;
         = false;
         = null;
        if (.availablePermits() != 1) {
            .drainPermits();
            .release();
        }
         = (.getSoTimeout() > 0 ? .getSoTimeout()
                : .);
    }

    
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.
    public void nextRequest() {
        // Recycle Request object
        .recycle();
        // Recycle filters
        for (int i = 0; i <= i++) {
            [i].recycle();
        }
        // Reset pointers
        byte[] leftoverBuf = .getBuffer();
        if (leftoverBuf != null && leftoverBuf.length > .) {
             = new ByteChunk();
        } else {
            .recycle();
        }
         = 0;
         = -1;
         = false;
         = false;
         = false;
    }

    
End request.

Throws:
IOException an undelying I/O error occured
    public void endRequest() throws IOException {
        if (!) {
            // Send the connector a request for commit. The connector should
            // then validate the headers, send them (using sendHeader) and
            // set the filters accordingly.
            .action(.null);
        }
        if () {
            return;
        }
        if ( != -1) {
            [].end();
        }
        flushBuffer();
         = true;
    }
    // ------------------------------------------------ HTTP/1.1 Output Methods

    
Send the response status line.
    public void sendStatus() {
        // Write protocol name
        write(.);
        [++] = .;
        // Write status code
        int status = .getStatus();
        switch (status) {
        case 200:
            write(.);
            break;
        case 400:
            write(.);
            break;
        case 404:
            write(.);
            break;
        default:
            write(status);
        }
        [++] = .;
        // Write message
        String message = null;
            message = .getMessage();
        }
        if (message == null) {
            write(HttpMessages.getMessage(status));
        } else {
            write(message.replace('\n'' ').replace('\r'' '));
        }
        // End the response status line
        [++] = .;
        [++] = .;
    }

    
Send a header.

Parameters:
name Header name
value Header value
    public void sendHeader(MessageBytes nameMessageBytes value) {
        if (name.getLength() > 0 && !value.isNull()) {
            write(name);
            [++] = .;
            [++] = .;
            write(value);
            [++] = .;
            [++] = .;
        }
    }

    
Send a header.

Parameters:
name Header name
value Header value
    public void sendHeader(ByteChunk nameByteChunk value) {
        write(name);
        [++] = .;
        [++] = .;
        write(value);
        [++] = .;
        [++] = .;
    }

    
Send a header.

Parameters:
name Header name
value Header value
    public void sendHeader(String nameString value) {
        write(name);
        [++] = .;
        [++] = .;
        write(value);
        [++] = .;
        [++] = .;
    }

    
End the header block.
    public void endHeaders() {
        [++] = .;
        [++] = .;
    }

    
Commit the response.

Throws:
IOException an undelying I/O error occured
    protected void commit() throws IOException {
        // The response is now committed
         = true;
        .setCommitted(true);
        if ( > 0) {
            // Sending the response header buffer
            .clear();
            .put(, 0, );
        }
    }

    
This method will write the contents of the specyfied message bytes buffer to the output stream, without filtering. This method is meant to be used to write the response header.

Parameters:
mb data to be written
    protected void write(MessageBytes mb) {
        if (mb == null) {
            return;
        }
        switch (mb.getType()) {
        case .:
            write(mb.getByteChunk());
            break;
        case .:
            write(mb.getCharChunk());
            break;
        default:
            write(mb.toString());
            break;
        }
    }

    
This method will write the contents of the specyfied message bytes buffer to the output stream, without filtering. This method is meant to be used to write the response header.

Parameters:
bc data to be written
    protected void write(ByteChunk bc) {
        // Writing the byte chunk to the output buffer
        int length = bc.getLength();
        System.arraycopy(bc.getBytes(), bc.getStart(), length);
         =  + length;
    }

    
This method will write the contents of the specyfied char buffer to the output stream, without filtering. This method is meant to be used to write the response header.

Parameters:
cc data to be written
    protected void write(CharChunk cc) {
        int start = cc.getStart();
        int end = cc.getEnd();
        char[] cbuf = cc.getBuffer();
        for (int i = starti < endi++) {
            char c = cbuf[i];
            // Note: This is clearly incorrect for many strings,
            // but is the only consistent approach within the current
            // servlet framework. It must suffice until servlet output
            // streams properly encode their output.
            if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
                c = ' ';
            }
            [++] = (bytec;
        }
    }

    
This method will write the contents of the specyfied byte buffer to the output stream, without filtering. This method is meant to be used to write the response header.

Parameters:
b data to be written
    public void write(byte[] b) {
        // Writing the byte chunk to the output buffer
        System.arraycopy(b, 0, b.length);
         =  + b.length;
    }

    
This method will write the contents of the specyfied String to the output stream, without filtering. This method is meant to be used to write the response header.

Parameters:
s data to be written
    protected void write(String s) {
        if (s == null) {
            return;
        }
        // From the Tomcat 3.3 HTTP/1.0 connector
        int len = s.length();
        for (int i = 0; i < leni++) {
            char c = s.charAt(i);
            // Note: This is clearly incorrect for many strings,
            // but is the only consistent approach within the current
            // servlet framework. It must suffice until servlet output
            // streams properly encode their output.
            if (((c <= 31) && (c != 9)) || c == 127 || c > 255) {
                c = ' ';
            }
            [++] = (bytec;
        }
    }

    
This method will print the specified integer to the output stream, without filtering. This method is meant to be used to write the response header.

Parameters:
i data to be written
    protected void write(int i) {
        write(String.valueOf(i));
    }
    // ----------------------------------- OutputBufferImpl Inner Class

    
OutputBufferImpl This class is an output buffer which will write data to an output stream/channel. Created on Jan 10, 2012 at 12:20:15 PM

Author(s):
Nabil Benothman
    class OutputBufferImpl implements OutputBuffer {

        
Write chunk.
        public int doWrite(ByteChunk chunkResponse resthrows IOException {
            if () {
                // If the buffer is growing and flow control is not used, autoblock if in a container thread 
                if (.getLength() > . && .getFlushLeftovers()
                        && ..get() == .) {
                    try {
                        if (.tryAcquire(.))
                            .release();
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }
                synchronized () {
                    leftover.append(chunk);
                    if (leftover.getLength() > Constants.ASYNC_BUFFER_SIZE) {
                        response.setLastWrite(0);
                    }
                }
                if (.tryAcquire()) {
                    // Calculate the number of bytes that fit in the buffer
                    int n = Math.min(.getLength(), .capacity() - .position());
                    .put(.getBuffer(), .getOffset(), n).flip();
                    .setOffset(.getOffset() + n);
                    boolean writeNotification = .getWriteNotification();
                    .setWriteNotification(false);
                    try {
                        .write(.);
                    } catch (Exception e) {
                        .getResponse().setErrorException(e);
                        if (..isDebugEnabled()) {
                            ..errorWithNonBlockingWrite(e);
                        }
                    }
                    if (.availablePermits() == 0) {
                        // Write did not complete inline, possible write notification
                        if (writeNotification) {
                            .setWriteNotification(true);
                        }
                    }
                }
            } else {
                int len = chunk.getLength();
                int start = chunk.getStart();
                byte[] b = chunk.getBuffer();
                while (len > 0) {
                    int thisTime = len;
                    if (!.hasRemaining()) {
                        flushBuffer();
                    }
                    if (thisTime > .remaining()) {
                        thisTime = .remaining();
                    }
                    .put(bstartthisTime);
                    len = len - thisTime;
                    start = start + thisTime;
                }
            }
            return chunk.getLength();
        }
    }
New to GrepCode? Check out our FAQ X