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 }