source: main/trunk/greenstone3/src/java/org/greenstone/server/Server2.java@ 22085

Last change on this file since 22085 was 22085, checked in by sjm84, 14 years ago

Created a util package from classes that could be useful outside of their original packages

File size: 14.0 KB
Line 
1
2package org.greenstone.server;
3
4import java.io.BufferedReader;
5import java.io.File;
6import java.io.FileInputStream;
7import java.io.FileOutputStream;
8import java.io.InputStreamReader;
9import java.io.IOException;
10import java.net.InetAddress;
11import java.net.ServerSocket;
12import java.net.Socket;
13import java.net.UnknownHostException;
14import java.net.URL;
15//import java.net.URLConnection;
16import java.util.Properties;
17import java.util.ArrayList;
18
19import org.apache.log4j.*;
20
21import org.greenstone.util.PortFinder;
22import org.greenstone.util.ScriptReadWrite;
23import org.greenstone.util.RunMake;
24import org.greenstone.util.RunAnt;
25
26import org.greenstone.server.BaseServer;
27import org.greenstone.server.BaseProperty;
28
29public class Server2 extends BaseServer
30{
31 private static final int WAITING_TIME = 10; // time to wait and check for whether the server is running
32 private static final String URL_PENDING="URL_pending";
33
34 protected String libraryURL;
35
36 private class QuitListener extends Thread
37 {
38 int quitPort = -1;
39 ServerSocket serverSocket = null;
40
41 public QuitListener(int quitport) throws Exception {
42 ///Server2.this.recordSuccess("In QuitListener constructor");
43 this.quitPort = quitport;
44 serverSocket = new ServerSocket(quitPort);
45 }
46
47 public void run() {
48 Socket connection = null;
49
50 try {
51 // wait for a connection
52 connection = serverSocket.accept();
53
54 // read input
55 try {
56 BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
57 String line = null;
58 if((line = reader.readLine()) != null) {
59 if(line.equals("QUIT")) {
60 // Server2.this.recordSuccess("In QuitListener - line is QUIT");
61 reader.close();
62 reader = null;
63 serverSocket.close();
64 serverSocket = null;
65 }
66 }
67 } catch(Exception e) {
68 Server2.this.recordError("Exception in QuitListener thread.");
69 } finally {
70 Server2.this.stop();
71 System.exit(0);
72 }
73 } catch(IOException ioe) {
74 Server2.this.recordError("Server2.QuitListener: Unable to make the connection with the client socket." + ioe);
75 }
76 }
77 }
78
79
80 public Server2(String gsdl2_home, String lang, String configfile, int quitPort)
81 {
82 super(gsdl2_home, lang, configfile, "etc"+File.separator+"logs-gsi");
83 // configfile can be either glisite.cfg or llssite.cfg
84
85 Property = new Server2Property();
86
87 String frame_title = dictionary.get("ServerControl.Frame_Title");
88 server_control_ = new Server2Control(this,frame_title);
89
90 /* Make command targets for managing Web server */
91 START_CMD = "web-start";
92 RESTART_CMD = "web-restart";
93 CONFIGURE_CMD = "configure-web \"" + configfile + "\"";
94 STOP_CMD = "web-stop";
95
96 // now we can monitor for the quit command if applicable
97 if(quitPort != -1) {
98 // First check if given port is within the range of allowed ports
99 if(PortFinder.isAssignablePortNumber(quitPort)) {
100 try {
101 new QuitListener(quitPort).start();
102 } catch(Exception e) {
103 Server2.this.recordError("Exception constructing the QuitListener thread.");
104 }
105 }
106 else {
107 recordError("QuitPort provided is not within acceptable range: ("
108 + PortFinder.PORTS_RESERVED + " - " + PortFinder.MAX_PORT + "]" );
109 quitPort = -1;
110 }
111 }
112
113 // If the GSI is set to NOT autoenter/autostart the server, then write url=URL_PENDING out to the file.
114 // When the user finally presses the Enter Library button and so has started up the server, the correct
115 // url will be written out to the configfile.
116 if(config_properties.getProperty(BaseServer.Property.AUTOSTART, "").equals("0")) {//if(configfile.endsWith("llssite.cfg")) {
117 if(config_properties.getProperty("url") == null) {
118 config_properties.setProperty("url", URL_PENDING);
119 ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
120 ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
121 scriptReadWrite.replaceOrAddLine(fileLines, "url", URL_PENDING, true);
122 scriptReadWrite.writeOutFile(config_properties_file, fileLines);
123 }
124 }
125
126 autoStart();
127 }
128
129 // Prepare the log4j.properties for GS2
130 protected void initLogger() {
131
132 String libjavaFolder = gsdl_home+File.separator+"lib"+File.separator+"java"+File.separator;
133 File propsFile = new File(libjavaFolder+"log4j.properties");
134
135 // create it from the template file log4j.properties.in
136 if(!propsFile.exists()) {
137 try {
138 // need to set gsdl2.home property's value to be gsdl_home,
139 // so that the location of the log files gets resolved correctly
140
141 // load the template log4j.properties.in file into logProps
142 FileInputStream infile = new FileInputStream(new File(libjavaFolder+"log4j.properties.in"));
143 if(infile != null) {
144 Properties logProps = new Properties();
145 logProps.load(infile);
146 infile.close();
147
148 // set gsdl3.home to gsdl_home
149 logProps.setProperty("gsdl2.home", gsdl_home);
150
151 // write the customised properties out to a custom log4j.properties file
152 FileOutputStream outfile = new FileOutputStream(propsFile);
153 if(outfile != null) {
154 logProps.store(outfile, "Customised log4j.properties file");
155 outfile.close();
156 } else {
157 System.err.println("Could not store properties file " + propsFile + " for Server2.");
158 }
159 }
160 } catch(Exception e) {
161 System.err.println("Exception occurred when custom-configuring the logger for Server2.\n" + e);
162 }
163 }
164
165 // now configure the logger with the custom log4j.properties file
166 if(propsFile.exists()) {
167 PropertyConfigurator.configure(propsFile.getAbsolutePath());
168 } else {
169 System.err.println("Could not create properties file " + propsFile + " for Server2.");
170 }
171 }
172
173
174 protected int runTarget(String cmd)
175 {
176 RunMake runMake = new RunMake();
177 runMake.setTargetCmd(cmd);
178 runMake.run();
179 return runMake.getTargetState();
180 }
181
182 public String getBrowserURL() {
183 return libraryURL;
184 }
185
186 // works out the library URL again
187 public void reload() {
188 // default values, to be replaced with what's in gsdlsite.cfg
189 String host = "localhost";
190 String port = "80";
191 String gwcgi;
192 String httpprefix = "/greenstone";
193 String suffix = "/cgi-bin/library.cgi";
194
195 // get the prefix from the gsdlsite.cfg and build.properties files (port number and servername)
196 try{
197 File gsdlsite_cfg = new File(gsdl_home + File.separator + "cgi-bin" + File.separator + "gsdlsite.cfg");
198 FileInputStream fin = new FileInputStream(gsdlsite_cfg);
199 Properties gsdlProperties = new Properties();
200 if(fin != null) {
201 gsdlProperties.load(fin);
202
203 gwcgi = gsdlProperties.getProperty("gwcgi");
204 if(gwcgi != null) {
205 suffix = gwcgi;
206 } else {
207 httpprefix = gsdlProperties.getProperty("httpprefix", httpprefix);
208 suffix = httpprefix + suffix;
209 }
210 fin.close();
211 } else {
212 recordError("Could not open gsdlsite_cfg for reading, using default library prefix.");
213 }
214 //reloadConfigProperties();
215 port = config_properties.getProperty("portnumber", port);
216
217 // The "hosts" property in the config file contains more than one allowed host
218 // Need to work out the particular host chosen from the address_resolution_method
219 // Default is address_resolution_method 2: localhost
220 String addressResolutionMethod = config_properties.getProperty("address_resolution_method");
221 int address_resolution_method = (addressResolutionMethod == null) ? 2 : Integer.parseInt(addressResolutionMethod);
222 InetAddress inetAddress = null;
223 try {
224 inetAddress = InetAddress.getLocalHost();
225 } catch(UnknownHostException e) {
226 logger_.error(e);
227 logger_.info("Defaulting host IP to "+ host); // use the default
228 address_resolution_method = 2;
229 }
230 switch(address_resolution_method) {
231 case 0:
232 host = inetAddress.getHostName();
233 break;
234 case 1:
235 host = inetAddress.getHostAddress();
236 break;
237 case 2:
238 host = "localhost";
239 break;
240 case 3:
241 host = "127.0.0.1";
242 break;
243 default:
244 host = "localhost";
245 }
246 } catch(Exception e) {
247 recordError("Exception trying to load properties from gsdlsite_cfg. Using default library prefix.", e);
248 suffix = httpprefix + suffix;
249 }
250
251 libraryURL = "http://" + host + ":" + port + suffix;
252 }
253
254 public void reloadConfigProperties() {
255 super.reloadConfigProperties();
256
257 // make sure the port is okay, otherwise find another port
258 // first choice is port 80, second choice starts at 8282
259 String port = config_properties.getProperty("portnumber", "80");
260 int portDefault = 8282;
261 try {
262 int portNum = Integer.parseInt(port);
263 boolean verbose = true;
264 if(!PortFinder.isPortAvailable(portNum, verbose)) { // first time, print any Port Unavailable messages
265
266 PortFinder portFinder = new PortFinder(portDefault, 101);
267 // Search for a free port silently from now on--don't want more
268 // messages saying that a port could not be found...
269 portNum = portFinder.findPortInRange(!verbose);
270
271 if (portNum == -1) {
272 // If we've still not found a free port, do we try the default port again?
273 System.err.println("No free port found. Going to try on " + portDefault + " anyway.");
274 port = Integer.toString(portDefault);
275 } else {
276 port = Integer.toString(portNum);
277 }
278 config_properties.setProperty("portnumber", port); // store the correct port
279
280 // write this updated port to the config file, since the configure target uses the file to run
281 ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
282 ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
283 scriptReadWrite.replaceOrAddLine(fileLines, "portnumber", port, false); // write the correct port
284 scriptReadWrite.writeOutFile(config_properties_file, fileLines);
285
286 configure_required_ = true;
287 System.err.println("Running server on port " + port + ".");
288 }
289 } catch (Exception e) {
290 recordError("Exception in Server2.reload(): " + e.getMessage());
291 port = Integer.toString(portDefault);
292 }
293
294 }
295
296
297 // About to stop the webserver
298 // Custom GS2 action: remove the url property from the config file
299 protected void preStop() {
300 ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
301 ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
302
303 // Remove the url=... line, start searching from the end
304 boolean done = false;
305 for (int i = fileLines.size()-1; i >= 0 && !done; i--) {
306 String line = ((String) fileLines.get(i)).trim();
307 if(line.startsWith("url=")) {
308 fileLines.remove(i);
309 done = true;
310 }
311 }
312 scriptReadWrite.writeOutFile(config_properties_file, fileLines);
313 }
314
315 // Called when the URL has been changed (called after a reload() and starting the server).
316 // By the time we get here, reload() would already have been called and have set
317 // both the port and worked out libraryURL
318 // This method needs to write the URL to the configfile since things should work
319 // like GS2's Local Lib Server for Windows
320 protected void postStart() {
321
322 URL libURL = null;
323 try {
324 libURL = new URL(libraryURL);
325 } catch (Exception e) {
326 recordError("Unable to convert library URL string into a valid URL, Server2.java." + e);
327 }
328
329 // 1. Test that the server is running at the libraryURL before writing it out to glisite.cfg/configfile
330 // A quick test involves opening a connection to get the home page for this collection
331 if(libURL != null && !libraryURL.equals(URL_PENDING)) {
332
333 boolean ready = false;
334 for(int i = 0; i < WAITING_TIME && !ready; i++) {
335 try {
336 libURL.openConnection();
337 //URLConnection connection = new URL(libraryURL).openConnection();
338 //connection.getContent();
339 ready = true;
340 recordSuccess("Try connecting to server on url: '" + libraryURL + "'");
341 } catch (IOException bad_url_connection) {
342 // keep looping
343 recordSuccess("NOT YET CONNECTED. Waiting to try again...");
344 try {
345 Thread.sleep(1000);
346 } catch (InterruptedException ie) {
347 ready = true;
348 recordError("Unexpected: got an InterruptedException in sleeping thread, Server2.java." + ie);
349 }
350 } catch (Exception e) {
351 ready = true;
352 recordError("Got an Exception while waiting for the connection to become live, Server2.java." + e);
353 }
354 }
355 }
356
357 // 2. Now write the URL to the config file
358 String port = config_properties.getProperty("portnumber");
359
360 ScriptReadWrite scriptReadWrite = new ScriptReadWrite();
361 ArrayList fileLines = scriptReadWrite.readInFile(BaseServer.config_properties_file);
362 scriptReadWrite.replaceOrAddLine(fileLines, "url", libraryURL, true);
363 scriptReadWrite.replaceOrAddLine(fileLines, "portnumber", port, false); // write the correct port
364 scriptReadWrite.writeOutFile(config_properties_file, fileLines);
365 }
366
367
368 public static void main (String[] args)
369 {
370 if ((args.length < 1) || (args.length > 4)) {
371 System.err.println(
372 "Usage: java org.greenstone.server.Server2 <gsdl2-home-dir> [lang] [--config=configfile] [--quitport=portNum]");
373 System.exit(1);
374 }
375
376 String gsdl2_home = args[0];
377 File gsdl2_dir = new File(gsdl2_home);
378 if (!gsdl2_dir.isDirectory()) {
379 System.err.println("gsdl-home-dir directory does not exist!");
380 System.exit(1);
381 }
382
383 String lang = (args.length>=2) ? args[1] : "en";
384
385 // if no config file is given, then it defaults to llssite.cfg (embedded in quotes to preserve spaces in the filepath)
386 File defaultConfigFile = new File(gsdl2_dir, "llssite.cfg");
387 String configfile = (args.length>=3 && args[2].startsWith("--config=")) ? args[2] : defaultConfigFile.getAbsolutePath();
388 gsdl2_dir = null;
389 defaultConfigFile = null;
390
391 int equalSign = configfile.indexOf('=');
392 if(equalSign != -1) {
393 configfile = configfile.substring(equalSign+1);
394 }
395
396 String quitport = (args.length == 4 && args[3].startsWith("--quitport=")) ? args[3] : "";
397 equalSign = quitport.indexOf('=');
398 int port = -1;
399 if(equalSign != -1) {
400 try {
401 quitport = quitport.substring(equalSign+1);
402 port = Integer.parseInt(quitport);
403 } catch(Exception e) { // parse fails
404 System.err.println("Port must be numeric. Continuing without it.");
405 }
406 }
407
408 //System.err.println("Running server with config file: " + configfile);
409
410 new Server2(gsdl2_home, lang, configfile, port);
411 }
412}
Note: See TracBrowser for help on using the repository browser.