001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.util;
033
034import java.io.BufferedWriter;
035import java.io.FileWriter;
036import java.io.IOException;
037import java.io.PrintWriter;
038
039/**
040 * Logger.
041 *
042 * @author Frédéric Guinand
043 * @author Yoann Pigné
044 * @author Antoine Dutot
045 * @since  20061108
046 */
047public class Logger
048{
049// ---------- Constants --------------
050
051        /**
052         * The different log levels.
053         * 
054         * It can be {@link LogLevel#DEBUG}, {@link LogLevel#INFO},
055         * {@link LogLevel#WARN} or {@link LogLevel#ERROR}. There is an order
056         * between the different log level: DEBUG < INFO < WARN < ERROR. So if you
057         * set the logLevel to DEBUG, then you will receive _all_ the messages, if
058         * you set it to INFO, then you will not receive the DEBUG messages. If you
059         * set it to WARN, you will not receive the INFO or DEBUG messages.
060         * And so on...
061         */
062        public enum LogLevel
063        {
064                DEBUG(  "Debug",   0 ),
065                INFO(   "Info",    1 ),
066                WARN(   "Warning", 2 ),
067                ERROR(  "Error",   3 ),
068                RESULT( "Result",  4 );
069                
070                public String info;
071                public int value;
072                LogLevel( String info, int value ) { this.info = info; this.value = value; }
073                public boolean ge( LogLevel other ) { return value >= other.value; }
074        };
075        
076        public static Logger GLOBAL_LOGGER;
077        
078// ------- Attributes ------
079        
080        /**
081         * Name of the log file. Default value is "stderr". It means that output is
082         * written on the standard error stream.
083         */
084        protected String logFileName = "stderr";
085
086        /**
087         * Has the logging file been opened yet?.
088         */
089        protected boolean logFileOpened = false;
090
091        /**
092         * Output stream.
093         */
094        protected static PrintWriter out;
095        
096        /**
097         * The current log level;
098         */
099        protected LogLevel logLevel = LogLevel.DEBUG;
100
101// ------- Methods -------
102
103        /**
104         * The method that every class of the package should use to send exception
105         * messages to the user.
106         * @param level The log level of the message.
107         * @param ref The name of the class calling this method.
108         * @param e The exception to log.
109         */
110        public void
111        log( LogLevel level, String ref, Exception e )
112        {
113                if( level.ge( logLevel ) )
114                {
115                        try
116                        {
117                                openLogFile();
118
119                                out.printf( "%-5s : %s : %s\n", logLevel.info, ref, e.toString() );
120                                out.printf( "The exception is in %s", java.lang.Thread.currentThread().toString() );
121                                e.printStackTrace( out );
122                                out.flush();
123                        }
124                        catch( IOException ioe )
125                        {
126                                System.err.printf( "%-5s : %s : %s\n", "ERROR", "Environment",
127                                                ioe.toString() );
128                                ioe.printStackTrace();
129                                System.exit( 0 );
130                        }
131                }
132        }
133
134        /**
135         * The method that every class of the package should use to send messages to
136         * the user.
137         * @param level The log level of the message.
138         * @param ref The name of the class calling this method.
139         * @param message The message to log (can be in printf format).
140         * @param params The parameter of the message if in printf format.
141         */
142        public void
143        log( LogLevel level, String ref, String message, Object ... params )
144        {
145                if( level.ge( logLevel ) )
146                {
147                        try
148                        {
149                                openLogFile();
150
151                                out.printf( "%-5s : %s : ", level.info, ref );
152                                out.printf( message, params );
153                                out.printf( "%n" );
154                                out.flush();
155                        }
156                        catch( IOException ioe )
157                        {
158                                System.err.printf( "%-5s : %s : %s\n", "ERROR", "Environment",
159                                                ioe.toString() );
160                                ioe.printStackTrace();
161                                System.exit( 0 );
162                        }
163                }
164        }
165        
166        /**
167         * Verifies that the output log file is open, and if not open it. 
168         * @throws IOException For any error while openning the file.
169         */
170        protected void
171        openLogFile()
172                throws IOException
173        {
174                if( ! logFileOpened )
175                {
176                        if( logFileName.equals( "stderr" ) )
177                        {
178                                out = new PrintWriter( System.err );
179                        }
180                        else
181                        {
182                                out = new PrintWriter( new BufferedWriter(
183                                                new FileWriter( logFileName ) ) );
184                        }
185                        
186                        logFileOpened = true;
187                }
188        }
189        
190        /**
191         * Change the log level.
192         * @param level The new log level.
193         */
194        public void
195        setLogLevel( LogLevel level )
196        {
197                logLevel = level;
198        }
199        
200        /**
201         * Return the shared global instance of the logger. This singleton instance
202         * is avaiable in the whole JVM.
203         * @return The singleton global instance of the logger.
204         */
205        public static Logger
206        getGlobalLogger()
207        {
208                if( GLOBAL_LOGGER == null )
209                        GLOBAL_LOGGER = new Logger();
210                
211                return GLOBAL_LOGGER;
212        }
213}