Added more logging and minor housekeeping

This commit is contained in:
dorving 2023-03-29 10:08:44 +02:00
parent 8b1acdf9d7
commit 51de1bbecd
11 changed files with 185 additions and 120 deletions

View File

@ -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<String> consumeInputLine;
public StreamGobbler(InputStream inputStream, Consumer<String> consumeInputLine) {
this.inputStream = inputStream;
this.consumeInputLine = consumeInputLine;
}
public void run() {
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumeInputLine);
}
}

View File

@ -13,12 +13,16 @@ import gearth.protocol.connection.proxy.ProxyProviderFactory;
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider; import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
import gearth.protocol.connection.proxy.unity.UnityProxyProvider; import gearth.protocol.connection.proxy.unity.UnityProxyProvider;
import gearth.services.extension_handler.ExtensionHandler; import gearth.services.extension_handler.ExtensionHandler;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.util.function.Consumer; import java.util.function.Consumer;
public class HConnection { public class HConnection {
private final static Logger LOGGER = LoggerFactory.getLogger(HConnection.class);
public static volatile boolean DECRYPTPACKETS = true; public static volatile boolean DECRYPTPACKETS = true;
public static volatile boolean DEBUG = true; public static volatile boolean DEBUG = true;
@ -31,19 +35,17 @@ public class HConnection {
private volatile HState state = HState.NOT_CONNECTED; private volatile HState state = HState.NOT_CONNECTED;
private volatile HProxy proxy = null; private volatile HProxy proxy = null;
private ProxyProviderFactory proxyProviderFactory; private final ProxyProviderFactory proxyProviderFactory;
private ProxyProvider proxyProvider = null; private ProxyProvider proxyProvider = null;
private volatile boolean developerMode = false; private volatile boolean developerMode = false;
public HConnection() { public HConnection() {
HConnection selff = this;
proxyProviderFactory = new ProxyProviderFactory( proxyProviderFactory = new ProxyProviderFactory(
proxy -> selff.proxy = proxy, providedProxy -> proxy = providedProxy,
selff::setState, this::setState,
this this
); );
PacketSafetyManager.PACKET_SAFETY_MANAGER.initialize(this); PacketSafetyManager.PACKET_SAFETY_MANAGER.initialize(this);
} }
@ -53,6 +55,7 @@ public class HConnection {
private void setState(HState state) { private void setState(HState state) {
if (state != this.state) { if (state != this.state) {
LOGGER.debug("Changed state to {}", state);
HState buffer = this.state; HState buffer = this.state;
this.state = state; this.state = state;
stateObservable.fireEvent(l -> l.stateChanged(buffer, state)); stateObservable.fireEvent(l -> l.stateChanged(buffer, state));
@ -62,6 +65,7 @@ public class HConnection {
// autodetect mode // autodetect mode
public void start() { public void start() {
proxyProvider = proxyProviderFactory.provide(); proxyProvider = proxyProviderFactory.provide();
LOGGER.debug("Created proxy provider {}",proxyProvider);
startMITM(); startMITM();
} }

View File

@ -2,21 +2,20 @@ package gearth.protocol.connection.proxy;
import gearth.misc.Cacher; import gearth.misc.Cacher;
import gearth.misc.OSValidator; import gearth.misc.OSValidator;
import gearth.misc.StreamGobbler;
import gearth.protocol.HConnection; import gearth.protocol.HConnection;
import gearth.protocol.connection.HProxySetter; import gearth.protocol.connection.HProxySetter;
import gearth.protocol.connection.HStateSetter; import gearth.protocol.connection.HStateSetter;
import gearth.protocol.connection.proxy.flash.NormalFlashProxyProvider; import gearth.protocol.connection.proxy.flash.NormalFlashProxyProvider;
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider; import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
import gearth.protocol.connection.proxy.flash.windows.WindowsRawIpFlashProxyProvider; import gearth.protocol.connection.proxy.flash.windows.WindowsRawIpFlashProxyProvider;
import gearth.ui.titlebar.TitleBarController; import gearth.ui.alert.AlertUtil;
import gearth.ui.translations.LanguageBundle; import gearth.ui.translations.LanguageBundle;
import javafx.application.Platform; import javafx.scene.control.DialogPane;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.stage.Stage; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -24,6 +23,8 @@ import java.util.List;
public class ProxyProviderFactory { public class ProxyProviderFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(ProxyProviderFactory.class);
public static final String HOTELS_CACHE_KEY = "hotelsConnectionInfo"; public static final String HOTELS_CACHE_KEY = "hotelsConnectionInfo";
private static SocksConfiguration socksConfig = null; private static SocksConfiguration socksConfig = null;
@ -52,11 +53,24 @@ public class ProxyProviderFactory {
if (OSValidator.isMac()) { if (OSValidator.isMac()) {
for (int i = 2; i <= autoDetectHosts.size() + 5; i++) { 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 { try {
allowLocalHost.start(); LOGGER.debug("Launching process with command {}", pb.command());
} catch (IOException e) { final Process process = pb.start();
e.printStackTrace();
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); return new WindowsRawIpFlashProxyProvider(proxySetter, stateSetter, hConnection, domain, port, true);
} }
Platform.runLater(() -> { AlertUtil.showAlert(alert -> {
Alert alert = new Alert(Alert.AlertType.ERROR, "", ButtonType.OK); final DialogPane dialogPane = alert.getDialogPane();
alert.getDialogPane().getChildren().add(new Label(LanguageBundle.get("alert.alreadyconnected.content").replaceAll("\\\\n", System.lineSeparator()))); dialogPane.setMinHeight(Region.USE_PREF_SIZE);
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE); dialogPane.getChildren()
alert.setResizable(false); .add(new Label(LanguageBundle.get("alert.alreadyconnected.content").replaceAll("\\\\n", System.lineSeparator())));
try {
TitleBarController.create(alert).showAlert();
} catch (IOException e) {
e.printStackTrace();
}
}); });
return null; return null;
} }
else if (OSValidator.isUnix() || OSValidator.isMac()) { else if (OSValidator.isUnix() || OSValidator.isMac()) {
@ -132,6 +140,7 @@ public class ProxyProviderFactory {
return provide(potentialHost); return provide(potentialHost);
} }
} }
private ProxyProvider provide(List<String> potentialHosts) { private ProxyProvider provide(List<String> potentialHosts) {
return new NormalFlashProxyProvider(proxySetter, stateSetter, hConnection, potentialHosts, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded()); return new NormalFlashProxyProvider(proxySetter, stateSetter, hConnection, potentialHosts, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded());
} }

View File

@ -9,10 +9,8 @@ import gearth.protocol.hostreplacer.hostsfile.HostReplacer;
import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory; import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory;
import gearth.protocol.portchecker.PortChecker; import gearth.protocol.portchecker.PortChecker;
import gearth.protocol.portchecker.PortCheckerFactory; import gearth.protocol.portchecker.PortCheckerFactory;
import gearth.ui.titlebar.TitleBarController; import gearth.ui.alert.AlertUtil;
import javafx.application.Platform; import org.jetbrains.annotations.NotNull;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import java.io.IOException; import java.io.IOException;
import java.net.*; import java.net.*;
@ -21,16 +19,14 @@ import java.util.List;
public class NormalFlashProxyProvider extends FlashProxyProvider { public class NormalFlashProxyProvider extends FlashProxyProvider {
private List<String> potentialHosts; private final List<String> potentialHosts;
private static final HostReplacer hostsReplacer = HostReplacerFactory.get(); private static final HostReplacer hostsReplacer = HostReplacerFactory.get();
private volatile boolean hostRedirected = false; private volatile boolean hostRedirected = false;
private volatile List<HProxy> potentialProxies = new ArrayList<>(); private final List<HProxy> potentialProxies = new ArrayList<>();
private volatile HProxy proxy = null; private volatile HProxy proxy = null;
private boolean useSocks; private final boolean useSocks;
public NormalFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, List<String> potentialHosts, boolean useSocks) { public NormalFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, List<String> potentialHosts, boolean useSocks) {
super(proxySetter, stateSetter, hConnection); super(proxySetter, stateSetter, hConnection);
@ -38,13 +34,12 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
this.useSocks = useSocks; this.useSocks = useSocks;
} }
@Override @Override
public void start() throws IOException { public void start() throws IOException {
if (hConnection.getState() != HState.NOT_CONNECTED) { if (hConnection.getState() != HState.NOT_CONNECTED) {
return; return;
} }
logger.debug("Starting...");
prepare(); prepare();
addToHosts(); addToHosts();
launchProxy(); launchProxy();
@ -53,7 +48,7 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
private void prepare() { private void prepare() {
stateSetter.setState(HState.PREPARING); stateSetter.setState(HState.PREPARING);
logger.debug("Preparing with {} potential hosts", potentialHosts);
List<String> willremove = new ArrayList<>(); List<String> willremove = new ArrayList<>();
int c = 0; int c = 0;
for (String host : potentialHosts) { for (String host : potentialHosts) {
@ -94,44 +89,27 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
private void launchProxy() throws IOException { private void launchProxy() throws IOException {
stateSetter.setState(HState.WAITING_FOR_CLIENT); stateSetter.setState(HState.WAITING_FOR_CLIENT);
for (int c = 0; c < potentialProxies.size(); c++) { logger.debug("Waiting for clients, potentialProxies={}", potentialProxies);
HProxy potentialProxy = potentialProxies.get(c); for (HProxy potentialProxy : potentialProxies) {
ServerSocket proxy_server; final ServerSocket proxyServer = createProxyServer(potentialProxy);
try { potentialProxy.initProxy(proxyServer);
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);
new Thread(() -> { final Thread thread = new Thread(() -> {
try { try {
Thread.sleep(30); Thread.sleep(30);
while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxy_server.isClosed()) { while ((hConnection.getState() == HState.WAITING_FOR_CLIENT) && !proxyServer.isClosed()) {
try { try {
Socket client = proxy_server.accept(); Socket client = proxyServer.accept();
proxy = potentialProxy; proxy = potentialProxy;
closeAllProxies(proxy); closeAllProxies(proxy);
logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})",proxy, useSocks); logger.debug("Accepted proxy {}, starting proxy thread (useSocks={})", proxy, useSocks);
new Thread(() -> { new Thread(() -> {
try { try {
Socket server; Socket server;
if (!useSocks) { if (!useSocks) {
server = new Socket(proxy.getActual_domain(), proxy.getActual_port()); server = new Socket(proxy.getActual_domain(), proxy.getActual_port());
} } else {
else {
SocksConfiguration configuration = ProxyProviderFactory.getSocksConfig(); SocksConfiguration configuration = ProxyProviderFactory.getSocksConfig();
if (configuration == null) { if (configuration == null) {
showInvalidConnectionError(); showInvalidConnectionError();
@ -148,30 +126,49 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
showInvalidConnectionError(); showInvalidConnectionError();
abort(); abort();
logger.error("Failed to configure SOCKS proxy", e); logger.error("Failed to configure SOCKS proxy", e);
} } catch (InterruptedException | IOException e) {
catch (InterruptedException | IOException e) {
logger.error("An unexpected exception occurred", e); logger.error("An unexpected exception occurred", e);
} }
}).start(); }).start();
} catch (IOException e1) { } catch (SocketException exception) {
logger.error("An unexpected exception occurred", e1); logger.error("An unexpected exception occurred: {}", exception.getLocalizedMessage());
} catch (IOException exception) {
logger.error("An unexpected exception occurred", exception);
} }
} }
} catch (Exception e) { } 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 @Override
public void abort() { public void abort() {
stateSetter.setState(HState.ABORTING); stateSetter.setState(HState.ABORTING);
logger.debug("Aborting... hostRedirected={}", hostRedirected);
if (hostRedirected) { if (hostRedirected) {
removeFromHosts(); removeFromHosts();
} }
clearAllProxies(); clearAllProxies();
super.abort(); super.abort();
} }
@ -197,15 +194,10 @@ public class NormalFlashProxyProvider extends FlashProxyProvider {
hostRedirected = true; hostRedirected = true;
} }
private void removeFromHosts(){ private void removeFromHosts(){
List<String> linesTemp = new ArrayList<>(); final String[] lines = potentialProxies.stream()
for (HProxy proxy : potentialProxies) { .map(proxy -> proxy.getIntercept_host() + " " + proxy.getInput_domain())
linesTemp.add(proxy.getIntercept_host() + " " + proxy.getInput_domain()); .toArray(String[]::new);
} logger.debug("Removing {} lines from hosts file (lines={})", lines.length, lines);
String[] lines = new String[linesTemp.size()];
for (int i = 0; i < linesTemp.size(); i++) {
lines[i] = linesTemp.get(i);
}
hostsReplacer.removeRedirect(lines); hostsReplacer.removeRedirect(lines);
hostRedirected = false; hostRedirected = false;
} }

View File

@ -4,6 +4,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.*; import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;

View File

@ -25,7 +25,7 @@ public class MacOSHabboClient extends HabboClient {
private static final Logger LOGGER = LoggerFactory.getLogger(MacOSHabboClient.class); 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. * The header id (opcode) of the packet that contains the value for the {@link #production} field.

View File

@ -4,7 +4,7 @@ import gearth.extensions.InternalExtensionBuilder;
import gearth.misc.HostInfo; import gearth.misc.HostInfo;
import gearth.misc.listenerpattern.Observable; import gearth.misc.listenerpattern.Observable;
import gearth.misc.listenerpattern.SynchronizedObservable; 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.services.packet_info.PacketInfoManager;
import gearth.protocol.HMessage; import gearth.protocol.HMessage;
import gearth.protocol.HPacket; 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. * 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 * @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 { public abstract class GEarthExtension {

View File

@ -1,15 +1,11 @@
package gearth.services.internal_extensions.extensionstore.application.entities; 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.GExtensionStore;
import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController; import gearth.services.internal_extensions.extensionstore.application.GExtensionStoreController;
import gearth.services.internal_extensions.extensionstore.application.WebUtils; 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.StoreRepository;
import gearth.services.internal_extensions.extensionstore.repository.models.StoreExtension; 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 gearth.ui.translations.LanguageBundle;
import netscape.javascript.JSObject; import netscape.javascript.JSObject;
@ -27,7 +23,7 @@ public class StoreExtensionItem implements ContentItem {
new StoreExtensionDetailsOverview( new StoreExtensionDetailsOverview(
gExtensionStore.getController().getCurrentOverview(), gExtensionStore.getController().getCurrentOverview(),
0, 0,
GExtensionStore.PAGESIZE, GExtensionStore.MAX_PAGES,
storeExtension, storeExtension,
gExtensionStore.getRepository() gExtensionStore.getRepository()
) )

View File

@ -44,12 +44,12 @@ public class StoreRepository {
String queryLower = queryString.toLowerCase(); String queryLower = queryString.toLowerCase();
final List<StoreExtension> extensions = getExtensions(); final List<StoreExtension> extensions = getExtensions();
for (StoreExtension extension : extensions) { // for (StoreExtension extension : extensions) {
System.out.println(extension.getTitle()); // System.out.println(extension.getTitle());
for (String system : extension.getCompatibility().getSystems()) { // for (String system : extension.getCompatibility().getSystems()) {
System.out.println(system); // System.out.println(system);
} // }
} // }
Stream<StoreExtension> stream = extensions.stream() Stream<StoreExtension> stream = extensions.stream()
.filter(ext -> ext.getTitle().toLowerCase().contains(queryLower) || ext.getDescription().toLowerCase().contains(queryLower) .filter(ext -> ext.getTitle().toLowerCase().contains(queryLower) || ext.getDescription().toLowerCase().contains(queryLower)
|| ext.getAuthors().stream().anyMatch(author -> author.getName().toLowerCase().contains(queryLower) || ext.getAuthors().stream().anyMatch(author -> author.getName().toLowerCase().contains(queryLower)

View File

@ -37,6 +37,7 @@ public class StoreExtensionTools {
public final static String EXTENSIONS_PATH = Paths.get(NormalExtensionRunner.JAR_PATH, ExecutionInfo.EXTENSIONS_DIRECTORY).toString(); public final static String EXTENSIONS_PATH = Paths.get(NormalExtensionRunner.JAR_PATH, ExecutionInfo.EXTENSIONS_DIRECTORY).toString();
public static void executeExtension(String extensionPath, int port) { public static void executeExtension(String extensionPath, int port) {
try { try {
String installedExtensionId = Paths.get(extensionPath).getFileName().toString(); String installedExtensionId = Paths.get(extensionPath).getFileName().toString();
@ -242,27 +243,28 @@ public class StoreExtensionTools {
} }
public static void main(String[] args) { public static void main(String[] args) {
StoreFetch.fetch(GEarth.version, new StoreFetch.StoreFetchListener() { System.out.println(EXTENSIONS_PATH);
@Override // StoreFetch.fetch(GEarth.version, new StoreFetch.StoreFetchListener() {
public void success(StoreRepository storeRepository) { // @Override
installExtension("G-BuildTools", storeRepository, new InstallExtListener() { // public void success(StoreRepository storeRepository) {
@Override // installExtension("G-BuildTools", storeRepository, new InstallExtListener() {
public void success(String installationFolder) { // @Override
System.out.println(String.format("Installed in: %s", installationFolder)); // public void success(String installationFolder) {
} // System.out.println(String.format("Installed in: %s", installationFolder));
// }
@Override //
public void fail(String reason) { // @Override
System.out.println(reason); // public void fail(String reason) {
} // System.out.println(reason);
}); // }
} // });
// }
@Override //
public void fail(String reason) { // @Override
System.out.println("failed fetching repository"); // public void fail(String reason) {
} // System.out.println("failed fetching repository");
}); // }
// });
} }

View File

@ -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<Alert> 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();
}
});
}
}