KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > snipsnap > server > AppServer


1 /*
2  * This file is part of "SnipSnap Wiki/Weblog".
3  *
4  * Copyright (c) 2002 Stephan J. Schmidt, Matthias L. Jugel
5  * All Rights Reserved.
6  *
7  * Please visit http://snipsnap.org/ for updates and contact.
8  *
9  * --LICENSE NOTICE--
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  * --LICENSE NOTICE--
24  */

25 package org.snipsnap.server;
26
27 import org.apache.xmlrpc.WebServer;
28 import org.jdesktop.jdic.desktop.Desktop;
29 import org.mortbay.http.HttpListener;
30 import org.mortbay.jetty.Server;
31 import org.mortbay.util.InetAddrPort;
32 import org.mortbay.util.MultiException;
33 import org.snipsnap.config.ServerConfiguration;
34 import org.snipsnap.user.Digest;
35
36 import java.io.BufferedOutputStream JavaDoc;
37 import java.io.BufferedReader JavaDoc;
38 import java.io.File JavaDoc;
39 import java.io.FileInputStream JavaDoc;
40 import java.io.FileOutputStream JavaDoc;
41 import java.io.IOException JavaDoc;
42 import java.io.InputStreamReader JavaDoc;
43 import java.io.OutputStream JavaDoc;
44 import java.net.InetAddress JavaDoc;
45 import java.net.MalformedURLException JavaDoc;
46 import java.net.URL JavaDoc;
47 import java.net.UnknownHostException JavaDoc;
48 import java.util.Date JavaDoc;
49 import java.util.Iterator JavaDoc;
50 import java.util.Properties JavaDoc;
51 import java.util.prefs.BackingStoreException JavaDoc;
52 import java.util.prefs.Preferences JavaDoc;
53
54 /**
55  * Application Server
56  *
57  * @author Matthias L. Jugel
58  * @version $Id: AppServer.java 1729 2004-08-16 11:22:24Z leo $
59  */

60 public class AppServer {
61   protected static Properties JavaDoc serverPrefsDefaults;
62   protected static Preferences JavaDoc serverPrefs;
63
64   protected static Server jettyServer;
65
66   /**
67    * Start application server.
68    */

69   public static void main(String JavaDoc args[]) {
70     // load server preferences (and possible convert old configs)
71
serverPrefs = getServerPrefs();
72     System.setProperty(ServerConfiguration.VERSION, serverPrefs.get(ServerConfiguration.VERSION, "<unknown version>"));
73
74     printCopyright();
75     parseArguments(args);
76
77     // make sure we shutdown the server nicely when the JVM is stopped
78
Runtime.getRuntime().addShutdownHook(new Thread JavaDoc() {
79       public void run() {
80         Shutdown.shutdown();
81       }
82     });
83
84     // set encoding of the JVM and make sure Jetty decodes URIs correctly
85
String JavaDoc enc = serverPrefs.get(ServerConfiguration.ENCODING, "UTF-8");
86     System.setProperty("file.encoding", enc);
87     System.setProperty("org.mortbay.util.URI.charset", enc);
88
89     // start jetty server and install web application
90
try {
91       jettyServer = new Server(getResource("/conf/jetty.conf", "./conf/jetty.conf"));
92       jettyServer.addWebApplication("/install", AppServer.class.getResource("/snipsnap-installer.war").toString());
93       jettyServer.start();
94     } catch (IOException JavaDoc e) {
95       System.err.println("AppServer: warning: admin server configuration not found: " + e);
96     } catch (MultiException e) {
97       Iterator JavaDoc exceptions = e.getExceptions().iterator();
98       while (exceptions.hasNext()) {
99         Exception JavaDoc ex = (Exception JavaDoc) exceptions.next();
100         ex.printStackTrace();
101         System.out.println("ERROR: can't start server: " + ex.getMessage());
102       }
103       System.exit(-1);
104     }
105
106     try {
107       URL JavaDoc xmlRpcServerUrl = new URL JavaDoc(serverPrefs.get(ServerConfiguration.ADMIN_URL,
108                                                     serverPrefsDefaults.getProperty(ServerConfiguration.ADMIN_URL)));
109       WebServer xmlRpcServer = new WebServer(xmlRpcServerUrl.getPort());
110       // xmlRpcServer.setParanoid(true);
111
xmlRpcServer.addHandler("$default", new AdminXmlRpcHandler());
112       xmlRpcServer.start();
113     } catch (Exception JavaDoc e) {
114       System.out.println("ERROR: can't start administrative server interface (XML-RPC): " + e.getMessage());
115       e.printStackTrace();
116     }
117
118     String JavaDoc webAppRoot = serverPrefs.get(ServerConfiguration.WEBAPP_ROOT,
119                                         serverPrefsDefaults.getProperty((ServerConfiguration.WEBAPP_ROOT)));
120     System.out.println(">> Applications: " + new File JavaDoc(webAppRoot).getAbsolutePath());
121     // now, after loading all possible services we will look for applications and start them
122
int errors = ApplicationLoader.loadApplications(serverPrefs.get(ServerConfiguration.WEBAPP_ROOT,
123                                                                     serverPrefsDefaults.getProperty((ServerConfiguration.WEBAPP_ROOT))));
124     if (errors == 0 && ApplicationLoader.getApplicationCount() == 0) {
125       System.out.println("ATTENTION: Server is still unconfigured!");
126       System.out.println("ATTENTION: Point your browser to the following address:");
127       HttpListener listener = jettyServer.getListeners()[0];
128       String JavaDoc host = listener.getHost();
129       if (InetAddrPort.__0_0_0_0.equals(host)) {
130         try {
131           host = InetAddress.getLocalHost().getCanonicalHostName();
132         } catch (UnknownHostException JavaDoc e) {
133           host = System.getProperty("host", "localhost");
134         }
135       }
136       String JavaDoc url = "http://" + host + ":" + listener.getPort() + "/install/" + serverPrefs.get(ServerConfiguration.ADMIN_PASS, "");
137       System.out.println("ATTENTION: " + url);
138       System.out.println("ATTENTION: To force setup of a specific host and port add '?expert=true'");
139       System.out.println("ATTENTION: to the above URL.");
140
141       // on an OS X System run the web browser to start configuration
142
String JavaDoc system = System.getProperty("os.name");
143       if (system.startsWith("Mac OS X")) {
144         try {
145           Runtime.getRuntime().exec("/usr/bin/open " + url);
146         } catch (IOException JavaDoc e) {
147           System.err.println("AppServer: unable to execute open web browser on MacOS X");
148         }
149       } else {
150         try {
151           Desktop.browse(new URL JavaDoc(url));
152         } catch (Exception JavaDoc e) {
153           System.err.println("AppServer: unable to open web browser on " + system);
154         } catch (Error JavaDoc err) {
155           System.err.println("AppServer: unable to open web browser on " + system);
156         }
157       }
158     } else {
159       System.out.println(ApplicationLoader.getApplicationCount() + " applications loaded and running (" + errors + " errors).");
160     }
161   }
162
163   /**
164    * Load server configuration from the preferences API. This method converts
165    * old config files into the preferences as well.
166    *
167    * @return the preferences object
168    */

169   private static Preferences JavaDoc getServerPrefs() {
170     serverPrefs = Preferences.userNodeForPackage(ServerConfiguration.class);
171     int keyCount = 0;
172     try {
173       keyCount = serverPrefs.keys().length;
174     } catch (BackingStoreException JavaDoc e) {
175       System.err.println("AppServer: WARNING: no preferences backing store available! Using defaults.");
176     }
177
178     serverPrefsDefaults = new Properties JavaDoc();
179     // load defaults
180
try {
181       serverPrefsDefaults.load(AppServer.class.getResourceAsStream("/conf/snipsnap.conf"));
182     } catch (IOException JavaDoc e) {
183       System.err.println("AppServer: Unable to read server defaults: " + e.getMessage());
184       e.printStackTrace();
185     }
186
187     // check whether the node has any keys, empty means it is not yet initialized
188
if (keyCount == 0) {
189       System.err.println("AppServer: unconfigured server, loading preferences");
190
191       // set application key pass (may be overidden by old config, see below)
192
serverPrefs.put(ServerConfiguration.ADMIN_PASS,
193                       Digest.getDigest("" + new Date JavaDoc()).substring(0, 5).toLowerCase());
194
195       // put defaults into the properties
196
Properties JavaDoc serverInfoProperties = new Properties JavaDoc();
197       Iterator JavaDoc defaultsIt = serverPrefsDefaults.keySet().iterator();
198       while (defaultsIt.hasNext()) {
199         String JavaDoc key = (String JavaDoc) defaultsIt.next();
200         System.err.println("AppServer: default preference: " + key + "=" + serverPrefsDefaults.get(key));
201         serverInfoProperties.put(key, serverPrefsDefaults.get(key));
202       }
203
204       // load defaults
205
try {
206         serverInfoProperties.load(AppServer.class.getResourceAsStream("/conf/snipsnap.conf"));
207       } catch (IOException JavaDoc e) {
208         System.err.println("AppServer: Unable to read server defaults: " + e.getMessage());
209         e.printStackTrace();
210       }
211
212       // now convert old config settings if necessary
213
try {
214         File JavaDoc propFile = new File JavaDoc("conf/server.conf");
215         serverInfoProperties.load(new FileInputStream JavaDoc(propFile));
216         System.err.println("AppServer: converted old server configuration, please remove '" + propFile + "'");
217       } catch (IOException JavaDoc e) {
218         // safely ignore file not found ...
219
}
220
221       // transfer defaults or existing old values into the preferences
222
Iterator JavaDoc oldConfigIt = serverInfoProperties.keySet().iterator();
223       while (oldConfigIt.hasNext()) {
224         String JavaDoc key = (String JavaDoc) oldConfigIt.next();
225         System.err.println("AppServer: converted old preference: " + key + "=" + serverInfoProperties.get(key));
226         serverPrefs.put(key, (String JavaDoc) serverInfoProperties.get(key));
227       }
228
229       File JavaDoc webappRoot = new File JavaDoc(serverInfoProperties.getProperty(ServerConfiguration.WEBAPP_ROOT));
230       System.err.println("webappRoot=" + webappRoot.getAbsolutePath());
231       if (!webappRoot.exists() || !webappRoot.canWrite()) {
232         webappRoot = new File JavaDoc(System.getProperty("user.home"), "applications");
233       }
234       serverPrefs.put(ServerConfiguration.WEBAPP_ROOT, webappRoot.getAbsolutePath());
235
236       try {
237         serverPrefs.flush();
238       } catch (BackingStoreException JavaDoc e) {
239         System.err.println("AppServer: unable to store server configuration: " + e.getMessage());
240         e.printStackTrace();
241       }
242
243       File JavaDoc confDir = new File JavaDoc("conf");
244       if (!confDir.exists() && !confDir.canWrite()) {
245         confDir = webappRoot;
246       }
247       try {
248         OutputStream JavaDoc configSave = new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(new File JavaDoc(confDir, "snipsnap.xml")));
249         serverPrefs.exportSubtree(configSave);
250       } catch (Exception JavaDoc e) {
251         System.err.println("AppServer: unable to store server configuation backup: " + e.getMessage());
252         e.printStackTrace();
253       }
254     }
255
256     String JavaDoc jarVersion = serverPrefsDefaults.getProperty(ServerConfiguration.VERSION);
257     String JavaDoc version = serverPrefs.get(ServerConfiguration.VERSION, null);
258     if (null == version || !(jarVersion != null && jarVersion.equals(version))) {
259       serverPrefs.put(ServerConfiguration.VERSION, jarVersion);
260       try {
261         serverPrefs.flush();
262       } catch (BackingStoreException JavaDoc e) {
263         System.err.println("AppServer: unable to store server configuration " + e.getMessage());
264         e.printStackTrace();
265       }
266     }
267
268     return serverPrefs;
269   }
270
271   private static void printCopyright() {
272     System.out.println("SnipSnap " + System.getProperty(ServerConfiguration.VERSION));
273
274     // output version and copyright information
275
try {
276       BufferedReader JavaDoc copyrightReader = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(AppServer.class.getResourceAsStream("/conf/copyright.txt")));
277       String JavaDoc line = null;
278       while ((line = copyrightReader.readLine()) != null) {
279         System.out.println(line);
280       }
281     } catch (IOException JavaDoc e) {
282       // ignore io exception here ...
283
}
284   }
285
286   /**
287    * Parse argument from command line and exit in case of erroneous options.
288    * The server will immedialy exit if there is a problem and display a usage message
289    *
290    * @param args the command line arguments
291    * @return the possibly changed configuration properties
292    */

293   private static Preferences JavaDoc parseArguments(String JavaDoc args[]) {
294     for (int i = 0; i < args.length; i++) {
295       if ("-help".equals(args[i])) {
296         usage("");
297         System.exit(0);
298       }
299
300       // the applications root directory
301
if ("-root".equals(args[i])) {
302         if (args.length >= i + 1 && !args[i + 1].startsWith("-")) {
303           serverPrefs.put(ServerConfiguration.WEBAPP_ROOT, args[++i]);
304         } else {
305           usage("an argument is required for -root");
306         }
307       } else if ("-url".equals(args[i])) {
308         if (args.length >= i + 1 && !args[i + 1].startsWith("-")) {
309           serverPrefs.put(ServerConfiguration.ADMIN_URL, args[++i]);
310         } else {
311           usage("an argument is required for -url");
312         }
313       } else if ("-killconfig".equals(args[i])) {
314         try {
315           serverPrefs.removeNode();
316           serverPrefs.flush();
317         } catch (BackingStoreException JavaDoc e) {
318           System.out.println("Error: cannot remove configuration ...");
319           e.printStackTrace();
320         }
321         System.exit(0);
322       } else if ("-showconfig".equals(args[i])) {
323         try {
324           serverPrefs.sync();
325           serverPrefs.exportSubtree(System.out);
326         } catch (Exception JavaDoc e) {
327           System.out.println("Error: cannot display configuration ...");
328           e.printStackTrace();
329         }
330         System.exit(0);
331       }
332     }
333     return serverPrefs;
334   }
335
336   /**
337    * Get a resource from file if the file exists, else just return the jar resource.
338    *
339    * @param jarResource the jar file resource (fallback)
340    * @param fileResource the file resource
341    */

342   private static URL JavaDoc getResource(String JavaDoc jarResource, String JavaDoc fileResource) {
343     File JavaDoc file = new File JavaDoc(fileResource);
344     URL JavaDoc url = null;
345     if (file.exists()) {
346       try {
347         url = file.toURL();
348       } catch (MalformedURLException JavaDoc e) {
349         System.err.println("Warning: unable to load '" + file + "': " + e.getMessage());
350       }
351     }
352
353     if (null == url) {
354       url = AppServer.class.getResource(jarResource);
355     }
356
357     return url;
358   }
359
360   /**
361    * Display a a message in addition to a usage message.
362    *
363    * @param message an additional informational text
364    */

365   private static void usage(String JavaDoc message) {
366     System.out.println(message);
367     System.out.println("usage: " + AppServer.class.getName() + " [-root <dir>] [-url <url>]");
368     System.out.println(" -root directory, where to find the applications for this server");
369     System.out.println(" -url URL, admin server URL (http://host:port/)");
370     System.out.println(" -killconfig remove server configuration from system");
371     System.out.println(" -showconfig show server configuration, dump it");
372     System.out.println(" -help this help text");
373     System.exit(0);
374   }
375 }
376
Popular Tags