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.logging.log4j.simple;
018    
019    import java.io.ByteArrayOutputStream;
020    import java.io.PrintStream;
021    import java.text.DateFormat;
022    import java.text.SimpleDateFormat;
023    import java.util.Date;
024    import java.util.Map;
025    
026    import org.apache.logging.log4j.Level;
027    import org.apache.logging.log4j.Marker;
028    import org.apache.logging.log4j.ThreadContext;
029    import org.apache.logging.log4j.message.Message;
030    import org.apache.logging.log4j.message.MessageFactory;
031    import org.apache.logging.log4j.spi.AbstractLogger;
032    import org.apache.logging.log4j.util.PropertiesUtil;
033    
034    /**
035     *  This is the default logger that is used when no suitable logging implementation is available.
036     *
037     */
038    public class SimpleLogger extends AbstractLogger {
039    
040        /**
041         * Used to format times.
042         * <p>
043         * Note that DateFormat is not Thread-safe.
044         */
045        private DateFormat dateFormatter = null;
046    
047        private Level level;
048    
049        private final boolean showDateTime;
050    
051        private final boolean showContextMap;
052    
053        private PrintStream stream;
054    
055        private String logName;
056    
057    
058        public SimpleLogger(final String name, final Level defaultLevel, final boolean showLogName,
059                            final boolean showShortLogName, final boolean showDateTime, final boolean showContextMap,
060                            final String dateTimeFormat, final MessageFactory messageFactory, final PropertiesUtil props,
061                            final PrintStream stream) {
062            super(name, messageFactory);
063            final String lvl = props.getStringProperty(SimpleLoggerContext.SYSTEM_PREFIX + name + ".level");
064            this.level = Level.toLevel(lvl, defaultLevel);
065            if (showShortLogName) {
066                final int index = name.lastIndexOf(".");
067                if (index > 0 && index < name.length()) {
068                    this.logName = name.substring(index + 1);
069                } else {
070                    this.logName = name;
071                }
072            } else if (showLogName) {
073                this.logName = name;
074            }
075            this.showDateTime = showDateTime;
076            this.showContextMap = showContextMap;
077            this.stream = stream;
078    
079            if (showDateTime) {
080                try {
081                    this.dateFormatter = new SimpleDateFormat(dateTimeFormat);
082                } catch (final IllegalArgumentException e) {
083                    // If the format pattern is invalid - use the default format
084                    this.dateFormatter = new SimpleDateFormat(SimpleLoggerContext.DEFAULT_DATE_TIME_FORMAT);
085                }
086            }
087        }
088    
089        public void setStream(final PrintStream stream) {
090            this.stream = stream;
091        }
092    
093        public void setLevel(final Level level) {
094            if (level != null) {
095                this.level = level;
096            }
097        }
098    
099        @Override
100        public void log(final Marker marker, final String fqcn, final Level level, final Message msg,
101                        final Throwable throwable) {
102            final StringBuilder sb = new StringBuilder();
103            // Append date-time if so configured
104            if (showDateTime) {
105                final Date now = new Date();
106                String dateText;
107                synchronized (dateFormatter) {
108                    dateText = dateFormatter.format(now);
109                }
110                sb.append(dateText);
111                sb.append(" ");
112            }
113    
114            sb.append(level.toString());
115            sb.append(" ");
116            if (logName != null && logName.length() > 0) {
117                sb.append(logName);
118                sb.append(" ");
119            }
120            sb.append(msg.getFormattedMessage());
121            if (showContextMap) {
122                final Map<String, String> mdc = ThreadContext.getContext();
123                if (mdc.size() > 0) {
124                    sb.append(" ");
125                    sb.append(mdc.toString());
126                    sb.append(" ");
127                }
128            }
129            final Object[] params = msg.getParameters();
130            Throwable t;
131            if (throwable == null && params != null && params[params.length - 1] instanceof Throwable) {
132                t = (Throwable) params[params.length - 1];
133            } else {
134                t = throwable;
135            }
136            if (t != null) {
137                sb.append(" ");
138                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
139                t.printStackTrace(new PrintStream(baos));
140                sb.append(baos.toString());
141            }
142            stream.println(sb.toString());
143        }
144    
145        @Override
146        protected boolean isEnabled(final Level level, final Marker marker, final String msg) {
147            return this.level.intLevel() >= level.intLevel();
148        }
149    
150    
151        @Override
152        protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) {
153            return this.level.intLevel() >= level.intLevel();
154        }
155    
156        @Override
157        protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) {
158            return this.level.intLevel() >= level.intLevel();
159        }
160    
161        @Override
162        protected boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) {
163            return this.level.intLevel() >= level.intLevel();
164        }
165    
166        @Override
167        protected boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) {
168            return this.level.intLevel() >= level.intLevel();
169        }
170    
171    }