001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.processor.interceptor;
018
019 import java.util.List;
020
021 import org.apache.camel.Exchange;
022 import org.apache.camel.Message;
023 import org.apache.camel.Predicate;
024 import org.apache.camel.Processor;
025 import org.apache.camel.model.ProcessorDefinition;
026 import org.apache.camel.processor.DelegateProcessor;
027
028 /**
029 * An interceptor for debugging and tracing routes
030 *
031 * @version $Revision: 750806 $
032 */
033 public class DebugInterceptor extends DelegateProcessor {
034 private final ProcessorDefinition node;
035 private final List<Exchange> exchanges;
036 private final List<ExceptionEvent> exceptions;
037 private Predicate traceFilter;
038 private Breakpoint breakpoint = new Breakpoint();
039 private boolean traceExceptions = true;
040 private boolean enabled = true;
041
042 public DebugInterceptor(ProcessorDefinition node, Processor target, List<Exchange> exchanges, List<ExceptionEvent> exceptions) {
043 super(target);
044 this.node = node;
045 this.exchanges = exchanges;
046 this.exceptions = exceptions;
047 }
048
049 @Override
050 public String toString() {
051 return "DebugInterceptor[" + node + "]";
052 }
053
054 public void process(Exchange exchange) throws Exception {
055 if (isEnabled()) {
056 checkForBreakpoint(exchange);
057 addTraceExchange(exchange);
058 }
059 try {
060 super.proceed(exchange);
061 } catch (Exception e) {
062 onException(exchange, e);
063 throw e;
064 } catch (Error e) {
065 onException(exchange, e);
066 throw e;
067 }
068 }
069
070 public ProcessorDefinition getNode() {
071 return node;
072 }
073
074 public boolean isEnabled() {
075 return enabled;
076 }
077
078 public void setEnabled(boolean flag) {
079 enabled = flag;
080 }
081
082 public List<Exchange> getExchanges() {
083 return exchanges;
084 }
085
086 public List<ExceptionEvent> getExceptions() {
087 return exceptions;
088 }
089
090 public Breakpoint getBreakpoint() {
091 return breakpoint;
092 }
093
094 public Predicate getTraceFilter() {
095 return traceFilter;
096 }
097
098 public void setTraceFilter(Predicate traceFilter) {
099 this.traceFilter = traceFilter;
100 }
101
102 public boolean isTraceExceptions() {
103 return traceExceptions;
104 }
105
106 public void setTraceExceptions(boolean traceExceptions) {
107 this.traceExceptions = traceExceptions;
108 }
109
110 /**
111 * Stategy method to wait for a breakpoint if one is set
112 */
113 protected void checkForBreakpoint(Exchange exchange) {
114 breakpoint.waitForBreakpoint(exchange);
115 }
116
117 /**
118 * Fired when an exception is thrown when processing the underlying processor
119 */
120 protected void onException(Exchange exchange, Throwable e) {
121 if (shouldTraceExceptionEvents(exchange, e)) {
122 exceptions.add(new ExceptionEvent(this, exchange, e));
123 }
124
125 }
126
127 private boolean shouldTraceExceptionEvents(Exchange exchange, Throwable e) {
128 return isTraceExceptions() && isEnabled();
129 }
130
131 /**
132 * Strategy method to store the exchange in a trace log if it is enabled
133 */
134 protected void addTraceExchange(Exchange exchange) {
135 if (shouldTraceExchange(exchange)) {
136 exchanges.add(copyExchange(exchange));
137 }
138 }
139
140 protected Exchange copyExchange(Exchange previousExchange) {
141 Exchange answer = previousExchange.newInstance();
142 answer.getProperties().putAll(previousExchange.getProperties());
143 answer.getIn().copyFrom(previousExchange.getIn());
144
145 // only copy the out if its defined
146 Message previousOut = previousExchange.getOut(false);
147 if (previousOut != null) {
148 answer.getOut().copyFrom(previousOut);
149 }
150 return answer;
151 }
152
153 /**
154 * Returns true if the given exchange should be logged in the trace list
155 */
156 protected boolean shouldTraceExchange(Exchange exchange) {
157 return traceFilter == null || traceFilter.matches(exchange);
158 }
159 }