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.logging.log4j.simple; 018 019import java.io.FileNotFoundException; 020import java.io.FileOutputStream; 021import java.io.PrintStream; 022import java.util.concurrent.ConcurrentHashMap; 023import java.util.concurrent.ConcurrentMap; 024 025import org.apache.logging.log4j.Level; 026import org.apache.logging.log4j.message.MessageFactory; 027import org.apache.logging.log4j.spi.AbstractLogger; 028import org.apache.logging.log4j.spi.ExtendedLogger; 029import org.apache.logging.log4j.spi.LoggerContext; 030import org.apache.logging.log4j.spi.LoggerContextKey; 031import org.apache.logging.log4j.util.PropertiesUtil; 032 033/** 034 * 035 */ 036public class SimpleLoggerContext implements LoggerContext { 037 038 /** The default format to use when formatting dates */ 039 protected static final String DEFAULT_DATE_TIME_FORMAT = "yyyy/MM/dd HH:mm:ss:SSS zzz"; 040 041 /** All system properties used by <code>SimpleLog</code> start with this */ 042 protected static final String SYSTEM_PREFIX = "org.apache.logging.log4j.simplelog."; 043 044 private final PropertiesUtil props; 045 046 /** Include the instance name in the log message? */ 047 private final boolean showLogName; 048 049 /** 050 * Include the short name (last component) of the logger in the log message. Defaults to true - otherwise we'll be 051 * lost in a flood of messages without knowing who sends them. 052 */ 053 private final boolean showShortName; 054 /** Include the current time in the log message */ 055 private final boolean showDateTime; 056 /** Include the ThreadContextMap in the log message */ 057 private final boolean showContextMap; 058 /** The date and time format to use in the log message */ 059 private final String dateTimeFormat; 060 061 private final Level defaultLevel; 062 063 private final PrintStream stream; 064 065 private final ConcurrentMap<String, ExtendedLogger> loggers = new ConcurrentHashMap<>(); 066 067 public SimpleLoggerContext() { 068 props = new PropertiesUtil("log4j2.simplelog.properties"); 069 070 showContextMap = props.getBooleanProperty(SYSTEM_PREFIX + "showContextMap", false); 071 showLogName = props.getBooleanProperty(SYSTEM_PREFIX + "showlogname", false); 072 showShortName = props.getBooleanProperty(SYSTEM_PREFIX + "showShortLogname", true); 073 showDateTime = props.getBooleanProperty(SYSTEM_PREFIX + "showdatetime", false); 074 final String lvl = props.getStringProperty(SYSTEM_PREFIX + "level"); 075 defaultLevel = Level.toLevel(lvl, Level.ERROR); 076 077 dateTimeFormat = showDateTime ? props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + "dateTimeFormat", 078 DEFAULT_DATE_TIME_FORMAT) : null; 079 080 final String fileName = props.getStringProperty(SYSTEM_PREFIX + "logFile", "system.err"); 081 PrintStream ps; 082 if ("system.err".equalsIgnoreCase(fileName)) { 083 ps = System.err; 084 } else if ("system.out".equalsIgnoreCase(fileName)) { 085 ps = System.out; 086 } else { 087 try { 088 final FileOutputStream os = new FileOutputStream(fileName); 089 ps = new PrintStream(os); 090 } catch (final FileNotFoundException fnfe) { 091 ps = System.err; 092 } 093 } 094 this.stream = ps; 095 } 096 097 @Override 098 public ExtendedLogger getLogger(final String name) { 099 return getLogger(name, null); 100 } 101 102 @Override 103 public ExtendedLogger getLogger(final String name, final MessageFactory messageFactory) { 104 // Note: This is the only method where we add entries to the 'loggers' ivar. 105 // The loggers map key is the logger name plus the messageFactory FQCN. 106 String key = LoggerContextKey.create(name, messageFactory); 107 final ExtendedLogger extendedLogger = loggers.get(key); 108 if (extendedLogger != null) { 109 AbstractLogger.checkMessageFactory(extendedLogger, messageFactory); 110 return extendedLogger; 111 } 112 final SimpleLogger simpleLogger = new SimpleLogger(name, defaultLevel, showLogName, showShortName, showDateTime, 113 showContextMap, dateTimeFormat, messageFactory, props, stream); 114 // If messageFactory was null then we need to pull it out of the logger now 115 key = LoggerContextKey.create(name, simpleLogger.getMessageFactory()); 116 loggers.putIfAbsent(key, simpleLogger); 117 return loggers.get(key); 118 } 119 120 @Override 121 public boolean hasLogger(final String name) { 122 return false; 123 } 124 125 @Override 126 public boolean hasLogger(String name, MessageFactory messageFactory) { 127 return false; 128 } 129 130 @Override 131 public boolean hasLogger(String name, Class<? extends MessageFactory> messageFactoryClass) { 132 return false; 133 } 134 135 @Override 136 public Object getExternalContext() { 137 return null; 138 } 139 140}