All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ajax4jsf.xml.serializer.SerializerTraceWriter Maven / Gradle / Ivy

Go to download

Ajax4jsf is an open source extension to the JavaServer Faces standard that adds AJAX capability to JSF applications without requiring the writing of any JavaScript.

The newest version!
/*
 * Copyright 2003-2004 The Apache Software Foundation.
 *
 * 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.
 */
/*
 * $Id: SerializerTraceWriter.java,v 1.1 2006/06/14 06:12:16 alexsmirnov Exp $
 */
package org.ajax4jsf.xml.serializer;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

/**
 * This class wraps the real writer, it only purpose is to send
 * CHARACTERTOSTREAM events to the trace listener. 
 * Each method immediately sends the call to the wrapped writer unchanged, but
 * in addition it collects characters to be issued to a trace listener.
 * 
 * In this way the trace
 * listener knows what characters have been written to the output Writer.
 * 
 * There may still be differences in what the trace events say is going to the
 * output writer and what is really going there. These differences will be due
 * to the fact that this class is UTF-8 encoding before emiting the trace event
 * and the underlying writer may not be UTF-8 encoding. There may also be
 * encoding differences.  So the main pupose of this class is to provide a
 * resonable facsimile of the true output.
 * 
 * @xsl.usage internal
 */
final class SerializerTraceWriter extends Writer implements WriterChain
{

    /** The real writer to immediately write to.
     * This reference may be null, in which case nothing is written out, but
     * only the trace events are fired for output.
     */
    private final java.io.Writer m_writer;

    /** The tracer to send events to */
    private final SerializerTrace m_tracer;

    /** The size of the internal buffer, just to keep too many
     * events from being sent to the tracer
     */
    private int buf_length;

    /**
     * Internal buffer to collect the characters to go to the trace listener.
     * 
     */
    private byte buf[];

    /**
     * How many bytes have been collected and still need to go to trace
     * listener.
     */
    private int count;

    /**
     * Creates or replaces the internal buffer, and makes sure it has a few
     * extra bytes slight overflow of the last UTF8 encoded character.
     * @param size
     */
    private void setBufferSize(int size)
    {
        buf = new byte[size + 3];
        buf_length = size;
        count = 0;
    }

    /**
     * Constructor.
     * If the writer passed in is null, then this SerializerTraceWriter will
     * only signal trace events of what would have been written to that writer.
     * If the writer passed in is not null then the trace events will mirror
     * what is going to that writer. In this way tools, such as a debugger, can
     * gather information on what is being written out.
     * 
     * @param out the Writer to write to (possibly null)
     * @param tracer the tracer to inform that characters are being written
     */
    public SerializerTraceWriter(Writer out, SerializerTrace tracer)
    {
        m_writer = out;
        m_tracer = tracer;
        setBufferSize(1024);
    }

    /**
     * Flush out the collected characters by sending them to the trace
     * listener.  These characters are never written to the real writer
     * (m_writer) because that has already happened with every method
     * call. This method simple informs the listener of what has already
     * happened.
     * @throws IOException
     */
    private void flushBuffer() throws IOException
    {

        // Just for tracing purposes
        if (count > 0)
        {
            char[] chars = new char[count];
            for(int i=0; i Subclasses that intend to support efficient single-character output
     * should override this method.
     *
     * @param c  int specifying a character to be written.
     * @exception  IOException  If an I/O error occurs
     */
    public void write(final int c) throws IOException
    {
        // send to the real writer
        if (m_writer != null)
            m_writer.write(c);

        // ---------- from here on just collect for tracing purposes

        /* If we are close to the end of the buffer then flush it.
         * Remember the buffer can hold a few more characters than buf_length
         */
        if (count >= buf_length)
            flushBuffer();

        if (c < 0x80)
        {
            buf[count++] = (byte) (c);
        }
        else if (c < 0x800)
        {
            buf[count++] = (byte) (0xc0 + (c >> 6));
            buf[count++] = (byte) (0x80 + (c & 0x3f));
        }
        else
        {
            buf[count++] = (byte) (0xe0 + (c >> 12));
            buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
            buf[count++] = (byte) (0x80 + (c & 0x3f));
        }
    }

    /**
     * Write a portion of an array of characters.
     *
     * @param  chars  Array of characters
     * @param  start   Offset from which to start writing characters
     * @param  length   Number of characters to write
     *
     * @exception  IOException  If an I/O error occurs
     *
     * @throws java.io.IOException
     */
    public void write(final char chars[], final int start, final int length)
        throws java.io.IOException
    {
        // send to the real writer
        if (m_writer != null)
            m_writer.write(chars, start, length);

        // from here on just collect for tracing purposes
        int lengthx3 = (length << 1) + length;

        if (lengthx3 >= buf_length)
        {

            /* If the request length exceeds the size of the output buffer,
              * flush the output buffer and make the buffer bigger to handle.
              */

            flushBuffer();
            setBufferSize(2 * lengthx3);

        }

        if (lengthx3 > buf_length - count)
        {
            flushBuffer();
        }

        final int n = length + start;
        for (int i = start; i < n; i++)
        {
            final char c = chars[i];

            if (c < 0x80)
                buf[count++] = (byte) (c);
            else if (c < 0x800)
            {
                buf[count++] = (byte) (0xc0 + (c >> 6));
                buf[count++] = (byte) (0x80 + (c & 0x3f));
            }
            else
            {
                buf[count++] = (byte) (0xe0 + (c >> 12));
                buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
                buf[count++] = (byte) (0x80 + (c & 0x3f));
            }
        }

    }

    /**
     * Write a string.
     *
     * @param  s  String to be written
     *
     * @exception  IOException  If an I/O error occurs
     */
    public void write(final String s) throws IOException
    {
        // send to the real writer
        if (m_writer != null)
            m_writer.write(s);

        // from here on just collect for tracing purposes
        final int length = s.length();

        // We multiply the length by three since this is the maximum length
        // of the characters that we can put into the buffer.  It is possible
        // for each Unicode character to expand to three bytes.

        int lengthx3 = (length << 1) + length;

        if (lengthx3 >= buf_length)
        {

            /* If the request length exceeds the size of the output buffer,
              * flush the output buffer and make the buffer bigger to handle.
              */

            flushBuffer();
            setBufferSize(2 * lengthx3);
        }

        if (lengthx3 > buf_length - count)
        {
            flushBuffer();
        }

        for (int i = 0; i < length; i++)
        {
            final char c = s.charAt(i);

            if (c < 0x80)
                buf[count++] = (byte) (c);
            else if (c < 0x800)
            {
                buf[count++] = (byte) (0xc0 + (c >> 6));
                buf[count++] = (byte) (0x80 + (c & 0x3f));
            }
            else
            {
                buf[count++] = (byte) (0xe0 + (c >> 12));
                buf[count++] = (byte) (0x80 + ((c >> 6) & 0x3f));
                buf[count++] = (byte) (0x80 + (c & 0x3f));
            }
        }
    }

    /**
     * Get the writer that this one directly wraps.
     */
    public Writer getWriter()
    {
        return m_writer;
    }

    /**
     * Get the OutputStream that is the at the end of the
     * chain of writers.
     */
    public OutputStream getOutputStream()
    {
        OutputStream retval = null;
        if (m_writer instanceof WriterChain)
            retval = ((WriterChain) m_writer).getOutputStream();
        return retval;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy