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

Last change on this file since 19441 was 19441, checked in by ak19, 15 years ago

Uses PortFinder.isPortAvailable() with the new verbose flag and prints out a message saying which port is being used if this is different from what was specified in llssite.cfg.

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