blob: cb16a0d67a93e1a2f3df04032b18f33c5ebf2773 [file] [log] [blame]
/*
* Copyright 2004,2005 The Apache Software Foundation.
* Copyright 2006 International Business Machines Corp.
*
* 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.apache.axis2.jaxws;
import java.lang.reflect.InvocationTargetException;
import javax.xml.ws.ProtocolException;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.http.HTTPException;
import javax.xml.ws.soap.SOAPFaultException;
import org.apache.axis2.AxisFault;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.message.MessageException;
import org.apache.axis2.jaxws.message.MessageInternalException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* ExceptionFactory is used to create exceptions within the JAX-WS implementation.
* There are several reasons for using a factory to create exceptions.
* 1. We can intercept all exception creation and add the appropriate logging/serviceability.
* 2. Exceptions are chained. ExceptionFactory can lengthen or reduce the cause chains as
* necessary to support the JAX-WS programming model.
* 3. Prevents construction of the same exception. Uses similar principles as AxisFault.makeException.
*
* Example Usage:
* // Example usage
*
* public fooMethod() throws WebServiceException {
* try{
* ...
* }
* catch(Exception e){
* throw ExceptionFactory.makeWebServiceException(e);
* }
* }
*
*
*/
public class ExceptionFactory {
protected static Log log =
LogFactory.getLog(ExceptionFactory.class.getName());
/**
* Private Constructor
* All methods are static. The private constructor prevents instantiation.
*/
private ExceptionFactory() {
}
/**
* Create a WebServiceException using the information from a given Throwable instance
* and message
* @param message
* @param throwable
* @return WebServiceException
*/
public static WebServiceException makeWebServiceException(String message, Throwable throwable) {
try {
// See if there is already a WebServiceException (Note that the returned exception could be a ProtocolException or
// other kind of exception)
WebServiceException e = (WebServiceException) findException(throwable, WebServiceException.class);
if (e == null) {
e = createWebServiceException(message, throwable);
}
return e;
} catch (RuntimeException re) {
// TODO
// This is not a good situation, an exception occurred while building the exception.
// This should never occur! For now log the problem and rethrow...we may revisit this later
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("exceptionDuringExceptionFlow"), re);
}
throw re;
}
}
/**
* Create a ProtocolException using the information from a Throwable and message
* @param message
* @param throwable
* @return ProtocolException
*/
public static ProtocolException makeProtocolException(String message, Throwable throwable) {
try {
// See if there is already a ProtocolException
ProtocolException e = (ProtocolException) findException(throwable, ProtocolException.class);
if (e == null) {
e = createProtocolException(message, throwable);
}
return e;
} catch (RuntimeException re) {
// TODO
// This is not a good situation, an exception occurred while building the exception.
// This should never occur! For now log the problem and rethrow...we may revisit this later
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("exceptionDuringExceptionFlow"), re);
}
throw re;
}
}
/**
* Create a MessageException using the information from a Throwable and message
* @param message
* @param throwable
* @return MessageException
*/
public static MessageException makeMessageException(String message, Throwable throwable) {
try {
// See if there is already a MessgeException
MessageException e = (MessageException) findException(throwable, MessageException.class);
if (e == null) {
e = createMessageException(message, throwable);
}
return e;
} catch (RuntimeException re) {
// TODO
// This is not a good situation, an exception occurred while building the exception.
// This should never occur! For now log the problem and rethrow...we may revisit this later
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("exceptionDuringExceptionFlow"), re);
}
throw re;
}
}
/**
* Create a MessageInternalException using the information from a Throwable and message
* @param message
* @param throwable
* @return MessageInternalException
*/
public static MessageInternalException makeMessageInternalException(String message, Throwable throwable) {
try {
// See if there is already a HTTPException
MessageInternalException e = (MessageInternalException) findException(throwable, MessageInternalException.class);
if (e == null) {
e = createMessageInternalException(message, throwable);
}
return e;
} catch (RuntimeException re) {
// TODO
// This is not a good situation, an exception occurred while building the exception.
// This should never occur! For now log the problem and rethrow...we may revisit this later
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("exceptionDuringExceptionFlow"), re);
}
throw re;
}
}
/**
* Make a WebServiceException with a given message
* @param message
* @return WebServiceException
*/
public static WebServiceException makeWebServiceException(String message) {
return makeWebServiceException(message, null);
}
/**
* Create a WebServiceException using the information from a given Throwable instance
* @param throwable
* @return WebServiceException
*/
public static WebServiceException makeWebServiceException(Throwable throwable){
return makeWebServiceException(null, throwable);
}
/**
* Create a MessageException using the information from a given Throwable instance
* @param throwable
* @return MessageException
*/
public static MessageException makeMessageException(Throwable throwable){
return makeMessageException(null, throwable);
}
/**
* Make a MessageException with a given message
* @param message
* @return MessageException
*/
public static MessageException makeMessageException(String message) {
return makeMessageException(message, null);
}
/**
* Create a WebServiceException
* @param message
* @param t Throwable
* @return WebServiceException
*/
private static WebServiceException createWebServiceException(String message, Throwable t) {
Throwable rootCause = null;
if (t != null) {
rootCause = getRootCause(t);
}
WebServiceException e = new WebServiceException(message, t);
if (log.isDebugEnabled()) {
log.debug("Create Exception:", e);
}
return e;
}
/**
* Create a ProtocolException
* @param message
* @param t Throwable
* @return ProtocolException
*/
private static ProtocolException createProtocolException(String message, Throwable t) {
Throwable rootCause = null;
if (t != null) {
rootCause = getRootCause(t);
}
ProtocolException e = new ProtocolException(message, t);
if (log.isDebugEnabled()) {
log.debug("create Exception:", t);
}
return e;
}
/**
* Create a MessageException
* @param message
* @param t Throwable
* @return MessageException
*/
private static MessageException createMessageException(String message, Throwable t) {
Throwable rootCause = null;
if (t != null) {
rootCause = getRootCause(t);
}
MessageException e = new MessageException(message, t);
if (log.isDebugEnabled()) {
log.debug("create Exception:", t);
}
return e;
}
/**
* Create a MessageInternalException
* @param message
* @param t Throwable
* @return MessageException
*/
private static MessageInternalException createMessageInternalException(String message, Throwable t) {
Throwable rootCause = null;
if (t != null) {
rootCause = getRootCause(t);
}
MessageInternalException e = new MessageInternalException(message, t);
if (log.isDebugEnabled()) {
log.debug("create Exception:", t);
}
return e;
}
/**
* Return the exception or nested cause that is assignable from the specified class
* @param t Throwable
* @param cls
* @return Exception or null
*/
private static Exception findException(Throwable t, Class cls) {
while(t != null) {
if (cls.isAssignableFrom(t.getClass())) {
return (Exception) t;
}
t = getCause(t);
}
return null;
}
/**
* Gets the Throwable cause of the Exception. Some exceptions
* store the cause in a different field, which is why this method
* should be used when walking the causes.
* @param t Throwable
* @return Throwable or null
*/
private static Throwable getCause(Throwable t) {
Throwable cause = null;
// Look for a specific cause for this kind of exception
if (t instanceof InvocationTargetException) {
cause = ((InvocationTargetException) t).getTargetException();
}
// If no specific cause, fall back to the general cause.
if (cause == null) {
cause = t.getCause();
}
return null;
}
/**
* This method searches the causes of the specified throwable
* until it finds one that is acceptable as a "root" cause.
*
* Example: If t is an AxisFault, the code traverses to the next cause.
*
* @param t Throwable
* @return Throwable root cause
*/
private static Throwable getRootCause(Throwable t) {
while (t != null) {
Throwable nextCause = null;
if (t instanceof InvocationTargetException ||
t instanceof AxisFault) {
// Skip over this cause
nextCause = getCause(t);
if (nextCause == null) {
return t;
}
t = nextCause;
} else {
// This is the root cause
return t;
}
}
return t;
}
}