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