001    package cpw.mods.fml.relauncher;
002    
003    import java.io.ByteArrayOutputStream;
004    import java.io.File;
005    import java.io.IOException;
006    import java.io.PrintStream;
007    import java.util.logging.ConsoleHandler;
008    import java.util.logging.FileHandler;
009    import java.util.logging.Level;
010    import java.util.logging.LogManager;
011    import java.util.logging.Logger;
012    
013    public class FMLRelaunchLog
014    {
015    
016        private static class LoggingOutStream extends ByteArrayOutputStream
017        {
018            private Logger log;
019            private StringBuilder currentMessage;
020    
021            public LoggingOutStream(Logger log)
022            {
023                this.log = log;
024                this.currentMessage = new StringBuilder();
025            }
026    
027            @Override
028            public void flush() throws IOException
029            {
030                String record;
031                synchronized(this)
032                {
033                    super.flush();
034                    record = this.toString();
035                    super.reset();
036    
037                    currentMessage.append(record);
038                    if (currentMessage.lastIndexOf(FMLLogFormatter.LINE_SEPARATOR)>=0)
039                    {
040                        // Are we longer than just the line separator?
041                        if (currentMessage.length()>FMLLogFormatter.LINE_SEPARATOR.length())
042                        {
043                            // Trim the line separator
044                            currentMessage.setLength(currentMessage.length()-FMLLogFormatter.LINE_SEPARATOR.length());
045                            log.log(Level.INFO, currentMessage.toString());
046                        }
047                        currentMessage.setLength(0);
048                    }
049                }
050            }
051        }
052        /**
053         * Our special logger for logging issues to. We copy various assets from the
054         * Minecraft logger to acheive a similar appearance.
055         */
056        public static FMLRelaunchLog log = new FMLRelaunchLog();
057    
058        static File minecraftHome;
059        private static boolean configured;
060        private Logger myLog;
061    
062        private FMLRelaunchLog()
063        {
064        }
065        /**
066         * Configure the FML logger
067         */
068        private static void configureLogging()
069        {
070            LogManager.getLogManager().reset();
071            Logger globalLogger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
072            globalLogger.setLevel(Level.OFF);
073    
074            log.myLog = Logger.getLogger("ForgeModLoader");
075    
076            Logger stdOut = Logger.getLogger("STDOUT");
077            stdOut.setParent(log.myLog);
078            Logger stdErr = Logger.getLogger("STDERR");
079            stdErr.setParent(log.myLog);
080            FMLLogFormatter formatter = new FMLLogFormatter();
081    
082            // Console handler captures the normal stderr before it gets replaced
083            ConsoleHandler ch = new ConsoleHandler();
084            ch.setLevel(Level.parse(System.getProperty("fml.log.level","INFO")));
085            log.myLog.setUseParentHandlers(false);
086            log.myLog.addHandler(ch);
087            ch.setFormatter(formatter);
088            log.myLog.setLevel(Level.ALL);
089            try
090            {
091                File logPath = new File(minecraftHome, FMLRelauncher.logFileNamePattern);
092                FileHandler fileHandler = new FileHandler(logPath.getPath(), 0, 3);
093                fileHandler.setFormatter(formatter);
094                fileHandler.setLevel(Level.ALL);
095                log.myLog.addHandler(fileHandler);
096            }
097            catch (Exception e)
098            {
099            }
100    
101            // Set system out to a log stream
102            System.setOut(new PrintStream(new LoggingOutStream(stdOut), true));
103            System.setErr(new PrintStream(new LoggingOutStream(stdErr), true));
104    
105            // Reset global logging to shut up other logging sources (thanks guava!)
106            configured = true;
107        }
108    
109        public static void log(Level level, String format, Object... data)
110        {
111            if (!configured)
112            {
113                configureLogging();
114            }
115            log.myLog.log(level, String.format(format, data));
116        }
117    
118        public static void log(Level level, Throwable ex, String format, Object... data)
119        {
120            if (!configured)
121            {
122                configureLogging();
123            }
124            log.myLog.log(level, String.format(format, data), ex);
125        }
126    
127        public static void severe(String format, Object... data)
128        {
129            log(Level.SEVERE, format, data);
130        }
131    
132        public static void warning(String format, Object... data)
133        {
134            log(Level.WARNING, format, data);
135        }
136    
137        public static void info(String format, Object... data)
138        {
139            log(Level.INFO, format, data);
140        }
141    
142        public static void fine(String format, Object... data)
143        {
144            log(Level.FINE, format, data);
145        }
146    
147        public static void finer(String format, Object... data)
148        {
149            log(Level.FINER, format, data);
150        }
151    
152        public static void finest(String format, Object... data)
153        {
154            log(Level.FINEST, format, data);
155        }
156        public Logger getLogger()
157        {
158            return myLog;
159        }
160    }