| /** |
| * 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.interceptor; |
| |
| import java.io.FilterWriter; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import org.apache.cxf.common.injection.NoJSR250Annotations; |
| import org.apache.cxf.common.logging.LogUtils; |
| import org.apache.cxf.io.CacheAndWriteOutputStream; |
| import org.apache.cxf.io.CachedOutputStream; |
| import org.apache.cxf.io.CachedOutputStreamCallback; |
| import org.apache.cxf.message.Message; |
| import org.apache.cxf.phase.Phase; |
| |
| /** |
| * |
| */ |
| @NoJSR250Annotations |
| public class LoggingOutInterceptor extends AbstractLoggingInterceptor { |
| private static final Logger LOG = LogUtils.getLogger(LoggingOutInterceptor.class); |
| private static final String LOG_SETUP = LoggingOutInterceptor.class.getName() + ".log-setup"; |
| |
| public LoggingOutInterceptor(String phase) { |
| super(phase); |
| addBefore(StaxOutInterceptor.class.getName()); |
| } |
| public LoggingOutInterceptor() { |
| this(Phase.PRE_STREAM); |
| } |
| public LoggingOutInterceptor(int lim) { |
| this(); |
| limit = lim; |
| } |
| |
| public LoggingOutInterceptor(PrintWriter w) { |
| this(); |
| this.writer = w; |
| } |
| |
| |
| public void handleMessage(Message message) throws Fault { |
| final OutputStream os = message.getContent(OutputStream.class); |
| final Writer iowriter = message.getContent(Writer.class); |
| if (os == null && iowriter == null) { |
| return; |
| } |
| Logger logger = getMessageLogger(message); |
| if (logger.isLoggable(Level.INFO) || writer != null) { |
| // Write the output while caching it for the log message |
| boolean hasLogged = message.containsKey(LOG_SETUP); |
| if (!hasLogged) { |
| message.put(LOG_SETUP, Boolean.TRUE); |
| if (os != null) { |
| final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os); |
| if (threshold > 0) { |
| newOut.setThreshold(threshold); |
| } |
| if (limit > 0) { |
| newOut.setCacheLimit(limit); |
| } |
| message.setContent(OutputStream.class, newOut); |
| newOut.registerCallback(new LoggingCallback(logger, message, os)); |
| } else { |
| message.setContent(Writer.class, new LogWriter(logger, message, iowriter)); |
| } |
| } |
| } |
| } |
| |
| private LoggingMessage setupBuffer(Message message) { |
| String id = (String)message.getExchange().get(LoggingMessage.ID_KEY); |
| if (id == null) { |
| id = LoggingMessage.nextId(); |
| message.getExchange().put(LoggingMessage.ID_KEY, id); |
| } |
| final LoggingMessage buffer |
| = new LoggingMessage("Outbound Message\n---------------------------", |
| id); |
| |
| Integer responseCode = (Integer)message.get(Message.RESPONSE_CODE); |
| if (responseCode != null) { |
| buffer.getResponseCode().append(responseCode); |
| } |
| |
| String encoding = (String)message.get(Message.ENCODING); |
| if (encoding != null) { |
| buffer.getEncoding().append(encoding); |
| } |
| String httpMethod = (String)message.get(Message.HTTP_REQUEST_METHOD); |
| if (httpMethod != null) { |
| buffer.getHttpMethod().append(httpMethod); |
| } |
| String address = (String)message.get(Message.ENDPOINT_ADDRESS); |
| if (address != null) { |
| buffer.getAddress().append(address); |
| String uri = (String)message.get(Message.REQUEST_URI); |
| if (uri != null && !address.startsWith(uri)) { |
| if (!address.endsWith("/") && !uri.startsWith("/")) { |
| buffer.getAddress().append("/"); |
| } |
| buffer.getAddress().append(uri); |
| } |
| } |
| String ct = (String)message.get(Message.CONTENT_TYPE); |
| if (ct != null) { |
| buffer.getContentType().append(ct); |
| } |
| Object headers = message.get(Message.PROTOCOL_HEADERS); |
| if (headers != null) { |
| buffer.getHeader().append(headers); |
| } |
| return buffer; |
| } |
| |
| private class LogWriter extends FilterWriter { |
| StringWriter out2; |
| int count; |
| Logger logger; //NOPMD |
| Message message; |
| final int lim; |
| |
| LogWriter(Logger logger, Message message, Writer writer) { |
| super(writer); |
| this.logger = logger; |
| this.message = message; |
| if (!(writer instanceof StringWriter)) { |
| out2 = new StringWriter(); |
| } |
| lim = limit == -1 ? Integer.MAX_VALUE : limit; |
| } |
| public void write(int c) throws IOException { |
| super.write(c); |
| if (out2 != null && count < lim) { |
| out2.write(c); |
| } |
| count++; |
| } |
| public void write(char[] cbuf, int off, int len) throws IOException { |
| super.write(cbuf, off, len); |
| if (out2 != null && count < lim) { |
| out2.write(cbuf, off, len); |
| } |
| count += len; |
| } |
| public void write(String str, int off, int len) throws IOException { |
| super.write(str, off, len); |
| if (out2 != null && count < lim) { |
| out2.write(str, off, len); |
| } |
| count += len; |
| } |
| public void close() throws IOException { |
| LoggingMessage buffer = setupBuffer(message); |
| if (count >= lim) { |
| buffer.getMessage().append("(message truncated to " + lim + " bytes)\n"); |
| } |
| StringWriter w2 = out2; |
| if (w2 == null) { |
| w2 = (StringWriter)out; |
| } |
| String ct = (String)message.get(Message.CONTENT_TYPE); |
| try { |
| writePayload(buffer.getPayload(), w2, ct); |
| } catch (Exception ex) { |
| //ignore |
| } |
| log(logger, formatLoggingMessage(buffer)); |
| message.setContent(Writer.class, out); |
| super.close(); |
| } |
| } |
| |
| protected String formatLoggingMessage(LoggingMessage buffer) { |
| return buffer.toString(); |
| } |
| |
| class LoggingCallback implements CachedOutputStreamCallback { |
| |
| private final Message message; |
| private final OutputStream origStream; |
| private final Logger logger; //NOPMD |
| private final int lim; |
| |
| LoggingCallback(final Logger logger, final Message msg, final OutputStream os) { |
| this.logger = logger; |
| this.message = msg; |
| this.origStream = os; |
| this.lim = limit == -1 ? Integer.MAX_VALUE : limit; |
| } |
| |
| public void onFlush(CachedOutputStream cos) { |
| |
| } |
| |
| public void onClose(CachedOutputStream cos) { |
| LoggingMessage buffer = setupBuffer(message); |
| |
| String ct = (String)message.get(Message.CONTENT_TYPE); |
| if (!isShowBinaryContent() && isBinaryContent(ct)) { |
| buffer.getMessage().append(BINARY_CONTENT_MESSAGE).append('\n'); |
| log(logger, formatLoggingMessage(buffer)); |
| return; |
| } |
| if (!isShowMultipartContent() && isMultipartContent(ct)) { |
| buffer.getMessage().append(MULTIPART_CONTENT_MESSAGE).append('\n'); |
| log(logger, formatLoggingMessage(buffer)); |
| return; |
| } |
| |
| if (cos.getTempFile() == null) { |
| //buffer.append("Outbound Message:\n"); |
| if (cos.size() >= lim) { |
| buffer.getMessage().append("(message truncated to " + lim + " bytes)\n"); |
| } |
| } else { |
| buffer.getMessage().append("Outbound Message (saved to tmp file):\n"); |
| buffer.getMessage().append("Filename: " + cos.getTempFile().getAbsolutePath() + "\n"); |
| if (cos.size() >= lim) { |
| buffer.getMessage().append("(message truncated to " + lim + " bytes)\n"); |
| } |
| } |
| try { |
| String encoding = (String)message.get(Message.ENCODING); |
| writePayload(buffer.getPayload(), cos, encoding, ct); |
| } catch (Exception ex) { |
| //ignore |
| } |
| |
| log(logger, formatLoggingMessage(buffer)); |
| try { |
| //empty out the cache |
| cos.lockOutputStream(); |
| cos.resetOut(null, false); |
| } catch (Exception ex) { |
| //ignore |
| } |
| message.setContent(OutputStream.class, origStream); |
| } |
| } |
| |
| @Override |
| protected Logger getLogger() { |
| return LOG; |
| |
| } |
| |
| } |