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.component.log;
018    
019    import java.io.PrintWriter;
020    import java.io.StringWriter;
021    import java.util.concurrent.Future;
022    
023    import org.apache.camel.Exchange;
024    import org.apache.camel.Message;
025    import org.apache.camel.StreamCache;
026    import org.apache.camel.spi.ExchangeFormatter;
027    import org.apache.camel.util.ObjectHelper;
028    
029    /**
030     * Log formatter to format the logging output.
031     */
032    public class LogFormatter implements ExchangeFormatter {
033    
034        private boolean showExchangeId;
035        private boolean showProperties;
036        private boolean showHeaders;
037        private boolean showBodyType = true;
038        private boolean showBody = true;
039        private boolean showOut;
040        private boolean showException;
041        private boolean showCaughtException;
042        private boolean showStackTrace;
043        private boolean showAll;
044        private boolean multiline;
045        private boolean showFuture;
046        private int maxChars;
047    
048        public Object format(Exchange exchange) {
049            Message in = exchange.getIn();
050    
051            StringBuilder sb = new StringBuilder("");
052            if (showAll || showExchangeId) {
053                if (multiline) {
054                    sb.append('\n');
055                }
056                sb.append(", Id:").append(exchange.getExchangeId());
057            }
058            if (showAll || showProperties) {
059                if (multiline) {
060                    sb.append('\n');
061                }
062                sb.append(", Properties:").append(exchange.getProperties());
063            }
064            if (showAll || showHeaders) {
065                if (multiline) {
066                    sb.append('\n');
067                }
068                sb.append(", Headers:").append(in.getHeaders());
069            }
070            if (showAll || showBodyType) {
071                if (multiline) {
072                    sb.append('\n');
073                }
074                sb.append(", BodyType:").append(getBodyTypeAsString(in));
075            }
076            if (showAll || showBody) {
077                if (multiline) {
078                    sb.append('\n');
079                }
080                sb.append(", Body:").append(getBodyAsString(in));
081            }
082    
083            if (showAll || showException || showCaughtException) {
084    
085                // try exception on exchange first
086                Exception exception = exchange.getException();
087                boolean caught = false;
088                if ((showAll || showCaughtException) && exception == null) {
089                    // fallback to caught exception
090                    exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
091                    caught = true;
092                }
093    
094                if (exception != null) {
095                    if (multiline) {
096                        sb.append('\n');
097                    }
098                    if (caught) {
099                        sb.append(", CaughtExceptionType:").append(exception.getClass().getCanonicalName());
100                        sb.append(", CaughtExceptionMessage:").append(exception.getMessage());
101                    } else {
102                        sb.append(", ExceptionType:").append(exception.getClass().getCanonicalName());
103                        sb.append(", ExceptionMessage:").append(exception.getMessage());
104                    }
105                    if (showAll || showStackTrace) {
106                        StringWriter sw = new StringWriter();
107                        exception.printStackTrace(new PrintWriter(sw));
108                        sb.append(", StackTrace:").append(sw.toString());
109                    }
110                }
111            }
112    
113            if (showAll || showOut) {
114                if (exchange.hasOut()) {
115                    Message out = exchange.getOut();
116                    if (showAll || showHeaders) {
117                        if (multiline) {
118                            sb.append('\n');
119                        }
120                        sb.append(", OutHeaders:").append(out.getHeaders());
121                    }
122                    if (showAll || showBodyType) {
123                        if (multiline) {
124                            sb.append('\n');
125                        }
126                        sb.append(", OutBodyType:").append(getBodyTypeAsString(out));
127                    }
128                    if (showAll || showBody) {
129                        if (multiline) {
130                            sb.append('\n');
131                        }
132                        sb.append(", OutBody:").append(getBodyAsString(out));
133                    }
134                } else {
135                    if (multiline) {
136                        sb.append('\n');
137                    }
138                    sb.append(", Out: null");
139                }
140            }
141    
142            if (maxChars > 0) {
143                StringBuilder answer = new StringBuilder();
144                for (String s : sb.toString().split("\n")) {
145                    if (s != null) {
146                        if (s.length() > maxChars) {
147                            s = s.substring(0, maxChars);
148                            answer.append(s).append("...");
149                        } else {
150                            answer.append(s);
151                        }
152                        if (multiline) {
153                            answer.append("\n");
154                        }
155                    }
156                }
157    
158                // get rid of the leading space comma if needed
159                return "Exchange[" + (multiline ? answer.append(']').toString() : answer.toString().substring(2) + "]");
160            }
161    
162            // get rid of the leading space comma if needed
163            return "Exchange[" + (multiline ? sb.append(']').toString() : sb.toString().substring(2) + "]");
164        }
165    
166        public boolean isShowExchangeId() {
167            return showExchangeId;
168        }
169    
170        public void setShowExchangeId(boolean showExchangeId) {
171            this.showExchangeId = showExchangeId;
172        }
173    
174        public boolean isShowProperties() {
175            return showProperties;
176        }
177    
178        public void setShowProperties(boolean showProperties) {
179            this.showProperties = showProperties;
180        }
181    
182        public boolean isShowHeaders() {
183            return showHeaders;
184        }
185    
186        public void setShowHeaders(boolean showHeaders) {
187            this.showHeaders = showHeaders;
188        }
189    
190        public boolean isShowBodyType() {
191            return showBodyType;
192        }
193    
194        public void setShowBodyType(boolean showBodyType) {
195            this.showBodyType = showBodyType;
196        }
197    
198        public boolean isShowBody() {
199            return showBody;
200        }
201    
202        public void setShowBody(boolean showBody) {
203            this.showBody = showBody;
204        }
205    
206        public boolean isShowOut() {
207            return showOut;
208        }
209    
210        public void setShowOut(boolean showOut) {
211            this.showOut = showOut;
212        }
213    
214        public boolean isShowAll() {
215            return showAll;
216        }
217    
218        public void setShowAll(boolean showAll) {
219            this.showAll = showAll;
220        }
221    
222        public boolean isShowException() {
223            return showException;
224        }
225    
226        public void setShowException(boolean showException) {
227            this.showException = showException;
228        }
229    
230        public boolean isShowStackTrace() {
231            return showStackTrace;
232        }
233    
234        public void setShowStackTrace(boolean showStackTrace) {
235            this.showStackTrace = showStackTrace;
236        }
237    
238        public boolean isShowCaughtException() {
239            return showCaughtException;
240        }
241    
242        public void setShowCaughtException(boolean showCaughtException) {
243            this.showCaughtException = showCaughtException;
244        }
245    
246        public boolean isMultiline() {
247            return multiline;
248        }
249    
250        public int getMaxChars() {
251            return maxChars;
252        }
253    
254        public void setMaxChars(int maxChars) {
255            this.maxChars = maxChars;
256        }
257    
258        /**
259         * If enabled then each information is outputted on a newline.
260         */
261        public void setMultiline(boolean multiline) {
262            this.multiline = multiline;
263        }
264    
265        public boolean isShowFuture() {
266            return showFuture;
267        }
268    
269        /**
270         * If enabled Camel will on Future objects wait for it to complete to obtain the payload to be logged.
271         * <p/>
272         * Is default disabled.
273         */
274        public void setShowFuture(boolean showFuture) {
275            this.showFuture = showFuture;
276        }
277    
278    
279        // Implementation methods
280        //-------------------------------------------------------------------------
281        protected Object getBodyAsString(Message message) {
282            if (message.getBody() instanceof Future) {
283                if (!isShowFuture()) {
284                    // just use a to string of the future object
285                    return message.getBody().toString();
286                }
287            }
288    
289            StreamCache newBody = message.getBody(StreamCache.class);
290            if (newBody != null) {
291                message.setBody(newBody);
292            }
293    
294            Object answer = message.getBody(String.class);
295            if (answer == null) {
296                answer = message.getBody();
297            }
298    
299            if (newBody != null) {
300                // Reset the StreamCache
301                newBody.reset();
302            }
303            return answer;
304        }
305    
306        protected Object getBodyTypeAsString(Message message) {
307            String answer = ObjectHelper.classCanonicalName(message.getBody());
308            if (answer != null && answer.startsWith("java.lang.")) {
309                return answer.substring(10);
310            }
311            return answer;
312        }
313    
314    }