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 */
017package org.apache.camel.model;
018
019import java.util.Map;
020import javax.xml.bind.annotation.XmlAccessType;
021import javax.xml.bind.annotation.XmlAccessorType;
022import javax.xml.bind.annotation.XmlAttribute;
023import javax.xml.bind.annotation.XmlRootElement;
024import javax.xml.bind.annotation.XmlTransient;
025
026import org.apache.camel.Exchange;
027import org.apache.camel.Expression;
028import org.apache.camel.LoggingLevel;
029import org.apache.camel.Processor;
030import org.apache.camel.processor.LogProcessor;
031import org.apache.camel.spi.Metadata;
032import org.apache.camel.spi.RouteContext;
033import org.apache.camel.util.CamelContextHelper;
034import org.apache.camel.util.CamelLogger;
035import org.apache.camel.util.ObjectHelper;
036import org.slf4j.Logger;
037import org.slf4j.LoggerFactory;
038
039/**
040 * Logs the defined message to the logger
041 *
042 * @version 
043 */
044@Metadata(label = "configuration")
045@XmlRootElement(name = "log")
046@XmlAccessorType(XmlAccessType.FIELD)
047public class LogDefinition extends NoOutputDefinition<LogDefinition> {
048    @XmlTransient
049    private static final Logger LOG = LoggerFactory.getLogger(LogDefinition.class);
050    @XmlAttribute(required = true)
051    private String message;
052    @XmlAttribute @Metadata(defaultValue = "INFO")
053    private LoggingLevel loggingLevel;
054    @XmlAttribute
055    private String logName;
056    @XmlAttribute
057    private String marker;
058    @XmlAttribute
059    private String loggerRef;
060    @XmlTransient
061    private Logger logger;
062
063    public LogDefinition() {
064    }
065
066    public LogDefinition(String message) {
067        this.message = message;
068    }
069
070    @Override
071    public String toString() {
072        return "Log[" + message + "]";
073    }
074    
075    @Override
076    public String getLabel() {
077        return "log";
078    }
079
080    @Override
081    public Processor createProcessor(RouteContext routeContext) throws Exception {
082        ObjectHelper.notEmpty(message, "message", this);
083
084        // use simple language for the message string to give it more power
085        Expression exp = routeContext.getCamelContext().resolveLanguage("simple").createExpression(message);
086
087        // get logger explicitely set in the definition
088        Logger logger = this.getLogger();
089
090        // get logger which may be set in XML definition
091        if (logger == null && ObjectHelper.isNotEmpty(loggerRef)) {
092            logger = CamelContextHelper.mandatoryLookup(routeContext.getCamelContext(), loggerRef, Logger.class);
093        }
094
095        if (logger == null) {
096            // first - try to lookup single instance in the registry, just like LogComponent
097            Map<String, Logger> availableLoggers = routeContext.lookupByType(Logger.class);
098            if (availableLoggers.size() == 1) {
099                logger = availableLoggers.values().iterator().next();
100                LOG.debug("Using custom Logger: {}", logger);
101            } else if (availableLoggers.size() > 1) {
102                // we should log about this somewhere...
103                LOG.debug("More than one {} instance found in the registry. Falling back to create logger by name.", Logger.class.getName());
104            }
105        }
106
107        if (logger == null) {
108            String name = getLogName();
109            if (name == null) {
110                name = routeContext.getCamelContext().getProperty(Exchange.LOG_EIP_NAME);
111                if (name != null) {
112                    LOG.debug("Using logName from CamelContext properties: {}", name);
113                }
114            }
115            if (name == null) {
116                name = routeContext.getRoute().getId();
117                LOG.debug("LogName is not configured, using route id as logName: {}", name);
118            }
119            logger = LoggerFactory.getLogger(name);
120        }
121
122        // should be INFO by default
123        LoggingLevel level = getLoggingLevel() != null ? getLoggingLevel() : LoggingLevel.INFO;
124        CamelLogger camelLogger = new CamelLogger(logger, level, getMarker());
125
126        return new LogProcessor(exp, camelLogger);
127    }
128
129    @Override
130    public void addOutput(ProcessorDefinition<?> output) {
131        // add outputs on parent as this log does not support outputs
132        getParent().addOutput(output);
133    }
134
135    public LoggingLevel getLoggingLevel() {
136        return loggingLevel;
137    }
138
139    /**
140     * Sets the logging level.
141     * <p/>
142     * The default value is INFO
143     */
144    public void setLoggingLevel(LoggingLevel loggingLevel) {
145        this.loggingLevel = loggingLevel;
146    }
147
148    public String getMessage() {
149        return message;
150    }
151
152    /**
153     * Sets the log message (uses simple language)
154     */
155    public void setMessage(String message) {
156        this.message = message;
157    }
158
159    public String getLogName() {
160        return logName;
161    }
162
163    /**
164     * Sets the name of the logger
165     */
166    public void setLogName(String logName) {
167        this.logName = logName;
168    }
169
170    public String getMarker() {
171        return marker;
172    }
173
174    /**
175     * To use slf4j marker
176     */
177    public void setMarker(String marker) {
178        this.marker = marker;
179    }
180
181    public String getLoggerRef() {
182        return loggerRef;
183    }
184
185    /**
186     * To refer to a custom logger instance to lookup from the registry.
187     */
188    public void setLoggerRef(String loggerRef) {
189        this.loggerRef = loggerRef;
190    }
191
192    public Logger getLogger() {
193        return logger;
194    }
195
196    /**
197     * To use a custom logger instance
198     */
199    public void setLogger(Logger logger) {
200        this.logger = logger;
201    }
202}