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.io.Serializable;
020    import java.util.Date;
021    
022    import org.apache.camel.Exchange;
023    import org.apache.camel.Message;
024    import org.apache.camel.RouteNode;
025    import org.apache.camel.model.ProcessorDefinition;
026    import org.apache.camel.spi.TracedRouteNodes;
027    import org.apache.camel.util.MessageHelper;
028    
029    /**
030     * Default {@link TraceEventMessage}.
031     */
032    public final class DefaultTraceEventMessage implements Serializable, TraceEventMessage {
033        private static final long serialVersionUID = -4549012920528941203L;
034    
035        private Date timestamp;
036        private String fromEndpointUri;
037        private String previousNode;
038        private String toNode;
039        private String exchangeId;
040        private String shortExchangeId;
041        private String exchangePattern;
042        private String properties;
043        private String headers;
044        private String body;
045        private String bodyType;
046        private String outHeaders;
047        private String outBody;
048        private String outBodyType;
049        private String causedByException;
050        private String routeId;
051        private final transient Exchange tracedExchange;
052    
053        /**
054         * Creates a {@link DefaultTraceEventMessage} based on the given node it was traced while processing
055         * the current {@link Exchange}
056         *
057         * @param toNode the node where this trace is intercepted
058         * @param exchange the current {@link Exchange}
059         */
060        public DefaultTraceEventMessage(final Date timestamp, final ProcessorDefinition<?> toNode, final Exchange exchange) {
061            this.tracedExchange = exchange;
062            Message in = exchange.getIn();
063    
064            // need to use defensive copies to avoid Exchange altering after the point of interception
065            this.timestamp = timestamp;
066            this.fromEndpointUri = exchange.getFromEndpoint() != null ? exchange.getFromEndpoint().getEndpointUri() : null;
067            this.previousNode = extractFromNode(exchange);
068            this.toNode = extractToNode(exchange);
069            this.exchangeId = exchange.getExchangeId();
070            this.routeId = exchange.getFromRouteId();
071            this.shortExchangeId = extractShortExchangeId(exchange);
072            this.exchangePattern = exchange.getPattern().toString();
073            this.properties = exchange.getProperties().isEmpty() ? null : exchange.getProperties().toString();
074            this.headers = in.getHeaders().isEmpty() ? null : in.getHeaders().toString();
075            this.body = MessageHelper.extractBodyAsString(in);
076            this.bodyType = MessageHelper.getBodyTypeName(in);
077            if (exchange.hasOut()) {
078                Message out = exchange.getOut();
079                this.outHeaders = out.getHeaders().isEmpty() ? null : out.getHeaders().toString();
080                this.outBody = MessageHelper.extractBodyAsString(out);
081                this.outBodyType = MessageHelper.getBodyTypeName(out);
082            }
083            this.causedByException = extractCausedByException(exchange);
084        }
085    
086        // Implementation
087        //---------------------------------------------------------------
088    
089        private static String extractCausedByException(Exchange exchange) {
090            Throwable cause = exchange.getException();
091            if (cause == null) {
092                cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
093            }
094    
095            if (cause != null) {
096                return cause.toString();
097            } else {
098                return null;
099            }
100        }
101    
102        private static String extractShortExchangeId(Exchange exchange) {
103            return exchange.getExchangeId().substring(exchange.getExchangeId().indexOf("/") + 1);
104        }
105    
106        private static String extractFromNode(Exchange exchange) {
107            if (exchange.getUnitOfWork() != null) {
108                TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes();
109                RouteNode last = traced.getSecondLastNode();
110                return last != null ? last.getLabel(exchange) : null;
111            }
112            return null;
113        }
114    
115        private static String extractToNode(Exchange exchange) {
116            if (exchange.getUnitOfWork() != null) {
117                TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes();
118                RouteNode last = traced.getLastNode();
119                return last != null ? last.getLabel(exchange) : null;
120            }
121            return null;
122        }
123    
124        // Properties
125        //---------------------------------------------------------------
126    
127        public Date getTimestamp() {
128            return timestamp;
129        }
130    
131        public String getFromEndpointUri() {
132            return fromEndpointUri;
133        }
134    
135        public String getPreviousNode() {
136            return previousNode;
137        }
138    
139        public String getToNode() {
140            return toNode;
141        }
142    
143        public String getExchangeId() {
144            return exchangeId;
145        }
146    
147        public String getRouteId() {
148            return routeId;
149        }
150    
151        public String getShortExchangeId() {
152            return shortExchangeId;
153        }
154    
155        public String getExchangePattern() {
156            return exchangePattern;
157        }
158    
159        public String getProperties() {
160            return properties;
161        }
162    
163        public String getHeaders() {
164            return headers;
165        }
166    
167        public String getBody() {
168            return body;
169        }
170    
171        public String getBodyType() {
172            return bodyType;
173        }
174    
175        public String getOutBody() {
176            return outBody;
177        }
178    
179        public String getOutBodyType() {
180            return outBodyType;
181        }
182    
183        public String getOutHeaders() {
184            return outHeaders;
185        }
186    
187        public String getCausedByException() {
188            return causedByException;
189        }
190    
191        public void setTimestamp(Date timestamp) {
192            this.timestamp = timestamp;
193        }
194    
195        public void setFromEndpointUri(String fromEndpointUri) {
196            this.fromEndpointUri = fromEndpointUri;
197        }
198    
199        public void setPreviousNode(String previousNode) {
200            this.previousNode = previousNode;
201        }
202    
203        public void setToNode(String toNode) {
204            this.toNode = toNode;
205        }
206    
207        public void setExchangeId(String exchangeId) {
208            this.exchangeId = exchangeId;
209        }
210    
211        public void setRouteId(String routeId) {
212            this.routeId = routeId;
213        }
214    
215        public void setShortExchangeId(String shortExchangeId) {
216            this.shortExchangeId = shortExchangeId;
217        }
218    
219        public void setExchangePattern(String exchangePattern) {
220            this.exchangePattern = exchangePattern;
221        }
222    
223        public void setProperties(String properties) {
224            this.properties = properties;
225        }
226    
227        public void setHeaders(String headers) {
228            this.headers = headers;
229        }
230    
231        public void setBody(String body) {
232            this.body = body;
233        }
234    
235        public void setBodyType(String bodyType) {
236            this.bodyType = bodyType;
237        }
238    
239        public void setOutBody(String outBody) {
240            this.outBody = outBody;
241        }
242    
243        public void setOutBodyType(String outBodyType) {
244            this.outBodyType = outBodyType;
245        }
246    
247        public void setOutHeaders(String outHeaders) {
248            this.outHeaders = outHeaders;
249        }
250    
251        public void setCausedByException(String causedByException) {
252            this.causedByException = causedByException;
253        }
254    
255        public Exchange getTracedExchange() {
256            return tracedExchange;
257        }
258    
259        @Override
260        public String toString() {
261            return "TraceEventMessage[" + exchangeId + "] on node: " + toNode;
262        }
263    }