001: /*
002: * $Id: Start.java,v 1.12 2003/12/22 03:41:28 ajzeneski Exp $
003: *
004: * Copyright (c) 2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: *
024: */
025: package org.ofbiz.base.start;
026:
027: import java.io.BufferedReader;
028: import java.io.File;
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.io.InputStreamReader;
032: import java.io.PrintWriter;
033: import java.lang.reflect.Method;
034: import java.net.InetAddress;
035: import java.net.ServerSocket;
036: import java.net.ConnectException;
037: import java.net.Socket;
038: import java.util.ArrayList;
039: import java.util.Iterator;
040: import java.util.List;
041: import java.util.Properties;
042:
043: /**
044: * Start - OFBiz Container(s) Startup Class
045: *
046: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
047: *@version $Revision: 1.12 $
048: * @since 2.1
049: */
050: public class Start implements Runnable {
051:
052: public static final String CONFIG_FILE = "org/ofbiz/base/start/start.properties";
053: public static final String SHUTDOWN_COMMAND = "SHUTDOWN";
054: public static final String STATUS_COMMAND = "STATUS";
055:
056: private Classpath classPath = new Classpath(System
057: .getProperty("java.class.path"));
058: private ServerSocket serverSocket = null;
059: private Thread serverThread = null;
060: private boolean serverRunning = true;
061: private List loaders = null;
062: private Config config = null;
063:
064: public Start(String configFile) throws IOException {
065: if (configFile == null) {
066: configFile = CONFIG_FILE;
067: }
068:
069: this .config = new Config(configFile);
070: this .loaders = new ArrayList();
071: }
072:
073: public void startListenerThread() throws IOException {
074: this .serverSocket = new ServerSocket(config.adminPort, 1,
075: config.adminAddress);
076: this .serverThread = new Thread(this , this .toString());
077: this .serverThread.setDaemon(false);
078: this .serverThread.start();
079: System.out.println("Admin socket listening on - "
080: + config.adminAddress + ":" + config.adminPort);
081: }
082:
083: public void run() {
084: while (serverRunning) {
085: try {
086: Socket clientSocket = serverSocket.accept();
087: System.out.println("Received connection from - "
088: + clientSocket.getInetAddress() + " : "
089: + clientSocket.getPort());
090: processClientRequest(clientSocket);
091: clientSocket.close();
092: } catch (IOException e) {
093: e.printStackTrace();
094: }
095: }
096: shutdownServer();
097: System.exit(0);
098: }
099:
100: private void processClientRequest(Socket client) throws IOException {
101: BufferedReader reader = new BufferedReader(
102: new InputStreamReader(client.getInputStream()));
103: String request = reader.readLine();
104:
105: PrintWriter writer = new PrintWriter(client.getOutputStream(),
106: true);
107: writer.println(processRequest(request, client));
108: writer.flush();
109:
110: writer.close();
111: reader.close();
112: }
113:
114: private String processRequest(String request, Socket client) {
115: if (request != null) {
116: String key = request.substring(0, request.indexOf(':'));
117: String command = request
118: .substring(request.indexOf(':') + 1);
119: if (!key.equals(config.adminKey)) {
120: return "FAIL";
121: } else {
122: if (command.equals(Start.SHUTDOWN_COMMAND)) {
123: System.out.println("Shutdown initiated from: "
124: + client.getInetAddress().getHostAddress()
125: + ":" + client.getPort());
126: serverRunning = false;
127: } else if (command.equals(Start.STATUS_COMMAND)) {
128: return serverRunning ? "Running" : "Stopped";
129: }
130: return "OK";
131: }
132: } else {
133: return "FAIL";
134: }
135: }
136:
137: private void loadLibs(String path) throws Exception {
138: File libDir = new File(path);
139: if (libDir.exists()) {
140: File files[] = libDir.listFiles();
141: for (int i = 0; i < files.length; i++) {
142: String fileName = files[i].getName();
143: if (files[i].isDirectory() && !"CVS".equals(fileName)) {
144: loadLibs(files[i].getCanonicalPath());
145: } else if (fileName.endsWith(".jar")
146: || fileName.endsWith(".zip")) {
147: classPath.addComponent(files[i]);
148: }
149: }
150: }
151: }
152:
153: private void startServer() throws Exception {
154: // load the lib directory
155: loadLibs(config.baseLib);
156:
157: // load the ofbiz-base.jar
158: classPath.addComponent(config.baseJar);
159:
160: // load the config directory
161: classPath.addComponent(config.baseConfig);
162:
163: // set the classpath/classloader
164: System.setProperty("java.class.path", classPath.toString());
165: ClassLoader classloader = classPath.getClassLoader();
166: Thread.currentThread().setContextClassLoader(classloader);
167:
168: // set the shutdown hook
169: setShutdownHook();
170:
171: // start the listener thread
172: startListenerThread();
173:
174: // stat the log directory
175: boolean createdDir = false;
176: File logDir = new File(config.logDir);
177: if (!logDir.exists()) {
178: logDir.mkdir();
179: createdDir = true;
180: }
181:
182: // start the loaders
183: Iterator li = config.loaders.iterator();
184: while (li.hasNext()) {
185: String loaderClassName = (String) li.next();
186: try {
187: Class loaderClass = classloader
188: .loadClass(loaderClassName);
189: StartupLoader loader = (StartupLoader) loaderClass
190: .newInstance();
191: loader.load(config);
192: loaders.add(loader);
193: } catch (Exception e) {
194: e.printStackTrace();
195: System.exit(99);
196: }
197: }
198: }
199:
200: private void setShutdownHook() {
201: try {
202: Method shutdownHook = java.lang.Runtime.class.getMethod(
203: "addShutdownHook",
204: new Class[] { java.lang.Thread.class });
205: Thread hook = new Thread() {
206: public void run() {
207: setName("OFBiz_Shutdown_Hook");
208: shutdownServer();
209: // Try to avoid JVM crash
210: try {
211: Thread.sleep(1000);
212: } catch (Exception e) {
213: e.printStackTrace();
214: }
215: }
216: };
217:
218: shutdownHook.invoke(Runtime.getRuntime(),
219: new Object[] { hook });
220: } catch (Exception e) {
221: // VM Does not support shutdown hook
222: e.printStackTrace();
223: }
224: }
225:
226: private void shutdownServer() {
227: if (loaders != null && loaders.size() > 0) {
228: Iterator i = loaders.iterator();
229: while (i.hasNext()) {
230: StartupLoader loader = (StartupLoader) i.next();
231: try {
232: loader.unload();
233: } catch (Exception e) {
234: e.printStackTrace();
235: }
236: }
237: }
238: serverRunning = false;
239: }
240:
241: public void start() throws Exception {
242: startServer();
243: }
244:
245: public String status() throws Exception {
246: String status = null;
247: try {
248: status = sendSocketCommand(Start.STATUS_COMMAND);
249: } catch (ConnectException e) {
250: return "Not Running";
251: } catch (IOException e) {
252: throw e;
253: }
254: return status;
255: }
256:
257: public String shutdown() throws Exception {
258: return sendSocketCommand(Start.SHUTDOWN_COMMAND);
259: }
260:
261: private String sendSocketCommand(String command)
262: throws IOException, ConnectException {
263: Socket socket = new Socket(config.adminAddress,
264: config.adminPort);
265:
266: // send the command
267: PrintWriter writer = new PrintWriter(socket.getOutputStream(),
268: true);
269: writer.println(config.adminKey + ":" + command);
270: writer.flush();
271:
272: // read the reply
273: BufferedReader reader = new BufferedReader(
274: new InputStreamReader(socket.getInputStream()));
275: String response = null;
276: if (reader.ready()) {
277: response = reader.readLine();
278: }
279:
280: reader.close();
281:
282: // close the socket
283: writer.close();
284: socket.close();
285:
286: return response;
287: }
288:
289: public static void main(String[] args) throws Exception {
290: Start start = new Start(args.length == 2 ? args[1] : null);
291: String firstArg = args.length > 0 ? args[0] : "";
292: if (firstArg.equals("-help") || firstArg.equals("-?")
293: || args.length > 2) {
294: System.out.println("");
295: System.out
296: .println("Usage: java -jar ofbiz.jar [command] [config]");
297: System.out.println("-help, -? ----> This screen");
298: System.out.println("-start -------> Start the server");
299: System.out.println("-status ------> Status of the server");
300: System.out.println("-shutdown ----> Shutdown the server");
301: System.out.println("[no config] --> Use default config");
302: System.out
303: .println("[no command] -> Start the server w/ default config");
304: } else if (firstArg.equals("-status")) {
305: System.out.println("Current Status : " + start.status());
306: } else if (firstArg.equals("-shutdown")) {
307: System.out.println("Shutting down server : "
308: + start.shutdown());
309: } else {
310: start.start();
311: }
312: }
313:
314: public static class Config {
315: public String containerConfig;
316: public InetAddress adminAddress;
317: public int adminPort;
318: public String adminKey;
319: public String ofbizHome;
320: public String baseJar;
321: public String baseLib;
322: public String baseConfig;
323: public String logDir;
324: public List loaders;
325: public String awtHeadless;
326:
327: public Config(String config) {
328: try {
329: init(config);
330: } catch (IOException e) {
331: e.printStackTrace();
332: System.exit(-1);
333: }
334: }
335:
336: public void init(String config) throws IOException {
337: InputStream propsStream = getClass().getClassLoader()
338: .getResourceAsStream(config);
339: if (propsStream == null) {
340: throw new IOException(
341: "Cannot load configuration properties : "
342: + config);
343: }
344: Properties props = new Properties();
345: props.load(propsStream);
346:
347: // set the ofbiz.home
348: if (ofbizHome == null) {
349: ofbizHome = props.getProperty("ofbiz.home", ".");
350: // get a full path
351: if (ofbizHome.equals(".")) {
352: ofbizHome = System.getProperty("user.dir");
353: ofbizHome = ofbizHome.replace('\\', '/');
354: }
355: }
356: System.setProperty("ofbiz.home", ofbizHome);
357:
358: // base config directory
359: baseConfig = System.getProperty("ofbiz.base.config");
360: if (baseConfig == null) {
361: baseConfig = ofbizHome
362: + "/"
363: + props.getProperty("ofbiz.base.config",
364: "config");
365: }
366:
367: // base lib directory
368: baseLib = System.getProperty("ofbiz.base.lib");
369: if (baseLib == null) {
370: baseLib = ofbizHome + "/"
371: + props.getProperty("ofbiz.base.lib", "lib");
372: }
373:
374: // base jar file
375: baseJar = System.getProperty("ofbiz.base.jar");
376: if (baseJar == null) {
377: baseJar = ofbizHome
378: + "/"
379: + props.getProperty("ofbiz.base.jar",
380: "base/build/lib/ofbiz-base.jar");
381: }
382:
383: // log directory
384: logDir = System.getProperty("ofbiz.log.dir");
385: if (logDir == null) {
386: logDir = ofbizHome + "/"
387: + props.getProperty("ofbiz.log.dir", "logs");
388: }
389:
390: // container configuration
391: containerConfig = System
392: .getProperty("ofbiz.container.config");
393: if (containerConfig == null) {
394: containerConfig = ofbizHome
395: + "/"
396: + props.getProperty("ofbiz.container.config",
397: "base/config/ofbiz-containers.xml");
398: }
399:
400: // get the admin server info
401: String serverHost = System.getProperty("ofbiz.admin.host");
402: if (serverHost == null) {
403: serverHost = props.getProperty("ofbiz.admin.host",
404: "127.0.0.1");
405: }
406:
407: String adminPortStr = System
408: .getProperty("ofbiz.admin.port");
409: if (adminPortStr == null) {
410: adminPortStr = props.getProperty("ofbiz.admin.port",
411: "10523");
412: }
413:
414: // set the admin key
415: adminKey = System.getProperty("ofbiz.admin.key");
416: if (adminKey == null) {
417: adminKey = props.getProperty("ofbiz.admin.key", "NA");
418: }
419:
420: // create the host InetAddress
421: adminAddress = InetAddress.getByName(serverHost);
422:
423: // parse the port number
424: try {
425: adminPort = Integer.parseInt(adminPortStr);
426: } catch (Exception e) {
427: adminPort = 10523;
428: }
429:
430: // set the property to tell Log4J to use debug.properties
431: String log4jConfig = System
432: .getProperty("log4j.configuration");
433: if (log4jConfig == null) {
434: log4jConfig = props.getProperty("log4j.configuration");
435: }
436:
437: // build a default log4j configuration based on ofbizHome
438: if (log4jConfig == null) {
439: log4jConfig = ofbizHome + "/config/debug.properties";
440: }
441:
442: // set the log4j configuration property so we don't pick up one inside jars by mistake
443: System.setProperty("log4j.configuration", log4jConfig);
444:
445: awtHeadless = System.getProperty("java.awt.headless");
446: if (awtHeadless == null) {
447: awtHeadless = props.getProperty("java.awt.headless");
448: }
449: if (awtHeadless != null) {
450: System.setProperty("java.awt.headless", awtHeadless);
451: }
452:
453: // set the property to tell Jetty to use 2.4 SessionListeners
454: System
455: .setProperty(
456: "org.mortbay.jetty.servlet.AbstractSessionManager.24SessionDestroyed",
457: "true");
458:
459: // loader classes
460: loaders = new ArrayList();
461: int currentPosition = 1;
462: while (true) {
463: String loaderClass = props
464: .getProperty("ofbiz.start.loader"
465: + currentPosition);
466: if (loaderClass == null || loaderClass.length() == 0) {
467: break;
468: } else {
469: loaders.add(loaderClass);
470: currentPosition++;
471: }
472: }
473:
474: // close the stream
475: propsStream.close();
476: }
477: }
478: }
|