package lighthouse.utils.ipc;
import javafx.application.*;
import lighthouse.*;
import lighthouse.files.*;
import java.io.*;
import java.net.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.util.*;
import static lighthouse.protocol.LHUtils.*;
/**
* Code to manage what happens when a user double clicks a file in their explorer. Either we load ourselves and queue
* the file for import, or we have to send a message to the existing app instance.
*/
public class FileOpenRequests {
public static boolean isAlreadyRunning() {
RandomAccessFile file = null;
try {
Path path = AppDirectory.dir().resolve(Main.APP_NAME + ".spvchain");
if (!Files.exists(path))
return false;
file = new RandomAccessFile(path.toFile(), "rw");
FileLock lock = file.getChannel().tryLock();
if (lock == null)
return true;
lock.release();
return false;
} catch (IOException e) {
return false;
} finally {
if (file != null) uncheck(file::close);
}
}
@SuppressWarnings("InfiniteLoopStatement")
public static boolean requestFileOpen(Application.Parameters params, List<Path> filesToOpen) {
if (isMac()) return false; // Mac stuff is handled later.
for (String arg : params.getUnnamed()) {
if (arg.startsWith("-")) continue;
Path path = Paths.get(arg);
if (Files.exists(path)) filesToOpen.add(path);
}
if (!isAlreadyRunning()) {
// Listen for file open requests.
Thread thread = new Thread(() -> {
try {
ServerSocket ss = new ServerSocket(22661, 0, InetAddress.getLoopbackAddress());
while (true) {
Socket socket = ss.accept();
DataInputStream stream = new DataInputStream(socket.getInputStream());
try {
while (true) {
String path = stream.readUTF();
Platform.runLater(() -> {
Main.instance.mainStage.toFront();
MainWindow.overviewActivity.handleOpenedFile(new File(path));
});
}
} catch (EOFException e) {
// End of file set.
}
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
});
thread.setName("File open request listener");
thread.setDaemon(true);
thread.start();
return false; // Keep loading.
}
// App is already running and not on Mac, so try and make the app notice.
try {
Socket client = new Socket(InetAddress.getLoopbackAddress(), 22661);
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
for (Path path : filesToOpen) dos.writeUTF(path.toAbsolutePath().toString());
client.close();
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public static void handleMacFileOpenRequests() {
// This is only for MacOS, where the OS single instances us by default and sends us a message at startup to ask
// us to open a file. It requires internal APIs.
com.sun.glass.ui.Application app = com.sun.glass.ui.Application.GetApplication();
com.sun.glass.ui.Application.EventHandler old = app.getEventHandler();
app.setEventHandler(new com.sun.glass.ui.Application.EventHandler() {
@Override
public void handleQuitAction(com.sun.glass.ui.Application app, long time) {
old.handleQuitAction(app, time);
}
@Override
public boolean handleThemeChanged(String themeName) {
return old.handleThemeChanged(themeName);
}
@Override
public void handleOpenFilesAction(com.sun.glass.ui.Application app, long time, String[] files) {
for (String strPath : files) {
if (strPath.equals("com.intellij.rt.execution.application.AppMain") || strPath.contains(".jar:"))
continue; // Only happens in dev environment.
Main.log.info("OS is requesting that we open " + strPath);
Platform.runLater(() -> {
MainWindow.overviewActivity.handleOpenedFile(new File(strPath));
});
}
}
});
}
}