OSDN Git Service

fix: fix crash feature
[delesterandomselector/DelesteRandomSelector.git] / src / com / ranfa / lib / handler / CrashHandler.java
1 package com.ranfa.lib.handler;
2
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;
9 import java.util.Date;
10 import java.util.Random;
11
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
14
15 import com.ranfa.lib.CheckVersion;
16
17 public class CrashHandler {
18
19         // Logger
20                 private final Logger LOG = LoggerFactory.getLogger(CrashHandler.class);
21                 
22                 // fields
23                 private Throwable e;
24                 private String description;
25                 private int estimateExitCode;
26                 private CrashReportList<String> crashReportLines = new CrashReportList<>();
27                 private Random random = new Random(System.currentTimeMillis());
28                 
29                 
30                 // constants
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!"
41                 };
42                 
43                 public CrashHandler() {
44                         this(DEFAULT_DESCRIPTION);
45                 }
46                 
47                 public CrashHandler(String m) {
48                         this(m, null);
49                 }
50                 
51                 public CrashHandler(Throwable e) {
52                         this(DEFAULT_DESCRIPTION, e);
53                 }
54                 
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);
58                         this.e = e;
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]);
64                 }
65                 
66                 public void execute() {
67                         if(e == null)
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);
72                 }
73                 
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.");
80                         if(e != null) {
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());
86                                 }
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);
93                         }
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();
112                 }
113                 
114                 public String outSystemInfo() {
115                         // Override fields
116                         this.e = null;
117                         this.description = "Loading screen debug info\n"
118                                         + "\n"
119                                         + "This is just a prompt for computer specs to be printed. THIS IS NOT A ERROR";
120                         String res = outputReport();
121                         LOG.info(res);
122                         return res;
123                 }
124                 
125                 public static CrashReportList<String> addLinesRecursively(Throwable e, CrashReportList<String> list) {
126                         if(e == null)
127                                 return list;
128                         StackTraceElement[] elements = e.getStackTrace();
129                         for(StackTraceElement element : elements) {
130                                 list.add("\tat " + element.toString());
131                         }
132                         if(e.getCause() != null) {
133                                 list.add("Caused by: " + e.getCause().toString());
134                                 addLinesRecursively(e.getCause(), list);
135                         }
136                         return list;
137                 }
138                 
139                 public String getDescription() {
140                         return description;
141                 }
142                 
143                 public Throwable getThrowable() {
144                         return e;
145                 }
146                 
147                 public int getEstimateExitCode() {
148                         return estimateExitCode;
149                 }
150 }