org.ajax4jsf.io.SAXResponseWriter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of richfaces-core Show documentation
Show all versions of richfaces-core Show documentation
The RichFaces core framework.
The newest version!
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.ajax4jsf.io;
import java.io.IOException;
import java.io.Writer;
import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
/**
* 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
*
* @author shura
*/
public class SAXResponseWriter extends ResponseWriter {
/**
* As we in XML framework, only UTF-8 supported for CHARTER_ENCODING
*/
private static final String CHARTER_ENCODING = "UTF-8";
/**
* As we in XML framework, only xml supported for CONTENT_TYPE
*/
private static final String CONTENT_TYPE = "text/xml";
private String namespaceURI = "http://www.w3.org/1999/xhtml";
private LexicalHandler xmlLexicalHandler = null;
private AttributesImpl attributes;
private XMLResponseWriterState cdataState;
private String element;
/**
* State after startElement. Collect Attributes for SAX startElement elementState
*/
private XMLResponseWriterState elementState;
/**
* State in normal document inDocumentState
*/
private XMLResponseWriterState inDocumentState;
/**
* Before StartDocument or after EndDocument notDocumentState
*/
private XMLResponseWriterState notDocumentState;
private XMLResponseWriterState state;
/**
* Hold Cocoon Generator XML consumer
*/
private ContentHandler xmlConsumer;
/**
* @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;
}
public ContentHandler getXmlConsumer() {
return xmlConsumer;
}
/**
* @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
}
/**
* @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("Sax exceptions in writeText: " + 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);
}
}
/**
* @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("Exception in startElement: " + 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
*
* 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("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("Sax exceptions in endElement: " + e.getMessage());
}
}
void endDocument() throws IOException {
try {
xmlConsumer.endDocument();
} catch (SAXException e) {
throw new IOException("Sax exceptions in endDocument" + e.getMessage());
} finally {
// after endDocument all events disabled ...
state = new XMLResponseWriterState();
}
}
}
// 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("StartDocument SAX exception :" + e.getMessage());
} finally {
state = inDocumentState;
}
}
}
}