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

org.ajax4jsf.framework.ajax.xmlfilter.SAXResponseWriter 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!
/**
 * Licensed under the Common Development and Distribution License,
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.sun.com/cddl/
 *   
 * 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.ajax4jsf.framework.ajax.xmlfilter;

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

import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;

import org.ajax4jsf.framework.util.message.Messages;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;

/**
 * @author shura
 * 
 * Realization of Faces ResponseWriter for Cocoon Environment.
 * Use ONLY Markup-specific calls , send it as SAX events to
 * XMLConsumer Use "State" pattern for control of events flow.
 * TODO - implement namespace capabilites
 *  
 */
public class SAXResponseWriter extends ResponseWriter {

    /**
     * As we in XML framework, only xml supported for CONTENT_TYPE
     */
    static final private String CONTENT_TYPE = "text/xml";

    /**
     * As we in XML framework, only UTF-8 supported for
     * CHARTER_ENCODING
     */
    static final private String CHARTER_ENCODING = "UTF-8";

    /**
     * Hold Cocoon Generator XML consumer
     */
    private ContentHandler xmlConsumer;
    
    private LexicalHandler xmlLexicalHandler = null;
    
    private String namespaceURI = "http://www.w3.org/1999/xhtml";

    private String element;

    private AttributesImpl attributes;

    private XMLResponseWriterState state;

    /**
     * Before StartDocument or after EndDocument notDocumentState
     */
    private XMLResponseWriterState notDocumentState;

    /**
     * State in normal document inDocumentState
     */
    private XMLResponseWriterState inDocumentState;

    private XMLResponseWriterState cdataState;

    /**
     * State after startElement. Collect Attributes for SAX startElement
     * elementState
     */
    private XMLResponseWriterState elementState;

    /**
     * @param consumer -
     *            SAX events receiver for Cocoon pipeline.
     */
    public SAXResponseWriter(ContentHandler consumer) {
        super();
        this.xmlConsumer = consumer;
        if (consumer instanceof LexicalHandler) {
			 xmlLexicalHandler = (LexicalHandler) consumer;
		}
        // Initialise states. May be must implemented in static block ?
        this.notDocumentState = new NotDocumentState();
        // inside document. allow any events exclude attributes and
        // startDocument.
        this.inDocumentState = new InDocumentState();
        this.cdataState = new CDATAState();
        // In element, collect attributes ...
        this.elementState = new ElementState();
        this.state = notDocumentState;
    }

    /**
	 * @return Returns the namespaceURI.
	 */
	public String getNamespaceURI() {
		return namespaceURI;
	}

	/**
	 * @param namespaceURI The namespaceURI to set.
	 */
	public void setNamespaceURI(String namespaceURI) {
		this.namespaceURI = namespaceURI;
	}

	/*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#getContentType()
     */
    public String getContentType() {
        return CONTENT_TYPE;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#getCharacterEncoding()
     */
    public String getCharacterEncoding() {
        return CHARTER_ENCODING;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.io.Flushable#flush()
     */
    public void flush() throws IOException {
        // DO NOTHING...

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#startDocument()
     */
    public void startDocument() throws IOException {
        state.startDocument();

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#endDocument()
     */
    public void endDocument() throws IOException {
        state.endDocument();

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#startElement(java.lang.String,
     *      javax.faces.component.UIComponent)
     */
    public void startElement(String name, UIComponent component)
            throws IOException {
        state.startElement(name, component);

    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#endElement(java.lang.String)
     */
    public void endElement(String name) throws IOException {
        state.endElement(name);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#writeAttribute(java.lang.String,
     *      java.lang.Object, java.lang.String)
     */
    public void writeAttribute(String name, Object value, String property)
            throws IOException {
        state.writeAttribute(name, value, property);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#writeURIAttribute(java.lang.String,
     *      java.lang.Object, java.lang.String)
     */
    public void writeURIAttribute(String name, Object value, String property)
            throws IOException {
        state.writeURIAttribute(name, value, property);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#writeComment(java.lang.Object)
     */
    public void writeComment(Object comment) throws IOException {
        state.writeComment(comment);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#writeText(java.lang.Object,
     *      java.lang.String)
     */
    public void writeText(Object text, String property) throws IOException {
        state.writeText(text, property);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#writeText(char[], int, int)
     */
    public void writeText(char[] text, int off, int len) throws IOException {
        state.writeText(text, off, len);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.faces.context.ResponseWriter#cloneWithWriter(java.io.Writer)
     */
    public ResponseWriter cloneWithWriter(Writer writer) {
        // TODO as used XML consumer to get sax Events, we simple return current
        // instance.
        // if will used wrapper to combine XML Consumer with plain Servlet
        // responce writer, must
        // perform real clone ...
        // We can use org.apache.cocoon.xml.SaxBuffer;
        return this;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.io.Writer#write(char[], int, int)
     */
    public void write(char[] cbuf, int off, int len) throws IOException {
        state.writeText(cbuf, off, len);
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.io.Closeable#close()
     */
    public void close() throws IOException {
        // TODO Auto-generated method stub

    }

    // Private classes
    /**
     * @author shura
     * 
     * state before startDocument - only allow startDocument.
     */
    private final class NotDocumentState extends XMLResponseWriterState {
        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#startDocument()
         */
        void startDocument() throws IOException {
            try {
                // 
                xmlConsumer.startDocument();
            } catch (SAXException e) {
                // 
                throw new IOException(Messages.getMessage(Messages.START_DOCUMENT_SAX_EXCEPTION, e.getMessage()));
            } finally {
                state = inDocumentState;
            }
        }
    }

    /**
     * @author shura
     * 
     * State in regular document. Disabled attributes & startDocument.
     */
    private final class InDocumentState extends XMLResponseWriterState {
        void startElement(String name, UIComponent component) {
            element = name;
            attributes = new AttributesImpl();
            state = elementState;

        }

        void writeComment(Object comment) throws IOException {
            String remark = comment.toString();
            try {
                xmlLexicalHandler.comment(remark.toCharArray(), 0, remark.length());
            } catch (SAXException e) {
                throw new IOException(Messages.getMessage(Messages.COMMENT_SAX_EXCEPTION, e.getMessage()));
            }
        }

        void writeText(Object o, String property) throws IOException {
            writeText(o.toString().toCharArray(), 0, o.toString().length());
        }

        void writeText(char[] text, int start, int lenght) throws IOException {
            //			try {
            //				xmlConsumer.startCDATA();
            //			} catch (SAXException e) {
            //				throw new IOException("Sax exceptions in writeText: "+
            // e.getMessage());
            //			} finally {
            state = cdataState;
            //			}
            state.writeText(text, start, lenght);
        }

        void endElement(String name) throws IOException {
            try {
                xmlConsumer.endElement(getNamespaceURI(), name, name);
            } catch (SAXException e) {
                throw new IOException(Messages.getMessage(Messages.END_ELEMENT_SAX_EXCEPTION, e.getMessage()));
            }
        }

        void endDocument() throws IOException {
            try {
                xmlConsumer.endDocument();
            } catch (SAXException e) {
                throw new IOException(Messages.getMessage(Messages.END_DOCUMENT_SAX_EXCEPTION, e.getMessage()));
            } finally {
                // after endDocument all events disabled ...
                state = new XMLResponseWriterState();
            }
        }
    }

    /**
     * @author shura State in element declsration. Collect attributes, on any
     *         other eventss - generate SAX startElement()
     */
    private final class ElementState extends XMLResponseWriterState {
        /**
         * Generate SAX StartElement event
         * 
         * @throws IOException
         */
        void flushElement() throws IOException {
            try {
                xmlConsumer.startElement(getNamespaceURI(), element, element, attributes);
            } catch (SAXException e) {
                throw new IOException(Messages.getMessage(Messages.START_ELEMENT_SAX_EXCEPTION, e.getMessage()));
            } finally {
                element = null;
                attributes = null;
            }
        }

        void writeAttribute(String name, Object value, String property)
                throws IOException {
            attributes.addAttribute(getNamespaceURI(), name, name, "id".equalsIgnoreCase(name)?"ID":"CDATA", value.toString());
        }

        void writeURIAttribute(String name, Object value, String property)
                throws IOException {
            String uri = value.toString();
            // TODO - perform encodeActionURL() or ???
            attributes.addAttribute(getNamespaceURI(), name, name, "CDATA", uri);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#endElement(java.lang.String)
         */
        void endElement(String name) throws IOException {
            // 
            flushElement();
            state = inDocumentState;
            state.endElement(name);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#startElement(java.lang.String,
         *      javax.faces.component.UIComponent)
         */
        void startElement(String name, UIComponent component)
                throws IOException {
            // 
            flushElement();
            element = name;
            attributes = new AttributesImpl();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#writeComment(java.lang.Object)
         */
        void writeComment(Object comment) throws IOException {
            // TODO Auto-generated method stub
            flushElement();
            state = inDocumentState;
            state.writeComment(comment);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#writeText(char[],
         *      int, int)
         */
        void writeText(char[] text, int off, int len) throws IOException {
            // TODO Auto-generated method stub
            flushElement();
            state = cdataState;
            state.writeText(text, off, len);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#writeText(java.lang.Object,
         *      java.lang.String)
         */
        void writeText(Object text, String property) throws IOException {
            // TODO Auto-generated method stub
            flushElement();
            state = cdataState;
            state.writeText(text, property);
        }
    }

    /**
     * @author shura
     * 
     * CDATA section. allow regular write() functions, write any text.
     */
    private final class CDATAState extends XMLResponseWriterState {

        void flushCDATA() throws IOException {
            //			try {
            //				xmlConsumer.endCDATA();
            //			} catch (SAXException e) {
            //				throw new IOException("Exception in endCDATA: "+ e.getMessage());
            //			}
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#endDocument()
         */
        void endDocument() throws IOException {
            flushCDATA();
            state = inDocumentState;
            state.endDocument();
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#endElement(java.lang.String)
         */
        void endElement(String name) throws IOException {
            flushCDATA();
            state = inDocumentState;
            state.endElement(name);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#startElement(java.lang.String,
         *      javax.faces.component.UIComponent)
         */
        void startElement(String name, UIComponent component)
                throws IOException {
            flushCDATA();
            element = name;
            attributes = new AttributesImpl();
            state = elementState;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#writeComment(java.lang.Object)
         */
        void writeComment(Object comment) throws IOException {
            flushCDATA();
            state = inDocumentState;
            state.writeComment(comment);
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#writeText(char[],
         *      int, int)
         */
        void writeText(char[] text, int off, int len) throws IOException {
            try {
                xmlConsumer.characters(text, off, len);
            } catch (SAXException e) {
                throw new IOException(Messages.getMessage(Messages.TEXT_SAX_EXCEPTION, e.getMessage()));
            }
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#writeText(java.lang.Object,
         *      java.lang.String)
         */
        void writeText(Object text, String property) throws IOException {
            writeText(text.toString().toCharArray(), 0, text.toString()
                    .length());
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.apache.cocoon.components.faces.context.XMLResponseWriterState#write(char[],
         *      int, int)
         */
        void write(char[] cbuf, int off, int len) throws IOException {
            writeText(cbuf, off, len);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy