asfgit closed pull request #340: [CXF-7562] correction for truncated flag URL: https://github.com/apache/cxf/pull/340
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): 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 8ba700eb135..f939b5efe15 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 @@ -43,11 +43,25 @@ */ @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 +69,11 @@ public LoggingInInterceptor(PrintWriter writer) { 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 +108,7 @@ private void addContent(Message message, final LogEvent event) { } 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 +130,19 @@ private void handleWriter(final LogEvent event, CachedWriter writer) throws IOEx 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 93a7a0bf9d2..9a8d71f57bc 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 LoggingOutInterceptor() { this(new Slf4jVerboseEventSender()); } - + public LoggingOutInterceptor(PrintWriter writer) { this(new PrintWriterEventSender(writer)); } @@ -82,12 +82,22 @@ private OutputStream createCachingOut(Message message, final OutputStream os, Ca 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 void close() throws IOException { 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 void close() throws IOException { } 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 void onClose(CachedOutputStream cos) { 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 00000000000..8f723be1693 --- /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 00000000000..e83e110ca1a --- /dev/null +++ b/rt/features/logging/src/test/java/org/apache/cxf/ext/logging/TruncatedTest.java @@ -0,0 +1,148 @@ +/** + * 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()); + } + + + +} ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services