Determining parameters on crawler4j - java

I am trying to use crawler4j like it was shown to be used in this example and no matter how I define the number of crawlers or change the root folder I continue to get this error from the code stating:
"Needed parameters:
rootFolder (it will contain intermediate crawl data)
numberOfCralwers (number of concurrent threads)"
The main code is below:
public class Controller {
public static void main(String[] args) throws Exception {
if (args.length != 2) {
System.out.println("Needed parameters: ");
System.out.println("\t rootFolder (it will contain intermediate crawl data)");
System.out.println("\t numberOfCralwers (number of concurrent threads)");
return;
}
/*
* crawlStorageFolder is a folder where intermediate crawl data is
* stored.
*/
String crawlStorageFolder = args[0];
/*
* numberOfCrawlers shows the number of concurrent threads that should
* be initiated for crawling.
*/
int numberOfCrawlers = Integer.parseInt(args[1]);
There was a similar question asking exactly what I want to know here , but I didn't quite understand the solution, like where I was to type java BasicCrawler Controller "arg1" "arg2" . I am running this code on Eclipse and I am still fairly new to the world of programming. I would really appreciate it if someone helped me understand this problem

If you aren't giving any arguments when you are running the file, you will get that error.
Put the following as comment sin your code or delete it.
if (args.length != 2) {
System.out.println("Needed parameters: ");
System.out.println("\t rootFolder (it will contain intermediate crawl data)");
System.out.println("\t numberOfCralwers (number of concurrent threads)");
return;
}
And after that set your root folder to the one where you want to store the meta data.

To use crawler4j in your project you must create two classes. One of the them is CrawlController (Which start crawler according to the parameters) and the other is Crawler.
Just run the main method in the Controller class and see crawled pages
Here is Controller.java file:
import edu.uci.ics.crawler4j.crawler.CrawlConfig;
import edu.uci.ics.crawler4j.crawler.CrawlController;
import edu.uci.ics.crawler4j.fetcher.PageFetcher;
import edu.uci.ics.crawler4j.robotstxt.RobotstxtConfig;
import edu.uci.ics.crawler4j.robotstxt.RobotstxtServer;
public class Controller {
public static void main(String[] args) throws Exception {
RobotstxtConfig robotstxtConfig2 = new RobotstxtConfig();
System.out.println(robotstxtConfig2.getCacheSize());
System.out.println(robotstxtConfig2.getUserAgentName());
String crawlStorageFolder = "/crawler/testdata";
int numberOfCrawlers = 4;
CrawlConfig config = new CrawlConfig();
config.setCrawlStorageFolder(crawlStorageFolder);
PageFetcher pageFetcher = new PageFetcher(config);
RobotstxtConfig robotstxtConfig = new RobotstxtConfig();
System.out.println(robotstxtConfig.getCacheSize());
System.out.println(robotstxtConfig.getUserAgentName());
RobotstxtServer robotstxtServer = new RobotstxtServer(robotstxtConfig, pageFetcher);
CrawlController controller = new CrawlController(config,
pageFetcher, robotstxtServer);
controller.addSeed("http://cyesilkaya.wordpress.com/");
controller.start(Crawler.class, numberOfCrawlers);
}
}
Here is Crawler.java file:
import java.io.IOException;
import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.crawler.WebCrawler;
import edu.uci.ics.crawler4j.url.WebURL;
public class Crawler extends WebCrawler {
#Override
public boolean shouldVisit(WebURL url) {
// you can write your own filter to decide crawl the incoming URL or not.
return true;
}
#Override
public void visit(Page page) {
String url = page.getWebURL().getURL();
try {
String url = page.getWebURL().getURL();
System.out.println("URL: " + url);
}
catch (IOException e) {
}
}
}

In Eclipse :
->Click on run
->Click on run configurations...
In the pop-up window :
First, left column: make sure that your application is selected in sub-dir Java Application, else create a new (Click on new).
Then in the central Window, go on "Arguments"
Write your arguments under "Program arguments" Once you have written your first argument press enter for the seconde arguments, and so on... (=newline because args is a [ ])
Then click Apply
And click Run.

Related

Why views does not increase when java opens the pages?

I have a code which uses tor every time to get a new IP address, and then it opens a blog page, but then also the views counter of the blog do not increases?
import java.io.InputStream;
import java.net.*;
public class test {
public static void main (String args [])throws Exception {
System.out.println (test.getData("http://checkip.amazonaws.com"));
System.out.println (test.getData("***BLOG URL***"));
}
public static String getData(String ur) throws Exception {
String TOR_IP="127.0.0.1", TOR_PORT="9050";
System.setProperty("java.net.preferIPv4Stack" , "true");
System.setProperty("socksProxyHost", TOR_IP);
System.setProperty("socksProxyPort", TOR_PORT);
URL url = new URL(ur);
String s = "";
URLConnection c = url.openConnection();
c.connect();
InputStream i = c.getInputStream();
int j ;
while ((j = i.read()) != -1) {
s+=(char)j;
}
return s;
}
}
This I just made to understand what they have to pass this little auto script.
This is an evolving field, the blog sites try to detect and thwart cheating. Wordpress in particular excludes (https://en.support.wordpress.com/stats/):
visits from browsers that do not execute javascript or load images
In other words just hitting the page doesn't count. You need to fetch all the resources and possibly execute the JavaScript as well.

Creating a VM on Softlayer based on public image ( using Java API client)

I am using Java Client to connect with soft layer API. I am able to create a new VM with the OS using the below code.
guest.setHostname("vstest2");
guest.setDomain("softlayer.com");
guest.setStartCpus(2L);
guest.setHourlyBillingFlag(true);
guest.setLocalDiskFlag(true);
guest.setOperatingSystemReferenceCode("UBUNTU_14_64");
But I am unable to create a new VM through already exisitng public image.
guest.setHostname("vstest2");
guest.setDomain("softlayer.com");
guest.setStartCpus(2L);
guest.setHourlyBillingFlag(true);
guest.setLocalDiskFlag(true);
Group blockDevice = new Group();
blockDevice.setGlobalIdentifier("ce3f5ea3-893a-4992-ad14-5bcd99d9b32a");
guest.setBlockDeviceTemplateGroup(blockDevice);
Please help in creating a new VM by using a public image. The error I got is
Caused by: com.softlayer.api.ApiException$Internal: Invalid value provided for 'blockDevices'. Block devices may not be provided when using an image template.(code: SoftLayer_Exception_InvalidValue, status: 500)
I simply want to create a new VM based on the public image template. But unable to find a way to do it.
I was able to order a VSI using the global identifier: ce3f5ea3-893a-4992-ad14-5bcd99d9b32a
Here the java script that I used:
package VirtualGuest;
import com.softlayer.api.ApiClient;
import com.softlayer.api.RestApiClient;
import com.softlayer.api.service.Location;
import com.softlayer.api.service.virtual.Guest;
import com.softlayer.api.service.virtual.guest.block.device.template.Group;
/**
* Created by Ruber Cuellar on 5/3/2016.
*/
public class CreateObject {
public CreateObject(){
// Declare username and api key
String username = "set me";
String apiKey = "set me";
// Get Api Client and service
ApiClient client = new RestApiClient().withCredentials(username, apiKey);
Guest.Service guestService = Guest.service(client);
Guest guest = new Guest();
guest.setHostname("rcvtest-3");
guest.setDomain("softlayer.com");
guest.setStartCpus(2L);
guest.setHourlyBillingFlag(true);
guest.setLocalDiskFlag(true);
guest.setMaxMemory(1L);
// Setting datacenter
Location newLocation = new Location();
newLocation.setName("sjc03");
guest.setDatacenter(newLocation);
// Setting image template
Group blockDevice = new Group();
blockDevice.setGlobalIdentifier("ce3f5ea3-893a-4992-ad14-5bcd99d9b32a");
guest.setBlockDeviceTemplateGroup(blockDevice);
try{
Guest result = guestService.createObject(guest);
System.out.println(result.getId());
} catch (Exception e)
{
System.out.println("Error: " + e);
}
}
public static void main(String [] args)
{
new CreateObject();
}
}
Try to do double check or can you provide the full code that you are trying, please?

find and call web service from uddi java

So I have been looking around for days and I still can't find a simple working method. This is what I am trying to do:
1 - Search and find web services registered in UDDI based on keywords
2 - Decide which service fits and use/call it
All this using Java (Eclipse).
I don't want to create my own uddi nor do I want to publish services, just find existing services stored in the public UDDI (I believe there's one, right?). I thought that these two tasks (find WS, call WS) would be easy and that it would be possible to find sample code to use, but I can't find any.
I came across Juddi while searching, but not sure if it works for my case and if it's worth installing.
Any tutorials? suggestions ? I found the following code, but can't find the jar file to use its libraries:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package uddi.createbulk;
import javax.xml.bind.JAXB;
import org.apache.juddi.v3.client.config.UDDIClient;
import org.apache.juddi.v3.client.config.UDDIClientContainer;
import org.apache.juddi.v3.client.transport.Transport;
import org.apache.juddi.v3_service.JUDDIApiPortType;
import org.uddi.api_v3.*;
import org.uddi.v3_service.UDDIInquiryPortType;
import org.uddi.v3_service.UDDIPublicationPortType;
import org.uddi.v3_service.UDDISecurityPortType;
/**
*
* #author Alex
*/
public class UddiFindService {
private static UDDISecurityPortType security = null;
private static JUDDIApiPortType juddiApi = null;
private static UDDIPublicationPortType publish = null;
private static UDDIInquiryPortType inquiry = null;
public UddiFindService() {
try {
// create a manager and read the config in the archive;
// you can use your config file name
UDDIClient clerkManager = new UDDIClient("META-INF/simple-publish-uddi.xml");
// register the clerkManager with the client side container
UDDIClientContainer.addClient(clerkManager);
// a ClerkManager can be a client to multiple UDDI nodes, so
// supply the nodeName (defined in your uddi.xml.
// The transport can be WS, inVM, RMI etc which is defined in the uddi.xml
Transport transport = clerkManager.getTransport("default");
// Now you create a reference to the UDDI API
security = transport.getUDDISecurityService();
juddiApi = transport.getJUDDIApiService();
publish = transport.getUDDIPublishService();
inquiry = transport.getUDDIInquiryService();
} catch (Exception e) {
e.printStackTrace();
}
}
public void find() {
try {
// Setting up the values to get an authentication token for the 'root' user ('root' user has admin privileges
// and can save other publishers).
GetAuthToken getAuthTokenRoot = new GetAuthToken();
getAuthTokenRoot.setUserID("root");
getAuthTokenRoot.setCred("root");
// Making API call that retrieves the authentication token for the 'root' user.
AuthToken rootAuthToken = security.getAuthToken(getAuthTokenRoot);
System.out.println("root AUTHTOKEN = " + rootAuthToken.getAuthInfo());
GetServiceDetail fs = new GetServiceDetail();
fs.setAuthInfo(rootAuthToken.getAuthInfo());
fs.getServiceKey().add("mykey");
ServiceDetail serviceDetail = inquiry.getServiceDetail(fs);
if (serviceDetail == null || serviceDetail.getBusinessService().isEmpty()) {
System.out.println("mykey is not registered");
} else {
JAXB.marshal(serviceDetail, System.out);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
UddiFindService sp = new UddiFindService();
sp.find();
}
}

JavaScript to Java Applet using DeployJava.js to run commandline

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

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