1+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2+
3+ /*
4+ Part of the Processing project - http://processing.org
5+
6+ Copyright (c) 2011 Ben Fry and Casey Reas
7+
8+ This program is free software; you can redistribute it and/or modify
9+ it under the terms of the GNU General Public License version 2
10+ as published by the Free Software Foundation.
11+
12+ This program is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with this program; if not, write to the Free Software Foundation,
19+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20+ */
21+ package processing .app ;
22+
23+ import java .io .BufferedReader ;
24+ import java .io .IOException ;
25+ import java .io .PrintWriter ;
26+ import java .net .InetAddress ;
27+ import java .net .ServerSocket ;
28+ import java .net .Socket ;
29+
30+ import javax .swing .SwingUtilities ;
31+
32+ import processing .core .PApplet ;
33+
34+
35+ /**
36+ * Class that handles a small server that prevents multiple instances of
37+ * Processing from running simultaneously. If there's already an instance
38+ * running, it'll handle opening a new empty sketch, or any files that had
39+ * been passed in on the command line.
40+ *
41+ * @author Peter Kalauskas, Ben Fry
42+ */
43+ public class SingleInstance {
44+ static final String SERVER_PORT = "instance_server.port" ;
45+ static final String SERVER_KEY = "instance_server.key" ;
46+
47+
48+ /**
49+ * Returns true if there's an instance of Processing already running.
50+ * @param filename Path to the PDE file that was opened, null if double-clicked
51+ * @return true if successfully launched on the other instance
52+ */
53+ static boolean exists (String [] args ) {
54+ return (Preferences .get (SERVER_PORT ) != null &&
55+ sendArguments (args , 5000 ));
56+ }
57+
58+
59+ static void createServer (final Platform platform ) {
60+ try {
61+ final ServerSocket ss = new ServerSocket (0 , 0 , InetAddress .getByName (null ));
62+ Preferences .set (SERVER_PORT , "" + ss .getLocalPort ());
63+ final String key = "" + Math .random ();
64+ Preferences .set (SERVER_KEY , key );
65+ Preferences .save ();
66+
67+ new Thread (new Runnable () {
68+ public void run () {
69+ while (true ) {
70+ try {
71+ Socket s = ss .accept (); // blocks (sleeps) until connection
72+ final BufferedReader reader = PApplet .createReader (s .getInputStream ());
73+ String receivedKey = reader .readLine ();
74+
75+ if (platform .base != null ) {
76+ if (key .equals (receivedKey )) {
77+ SwingUtilities .invokeLater (new Runnable () {
78+ public void run () {
79+ try {
80+ String filename = reader .readLine ();
81+ if (filename != null ) {
82+ platform .base .handleOpen (filename );
83+ // see if there is more than one file that was passed in
84+ while ((filename = reader .readLine ()) != null ) {
85+ platform .base .handleOpen (filename );
86+ }
87+ } else {
88+ platform .base .handleNew ();
89+ }
90+ } catch (IOException e ) {
91+ e .printStackTrace ();
92+ }
93+ }
94+ });
95+ }
96+ }
97+ } catch (IOException e ) {
98+ e .printStackTrace ();
99+ }
100+ }
101+ }
102+ }).start ();
103+
104+ } catch (IOException e ) {
105+ System .err .println ("Could not create single instance server." );
106+ e .printStackTrace ();
107+ }
108+ }
109+
110+
111+ static boolean sendArguments (String [] args , long timeout ) {
112+ try {
113+ //int port = Integer.parseInt(Preferences.get("server.port"));
114+ //String key = Preferences.get("server.key");
115+ int port = Preferences .getInteger (SERVER_PORT );
116+ String key = Preferences .get (SERVER_KEY );
117+
118+ long endTime = System .currentTimeMillis () + timeout ;
119+
120+ Socket socket = null ;
121+ while (socket == null && System .currentTimeMillis () < endTime ) {
122+ try {
123+ socket = new Socket (InetAddress .getByName (null ), port );
124+ } catch (Exception ioe ) {
125+ try {
126+ Thread .sleep (50 );
127+ } catch (InterruptedException ie ) {
128+ Thread .yield ();
129+ }
130+ }
131+ }
132+
133+ if (socket != null ) {
134+ PrintWriter writer = PApplet .createWriter (socket .getOutputStream ());
135+ // bw.write(key + "\n");
136+ writer .println (key );
137+ for (String arg : args ) {
138+ // if (filename != null) {
139+ //// bw.write(filename + "\n");
140+ // writer.println(filename);
141+ writer .println (arg );
142+ }
143+ // bw.close();
144+ writer .flush ();
145+ writer .close ();
146+ return true ;
147+ }
148+ } catch (IOException e ) {
149+ System .err .println ("Error sending commands to other instance." );
150+ e .printStackTrace ();
151+ }
152+ return false ;
153+ }
154+ }
0 commit comments