| 1 | package com.jsql.util; | |
| 2 | ||
| 3 | import com.jsql.model.InjectionModel; | |
| 4 | import com.jsql.util.bruter.Coder; | |
| 5 | import com.jsql.util.bruter.HashUtil; | |
| 6 | import org.apache.commons.lang3.exception.ExceptionUtils; | |
| 7 | import org.apache.logging.log4j.Level; | |
| 8 | import org.apache.logging.log4j.LogManager; | |
| 9 | import org.apache.logging.log4j.Logger; | |
| 10 | ||
| 11 | import javax.swing.*; | |
| 12 | import java.lang.reflect.InvocationTargetException; | |
| 13 | import java.nio.charset.StandardCharsets; | |
| 14 | import java.security.MessageDigest; | |
| 15 | import java.security.NoSuchAlgorithmException; | |
| 16 | import java.util.Set; | |
| 17 | import java.util.concurrent.CopyOnWriteArraySet; | |
| 18 | ||
| 19 | /** | |
| 20 | * Utility class managing exception reporting to GitHub. | |
| 21 | */ | |
| 22 | public class ExceptionUtil { | |
| 23 | | |
| 24 | private static final Logger LOGGER = LogManager.getRootLogger(); | |
| 25 | | |
| 26 | private final InjectionModel injectionModel; | |
| 27 | | |
| 28 | private final Set<String> exceptionsMd5Cached = new CopyOnWriteArraySet<>(); | |
| 29 | | |
| 30 | public ExceptionUtil(InjectionModel injectionModel) { | |
| 31 | this.injectionModel = injectionModel; | |
| 32 | } | |
| 33 | | |
| 34 | /** | |
| 35 | * Handler class processing errors on top of the JVM in order to send | |
| 36 | * a report to GitHub automatically. | |
| 37 | */ | |
| 38 | public class ExceptionHandler implements Thread.UncaughtExceptionHandler { | |
| 39 | ||
| 40 | @Override | |
| 41 | public void uncaughtException(Thread thread, Throwable throwable) { | |
| 42 | LOGGER.log( | |
| 43 | LogLevelUtil.CONSOLE_JAVA, | |
| 44 |
1
1. lambda$uncaughtException$0 : replaced return value with null for com/jsql/util/ExceptionUtil$ExceptionHandler::lambda$uncaughtException$0 → NO_COVERAGE |
() -> String.format("Unhandled Exception on %s", thread.getName()), |
| 45 | throwable | |
| 46 | ); | |
| 47 | LOGGER.log( // Display to stdout | |
| 48 | Level.ERROR, | |
| 49 |
1
1. lambda$uncaughtException$1 : replaced return value with null for com/jsql/util/ExceptionUtil$ExceptionHandler::lambda$uncaughtException$1 → NO_COVERAGE |
() -> String.format("Unhandled Exception on %s", thread.getName()), |
| 50 | throwable | |
| 51 | ); | |
| 52 | ||
| 53 | // Report #214: ignore if OutOfMemoryError: Java heap space | |
| 54 | if ( | |
| 55 |
1
1. uncaughtException : negated conditional → NO_COVERAGE |
ExceptionUtil.this.injectionModel.getMediatorUtils().getPreferencesUtil().isReportingBugs() |
| 56 |
2
1. uncaughtException : negated conditional → NO_COVERAGE 2. uncaughtException : negated conditional → NO_COVERAGE |
&& ExceptionUtils.getStackTrace(throwable).contains("com.jsql") |
| 57 | && !(throwable instanceof OutOfMemoryError) | |
| 58 |
1
1. uncaughtException : negated conditional → NO_COVERAGE |
&& !ExceptionUtils.getStackTrace(throwable).contains("OutOfMemoryError") // when implicit |
| 59 | ) { | |
| 60 |
1
1. uncaughtException : negated conditional → NO_COVERAGE |
if (ExceptionUtils.getStackTrace(throwable).contains("Could not initialize class java.awt.Toolkit")) { |
| 61 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, "System libraries are missing, please use a proper Java runtime instead of headless runtime"); | |
| 62 | return; | |
| 63 |
1
1. uncaughtException : negated conditional → NO_COVERAGE |
} else if (ExceptionUtils.getStackTrace(throwable).contains("Could not initialize class sun.awt.X11.XToolkit")) { |
| 64 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, "System libraries are missing or wrong DISPLAY variable, please verify your settings"); | |
| 65 | return; | |
| 66 | } | |
| 67 | ||
| 68 | try { | |
| 69 | var messageDigest = MessageDigest.getInstance(Coder.MD5.label); | |
| 70 | ||
| 71 | String stackTrace = ExceptionUtils.getStackTrace(throwable).trim(); | |
| 72 | var passwordString = String.valueOf(stackTrace.toCharArray()); | |
| 73 | ||
| 74 | byte[] passwordByte = passwordString.getBytes(StandardCharsets.UTF_8); | |
| 75 |
1
1. uncaughtException : removed call to java/security/MessageDigest::update → NO_COVERAGE |
messageDigest.update(passwordByte, 0, passwordByte.length); |
| 76 | ||
| 77 | byte[] encodedPassword = messageDigest.digest(); | |
| 78 | var md5Exception = HashUtil.digestToHexString(encodedPassword); | |
| 79 |
1
1. uncaughtException : negated conditional → NO_COVERAGE |
if (!ExceptionUtil.this.exceptionsMd5Cached.contains(md5Exception)) { |
| 80 | ExceptionUtil.this.exceptionsMd5Cached.add(md5Exception); | |
| 81 |
1
1. uncaughtException : removed call to com/jsql/util/GitUtil::sendUnhandledException → NO_COVERAGE |
ExceptionUtil.this.injectionModel.getMediatorUtils().getGitUtil().sendUnhandledException( |
| 82 | thread.getName(), | |
| 83 | throwable | |
| 84 | ); | |
| 85 | } | |
| 86 | } catch (NoSuchAlgorithmException e) { | |
| 87 | LOGGER.log(LogLevelUtil.IGNORE, e); | |
| 88 | } | |
| 89 | } | |
| 90 | } | |
| 91 | } | |
| 92 | | |
| 93 | /** | |
| 94 | * Add the error reporting mechanism on top of the JVM in order to | |
| 95 | * intercept and process the error to GitHub. | |
| 96 | */ | |
| 97 | public void setUncaughtExceptionHandler() { | |
| 98 |
1
1. setUncaughtExceptionHandler : removed call to java/lang/Thread::setDefaultUncaughtExceptionHandler → NO_COVERAGE |
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler()); // Regular Exception |
| 99 | try { // Event dispatching thread Exception | |
| 100 |
1
1. setUncaughtExceptionHandler : removed call to javax/swing/SwingUtilities::invokeAndWait → NO_COVERAGE |
SwingUtilities.invokeAndWait(() -> |
| 101 |
1
1. lambda$setUncaughtExceptionHandler$0 : removed call to java/lang/Thread::setUncaughtExceptionHandler → NO_COVERAGE |
Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler()) // We are in the event dispatching thread |
| 102 | ); | |
| 103 | } catch (InvocationTargetException | InterruptedException e) { | |
| 104 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
| 105 |
1
1. setUncaughtExceptionHandler : removed call to java/lang/Thread::interrupt → NO_COVERAGE |
Thread.currentThread().interrupt(); |
| 106 | } | |
| 107 | } | |
| 108 | } | |
Mutations | ||
| 44 |
1.1 |
|
| 49 |
1.1 |
|
| 55 |
1.1 |
|
| 56 |
1.1 2.2 |
|
| 58 |
1.1 |
|
| 60 |
1.1 |
|
| 63 |
1.1 |
|
| 75 |
1.1 |
|
| 79 |
1.1 |
|
| 81 |
1.1 |
|
| 98 |
1.1 |
|
| 100 |
1.1 |
|
| 101 |
1.1 |
|
| 105 |
1.1 |