| /* |
| * 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.myfaces.test.mock; |
| |
| import java.io.IOException; |
| import java.io.Writer; |
| import javax.faces.component.UIComponent; |
| import javax.faces.context.ResponseWriter; |
| |
| /** |
| * <p>Mock implementation of <code>javax.faces.context.ResponseWriter</code>.</p> |
| */ |
| public class MockResponseWriter extends ResponseWriter { |
| |
| |
| // ------------------------------------------------------------ Constructors |
| |
| public MockResponseWriter(Writer writer) { |
| this.writer = writer; |
| this.contentType = "text/html"; |
| this.characterEncoding = "UTF-8"; |
| } |
| |
| /** |
| * <p>Construct an instance wrapping the specified writer.</p> |
| * |
| * @param writer Writer we are wrapping |
| * @param contentType Content type to be created |
| * @param characterEncoding Character encoding of this response |
| */ |
| public MockResponseWriter(Writer writer, String contentType, String characterEncoding) { |
| this.writer = writer; |
| this.contentType = contentType; |
| this.characterEncoding = characterEncoding; |
| } |
| |
| |
| // ------------------------------------------------------ Instance Variables |
| |
| |
| private String characterEncoding = null; |
| private String contentType = "text/html"; |
| private boolean open = false; // Is an element currently open? |
| private UIComponent component; |
| private Writer writer = null; |
| |
| |
| // ----------------------------------------------------- Mock Object Methods |
| |
| |
| /** |
| * <p>Return the <code>Writer</code> that we are wrapping.</p> |
| */ |
| public Writer getWriter() { |
| return this.writer; |
| } |
| |
| |
| // -------------------------------------------------- ResponseWriter Methods |
| |
| |
| /** {@inheritDoc} */ |
| public ResponseWriter cloneWithWriter(Writer writer) { |
| return new MockResponseWriter(writer, contentType, characterEncoding); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void endDocument() throws IOException { |
| finish(); |
| writer.flush(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void endElement(String name) throws IOException { |
| if (open) { |
| writer.write("/"); |
| finish(); |
| } else { |
| writer.write("</"); |
| writer.write(name); |
| writer.write(">"); |
| } |
| component = null; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public String getCharacterEncoding() { |
| return this.characterEncoding; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public String getContentType() { |
| return this.contentType; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void flush() throws IOException { |
| finish(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void startDocument() throws IOException { |
| // Do nothing |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void startElement(String name, UIComponent component) throws IOException { |
| if (name == null) { |
| throw new NullPointerException(); |
| } |
| finish(); |
| writer.write('<'); |
| writer.write(name); |
| open = true; |
| this.component = component; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void writeAttribute(String name, Object value, String property) throws IOException { |
| if (name == null) { |
| throw new NullPointerException(); |
| } |
| if (!open) { |
| throw new IllegalStateException(); |
| } |
| String attribute = findValue(value, property); |
| if (attribute != null) { |
| writer.write(" "); |
| writer.write(name); |
| writer.write("=\""); |
| string(attribute); |
| |
| writer.write("\""); |
| } |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void writeComment(Object comment) throws IOException { |
| if (comment == null) { |
| throw new NullPointerException(); |
| } |
| finish(); |
| writer.write("<!-- "); |
| if (comment instanceof String) { |
| writer.write((String) comment); |
| } else { |
| writer.write(comment.toString()); |
| } |
| writer.write(" -->"); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void writeText(Object text, String property) throws IOException { |
| if (text == null) { |
| throw new NullPointerException(); |
| } |
| finish(); |
| String value = findValue(text, property); |
| if (value != null) { |
| string(value); |
| } |
| |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void writeText(char[] text, int off, int len) throws IOException { |
| if (text == null) { |
| throw new NullPointerException(); |
| } |
| if ((off < 0) || (off > text.length) || (len < 0) || (len > text.length)) { |
| throw new IndexOutOfBoundsException(); |
| } |
| finish(); |
| string(text, off, len); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void writeURIAttribute(String name, Object value, String property) throws IOException { |
| if (name == null) { |
| throw new NullPointerException(); |
| } |
| if (!open) { |
| throw new IllegalStateException(); |
| } |
| String attribute = findValue(value, property); |
| if (attribute != null) { |
| writer.write(" "); |
| writer.write(name); |
| writer.write("=\""); |
| |
| string(attribute); |
| writer.write("\""); |
| } |
| } |
| |
| |
| // ---------------------------------------------------------- Writer Methods |
| |
| |
| /** {@inheritDoc} */ |
| public void close() throws IOException { |
| finish(); |
| writer.close(); |
| } |
| |
| |
| /** {@inheritDoc} */ |
| public void write(char[] cbuf, int off, int len) throws IOException { |
| finish(); |
| writer.write(cbuf, off, len); |
| } |
| |
| |
| // --------------------------------------------------------- Support Methods |
| |
| |
| /** |
| * <p>Write the specified character, filtering if necessary.</p> |
| * |
| * @param ch Character to be written |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| private void character(char ch) throws IOException { |
| |
| if (ch <= 0xff) { |
| // In single byte characters, replace only the five |
| // characters for which well-known entities exist in XML |
| if (ch == 0x22) { |
| writer.write("""); |
| } else if (ch == 0x26) { |
| writer.write("&"); |
| } else if (ch == 0x27) { |
| writer.write("'"); |
| } else if (ch == 0x3C) { |
| writer.write("<"); |
| } else if (ch == 0X3E) { |
| writer.write(">"); |
| } else { |
| writer.write(ch); |
| } |
| } else { |
| if (substitution()) { |
| numeric(writer, ch); |
| } else { |
| writer.write(ch); |
| } |
| } |
| |
| } |
| |
| |
| /** |
| * <p>Close any element that is currently open.</p> |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| private void finish() throws IOException { |
| |
| if (open) { |
| writer.write(">"); |
| open = false; |
| } |
| |
| } |
| |
| |
| /** |
| * <p>Write a numeric character reference for specified character |
| * to the specfied writer.</p> |
| * |
| * @param writer Writer we are writing to |
| * @param ch Character to be translated and appended |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| private void numeric(Writer writer, char ch) throws IOException { |
| |
| writer.write("&#"); |
| writer.write(String.valueOf(ch)); |
| writer.write(";"); |
| |
| } |
| |
| |
| /** |
| * <p>Write the specified characters (after performing suitable |
| * replacement of characters by corresponding entities).</p> |
| * |
| * @param text Character array containing text to be written |
| * @param off Starting offset (zero relative) |
| * @param len Number of characters to be written |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| private void string(char[] text, int off, int len) throws IOException { |
| |
| // Process the specified characters |
| for (int i = off; i < (off + len); i++) { |
| character(text[i]); |
| } |
| |
| } |
| |
| |
| /** |
| * <p>Write the specified string (after performing suitable |
| * replacement of characters by corresponding entities).</p> |
| * |
| * @param s String to be filtered and written |
| * |
| * @exception IOException if an input/output error occurs |
| */ |
| private void string(String s) throws IOException { |
| for (int i = 0; i < s.length(); i++) { |
| character(s.charAt(i)); |
| } |
| |
| } |
| |
| |
| /** |
| * <p>Return true if entity substitution should be performed on double |
| * byte character values.</p> |
| */ |
| private boolean substitution() { |
| |
| return !("UTF-8".equals(characterEncoding) || "UTF-16".equals(characterEncoding)); |
| |
| } |
| |
| private String findValue(final Object value, final String property) { |
| if (value != null) { |
| return value instanceof String ? (String) value : value.toString(); |
| } else if (property != null) { |
| if (component != null) { |
| final Object object = component.getAttributes().get(property); |
| if (object != null) { |
| return object instanceof String ? (String) object : object.toString(); |
| } else { |
| return null; |
| } |
| } |
| |
| } |
| return null; |
| } |
| |
| } |