KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > lucane > server > Server


1 /*
2  * Lucane - a collaborative platform
3  * Copyright (C) 2002 Gautier Ringeisen <gautier_ringeisen@hotmail.com>
4  * Copyright (C) 2004 Vincent Fiack <vfiack@mail15.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */

20 package org.lucane.server;
21
22 import org.lucane.common.concepts.*;
23 import org.lucane.common.crypto.KeyTool;
24 import org.lucane.server.acl.AccessController;
25 import org.lucane.server.auth.Authenticator;
26 import org.lucane.server.database.*;
27 import org.lucane.server.store.*;
28 import org.lucane.common.*;
29 import org.lucane.common.net.ClientSocketFactory;
30 import org.lucane.common.net.ObjectConnection;
31 import org.lucane.common.net.ServerSocketFactory;
32
33 import java.io.*;
34 import java.net.*;
35 import java.util.*;
36
37 /**
38  * The server's class
39  */

40 public class Server
41 {
42     
43     private String JavaDoc workingDirectory;
44     
45     private static final String JavaDoc CONFIG_FILE = "etc/server-config.xml";
46     private static final String JavaDoc LOG_FILE = "logs/lucane.log";
47     public static final String JavaDoc APPLICATIONS_DIRECTORY = "applications/";
48     public static final String JavaDoc VERSION = "0.7.5";
49     
50     //-- instance management
51
private static Server instance = null;
52     public static Server getInstance()
53     {
54         return instance;
55     }
56     
57     //-- attributes
58
private ServerConfig config;
59     
60     private ServerSocket plainSocket;
61     private ServerSocket sslSocket;
62     private Store store;
63     private Authenticator authenticator;
64     private AccessController accessController;
65     private DatabaseAbstractionLayer dbLayer;
66     private String JavaDoc privateKey;
67     
68     /**
69      * Creates a new Server object.
70      */

71     private Server(ServerConfig config, String JavaDoc workingDirectory)
72     {
73         Server.instance = this;
74         this.config = config;
75         this.workingDirectory = workingDirectory;
76         this.dbLayer = null;
77         this.privateKey = "nokey";
78         
79         try {
80             dbLayer = DatabaseAbstractionLayer.createLayer(config);
81             Logging.getLogger().finer("dbLayer : " + dbLayer);
82             
83             this.store = new Store(config);
84         } catch (Exception JavaDoc ex) {
85             Logging.getLogger().severe(
86                     "#Err > Unable to connect to the database : "
87                     + ex.getMessage());
88             ex.printStackTrace();
89             System.exit(1);
90         }
91
92         try {
93             this.authenticator = Authenticator.newInstance(config);
94         } catch (Exception JavaDoc e) {
95             Logging.getLogger().severe("Unable to get Authenticator instance.");
96             e.printStackTrace();
97             System.exit(1);
98         }
99         
100         try {
101             this.accessController = AccessController.newInstance(config);
102         } catch (Exception JavaDoc e) {
103             Logging.getLogger().severe("Unable to get AccessController instance.");
104             e.printStackTrace();
105             System.exit(1);
106         }
107     }
108     
109     /**
110      * Create server's ConnectInfo
111      */

112     private void initConnectInfo()
113     {
114         int port = config.getPort();
115         String JavaDoc publicKey = "nokey";
116         
117         if(config.isSslEnabled())
118         {
119             port = config.getSslPort();
120             
121             try {
122                 this.privateKey = KeyTool.createPrivateStore("server", config.getSslPassword());
123                 publicKey = KeyTool.createPublicStore(privateKey, "server");
124             } catch(Exception JavaDoc e) {
125                 Logging.getLogger().severe("Unable to generate keypair : " + e);
126                 System.exit(1);
127             }
128         }
129         
130         ConnectInfo myConnectInfo = new ConnectInfo("server",
131                 "not-used",
132                 port, publicKey, "Server");
133         ConnectInfoManager.getInstance().setServerInfo(myConnectInfo);
134         ConnectInfoManager.getInstance().addConnectInfo(myConnectInfo);
135     }
136     
137     /**
138      * Accepts connections
139      */

140     public void acceptConnections()
141     {
142         if(config.isSslEnabled())
143             this.acceptSslConnections();
144
145         this.acceptPlainConnections();
146     }
147
148     private void acceptPlainConnections()
149     {
150         try {
151             this.plainSocket = ServerSocketFactory.getServerSocket(config.getPort());
152         } catch (Exception JavaDoc e) {
153             Logging.getLogger().severe("#Err > Unable to listen on the port " + config.getPort() + ".");
154             e.printStackTrace();
155             System.exit(1);
156         }
157         
158         Runnable JavaDoc plain = new Runnable JavaDoc() {
159             public void run() {
160                 while(!plainSocket.isClosed())
161                 {
162                     try {
163                         MessageHandler handler = new MessageHandler(plainSocket.accept());
164                         handler.start();
165                     } catch (IOException ex) {
166                         if(!plainSocket.isClosed())
167                             Logging.getLogger().warning("#Err > Unable to accept connections.");
168                     }
169                 }
170             }
171         };
172         
173         new Thread JavaDoc(plain).start();
174         Logging.getLogger().info("Accepting plain connections on port " + config.getPort());
175     }
176     
177     private void acceptSslConnections()
178     {
179         try {
180             this.sslSocket = ServerSocketFactory.getServerSocket(config.getSslPort(),
181                     this.privateKey, "server", config.getSslPassword());
182         } catch (Exception JavaDoc e) {
183             Logging.getLogger().severe("#Err > Unable to listen on the port " + config.getSslPort() + ".");
184             e.printStackTrace();
185             System.exit(1);
186         }
187
188         Runnable JavaDoc ssl = new Runnable JavaDoc() {
189             public void run() {
190                 while(!sslSocket.isClosed())
191                 {
192                     try {
193                         MessageHandler handler = new MessageHandler(sslSocket.accept());
194                         handler.start();
195                     } catch (IOException ex) {
196                         if(!sslSocket.isClosed())
197                             Logging.getLogger().warning("#Err > Unable to accept connections.");
198                     }
199                 }
200             }
201         };
202         
203         new Thread JavaDoc(ssl).start();
204         Logging.getLogger().info("Accepting SSL connections on port " + config.getSslPort());
205     }
206     
207     /**
208      * Stop the server
209      */

210     public void shutdown()
211     {
212         this.authenticator.disableLogin();
213         ConnectInfoManager.getInstance().kickAllUsers();
214         Logging.getLogger().info("Users disconnected.");
215         ServiceManager.getInstance().shutdownAllServices();
216         Logging.getLogger().info("Services shutdowned.");
217         
218         try {
219             this.plainSocket.close();
220             if(config.isSslEnabled())
221                 this.sslSocket.close();
222
223             Logging.getLogger().info("Socket closed.");
224         } catch (IOException e) {
225             Logging.getLogger().warning("Unable to close socket : " + e);
226         }
227         
228         System.exit(0);
229     }
230     
231     /**
232      * Send the ConnectInfo associated with this name
233      *
234      * @param name the user wanted
235      */

236     public void sendConnectInfo(String JavaDoc name, ObjectConnection oc)
237     {
238         ConnectInfo ci = ConnectInfoManager.getInstance().getConnectInfo(name);
239         if(ci != null)
240         {
241             try {
242                 oc.write(ci);
243             } catch (Exception JavaDoc e) {}
244         }
245         else
246         {
247             try {
248                 oc.write("unknown");
249             } catch (Exception JavaDoc e) {}
250         }
251     }
252     
253     /**
254      * Send the connected users list
255      */

256     public void sendUserList(ObjectConnection oc)
257     {
258         //get into vector
259
Vector v = new Vector();
260         Iterator i = ConnectInfoManager.getInstance().getClientConnectInfos();
261         while(i.hasNext())
262             v.addElement(i.next());
263         
264         //send
265
try {
266             oc.write(v);
267         } catch (Exception JavaDoc e) {}
268     }
269     
270     public void sendServerConnectInfo(ObjectConnection oc)
271     {
272         try {
273             oc.write(ConnectInfoManager.getInstance().getServerInfo());
274         } catch(Exception JavaDoc e) {
275             e.printStackTrace();
276         }
277     }
278     
279     /**
280      * Send the plugin list to a client.
281      * The list depends of the client's groups
282      *
283      * @param source the user that asked this command
284      */

285     public void sendPluginList(ObjectConnection oc, String JavaDoc source)
286     {
287         Vector plist = new Vector();
288         Iterator plugins;
289         String JavaDoc line = "";
290         
291         try
292         {
293             UserConcept user = store.getUserStore().getUser(source);
294             plugins = store.getPluginStore().getAuthorizedPlugins(user);
295             
296             while(plugins.hasNext())
297             {
298                 PluginConcept plugin = (PluginConcept)plugins.next();
299                 line = plugin.getName();
300                 line += " " + plugin.getVersion();
301                 plist.add(line);
302             }
303             oc.write(plist);
304         }
305         catch (Exception JavaDoc e)
306         {
307             Logging.getLogger().warning("Unable to send the plugin list.");
308             e.printStackTrace();
309         }
310     }
311     
312     /**
313      * Send a plugin JAR file to the client
314      *
315      * @param data the plugin name
316      */

317     public void sendPluginFile(ObjectConnection oc, String JavaDoc data)
318     {
319         DataInputStream dis = null;
320         try
321         {
322             dis = new DataInputStream(new FileInputStream(getWorkingDirectory()+APPLICATIONS_DIRECTORY + data + ".jar"));
323             byte[] buf = new byte[dis.available()];
324             dis.readFully(buf);
325             oc.write(buf);
326         }
327         catch (Exception JavaDoc e)
328         {
329             Logging.getLogger().warning("Unable to send the file: " + data + ".jar");
330         }
331         finally {
332             if(dis != null)
333             {
334                 try {
335                     dis.close();
336                 } catch(IOException ioe) {}
337             }
338             
339         }
340     }
341     
342     /**
343      * Send the user's startup plugin
344      *
345      * @param source the user
346      */

347     public void sendStartupPlugin(ObjectConnection oc, String JavaDoc source)
348     {
349         try
350         {
351             UserConcept user = store.getUserStore().getUser(source);
352             oc.write(user.getStartupPlugin());
353         }
354         catch (Exception JavaDoc e)
355         {
356         }
357     }
358     
359     /**
360      * Send the user list to all users
361      */

362     public void sendUserListToEveryone()
363     {
364         ArrayList userList = new ArrayList();
365         Iterator users = ConnectInfoManager.getInstance().getClientConnectInfos();
366         while(users.hasNext())
367         {
368             ConnectInfo user = (ConnectInfo)users.next();
369             userList.add(user.getName());
370         }
371
372         Map action = new HashMap();
373         action.put("command", "USER_LIST");
374         action.put("users", userList);
375
376         // send to everyone
377
Iterator clients = ConnectInfoManager.getInstance().getClientConnectInfos();
378         while(clients.hasNext())
379         {
380             ConnectInfo client = (ConnectInfo)clients.next();
381             try {
382                 ObjectConnection oc = sendMessageTo(client, "Client", action);
383                 oc.close();
384             } catch (Exception JavaDoc e) {
385                 Logging.getLogger().warning("unable to send user list to " + client);
386                 
387                 //if we can't send to the client, he's probably disconnected
388
//removeConnectInfo will call me again, that's why I break here
389
ConnectInfoManager.getInstance().removeConnectInfo(client);
390                 break;
391             }
392         }
393     }
394     
395     
396     /**
397      * Send a message through the network
398      *
399      * @param dest the receiver
400      * @param app the application that need to process this message
401      * @param data the data to send
402      */

403     public ObjectConnection sendMessageTo(ConnectInfo dest, String JavaDoc app, Object JavaDoc data)
404     throws Exception JavaDoc
405     {
406         Socket sock = ClientSocketFactory.getSocket(dest);
407         ObjectConnection oc = new ObjectConnection(sock);
408         
409         Message msg = new Message(ConnectInfoManager.getInstance().getServerInfo(), dest, app, data);
410         oc.write(msg);
411         
412         return oc;
413     }
414     
415     /**
416      * Get the database layer
417      *
418      * @return the Layer instance
419      */

420     public DatabaseAbstractionLayer getDBLayer()
421     {
422         return this.dbLayer;
423     }
424     
425     /**
426      * Get the store factory
427      *
428      * @return the store factory instance
429      */

430     public Store getStore()
431     {
432         return store;
433     }
434     
435     /**
436      * Get the authenticator
437      *
438      * @return the authenticator instance
439      */

440     public Authenticator getAuthenticator()
441     {
442         return this.authenticator;
443     }
444     
445     /**
446      * Get the access controller
447      *
448      * @return the access controller instance
449      */

450     public AccessController getAccessController()
451     {
452         return this.accessController;
453     }
454     
455     /**
456      * Get the working directory
457      *
458      * @return the working directory
459      */

460     public String JavaDoc getWorkingDirectory()
461     {
462         return workingDirectory;
463     }
464     
465     
466     //-- static methods
467

468     /**
469      * Used to shutdown the server for the NT service
470      */

471     public static void shutdownServer(String JavaDoc[] args)
472     {
473         Server.getInstance().shutdown();
474     }
475     
476     /**
477      * Main Method
478      *
479      * @param args command line arguments
480      */

481     public static void main(String JavaDoc[] args)
482     {
483         if (args.length > 1) {
484             System.err.println("USAGE :\nserver.(bat|sh) [server path]");
485             System.exit(1);
486         }
487         
488         // get the workingDirectory
489
String JavaDoc workingDirectory;
490         if (args.length==1) {
491             workingDirectory=args[0];
492         } else {
493             workingDirectory=System.getProperty("user.dir");
494         }
495         workingDirectory=workingDirectory.replace('\\','/');
496         if (workingDirectory.startsWith("\""))
497             workingDirectory=workingDirectory.substring(1, workingDirectory.length()-2);
498         if (!workingDirectory.endsWith("/"))
499             workingDirectory+="/";
500         
501         //init logging
502
try {
503             new File(workingDirectory + "/logs").mkdirs();
504             Logging.init(workingDirectory+LOG_FILE, "ALL");
505         } catch(IOException ioe) {
506             System.err.println("Unable to init logging, exiting.");
507             System.exit(1);
508         }
509         
510         ServerConfig config = null;
511         
512         try {
513             config = new ServerConfig(workingDirectory+CONFIG_FILE);
514         } catch (Exception JavaDoc e) {
515             Logging.getLogger().severe("Unable to read or parse the config file.");
516             e.printStackTrace();
517             System.exit(1);
518         }
519         
520         // Server creation
521
Server server = new Server(config, workingDirectory);
522         server.initConnectInfo();
523         ServiceManager.getInstance().loadAllServices();
524         ServiceManager.getInstance().startAllServices();
525         server.acceptConnections();
526         Logging.getLogger().info("Server is ready.");
527     }
528 }
529
Popular Tags