1 /* 2 * Copyright 2006 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package org.springframework.ws.server.endpoint; 18 19 import java.io.StringWriter; 20 import javax.xml.transform.OutputKeys; 21 import javax.xml.transform.Source; 22 import javax.xml.transform.Transformer; 23 import javax.xml.transform.TransformerConfigurationException; 24 import javax.xml.transform.TransformerException; 25 import javax.xml.transform.stream.StreamResult; 26 27 import org.apache.commons.logging.Log; 28 import org.apache.commons.logging.LogFactory; 29 30 import org.springframework.ws.WebServiceMessage; 31 import org.springframework.ws.context.MessageContext; 32 import org.springframework.ws.server.EndpointInterceptor; 33 import org.springframework.xml.transform.TransformerObjectSupport; 34 35 /** 36 * Abstract base class for <code>EndpointInterceptor</code> instances that log a part of a 37 * <code>WebServiceMessage</code>. By default, both request and response messages are logged, but this behaviour can be 38 * changed using the <code>logRequest</code> and <code>logResponse</code> properties. 39 * 40 * @author Arjen Poutsma 41 * @since 1.0.0 42 */ 43 public abstract class AbstractLoggingInterceptor extends TransformerObjectSupport implements EndpointInterceptor { 44 45 /** 46 * The default <code>Log</code> instance used to write trace messages. This instance is mapped to the implementing 47 * <code>Class</code>. 48 */ 49 protected transient Log logger = LogFactory.getLog(getClass()); 50 51 private boolean logRequest = true; 52 53 private boolean logResponse = true; 54 55 /** Indicates whether the request should be logged. Default is <code>true</code>. */ 56 public final void setLogRequest(boolean logRequest) { 57 this.logRequest = logRequest; 58 } 59 60 /** Indicates whether the response should be logged. Default is <code>true</code>. */ 61 public final void setLogResponse(boolean logResponse) { 62 this.logResponse = logResponse; 63 } 64 65 /** 66 * Set the name of the logger to use. The name will be passed to the underlying logger implementation through 67 * Commons Logging, getting interpreted as log category according to the logger's configuration. 68 * <p/> 69 * This can be specified to not log into the category of a class but rather into a specific named category. 70 * 71 * @see org.apache.commons.logging.LogFactory#getLog(String) 72 * @see org.apache.log4j.Logger#getLogger(String) 73 * @see java.util.logging.Logger#getLogger(String) 74 */ 75 public void setLoggerName(String loggerName) { 76 this.logger = LogFactory.getLog(loggerName); 77 } 78 79 /** 80 * Logs the request message payload. Logging only ocurs if <code>logRequest</code> is set to <code>true</code>, 81 * which is the default. 82 * 83 * @param messageContext the message context 84 * @return <code>true</code> 85 * @throws TransformerException when the payload cannot be transformed to a string 86 */ 87 public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws TransformerException { 88 if (logRequest && isLogEnabled()) { 89 logMessageSource("Request: ", getSource(messageContext.getRequest())); 90 } 91 return true; 92 } 93 94 /** 95 * Logs the response message payload. Logging only ocurs if <code>logResponse</code> is set to <code>true</code>, 96 * which is the default. 97 * 98 * @param messageContext the message context 99 * @return <code>true</code> 100 * @throws TransformerException when the payload cannot be transformed to a string 101 */ 102 public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception { 103 if (logResponse && isLogEnabled()) { 104 logMessageSource("Response: ", getSource(messageContext.getResponse())); 105 } 106 return true; 107 } 108 109 /** Does nothing by default. Faults are not logged. */ 110 public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { 111 return true; 112 } 113 114 /** 115 * Determine whether the {@link #logger} field is enabled. 116 * <p/> 117 * Default is <code>true</code> when the "debug" level is enabled. Subclasses can override this to change the level 118 * under which logging occurs. 119 */ 120 protected boolean isLogEnabled() { 121 return logger.isDebugEnabled(); 122 } 123 124 private Transformer createNonIndentingTransformer() throws TransformerConfigurationException { 125 Transformer transformer = createTransformer(); 126 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 127 transformer.setOutputProperty(OutputKeys.INDENT, "no"); 128 return transformer; 129 } 130 131 /** 132 * Logs the given {@link Source source} to the {@link #logger}, using the message as a prefix. 133 * <p/> 134 * By default, this message creates a string representation of the given source, and delegates to {@link 135 * #logMessage(String)}. 136 * 137 * @param logMessage the log message 138 * @param source the source to be logged 139 * @throws TransformerException in case of errors 140 */ 141 protected void logMessageSource(String logMessage, Source source) throws TransformerException { 142 if (source != null) { 143 Transformer transformer = createNonIndentingTransformer(); 144 StringWriter writer = new StringWriter(); 145 transformer.transform(source, new StreamResult(writer)); 146 String message = logMessage + writer.toString(); 147 logMessage(message); 148 } 149 } 150 151 /** 152 * Logs the given string message. 153 * <p/> 154 * By default, this method uses a "debug" level of logging. Subclasses can override this method to change the level 155 * of loging used by the logger. 156 * 157 * @param message the message 158 */ 159 protected void logMessage(String message) { 160 logger.debug(message); 161 } 162 163 /** 164 * Abstract template method that returns the <code>Source</code> for the given <code>WebServiceMessage</code>. 165 * 166 * @param message the message 167 * @return the source of the message 168 */ 169 protected abstract Source getSource(WebServiceMessage message); 170 }