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 Level getLevel() {
094            return level;
095        }
096    
097        public void setLevel(final Level level) {
098            if (level != null) {
099                this.level = level;
100            }
101        }
102    
103        @Override
104        public void log(final Marker marker, final String fqcn, final Level level, final Message msg,
105                        final Throwable throwable) {
106            final StringBuilder sb = new StringBuilder();
107            // Append date-time if so configured
108            if (showDateTime) {
109                final Date now = new Date();
110                String dateText;
111                synchronized (dateFormatter) {
112                    dateText = dateFormatter.format(now);
113                }
114                sb.append(dateText);
115                sb.append(" ");
116            }
117    
118            sb.append(level.toString());
119            sb.append(" ");
120            if (logName != null && logName.length() > 0) {
121                sb.append(logName);
122                sb.append(" ");
123            }
124            sb.append(msg.getFormattedMessage());
125            if (showContextMap) {
126                final Map<String, String> mdc = ThreadContext.getContext();
127                if (mdc.size() > 0) {
128                    sb.append(" ");
129                    sb.append(mdc.toString());
130                    sb.append(" ");
131                }
132            }
133            final Object[] params = msg.getParameters();
134            Throwable t;
135            if (throwable == null && params != null && params[params.length - 1] instanceof Throwable) {
136                t = (Throwable) params[params.length - 1];
137            } else {
138                t = throwable;
139            }
140            if (t != null) {
141                sb.append(" ");
142                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
143                t.printStackTrace(new PrintStream(baos));
144                sb.append(baos.toString());
145            }
146            stream.println(sb.toString());
147        }
148    
149        @Override
150        protected boolean isEnabled(final Level level, final Marker marker, final String msg) {
151            return this.level.intLevel() >= level.intLevel();
152        }
153    
154    
155        @Override
156        protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Throwable t) {
157            return this.level.intLevel() >= level.intLevel();
158        }
159    
160        @Override
161        protected boolean isEnabled(final Level level, final Marker marker, final String msg, final Object... p1) {
162            return this.level.intLevel() >= level.intLevel();
163        }
164    
165        @Override
166        protected boolean isEnabled(final Level level, final Marker marker, final Object msg, final Throwable t) {
167            return this.level.intLevel() >= level.intLevel();
168        }
169    
170        @Override
171        protected boolean isEnabled(final Level level, final Marker marker, final Message msg, final Throwable t) {
172            return this.level.intLevel() >= level.intLevel();
173        }
174    
175    }