Ensure that there is only one instance : Runtime « Development Class « Java






Ensure that there is only one instance

        

/**
 *
    DEScribe - A Discrete Experience Sampling cross platform application
    Copyright (C) 2011
    Sbastien Faure <sebastien.faure3@gmail.com>,
    Bertrand Gros   <gros.bertrand@gmail.com>,
    Yannick Prie    <yannick.prie@univ-lyon1.fr>.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

//package api.utils;

/**
 * Class UniqueInstance.java
 * @description Limit the use of only one instance of DEScribe at a time
 * @author Sbastien Faure  <sebastien.faure3@gmail.com>
 * @author Bertrand Gros    <gros.bertrand@gmail.com>
 * @version 2011-01-28
 */
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Logger;

/**
Cette classe permet d'assurer l'unicit de l'instance de l'application. Deux applications ne peuvent pas tre lances
simultanment. Voici un exemple typique d'utilisation :
 *
 * <pre>
 * // Port  utiliser pour communiquer avec l'instance de l'application lance.
 * final int PORT = 32145;
 * // Message  envoyer  l'application lance lorsqu'une autre instance essaye de dmarrer.
 * final String MESSAGE = "nomDeMonApplication";
 * // Actions  effectuer lorsqu'une autre instance essaye de dmarrer.
 * final Runnable RUN_ON_RECEIVE = new Runnable() {
 * public void run() {
 * if(mainFrame != null) {
 * // Si la fentre n'est pas visible (uniquement dans le systray par exemple), on la rend visible.
 * if(!mainFrame.isVisible())
 * mainFrame.setVisible(true);
 * // On demande  la mettre au premier plan.
 * mainFrame.toFront();
 * }
 * }
 * });
 *
 * UniqueInstance uniqueInstance = new UniqueInstance(PORT, MESSAGE, RUN_ON_RECEIVE);
 * // Si aucune autre instance n'est lance...
 * if(uniqueInstance.launch()) {
 * // On dmarre l'application.
 * new MonApplication();
 * }
 * </pre>
 *
 * @author rom1v
 */
public class UniqueInstance {

    /** Port d'coute utilis pour l'unique instance de l'application. */
    private int port;
    /** Message  envoyer  l'ventuelle application dj lance. */
    private String message;
    /** Actions  effectuer lorsqu'une autre instance de l'application a indiqu qu'elle avait essay de dmarrer. */
    private Runnable runOnReceive;

    /**
     * Crer un gestionnaire d'instance unique de l'application.
     *
     * @param port
     * Port d'coute utilis pour l'unique instance de l'application.
     * @param message
     * Message  envoyer  l'ventuelle application dj lance, {@code null} si aucune action.
     * @param runOnReceive
     * Actions  effectuer lorsqu'une autre instance de l'application a indiqu qu'elle avait essay de
     * dmarrer, {@code null} pour aucune action.
     */
    public UniqueInstance(int port, String message, Runnable runOnReceive) {
        assert port > 0 && port < 1 << 16 : "Le port doit tre entre 1 et 65535";
        assert message != null || runOnReceive == null : "Il y a des actions  effectuer => le message ne doit pas tre null.";
        this.port = port;
        this.message = message;
        this.runOnReceive = runOnReceive;
    }

    /**
     * Crer un gestionnaire d'instance unique de l'application. Ce constructeur dsactive la communication entre
     * l'instance dj lance et l'instance qui essaye de dmarrer.
     *
     * @param port
     * Port d'coute utilis pour l'unique instance de l'application.
     */
    public UniqueInstance(int port) {
        this(port, null, null);
    }

    /**
     * Essaye de dmarrer le gestionnaire d'instance unique. Si l'initialisation a russi, c'est que l'instance est
     * unique. Sinon, c'est qu'une autre instance de l'application est dj lance. L'appel de cette mthode prvient
     * l'application dj lance qu'une autre vient d'essayer de se connecter.
     *
     * @return {@code true} si l'instance de l'application est unique.
     */
    public boolean launch() {
        /* Indique si l'instance du programme est unique. */
        boolean unique;

        try {
            /* On cre une socket sur le port dfini. */
            final ServerSocket server = new ServerSocket(port);

            /* Si la cration de la socket russit, c'est que l'instance du programme est unique, aucune autre n'existe. */
            unique = true;

            /* Si il y a des actions  faire lorsqu'une autre instance essaye de dmarrer... */
            if (runOnReceive != null) {

                /* On lance un Thread d'coute sur ce port. */
                Thread portListenerThread = new Thread() {

                    @Override
                    public void run() {
                        /* Tant que l'application est lance... */
                        while (true) {
                            try {
                                /* On attend qu'une socket se connecte sur le serveur. */
                                final Socket socket = server.accept();

                                /* Si une socket est connecte, on coute le message envoy dans un nouveau Thread. */
                                new Thread() {

                                    @Override
                                    public void run() {
                                        receive(socket);
                                    }
                                }.start();
                            } catch (IOException e) {
                                Logger.getLogger("UniqueInstance").warning("Attente de connexion de socket choue.");
                            }
                        }
                    }
                };

                /* Le Thread d'coute de port est dmon. */
                portListenerThread.setDaemon(true);

                /* On dmarre le Thread. */
                portListenerThread.start();
            }
        } catch (IOException e) {
            /* Si la cration de la socket choue, c'est que l'instance de n'est pas unique, une autre n'existe. */
            unique = false;

            /* Si des actions sont prvues par l'instance dj lance... */
            if (runOnReceive != null) {
                /*
                 * Dans ce cas, on envoie un message  l'autre instance de l'application pour lui demander d'avoir le
                 * focus (par exemple).
                 */
                send();
            }
        }
        return unique;
    }

    /**
     * Envoie un message  l'instance de l'application dj ouverte.
     */
    private void send() {
        PrintWriter pw = null;
        try {
            /* On se connecte sur la machine locale. */
            Socket socket = new Socket("localhost", port);

            /* On dfinit un PrintWriter pour crire sur la sortie de la socket. */
            pw = new PrintWriter(socket.getOutputStream());

            /* On crit le message sur la socket. */
            pw.write(message);
        } catch (IOException e) {
            Logger.getLogger("UniqueInstance").warning("criture sur flux de sortie de la socket chou.");
        } finally {
            if (pw != null) {
                pw.close();
            }
        }
    }

    /**
     * Reoit un message d'une socket s'tant connecte au serveur d'coute. Si ce message est le message de l'instance
     * unique, l'application demande le focus.
     *
     * @param socket
     * Socket connect au serveur d'coute.
     */
    private void receive(Socket socket) {
        Scanner sc = null;

        try {
            /* On n'coute que 5 secondes, si aucun message n'est reu, tant pis... */
            socket.setSoTimeout(5000);

            /* On dfinit un Scanner pour lire sur l'entre de la socket. */
            sc = new Scanner(socket.getInputStream());

            /* On ne lit qu'une ligne. */
            String s = sc.nextLine();

            /* Si cette ligne est le message de l'instance unique... */
            if (message.equals(s)) {
                /* On excute le code demand. */
                runOnReceive.run();
            }
        } catch (IOException e) {
            Logger.getLogger("UniqueInstance").warning("Lecture du flux d'entre de la socket chou.");
        } finally {
            if (sc != null) {
                sc.close();
            }
        }

    }
}

   
    
    
    
    
    
    
    
  








Related examples in the same category

1.Runtime.getRuntime().exec
2.Get Number of Available Processors
3.Execute system command
4.Determine when the application is about to exit
5.Getting the Size of the Java Memory Heap
6.Read all information that the child process sends to its standard output stream
7.Execute a command from code
8.Execute a command with more than one argument
9.Launch a Unix script with Java
10.Read output from a Command execution
11.Send an Input to a Command
12.From Runtime.exec() to ProcessBuilder
13.Get current size of heap in bytes
14.Get maximum size of heap in bytes.
15.Get amount of free memory within the heap in bytes.
16.Minimize all programs on Windows to show the Desktop
17.Command and its arguments supplied in an array
18.Execute a command with an argument that contains a space
19.Execute a command with an argument that contains a space: use array
20.Calculate process elapsed time
21.Registering Shutdown Hooks for Virtual Machine
22.Get memory information
23.Returns a description of the JVM.
24.Returns a description of the operating system and processor configuration.
25.Returns a report of used and available memory.
26.Returns used(max) memory in MB