001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.synapse;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024:
025: import java.util.Stack;
026: import java.io.StringWriter;
027: import java.io.Writer;
028: import java.io.PrintWriter;
029:
030: /**
031: * This is an abstract class that handles an unexpected error during Synapse mediation, but looking
032: * at the stack of registered FaultHanders and invoking on them as appropriate. Sequences and
033: * Endpoints would be Synapse entities that handles faults. If such an entity is unable to handle
034: * an error condition, then a SynapseException should be thrown, which triggers this fault
035: * handling logic.
036: */
037: public abstract class FaultHandler {
038:
039: private static final Log log = LogFactory
040: .getLog(FaultHandler.class);
041: private static final Log trace = LogFactory
042: .getLog(SynapseConstants.TRACE_LOGGER);
043:
044: public void handleFault(MessageContext synCtx) {
045:
046: boolean traceOn = synCtx.getTracingState() == SynapseConstants.TRACING_ON;
047: boolean traceOrDebugOn = traceOn || log.isDebugEnabled();
048:
049: if (traceOrDebugOn) {
050: traceOrDebugWarn(traceOn, "FaultHandler executing impl: "
051: + this .getClass().getName());
052: }
053:
054: try {
055: synCtx.getServiceLog().info(
056: "FaultHandler executing impl: "
057: + this .getClass().getName());
058: onFault(synCtx);
059:
060: } catch (SynapseException e) {
061:
062: Stack faultStack = synCtx.getFaultStack();
063: if (faultStack != null && !faultStack.isEmpty()) {
064: ((FaultHandler) faultStack.pop()).handleFault(synCtx);
065: }
066: }
067: }
068:
069: /**
070: * Extract and set ERROR_MESSAGE and ERROR_DETAIL to the message context from the Exception
071: * @param synCtx the message context
072: * @param e the exception encountered
073: */
074: public void handleFault(MessageContext synCtx, Exception e) {
075:
076: boolean traceOn = synCtx.getTracingState() == SynapseConstants.TRACING_ON;
077: boolean traceOrDebugOn = traceOn || log.isDebugEnabled();
078:
079: synCtx.setProperty(SynapseConstants.ERROR_CODE, "00000");
080: // use only the first line as the message for multiline exception messages (Axis2 has these)
081: synCtx.setProperty(SynapseConstants.ERROR_MESSAGE, e
082: .getMessage().split("\n")[0]);
083:
084: synCtx.setProperty(SynapseConstants.ERROR_DETAIL,
085: getStackTrace(e));
086: synCtx.setProperty(SynapseConstants.ERROR_EXCEPTION, e);
087:
088: if (traceOrDebugOn) {
089: traceOrDebugWarn(
090: traceOn,
091: "Fault handler - setting ERROR_MESSAGE : "
092: + synCtx
093: .getProperty(SynapseConstants.ERROR_MESSAGE));
094: traceOrDebugWarn(
095: traceOn,
096: "Fault handler - setting ERROR_DETAIL : "
097: + synCtx
098: .getProperty(SynapseConstants.ERROR_DETAIL));
099: traceOrDebugWarn(
100: traceOn,
101: "Fault handler - setting ERROR_EXCEPTION : "
102: + synCtx
103: .getProperty(SynapseConstants.ERROR_EXCEPTION));
104: }
105:
106: synCtx
107: .getServiceLog()
108: .warn(
109: "Fault handler - setting ERROR_MESSAGE : "
110: + synCtx
111: .getProperty(SynapseConstants.ERROR_MESSAGE));
112:
113: try {
114: onFault(synCtx);
115:
116: } catch (SynapseException se) {
117:
118: Stack faultStack = synCtx.getFaultStack();
119: if (faultStack != null && !faultStack.isEmpty()) {
120: ((FaultHandler) faultStack.pop()).handleFault(synCtx,
121: se);
122: }
123: }
124: }
125:
126: /**
127: * This will be executed to handle any Exceptions occurred within the Synapse environment.
128: * @param synCtx SynapseMessageContext of which the fault occured message comprises
129: * @throws SynapseException in case there is a failure in the fault execution
130: */
131: public abstract void onFault(MessageContext synCtx);
132:
133: /**
134: * Get the stack trace into a String
135: * @param aThrowable
136: * @return the stack trace as a string
137: */
138: public static String getStackTrace(Throwable aThrowable) {
139: final Writer result = new StringWriter();
140: final PrintWriter printWriter = new PrintWriter(result);
141: aThrowable.printStackTrace(printWriter);
142: return result.toString();
143: }
144:
145: private void traceOrDebugWarn(boolean traceOn, String msg) {
146: if (traceOn) {
147: trace.warn(msg);
148: }
149: log.warn(msg);
150: }
151:
152: }
|