myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bom...@apache.org
Subject svn commit: r926334 - in /myfaces/tobago/trunk/core/src: main/java/org/apache/myfaces/tobago/internal/webapp/ main/java/org/apache/myfaces/tobago/renderkit/ main/java/org/apache/myfaces/tobago/webapp/ test/java/org/apache/myfaces/tobago/internal/contex...
Date Mon, 22 Mar 2010 21:05:43 GMT
Author: bommel
Date: Mon Mar 22 21:05:42 2010
New Revision: 926334

URL: http://svn.apache.org/viewvc?rev=926334&view=rev
Log:
(TOBAGO-863) Split TobagoResponseWriterImpl into a XmlResponseWriter and a normal HtmlResponseWriter
and introduce a Debug Response Writer

Added:
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java
  (with props)
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
  (with props)
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java
  (with props)
Modified:
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseJsonWriterImpl.java
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterImpl.java
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java
    myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
    myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/internal/context/ResponseWriterDividerUnitTest.java
    myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java

Added: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java?rev=926334&view=auto
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java
(added)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java
Mon Mar 22 21:05:42 2010
@@ -0,0 +1,159 @@
+package org.apache.myfaces.tobago.internal.webapp;
+
+/*
+ * 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.
+ */
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.EmptyStackException;
+import java.util.Stack;
+
+public class DebugTobagoResponseWriterWrapper extends TobagoResponseWriter {
+
+  private Stack<String> stack = new Stack<String>();
+
+  private static final Log LOG = LogFactory.getLog(DebugTobagoResponseWriterWrapper.class);
+
+  private final TobagoResponseWriter responseWriter;
+
+  public DebugTobagoResponseWriterWrapper(TobagoResponseWriter responseWriter) {
+    this.responseWriter = responseWriter;
+  }
+
+  public void write(String string) throws IOException {
+    responseWriter.write(string);
+  }
+
+  public void writeComment(Object comment) throws IOException {
+    String commentStr = comment.toString();
+    if (commentStr.indexOf("--") > 0) {
+      String trace = getCallingClassStackTraceElementString();
+      LOG.error(
+          "Comment must not contain the sequence '--', comment = '"
+              + comment + "' " + trace.substring(trace.indexOf('(')));
+
+      commentStr = StringUtils.replace(commentStr, "--", "++");
+    }
+    responseWriter.writeComment(commentStr);
+  }
+
+  public ResponseWriter cloneWithWriter(Writer writer) {
+    return new DebugTobagoResponseWriterWrapper((TobagoResponseWriter) responseWriter.cloneWithWriter(writer));
+  }
+
+  @Deprecated
+  public void writeAttribute(String name, Object value, String property) throws IOException
{
+    responseWriter.writeAttribute(name, value, property);
+  }
+
+  @Deprecated
+  public void writeText(Object text, String property) throws IOException {
+    responseWriter.writeText(text, property);
+  }
+
+  public void flush() throws IOException {
+    responseWriter.flush();
+  }
+
+  public void writeAttribute(String name, String value, boolean escape) throws IOException
{
+    responseWriter.writeAttribute(name, value, null);
+  }
+
+  public void writeClassAttribute() throws IOException {
+    responseWriter.writeAttribute(HtmlAttributes.CLASS, null, Attributes.STYLE_CLASS);
+  }
+
+  public String getContentType() {
+    return responseWriter.getContentType();
+  }
+
+  public String getCharacterEncoding() {
+    return responseWriter.getCharacterEncoding();
+  }
+
+  public void startDocument() throws IOException {
+    responseWriter.startDocument();
+  }
+
+  public void endDocument() throws IOException {
+    responseWriter.endDocument();
+  }
+
+  public void writeURIAttribute(String name, Object value, String property) throws IOException
{
+    responseWriter.writeURIAttribute(name, value, property);
+  }
+
+  public void writeText(char[] text, int off, int len) throws IOException {
+    responseWriter.writeText(text, off, len);
+  }
+
+  public void write(char[] chars, int i, int i1) throws IOException {
+    responseWriter.write(chars, i, i1);
+  }
+
+  public void close() throws IOException {
+    responseWriter.close();
+  }
+
+  @Override
+  public void endElement(String name) throws IOException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("end Element: " + name);
+    }
+    String top = "";
+    try {
+      top = stack.pop();
+    } catch (EmptyStackException e) {
+      LOG.error("Failed to close element \"" + name + "\"!");
+      throw e;
+    }
+
+    if (!top.equals(name)) {
+      final String trace = getCallingClassStackTraceElementString();
+      LOG.error("Element end with name='" + name + "' doesn't "
+          + "match with top element on the stack='" + top + "' "
+          + trace.substring(trace.indexOf('(')));
+    }
+    responseWriter.endElement(name);
+  }
+
+  @Override
+  public void startElement(String name, UIComponent currentComponent)
+      throws IOException {
+    stack.push(name);
+    responseWriter.startElement(name, currentComponent);
+  }
+  
+  protected final String getCallingClassStackTraceElementString() {
+    final StackTraceElement[] stackTrace = new Exception().getStackTrace();
+    int i = 1;
+    while (stackTrace[i].getClassName().equals(this.getClass().getName())) {
+      i++;
+    }
+    return stackTrace[i].toString();
+  }
+
+}

Propchange: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugTobagoResponseWriterWrapper.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseJsonWriterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseJsonWriterImpl.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseJsonWriterImpl.java
(original)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseJsonWriterImpl.java
Mon Mar 22 21:05:42 2010
@@ -21,12 +21,10 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.tobago.internal.ajax.AjaxInternalUtils;
 import org.apache.myfaces.tobago.internal.util.FastStringWriter;
-import org.apache.myfaces.tobago.util.XmlUtils;
 
 import javax.faces.component.UIComponent;
 import java.io.IOException;
 import java.io.Writer;
-import java.util.EmptyStackException;
 
 public class TobagoResponseJsonWriterImpl extends TobagoResponseWriterImpl {
 
@@ -35,8 +33,8 @@ public class TobagoResponseJsonWriterImp
   private Writer javascriptWriter;
   private boolean javascriptMode;
 
-  public TobagoResponseJsonWriterImpl(Writer writer, String contentType, String characterEncoding,
boolean xml) {
-    super(writer, contentType, characterEncoding, xml);
+  public TobagoResponseJsonWriterImpl(Writer writer, String contentType, String characterEncoding)
{
+    super(writer, contentType, characterEncoding);
     this.javascriptWriter = new FastStringWriter();
   }
 
@@ -68,7 +66,6 @@ public class TobagoResponseJsonWriterImp
   protected void startElementInternal(Writer writer, String name, UIComponent currentComponent)
       throws IOException {
     setComponent(currentComponent);
-    getStack().push(name);
     if (isStartStillOpen()) {
       writer.write(">");
     }
@@ -79,29 +76,8 @@ public class TobagoResponseJsonWriterImp
 
   @Override
   protected void endElementInternal(Writer writer, String name) throws IOException {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("end Element: " + name);
-    }
-    String top = "";
-    try {
-      top = getStack().pop();
-    } catch (EmptyStackException e) {
-      LOG.error("Failed to close element \"" + name + "\"!");
-      throw e;
-    }
-    if (!top.equals(name)) {
-      final String trace = getCallingClassStackTraceElementString();
-      LOG.error("Element end with name='" + name + "' doesn't "
-          + "match with top element on the stack='" + top + "' "
-          + trace.substring(trace.indexOf('(')));
-    }
-
     if (EMPTY_TAG.contains(name)) {
-      if (isXml()) {
-        writer.write("/>");
-      } else {
         writer.write(">");
-      }
     } else {
       if (isStartStillOpen()) {
         writer.write(">");
@@ -138,14 +114,10 @@ public class TobagoResponseJsonWriterImp
       writer.write(' ');
       writer.write(name);
       writer.write("=\\\"");
-      if (isXml()) {
-        writer.write(XmlUtils.escape(value));
+      if (escape) {
+        getHelper().writeAttributeValue(value);
       } else {
-        if (escape) {
-          getHelper().writeAttributeValue(value);
-        } else {
-          writer.write(value);
-        }
+        writer.write(value);
       }
       writer.write("\\\"");
     }

Added: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java?rev=926334&view=auto
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
(added)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
Mon Mar 22 21:05:42 2010
@@ -0,0 +1,303 @@
+package org.apache.myfaces.tobago.internal.webapp;
+
+/*
+ * 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.
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlConstants;
+import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class TobagoResponseWriterBase extends TobagoResponseWriter {
+
+  private static final Log LOG = LogFactory.getLog(TobagoResponseWriterBase.class);
+
+  protected static final Set<String> EMPTY_TAG = new HashSet<String>(Arrays.asList(
+      HtmlConstants.BR,
+      HtmlConstants.AREA,
+      HtmlConstants.LINK,
+      HtmlConstants.IMG,
+      HtmlConstants.PARAM,
+      HtmlConstants.HR,
+      HtmlConstants.INPUT,
+      HtmlConstants.COL,
+      HtmlConstants.BASE,
+      HtmlConstants.META));
+
+  private UIComponent component;
+
+  private boolean startStillOpen;
+
+  private final Writer writer;
+
+  private final String contentType;
+
+  private final String characterEncoding;
+
+  protected TobagoResponseWriterBase(Writer writer, String contentType, String characterEncoding)
{
+    this.writer = writer;
+    this.contentType = contentType;
+    this.characterEncoding = characterEncoding != null ? characterEncoding : "UTF-8";
+  }
+
+  protected final Writer getWriter() {
+    return writer;
+  }
+
+
+
+  protected final UIComponent getComponent() {
+    return component;
+  }
+
+  protected final void setComponent(UIComponent component) {
+    this.component = component;
+  }
+
+  protected final boolean isStartStillOpen() {
+    return startStillOpen;
+  }
+
+  protected final void setStartStillOpen(boolean startStillOpen) {
+    this.startStillOpen = startStillOpen;
+  }
+
+  protected final 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;
+        }
+      } else {
+        final String trace = getCallingClassStackTraceElementString();
+        LOG.error("Don't know what to do! "
+            + "Property defined, but no component to get a value. "
+            + trace.substring(trace.indexOf('(')));
+        LOG.error("value = 'null'");
+        LOG.error("property = '" + property + "'");
+        return null;
+      }
+    } else {
+      final String trace = getCallingClassStackTraceElementString();
+      LOG.error("Don't know what to do! "
+          + "No value and no property defined. "
+          + trace.substring(trace.indexOf('(')));
+      LOG.error("value = 'null'");
+      LOG.error("property = 'null'");
+      return null;
+    }
+  }
+
+  public void write(final char[] cbuf, final int off, final int len)
+      throws IOException {
+    writer.write(cbuf, off, len);
+  }
+
+  @Override
+  public void write(String string) throws IOException {
+    writeInternal(writer, string);
+  }
+
+  protected final void writeInternal(Writer writer, String string) throws IOException {
+    closeOpenTag();
+    writer.write(string);
+  }
+
+  @Override
+  public void write(int i) throws IOException {
+    closeOpenTag();
+    writer.write(i);
+  }
+
+  @Override
+  public void write(char[] chars) throws IOException {
+    closeOpenTag();
+    writer.write(chars);
+  }
+
+  @Override
+  public void write(String string, int i, int i1) throws IOException {
+    closeOpenTag();
+    writer.write(string, i, i1);
+  }
+
+  public void close() throws IOException {
+    closeOpenTag();
+    writer.close();
+  }
+
+  public void flush() throws IOException {
+    /*
+    From the api:
+    Flush any ouput buffered by the output method to the underlying Writer or OutputStream.
+    This method will not flush the underlying Writer or OutputStream;
+    it simply clears any values buffered by this ResponseWriter.
+     */
+    closeOpenTag();
+  }
+
+
+
+
+
+
+  protected void closeOpenTag() throws IOException {
+    if (startStillOpen) {
+      writer.write("\n>");
+      startStillOpen = false;
+    }
+  }
+
+  public void startDocument() throws IOException {
+    // nothing to do
+  }
+
+  public void endDocument() throws IOException {
+    // nothing to do
+  }
+
+  public String getContentType() {
+    return contentType;
+  }
+
+  public String getCharacterEncoding() {
+    return characterEncoding;
+  }
+
+  public void startElement(final String name, final UIComponent currentComponent)
+      throws IOException {
+    startElementInternal(writer, name, currentComponent);
+  }
+
+  protected void startElementInternal(Writer writer, String name, UIComponent currentComponent)
+      throws IOException {
+    this.component = currentComponent;
+//    closeOpenTag();
+    if (startStillOpen) {
+      writer.write("\n>");
+    }
+    writer.write("<");
+    writer.write(name);
+    startStillOpen = true;
+  }
+
+  public void endElement(final String name) throws IOException {
+    endElementInternal(writer, name);
+  }
+
+  public void writeComment(final Object obj) throws IOException {
+    closeOpenTag();
+    String comment = obj.toString();
+    write("<!--");
+    write(comment);
+    write("-->");
+  }
+
+
+
+  public void writeAttribute(final String name, final Object value, final String property)
+      throws IOException {
+
+    final String attribute = findValue(value, property);
+    writeAttribute(name, attribute, true);
+  }
+
+  protected final String getCallingClassStackTraceElementString() {
+    final StackTraceElement[] stackTrace = new Exception().getStackTrace();
+    int i = 1;
+    while (stackTrace[i].getClassName().equals(this.getClass().getName())) {
+      i++;
+    }
+    return stackTrace[i].toString();
+  }
+
+  public void writeURIAttribute(final String s, final Object obj, final String s1)
+      throws IOException {
+    LOG.error("Not implemented yet!");
+  }
+
+// interface TobagoResponseWriter //////////////////////////////////////////////////////////////////////////////////
+
+  public void writeAttribute(final String name, final String value, final boolean escape)
+      throws IOException {
+    writeAttributeInternal(writer, name, value, escape);
+  }
+
+  public void writeClassAttribute() throws IOException {
+    StyleClasses clazz = (StyleClasses) component.getAttributes().get(Attributes.STYLE_CLASS);
+    if (clazz != null) {
+      writeAttribute(HtmlAttributes.CLASS, clazz.toString(), false);
+    }
+  }
+
+
+  protected void endElementInternal(Writer writer, String name) throws IOException {
+    if (EMPTY_TAG.contains(name)) {
+      closeEmptyTag();
+    } else {
+      if (startStillOpen) {
+        writer.write("\n>");
+      }
+      writer.write("</");
+      writer.write(name);
+//      writer.write("\n>"); // FIXME: this makes problems with Tidy
+      writer.write(">");
+    }
+    startStillOpen = false;
+  }
+  protected abstract void closeEmptyTag() throws IOException;
+
+  protected void writeAttributeInternal(Writer writer, String name, String value, boolean
escape)
+      throws IOException {
+    if (!startStillOpen) {
+      String trace = getCallingClassStackTraceElementString();
+      String error = "Cannot write attribute when start-tag not open. "
+          + "name = '" + name + "' "
+          + "value = '" + value + "' "
+          + trace.substring(trace.indexOf('('));
+      LOG.error(error);
+      throw new IllegalStateException(error);
+    }
+
+    if (value != null) {
+      writer.write(' ');
+      writer.write(name);
+      writer.write("=\"");
+      writerAttributeValue(value, escape);
+      writer.write('\"');
+    }
+  }
+  protected abstract void writerAttributeValue(String value, boolean escape) throws IOException;
+
+
+}
+

Propchange: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterImpl.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterImpl.java
(original)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterImpl.java
Mon Mar 22 21:05:42 2010
@@ -17,378 +17,66 @@ package org.apache.myfaces.tobago.intern
  * limitations under the License.
  */
 
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.tobago.component.Attributes;
 import org.apache.myfaces.tobago.internal.util.HtmlWriterUtils;
 import org.apache.myfaces.tobago.renderkit.css.Style;
-import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
 import org.apache.myfaces.tobago.renderkit.html.HtmlConstants;
-import org.apache.myfaces.tobago.renderkit.html.StyleClasses;
-import org.apache.myfaces.tobago.util.XmlUtils;
-import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 
 import javax.faces.component.UIComponent;
 import javax.faces.context.ResponseWriter;
 import java.io.IOException;
 import java.io.Writer;
-import java.util.*;
+import java.util.Map;
 
-public class TobagoResponseWriterImpl extends TobagoResponseWriter {
+public class TobagoResponseWriterImpl extends TobagoResponseWriterBase {
 
-  private static final Log LOG = LogFactory.getLog(TobagoResponseWriterImpl.class);
-
-  protected static final Set<String> EMPTY_TAG = new HashSet<String>(Arrays.asList(
-      HtmlConstants.BR,
-      HtmlConstants.AREA,
-      HtmlConstants.LINK,
-      HtmlConstants.IMG,
-      HtmlConstants.PARAM,
-      HtmlConstants.HR,
-      HtmlConstants.INPUT,
-      HtmlConstants.COL,
-      HtmlConstants.BASE,
-      HtmlConstants.META));
-
-  private Writer writer;
-
-  private UIComponent component;
-
-  private boolean startStillOpen;
-
-  private String contentType;
-
-  private String characterEncoding;
-
-  private Stack<String> stack;
-
-  /**
-   * use XML instead HMTL
-   */
-  private boolean xml;
+   private static final String HTML_DOCTYPE =
+      "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">";
 
   private HtmlWriterUtils helper;
 
   public TobagoResponseWriterImpl(
-      Writer writer, String contentType, String characterEncoding, boolean xml) {
-//    LOG.info("new TobagoResponseWriterImpl!");
-//    final StackTraceElement[] stackTrace = new Exception().getStackTrace();
-//    for (int i = 1; i < stackTrace.length && i < 5; i++) {
-//      LOG.info("  " + stackTrace[i].toString());
-//    }
-    this.writer = writer;
-    this.component = null;
-    this.stack = new Stack<String>();
-    this.contentType = contentType;
-    this.characterEncoding = characterEncoding != null ? characterEncoding : "UTF-8";
-    this.xml = xml;
+      Writer writer, String contentType, String characterEncoding) {
+    super(writer, contentType, characterEncoding);
     this.helper = new HtmlWriterUtils(writer, characterEncoding);
   }
 
-  protected final UIComponent getComponent() {
-    return component;
-  }
-
-  protected final void setComponent(UIComponent component) {
-    this.component = component;
-  }
-
-  protected final boolean isStartStillOpen() {
-    return startStillOpen;
-  }
-
-  protected final void setStartStillOpen(boolean startStillOpen) {
-    this.startStillOpen = startStillOpen;
-  }
-
-  protected final Stack<String> getStack() {
-    return stack;
-  }
-
-  public final boolean isXml() {
-    return xml;
-  }
-
   public final HtmlWriterUtils getHelper() {
     return helper;
   }
 
-
-  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;
-        }
-      } else {
-        final String trace = getCallingClassStackTraceElementString();
-        LOG.error("Don't know what to do! "
-            + "Property defined, but no component to get a value. "
-            + trace.substring(trace.indexOf('(')));
-        LOG.error("value = 'null'");
-        LOG.error("property = '" + property + "'");
-        return null;
-      }
-    } else {
-      final String trace = getCallingClassStackTraceElementString();
-      LOG.error("Don't know what to do! "
-          + "No value and no property defined. "
-          + trace.substring(trace.indexOf('(')));
-      LOG.error("value = 'null'");
-      LOG.error("property = 'null'");
-      return null;
-    }
-  }
-
-  protected final Writer getWriter() {
-    return writer;
-  }
-
-  public void write(final char[] cbuf, final int off, final int len)
-      throws IOException {
-    if (new String(cbuf).equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")) {
-      LOG.error("Filtering XML header: " + new String(cbuf) + " FIXME"); // FIXME
-    } else {
-      writer.write(cbuf, off, len);
-    }
-  }
-
-  @Override
-  public void write(String string) throws IOException {
-    writeInternal(writer, string);
-  }
-
-  protected final void writeInternal(Writer writer, String string) throws IOException {
-    closeOpenTag();
-    writer.write(string);
-  }
-
-  @Override
-  public void write(int i) throws IOException {
-    closeOpenTag();
-    writer.write(i);
-  }
-
-  @Override
-  public void write(char[] chars) throws IOException {
-    closeOpenTag();
-    writer.write(chars);
-  }
-
-  @Override
-  public void write(String string, int i, int i1) throws IOException {
-    closeOpenTag();
-    writer.write(string, i, i1);
-  }
-
-  public void close() throws IOException {
-    closeOpenTag();
-    writer.close();
-  }
-
-  public void flush() throws IOException {
-    /*
-    From the api:
-    Flush any ouput buffered by the output method to the underlying Writer or OutputStream.
-    This method will not flush the underlying Writer or OutputStream;
-    it simply clears any values buffered by this ResponseWriter.
-     */
-    closeOpenTag();
-  }
-
   public void writeText(final Object text, final String property)
       throws IOException {
     closeOpenTag();
     final String value = findValue(text, property);
-    if (xml) {
-      write(XmlUtils.escape(value));
-    } else {
-      helper.writeText(value);
-    }
-  }
-
-  protected void closeOpenTag() throws IOException {
-    if (startStillOpen) {
-      writer.write("\n>");
-      startStillOpen = false;
-    }
+    helper.writeText(value);
   }
 
   public void writeText(final char[] text, final int offset, final int length)
       throws IOException {
     closeOpenTag();
-    if (xml) {
-      writer.write(XmlUtils.escape(text, offset, length, true));
-    } else {
-      helper.writeText(text, offset, length);
-    }
-  }
-
-  public void startDocument() throws IOException {
-    // nothing to do
-  }
-
-  public void endDocument() throws IOException {
-    // nothing to do
-  }
-
-  public String getContentType() {
-    return contentType;
-  }
-
-  public String getCharacterEncoding() {
-    return characterEncoding;
-  }
-
-  public void startElement(final String name, final UIComponent currentComponent)
-      throws IOException {
-    startElementInternal(writer, name, currentComponent);
+    helper.writeText(text, offset, length);
   }
 
-  protected void startElementInternal(Writer writer, String name, UIComponent currentComponent)
-      throws IOException {
-    this.component = currentComponent;
-    stack.push(name);
-//    closeOpenTag();
-    if (startStillOpen) {
-      writer.write("\n>");
-    }
-    writer.write("<");
-    writer.write(name);
-    startStillOpen = true;
-  }
-
-  public void endElement(final String name) throws IOException {
-    endElementInternal(writer, name);
-  }
-
-  protected void endElementInternal(Writer writer, String name) throws IOException {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("end Element: " + name);
-    }
-
-    String top = "";
-    try {
-      top = stack.pop();
-    } catch (EmptyStackException e) {
-      LOG.error("Failed to close element \"" + name + "\"!");
-      throw e;
-    }
-    if (!top.equals(name)) {
-      final String trace = getCallingClassStackTraceElementString();
-      LOG.error("Element end with name='" + name + "' doesn't "
-          + "match with top element on the stack='" + top + "' "
-          + trace.substring(trace.indexOf('(')));
-    }
-
-    if (EMPTY_TAG.contains(name)) {
-      if (xml) {
-        writer.write("\n/>");
-      } else {
-        writer.write("\n>");
-      }
-    } else {
-      if (startStillOpen) {
-        writer.write("\n>");
-      }
-      writer.write("</");
-      writer.write(name);
-//      writer.write("\n>"); // FIXME: this makes problems with Tidy
-      writer.write(">");
-    }
-    startStillOpen = false;
+  @Override
+  protected final void closeEmptyTag() throws IOException {
+     getWriter().write("\n>");
   }
 
-  public void writeComment(final Object obj) throws IOException {
-    closeOpenTag();
-    String comment = obj.toString();
-    write("<!--");
-    if (comment.indexOf("--") < 0) {
-      write(comment);
+  @Override
+  protected void writerAttributeValue(String value, boolean escape) throws IOException {
+    if (escape) {
+       helper.writeAttributeValue(value);
     } else {
-      String trace = getCallingClassStackTraceElementString();
-      LOG.warn(
-          "Comment must not contain the sequence '--', comment = '"
-              + comment + "' " + trace.substring(trace.indexOf('(')));
-      write(StringUtils.replace(comment, "--", "++"));
+       getWriter().write(value);
     }
-    write("-->");
   }
 
   public ResponseWriter cloneWithWriter(final Writer originalWriter) {
     return new TobagoResponseWriterImpl(
-        originalWriter, getContentType(), getCharacterEncoding(), isXml());
-  }
-
-  public void writeAttribute(final String name, final Object value, final String property)
-      throws IOException {
-
-    final String attribute = findValue(value, property);
-    writeAttribute(name, attribute, true);
-  }
-
-  protected final String getCallingClassStackTraceElementString() {
-    final StackTraceElement[] stackTrace = new Exception().getStackTrace();
-    int i = 1;
-    while (stackTrace[i].getClassName().equals(this.getClass().getName())) {
-      i++;
-    }
-    return stackTrace[i].toString();
-  }
-
-  public void writeURIAttribute(final String s, final Object obj, final String s1)
-      throws IOException {
-    LOG.error("Not implemented yet!");
-  }
-
-// interface TobagoResponseWriter //////////////////////////////////////////////////////////////////////////////////
-
-  public void writeAttribute(final String name, final String value, final boolean escape)
-      throws IOException {
-    writeAttributeInternal(writer, name, value, escape);
+        originalWriter, getContentType(), getCharacterEncoding());
   }
 
-  protected void writeAttributeInternal(Writer writer, String name, String value, boolean
escape)
-      throws IOException {
-    if (!startStillOpen) {
-      String trace = getCallingClassStackTraceElementString();
-      String error = "Cannot write attribute when start-tag not open. "
-          + "name = '" + name + "' "
-          + "value = '" + value + "' "
-          + trace.substring(trace.indexOf('('));
-      LOG.error(error);
-      throw new IllegalStateException(error);
-    }
-
-    if (value != null) {
-      writer.write(' ');
-      writer.write(name);
-      writer.write("=\"");
-      if (xml) {
-        writer.write(XmlUtils.escape(value));
-      } else {
-        if (escape) {
-          helper.writeAttributeValue(value);
-        } else {
-          writer.write(value);
-        }
-      }
-      writer.write('\"');
-    }
-  }
-
-  public void writeClassAttribute() throws IOException {
-    StyleClasses clazz = (StyleClasses) component.getAttributes().get(Attributes.STYLE_CLASS);
-    if (clazz != null) {
-      writeAttribute(HtmlAttributes.CLASS, clazz.toString(), false);
-    }
-  }
 
   public static Style ensureHtmlStyleMap(UIComponent component, Style styles) {
     if (styles == null) {
@@ -398,4 +86,15 @@ public class TobagoResponseWriterImpl ex
     return styles;
   }
 
+  @Override
+  public void startDocument() throws IOException {
+    getWriter().write(HTML_DOCTYPE);
+    getWriter().write('\n');
+    startElement(HtmlConstants.HTML, null);
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+    endElement(HtmlConstants.HTML);    
+  }
 }

Modified: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java
(original)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java
Mon Mar 22 21:05:42 2010
@@ -42,11 +42,6 @@ public class TobagoResponseWriterWrapper
     responseWriter.endElement(name);
   }
 
-  @Override
-  public boolean isXml() {
-    // fixme
-    return false;
-  }
 
   public void write(String string) throws IOException {
     responseWriter.write(string);

Added: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java?rev=926334&view=auto
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java
(added)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java
Mon Mar 22 21:05:42 2010
@@ -0,0 +1,80 @@
+package org.apache.myfaces.tobago.internal.webapp;
+
+/*
+ * 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.
+ */
+
+import org.apache.myfaces.tobago.renderkit.html.HtmlConstants;
+import org.apache.myfaces.tobago.util.XmlUtils;
+
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+public final class TobagoResponseXmlWriterImpl extends TobagoResponseWriterBase {
+
+  private static final String XHTML_DOCTYPE =
+      "<!DOCTYPE html      PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
+          + "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">";
+
+  public TobagoResponseXmlWriterImpl(
+      Writer writer, String contentType, String characterEncoding) {
+    super(writer, contentType, characterEncoding);
+  }
+
+  public void writeText(final Object text, final String property)
+      throws IOException {
+    closeOpenTag();
+    final String value = findValue(text, property);
+    write(XmlUtils.escape(value));
+  }
+
+  public void writeText(final char[] text, final int offset, final int length)
+      throws IOException {
+    closeOpenTag();
+    getWriter().write(XmlUtils.escape(text, offset, length, true));
+  }
+
+
+  public ResponseWriter cloneWithWriter(final Writer originalWriter) {
+    return new TobagoResponseXmlWriterImpl(
+        originalWriter, getContentType(), getCharacterEncoding());
+  }
+
+  @Override
+  public void closeEmptyTag() throws IOException {
+    getWriter().write("\n/>");
+  }
+
+  @Override
+  protected void writerAttributeValue(String value, boolean escape) throws IOException {
+    getWriter().write(XmlUtils.escape(value));
+  }
+
+  @Override
+  public void startDocument() throws IOException {
+    getWriter().write(XHTML_DOCTYPE);
+    getWriter().write('\n');
+    startElement(HtmlConstants.HTML, null);
+    writeAttribute("xmlns", "http://www.w3.org/1999/xhtml", false);
+
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+    endElement(HtmlConstants.HTML);
+  }
+}

Propchange: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseXmlWriterImpl.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Modified: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java
(original)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java
Mon Mar 22 21:05:42 2010
@@ -21,6 +21,8 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseJsonWriterImpl;
 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterImpl;
+import org.apache.myfaces.tobago.internal.webapp.TobagoResponseXmlWriterImpl;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
 
 import javax.faces.FactoryFinder;
 import javax.faces.context.FacesContext;
@@ -91,7 +93,7 @@ public class TobagoRenderKit extends Ren
       contentType = "text/fo";
       LOG.warn("patching content type from " + contentTypeList + " to " + contentType + "'");
     } else if (contentTypeList.indexOf("application/json") > -1) {
-      return new TobagoResponseJsonWriterImpl(writer, "application/json", characterEncoding,
false);
+      return new TobagoResponseJsonWriterImpl(writer, "application/json", characterEncoding);
     } else {
       contentType = "text/html";
       LOG.warn("Content-Type '" + contentTypeList + "' not supported! Using text/html");
@@ -106,8 +108,17 @@ public class TobagoRenderKit extends Ren
     // XXX for XHTML 1.0 the content type must be set to "text/html" for IE6
     // XXX so at this time we can't differ ...
 //    xml = true;
-
-    return new TobagoResponseWriterImpl(writer, contentType, characterEncoding, xml);
+    TobagoResponseWriter responseWriter;
+    if (xml) {
+      responseWriter = new TobagoResponseXmlWriterImpl(writer, contentType, characterEncoding);
+    } else {
+      responseWriter = new TobagoResponseWriterImpl(writer, contentType, characterEncoding);
+    }
+    /* TODO if ProjectState Development use the Debug Response Writer
+    if (ProjectStage.Development)) {
+      return new DebugTobagoResponseWriterWrapper(responseWriter);
+    } */
+    return responseWriter;
   }
 
   @Override

Modified: myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
(original)
+++ myfaces/tobago/trunk/core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
Mon Mar 22 21:05:42 2010
@@ -50,8 +50,6 @@ public abstract class TobagoResponseWrit
 
   @Override
   public abstract void endElement(String name) throws IOException;
-
-  public abstract boolean isXml();
     
   public abstract void write(String string) throws IOException;
 

Modified: myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/internal/context/ResponseWriterDividerUnitTest.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/internal/context/ResponseWriterDividerUnitTest.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/internal/context/ResponseWriterDividerUnitTest.java
(original)
+++ myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/internal/context/ResponseWriterDividerUnitTest.java
Mon Mar 22 21:05:42 2010
@@ -3,7 +3,7 @@ package org.apache.myfaces.tobago.intern
 import org.apache.myfaces.test.mock.MockExternalContext;
 import org.apache.myfaces.test.mock.MockFacesContext;
 import org.apache.myfaces.test.mock.MockHttpServletRequest;
-import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterImpl;
+import org.apache.myfaces.tobago.internal.webapp.TobagoResponseXmlWriterImpl;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -39,7 +39,7 @@ public class ResponseWriterDividerUnitTe
     MockExternalContext externalContext = new MockExternalContext(null, new MockHttpServletRequest(),
null);
     facesContext.setExternalContext(externalContext);
     StringWriter stringWriter = new StringWriter();
-    facesContext.setResponseWriter(new TobagoResponseWriterImpl(stringWriter, "text/xml",
"ISO-8859-1", true));
+    facesContext.setResponseWriter(new TobagoResponseXmlWriterImpl(stringWriter, "text/xml",
"ISO-8859-1"));
 
     DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
     DefaultMutableTreeNode colors = new DefaultMutableTreeNode("Colors");

Modified: myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java
URL: http://svn.apache.org/viewvc/myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java?rev=926334&r1=926333&r2=926334&view=diff
==============================================================================
--- myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java
(original)
+++ myfaces/tobago/trunk/core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java
Mon Mar 22 21:05:42 2010
@@ -19,6 +19,7 @@ package org.apache.myfaces.tobago.webapp
 
 import junit.framework.TestCase;
 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterImpl;
+import org.apache.myfaces.tobago.internal.webapp.TobagoResponseXmlWriterImpl;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -26,18 +27,21 @@ import java.io.StringWriter;
 public class TobagoResponseWriterUnitTest extends TestCase {
 
   private StringWriter stringWriter;
-  private TobagoResponseWriterImpl writer;
+  private TobagoResponseWriter writer;
 
   protected void setUp() throws Exception {
     super.setUp();
     stringWriter = new StringWriter();
-    writer = new TobagoResponseWriterImpl(stringWriter, "", "UTF-8", false);
+    writer = new TobagoResponseWriterImpl(stringWriter, "", "UTF-8");
   }
 
   public void testDocument() throws IOException {
     writer.startDocument();
     writer.endDocument();
-    assertEquals("no content needed", "", stringWriter.toString());
+    assertEquals("content expected", 
+        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"
+
+        "<html\n" +
+        "></html>", stringWriter.toString());
   }
 
   public void testEmptyTag() throws IOException {
@@ -97,7 +101,7 @@ public class TobagoResponseWriterUnitTes
   }
 
   public void testNonUtf8() throws IOException {
-    TobagoResponseWriterImpl writer1 = new TobagoResponseWriterImpl(stringWriter, "", "ISO-8859-1",
false);
+    TobagoResponseWriter writer1 = new TobagoResponseWriterImpl(stringWriter, "", "ISO-8859-1");
     writer1.startElement("input", null);
     writer1.writeAttribute("value", "Gutschein über 100 €.", null);
     writer1.writeAttribute("readonly", true);
@@ -107,7 +111,7 @@ public class TobagoResponseWriterUnitTes
   }
 
   public void testCharArray() throws IOException {
-    TobagoResponseWriterImpl writer = new TobagoResponseWriterImpl(stringWriter, "text/xml",
"ISO-8859-1", true);
+    TobagoResponseWriter writer = new TobagoResponseXmlWriterImpl(stringWriter, "text/xml",
"ISO-8859-1");
     writer.writeText("123".toCharArray(), 0, 3);
     assertEquals("123", stringWriter.toString());
   }



Mime
View raw message