diff --git a/build.gradle b/build.gradle index 7b84a38ca5..8e05840830 100644 --- a/build.gradle +++ b/build.gradle @@ -104,7 +104,10 @@ project(":core") { compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.8' compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.4' compile group: 'com.google.guava', name: 'guava', version: '18.0' - compile group: 'com.google.inject', name: 'guice', version: '4.0' + // We use the no_aop version of Guice because the aop isn't avaiable in arm java + // http://stackoverflow.com/a/15235190/3708426 + // https://github.com/google/guice/wiki/OptionalAOP + compile group: 'com.google.inject', name: 'guice', version: '4.0', classifier: 'no_aop' compile group: 'com.google.inject.extensions', name: 'guice-assistedinject', version: '4.0' } diff --git a/core/src/main/java/edu/wpi/grip/core/GRIPCoreModule.java b/core/src/main/java/edu/wpi/grip/core/GRIPCoreModule.java index 13f20d02e5..ec2a2d0e9a 100644 --- a/core/src/main/java/edu/wpi/grip/core/GRIPCoreModule.java +++ b/core/src/main/java/edu/wpi/grip/core/GRIPCoreModule.java @@ -16,8 +16,8 @@ import edu.wpi.grip.core.sources.MultiImageFileSource; import edu.wpi.grip.core.util.ExceptionWitness; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.io.IOException; +import java.util.logging.*; /** * A Guice {@link com.google.inject.Module} for GRIP's core package. This is where instances of {@link Pipeline}, @@ -29,6 +29,47 @@ public class GRIPCoreModule extends AbstractModule { private final EventBus eventBus = new EventBus(this::onSubscriberException); public GRIPCoreModule() { + //Set up the global level logger. This handles IO for all loggers. + final Logger globalLogger = LogManager.getLogManager().getLogger("");//This is our global logger + + try { + // Remove the default handlers that stream to System.err + for(Handler handler : globalLogger.getHandlers()) { + globalLogger.removeHandler(handler); + } + + final Handler fileHandler = new FileHandler("%h/GRIP.log");//Log to the file "GRIPlogger.log" + + //Set level to handler and logger + fileHandler.setLevel(Level.FINE); + globalLogger.setLevel(Level.FINE); + + // We need to stream to System.out instead of System.err + final StreamHandler sh = new StreamHandler(System.out, new SimpleFormatter()) { + + @Override + public synchronized void publish(final LogRecord record) { + super.publish(record); + // For some reason this doesn't happen automatically. + // This will ensure we get all of the logs printed to the console immediately + // when running on a remote device. + flush(); + } + }; + sh.setLevel(Level.CONFIG); + + globalLogger.addHandler(sh); // Add stream handler + + globalLogger.addHandler(fileHandler);//Add the handler to the global logger + + fileHandler.setFormatter(new SimpleFormatter());//log in text, not xml + + globalLogger.config("Configuration done.");//Log that we are done setting up the logger + + } catch (IOException exception) {//Something happened setting up file IO + throw new IllegalStateException("Failed to configure the Logger", exception); + } + Thread.setDefaultUncaughtExceptionHandler(this::onThreadException); } @@ -68,6 +109,7 @@ private void onSubscriberException(Throwable exception, SubscriberExceptionConte logger.log(Level.FINE, "EventBus Subscriber threw InterruptedException", exception); Thread.currentThread().interrupt(); } else { + logger.log(Level.SEVERE, "An event subscriber threw an exception", exception); eventBus.post(new UnexpectedThrowableEvent(exception, "An event subscriber threw an exception")); } } @@ -77,6 +119,8 @@ private void onThreadException(Thread thread, Throwable exception) { logger.log(Level.FINE, "InterruptedException from thread " + thread, exception); Thread.currentThread().interrupt(); } else { + // This can potentially happen before the main class has even been loaded to handle these exceptions + logger.log(Level.SEVERE, "Uncaught Exception on thread " + thread, exception); eventBus.post(new UnexpectedThrowableEvent(exception, thread + " threw an exception")); } } diff --git a/core/src/main/java/edu/wpi/grip/core/Main.java b/core/src/main/java/edu/wpi/grip/core/Main.java index f5087567e8..2e1f9bc611 100644 --- a/core/src/main/java/edu/wpi/grip/core/Main.java +++ b/core/src/main/java/edu/wpi/grip/core/Main.java @@ -28,7 +28,9 @@ public class Main { @Inject private Logger logger; + @SuppressWarnings("PMD.SystemPrintln") public static void main(String[] args) throws IOException, InterruptedException { + System.out.println("Loading Dependency Injection Framework"); final Injector injector = Guice.createInjector(new GRIPCoreModule()); injector.getInstance(Main.class).start(args); } @@ -38,31 +40,10 @@ public void start(String[] args) throws IOException, InterruptedException { if (args.length != 1) { System.err.println("Usage: GRIP.jar project.grip"); return; + } else { + logger.log(Level.INFO, "Loading file " + args[0]); } - //Set up the global level logger. This handles IO for all loggers. - Logger globalLogger = LogManager.getLogManager().getLogger("");//This is our global logger - - Handler fileHandler = null;//This will be our handler for the global logger - - try { - fileHandler = new FileHandler("%h/GRIP.log");//Log to the file "GRIPlogger.log" - - globalLogger.addHandler(fileHandler);//Add the handler to the global logger - - fileHandler.setFormatter(new SimpleFormatter());//log in text, not xml - - //Set level to handler and logger - fileHandler.setLevel(Level.FINE); - globalLogger.setLevel(Level.FINE); - - globalLogger.config("Configuration done.");//Log that we are done setting up the logger - - } catch (IOException exception) {//Something happened setting up file IO - throw new IllegalStateException(exception); - } - - Operations.addOperations(eventBus); CVOperations.addOperations(eventBus); @@ -73,7 +54,7 @@ public void start(String[] args) throws IOException, InterruptedException { // This is done in order to indicate to the user using the deployment UI that this is running - System.out.println("SUCCESS! The project is running in headless mode!"); + logger.log(Level.INFO, "SUCCESS! The project is running in headless mode!"); // There's nothing more to do in the main thread since we're in headless mode - sleep forever for (; ; ) { Thread.sleep(Integer.MAX_VALUE); diff --git a/ui/src/main/java/edu/wpi/grip/ui/DeployerController.java b/ui/src/main/java/edu/wpi/grip/ui/DeployerController.java index 3bc3c1dd0e..55a66071a0 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/DeployerController.java +++ b/ui/src/main/java/edu/wpi/grip/ui/DeployerController.java @@ -55,13 +55,13 @@ public StreamToTextArea(TextArea outputArea) { } public StreamToTextArea reset() { - outputArea.clear(); + Platform.runLater(outputArea::clear); return this; } @Override public void write(int i) throws IOException { - outputArea.appendText(String.valueOf((char) i)); + Platform.runLater(()-> outputArea.appendText(String.valueOf((char) i))); } } diff --git a/ui/src/main/java/edu/wpi/grip/ui/Main.java b/ui/src/main/java/edu/wpi/grip/ui/Main.java index 2832acacd5..39235e934b 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/Main.java +++ b/ui/src/main/java/edu/wpi/grip/ui/Main.java @@ -20,8 +20,6 @@ import javafx.stage.Stage; import javax.inject.Inject; -import java.io.IOException; -import java.util.logging.*; public class Main extends Application { @@ -53,29 +51,6 @@ public Main() { @Override @SuppressWarnings("PMD.SignatureDeclareThrowsException") public void start(Stage stage) throws Exception { - - //Set up the global level logger. This handles IO for all loggers. - Logger globalLogger = LogManager.getLogManager().getLogger("");//This is our global logger - - Handler fileHandler = null;//This will be our handler for the global logger - - try { - fileHandler = new FileHandler("%h/GRIP.log");//Log to the file "GRIP.log" - - globalLogger.addHandler(fileHandler);//Add the handler to the global logger - - fileHandler.setFormatter(new SimpleFormatter());//log in text, not xml - - //Set level to handler and logger - fileHandler.setLevel(Level.FINE); - globalLogger.setLevel(Level.FINE); - - globalLogger.config("Configuration done.");//Log that we are done setting up the logger - - } catch (IOException exception) {//Something happened setting up file IO - throw new IllegalStateException(exception); - } - root = FXMLLoader.load(Main.class.getResource("MainWindow.fxml"), null, null, injector::getInstance); root.setStyle("-fx-font-size: " + DPIUtility.FONT_SIZE + "px"); diff --git a/ui/src/main/java/edu/wpi/grip/ui/util/deployment/DeployedInstanceManager.java b/ui/src/main/java/edu/wpi/grip/ui/util/deployment/DeployedInstanceManager.java index 488b3602d8..71c3c5ffd7 100644 --- a/ui/src/main/java/edu/wpi/grip/ui/util/deployment/DeployedInstanceManager.java +++ b/ui/src/main/java/edu/wpi/grip/ui/util/deployment/DeployedInstanceManager.java @@ -180,6 +180,7 @@ public synchronized void start() throws IOException { synchronized (this) { sshThread = Optional.empty(); } + eventBus.post(new StartedStoppedEvent(this)); } }, "SSH Monitor Thread"); launcher.setUncaughtExceptionHandler((thread, exception) -> { @@ -216,7 +217,6 @@ public synchronized void stop() throws IOException { } runStop(); } while (isStarted() && !Thread.interrupted()); - eventBus.post(new StartedStoppedEvent(this)); } /**