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.sling.engine.impl.output;
 
 
 
The BufferedPrintWriter implements buffering for the PrintWriter returned by the javax.servlet.ServletResponse.getWriter() method.

We need this additional buffering class for the javax.servlet.ServletResponse.getWriter() class because we wrap the original PrintWriter retrieved from the servlet container with optional caching and link checking writers.

This class overwrites all the base class's write methods, which are used as the base for writing. All other methods of the base class use the write methods after having formatted the parameter.

The buffer is flushed to the wrapped writer in the following cases :

  1. The buffer is full if more characters have to be added. That is the buffer is not flushed when the buffer gets full by adding characters but when the buffer would get 'overfull' with adding characters.
  2. When the flush() method is called.
  3. When the writer is closed

This class is not multithread safe as it is intended to be used on single requests which are assigned to single threads.

This extension to the PrintWriter class does not support automatic flush of the output buffer. That is, the println method never ever flushes output.

 
 public class BufferedPrintWriter extends PrintWriter implements Buffer {

    
default logger
 
    
default log
 
     private static final Logger log = LoggerFactory.getLogger(BufferedPrintWriter.class);

    
The line separator
 
     private static final String lineSeparator =
             System.getProperty("line.separator");

    
The current buffer size which may be modified and retrieved.

 
     private int bufferSize;

    
The character buffer
 
     private char[] buffer;

    
The current offset of writing characters into the buffer
 
     private int offset;

    
 
     protected boolean trouble;

    
flag to indicate that the writer has been closed
 
     protected boolean closed;
 
     protected boolean loggedNoBuffering = false;

    
Creates an instance wrapping the PrintWriter and providing an initial buffer size.

The servletWriter is to initially write data to.

The other use of the servletWriter is to check for any errors occurred by forwarding the call to the checkError() to this writer.

Parameters:
servletWriter The PrintWriter to which data is initially written.
bufferSize The initial size of the buffer. If negative or zero no buffering is initiallly done.
    public BufferedPrintWriter(PrintWriter servletWriterint bufferSize) {
        super(servletWriterfalse);
        // set the buffer
        this. = 0;
        this.setBufferSize(bufferSize);
    }

    
Creates a BufferedWriter for the given response instance. This instance uses the PrintWriter retrieved from the response object to write the data flushing out of the buffer.

The PrintWriter from the response is to initially write data to. This destination may be replaced with the setDestination. It is intended that any Writer set in the setDestination method be ultimately writing to this same servlet container PrintWriter.

The other use of the servlet container's PrintWriter is to check for any errors occurred by forwarding the call to the checkError() to this writer.

Parameters:
response The response object for which to return a BufferedPrintWriter. This MUST be the servlet containers response object otherwise a stack overflow will occur.
Throws:
java.io.IOException If a problem occurrs getting the writer from the response
java.lang.IllegalStateException If an OutputStream has already been obtained from the response and the PrintWriter is not available any more.
java.lang.StackOverflowError if the response parameter is not the servlet container's response object.
    BufferedPrintWriter(ServletResponse responsethrows IOException {
        this(response.getWriter(), response.getBufferSize());
    }
    //---------- buffer handling -----------------------------------------------

    
Sets the buffer size. If the buffer contains data, this method throws an IllegalStateException.

Parameters:
bufferSize The new size of the buffer. If this value is less than or equal to zero, buffering is disabled alltogether.
Throws:
java.lang.IllegalStateException if the buffer contains data.
    public void setBufferSize(int bufferSize) {
        // check buffer requirements
        if (this. != 0) {
            throw new IllegalStateException("Buffer not empty");
        }
        // only resize buffer if positive value
        if (bufferSize > 0) {
            .debug("setBufferSize: Creating Buffer of {0} characters",
                    String.valueOf(bufferSize));
            this. = bufferSize;
            this. = new char[bufferSize];
        } else {
            .debug("setBufferSize: Disabling Buffering");
            this. = -1;
            this. = null;
        }
    }

    
Returns the size of the buffer

Returns:
the size of the buffer
    public int getBufferSize() {
        return this.;
    }

    
Clears the buffer.
    public void resetBuffer() {
        // Simply reset the write offset to the beginning of the buffer
        .debug("resetBuffer");
        this. = 0;
    }

    
Writes the contents of the buffer to the wrapped writer.
    public void flushBuffer() {
        if (this.isClosed()) {
            .info("flush: PrintWriter already closed. No Flushing");
            this.setError();
            return;
        }
        // write the buffer
        if (this. != null) {
            if (this. > 0) {
                .debug("flush: Flushing {0} characters", String.valueOf(this.));
                super.write(this.buffer, 0, this.);
            } else {
                .debug("flush: Empty buffer");
            }
        } else {
            .debug("write: No buffer to flush due to disabled buffering");
        }
        // reset buffer offset to start writing at the beginning
        this. = 0;
    }
    //---------- PrintWriter overwrites ----------------------------------------

    
Flush the stream if it's not closed and check its error state. Errors are cumulative; once the stream encounters an error, this routine will return true on all successive calls.

This implementation checks with the PrintWriter used to create this BufferedPrintWriter.

Returns:
true if the print stream has encountered an error, either on the underlying output stream or during a format conversion.
    public boolean checkError() {
        
Three steps of checking : - first check whether this is already marked as trouble some - next flush all buffers and check whether an error occurred - next check with the servlet writer whether this one had troubles ( the servlet writer has to be checked, because this one eats all io exceptions trying to write to the client )
        return this. || super.checkError();
    }

    
Indicate that an error has occurred.
    protected void setError() {
        this. = true;
        super.setError();
    }

    
Writes the contents of the buffer to the wrapped writer and flushes the latter.
    public void flush() {
        // flush the buffer to the destination
        this.flushBuffer();
        // flush the destination if not closed already
        if (!this.isClosed()) {
            super.flush();
        }
    }

    
Closes the output after flushing the buffer contents to the wrapped writer.
    public void close() {
        if (!this.isClosed()) {
            // only write buffer, leave to wrapped to flush upon close
            this.flushBuffer();
            // close the writer and release wrapped writer
            super.close();
            // remove the buffer space alltogether
            this.setBufferSize(0);
            // set the destination to the servlet writer to prevent possible NPE
            this. = true;
        }
    }

    
Writes a single character. If the buffer is already full, it is flushed to the wrapped writer before writing the character to the buffer.

Parameters:
c The character to write to the buffer.
    public void write(int c) {
        if (this.isClosed()) {
            .info("write: PrintWriter already closed. No Writing");
            this.setError();
            return;
        }
        if (this. == null) {
            // checks for open stream itself
            if ( ! ) {
                .debug("write: Direct writing due to disabled buffering");
                 = true;
            }
            super.write(c);
        } else {
            if (this. >= this.) {
                .debug("write: Buffer full, flushing first");
                this.flushBuffer();
            }
            this.[this.++] = (charc;
        }
    }

    
Writes a portion of an array of characters.

If the number of characters is more than the buffer capacity, the buffer is flushed. Due to buffering it is not guaranteed that the complete number of characters is either buffered or written. It is acceptable for part of the characters to be written and the rest to be buffered.

Parameters:
buf The characters to write
off The starting offset into the character array
len The number of characters to write starting with the offset.
Throws:
java.lang.NullPointerException if buf is null
java.lang.IndexOutOfBoundsException if either or both off and off+len are outside of the bounds of the character array buf.
    public void write(char buf[], int offint len) {
        if (this.isClosed()) {
            .info("write: PrintWriter already closed. No Writing");
            this.setError();
            return;
        }
        if (this. == null) {
            // checks for open stream itself
            if ( ! ) {
                .debug("write: Direct writing due to disabled buffering");
                 = true;
            }
            super.write(bufofflen);
        } else {
            // copy all buffer parts bigger than the current space
            while (this. + len - 1 >= this.) {
                // write the first portion to the buffer to flush
                int space = this. - this.;
                System.arraycopy(bufoffthis.this.space);
                off += space;
                len -= space;
                .debug("write: {0} characters written, flush buffer",
                        String.valueOf(space));
                // flush buffer and reset offset to 0
                this. = this.;
                this.flushBuffer();
            }
            // copy rest of the data
            if (len > 0) {
                .debug("write: Writing {0} characters to the buffer",
                        String.valueOf(len));
                System.arraycopy(bufoffthis.this.len);
                this. += len;
            }
        }
    }

    
Writes a portion of a string.

If the number of characters is more than the buffer capacity, the buffer is flushed. Due to buffering it is not guaranteed that the complete number of characters is either buffered or written. It is acceptable for part of the characters to be written and the rest to be buffered.

Parameters:
s The string to write
off The starting offset into the string
len The number of characters to write starting with the offset.
Throws:
java.lang.NullPointerException if s is null
java.lang.IndexOutOfBoundsException if either or both off and off+len are outside of the bounds of the string s.
    public void write(String sint offint len) {
        if (this.isClosed()) {
            .info("write: PrintWriter already closed. No Writing");
            this.setError();
            return;
        }

        
For performance reasons the code from the write(char[], int, int) method is copied where the System.arraycopy calls are replaced by String.getChars calls. This prevents excessive copying and array allocation which would be needed using the String.toCharArray method.
        if (this. == null) {
            // checks for open stream itself
            if ( ! ) {
                .debug("write: Direct writing due to disabled buffering");
                 = true;
            }
            super.write(sofflen);
        } else {
            // copy all buffer parts bigger than the current space
            while (this. + len -1 >= this.) {
                // write the first portion to the buffer to flush
                int space = this. - this.;
                s.getChars(offoff+spacethis.this.);
                off += space;
                len -= space;
                .debug("write: {0} characters written, flush buffer",
                        String.valueOf(space));
                // flush buffer and reset offset to 0
                this. = this.;
                this.flushBuffer();
            }
            // copy rest of the data
            if (len > 0) {
                .debug("write: Writing {0} characters to the buffer",
                        String.valueOf(len));
                s.getChars(offoff+lenthis.this.);
                this. += len;
            }
        }
    }

    
Terminate the current line by writing the line separator string without ever flushing the buffer. The line separator string is defined by the system property line.separator, and is not necessarily a single newline character ('\n').

This duplicates the functionality of the private of the PrintWriter.newLine method.

    public void println() {
        // write the line separator
        this.write();
    }

    
Returns true if this writer has been closed.

Returns:
true if this writer has been closed.
    private boolean isClosed() {
        return this.;
    }
New to GrepCode? Check out our FAQ X