KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > core > main > ColumbaServer


1 //The contents of this file are subject to the Mozilla Public License Version 1.1
2
//(the "License"); you may not use this file except in compliance with the
3
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
4
//
5
//Software distributed under the License is distributed on an "AS IS" basis,
6
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
7
//for the specific language governing rights and
8
//limitations under the License.
9
//
10
//The Original Code is "The Columba Project"
11
//
12
//The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
13
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
14
//
15
//All Rights Reserved.
16

17 package org.columba.core.main;
18
19 import java.io.BufferedReader JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.InputStreamReader JavaDoc;
22 import java.io.PrintWriter JavaDoc;
23 import java.net.ServerSocket JavaDoc;
24 import java.net.Socket JavaDoc;
25 import java.net.SocketException JavaDoc;
26 import java.net.SocketTimeoutException JavaDoc;
27 import java.util.LinkedList JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Random JavaDoc;
30 import java.util.StringTokenizer JavaDoc;
31
32 import javax.swing.JOptionPane JavaDoc;
33
34 import org.apache.commons.cli.CommandLine;
35 import org.apache.commons.cli.ParseException;
36 import org.columba.core.component.ComponentManager;
37 import org.columba.core.resourceloader.GlobalResourceLoader;
38 import org.columba.core.shutdown.ShutdownManager;
39
40 /**
41  * Opens a server socket to manage multiple sessions of Columba capable of
42  * passing commands to the main session.
43  * <p>
44  * This class is a singleton because there can only be one server per Columba
45  * session.
46  * <p>
47  * Basic idea taken from www.jext.org (author Roman Guy)
48  *
49  * @author fdietz
50  */

51 public class ColumbaServer {
52     static final String JavaDoc RESOURCE_PATH = "org.columba.core.i18n.dialog";
53
54     /**
55      * The anonymous user for single-user systems without user name.
56      */

57     protected static final String JavaDoc ANONYMOUS_USER = "anonymous";
58
59     /**
60      * The singleton instance of this class.
61      */

62     private static ColumbaServer instance;
63
64     /**
65      * Random number generator for port numbers.
66      */

67     private static Random JavaDoc random = new Random JavaDoc();
68
69     /**
70      * The port range Columba should use is between LOWEST_PORT and 65536.
71      */

72     private static final int LOWEST_PORT = 30000;
73
74     /**
75      * Server runs in its own thread.
76      */

77     protected Thread JavaDoc thread;
78
79     /**
80      * The ServerSocket used by the server.
81      */

82     protected ServerSocket JavaDoc serverSocket;
83
84     /**
85      * Constructor
86      */

87     protected ColumbaServer() {
88         thread = new Thread JavaDoc(new Runnable JavaDoc() {
89             public void run() {
90                 while (!Thread.currentThread().isInterrupted()) {
91                     try {
92                         handleClient(serverSocket.accept());
93                     } catch (SocketTimeoutException JavaDoc ste) {
94                         // do nothing here, just continue
95
} catch (IOException JavaDoc ioe) {
96                         ioe.printStackTrace();
97
98                         // what to do here? we could start a new server...
99
}
100                 }
101
102                 try {
103                     serverSocket.close();
104
105                     // cleanup: remove port number file
106
SessionController.serializePortNumber(-1);
107                 } catch (IOException JavaDoc ioe) {
108                 }
109
110                 serverSocket = null;
111             }
112         }, "ColumbaServer");
113         thread.setDaemon(true);
114
115         // stop server when shutting down
116
ShutdownManager.getInstance().register(new Runnable JavaDoc() {
117             public void run() {
118                 stop();
119             }
120         });
121     }
122
123     /**
124      * Starts the server.
125      *
126      * @throws IOException
127      */

128     public synchronized void start() throws IOException JavaDoc {
129         if (!isRunning()) {
130             int port;
131             int count = 0;
132
133             while (serverSocket == null) {
134                 // create random port number within range
135
port = random.nextInt(65536 - LOWEST_PORT) + LOWEST_PORT;
136
137                 try {
138                     serverSocket = new ServerSocket JavaDoc(port);
139
140                     // store port number in file
141
SessionController.serializePortNumber(port);
142                 } catch (SocketException JavaDoc se) { // port is in use, try next
143
count++;
144
145                     if (count == 10) { // something is very wrong here
146
JOptionPane.showMessageDialog(null,
147                                 GlobalResourceLoader.getString(RESOURCE_PATH,
148                                         "session", "err_10se_msg"),
149                                 GlobalResourceLoader.getString(RESOURCE_PATH,
150                                         "session", "err_10se_title"),
151                                 JOptionPane.ERROR_MESSAGE);
152
153                         // this is save because the only shutdown plugin
154
// to stop this server, the configuration isn't touched
155
System.exit(1);
156                     }
157                 }
158             }
159
160             serverSocket.setSoTimeout(2000);
161             thread.start();
162         }
163     }
164
165     /**
166      * Stops the server.
167      */

168     public synchronized void stop() {
169         thread.interrupt();
170     }
171
172     /**
173      * Check if server is already running
174      *
175      * @return true, if server is running. False, otherwise
176      */

177     public synchronized boolean isRunning() {
178         return thread.isAlive();
179     }
180
181     /**
182      * Handles a client connect and authentication.
183      */

184     protected void handleClient(Socket JavaDoc client) {
185         try {
186             // only accept client from local machine
187
String JavaDoc host = client.getLocalAddress().getHostAddress();
188             if (!(host.equals("127.0.0.1"))) {
189                 // client isn't from local machine
190
return;
191             }
192
193             BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(
194                     client.getInputStream()));
195             String JavaDoc line = reader.readLine();
196             if (!line.startsWith("Columba ")) {
197                 return;
198             }
199
200             line = reader.readLine();
201             if (!line.startsWith("User ")) {
202                 return;
203             }
204
205             PrintWriter JavaDoc writer = new PrintWriter JavaDoc(client.getOutputStream());
206             if (!line.substring(5).equals(
207                     System.getProperty("user.name", ANONYMOUS_USER))) {
208                 writer.write("WRONG USER\r\n");
209                 writer.close();
210                 return;
211             }
212             writer.write("\r\n");
213             writer.flush();
214
215             line = reader.readLine();
216             // do something with the arguments..
217
List JavaDoc<String JavaDoc> list = new LinkedList JavaDoc<String JavaDoc>();
218             StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(line, "%");
219             while (st.hasMoreTokens()) {
220                 String JavaDoc tok = (String JavaDoc) st.nextToken();
221                 list.add(tok);
222             }
223
224             try {
225                 CommandLine commandLine = ColumbaCmdLineParser.getInstance()
226                         .parse((String JavaDoc[]) list.toArray(new String JavaDoc[0]));
227
228                 ComponentManager.getInstance().handleCommandLineParameters(
229                         commandLine);
230
231             } catch (ParseException e) {
232                 e.printStackTrace();
233             }
234         } catch (IOException JavaDoc ioe) {
235             ioe.printStackTrace();
236         } finally {
237             try {
238                 client.close();
239             } catch (IOException JavaDoc ioe) {
240             }
241         }
242     }
243
244     /**
245      * Returns the singleton instance of this class.
246      *
247      * @return instance
248      */

249     public static synchronized ColumbaServer getColumbaServer() {
250         if (instance == null) {
251             instance = new ColumbaServer();
252         }
253         return instance;
254     }
255 }
256
Popular Tags