package org.jtheque.osgi;
/*
* Copyright JTheque (Baptiste Wicht)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.jtheque.utils.collections.CollectionUtils;
import org.jtheque.utils.io.FileUtils;
import org.jtheque.utils.io.SocketUtils;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collection;
/**
* This class permit to have only one launched instance of the application.
*
* @author Baptiste Wicht
*/
final class ApplicationManager {
private static final String LOCALHOST = "127.0.0.1";
private static final int PORT = 12345;
private final Collection<Application> applications = CollectionUtils.newList(2);
private ServerSocket serverSocket;
private Thread thread;
/**
* Launch the application. If an other instance of the application is soon launched, call it and exit the current
* instance.
*/
public void tryLaunchApplication() {
try {
serverSocket = new ServerSocket(PORT);
registerApplication();
} catch (IOException e) {
LoggerFactory.getLogger(getClass()).debug("The application is already launched");
wakeUpApplication();
System.exit(0); //At this moment, nothing need to be released
}
}
/**
* Register the application. .
*/
private void registerApplication() {
thread = new ServerThread();
thread.start();
}
/**
* Call the another instance of JTheque.
*/
private void wakeUpApplication() {
Socket clientSocket = null;
PrintStream stream = null;
try {
clientSocket = new Socket(LOCALHOST, PORT);
stream = new PrintStream(clientSocket.getOutputStream());
stream.println("open");
} catch (UnknownHostException e) {
LoggerFactory.getLogger(getClass()).error("The host is unknown", e);
} catch (IOException e) {
LoggerFactory.getLogger(getClass()).error("I/O error", e);
} finally {
FileUtils.close(stream);
SocketUtils.close(clientSocket);
}
}
/**
* Close definitively all the open flows.
*/
public void closeInstance() {
stopClients();
stopServer();
SocketUtils.close(serverSocket);
}
/**
* Stop all the applications.
*/
private void stopClients() {
for (Application application : applications) {
application.interrupt();
}
}
/**
* Stop the server.
*/
private void stopServer() {
if (thread != null) {
thread.interrupt();
}
}
/**
* A thread for a client.
*
* @author Baptiste Wicht
*/
private final class ServerThread extends Thread {
@Override
public void run() {
while (!serverSocket.isClosed() && serverSocket != null) {
try {
Application application = new Application(serverSocket.accept());
applications.add(application);
application.start();
} catch (SocketException e1) {
LoggerFactory.getLogger(getClass()).debug("The socket has been closed. Normally no problems. ");
} catch (IOException e2) {
LoggerFactory.getLogger(getClass()).error(e2.getMessage(), e2);
interrupt();
}
}
}
@Override
public void interrupt() {
SocketUtils.close(serverSocket);
super.interrupt();
}
}
}