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 org.apache.camel.Exchange;
020    import org.apache.camel.Processor;
021    import org.apache.camel.model.InterceptorRef;
022    import org.apache.camel.model.ProcessorType;
023    import org.apache.camel.processor.DelegateProcessor;
024    import org.apache.camel.processor.Logger;
025    import org.apache.camel.spi.InterceptStrategy;
026    import org.apache.commons.logging.LogFactory;
027    
028    /**
029     * An interceptor for debugging and tracing routes
030     *
031     * @version $Revision: 1532 $
032     */
033    public class TraceInterceptor extends DelegateProcessor implements ExchangeFormatter {
034        private Logger logger;
035        private final ProcessorType node;
036        private final Tracer tracer;
037        private TraceFormatter formatter;
038    
039        public TraceInterceptor(ProcessorType node, Processor target, TraceFormatter formatter, Tracer tracer) {
040            super(target);
041            this.tracer = tracer;
042            this.node = node;
043            this.formatter = formatter;
044    
045            // set logger to use
046            if (tracer.getLogName() != null) {
047                logger = new Logger(LogFactory.getLog(tracer.getLogName()), this);
048            } else {
049                // use default logger
050                logger = new Logger(LogFactory.getLog(TraceInterceptor.class), this);
051            }
052    
053            // set logging level if provided
054            if (tracer.getLogLevel() != null) {
055                logger.setLevel(tracer.getLogLevel());
056            }
057    
058            if (tracer.getFormatter() != null) {
059                this.formatter = tracer.getFormatter();
060            }
061        }
062    
063        /**
064         * @deprecated will be removed in Camel 2.0
065         */
066        public TraceInterceptor(ProcessorType node, Processor target, TraceFormatter formatter) {
067            this(node, target, formatter, new Tracer());
068        }
069    
070        public TraceInterceptor(ProcessorType node, Processor target, Tracer tracer) {
071            this(node, target, null, tracer);
072        }
073    
074        @Override
075        public String toString() {
076            return "TraceInterceptor[" + node + "]";
077        }
078    
079        public void process(final Exchange exchange) throws Exception {
080            try {
081                if (shouldLogNode(node) && shouldLogExchange(exchange)) {
082                    logExchange(exchange);
083                }
084                super.proceed(exchange);
085                if (tracer.isTraceOutExchanges() && shouldLogNode(node) && shouldLogExchange(exchange)) {
086                    logExchange(exchange);
087                }            
088            } catch (Exception e) {
089                if (shouldLogException(exchange)) {
090                    logException(exchange, e);
091                }
092                throw e;
093            }
094        }
095    
096        public Object format(Exchange exchange) {
097            return formatter.format(this, exchange);
098        }
099    
100        // Properties
101        //-------------------------------------------------------------------------
102        public ProcessorType getNode() {
103            return node;
104        }
105    
106        public Logger getLogger() {
107            return logger;
108        }
109    
110        public TraceFormatter getFormatter() {
111            return formatter;
112        }
113    
114        // Implementation methods
115        //-------------------------------------------------------------------------
116        protected void logExchange(Exchange exchange) {
117            logger.process(exchange);
118        }
119    
120        protected void logException(Exchange exchange, Throwable throwable) {
121            if (tracer.isTraceExceptions()) {
122                logger.process(exchange, throwable);
123            }
124        }
125    
126        /**
127         * Returns true if the given exchange should be logged in the trace list
128         */
129        protected boolean shouldLogExchange(Exchange exchange) {
130            return (tracer == null || tracer.isEnabled())
131                && (tracer.getTraceFilter() == null || tracer.getTraceFilter().matches(exchange));
132        }
133    
134        /**
135         * Returns true if the given exchange should be logged when an exception was thrown
136         */
137        protected boolean shouldLogException(Exchange exchange) {
138            return tracer.isTraceExceptions();
139        }
140    
141        /**
142         * Returns whether exchanges coming out of processors should be traced
143         */   
144        public boolean shouldTraceOutExchanges() {
145            return tracer.isTraceOutExchanges();
146        }
147        
148        /**
149         * Returns true if the given node should be logged in the trace list
150         */
151        protected boolean shouldLogNode(ProcessorType node) {
152            if (node == null) {
153                return false;
154            }
155            if (!tracer.isTraceInterceptors() && (node instanceof InterceptStrategy || node instanceof InterceptorRef)) {
156                return false;
157            }
158            return true;
159        }
160    
161    }