JavaScript to Java Applet using DeployJava.js to run commandline - java

I am pretty new to Java. I want to create a Java Applet that will allow my JavaScript to pass a commandline to the Java Applet. This will only ever be run on my development machine - no need to remind me what a security issue that is. The use-case is that I have an introspector for my ExtJS app that allows me to display the classes. I want to be able to click a class, pass the relevant pathname to the Applet and have that file open in Eclipse for editing.
I am using Win7x64, jre 1.7
So, to get Eclipse to open the file from the commandline the command is:
D:\Eclipse\eclipse.exe --launcher.openFile C:\mytestfile.js
This works.
I have written the Applet, self signed it and tested the say() method using the code shown below. That works. However when I run the executecmd() method, I don't get any output. If I comment out the whole try/catch block so that I am simply returning the cmd string passed in, the method works. Therefore, I suspect that I have the try catch incorrectly setup and since my Java skills and knowledge of the exceptions are primitive I am lost.
Can anyone help me please? At least to get some output returned, if not how to actually run the command line passed in?
And, I am passing the whole command line because when I have this working I would like to share it (since the Ext introspector is really useful). Other developers will be using different editors so this way they can use it by passing their specific commandline.
Thanks!
Murray
My HTML test page:
<html>
<head>
<meta charset="UTF-8">
<title>Test Run</title>
<script src="http://www.java.com/js/deployJava.js"></script>
<script>
var attributes = { id:'testapp', code:'systemcmd.Runcmd', archive:'runcmd.jar', width:300, height:50} ;
var parameters = {} ;
deployJava.runApplet(attributes, parameters, '1.6');
</script>
</head>
<body>
<p>Hello</p>
<script type="text/javascript">
//alert(testapp.say("Hello test")); // This works
var command = "D:\Eclipse\eclipse.exe --launcher.openFile C:\mytestfile.js";
alert(testapp.executecmd(command)); // Nothing returned at all.
</script>
</body>
</html>
My class:
package systemcmd;
import java.applet.Applet;
import java.io.IOException;
import java.security.AccessController;
//import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
public class Runcmd extends Applet {
private static final long serialVersionUID = -4370650602318597069L;
/**
* #param args
*/
public static void main(String[] args) {
}
public String say(String arg)
{
String msg[] = {null};
msg[0] = "In Say. You said: " + arg;
String output ="";
for(String str: msg)
output=output+str;
return output;
}
public String executecmd(final String cmd) throws IOException
{
final String msg[] = {null};
String output ="";
msg[0] = "In executecmd, cmd="+cmd;
try {
try {
AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws IOException { //RuntimeException,
msg[1] = " Pre exec()";
Runtime.getRuntime().exec(cmd);
msg[2] = " Post exec()";
return null;
}
}
);
} catch (PrivilegedActionException e) {
msg[3] = " Caught PrivilegedActionException:"+ e.toString();
throw (IOException) e.getException();
}
}
catch (Exception e) {
msg[4] = " Command:" + cmd + ". Exception:" + e.toString();
}
msg[5] = " End of executecmd.";
for(String str: msg)
output=output+str;
return output;
}
}

Set Eclipse as the default consumer for .java files and use Desktop.open(File) which..
Launches the associated application to open the file.

Ok, #Andrew. Some progress, thank you!
I set the default program for *.js files to Eclipse and if I double click a file it opens in Eclipse. All good.
I then had success running the following using RunAs Java Application - the test file opened in Eclipse. Getting closer!
public class Runcmd extends Applet {
File file;
private static Desktop desktop;
private static final long serialVersionUID = -4370650602318597069L;
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
System.out.println("hello");
if (Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
}
File file = new File("C:\\sites\\test.js");
// This works if I execute it from the Eclipse RunsAs Java Application.
// ie the file is opened in Eclipse for editing.
// And, if I specify a non-existant file, it correctly throws and prints the error
try {
desktop.open(file);
} catch (Exception ioe) {
ioe.printStackTrace();
System.out.println("Error: " + ioe.toString());
}
}}
However, when I added the following method and ran it via the DeployJava.js (as per my original post above), I get the following output returned with the error appearing whether or not the jar is self signed.
Started: , Desktop is supported , Error:
java.security.AccessControlException: access denied
("java.awt.AWTPermission" "showWindowWithoutWarningBanner")
public static String openfile(String arg) {
String output = "Started: ";
File file = new File("C:\\sites\\test.js");
if (Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
output = output + ", Desktop is supported ";
}
try {
desktop.open(file);
} catch (Exception ioe) {
output = output + ", Error: " + ioe.toString();
}
return output + arg;
}
So, what do I need to add to get around the apparent security issue? I have read the docs and the tutorials and I am going around in circles! There seems to be a lot of conflicting advice. :-(
Thanks again,
Murray

Related

How do I make a new main class? There is already one made but its not its own .java file and currently does not work

I am using Lobo Browser in NetBeans 11.2 and I cant run the program because NetBeans cannot read which file has the Main class which is in the main browser file (main class of main browser code below)
I would like to get this working because I need some code that I want to steal but I would like to see how the browser runs first.
public static void main(final String[] args) {
// Detect if we are running on mac
if (isMac()) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
System.setProperty("dock.name", "LoboBrowser");
}
// Checking for stack allows us to call AccessController.doPrivileged()
// which in turn allows us to reduce the permissions on Uno codesource
final int stackDepth = Thread.currentThread().getStackTrace().length;
if (stackDepth > 11) {
System.err.println("Stack depth (" + stackDepth + ") is too deep! Quitting as a safety precaution");
Thread.dumpStack();
System.exit(1);
} else {
privilegedLaunch(args);
}
}
private static void launch(final String[] args) {
try {
final SSLSocketFactory socketFactory = TrustManager.makeSSLSocketFactory(ReuseManager.class.getResourceAsStream("/trustStore.certs"));
ReuseManager.getInstance().launch(args, socketFactory);
} catch (final Exception err) {
final StringWriter swriter = new StringWriter();
final PrintWriter writer = new PrintWriter(swriter);
err.printStackTrace(writer);
writer.flush();
JOptionPane.showMessageDialog(new JFrame(),
"An unexpected error occurred during application startup:\r\n" + swriter.toString(),
"ERROR", JOptionPane.ERROR_MESSAGE);
System.err.println(swriter.toString());
System.exit(1);
}
}
I believe you have to put the main method with in a class as described here http://tutorials.jenkov.com/java/main-method.html. I know in net beans you can tell it what class to try to run by I think right clicking the run then selecting what file to run and if its set up correctly it will run the file.

Runtime exec command working when when run from terminal but not eclipse

I'm trying to use tesseract to do OCR on an image in java. I realize there are wrappers like Tess4J that provide a bunch more functionality and stuff, but I've been struggling to get it set up properly. Simply running a one-line command with Runtime is really all I need anyways since this is just a personal little project and doesn't need to work on other computers or anything.
I have this code:
import java.io.IOException;
public class Test {
public static void main(String[] args) {
System.out.println(scan("full-path-to-test-image"));
}
public static String scan(String imgPath) {
String contents = "";
String cmd = "[full-path-to-tesseract-binary] " + imgPath + " stdout";
try { contents = execCmd(cmd); }
catch (IOException e) { e.printStackTrace(); }
return contents;
}
public static String execCmd(String cmd) throws java.io.IOException {
java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
}
When it's compiled and run directly from terminal, it works perfectly. When I open the exact same file in eclipse, however, it gives an IOException:
java.io.IOException: Cannot run program "tesseract": error=2, No such file or directory
What's going on? Thank you for any help.
Check the working folder in the run configuration for the Test class in Eclipse. I bet it's different from the one when you run the same program from a terminal.

Finding batch file using parameter in java

I have a batch file (test.bat) which has the command copy NUL test.txt. I have a java program, when i run it and when i enter a URL in the web browser e.g http://localhost:8080/runbatchfileparam, i get a result as either {"result":true} or {"result":false}. True means the java application has executed the batch file correctly (test.txt is created under the directory).
What i want to do now is, i want the java program to be able to take in parameters. E.g. User should be able to enter http://localhost:8080/runbatchfileparam/testabc.bat as the URL in web browser and the result should be {"result":true} if testabc.bat file is found and is executed (under desktop) and {"result":false} if the testabc.bat file is not found and not executed . (Note: All batch files are created under desktop filepath: C:/Users/attsuap1/Desktop)
I have edited my controller to take in a parameter and done the #PathVariable. In my codes, the fileName variable refers to the batch file name that i have created (test.bat, test123.bat) Command in test.bat: copy NUL test.txt Command in test123.bat: copy NUL test123.txt. However, i keep getting the result as {"result": false}. Which means the java program is not able to find the batch file and execute it.
Here are my codes:
RunBatchFile.java
public ResultFormat runBatch(String fileName) {
String var = fileName;
String filePath = "C:/Users/attsuap1/Desktop" + var;
try {
Process p = Runtime.getRuntime().exec(filePath);
int exitVal = p.waitFor();
return new ResultFormat(exitVal == 0);
} catch (Exception e) {
e.printStackTrace();
return new ResultFormat(false);
}
}
ResultFormat.java
private boolean result;
public ResultFormat(boolean result) {
this.result = result;
}
public boolean getResult() {
return result;
}
BatchFileController
private static final String template = "Sum, %s!";
#RequestMapping("/runbatchfileparam/{param}")
public ResultFormat runbatchFile(#PathVariable("param") String fileName ) {
RunBatchFile rbf = new RunBatchFile();
return rbf.runBatch(fileName);
}
Application.java
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
What do i have to edit or what should i add to the codes to achieve what i want?
After this line:
String filePath = "C:/Users/attsuap1/Desktop" + var;
Try to print the contents of filePath, i suspect that you come up with something like this:
C:/Users/attsuap1/Desktoptestabc.bat

Self-destructing application

Along the lines of "This tape will self-destruct in five seconds. Good luck, Jim"...
Would it be possible for an application to delete itself (or it's executable wrapper form) once a preset time of use or other condition has been reached?
Alternatively, what other approaches could be used to make the application useless?
The aim here is to have a beta expire, inviting users to get a more up-to-date version.
It is possible. To get around the lock on the JAR file, your application may need to spawn a background process that waits until the JVM has exited before deleting stuff.
However, this isn't bomb-proof. Someone could install the application and then make the installed files and directories read-only so that your application can't delete itself. The user (or their administrator) via the OS'es access control system has the final say on what files are created and deleted.
If you control where testers download your application, you could use an automated build system (e.g. Jenkins) that you could create a new beta versions every night that has a hard-coded expiry date:
private static final Date EXPIRY_DATE = <90 days in the future from build date>;
the above date is automatically inserted by the build process
if (EXPIRY_DATE.before(new Date()) {
System.out.println("Get a new beta version, please");
System.exit(1);
}
Mix that with signed and sealed jars, to put obstacles in the way of decompiling the bytecode and providing an alternative implementation that doesn't include that code, you can hand out a time-expiring beta of the code.
The automated build system could be configured to automatically upload the beta version to the server hosting the download version.
Since Windows locks the JAR file while it is running, you cannot delete it from your own Java code hence you need a Batch file:
private static void selfDestructWindowsJARFile() throws Exception
{
String resourceName = "self-destruct.bat";
File scriptFile = File.createTempFile(FilenameUtils.getBaseName(resourceName), "." + FilenameUtils.getExtension(resourceName));
try (FileWriter fileWriter = new FileWriter(scriptFile);
PrintWriter printWriter = new PrintWriter(fileWriter))
{
printWriter.println("taskkill /F /IM \"java.exe\"");
printWriter.println("DEL /F \"" + ProgramDirectoryUtilities.getCurrentJARFilePath() + "\"");
printWriter.println("start /b \"\" cmd /c del \"%~f0\"&exit /b");
}
Desktop.getDesktop().open(scriptFile);
}
public static void selfDestructJARFile() throws Exception
{
if (SystemUtils.IS_OS_WINDOWS)
{
selfDestructWindowsJARFile();
} else
{
// Unix does not lock the JAR file so we can just delete it
File directoryFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath();
Files.delete(directoryFilePath.toPath());
}
System.exit(0);
}
ProgramDirectoryUtilities class:
public class ProgramDirectoryUtilities
{
private static String getJarName()
{
return new File(ProgramDirectoryUtilities.class.getProtectionDomain()
.getCodeSource()
.getLocation()
.getPath())
.getName();
}
public static boolean isRunningFromJAR()
{
String jarName = getJarName();
return jarName.contains(".jar");
}
public static String getProgramDirectory()
{
if (isRunningFromJAR())
{
return getCurrentJARDirectory();
} else
{
return getCurrentProjectDirectory();
}
}
private static String getCurrentProjectDirectory()
{
return new File("").getAbsolutePath();
}
public static String getCurrentJARDirectory()
{
try
{
return getCurrentJARFilePath().getParent();
} catch (URISyntaxException exception)
{
exception.printStackTrace();
}
throw new IllegalStateException("Unexpected null JAR path");
}
public static File getCurrentJARFilePath() throws URISyntaxException
{
return new File(ProgramDirectoryUtilities.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
}
}
Solution inspired by this question.
Here is a better method for Windows:
private static void selfDestructWindowsJARFile() throws Exception
{
String currentJARFilePath = ProgramDirectoryUtilities.getCurrentJARFilePath().toString();
Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd /c ping localhost -n 2 > nul && del \"" + currentJARFilePath + "\"");
}
Here is the original answer.
it is pretty possible i guess. maybe you can delete the jar like this and make sure the application vanishes given that you have the rights.
File jar = new File(".\\app.jar");
jar.deleteOnExit();
System.exit(0);
also using something like Nullsoft Scriptable Install System which enables you to write your own installed/uninstaller should help.

Prevent launching multiple instances of a java application

I want to prevent the user from running my java application multiple times in parallel.
To prevent this, I have created a lock file when am opening the application, and delete the lock file when closing the application.
When the application is running, you can not open an another instance of jar. However, if you kill the application through task manager, the window closing event in the application is not triggered and the lock file is not deleted.
How can I make sure the lock file method works or what other mechanism could I use?
You could use a FileLock, this also works in environments where multiple users share ports:
String userHome = System.getProperty("user.home");
File file = new File(userHome, "my.lock");
try {
FileChannel fc = FileChannel.open(file.toPath(),
StandardOpenOption.CREATE,
StandardOpenOption.WRITE);
FileLock lock = fc.tryLock();
if (lock == null) {
System.out.println("another instance is running");
}
} catch (IOException e) {
throw new Error(e);
}
Also survives Garbage Collection.
The lock is released once your process ends, doesn't matter if regular exit or crash or whatever.
Similar discussion is at
http://www.daniweb.com/software-development/java/threads/83331
Bind a ServerSocket. If it fails to bind then abort the startup. Since a ServerSocket can be bound only once, only single instsances of the program will be able to run.
And before you ask, no. Just because you bind a ServerSocket, does not mean you are open to network traffic. That only comes into effect once the program starts "listening" to the port with accept().
I see two options you can try:
Use a Java shutdown hook
Have your lock file hold the main process number. The process should exist when you lanuch another instance. If it's not found in your system, you can assume that the lock can be dismissed and overwritten.
Creating a server socket, bounds to a specific port with a ServerSocket instance as the application starts is a straight way.
Note that ServerSocket.accept() blocks, so running it in its own thread makes sense to not block the main Thread.
Here is an example with a exception thrown as detected :
public static void main(String[] args) {
assertNoOtherInstanceRunning();
... // application code then
}
public static void assertNoOtherInstanceRunning() {
new Thread(() -> {
try {
new ServerSocket(9000).accept();
} catch (IOException e) {
throw new RuntimeException("the application is probably already started", e);
}
}).start();
}
You could write the process id of the process that created the lock file into the file.
When you encounter an existing lock file, you do not just quit, but you check if the process with that id is still alive. If not, you can go ahead.
You can create a Server socket like
new ServerSocket(65535, 1, InetAddress.getLocalHost());
at very beginning of your code. Then if AddressAlreadyInUse exception caught in main block you can display the appropriate message.
There are already available java methods in File class to achieve the same. The method is deleteOnExit() which ensure the file is automatically deleted when the JVM exits. However, it does not cater to forcible terminations. One should use FileLock in case of forcible termination.
For more details check, https://docs.oracle.com/javase/7/docs/api/java/io/File.html
Thus code snippet which could be used in the main method can be like :
public static void main(String args[]) throws Exception {
File f = new File("checkFile");
if (!f.exists()) {
f.createNewFile();
} else {
System.out.println("App already running" );
return;
}
f.deleteOnExit();
// whatever your app is supposed to do
System.out.println("Blah Blah")
}
..what other mechanism could I use?
If the app. has a GUI it can be launched using Java Web Start. The JNLP API provided to web-start offers the SingleInstanceService. Here is my demo. of the SingleInstanceService.
You can write something like this.
If file exists try to delete it. if it is not able to delete. We can say that application is already running.
Now create the same file again and redirect the sysout and syserr.
This works for me
Simple lock and advanced lock
I developed 2 solutions for this problem. I was also looking for an easy way of doing this without using any libraries and a lot of code.
My solutions are based on: https://stackoverflow.com/a/46705579/10686802 which I have improved upon. Therefore I would like to thank #akshaya pandey and #rbento
Simple file lock
package YOUR_PACKAGE_NAME;
import java.io.File;
import java.io.IOException;
/**
* Minimal reproducible example (MRE) - Example of a simple lock file.
* #author Remzi Cavdar - ict#remzi.info - #Remzi1993
*/
public class Main {
public static void main(String[] args) {
/*
* Prevents the user of starting multiple instances of the application.
* This is done by creating a temporary file in the app directory.
* The temp file should be excluded from git and is called App.lock in this example.
*/
final File FILE = new File("App.lock");
try {
if (FILE.createNewFile()) {
System.out.println("Starting application");
} else {
System.err.println("The application is already running!");
return;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
/*
* Register a shutdown hook to delete the lock file when the application is closed. Even when forcefully closed
* with the task manager. (Tested on Windows 11 with JavaFX 19)
*/
FILE.deleteOnExit();
// Whatever your app is supposed to do
}
}
Advanced lock
package YOUR_PACKAGE_NAME;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
/**
* Minimal reproducible example (MRE) - Example of a more advanced lock system.
* #author Remzi Cavdar - ict#remzi.info - #Remzi1993
*/
public class Main {
public static void main(String[] args) {
/*
* Prevents the user of starting multiple instances of the application.
* This is done by creating a temporary file in the app directory.
* The temp file should be excluded from git and is called App.lock in this example.
*/
final File FILE = new File("App.lock");
if (FILE.exists()) {
System.err.println("The application is already running!");
return;
}
try (
FileOutputStream fileOutputStream = new FileOutputStream(FILE);
FileChannel channel = fileOutputStream.getChannel();
FileLock lock = channel.lock()
) {
System.out.println("Starting application");
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
/*
* Register a shutdown hook to delete the lock file when the application is closed. Even when forcefully closed
* with the task manager. (Tested on Windows 11 with JavaFX 19)
*/
FILE.deleteOnExit();
// Whatever your app is supposed to do
}
}
Testing
Tested on: 31-10-2022
Tested OS: Windows 11 - Version 21H2 (OS Build 22000.1098)
Tested with: OpenJDK 19 - Eclipse Temurin JDK with Hotspot 19+36(x64)
I closed the application and also forcefully closed the application with task manager on Windows both times the lock file seems to be deleted upon (force) close.
I struggled with this same problem for a while... none of the ideas presented here worked for me. In all cases, the lock (file, socket or otherwise) did not persist into the 2nd process instance, so the 2nd instance still ran.
So I decided to try an old school approach to simply crate a .pid file with the process id of the first process. Then any 2nd process would quit if it finds the .pid file, and also the process number specified in the file is confirmed to be still running. This approach worked for me.
There is a fair bit of code, which I provide here in full for your use... a complete solution.
package common.environment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.*;
import java.nio.charset.Charset;
public class SingleAppInstance
{
private static final #Nonnull Logger log = LogManager.getLogger(SingleAppInstance.class.getName());
/**
* Enforces that only a single instance of the given component is running. This
* is resilient to crashes, unexpected reboots and other forceful termination
* scenarios.
*
* #param componentName = Name of this component, for disambiguation with other
* components that may run simultaneously with this one.
* #return = true if the program is the only instance and is allowed to run.
*/
public static boolean isOnlyInstanceOf(#Nonnull String componentName)
{
boolean result = false;
// Make sure the directory exists
String dirPath = getHomePath();
try
{
FileUtil.createDirectories(dirPath);
}
catch (IOException e)
{
throw new RuntimeException(String.format("Unable to create directory: [%s]", dirPath));
}
File pidFile = new File(dirPath, componentName + ".pid");
// Try to read a prior, existing pid from the pid file. Returns null if the file doesn't exist.
String oldPid = FileUtil.readFile(pidFile);
// See if such a process is running.
if (oldPid != null && ProcessChecker.isStillAllive(oldPid))
{
log.error(String.format("An instance of %s is already running", componentName));
}
// If that process isn't running, create a new lock file for the current process.
else
{
// Write current pid to the file.
long thisPid = ProcessHandle.current().pid();
FileUtil.createFile(pidFile.getAbsolutePath(), String.valueOf(thisPid));
// Try to be tidy. Note: This won't happen on exit if forcibly terminated, so we don't depend on it.
pidFile.deleteOnExit();
result = true;
}
return result;
}
public static #Nonnull String getHomePath()
{
// Returns a path like C:/Users/Person/
return System.getProperty("user.home") + "/";
}
}
class ProcessChecker
{
private static final #Nonnull Logger log = LogManager.getLogger(io.cpucoin.core.platform.ProcessChecker.class.getName());
static boolean isStillAllive(#Nonnull String pidStr)
{
String OS = System.getProperty("os.name").toLowerCase();
String command;
if (OS.contains("win"))
{
log.debug("Check alive Windows mode. Pid: [{}]", pidStr);
command = "cmd /c tasklist /FI \"PID eq " + pidStr + "\"";
}
else if (OS.contains("nix") || OS.contains("nux"))
{
log.debug("Check alive Linux/Unix mode. Pid: [{}]", pidStr);
command = "ps -p " + pidStr;
}
else
{
log.warn("Unsupported OS: Check alive for Pid: [{}] return false", pidStr);
return false;
}
return isProcessIdRunning(pidStr, command); // call generic implementation
}
private static boolean isProcessIdRunning(#Nonnull String pid, #Nonnull String command)
{
log.debug("Command [{}]", command);
try
{
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec(command);
InputStreamReader isReader = new InputStreamReader(pr.getInputStream());
BufferedReader bReader = new BufferedReader(isReader);
String strLine;
while ((strLine = bReader.readLine()) != null)
{
if (strLine.contains(" " + pid + " "))
{
return true;
}
}
return false;
}
catch (Exception ex)
{
log.warn("Got exception using system command [{}].", command, ex);
return true;
}
}
}
class FileUtil
{
static void createDirectories(#Nonnull String dirPath) throws IOException
{
File dir = new File(dirPath);
if (dir.mkdirs()) /* If false, directories already exist so nothing to do. */
{
if (!dir.exists())
{
throw new IOException(String.format("Failed to create directory (access permissions problem?): [%s]", dirPath));
}
}
}
static void createFile(#Nonnull String fullPathToFile, #Nonnull String contents)
{
try (PrintWriter writer = new PrintWriter(fullPathToFile, Charset.defaultCharset()))
{
writer.print(contents);
}
catch (IOException e)
{
throw new RuntimeException(String.format("Unable to create file at %s! %s", fullPathToFile, e.getMessage()), e);
}
}
static #Nullable String readFile(#Nonnull File file)
{
try
{
try (BufferedReader fileReader = new BufferedReader(new FileReader(file)))
{
StringBuilder result = new StringBuilder();
String line;
while ((line = fileReader.readLine()) != null)
{
result.append(line);
if (fileReader.ready())
result.append("\n");
}
return result.toString();
}
}
catch (IOException e)
{
return null;
}
}
}
To use it, simply invoke it like this:
if (!SingleAppInstance.isOnlyInstanceOf("my-component"))
{
// quit
}
I hope you find this helpful.
Finally I found really simple library to achieve this. You can you use JUniqe.
The JUnique library can be used to prevent a user to run at the same
time more instances of the same Java application.
This is an example how to use it from the documentation
public static void main(String[] args) {
String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
// Start sequence here
}
}
here is a pretty rudimental approach.
If your application is launched from a script, check the running java/javaw processes and their command line before launch
In windows
REM check if there is a javaw process running your.main.class
REM if found, go to the end of the script and skip the launch of a new instance
WMIC path win32_process WHERE "Name='javaw.exe'" get CommandLine 2>nul | findstr your.main.class >nul 2>&1
if %ERRORLEVEL% EQU 0 goto:eof
javaw your.main.class

Categories