You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by cs...@apache.org on 2017/03/16 13:20:53 UTC

cxf git commit: [CXF-6423] PrettyLoggingFilter tests and improvements with thanks to Thomas Skjolberg. Closes #75

Repository: cxf
Updated Branches:
  refs/heads/master 8e769d46b -> 3bbfc22e1


[CXF-6423] PrettyLoggingFilter tests and improvements with thanks to Thomas Skjolberg. Closes #75


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/3bbfc22e
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/3bbfc22e
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/3bbfc22e

Branch: refs/heads/master
Commit: 3bbfc22e182ffea8c98ba8f84b4f55abfce353e7
Parents: 8e769d4
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Thu Mar 16 14:20:42 2017 +0100
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Thu Mar 16 14:20:42 2017 +0100

----------------------------------------------------------------------
 .../ext/logging/event/PrettyLoggingFilter.java  | 102 ++++++++++++-------
 .../ext/logging/TestPrettyLoggingFilter.java    |  90 ++++++++++++++++
 2 files changed, 158 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/3bbfc22e/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrettyLoggingFilter.java
----------------------------------------------------------------------
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrettyLoggingFilter.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrettyLoggingFilter.java
index 27ed7e4..a3bc909 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrettyLoggingFilter.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrettyLoggingFilter.java
@@ -18,14 +18,12 @@
  */
 package org.apache.cxf.ext.logging.event;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.StringReader;
 import java.io.StringWriter;
 
 import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
-import javax.xml.transform.stream.StreamSource;
 
 import org.apache.cxf.staxutils.PrettyPrintXMLStreamWriter;
 import org.apache.cxf.staxutils.StaxUtils;
@@ -45,54 +43,90 @@ public class PrettyLoggingFilter implements LogEventSender {
     @Override
     public void send(LogEvent event) {
         if (shouldPrettyPrint(event)) {
-            event.setPayload(getPrettyMessage(event.getPayload(), event.getEncoding()));
+            event.setPayload(getPrettyMessage(event));
         }
         next.send(event);
     }
 
     private boolean shouldPrettyPrint(LogEvent event) {
-        String contentType = event.getContentType();
-        return prettyLogging
-            && contentType != null
+        String contentType = event.getContentType(); 
+        return prettyLogging 
+            && contentType != null 
             && contentType.indexOf("xml") >= 0
             && contentType.toLowerCase().indexOf("multipart/related") < 0
             && event.getPayload().length() > 0;
     }
 
-    public String getPrettyMessage(String message, String encoding) {
-        StringWriter swriter = new StringWriter();
+    /**
+     * Pretty-print {@linkplain LogEvent} XML payload.
+     * 
+     * @param event the log event containing an XML payload which is to be pretty-printed.
+     * @return pretty-printed XML or original payload in case of an unexpected exception.
+     */
+    
+    private String getPrettyMessage(LogEvent event) {
+        String payload = event.getPayload();
+        StringWriter swriter = new StringWriter(estimatePrettySize(payload));
+        
+        XMLStreamWriter xwriter = new PrettyPrintXMLStreamWriter(StaxUtils.createXMLStreamWriter(swriter), 2);
+        XMLStreamReader xreader = StaxUtils.createXMLStreamReader(new StringReader(payload));
         try {
-            // Using XMLStreamWriter instead of Transformer as it works with non well formed xml
-            // that can occur when we set a limit and cur the rest off
-            XMLStreamWriter xwriter = StaxUtils.createXMLStreamWriter(swriter);
-            xwriter = new PrettyPrintXMLStreamWriter(xwriter, 2);
-            encoding = encoding == null ? "UTF-8" : encoding;
-            InputStream in = new ByteArrayInputStream(message.getBytes(encoding));
-            try {
-                StaxUtils.copy(new StreamSource(in), xwriter);
-            } catch (XMLStreamException xse) {
-                //ignore
-            } finally {
-                try {
-                    xwriter.flush();
-                    xwriter.close();
-                } catch (XMLStreamException xse2) {
-                    //ignore
-                }
-                in.close();
-            }
-        } catch (IOException e) {
-            LOG.debug("Error while pretty printing cxf message, returning what we got till now.", e);
-        }
+            StaxUtils.copy(xreader, xwriter);
+            xwriter.flush();
+        } catch (XMLStreamException xse) {
+            if (!event.isTruncated()) {
+                LOG.debug("Error while pretty printing cxf message, returning raw message.", xse);
+                return payload;
+            } 
+            
+            // Expected behavior for truncated payloads - keep what is already written.
+            // This might effectively result in additional truncation, 
+            // as the truncated XML document might result in partially parsed XML nodes, 
+            // for example an open start tag. As long as a truncated payload is not 
+            // mistaken for a non-truncated payload, we're good.
+            flush(xwriter);
+            return swriter.toString();
+        } finally {
+            close(xwriter);
+            close(xreader);
+        } 
         return swriter.toString();
     }
+    
+    private void flush(XMLStreamWriter xwriter) {
+        try {
+            xwriter.flush();
+        } catch (XMLStreamException xse2) {
+            //ignore
+        }
+    }
+    
+    private void close(XMLStreamWriter xwriter) {
+        try {
+            xwriter.close();
+        } catch (XMLStreamException xse2) {
+            //ignore
+        }
+    }
+
+    private void close(XMLStreamReader xreader) {
+        try {
+            xreader.close();
+        } catch (XMLStreamException xse2) {
+            //ignore
+        }
+    }
+
+    private int estimatePrettySize(String payload) {
+        return payload.length() * 2;
+    }
 
     public void setNext(LogEventSender next) {
         this.next = next;
     }
-
+    
     public void setPrettyLogging(boolean prettyLogging) {
         this.prettyLogging = prettyLogging;
     }
 
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cxf/blob/3bbfc22e/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TestPrettyLoggingFilter.java
----------------------------------------------------------------------
diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TestPrettyLoggingFilter.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TestPrettyLoggingFilter.java
new file mode 100644
index 0000000..9cc6179
--- /dev/null
+++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TestPrettyLoggingFilter.java
@@ -0,0 +1,90 @@
+/**
+ * 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.cxf.ext.logging;
+
+import org.apache.cxf.ext.logging.event.LogEvent;
+import org.apache.cxf.ext.logging.event.LogEventSender;
+import org.apache.cxf.ext.logging.event.PrettyLoggingFilter;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * 
+ * Test {@linkplain PrettyLoggingFilter}} with well-formed and non-well-formed XML payloads.
+ * 
+ */
+
+public class TestPrettyLoggingFilter {
+
+    @Test
+    public void testWellformedXMLMessage() {
+        String message = "<parent><child>text</child></parent>";
+        String expected = "<parent>\n  <child>text</child>\n</parent>\n";
+        filter(message, expected, false);
+    }
+
+    @Test
+    public void testInvalidXMLMessageUnexpectedEndTag() {
+        String message = "<parentA><child>text</child></parentB>";
+        filter(message, message, false);
+    }
+    
+    @Test
+    public void testInvalidXMLMessageMissingEndTag() {
+        String message = "<parentA><child>text</child>";
+        filter(message, message, false);
+    }
+
+    @Test
+    public void testInvalidXMLMessageGarbageStartTag() {
+        String message = "<a b c><child>text</child>";
+        filter(message, message, false);
+    }
+    
+    /**
+     * In case of a truncated message we do not want the pretty print to auto close the tags 
+     * giving a false impression of how to message looks like.
+     */
+    @Test
+    public void testInvalidButTruncatedXMLMessageWithMissingEndTag() {
+        String message = "<parent><child>text</child>";
+        String expected = "<parent>\n  <child>text</child>";
+        filter(message, expected, true);
+    }
+
+    private void filter(String payload, String expected, boolean truncated) {
+        LogEvent logEvent  = new LogEvent();
+        logEvent.setPayload(payload);
+        logEvent.setContentType("text/xml");
+        logEvent.setTruncated(truncated);
+        
+        LogEventSender dummy = new LogEventSender() {
+            public void send(LogEvent event) {
+            }
+        };
+        
+        PrettyLoggingFilter prettyFilter = new PrettyLoggingFilter(dummy);
+        prettyFilter.setPrettyLogging(true);
+        prettyFilter.send(logEvent);
+        
+        assertEquals(expected, logEvent.getPayload());
+    }
+    
+}
\ No newline at end of file