package com.vitco.manager.error;
import com.vitco.layout.content.console.ConsoleInterface;
import com.vitco.settings.VitcoSettings;
import com.vitco.util.misc.DateTools;
import com.vitco.manager.lang.LangSelectorInterface;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.URLDecoder;
/**
* Deals with all the exceptions in the program. Writes them to file and tries to upload
* them to a server.
*/
public class ErrorHandler implements ErrorHandlerInterface {
// var & setter
private ConsoleInterface console;
@Override
public final void setConsole(ConsoleInterface console) {
this.console = console;
initOutMapping();
}
private void initOutMapping() {
if (!debug) {
// write error to console
try {
System.setErr(new PrintStream(new OutputStream() {
private String buffer = "";
@Override
public void write(int arg0) throws IOException {
if (((char)arg0) == '\n') {
console.addLine(buffer);
buffer = "";
} else {
buffer += (char)arg0;
}
}
}, true, "utf-8"));
} catch (UnsupportedEncodingException e) {
this.handle(e);
}
// write out to console
try {
System.setOut(new PrintStream(new OutputStream() {
private String buffer = "";
@Override
public void write(int arg0) throws IOException {
if (((char)arg0) == '\n') {
console.addLine(buffer);
buffer = "";
} else {
buffer += (char)arg0;
}
}
}, true, "utf-8"));
} catch (UnsupportedEncodingException e) {
this.handle(e);
}
}
}
// var & setter
private String debugReportUrl;
@Override
public final void setDebugReportUrl(String debugReportUrl) {
this.debugReportUrl = debugReportUrl;
}
// to check if we are in debug mode
private static boolean debug = false;
public static void setDebugMode() {
ErrorHandler.debug = true;
}
// var & setter
private LangSelectorInterface langSelector;
@Override
public final void setLangSelector(LangSelectorInterface langSelector) {
this.langSelector = langSelector;
}
private long lastErrorReport = 0;
private final static long error_spam_timeout = 2*60*1000; // 2 minutes
// handle exceptions
@Override
public void handle(Throwable e) {
synchronized (VitcoSettings.SYNC) {
if (debug) {
// print the trace (debug)
e.printStackTrace();
} else {
if (lastErrorReport + error_spam_timeout < System.currentTimeMillis()) {
lastErrorReport = System.currentTimeMillis();
Toolkit.getDefaultToolkit().beep(); // play beep
boolean result = false;
// print this error to file
String path = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
try {
String appJarLocation = URLDecoder.decode(path, "UTF-8");
File appJar = new File(appJarLocation);
String absolutePath = appJar.getAbsolutePath();
String filePath = absolutePath.
substring(0, absolutePath.lastIndexOf(File.separator) + 1);
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(filePath + "errorlog.txt", true),"UTF-8")));
out.println("===================");
out.println(DateTools.now("yyyy-MM-dd HH-mm-ss"));
out.println("-------------------");
e.printStackTrace(out);
out.println();
out.close();
} catch (UnsupportedEncodingException ex) {
// If this fails, the program is not reporting.
if (debug) {
ex.printStackTrace();
}
} catch (IOException ex) {
// If this fails, the program is not reporting.
if (debug) {
ex.printStackTrace();
}
}
// show dialog
if (JOptionPane.showOptionDialog(null, langSelector.getString("error_dialog_text"),
langSelector.getString("error_dialog_caption"),
JOptionPane.YES_NO_OPTION,
JOptionPane.ERROR_MESSAGE,
null,
new String[]{langSelector.getString("error_dialog_clc_yes"),
langSelector.getString("error_dialog_clc_no")},
0) == JOptionPane.YES_OPTION
) {
try {
// write temporary file with stack-trace
File temp = File.createTempFile("PS4k_" + DateTools.now("yyyy-MM-dd_HH-mm-ss_"), ".error");
temp.deleteOnExit();
PrintStream ps = new PrintStream(temp, "utf-8");
e.printStackTrace(ps);
// upload to server
if (uploadFile(temp, e.getMessage())) {
result = true;
}
} catch (FileNotFoundException e1) {
if (debug) {
e1.printStackTrace();
}
} catch (IOException e1) {
if (debug) {
e1.printStackTrace();
}
}
}
if (!result) {
console.addLine(langSelector.getString("error_dialog_upload_failed"));
console.addLine(langSelector.getString("error_dialog_request_upload_manually"));
} else {
console.addLine(langSelector.getString("error_dialog_upload_ok"));
}
}
}
}
}
// upload file to server
private boolean uploadFile(File temp, String error) {
boolean result = false;
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(debugReportUrl);
try {
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("error", new StringBody(error));
reqEntity.addPart("report", new FileBody(temp));
httpPost.setEntity(reqEntity);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
// do something useful with the response body
if (EntityUtils.toString(entity).equals("1")) {
// upload was successful
result = true;
}
// and ensure it is fully consumed
EntityUtils.consume(entity);
} catch (IOException e) {
// If this fails, the program is not reporting.
if (debug) {
e.printStackTrace();
}
} finally {
httpPost.releaseConnection();
}
return result;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
try {
handle(e);
} catch (Exception ex) {
// makes sure there will never be a loop!
}
}
}