001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.FMLCommonHandler; 004 import cpw.mods.fml.common.Side; 005 import cpw.mods.fml.common.asm.SideOnly; 006 import java.io.File; 007 import java.io.FileWriter; 008 import java.io.IOException; 009 import java.io.PrintWriter; 010 import java.io.StringWriter; 011 import java.text.SimpleDateFormat; 012 import java.util.ArrayList; 013 import java.util.Date; 014 import java.util.Iterator; 015 import java.util.List; 016 import java.util.logging.Level; 017 import java.util.logging.Logger; 018 019 public class CrashReport 020 { 021 /** Description of the crash report. */ 022 private final String description; 023 024 /** The Throwable that is the "cause" for this crash and Crash Report. */ 025 private final Throwable cause; 026 private final CrashReportCategory field_85061_c = new CrashReportCategory(this, "System Details"); 027 028 /** Holds the keys and values of all crash report sections. */ 029 private final List crashReportSections = new ArrayList(); 030 031 /** File of crash report. */ 032 private File crashReportFile = null; 033 private boolean field_85059_f = true; 034 private StackTraceElement[] field_85060_g = new StackTraceElement[0]; 035 036 public CrashReport(String par1Str, Throwable par2Throwable) 037 { 038 this.description = par1Str; 039 this.cause = par2Throwable; 040 this.func_71504_g(); 041 } 042 043 private void func_71504_g() 044 { 045 this.field_85061_c.addCrashSectionCallable("Minecraft Version", new CallableMinecraftVersion(this)); 046 this.field_85061_c.addCrashSectionCallable("Operating System", new CallableOSInfo(this)); 047 this.field_85061_c.addCrashSectionCallable("Java Version", new CallableJavaInfo(this)); 048 this.field_85061_c.addCrashSectionCallable("Java VM Version", new CallableJavaInfo2(this)); 049 this.field_85061_c.addCrashSectionCallable("Memory", new CallableMemoryInfo(this)); 050 this.field_85061_c.addCrashSectionCallable("JVM Flags", new CallableJVMFlags(this)); 051 this.field_85061_c.addCrashSectionCallable("AABB Pool Size", new CallableCrashMemoryReport(this)); 052 this.field_85061_c.addCrashSectionCallable("Suspicious classes", new CallableSuspiciousClasses(this)); 053 this.field_85061_c.addCrashSectionCallable("IntCache", new CallableIntCache(this)); 054 FMLCommonHandler.instance().enhanceCrashReport(this, this.field_85061_c); 055 } 056 057 /** 058 * Returns the description of the Crash Report. 059 */ 060 public String getDescription() 061 { 062 return this.description; 063 } 064 065 /** 066 * Returns the Throwable object that is the cause for the crash and Crash Report. 067 */ 068 public Throwable getCrashCause() 069 { 070 return this.cause; 071 } 072 073 /** 074 * Gets the various sections of the crash report into the given StringBuilder 075 */ 076 public void getSectionsInStringBuilder(StringBuilder par1StringBuilder) 077 { 078 if (this.field_85060_g != null && this.field_85060_g.length > 0) 079 { 080 par1StringBuilder.append("-- Head --\n"); 081 par1StringBuilder.append("Stacktrace:\n"); 082 StackTraceElement[] var2 = this.field_85060_g; 083 int var3 = var2.length; 084 085 for (int var4 = 0; var4 < var3; ++var4) 086 { 087 StackTraceElement var5 = var2[var4]; 088 par1StringBuilder.append("\t").append("at ").append(var5.toString()); 089 par1StringBuilder.append("\n"); 090 } 091 092 par1StringBuilder.append("\n"); 093 } 094 095 Iterator var6 = this.crashReportSections.iterator(); 096 097 while (var6.hasNext()) 098 { 099 CrashReportCategory var7 = (CrashReportCategory)var6.next(); 100 var7.func_85072_a(par1StringBuilder); 101 par1StringBuilder.append("\n\n"); 102 } 103 104 this.field_85061_c.func_85072_a(par1StringBuilder); 105 } 106 107 /** 108 * Gets the stack trace of the Throwable that caused this crash report, or if that fails, the cause .toString(). 109 */ 110 public String getCauseStackTraceOrString() 111 { 112 StringWriter var1 = null; 113 PrintWriter var2 = null; 114 String var3 = this.cause.toString(); 115 116 try 117 { 118 var1 = new StringWriter(); 119 var2 = new PrintWriter(var1); 120 this.cause.printStackTrace(var2); 121 var3 = var1.toString(); 122 } 123 finally 124 { 125 try 126 { 127 if (var1 != null) 128 { 129 var1.close(); 130 } 131 132 if (var2 != null) 133 { 134 var2.close(); 135 } 136 } 137 catch (IOException var10) 138 { 139 ; 140 } 141 } 142 143 return var3; 144 } 145 146 /** 147 * Gets the complete report with headers, stack trace, and different sections as a string. 148 */ 149 public String getCompleteReport() 150 { 151 StringBuilder var1 = new StringBuilder(); 152 var1.append("---- Minecraft Crash Report ----\n"); 153 var1.append("// "); 154 var1.append(getWittyComment()); 155 var1.append("\n\n"); 156 var1.append("Time: "); 157 var1.append((new SimpleDateFormat()).format(new Date())); 158 var1.append("\n"); 159 var1.append("Description: "); 160 var1.append(this.description); 161 var1.append("\n\n"); 162 var1.append(this.getCauseStackTraceOrString()); 163 var1.append("\n\nA detailed walkthrough of the error, its code path and all known details is as follows:\n"); 164 165 for (int var2 = 0; var2 < 87; ++var2) 166 { 167 var1.append("-"); 168 } 169 170 var1.append("\n\n"); 171 this.getSectionsInStringBuilder(var1); 172 return var1.toString(); 173 } 174 175 @SideOnly(Side.CLIENT) 176 177 /** 178 * Gets the file this crash report is saved into. 179 */ 180 public File getFile() 181 { 182 return this.crashReportFile; 183 } 184 185 /** 186 * Saves the complete crash report to the given File. 187 */ 188 public boolean saveToFile(File par1File) 189 { 190 if (this.crashReportFile != null) 191 { 192 return false; 193 } 194 else 195 { 196 if (par1File.getParentFile() != null) 197 { 198 par1File.getParentFile().mkdirs(); 199 } 200 201 try 202 { 203 FileWriter var2 = new FileWriter(par1File); 204 var2.write(this.getCompleteReport()); 205 var2.close(); 206 this.crashReportFile = par1File; 207 return true; 208 } 209 catch (Throwable var3) 210 { 211 Logger.getLogger("Minecraft").log(Level.SEVERE, "Could not save crash report to " + par1File, var3); 212 return false; 213 } 214 } 215 } 216 217 public CrashReportCategory func_85056_g() 218 { 219 return this.field_85061_c; 220 } 221 222 public CrashReportCategory func_85058_a(String par1Str) 223 { 224 return this.func_85057_a(par1Str, 1); 225 } 226 227 public CrashReportCategory func_85057_a(String par1Str, int par2) 228 { 229 CrashReportCategory var3 = new CrashReportCategory(this, par1Str); 230 231 if (this.field_85059_f) 232 { 233 int var4 = var3.func_85073_a(par2); 234 StackTraceElement[] var5 = this.cause.getStackTrace(); 235 StackTraceElement var6 = null; 236 StackTraceElement var7 = null; 237 238 if (var5 != null && var5.length - var4 < var5.length) 239 { 240 var6 = var5[var5.length - var4]; 241 242 if (var5.length + 1 - var4 < var5.length) 243 { 244 var7 = var5[var5.length + 1 - var4]; 245 } 246 } 247 248 this.field_85059_f = var3.func_85069_a(var6, var7); 249 250 if (var4 > 0 && !this.crashReportSections.isEmpty()) 251 { 252 CrashReportCategory var8 = (CrashReportCategory)this.crashReportSections.get(this.crashReportSections.size() - 1); 253 var8.func_85070_b(var4); 254 } 255 else if (var5 != null && var5.length >= var4) 256 { 257 this.field_85060_g = new StackTraceElement[var5.length - var4]; 258 System.arraycopy(var5, 0, this.field_85060_g, 0, this.field_85060_g.length); 259 } 260 else 261 { 262 this.field_85059_f = false; 263 } 264 } 265 266 this.crashReportSections.add(var3); 267 return var3; 268 } 269 270 /** 271 * Gets a random witty comment for inclusion in this CrashReport 272 */ 273 private static String getWittyComment() 274 { 275 String[] var0 = new String[] {"Who set us up the TNT?", "Everything\'s going to plan. No, really, that was supposed to happen.", "Uh... Did I do that?", "Oops.", "Why did you do that?", "I feel sad now :(", "My bad.", "I\'m sorry, Dave.", "I let you down. Sorry :(", "On the bright side, I bought you a teddy bear!", "Daisy, daisy...", "Oh - I know what I did wrong!", "Hey, that tickles! Hehehe!", "I blame Dinnerbone.", "You should try our sister game, Minceraft!", "Don\'t be sad. I\'ll do better next time, I promise!", "Don\'t be sad, have a hug! <3", "I just don\'t know what went wrong :(", "Shall we play a game?", "Quite honestly, I wouldn\'t worry myself about that.", "I bet Cylons wouldn\'t have this problem.", "Sorry :(", "Surprise! Haha. Well, this is awkward.", "Would you like a cupcake?", "Hi. I\'m Minecraft, and I\'m a crashaholic.", "Ooh. Shiny.", "This doesn\'t make any sense!", "Why is it breaking :(", "Don\'t do that.", "Ouch. That hurt :(", "You\'re mean.", "This is a token for 1 free hug. Redeem at your nearest Mojangsta: [~~HUG~~]", "There are four lights!"}; 276 277 try 278 { 279 return var0[(int)(System.nanoTime() % (long)var0.length)]; 280 } 281 catch (Throwable var2) 282 { 283 return "Witty comment unavailable :("; 284 } 285 } 286 287 public static CrashReport func_85055_a(Throwable par0Throwable, String par1Str) 288 { 289 CrashReport var2; 290 291 if (par0Throwable instanceof ReportedException) 292 { 293 var2 = ((ReportedException)par0Throwable).getTheReportedExceptionCrashReport(); 294 } 295 else 296 { 297 var2 = new CrashReport(par1Str, par0Throwable); 298 } 299 300 return var2; 301 } 302 }