1 package com.ranfa.lib.handler;
3 import java.lang.management.ManagementFactory;
4 import java.lang.management.MemoryMXBean;
5 import java.lang.management.MemoryUsage;
6 import java.lang.management.OperatingSystemMXBean;
7 import java.lang.management.RuntimeMXBean;
8 import java.text.SimpleDateFormat;
10 import java.util.Random;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
15 import com.ranfa.lib.CheckVersion;
17 public class CrashHandler {
20 private final Logger LOG = LoggerFactory.getLogger(CrashHandler.class);
24 private String description;
25 private int estimateExitCode;
26 private CrashReportList<String> crashReportLines = new CrashReportList<>();
27 private Random random = new Random(System.currentTimeMillis());
31 private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yy/MM/dd HH:mm");
32 private static final String DEFAULT_DESCRIPTION = "Unexpected Error";
33 private static final String[] EASTER_LINES = {
34 "// It will need to do more test?",
35 "// I may be so bad to code?",
36 "// Shimamura Uzuki, I'll do my best!",
37 "// This is also adventure!, isn't it?",
38 "// I... leave all books... behind... 'cause I want to talk... with you...",
39 "// This software was developed by @hizumiaoba",
40 "// These Easter sentences were inspired by Minecraft Crash Report!"
43 public CrashHandler() {
44 this(DEFAULT_DESCRIPTION);
47 public CrashHandler(String m) {
51 public CrashHandler(Throwable e) {
52 this(DEFAULT_DESCRIPTION, e);
55 public CrashHandler(String description, Throwable e) {
56 LOG.warn("Unexpected Exception has occured. : {}", e == null ? "null" : e.toString());
57 LOG.warn("Provided Detail Message : {}", description);
59 this.description = description;
60 estimateExitCode = Integer.MIN_VALUE;
61 crashReportLines.add("---- DelesteRandomSelector Crash Report ----");
62 int randomInt = random.nextInt(EASTER_LINES.length);
63 crashReportLines.add(EASTER_LINES[randomInt]);
66 public void execute() {
68 throw new NullPointerException("Cannot execute crash because throwable is null.");
69 LOG.error("Cannot keep up application! : {}", e.toString());
70 LOG.error(outputReport());
71 System.exit(estimateExitCode);
74 private String outputReport() {
75 crashReportLines.emptyLine();
76 crashReportLines.add("Time: " + FORMAT.format(new Date()));
77 crashReportLines.add("Description: " + description);
78 crashReportLines.emptyLine();
79 LOG.debug("Gathering exception informations.");
81 crashReportLines.add("These are simplified stack trace. (shown up to 5 lines. Full Stack trace is below.)");
82 crashReportLines.add(e.toString());
83 StackTraceElement[] topElements = e.getStackTrace();
84 for(int i = 0; i < 5; i++) {
85 crashReportLines.add("\tat " + topElements[i].toString());
87 crashReportLines.emptyLine();
88 crashReportLines.add("A detailed walkthrough of the error, its code path and all known details is as follows:");
89 crashReportLines.add("---------------------------------------------------------------------------------------");
90 crashReportLines.emptyLine();
91 crashReportLines.add("Stacktrace:");
92 addLinesRecursively(e, crashReportLines);
94 LOG.debug("Gathering system informations.");
95 RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
96 OperatingSystemMXBean operatingBean = ManagementFactory.getOperatingSystemMXBean();
97 MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
98 MemoryUsage memUsage = memoryBean.getHeapMemoryUsage();
99 crashReportLines.emptyLine();
100 crashReportLines.add("-- System Details --");
101 crashReportLines.add("Details:");
102 crashReportLines.add("\tDelesteRandomSelector Version: " + CheckVersion.getVersion());
103 crashReportLines.add("\tOperating System: "
104 + operatingBean.getName() + " ("
105 + operatingBean.getArch() + ") version "
106 + operatingBean.getVersion());
107 crashReportLines.add("\tJava Version: " + runtimeBean.getSpecVersion() + ", " + runtimeBean.getVmVendor());
108 crashReportLines.add("\tJava VM Version: " + runtimeBean.getVmName() + ", version " + runtimeBean.getVmVersion());
109 crashReportLines.add("\tMemory: " + memUsage.getUsed() + " bytes / " + memUsage.getInit() + " bytes up to " + memUsage.getMax() + " bytes");
110 crashReportLines.add("\tJVM Flags: " + runtimeBean.getInputArguments().size() + " total: " + runtimeBean.getInputArguments().toString());
111 return crashReportLines.generateCrashReport();
114 public String outSystemInfo() {
117 this.description = "Loading screen debug info\n"
119 + "This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR";
120 String res = outputReport();
125 public static CrashReportList<String> addLinesRecursively(Throwable e, CrashReportList<String> list) {
128 StackTraceElement[] elements = e.getStackTrace();
129 for(StackTraceElement element : elements) {
130 list.add("\tat " + element.toString());
132 if(e.getCause() != null) {
133 list.add("Caused by: " + e.getCause().toString());
134 addLinesRecursively(e.getCause(), list);
139 public String getDescription() {
143 public Throwable getThrowable() {
147 public int getEstimateExitCode() {
148 return estimateExitCode;