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