Merge pull request #318 from Parabot/development

[RELEASE] Release of V2.8.1
This commit is contained in:
Jeroen Ketelaar
2019-05-22 07:36:28 -05:00
committed by GitHub
22 changed files with 466 additions and 157 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ env:
- secure: UG+b1tEgc8xv9x4r//2OAIK1RrYv6n209KTTFMMwcnAa7DI8HaP8nljRa5/VhDhuKHdlVrYH/tI90v7UVBs0GDVNwK5V17Io0fMm3FUGZekSthTCqqno5wAGa9r6a6mMLtSaSmIFeIKi0+0d2ZwplRuhj/dtEYjjBBj+kK8g4nE=
- secure: St/fecUDInFBCRriYqgp2F8PU9/SooorgxD9Mrs+b0EsC7AbtSsQXvdIv2Lp6xzdQ0VSXPcLIhULPOYrmBKnGQ/NjXTIZXxnroyQxxnI6xyEWIZwiHRY/bKRJDRbQTxD9NL32szKiDSwnw7pu6llF4D64UqQvziq4Gm6VohU75M=
- secure: bD15GVZWowiknbfLavh8CxSh0GsnF5kT4kZ6ggCuUDGyj0mzqf7dNRnchQIKkCG0WRYyTrFN4pEiygeywWsipEeAVv9Xhx3cuUZmzeQaR5KCWabSwJ8gK6jZd1YhcWmM9vrdPHobZr65MP0y/8mu/Fovgky9dY7KDf4G3SebNrM=
- PARABOT_VERSION=2.8
- PARABOT_VERSION=2.8.1
cache:
directories:
+2 -2
View File
@@ -3,7 +3,7 @@
# Parabot
Parabot V2.8
Parabot V2.8.1
#### Links
@@ -42,7 +42,7 @@ Then you'll need to add the dependency:
<dependency>
<groupId>org.parabot</groupId>
<artifactId>client</artifactId>
<version>2.7</version>
<version>2.8.1</version>
</dependency>
</dependencies>
```
+5 -5
View File
@@ -6,7 +6,7 @@
<groupId>org.parabot</groupId>
<artifactId>client</artifactId>
<version>2.8</version>
<version>2.8.1</version>
<packaging>jar</packaging>
@@ -17,7 +17,7 @@
</properties>
<name>Parabot client</name>
<description>The only perfect open source (Runescape private server) bot!</description>
<description>The best open-source (Runescape Private Server) bot</description>
<url>http://www.parabot.org/</url>
<licenses>
@@ -68,7 +68,7 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>provided</scope>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.parabot</groupId>
@@ -191,13 +191,13 @@
<uniqueVersion>false</uniqueVersion>
<id>parabot-maven</id>
<name>Custom Maven Repository</name>
<url>ftp://maven.parabot.org</url>
<url>ftp://maven.parabot.org/public_html</url>
<layout>default</layout>
</repository>
<site>
<id>parabot-maven</id>
<name>Frontend Parabot Maven</name>
<url>ftp://maven.parabot.org/docs/${artifactId}/</url>
<url>ftp://maven.parabot.org/public_html/docs/${artifactId}/</url>
</site>
</distributionManagement>
+12 -17
View File
@@ -11,32 +11,31 @@ import org.parabot.core.network.proxy.ProxyType;
import org.parabot.core.ui.BotUI;
import org.parabot.core.ui.ServerSelector;
import org.parabot.core.ui.utils.UILog;
import org.parabot.environment.handlers.exceptions.ExceptionHandler;
import org.parabot.environment.handlers.exceptions.FileExceptionHandler;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
/**
* Parabot v2.7
*
* @author Everel, JKetelaar, Matt, Dane
* @version 2.7
* @see <a href="http://www.parabot.org">Homepage</a>
* @version 2.8.1
* @see <a href="https://www.parabot.org">Homepage</a>
*/
public final class Landing {
private static String username;
private static String password;
public static void main(String... args) throws IOException {
public static void main(String... args) {
// Thread.setDefaultUncaughtExceptionHandler(new FileExceptionHandler(ExceptionHandler.ExceptionType.CLIENT));
if (Context.getJavaVersion() >= 9) {
UILog.log("Parabot", "Parabot doesn't support Java 9+ currently. Please downgrade to Java 8 to ensure Parabot is working correctly.");
System.exit(0);
}
if (!System.getProperty("os.arch").contains("64")) {
UILog.log("Parabot", "You are not running a 64-bit version of Java, this might cause the client to lag or crash unexpectedly.\r\n" +
"It's recommended to upgrade to a 64-bit version.");
"It is recommended to upgrade to a 64-bit version.");
}
parseArgs(args);
@@ -80,11 +79,11 @@ public final class Landing {
switch (arg.toLowerCase()) {
case "-createdirs":
Directories.validate();
System.out
.println(TranslationHelper.translate(("DIRECTORIES_CREATED")));
System.out.println(TranslationHelper.translate(("DIRECTORIES_CREATED")));
System.exit(0);
break;
case "-debug":
Core.setDump(true);
case "-offlinemode":
Core.setDebug(true);
break;
@@ -130,14 +129,9 @@ public final class Landing {
break;
case "-proxy":
ProxyType type = ProxyType.valueOf(args[++i].toUpperCase());
if (type == null) {
System.err.println(TranslationHelper.translate("INVALID_PROXY_TYPE") + args[i]);
System.exit(1);
return;
}
ProxySocket.setProxy(type, args[++i],
Integer.parseInt(args[++i]));
ProxySocket.setProxy(type, args[++i], Integer.parseInt(args[++i]));
break;
case "-proxy_auth":
case "-auth":
ProxySocket.auth = true;
ProxySocket.setLogin(args[++i], args[++i]);
@@ -146,6 +140,7 @@ public final class Landing {
Core.disableSec();
break;
case "-no_validation":
case "-ignore_updates":
Core.disableValidation();
break;
case "-uuid":
+56 -46
View File
@@ -140,46 +140,13 @@ public class Core {
}
/**
* Checks the version of the bot using a checksum of the jar comparison against checksum given by the website
* Prints a debug line to the Logger and System PrintStream
* Meant for the debug adapter within hooks
*
* @return <b>true</b> if no new version is found, otherwise <b>false</b>.
* @param line
*/
private static boolean checksumValid() {
File f = new File(Landing.class.getProtectionDomain().getCodeSource().getLocation().getFile());
if (f.isFile()) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
File location = new File(Landing.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
if (location.exists()) {
FileInputStream fis = new FileInputStream(location);
byte[] dataBytes = new byte[1024];
int nread;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
byte[] mdbytes = md.digest();
StringBuilder sb = new StringBuilder("");
for (byte mdbyte : mdbytes) {
sb.append(Integer.toString((mdbyte & 0xff) + 0x100, 16).substring(1));
}
String result;
if ((result = WebUtil.getContents(String.format(Configuration.COMPARE_CHECKSUM_URL, "client", currentVersion.get()), "checksum=" + URLEncoder.encode(sb.toString(), "UTF-8"))) != null) {
JSONObject object = (JSONObject) WebUtil.getJsonParser().parse(result);
boolean upToDate = (boolean) object.get("result");
Core.verbose("Local checksum: " + URLEncoder.encode(sb.toString(), "UTF-8") + ". " + (upToDate ? "This matches BDN and is up to date." : "BDN mismatch, must be Out Of Date."));
return upToDate;
}
}
} catch (NoSuchAlgorithmException | ParseException | IOException | URISyntaxException e) {
e.printStackTrace();
}
}
return true;
public static void debug(final String line) {
System.out.println(line);
}
/**
@@ -216,14 +183,6 @@ public class Core {
return true;
}
/**
* Method that removes the cache contents after 3 days
*/
private static void validateCache() {
// Already handled by Directories initiating
// Method will be used once BDN V3 has a functionality for this
}
public static void downloadNewVersion() {
UILog.log(TranslationHelper.translate("UPDATES"),
TranslationHelper.translate("DOWNLOAD_UPDATE_PARABOT_AT")
@@ -268,4 +227,55 @@ public class Core {
public static int newVersionAlert() {
return UILog.alert("Parabot Update", "There's a new version of Parabot! \nDo you wish to download it?\n\nThe current version could have some problems!", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
}
/**
* Checks the version of the bot using a checksum of the jar comparison against checksum given by the website
*
* @return <b>true</b> if no new version is found, otherwise <b>false</b>.
*/
private static boolean checksumValid() {
File f = new File(Landing.class.getProtectionDomain().getCodeSource().getLocation().getFile());
if (f.isFile()) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
File location = new File(Landing.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
if (location.exists()) {
FileInputStream fis = new FileInputStream(location);
byte[] dataBytes = new byte[1024];
int nread;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
byte[] mdbytes = md.digest();
StringBuilder sb = new StringBuilder("");
for (byte mdbyte : mdbytes) {
sb.append(Integer.toString((mdbyte & 0xff) + 0x100, 16).substring(1));
}
String result;
if ((result = WebUtil.getContents(String.format(Configuration.COMPARE_CHECKSUM_URL, "client", currentVersion.get()), "checksum=" + URLEncoder.encode(sb.toString(), "UTF-8"))) != null) {
JSONObject object = (JSONObject) WebUtil.getJsonParser().parse(result);
boolean upToDate = (boolean) object.get("result");
Core.verbose("Local checksum: " + URLEncoder.encode(sb.toString(), "UTF-8") + ". " + (upToDate ? "This matches BDN and is up to date." : "BDN mismatch, must be Out Of Date."));
return upToDate;
}
}
} catch (NoSuchAlgorithmException | ParseException | IOException | URISyntaxException e) {
e.printStackTrace();
}
}
return true;
}
/**
* Method that removes the cache contents after 3 days
*/
private static void validateCache() {
// Already handled by Directories initiating
// Method will be used once BDN V3 has a functionality for this
}
}
@@ -57,7 +57,7 @@ public class AddCallbackAdapter implements Injectable, Opcodes {
}
inject.add(new MethodInsnNode(INVOKESTATIC,
this.invokeClass, this.invokeMethod,
this.desc));
this.desc, false));
if (this.conditional) {
LabelNode ln = new LabelNode(new Label());
inject.add(new JumpInsnNode(IFEQ, ln));
@@ -25,8 +25,13 @@ public class AddDebugAdapter {
String callString = owner.name + "." + mn.name + " " + mn.desc;
LdcInsnNode ldc = new LdcInsnNode(callString);
MethodInsnNode methodNode = new MethodInsnNode(Opcodes.INVOKESTATIC, "org/parabot/core/Core", "debug",
"(Ljava/lang/String;)V");
MethodInsnNode methodNode = new MethodInsnNode(
Opcodes.INVOKESTATIC,
"org/parabot/core/Core",
"debug",
"(Ljava/lang/String;)V",
false
);
inject.add(ldc);
inject.add(methodNode);
@@ -94,9 +94,9 @@ public class AddInvokerAdapter implements Opcodes, Injectable {
}
if (isInterface) {
m.visitMethodInsn(INVOKEINTERFACE, instanceCast, mName, mDesc);
m.visitMethodInsn(INVOKEINTERFACE, instanceCast, mName, mDesc, true);
} else {
m.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL, methodLocation.name, mn.name, mn.desc);
m.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL, methodLocation.name, mn.name, mn.desc, false);
}
if (this.returnDesc.contains("L")) {
if (!this.returnDesc.contains("[")) {
@@ -23,11 +23,23 @@ public class SystemRedirect {
System.exit(i);
}
private static String getClassPath(){
String classPath = System.getProperty("java.class.path");
StringBuilder finalClassPath = new StringBuilder();
for (String path : classPath.split(":")) {
if (!path.toLowerCase().contains("parabot")) {
finalClassPath.append(path).append(":");
}
}
return finalClassPath.toString();
}
public static String getProperty(String s) {
String value;
switch (s) {
case "java.class.path":
value = ".";
value = getClassPath();
break;
default:
value = System.getProperty(s);
@@ -42,14 +54,14 @@ public class SystemRedirect {
String value = null;
switch (s2) {
case "java.class.path":
value = ".";
value = getClassPath();
break;
}
if (value == null) {
switch (s) {
case "java.class.path":
value = ".";
value = getClassPath();
break;
default:
value = System.getProperty(s);
@@ -18,9 +18,10 @@ public abstract class ScriptParser {
public static final Map<ScriptDescription, ScriptExecuter> SCRIPT_CACHE = new HashMap<>();
private static final ArrayList<ScriptParser> parsers = new ArrayList<>();
public static ScriptDescription[] getDescriptions() {
SCRIPT_CACHE.clear();
final ArrayList<ScriptParser> parsers = new ArrayList<>();
if (Core.inLoadLocal()) {
parsers.add(new LocalJavaScripts());
parsers.add(new BDNScripts());
@@ -47,6 +48,9 @@ public abstract class ScriptParser {
return SORTED_SCRIPT_CACHE.keySet().toArray(new ScriptDescription[SORTED_SCRIPT_CACHE.size()]);
}
public abstract void execute();
public static final void addParser(ScriptParser parser) {
parsers.add(parser);
}
public abstract void execute();
}
@@ -240,12 +240,24 @@ public class ReflectUI extends JFrame {
builder.append("<b>Static: </b>").append(refField.isStatic() ? "yes" : "no").append("<br/>");
builder.append("<b>Array: </b>").append(refField.isArray() ? refField.getArrayDimensions() + " dimension(s)" : "no").append("<br/>");
if (refField.isArray() && refField.getASMType().getClassName().contains("String") && refField.getArrayDimensions() == 1) {
if (refField.isArray()) {
if (refField.getArrayDimensions() == 1) {
if (refField.getASMType().getClassName().contains("int")) {
int[] ints = (int[]) refField.asObject();
String values = "";
for (int i = 0; i < ints.length; i++) {
values += (ints[i] + (i < ints.length - 1 ? ", " : ""));
}
builder.append("<b>Values: </b>").append(values).append("<br/>");
} else if (refField.getASMType().getClassName().contains("String")) {
String[] strings = (String[]) refField.asObject();
String values = StringUtils.implode(", ", strings);
builder.append("<b>Values: </b>").append(values).append("<br/>");
}
}
}
selectionInfoPane.setText(builder.toString());
fillBasicInfoPane();
@@ -163,15 +163,8 @@ public final class ScriptSelector extends JFrame {
@Override
public void actionPerformed(ActionEvent e) {
String s = getScriptName(tree.getSelectionPath().toString());
if (s != null) {
try {
WebUtil.getContents("http://bdn.parabot.org/api/v2/scripts/local", "script=" + URLEncoder.encode(s, "UTF-8") + "&username=" + URLEncoder.encode(Context.getUsername(), "UTF-8"));
} catch (MalformedURLException | UnsupportedEncodingException e1) {
e1.printStackTrace();
}
runScript(format.get(s));
}
}
});
JButton cmdHome = new JButton("Open home");
@@ -39,4 +39,9 @@ public class UILog {
return JOptionPane.showOptionDialog(null, message, title,
JOptionPane.YES_NO_CANCEL_OPTION, messageType, null, options, null);
}
public static int alert(final String title, final String message, Object[] options, int initialValue, int messageType) {
return JOptionPane.showOptionDialog(null, message, title,
JOptionPane.YES_NO_CANCEL_OPTION, messageType, null, options, initialValue);
}
}
@@ -0,0 +1,88 @@
package org.parabot.environment.handlers.exceptions;
/**
* Class to be implemented that allows multiple types of exception handlers
*/
public abstract class ExceptionHandler implements Thread.UncaughtExceptionHandler {
/**
* The name of the exception handler
*/
private final String name;
/**
* The status of the exception handler; Defines if the exception handler is enabled or disabled
*/
private boolean enabled = true;
/**
* The type the handler is meant for
*/
private ExceptionType exceptionType;
public ExceptionHandler(String name, ExceptionType exceptionType) {
this.name = name;
this.exceptionType = exceptionType;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
this.handle(e);
}
/**
* Writes the exception to class extending this abstract class
*
* @param e
*/
public abstract void handle(Throwable e);
/**
* Returns if the exception handler is enabled or disabled
*
* @return
*/
public boolean isEnabled() {
return enabled;
}
/**
* Sets the enabled status of the exception handler
*
* @param enabled
*
* @return
*/
public ExceptionHandler setEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}
public ExceptionType getExceptionType() {
return exceptionType;
}
public ExceptionHandler setExceptionType(ExceptionType exceptionType) {
this.exceptionType = exceptionType;
return this;
}
public String getName() {
return name;
}
public enum ExceptionType {
SERVER("Server"),
SCRIPT("Script"),
CLIENT("Client");
private String name;
ExceptionType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
@@ -0,0 +1,139 @@
package org.parabot.environment.handlers.exceptions;
import org.parabot.core.Directories;
import org.parabot.core.ui.utils.UILog;
import org.parabot.environment.api.utils.FileUtil;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
/**
* Writes exceptions to a file and reports the file location back to the user
*/
public class FileExceptionHandler extends ExceptionHandler {
/**
* The default index of all options to be selected when the popup appears
*/
private static final int defaultOptionIndex = 1;
/**
* Directory where the reports get written to
*/
private final File reportsDirectory;
/**
* All possible options to select when the popup appears
*/
private final Object[] options = new Object[]{
"Close",
"Open report",
"Ignore " + this.getExceptionType().getName().toLowerCase() + " errors" };
/**
* Defines if the alert should popup during this client instance again
*/
private boolean ignored = false;
/**
* Initializes the exception handler and ensures the reports directory is created and writable
*/
public FileExceptionHandler(ExceptionType exceptionType) {
super("File exception handler", exceptionType);
this.reportsDirectory = new File(Directories.getWorkspace(), "reports");
if (!this.reportsDirectory.exists() || !this.reportsDirectory.isDirectory()) {
this.reportsDirectory.mkdir();
}
this.cleanOldErrors();
}
@Override
public void handle(Throwable e) {
File report = new File(this.reportsDirectory, "report-" + this.getExceptionType().getName().toLowerCase() + "-" + (System.currentTimeMillis() / 1000) + ".txt");
try {
report.createNewFile();
StringBuilder reportContent = new StringBuilder();
reportContent.append("Message: ").append(e.getMessage()).append("\n\n");
reportContent.append(e.toString()).append("\n\n");
for (int i = 0; i < e.getStackTrace().length; i++) {
if (i > 0) {
reportContent.append("\t");
}
reportContent.append(e.getStackTrace()[i]).append("\n");
}
FileUtil.writeFileContents(report, reportContent.toString());
if (!ignored) {
displayAlert(report);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public boolean isIgnored() {
return ignored;
}
public FileExceptionHandler setIgnored(boolean ignored) {
this.ignored = ignored;
return this;
}
public File getReportsDirectory() {
return reportsDirectory;
}
/**
* Displays the dialog of the alert
*
* @param report
*/
private void displayAlert(File report) {
int response = UILog.alert(
"Error occurred",
"We are sorry to inform you that an error occurred within Parabot.\n\n" +
"The error has been written to a report file.\n" +
"Please report the error to the Parabot staff with as much information as possible.",
this.options,
defaultOptionIndex,
JOptionPane.WARNING_MESSAGE
);
switch (response) {
case 1:
try {
Desktop.getDesktop().open(report);
} catch (Exception ex) {
ex.printStackTrace();
}
break;
case 2:
ignored = true;
break;
}
}
/**
* Remove errors older than 24 hours
*/
private void cleanOldErrors() {
File[] reports = this.reportsDirectory.listFiles();
if (reports != null) {
for (File report : reports) {
if (report.isFile()) {
if ((System.currentTimeMillis() - report.lastModified()) / 1000 > 60 * 60 * 24) {
report.delete();
}
}
}
}
}
}
@@ -95,14 +95,15 @@ public abstract class ServerProvider implements Opcodes {
if (!crashed) {
Injectable inj = injectables[index];
int resp = UILog.alert("Outdated client", "This server currently has outdated hooks, please report it to a member of the Parabot staff.\r\n\r\n" +
int resp = UILog.alert("Outdated client", "This server currently has outdated hooks, please report it to the Parabot staff.\r\n\r\n" +
"Broken hook:\r\n" + inj, new Object[]{ "Close", "Report here..." }, JOptionPane.ERROR_MESSAGE);
if (resp == 1) {
URI uri = URI.create(Configuration.COMMUNITY_PAGE + "forum/135-reports/");
try {
Desktop.getDesktop().browse(uri);
} catch (IOException ignore) {}
} catch (IOException ignore) {
}
}
}
crashed = true;
@@ -112,20 +113,6 @@ public abstract class ServerProvider implements Opcodes {
Context.getInstance().setHookParser(parser);
}
private HookFile fetchHookFile() {
HookFile hookFile = getHookFile();
if (hookFile != null) {
return hookFile;
}
URL hookLocation = getHooks();
if (hookLocation == null) {
return null;
}
return new HookFile(hookLocation, HookFile.TYPE_XML);
}
/**
* Add custom items to the bot menu bar
*
@@ -191,4 +178,18 @@ public abstract class ServerProvider implements Opcodes {
}
private HookFile fetchHookFile() {
HookFile hookFile = getHookFile();
if (hookFile != null) {
return hookFile;
}
URL hookLocation = getHooks();
if (hookLocation == null) {
return null;
}
return new HookFile(hookLocation, HookFile.TYPE_XML);
}
}
@@ -36,10 +36,9 @@ public class PublicServerExecuter extends ServerExecuter {
}
};
private String serverName;
private PBLocalPreferences settings;
private final String cacheVersionKey = "cachedProviderVersion";
private String serverName;
private PBLocalPreferences settings;
public PublicServerExecuter(final String serverName) {
this.serverName = serverName;
@@ -3,6 +3,8 @@ package org.parabot.environment.servers.executers;
import org.parabot.core.Context;
import org.parabot.core.ui.BotUI;
import org.parabot.core.ui.components.PaintComponent;
import org.parabot.environment.handlers.exceptions.ExceptionHandler;
import org.parabot.environment.handlers.exceptions.FileExceptionHandler;
import org.parabot.environment.servers.ServerProvider;
/**
@@ -15,7 +17,7 @@ public abstract class ServerExecuter {
public abstract void run();
public void finalize(final ServerProvider provider, final String serverName) {
new Thread(new Runnable() {
Thread serverThread = new Thread(new Runnable() {
@Override
public void run() {
try {
@@ -30,7 +32,11 @@ public abstract class ServerExecuter {
t.printStackTrace();
}
}
}).start();
});
serverThread.setUncaughtExceptionHandler(new FileExceptionHandler(ExceptionHandler.ExceptionType.SERVER));
serverThread.start();
}
}
@@ -29,8 +29,9 @@ public class ServerLoader extends ASMClassLoader {
public final String[] getServerClassNames() {
final List<String> classNames = new ArrayList<String>();
for (ClassNode c : classPath.classes.values()) {
if (c.superName.replace('/', '.').equals(
ServerProvider.class.getName())) {
if (c.superName
.replace('/', '.')
.equals(ServerProvider.class.getName())) {
classNames.add(c.name.replace('/', '.'));
}
}
@@ -0,0 +1,39 @@
package org.parabot;
import org.junit.Test;
import org.parabot.environment.handlers.exceptions.ExceptionHandler;
import org.parabot.environment.handlers.exceptions.FileExceptionHandler;
public class FileExceptionHandlerTest {
@Test
public void manualTest() {
FileExceptionHandler handler = new FileExceptionHandler(ExceptionHandler.ExceptionType.CLIENT);
handler.setIgnored(true);
Exception exception = new NullPointerException("Manual test");
handler.handle(exception);
}
@Test
public void threadHandlerTest() {
FileExceptionHandler handler = new FileExceptionHandler(ExceptionHandler.ExceptionType.CLIENT);
handler.setIgnored(true);
Thread thread = new Thread() {
@Override
public void run() throws NullPointerException {
throw new NullPointerException("Thread test");
}
};
thread.setUncaughtExceptionHandler(handler);
thread.start();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}