org.apache.myfaces.renderkit.html.HtmlResponseWriterImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of myfaces-commons Show documentation
Show all versions of myfaces-commons Show documentation
The MyFaces Commons Subproject provides base classes for usage in both the
MyFaces implementation and the MyFaces Tomahawk components. This is also
a general set of utility classes for usage in your JSF projects independent
of the implementation you might be deciding upon.
The newest version!
/*
* Copyright 2004-2006 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.
*/
package org.apache.myfaces.renderkit.html;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.renderkit.RendererUtils;
import org.apache.myfaces.renderkit.html.util.DummyFormUtils;
import org.apache.myfaces.renderkit.html.util.HTMLEncoder;
import org.apache.myfaces.renderkit.html.util.UnicodeEncoder;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashSet;
import java.util.Set;
/**
* @author Manfred Geiler (latest modification by $Author: baranda $)
* @author Anton Koinov
* @version $Revision: 373272 $ $Date: 2006-01-29 02:01:37 +0000 (Sun, 29 Jan 2006) $
*/
public class HtmlResponseWriterImpl
extends ResponseWriter
{
private static final Log log = LogFactory.getLog(HtmlResponseWriterImpl.class);
private static final String DEFAULT_CONTENT_TYPE = "text/html";
private static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1";
private static final String UTF8 = "UTF-8";
private boolean _writeDummyForm = false;
private Set _dummyFormParams = null;
private Writer _writer;
private String _contentType;
private String _characterEncoding;
private String _startElementName;
private Boolean _isScript;
private Boolean _isStyle;
private Boolean _isTextArea;
private UIComponent _startElementUIComponent;
private boolean _startTagOpen;
private static final Set s_emptyHtmlElements = new HashSet();
static
{
s_emptyHtmlElements.add("area");
s_emptyHtmlElements.add("br");
s_emptyHtmlElements.add("base");
s_emptyHtmlElements.add("basefont");
s_emptyHtmlElements.add("col");
s_emptyHtmlElements.add("frame");
s_emptyHtmlElements.add("hr");
s_emptyHtmlElements.add("img");
s_emptyHtmlElements.add("input");
s_emptyHtmlElements.add("isindex");
s_emptyHtmlElements.add("link");
s_emptyHtmlElements.add("meta");
s_emptyHtmlElements.add("param");
}
public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding)
throws FacesException
{
_writer = writer;
_contentType = contentType;
if (_contentType == null)
{
if (log.isDebugEnabled()) log.debug("No content type given, using default content type " + DEFAULT_CONTENT_TYPE);
_contentType = DEFAULT_CONTENT_TYPE;
}
if (characterEncoding == null)
{
if (log.isDebugEnabled()) log.debug("No character encoding given, using default character encoding " + DEFAULT_CHARACTER_ENCODING);
_characterEncoding = DEFAULT_CHARACTER_ENCODING;
}
else
{
// validates the encoding, it will throw an UnsupportedEncodingException if the encoding is invalid
try
{
new String("myfaces".getBytes(), characterEncoding);
}
catch (UnsupportedEncodingException e)
{
throw new IllegalArgumentException("Unsupported encoding: "+characterEncoding);
}
// canonize to uppercase, that's the standard format
_characterEncoding = characterEncoding.toUpperCase();
}
}
public static boolean supportsContentType(String contentType)
{
String[] supportedContentTypes = HtmlRendererUtils.getSupportedContentTypes();
for (int i = 0; i < supportedContentTypes.length; i++)
{
String supportedContentType = supportedContentTypes[i];
if(supportedContentType.indexOf(contentType)!=-1)
return true;
}
return false;
}
public String getContentType()
{
return _contentType;
}
public String getCharacterEncoding()
{
return _characterEncoding;
}
public void flush() throws IOException
{
// API doc says we should not flush the underlying writer
//_writer.flush();
// but rather clear any values buffered by this ResponseWriter:
closeStartTagIfNecessary();
}
public void startDocument()
{
// do nothing
}
public void endDocument() throws IOException
{
_writer.flush();
}
public void startElement(String name, UIComponent uiComponent) throws IOException
{
if (name == null)
{
throw new NullPointerException("elementName name must not be null");
}
closeStartTagIfNecessary();
_writer.write('<');
_writer.write(name);
resetStartedElement();
_startElementName = name;
_startElementUIComponent = uiComponent;
_startTagOpen = true;
}
private void closeStartTagIfNecessary() throws IOException
{
if (_startTagOpen)
{
if (s_emptyHtmlElements.contains(_startElementName.toLowerCase()))
{
_writer.write(" />");
// make null, this will cause NullPointer in some invalid element nestings
// (better than doing nothing)
resetStartedElement();
}
else
{
_writer.write('>');
if(isScriptOrStyle())
{
if(HtmlRendererUtils.isXHTMLContentType(_contentType))
{
_writer.write("");
else
_writer.write("\n]]>");
}
else
{
if(isScript())
_writer.write("\n//-->");
else
_writer.write("\n-->");
}
}
_writer.write("");
_writer.write(name);
_writer.write('>');
}
public void writeAttribute(String name, Object value, String componentPropertyName) throws IOException
{
if (name == null)
{
throw new NullPointerException("attributeName name must not be null");
}
if (!_startTagOpen)
{
throw new IllegalStateException("Must be called before the start element is closed (attribute '" + name + "')");
}
if (value instanceof Boolean)
{
if (((Boolean)value).booleanValue())
{
// name as value for XHTML compatibility
_writer.write(' ');
_writer.write(name);
_writer.write("=\"");
_writer.write(name);
_writer.write('"');
}
}
else
{
String strValue = (value==null)?"":value.toString();
_writer.write(' ');
_writer.write(name);
_writer.write("=\"");
_writer.write(HTMLEncoder.encode(strValue, false, false, !UTF8.equals(_characterEncoding)));
_writer.write('"');
}
}
public void writeURIAttribute(String name, Object value, String componentPropertyName) throws IOException
{
if (name == null)
{
throw new NullPointerException("attributeName name must not be null");
}
if (!_startTagOpen)
{
throw new IllegalStateException("Must be called before the start element is closed (attribute '" + name + "')");
}
String strValue = value.toString();
_writer.write(' ');
_writer.write(name);
_writer.write("=\"");
if (strValue.toLowerCase().startsWith("javascript:"))
{
_writer.write(HTMLEncoder.encode(strValue, false, false, !UTF8.equals(_characterEncoding)));
}
else
{
/*
Todo: what is this section about? still needed?
client side state saving is now done via javascript...
if (_startElementName.equalsIgnoreCase(HTML.ANCHOR_ELEM) && //Also support image and button urls?
name.equalsIgnoreCase(HTML.HREF_ATTR) &&
!strValue.startsWith("#"))
{
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext))
{
// saving state in url depends on the work together
// of 3 (theoretically) pluggable components:
// ViewHandler, ResponseWriter and ViewTag
// We should try to make this HtmlResponseWriterImpl able
// to handle this alone!
if (strValue.indexOf('?') < 0)
{
strValue = strValue + '?' + JspViewHandlerImpl.URL_STATE_MARKER;
}
else
{
strValue = strValue + '&' + JspViewHandlerImpl.URL_STATE_MARKER;
}
}
}
*/
_writer.write(strValue);
}
_writer.write('"');
}
public void writeComment(Object value) throws IOException
{
if (value == null)
{
throw new NullPointerException("comment name must not be null");
}
closeStartTagIfNecessary();
_writer.write("" inside!
_writer.write("-->");
}
public void writeText(Object value, String componentPropertyName) throws IOException
{
if (value == null)
{
throw new NullPointerException("Text must not be null.");
}
closeStartTagIfNecessary();
String strValue = value.toString();
if (isScriptOrStyle())
{
// Don't bother encoding anything if chosen character encoding is UTF-8
if (UTF8.equals(_characterEncoding)) _writer.write(strValue);
else _writer.write(UnicodeEncoder.encode(strValue) );
}
else
{
_writer.write(HTMLEncoder.encode(strValue, false, false, !UTF8.equals(_characterEncoding)));
}
}
public void writeText(char cbuf[], int off, int len) throws IOException
{
if (cbuf == null)
{
throw new NullPointerException("cbuf name must not be null");
}
if (cbuf.length < off + len)
{
throw new IndexOutOfBoundsException((off + len) + " > " + cbuf.length);
}
closeStartTagIfNecessary();
if (isScriptOrStyle())
{
String strValue = new String(cbuf, off, len);
// Don't bother encoding anything if chosen character encoding is UTF-8
if (UTF8.equals(_characterEncoding)) _writer.write(strValue);
else _writer.write(UnicodeEncoder.encode(strValue) );
}
else if (isTextarea())
{
// For textareas we must *not* map successive spaces to   or Newlines to
// TODO: Make HTMLEncoder support char arrays directly
String strValue = new String(cbuf, off, len);
_writer.write(HTMLEncoder.encode(strValue, false, false, !UTF8.equals(_characterEncoding)));
}
else
{
// We map successive spaces to and Newlines to
// TODO: Make HTMLEncoder support char arrays directly
String strValue = new String(cbuf, off, len);
_writer.write(HTMLEncoder.encode(strValue, true, true, !UTF8.equals(_characterEncoding)));
}
}
private boolean isScriptOrStyle()
{
initializeStartedTagInfo();
return (_isStyle != null && _isStyle.booleanValue()) ||
(_isScript != null && _isScript.booleanValue());
}
private boolean isScript()
{
initializeStartedTagInfo();
return (_isScript != null && _isScript.booleanValue());
}
private boolean isTextarea()
{
initializeStartedTagInfo();
return _isTextArea != null && _isTextArea.booleanValue();
}
private void initializeStartedTagInfo()
{
if(_startElementName != null)
{
if(_isScript==null)
{
if(_startElementName.equalsIgnoreCase(HTML.SCRIPT_ELEM))
{
_isScript = Boolean.TRUE;
_isStyle = Boolean.FALSE;
_isTextArea = Boolean.FALSE;
}
else
{
_isScript = Boolean.FALSE;
}
}
if(_isStyle == null)
{
if(_startElementName.equalsIgnoreCase(HTML.STYLE_ELEM))
{
_isStyle = Boolean.TRUE;
_isTextArea = Boolean.FALSE;
}
else
{
_isStyle = Boolean.FALSE;
}
}
if(_isTextArea == null)
{
if(_startElementName.equalsIgnoreCase(HTML.TEXTAREA_ELEM))
{
_isTextArea = Boolean.TRUE;
}
else
{
_isTextArea = Boolean.FALSE;
}
}
}
}
public ResponseWriter cloneWithWriter(Writer writer)
{
HtmlResponseWriterImpl newWriter
= new HtmlResponseWriterImpl(writer, getContentType(), getCharacterEncoding());
newWriter._writeDummyForm = _writeDummyForm;
newWriter._dummyFormParams = _dummyFormParams;
return newWriter;
}
// Writer methods
public void close() throws IOException
{
closeStartTagIfNecessary();
_writer.close();
}
public void write(char cbuf[], int off, int len) throws IOException
{
closeStartTagIfNecessary();
String strValue = new String(cbuf, off, len);
// Don't bother encoding anything if chosen character encoding is UTF-8
if (UTF8.equals(_characterEncoding)) _writer.write(strValue);
else _writer.write(UnicodeEncoder.encode(strValue) );
}
public void write(int c) throws IOException
{
closeStartTagIfNecessary();
_writer.write(c);
}
public void write(char cbuf[]) throws IOException
{
closeStartTagIfNecessary();
String strValue = new String(cbuf);
// Don't bother encoding anything if chosen character encoding is UTF-8
if (UTF8.equals(_characterEncoding)) _writer.write(strValue);
else _writer.write(UnicodeEncoder.encode(strValue) );
}
public void write(String str) throws IOException
{
closeStartTagIfNecessary();
// empty string commonly used to force the start tag to be closed.
// in such case, do not call down the writer chain
if (str.length() > 0)
{
// Don't bother encoding anything if chosen character encoding is UTF-8
if (UTF8.equals(_characterEncoding)) _writer.write(str);
else _writer.write(UnicodeEncoder.encode(str) );
}
}
public void write(String str, int off, int len) throws IOException
{
closeStartTagIfNecessary();
String strValue = str.substring(off, off+len);
// Don't bother encoding anything if chosen character encoding is UTF-8
if (UTF8.equals(_characterEncoding)) _writer.write(strValue);
else _writer.write(UnicodeEncoder.encode(strValue) );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy