/* * Copyright 2005-2014 the original author or authors. * * Licensed 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.springframework.ws.server.endpoint; import java.io.StringWriter; import javax.xml.transform.OutputKeys; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.stream.StreamResult; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.ws.WebServiceMessage; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; import org.springframework.xml.transform.TransformerObjectSupport; /** * Abstract base class for {@code EndpointInterceptor} instances that log a part of a * {@code WebServiceMessage}. By default, both request and response messages are logged, but this behaviour can be * changed using the {@code logRequest} and {@code logResponse} properties. * * @author Arjen Poutsma * @since 1.0.0 */ public abstract class AbstractLoggingInterceptor extends TransformerObjectSupport implements EndpointInterceptor { /** * The default {@code Log} instance used to write trace messages. This instance is mapped to the implementing * {@code Class}. */ protected transient Log logger = LogFactory.getLog(getClass()); private boolean logRequest = true; private boolean logResponse = true; /** Indicates whether the request should be logged. Default is {@code true}. */ public final void setLogRequest(boolean logRequest) { this.logRequest = logRequest; } /** Indicates whether the response should be logged. Default is {@code true}. */ public final void setLogResponse(boolean logResponse) { this.logResponse = logResponse; } /** * Set the name of the logger to use. The name will be passed to the underlying logger implementation through * Commons Logging, getting interpreted as log category according to the logger's configuration. * * <p>This can be specified to not log into the category of a class but rather into a specific named category. * * @see org.apache.commons.logging.LogFactory#getLog(String) * @see org.apache.log4j.Logger#getLogger(String) * @see java.util.logging.Logger#getLogger(String) */ public void setLoggerName(String loggerName) { this.logger = LogFactory.getLog(loggerName); } /** * Logs the request message payload. Logging only occurs if {@code logRequest} is set to {@code true}, * which is the default. * * @param messageContext the message context * @return {@code true} * @throws TransformerException when the payload cannot be transformed to a string */ @Override public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws TransformerException { if (logRequest && isLogEnabled()) { logMessageSource("Request: ", getSource(messageContext.getRequest())); } return true; } /** * Logs the response message payload. Logging only occurs if {@code logResponse} is set to {@code true}, * which is the default. * * @param messageContext the message context * @return {@code true} * @throws TransformerException when the payload cannot be transformed to a string */ @Override public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { if (logResponse && isLogEnabled()) { logMessageSource("Response: ", getSource(messageContext.getResponse())); } return true; } /** Does nothing by default. Faults are not logged. */ @Override public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { return true; } /** Does nothing by default*/ @Override public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) { } /** * Determine whether the {@link #logger} field is enabled. * * <p>Default is {@code true} when the "debug" level is enabled. Subclasses can override this to change the level * under which logging occurs. */ protected boolean isLogEnabled() { return logger.isDebugEnabled(); } private Transformer createNonIndentingTransformer() throws TransformerConfigurationException { Transformer transformer = createTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "no"); return transformer; } /** * Logs the given {@link Source source} to the {@link #logger}, using the message as a prefix. * * <p>By default, this message creates a string representation of the given source, and delegates to {@link * #logMessage(String)}. * * @param logMessage the log message * @param source the source to be logged * @throws TransformerException in case of errors */ protected void logMessageSource(String logMessage, Source source) throws TransformerException { if (source != null) { Transformer transformer = createNonIndentingTransformer(); StringWriter writer = new StringWriter(); transformer.transform(source, new StreamResult(writer)); String message = logMessage + writer.toString(); logMessage(message); } } /** * Logs the given string message. * * <p>By default, this method uses a "debug" level of logging. Subclasses can override this method to change the level * of logging used by the logger. * * @param message the message */ protected void logMessage(String message) { logger.debug(message); } /** * Abstract template method that returns the {@code Source} for the given {@code WebServiceMessage}. * * @param message the message * @return the source of the message */ protected abstract Source getSource(WebServiceMessage message); }