Я хотел бы ограничить свое приложение Eclipse-RCP одним экземпляром. Под этим я подразумеваю, что, как только пользователь открывает приложение в первый раз, он прослушивает порт и для второго доступа он должен открыть предыдущий экземпляр вместо того, чтобы показывать предупреждающее сообщение типа «уже запущен экземпляр»
Код моего приложения RCP:
Код интерфейса ApplicationInstanceListener.java
public interface ApplicationInstanceListener
{
public void newInstanceCreated();
}
ApplicationInstanceManager.java код
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class ApplicationInstanceManager {
private static ApplicationInstanceListener subListener;
/** Randomly chosen, but static, high socket number */
public static final int SINGLE_INSTANCE_NETWORK_SOCKET = 2020;
/** Must end with newline */
public static final String SINGLE_INSTANCE_SHARED_KEY = "$$NewInstance$$\n";
/**
* Registers this instance of the application.
*
* @return true if first instance, false if not.
*/
public static boolean registerInstance() {
// returnValueonerror should be true if lenient (allows app to run on network error) or false if strict.
boolean returnValueonerror = true;
// try to open network socket
// if success, listen to socket for new instance message, return true
// if unable to open, connect to existing and send new instance message, return false
try {
final ServerSocket socket = new ServerSocket(SINGLE_INSTANCE_NETWORK_SOCKET, 10, InetAddress
.getLocalHost());
System.out.println("Listening for application instances on socket " + SINGLE_INSTANCE_NETWORK_SOCKET);
Thread instanceListenerThread = new Thread(new Runnable() {
public void run() {
boolean socketClosed = false;
while (!socketClosed) {
if (socket.isClosed()) {
socketClosed = true;
} else {
try {
Socket client = socket.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String message = in.readLine();
if (SINGLE_INSTANCE_SHARED_KEY.trim().equals(message.trim())) {
System.out.println("Shared key matched - new application instance found");
fireNewInstance();
}
in.close();
client.close();
} catch (IOException e) {
socketClosed = true;
}
}
}
}
});
instanceListenerThread.start();
// listen
} catch (UnknownHostException e) {
System.out.println(e.getMessage());
return returnValueonerror;
} catch (IOException e) {
System.out.println("Port is already taken. Notifying first instance.");
try {
Socket clientSocket = new Socket(InetAddress.getLocalHost(), SINGLE_INSTANCE_NETWORK_SOCKET);
OutputStream out = clientSocket.getOutputStream();
out.write(SINGLE_INSTANCE_SHARED_KEY.getBytes());
out.close();
clientSocket.close();
System.out.println("Successfully notified first instance.");
return false;
} catch (UnknownHostException e1) {
System.out.println(e.getMessage());
return returnValueonerror;
} catch (IOException e1) {
System.out.println("Error connecting to local port for single instance notification");
System.out.println(e1.getMessage());
return returnValueonerror;
}
}
return true;
}
public static void setApplicationInstanceListener(ApplicationInstanceListener listener) {
subListener = listener;
}
private static void fireNewInstance() {
if (subListener != null) {
subListener.newInstanceCreated();
}
}
}
Application.java код
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
/**
* This class controls all aspects of the application's execution
*/
public class Application implements IApplication {
/*
* (non-Javadoc)
*
* @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.
* IApplicationContext)
*/
public Object start(IApplicationContext context) throws Exception {
if (!ApplicationInstanceManager.registerInstance()) {
// instance already running.
System.out
.println("Another instance of this application is already running. Exiting.");
MessageDialog
.openInformation(new Shell(), "Information",
"Another instance of this application is already running. Exiting.");
System.exit(0);
}
Display display = PlatformUI.createDisplay();
try {
int returnCode = PlatformUI.createAndRunWorkbench(display,
new ApplicationWorkbenchAdvisor());
if (returnCode == PlatformUI.RETURN_RESTART)
return IApplication.EXIT_RESTART;
else
return IApplication.EXIT_OK;
} finally {
display.dispose();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.equinox.app.IApplication#stop()
*/
public void stop() {
if (!PlatformUI.isWorkbenchRunning())
return;
final IWorkbench workbench = PlatformUI.getWorkbench();
final Display display = workbench.getDisplay();
display.syncExec(new Runnable() {
public void run() {
if (!display.isDisposed())
workbench.close();
}
});
}
}
Я взял простое приложение RCP с представлением в качестве шаблона.
Приведенный выше код работает нормально, но не открывает предыдущий экземпляр, например Skype или Windows Media Player , несмотря на то, что он показывает предупреждение, как показано ниже
Как показать или открыть предыдущий экземпляр при втором запуске приложения?