You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by de...@apache.org on 2018/01/21 12:14:19 UTC

[cxf] branch master updated: [CXF-7562] ext.logging: truncated flag not set closes #340

This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 62ba50c  [CXF-7562] ext.logging: truncated flag not set closes #340
62ba50c is described below

commit 62ba50cc2cf934865d4646785137167cd44c29ff
Author: Franz Forsthofer <fr...@sap.com>
AuthorDate: Sun Jan 21 13:13:02 2018 +0100

    [CXF-7562] ext.logging: truncated flag not set closes #340
---
 .../cxf/ext/logging/LoggingInInterceptor.java      |  39 +++++-
 .../cxf/ext/logging/LoggingOutInterceptor.java     |  32 +++--
 .../apache/cxf/ext/logging/LogEventSenderMock.java |  37 +++++
 .../org/apache/cxf/ext/logging/TruncatedTest.java  | 149 +++++++++++++++++++++
 4 files changed, 242 insertions(+), 15 deletions(-)

diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
index 8ba700e..8d06c7d 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
@@ -35,6 +35,7 @@ import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.io.CachedWriter;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
 import org.apache.cxf.phase.PhaseInterceptor;
 
@@ -43,11 +44,25 @@ import org.apache.cxf.phase.PhaseInterceptor;
  */
 @NoJSR250Annotations
 public class LoggingInInterceptor extends AbstractLoggingInterceptor {
-    
+    class LoggingInFaultInterceptor extends AbstractPhaseInterceptor<Message> {
+        LoggingInFaultInterceptor() {
+            super(Phase.RECEIVE);
+        }
+
+        @Override
+        public void handleMessage(Message message) throws Fault {
+        }
+
+        @Override
+        public void handleFault(Message message) throws Fault {
+            LoggingInInterceptor.this.handleMessage(message);
+        }
+    }
+
     public LoggingInInterceptor() {
         this(new Slf4jVerboseEventSender());
     }
-    
+
     public LoggingInInterceptor(PrintWriter writer) {
         this(new PrintWriterEventSender(writer));
     }
@@ -55,11 +70,11 @@ public class LoggingInInterceptor extends AbstractLoggingInterceptor {
     public LoggingInInterceptor(LogEventSender sender) {
         super(Phase.PRE_INVOKE, sender);
     }
-    
 
     public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
         Collection<PhaseInterceptor<? extends Message>> ret = new ArrayList<>();
-        ret.add(new WireTapIn(limit, threshold));
+        ret.add(new WireTapIn(getWireTapLimit(), threshold));
+        ret.add(new LoggingInFaultInterceptor());
         return ret;
     }
 
@@ -94,7 +109,7 @@ public class LoggingInInterceptor extends AbstractLoggingInterceptor {
     }
 
     private void handleOutputStream(final LogEvent event, Message message, CachedOutputStream cos) throws IOException {
-        String encoding = (String)message.get(Message.ENCODING);
+        String encoding = (String) message.get(Message.ENCODING);
         if (StringUtils.isEmpty(encoding)) {
             encoding = StandardCharsets.UTF_8.name();
         }
@@ -116,5 +131,19 @@ public class LoggingInInterceptor extends AbstractLoggingInterceptor {
         event.setFullContentFile(writer.getTempFile());
     }
 
+    int getWireTapLimit() {
+        if (limit == -1) {
+            return -1;
+        } else if (limit == Integer.MAX_VALUE) {
+            return limit;
+        } else {
+            // add limit +1 as limit for the wiretab in order to read one byte more, so that truncated
+            // is correctly calculated in LogginInIntecepteor! 
+            // See code line :  boolean isTruncated = cos.size() > limit && limit != -1; 
+            // cos is here the outputstream read by the wiretab which will return for cos.size() the 
+            // limit in the truncated case!
+            return limit + 1;
+        }
+    }
 
 }
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
index 93a7a0b..9a8d71f 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
@@ -49,7 +49,7 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
     public LoggingOutInterceptor() {
         this(new Slf4jVerboseEventSender());
     }
-    
+
     public LoggingOutInterceptor(PrintWriter writer) {
         this(new PrintWriterEventSender(writer));
     }
@@ -82,12 +82,22 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
             newOut.setThreshold(threshold);
         }
         if (limit > 0) {
-            newOut.setCacheLimit(limit);
+            // make the limit for the cache greater than the limit for the truncated payload in the log event, 
+            // this is necessary for finding out that the payload was truncated 
+            //(see boolean isTruncated = cos.size() > limit && limit != -1;)  in method copyPayload
+            newOut.setCacheLimit(getCacheLimit());
         }
         newOut.registerCallback(callback);
         return newOut;
     }
 
+    private int getCacheLimit() {
+        if (limit == Integer.MAX_VALUE) {
+            return limit;
+        }
+        return limit + 1;
+    }
+
     private class LogEventSendingWriter extends FilterWriter {
         StringWriter out2;
         int count;
@@ -133,7 +143,7 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
             final LogEvent event = new DefaultLogEventMapper().map(message);
             StringWriter w2 = out2;
             if (w2 == null) {
-                w2 = (StringWriter)out;
+                w2 = (StringWriter) out;
             }
 
             String payload = shouldLogContent(event) ? getPayload(event, w2) : CONTENT_SUPPRESSED;
@@ -144,23 +154,23 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
         }
 
         private String getPayload(final LogEvent event, StringWriter w2) {
-            String ct = (String)message.get(Message.CONTENT_TYPE);
             StringBuilder payload = new StringBuilder();
             try {
-                writePayload(payload, w2, ct);
+                writePayload(payload, w2, event);
             } catch (Exception ex) {
                 // ignore
             }
             return payload.toString();
         }
 
-        protected void writePayload(StringBuilder builder, StringWriter stringWriter, String contentType)
-            throws Exception {
+        protected void writePayload(StringBuilder builder, StringWriter stringWriter, LogEvent event) throws Exception {
             StringBuffer buffer = stringWriter.getBuffer();
             if (buffer.length() > lim) {
                 builder.append(buffer.subSequence(0, lim));
+                event.setTruncated(true);
             } else {
                 builder.append(buffer);
+                event.setTruncated(false);
             }
         }
     }
@@ -204,17 +214,19 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
 
         private void copyPayload(CachedOutputStream cos, final LogEvent event) {
             try {
-                String encoding = (String)message.get(Message.ENCODING);
+                String encoding = (String) message.get(Message.ENCODING);
                 StringBuilder payload = new StringBuilder();
                 writePayload(payload, cos, encoding, event.getContentType());
                 event.setPayload(payload.toString());
+                boolean isTruncated = cos.size() > limit && limit != -1;
+                event.setTruncated(isTruncated);
             } catch (Exception ex) {
                 // ignore
             }
         }
 
-        protected void writePayload(StringBuilder builder, CachedOutputStream cos, String encoding,
-                                    String contentType) throws Exception {
+        protected void writePayload(StringBuilder builder, CachedOutputStream cos, String encoding, String contentType)
+                throws Exception {
             if (StringUtils.isEmpty(encoding)) {
                 cos.writeCacheTo(builder, lim);
             } else {
diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java
new file mode 100644
index 0000000..8f723be
--- /dev/null
+++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/LogEventSenderMock.java
@@ -0,0 +1,37 @@
+/**
+ * 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;
+
+public class LogEventSenderMock implements LogEventSender {
+
+    private LogEvent logEvent;
+
+    @Override
+    public void send(LogEvent event) {
+        logEvent = event;
+    }
+
+    public LogEvent getLogEvent() {
+        return logEvent;
+    }
+
+}
diff --git a/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TruncatedTest.java b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TruncatedTest.java
new file mode 100644
index 0000000..a7567fc
--- /dev/null
+++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TruncatedTest.java
@@ -0,0 +1,149 @@
+/**
+ * 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+
+import org.apache.cxf.ext.logging.event.LogEvent;
+import org.apache.cxf.message.Exchange;
+import org.apache.cxf.message.ExchangeImpl;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+import org.apache.cxf.phase.PhaseInterceptor;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+
+
+public class TruncatedTest {
+
+    @Test
+    public void truncatedOutboundInterceptorOutputStream() throws IOException {
+
+        Message message = new MessageImpl();
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        message.setContent(OutputStream.class, outputStream);
+        Exchange exchange = new ExchangeImpl();
+        message.setExchange(exchange);
+        LogEventSenderMock logEventSender = new LogEventSenderMock();
+        LoggingOutInterceptor interceptor = new LoggingOutInterceptor(logEventSender);
+        interceptor.setLimit(1); // set limit to 1 byte in order to get a truncated message!
+        interceptor.handleMessage(message);
+        byte[] payload = "TestMessage".getBytes(StandardCharsets.UTF_8);
+
+        OutputStream out = message.getContent(OutputStream.class);
+        out.write(payload);
+        out.close();
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals("T", event.getPayload()); // only the first byte is read!
+        assertTrue(event.isTruncated());
+    }
+
+    @Test
+    public void truncatedOutboundInterceptorWriter() throws IOException {
+
+        Message message = new MessageImpl();
+        StringWriter stringWriter = new StringWriter();
+        message.setContent(Writer.class, stringWriter);
+        Exchange exchange = new ExchangeImpl();
+        message.setExchange(exchange);
+        LogEventSenderMock logEventSender = new LogEventSenderMock();
+        LoggingOutInterceptor interceptor = new LoggingOutInterceptor(logEventSender);
+        interceptor.setLimit(1); // set limit to 1 byte in order to get a truncated message!
+        interceptor.handleMessage(message);
+
+        Writer out = message.getContent(Writer.class);
+        out.write("TestMessage");
+        out.close();
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals("T", event.getPayload()); // only the first byte is read!
+        assertTrue(event.isTruncated());
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void truncatedInboundInterceptorInputStream() throws IOException {
+
+        Message message = new MessageImpl();
+        ByteArrayInputStream inputStream = new ByteArrayInputStream("TestMessage".getBytes(StandardCharsets.UTF_8));
+        message.setContent(InputStream.class, inputStream);
+        Exchange exchange = new ExchangeImpl();
+        message.setExchange(exchange);
+        LogEventSenderMock logEventSender = new LogEventSenderMock();
+        LoggingInInterceptor interceptor = new LoggingInInterceptor(logEventSender);
+        interceptor.setLimit(1); // set limit to 1 byte in order to get a truncated message!
+
+        Collection<PhaseInterceptor<? extends Message>> interceptors = interceptor.getAdditionalInterceptors();
+        for (PhaseInterceptor intercept : interceptors) {
+            intercept.handleMessage(message);
+        }
+
+        interceptor.handleMessage(message);
+
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals("T", event.getPayload()); // only the first byte is read!
+        assertTrue(event.isTruncated());
+    }
+    
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void truncatedInboundInterceptorReader() throws IOException {
+
+        Message message = new MessageImpl();
+        StringReader stringReader = new StringReader("TestMessage");
+        message.setContent(Reader.class, stringReader);
+        Exchange exchange = new ExchangeImpl();
+        message.setExchange(exchange);
+        LogEventSenderMock logEventSender = new LogEventSenderMock();
+        LoggingInInterceptor interceptor = new LoggingInInterceptor(logEventSender);
+        interceptor.setLimit(1); // set limit to 1 byte in order to get a truncated message!
+
+        Collection<PhaseInterceptor<? extends Message>> interceptors = interceptor.getAdditionalInterceptors();
+        for (PhaseInterceptor intercept : interceptors) {
+            intercept.handleMessage(message);
+        }
+
+        interceptor.handleMessage(message);
+
+        LogEvent event = logEventSender.getLogEvent();
+        assertNotNull(event);
+        assertEquals("T", event.getPayload()); // only the first byte is read!
+        assertTrue(event.isTruncated());
+    }
+    
+
+
+}

-- 
To stop receiving notification emails like this one, please contact
['"commits@cxf.apache.org" <co...@cxf.apache.org>'].