From 51de1bbecdcf9398c0aa721a49c01c21a3ee19f9 Mon Sep 17 00:00:00 2001 From: dorving Date: Wed, 29 Mar 2023 10:08:44 +0200 Subject: [PATCH] Added more logging and minor housekeeping --- .../main/java/gearth/misc/StreamGobbler.java | 21 ++++ .../java/gearth/protocol/HConnection.java | 14 ++- .../proxy/ProxyProviderFactory.java | 51 +++++---- .../proxy/flash/NormalFlashProxyProvider.java | 106 ++++++++---------- .../hostsfile/UnixHostReplacer.java | 1 + .../habboclient/macos/MacOSHabboClient.java | 2 +- .../extensions/GEarthExtension.java | 6 +- .../entities/StoreExtensionItem.java | 8 +- .../repository/StoreRepository.java | 12 +- .../tools/StoreExtensionTools.java | 44 ++++---- .../main/java/gearth/ui/alert/AlertUtil.java | 40 +++++++ 11 files changed, 185 insertions(+), 120 deletions(-) create mode 100644 G-Earth/src/main/java/gearth/misc/StreamGobbler.java create mode 100644 G-Earth/src/main/java/gearth/ui/alert/AlertUtil.java diff --git a/G-Earth/src/main/java/gearth/misc/StreamGobbler.java b/G-Earth/src/main/java/gearth/misc/StreamGobbler.java new file mode 100644 index 0000000..60a2984 --- /dev/null +++ b/G-Earth/src/main/java/gearth/misc/StreamGobbler.java @@ -0,0 +1,21 @@ +package gearth.misc; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.function.Consumer; + +public class StreamGobbler implements Runnable { + + private final InputStream inputStream; + private final Consumer consumeInputLine; + + public StreamGobbler(InputStream inputStream, Consumer consumeInputLine) { + this.inputStream = inputStream; + this.consumeInputLine = consumeInputLine; + } + + public void run() { + new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumeInputLine); + } +} \ No newline at end of file diff --git a/G-Earth/src/main/java/gearth/protocol/HConnection.java b/G-Earth/src/main/java/gearth/protocol/HConnection.java index 9263687..fdf07aa 100644 --- a/G-Earth/src/main/java/gearth/protocol/HConnection.java +++ b/G-Earth/src/main/java/gearth/protocol/HConnection.java @@ -13,12 +13,16 @@ import gearth.protocol.connection.proxy.ProxyProviderFactory; import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider; import gearth.protocol.connection.proxy.unity.UnityProxyProvider; import gearth.services.extension_handler.ExtensionHandler; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; import java.io.IOException; import java.util.function.Consumer; public class HConnection { + private final static Logger LOGGER = LoggerFactory.getLogger(HConnection.class); + public static volatile boolean DECRYPTPACKETS = true; public static volatile boolean DEBUG = true; @@ -31,19 +35,17 @@ public class HConnection { private volatile HState state = HState.NOT_CONNECTED; private volatile HProxy proxy = null; - private ProxyProviderFactory proxyProviderFactory; + private final ProxyProviderFactory proxyProviderFactory; private ProxyProvider proxyProvider = null; private volatile boolean developerMode = false; public HConnection() { - HConnection selff = this; proxyProviderFactory = new ProxyProviderFactory( - proxy -> selff.proxy = proxy, - selff::setState, + providedProxy -> proxy = providedProxy, + this::setState, this ); - PacketSafetyManager.PACKET_SAFETY_MANAGER.initialize(this); } @@ -53,6 +55,7 @@ public class HConnection { private void setState(HState state) { if (state != this.state) { + LOGGER.debug("Changed state to {}", state); HState buffer = this.state; this.state = state; stateObservable.fireEvent(l -> l.stateChanged(buffer, state)); @@ -62,6 +65,7 @@ public class HConnection { // autodetect mode public void start() { proxyProvider = proxyProviderFactory.provide(); + LOGGER.debug("Created proxy provider {}",proxyProvider); startMITM(); } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/ProxyProviderFactory.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/ProxyProviderFactory.java index 9070132..1e64ad6 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/ProxyProviderFactory.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/ProxyProviderFactory.java @@ -2,21 +2,20 @@ package gearth.protocol.connection.proxy; import gearth.misc.Cacher; import gearth.misc.OSValidator; +import gearth.misc.StreamGobbler; import gearth.protocol.HConnection; import gearth.protocol.connection.HProxySetter; import gearth.protocol.connection.HStateSetter; import gearth.protocol.connection.proxy.flash.NormalFlashProxyProvider; import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider; import gearth.protocol.connection.proxy.flash.windows.WindowsRawIpFlashProxyProvider; -import gearth.ui.titlebar.TitleBarController; +import gearth.ui.alert.AlertUtil; import gearth.ui.translations.LanguageBundle; -import javafx.application.Platform; -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; +import javafx.scene.control.DialogPane; import javafx.scene.control.Label; -import javafx.scene.image.Image; import javafx.scene.layout.Region; -import javafx.stage.Stage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; @@ -24,6 +23,8 @@ import java.util.List; public class ProxyProviderFactory { + private static final Logger LOGGER = LoggerFactory.getLogger(ProxyProviderFactory.class); + public static final String HOTELS_CACHE_KEY = "hotelsConnectionInfo"; private static SocksConfiguration socksConfig = null; @@ -52,11 +53,24 @@ public class ProxyProviderFactory { if (OSValidator.isMac()) { for (int i = 2; i <= autoDetectHosts.size() + 5; i++) { - ProcessBuilder allowLocalHost = new ProcessBuilder("ifconfig", "lo0", "alias", ("127.0.0." + i), "up"); + final String alias = ("127.0.0." + i); + final String processName = "Process for lo0 with alias "+alias; + final ProcessBuilder pb = new ProcessBuilder("ifconfig", "lo0", "alias", alias, "up"); try { - allowLocalHost.start(); - } catch (IOException e) { - e.printStackTrace(); + LOGGER.debug("Launching process with command {}", pb.command()); + final Process process = pb.start(); + + final Logger logger = LoggerFactory.getLogger(processName); + final StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), logger::debug); + final StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), logger::error); + + new Thread(outputGobbler).start(); + new Thread(errorGobbler).start(); + process.waitFor(); + + LOGGER.debug("Finished process {}", process); + } catch (IOException | InterruptedException e) { + LOGGER.error("Exception occurred for {}", processName, e); } } } @@ -106,18 +120,12 @@ public class ProxyProviderFactory { return new WindowsRawIpFlashProxyProvider(proxySetter, stateSetter, hConnection, domain, port, true); } - Platform.runLater(() -> { - Alert alert = new Alert(Alert.AlertType.ERROR, "", ButtonType.OK); - alert.getDialogPane().getChildren().add(new Label(LanguageBundle.get("alert.alreadyconnected.content").replaceAll("\\\\n", System.lineSeparator()))); - alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); - alert.setResizable(false); - try { - TitleBarController.create(alert).showAlert(); - } catch (IOException e) { - e.printStackTrace(); - } + AlertUtil.showAlert(alert -> { + final DialogPane dialogPane = alert.getDialogPane(); + dialogPane.setMinHeight(Region.USE_PREF_SIZE); + dialogPane.getChildren() + .add(new Label(LanguageBundle.get("alert.alreadyconnected.content").replaceAll("\\\\n", System.lineSeparator()))); }); - return null; } else if (OSValidator.isUnix() || OSValidator.isMac()) { @@ -132,6 +140,7 @@ public class ProxyProviderFactory { return provide(potentialHost); } } + private ProxyProvider provide(List potentialHosts) { return new NormalFlashProxyProvider(proxySetter, stateSetter, hConnection, potentialHosts, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded()); } diff --git a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java index 4404cf4..89ff304 100644 --- a/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java +++ b/G-Earth/src/main/java/gearth/protocol/connection/proxy/flash/NormalFlashProxyProvider.java @@ -9,10 +9,8 @@ import gearth.protocol.hostreplacer.hostsfile.HostReplacer; import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory; import gearth.protocol.portchecker.PortChecker; import gearth.protocol.portchecker.PortCheckerFactory; -import gearth.ui.titlebar.TitleBarController; -import javafx.application.Platform; -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; +import gearth.ui.alert.AlertUtil; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.net.*; @@ -21,16 +19,14 @@ import java.util.List; public class NormalFlashProxyProvider extends FlashProxyProvider { - private List potentialHosts; - + private final List potentialHosts; private static final HostReplacer hostsReplacer = HostReplacerFactory.get(); private volatile boolean hostRedirected = false; - private volatile List potentialProxies = new ArrayList<>(); + private final List potentialProxies = new ArrayList<>(); private volatile HProxy proxy = null; - private boolean useSocks; - + private final boolean useSocks; public NormalFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, List potentialHosts, boolean useSocks) { super(proxySetter, stateSetter, hConnection); @@ -38,13 +34,12 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { this.useSocks = useSocks; } - @Override public void start() throws IOException { if (hConnection.getState() != HState.NOT_CONNECTED) { return; } - + logger.debug("Starting..."); prepare(); addToHosts(); launchProxy(); @@ -53,7 +48,7 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { private void prepare() { stateSetter.setState(HState.PREPARING); - + logger.debug("Preparing with {} potential hosts", potentialHosts); List willremove = new ArrayList<>(); int c = 0; for (String host : potentialHosts) { @@ -94,44 +89,27 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { private void launchProxy() throws IOException { stateSetter.setState(HState.WAITING_FOR_CLIENT); - for (int c = 0; c < potentialProxies.size(); c++) { - HProxy potentialProxy = potentialProxies.get(c); + logger.debug("Waiting for clients, potentialProxies={}", potentialProxies); + for (HProxy potentialProxy : potentialProxies) { - ServerSocket proxy_server; - try { - proxy_server = new ServerSocket(potentialProxy.getIntercept_port(), 10, InetAddress.getByName(potentialProxy.getIntercept_host())); - } catch (BindException e) { - PortChecker portChecker = PortCheckerFactory.getPortChecker(); - String processName = portChecker.getProcessUsingPort(potentialProxy.getIntercept_port()); - Platform.runLater(() -> { - Alert a = new Alert(Alert.AlertType.ERROR, "The port is in use by " + processName, - ButtonType.OK); - try { - TitleBarController.create(a).showAlertAndWait(); - } catch (IOException ex) { - logger.error("Failed to create port in use error alert", ex); - } - }); - throw new IOException(e); - } - potentialProxy.initProxy(proxy_server); + final ServerSocket proxyServer = createProxyServer(potentialProxy); + potentialProxy.initProxy(proxyServer); - new Thread(() -> { - try { + final Thread thread = new Thread(() -> { + try { Thread.sleep(30); - while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxy_server.isClosed()) { + while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxyServer.isClosed()) { try { - Socket client = proxy_server.accept(); + Socket client = proxyServer.accept(); proxy = potentialProxy; closeAllProxies(proxy); - logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})",proxy, useSocks); + logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})", proxy, useSocks); new Thread(() -> { try { Socket server; if (!useSocks) { - server = new Socket(proxy.getActual_domain(), proxy.getActual_port()); - } - else { + server = new Socket(proxy.getActual_domain(), proxy.getActual_port()); + } else { SocksConfiguration configuration = ProxyProviderFactory.getSocksConfig(); if (configuration == null) { showInvalidConnectionError(); @@ -148,30 +126,49 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { showInvalidConnectionError(); abort(); logger.error("Failed to configure SOCKS proxy", e); - } - catch (InterruptedException | IOException e) { + } catch (InterruptedException | IOException e) { logger.error("An unexpected exception occurred", e); } }).start(); - } catch (IOException e1) { - logger.error("An unexpected exception occurred", e1); + } catch (SocketException exception) { + logger.error("An unexpected exception occurred: {}", exception.getLocalizedMessage()); + + } catch (IOException exception) { + logger.error("An unexpected exception occurred", exception); } } } catch (Exception e) { - e.printStackTrace(); + logger.error("An unexpected error occurred", e); + } finally { + logger.debug("Stopped"); } - }).start(); + }); + thread.setName("ProxyServerThread ("+ potentialProxy.getInput_domain()+") -> ("+potentialProxy.getActual_domain()+")"); + thread.start(); } - logger.debug("Done waiting for clients with connection state {}", hConnection.getState()); + } + + @NotNull + private static ServerSocket createProxyServer(HProxy potentialProxy) throws IOException { + final ServerSocket proxy_server; + try { + proxy_server = new ServerSocket(potentialProxy.getIntercept_port(), 10, InetAddress.getByName(potentialProxy.getIntercept_host())); + } catch (BindException e) { + final PortChecker portChecker = PortCheckerFactory.getPortChecker(); + final String processName = portChecker.getProcessUsingPort(potentialProxy.getIntercept_port()); + AlertUtil.showAlertAndWait("The port is in use by " + processName); + throw new IOException(e); + } + return proxy_server; } @Override public void abort() { stateSetter.setState(HState.ABORTING); + logger.debug("Aborting... hostRedirected={}", hostRedirected); if (hostRedirected) { removeFromHosts(); } - clearAllProxies(); super.abort(); } @@ -197,15 +194,10 @@ public class NormalFlashProxyProvider extends FlashProxyProvider { hostRedirected = true; } private void removeFromHosts(){ - List linesTemp = new ArrayList<>(); - for (HProxy proxy : potentialProxies) { - linesTemp.add(proxy.getIntercept_host() + " " + proxy.getInput_domain()); - } - - String[] lines = new String[linesTemp.size()]; - for (int i = 0; i < linesTemp.size(); i++) { - lines[i] = linesTemp.get(i); - } + final String[] lines = potentialProxies.stream() + .map(proxy -> proxy.getIntercept_host() + " " + proxy.getInput_domain()) + .toArray(String[]::new); + logger.debug("Removing {} lines from hosts file (lines={})", lines.length, lines); hostsReplacer.removeRedirect(lines); hostRedirected = false; } diff --git a/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java b/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java index 4754cbf..707ade7 100644 --- a/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java +++ b/G-Earth/src/main/java/gearth/protocol/hostreplacer/hostsfile/UnixHostReplacer.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; diff --git a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java index 95420e9..87c4ac1 100644 --- a/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java +++ b/G-Earth/src/main/java/gearth/protocol/memory/habboclient/macos/MacOSHabboClient.java @@ -25,7 +25,7 @@ public class MacOSHabboClient extends HabboClient { private static final Logger LOGGER = LoggerFactory.getLogger(MacOSHabboClient.class); - private static final String G_MEM_EXECUTABLE_FILE_NAME = "/g_mem_mac"; + private static final String G_MEM_EXECUTABLE_FILE_NAME = "/G-Mem"; /** * The header id (opcode) of the packet that contains the value for the {@link #production} field. diff --git a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/GEarthExtension.java b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/GEarthExtension.java index 77484fa..dc6b334 100644 --- a/G-Earth/src/main/java/gearth/services/extension_handler/extensions/GEarthExtension.java +++ b/G-Earth/src/main/java/gearth/services/extension_handler/extensions/GEarthExtension.java @@ -4,7 +4,7 @@ import gearth.extensions.InternalExtensionBuilder; import gearth.misc.HostInfo; import gearth.misc.listenerpattern.Observable; import gearth.misc.listenerpattern.SynchronizedObservable; -import gearth.services.extension_handler.extensions.implementations.network.NetworkExtension; +import gearth.services.extension_handler.extensions.implementations.network.NetworkExtensionClient; import gearth.services.packet_info.PacketInfoManager; import gearth.protocol.HMessage; import gearth.protocol.HPacket; @@ -16,9 +16,9 @@ import gearth.services.extension_handler.extensions.listeners.OnDeleteListener; /** * Represents a type of extension created with one of the extension APIs. * - * @see NetworkExtension extensions connecting to G-Earth from a different process. + * @see NetworkExtensionClient xtensions connecting to G-Earth from a different process. * @see InternalExtensionBuilder internal extensions (JAR files) that follow - * the same communication protocol as {@link NetworkExtension network extensions}. + * the same communication protocol as {@link NetworkExtensionClient network extensions}. */ public abstract class GEarthExtension { diff --git a/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/application/entities/StoreExtensionItem.java b/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/application/entities/StoreExtensionItem.java index d859bbc..9b9bf37 100644 --- a/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/application/entities/StoreExtensionItem.java +++ b/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/application/entities/StoreExtensionItem.java @@ -1,15 +1,11 @@ package gearth.services.internal_extensions.extensionstore.application.entities; -import gearth.GEarth; -import gearth.protocol.HMessage; -import gearth.protocol.HPacket; import gearth.services.internal_extensions.extensionstore.GExtensionStore; import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController; import gearth.services.internal_extensions.extensionstore.application.WebUtils; -import gearth.services.internal_extensions.extensionstore.application.entities.extensiondetails.StoreExtensionDetailsOverview; -import gearth.services.internal_extensions.extensionstore.application.entities.queriedoverviews.CategorizedOverview; import gearth.services.internal_extensions.extensionstore.repository.StoreRepository; import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension; +import gearth.services.internal_extensions.extensionstore.application.entities.extensiondetails.StoreExtensionDetailsOverview; import gearth.ui.translations.LanguageBundle; import netscape.javascript.JSObject; @@ -27,7 +23,7 @@ public class StoreExtensionItem implements ContentItem { new StoreExtensionDetailsOverview( gExtensionStore.getController().getCurrentOverview(), 0, - GExtensionStore.PAGESIZE, + GExtensionStore.MAX_PAGES, storeExtension, gExtensionStore.getRepository() ) diff --git a/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/repository/StoreRepository.java b/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/repository/StoreRepository.java index fc01e3b..c5aaf49 100644 --- a/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/repository/StoreRepository.java +++ b/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/repository/StoreRepository.java @@ -44,12 +44,12 @@ public class StoreRepository { String queryLower = queryString.toLowerCase(); final List extensions = getExtensions(); - for (StoreExtension extension : extensions) { - System.out.println(extension.getTitle()); - for (String system : extension.getCompatibility().getSystems()) { - System.out.println(system); - } - } +// for (StoreExtension extension : extensions) { +// System.out.println(extension.getTitle()); +// for (String system : extension.getCompatibility().getSystems()) { +// System.out.println(system); +// } +// } Stream stream = extensions.stream() .filter(ext -> ext.getTitle().toLowerCase().contains(queryLower) || ext.getDescription().toLowerCase().contains(queryLower) || ext.getAuthors().stream().anyMatch(author -> author.getName().toLowerCase().contains(queryLower) diff --git a/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/tools/StoreExtensionTools.java b/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/tools/StoreExtensionTools.java index 9a8f1e6..c2d839e 100644 --- a/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/tools/StoreExtensionTools.java +++ b/G-Earth/src/main/java/gearth/services/internal_extensions/extensionstore/tools/StoreExtensionTools.java @@ -37,6 +37,7 @@ public class StoreExtensionTools { public final static String EXTENSIONS_PATH = Paths.get(NormalExtensionRunner.JAR_PATH, ExecutionInfo.EXTENSIONS_DIRECTORY).toString(); + public static void executeExtension(String extensionPath, int port) { try { String installedExtensionId = Paths.get(extensionPath).getFileName().toString(); @@ -242,27 +243,28 @@ public class StoreExtensionTools { } public static void main(String[] args) { - StoreFetch.fetch(GEarth.version, new StoreFetch.StoreFetchListener() { - @Override - public void success(StoreRepository storeRepository) { - installExtension("G-BuildTools", storeRepository, new InstallExtListener() { - @Override - public void success(String installationFolder) { - System.out.println(String.format("Installed in: %s", installationFolder)); - } - - @Override - public void fail(String reason) { - System.out.println(reason); - } - }); - } - - @Override - public void fail(String reason) { - System.out.println("failed fetching repository"); - } - }); + System.out.println(EXTENSIONS_PATH); +// StoreFetch.fetch(GEarth.version, new StoreFetch.StoreFetchListener() { +// @Override +// public void success(StoreRepository storeRepository) { +// installExtension("G-BuildTools", storeRepository, new InstallExtListener() { +// @Override +// public void success(String installationFolder) { +// System.out.println(String.format("Installed in: %s", installationFolder)); +// } +// +// @Override +// public void fail(String reason) { +// System.out.println(reason); +// } +// }); +// } +// +// @Override +// public void fail(String reason) { +// System.out.println("failed fetching repository"); +// } +// }); } diff --git a/G-Earth/src/main/java/gearth/ui/alert/AlertUtil.java b/G-Earth/src/main/java/gearth/ui/alert/AlertUtil.java new file mode 100644 index 0000000..9ba9f61 --- /dev/null +++ b/G-Earth/src/main/java/gearth/ui/alert/AlertUtil.java @@ -0,0 +1,40 @@ +package gearth.ui.alert; + +import gearth.ui.titlebar.TitleBarController; +import javafx.application.Platform; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.function.Consumer; + +public class AlertUtil { + + private final static Logger LOGGER = LoggerFactory.getLogger(AlertUtil.class); + public static void showAlertAndWait(String contentText) { + Platform.runLater(() -> { + Alert alert = new Alert(Alert.AlertType.ERROR, contentText, ButtonType.OK); + try { + TitleBarController.create(alert).showAlertAndWait(); + } catch (IOException ex) { + LOGGER.error("Failed to create alert with content \"{}\"", contentText, ex); + } + }); + } + + public static void showAlert(Consumer consumer) { + Platform.runLater(() -> { + final Alert alert = new Alert(Alert.AlertType.ERROR, "", ButtonType.OK); + alert.setResizable(false); + consumer.accept(alert); + + try { + TitleBarController.create(alert).showAlert(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } +}