001: /*
002: * Helma License Notice
003: *
004: * The contents of this file are subject to the Helma License
005: * Version 2.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://adele.helma.org/download/helma/license.txt
008: *
009: * Copyright 1998-2003 Helma Software. All Rights Reserved.
010: *
011: * $RCSfile: Server.java,v $
012: * $Author: hannes $
013: * $Revision: 8701 $
014: * $Date: 2007-12-11 12:17:37 +0100 (Die, 11 Dez 2007) $
015: */
016:
017: package helma.main;
018:
019: import helma.extensions.HelmaExtension;
020: import helma.framework.repository.FileResource;
021: import helma.framework.core.*;
022: import helma.objectmodel.db.DbSource;
023: import helma.util.*;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.apache.xmlrpc.*;
027: import org.mortbay.http.*;
028: import org.mortbay.http.ajp.*;
029: import org.mortbay.util.InetAddrPort;
030:
031: import java.io.*;
032: import java.rmi.registry.*;
033: import java.rmi.server.*;
034: import java.util.*;
035: import helma.util.ResourceProperties;
036:
037: /**
038: * Helma server main class.
039: */
040: public class Server implements Runnable {
041: // version string
042: public static final String version = "1.6.1 (__builddate__)";
043:
044: // static server instance
045: private static Server server;
046:
047: // Server home directory
048: protected File hopHome;
049:
050: // server-wide properties
051: ResourceProperties appsProps;
052: ResourceProperties dbProps;
053: ResourceProperties sysProps;
054:
055: // our logger
056: private Log logger;
057: // are we using helma.util.Logging?
058: private boolean helmaLogging;
059:
060: // server start time
061: public final long starttime;
062:
063: // if paranoid == true we only accept RMI and XML-RPC connections from
064: // explicitly listed hosts.
065: public boolean paranoid;
066: private ApplicationManager appManager;
067: private Vector extensions;
068: private Thread mainThread;
069:
070: // server ports
071: InetAddrPort rmiPort = null;
072: InetAddrPort xmlrpcPort = null;
073: InetAddrPort websrvPort = null;
074: InetAddrPort ajp13Port = null;
075:
076: // map of server-wide database sources
077: Hashtable dbSources;
078:
079: // the embedded web server
080: // protected Serve websrv;
081: protected HttpServer http;
082:
083: // the AJP13 Listener, used for connecting from external webserver to servlet via JK
084: protected AJP13Listener ajp13;
085:
086: // the XML-RPC server
087: protected WebServer xmlrpc;
088:
089: Thread shutdownhook;
090:
091: /**
092: * Constructs a new Server instance with an array of command line options.
093: */
094: public Server(ServerConfig config) {
095: server = this ;
096: starttime = System.currentTimeMillis();
097:
098: rmiPort = config.rmiPort;
099: xmlrpcPort = config.xmlrpcPort;
100: websrvPort = config.websrvPort;
101: ajp13Port = config.ajp13Port;
102: hopHome = config.homeDir;
103:
104: // create system properties
105: sysProps = new ResourceProperties();
106: sysProps.addResource(new FileResource(config.propFile));
107: }
108:
109: /**
110: * static main entry point.
111: */
112: public static void main(String[] args) {
113: checkJavaVersion();
114:
115: ServerConfig config = null;
116: try {
117: config = getConfig(args);
118: } catch (Exception cex) {
119: printUsageError("error reading configuration: "
120: + cex.getMessage());
121: System.exit(1);
122: }
123:
124: checkRunning(config);
125:
126: // create new server instance
127: server = new Server(config);
128:
129: // parse properties files etc
130: server.init();
131:
132: // start the server main thread
133: server.start();
134: }
135:
136: /**
137: * check if we are running on a Java 2 VM - otherwise exit with an error message
138: */
139: public static void checkJavaVersion() {
140: String javaVersion = System.getProperty("java.version");
141:
142: if ((javaVersion == null) || javaVersion.startsWith("1.3")
143: || javaVersion.startsWith("1.2")
144: || javaVersion.startsWith("1.1")
145: || javaVersion.startsWith("1.0")) {
146: System.err
147: .println("This version of Helma requires Java 1.4 or greater.");
148:
149: if (javaVersion == null) { // don't think this will ever happen, but you never know
150: System.err
151: .println("Your Java Runtime did not provide a version number. Please update to a more recent version.");
152: } else {
153: System.err.println("Your Java Runtime is version "
154: + javaVersion
155: + ". Please update to a more recent version.");
156: }
157:
158: System.exit(1);
159: }
160: }
161:
162: /**
163: * parse the command line arguments, read a given server.properties file
164: * and check the values given for server ports
165: * @return ServerConfig if successfull
166: * @throws Exception on any configuration error
167: */
168: public static ServerConfig getConfig(String[] args)
169: throws Exception {
170:
171: ServerConfig config = new ServerConfig();
172:
173: // get possible environment setting for helma home
174: if (System.getProperty("helma.home") != null) {
175: config.homeDir = new File(System.getProperty("helma.home"));
176: }
177:
178: parseArgs(config, args);
179:
180: guessConfig(config);
181:
182: // create system properties
183: ResourceProperties sysProps = new ResourceProperties();
184: sysProps.addResource(new FileResource(config.propFile));
185:
186: // check if there's a property setting for those ports not specified via command line
187: if ((config.websrvPort == null)
188: && (sysProps.getProperty("webPort") != null)) {
189: try {
190: config.websrvPort = new InetAddrPort(sysProps
191: .getProperty("webPort"));
192: } catch (Exception portx) {
193: throw new Exception(
194: "Error parsing web server port property from server.properties: "
195: + portx);
196: }
197: }
198:
199: if ((config.ajp13Port == null)
200: && (sysProps.getProperty("ajp13Port") != null)) {
201: try {
202: config.ajp13Port = new InetAddrPort(sysProps
203: .getProperty("ajp13Port"));
204: } catch (Exception portx) {
205: throw new Exception(
206: "Error parsing AJP1.3 server port property from server.properties: "
207: + portx);
208: }
209: }
210:
211: if ((config.rmiPort == null)
212: && (sysProps.getProperty("rmiPort") != null)) {
213: try {
214: config.rmiPort = new InetAddrPort(sysProps
215: .getProperty("rmiPort"));
216: } catch (Exception portx) {
217: throw new Exception(
218: "Error parsing RMI server port property from server.properties: "
219: + portx);
220: }
221: }
222:
223: if ((config.xmlrpcPort == null)
224: && (sysProps.getProperty("xmlrpcPort") != null)) {
225: try {
226: config.xmlrpcPort = new InetAddrPort(sysProps
227: .getProperty("xmlrpcPort"));
228: } catch (Exception portx) {
229: throw new Exception(
230: "Error parsing XML-RPC server port property from server.properties: "
231: + portx);
232: }
233: }
234: return config;
235: }
236:
237: /**
238: * parse argument list from command line and store values
239: * in given ServerConfig object
240: * @throws Exception when argument can't be parsed into an InetAddrPort
241: * or invalid token is given.
242: */
243: public static void parseArgs(ServerConfig config, String[] args)
244: throws Exception {
245: for (int i = 0; i < args.length; i++) {
246: if (args[i].equals("-h") && ((i + 1) < args.length)) {
247: config.homeDir = new File(args[++i]);
248: } else if (args[i].equals("-f") && ((i + 1) < args.length)) {
249: config.propFile = new File(args[++i]);
250: } else if (args[i].equals("-p") && ((i + 1) < args.length)) {
251: try {
252: config.rmiPort = new InetAddrPort(args[++i]);
253: } catch (Exception portx) {
254: throw new Exception(
255: "Error parsing RMI server port property: "
256: + portx);
257: }
258: } else if (args[i].equals("-x") && ((i + 1) < args.length)) {
259: try {
260: config.xmlrpcPort = new InetAddrPort(args[++i]);
261: } catch (Exception portx) {
262: throw new Exception(
263: "Error parsing XML-RPC server port property: "
264: + portx);
265: }
266: } else if (args[i].equals("-w") && ((i + 1) < args.length)) {
267: try {
268: config.websrvPort = new InetAddrPort(args[++i]);
269: } catch (Exception portx) {
270: throw new Exception(
271: "Error parsing web server port property: "
272: + portx);
273: }
274: } else if (args[i].equals("-jk") && ((i + 1) < args.length)) {
275: try {
276: config.ajp13Port = new InetAddrPort(args[++i]);
277: } catch (Exception portx) {
278: throw new Exception(
279: "Error parsing AJP1.3 server port property: "
280: + portx);
281: }
282: } else if (args[i].equals("-i") && ((i + 1) < args.length)) {
283: // eat away the -i parameter which is meant for helma.main.launcher.Main
284: i++;
285: } else {
286: throw new Exception("Unknown command line token: "
287: + args[i]);
288: }
289: }
290: }
291:
292: /**
293: * get main property file from home dir or vice versa,
294: * depending on what we have
295: */
296: public static void guessConfig(ServerConfig config)
297: throws Exception {
298: // get property file from hopHome:
299: if (config.propFile == null) {
300: if (config.homeDir != null) {
301: config.propFile = new File(config.homeDir,
302: "server.properties");
303: } else {
304: config.propFile = new File("server.properties");
305: }
306: }
307:
308: // create system properties
309: ResourceProperties sysProps = new ResourceProperties();
310: sysProps.addResource(new FileResource(config.propFile));
311:
312: // try to get hopHome from property file
313: if (config.homeDir == null
314: && sysProps.getProperty("hophome") != null) {
315: config.homeDir = new File(sysProps.getProperty("hophome"));
316: }
317:
318: // use the directory where server.properties is located:
319: if (config.homeDir == null && config.propFile != null) {
320: config.homeDir = config.propFile.getAbsoluteFile()
321: .getParentFile();
322: }
323:
324: if (!config.hasPropFile()) {
325: throw new Exception("no server.properties found");
326: }
327:
328: if (!config.hasHomeDir()) {
329: throw new Exception("couldn't determine helma directory");
330: }
331:
332: // try to transform hopHome directory to its canonical representation
333: try {
334: config.homeDir = config.homeDir.getCanonicalFile();
335: } catch (IOException iox) {
336: config.homeDir = config.homeDir.getAbsoluteFile();
337: }
338: }
339:
340: /**
341: * print the usage hints and prefix them with a message.
342: */
343: public static void printUsageError(String msg) {
344: System.out.println(msg);
345: printUsageError();
346: }
347:
348: /**
349: * print the usage hints
350: */
351: public static void printUsageError() {
352: System.out.println("");
353: System.out.println("Usage: java helma.main.Server [options]");
354: System.out.println("Possible options:");
355: System.out.println(" -h dir Specify hop home directory");
356: System.out
357: .println(" -f file Specify server.properties file");
358: System.out
359: .println(" -w [ip:]port Specify embedded web server address/port");
360: System.out
361: .println(" -x [ip:]port Specify XML-RPC address/port");
362: System.out
363: .println(" -jk [ip:]port Specify AJP13 address/port");
364: System.out
365: .println(" -p [ip:]port Specify RMI address/port");
366: System.out.println("");
367: System.out.println("Supported formats for server ports:");
368: System.out.println(" <port-number>");
369: System.out.println(" <ip-address>:<port-number>");
370: System.out.println(" <hostname>:<port-number>");
371: System.out.println("");
372: System.err.println("Usage Error - exiting");
373: System.out.println("");
374: }
375:
376: /**
377: * Check wheter a server is already running on any of the given ports
378: * - otherwise exit with an error message
379: */
380: public static void checkRunning(ServerConfig config) {
381: // check if any of the specified server ports is in use already
382: try {
383: if (config.websrvPort != null) {
384: checkPort(config.websrvPort);
385: }
386:
387: if (config.rmiPort != null) {
388: checkPort(config.rmiPort);
389: }
390:
391: if (config.xmlrpcPort != null) {
392: checkPort(config.xmlrpcPort);
393: }
394:
395: if (config.ajp13Port != null) {
396: checkPort(config.ajp13Port);
397: }
398: } catch (Exception running) {
399: System.out.println(running.getMessage());
400: System.exit(1);
401: }
402:
403: }
404:
405: /**
406: * A primitive method to check whether a server is already running on our port.
407: */
408: private static void checkPort(InetAddrPort addrPort)
409: throws Exception {
410: // checkRunning is disabled until we find a fix for the socket creation
411: // timeout problems reported on the list.
412: return;
413:
414: /*
415: InetAddress addr = addrPort.getInetAddress();
416: if (addr == null) {
417: try {
418: addr = InetAddress.getLocalHost();
419: } catch (UnknownHostException unknown) {
420: System.err.println("Error checking running server: localhost is unknown.");
421: return;
422: }
423: }
424: try {
425: new Socket(addr, addrPort.getPort());
426: } catch (IOException x) {
427: // we couldn't connect to the socket because no server
428: // is running on it yet. Everything's ok.
429: return;
430: }
431:
432: // if we got so far, another server is already running on this port and db
433: throw new Exception("Error: Server already running on this port: " + addrPort);
434: */
435: }
436:
437: /**
438: * initialize the server
439: */
440: public void init() {
441:
442: // set the log factory property
443: String logFactory = sysProps.getProperty("loggerFactory",
444: "helma.util.Logging");
445:
446: helmaLogging = "helma.util.Logging".equals(logFactory);
447: System.setProperty("org.apache.commons.logging.LogFactory",
448: logFactory);
449:
450: // set the current working directory to the helma home dir.
451: // note that this is not a real cwd, which is not supported
452: // by java. It makes sure relative to absolute path name
453: // conversion is done right, so for Helma code, this should work.
454: System.setProperty("user.dir", hopHome.getPath());
455:
456: // from now on it's safe to call getLogger() because hopHome is set up
457: getLogger();
458:
459: String startMessage = "Starting Helma " + version + " on Java "
460: + System.getProperty("java.version");
461:
462: logger.info(startMessage);
463:
464: // also print a msg to System.out
465: System.out.println(startMessage);
466:
467: logger.info("Setting Helma Home to " + hopHome);
468:
469: // read db.properties file in helma home directory
470: dbProps = new ResourceProperties();
471: dbProps.setIgnoreCase(false);
472: dbProps.addResource(new FileResource(new File(hopHome,
473: "db.properties")));
474: DbSource.setDefaultProps(dbProps);
475:
476: // read apps.properties file
477: String appsPropfile = sysProps.getProperty("appsPropFile");
478: File file;
479: if ((appsPropfile != null) && !"".equals(appsPropfile.trim())) {
480: file = new File(appsPropfile);
481: } else {
482: file = new File(hopHome, "apps.properties");
483: }
484: appsProps = new ResourceProperties();
485: appsProps.setIgnoreCase(true);
486: appsProps.addResource(new FileResource(file));
487:
488: paranoid = "true".equalsIgnoreCase(sysProps
489: .getProperty("paranoid"));
490:
491: String language = sysProps.getProperty("language");
492: String country = sysProps.getProperty("country");
493: String timezone = sysProps.getProperty("timezone");
494:
495: if ((language != null) && (country != null)) {
496: Locale.setDefault(new Locale(language, country));
497: }
498:
499: if (timezone != null) {
500: TimeZone.setDefault(TimeZone.getTimeZone(timezone));
501: }
502:
503: // logger.debug("Locale = " + Locale.getDefault());
504: // logger.debug("TimeZone = " +
505: // TimeZone.getDefault().getDisplayName(Locale.getDefault()));
506:
507: dbSources = new Hashtable();
508:
509: // try to load the extensions
510: extensions = new Vector();
511: if (sysProps.getProperty("extensions") != null) {
512: initExtensions();
513: }
514: }
515:
516: /**
517: * initialize extensions
518: */
519: private void initExtensions() {
520: StringTokenizer tok = new StringTokenizer(sysProps
521: .getProperty("extensions"), ",");
522: while (tok.hasMoreTokens()) {
523: String extClassName = tok.nextToken().trim();
524:
525: try {
526: Class extClass = Class.forName(extClassName);
527: HelmaExtension ext = (HelmaExtension) extClass
528: .newInstance();
529: ext.init(this );
530: extensions.add(ext);
531: logger.info("Loaded: " + extClassName);
532: } catch (Throwable e) {
533: logger.error("Error loading extension " + extClassName
534: + ": " + e.toString());
535: }
536: }
537: }
538:
539: public void start() {
540: // Start running, finishing setup and then entering a loop to check changes
541: // in the apps.properties file.
542: mainThread = new Thread(this );
543: mainThread.start();
544: }
545:
546: public void stop() {
547: mainThread = null;
548:
549: getLogger().info("Shutting down Helma");
550:
551: appManager.stopAll();
552:
553: if (http != null) {
554: try {
555: http.stop();
556: http.destroy();
557: } catch (InterruptedException irx) {
558: // http.stop() interrupted by another thread. ignore.
559: }
560: }
561:
562: if (xmlrpc != null) {
563: try {
564: xmlrpc.shutdown();
565: } catch (Exception x) {
566: // exception in xmlrpc server shutdown, ignore.
567: }
568: }
569:
570: if (helmaLogging) {
571: Logging.shutdown();
572: }
573:
574: server = null;
575:
576: try {
577: Runtime.getRuntime().removeShutdownHook(shutdownhook);
578: // HACK: running the shutdownhook seems to be necessary in order
579: // to prevent it from blocking garbage collection of helma
580: // classes/classloaders. Since we already set server to null it
581: // won't do anything anyhow.
582: shutdownhook.start();
583: shutdownhook = null;
584: } catch (Exception x) {
585: // invalid shutdown hook or already shutting down. ignore.
586: }
587: }
588:
589: /**
590: * The main method of the Server. Basically, we set up Applications and than
591: * periodically check for changes in the apps.properties file, shutting down
592: * apps or starting new ones.
593: */
594: public void run() {
595: try {
596: if ((websrvPort != null) || (ajp13Port != null)) {
597: http = new HttpServer();
598: }
599:
600: // start embedded web server if port is specified
601: if (websrvPort != null) {
602: http.addListener(websrvPort);
603: }
604:
605: // activate the ajp13-listener
606: if (ajp13Port != null) {
607: // create AJP13Listener
608: ajp13 = new AJP13Listener(ajp13Port);
609: ajp13.setHttpServer(http);
610:
611: String jkallow = sysProps.getProperty("allowAJP13");
612:
613: // by default the AJP13-connection just accepts requests from 127.0.0.1
614: if (jkallow == null) {
615: jkallow = "127.0.0.1";
616: }
617:
618: StringTokenizer st = new StringTokenizer(jkallow, " ,;");
619: String[] jkallowarr = new String[st.countTokens()];
620: int cnt = 0;
621:
622: while (st.hasMoreTokens()) {
623: jkallowarr[cnt] = st.nextToken();
624: cnt++;
625: }
626:
627: ajp13.setRemoteServers(jkallowarr);
628: logger.info("Starting AJP13-Listener on port "
629: + (ajp13Port));
630: }
631:
632: if (xmlrpcPort != null) {
633: String xmlparser = sysProps.getProperty("xmlparser");
634:
635: if (xmlparser != null) {
636: XmlRpc.setDriver(xmlparser);
637: }
638:
639: if (xmlrpcPort.getInetAddress() != null) {
640: xmlrpc = new WebServer(xmlrpcPort.getPort(),
641: xmlrpcPort.getInetAddress());
642: } else {
643: xmlrpc = new WebServer(xmlrpcPort.getPort());
644: }
645:
646: if (paranoid) {
647: xmlrpc.setParanoid(true);
648:
649: String xallow = sysProps.getProperty("allowXmlRpc");
650:
651: if (xallow != null) {
652: StringTokenizer st = new StringTokenizer(
653: xallow, " ,;");
654:
655: while (st.hasMoreTokens())
656: xmlrpc.acceptClient(st.nextToken());
657: }
658: }
659: xmlrpc.start();
660: logger.info("Starting XML-RPC server on port "
661: + (xmlrpcPort));
662: }
663:
664: if (rmiPort != null) {
665: if (paranoid) {
666: HelmaSocketFactory factory = new HelmaSocketFactory();
667: String rallow = sysProps.getProperty("allowWeb");
668: if (rallow == null) {
669: rallow = sysProps.getProperty("allowRMI");
670: }
671:
672: if (rallow != null) {
673: StringTokenizer st = new StringTokenizer(
674: rallow, " ,;");
675:
676: while (st.hasMoreTokens())
677: factory.addAddress(st.nextToken());
678: }
679:
680: RMISocketFactory.setSocketFactory(factory);
681: }
682:
683: logger.info("Starting RMI server on port " + rmiPort);
684: LocateRegistry.createRegistry(rmiPort.getPort());
685:
686: // create application manager which binds to the given RMI port
687: appManager = new ApplicationManager(appsProps, this ,
688: rmiPort.getPort());
689: } else {
690: // create application manager with RMI port 0
691: appManager = new ApplicationManager(appsProps, this , 0);
692: }
693:
694: if (xmlrpc != null) {
695: xmlrpc.addHandler("$default", appManager);
696: }
697:
698: // add shutdown hook to close running apps and servers on exit
699: shutdownhook = new HelmaShutdownHook();
700: Runtime.getRuntime().addShutdownHook(shutdownhook);
701: } catch (Exception x) {
702: throw new RuntimeException("Error setting up Server", x);
703: }
704:
705: // set the security manager.
706: // the default implementation is helma.main.HelmaSecurityManager.
707: try {
708: String secManClass = sysProps
709: .getProperty("securityManager");
710:
711: if (secManClass != null) {
712: SecurityManager secMan = (SecurityManager) Class
713: .forName(secManClass).newInstance();
714:
715: System.setSecurityManager(secMan);
716: logger.info("Setting security manager to "
717: + secManClass);
718: }
719: } catch (Exception x) {
720: logger.error("Error setting security manager", x);
721: }
722:
723: // start embedded web server
724: if (http != null) {
725: try {
726: http.start();
727: } catch (Exception m) {
728: throw new RuntimeException(
729: "Error starting embedded web server", m);
730: }
731: }
732:
733: if (ajp13 != null) {
734: try {
735: ajp13.start();
736: } catch (Exception m) {
737: throw new RuntimeException(
738: "Error starting AJP13 listener: " + m);
739: }
740: }
741:
742: // start applications
743: appManager.startAll();
744:
745: while (Thread.currentThread() == mainThread) {
746: try {
747: Thread.sleep(3000L);
748: } catch (InterruptedException ie) {
749: }
750:
751: try {
752: appManager.checkForChanges();
753: } catch (Exception x) {
754: logger.warn("Caught in app manager loop: " + x);
755: }
756: }
757: }
758:
759: /**
760: * Make sure this server has an ApplicationManager (e.g. used when
761: * accessed from CommandlineRunner)
762: */
763: public void checkAppManager(int port) {
764: if (appManager == null) {
765: appManager = new ApplicationManager(appsProps, this , port);
766: }
767: }
768:
769: /**
770: * Get an Iterator over the applications currently running on this Server.
771: */
772: public Object[] getApplications() {
773: return appManager.getApplications();
774: }
775:
776: /**
777: * Get an Application by name
778: */
779: public Application getApplication(String name) {
780: return appManager.getApplication(name);
781: }
782:
783: /**
784: * Get a logger to use for output in this server.
785: */
786: public Log getLogger() {
787: if (logger == null) {
788: if (helmaLogging) {
789: // set up system properties for helma.util.Logging
790: String logDir = sysProps.getProperty("logdir", "log");
791:
792: if (!"console".equals(logDir)) {
793: // try to get the absolute logdir path
794:
795: // set up helma.logdir system property
796: File dir = new File(logDir);
797: if (!dir.isAbsolute()) {
798: dir = new File(hopHome, logDir);
799: }
800:
801: logDir = dir.getAbsolutePath();
802: }
803: System.setProperty("helma.logdir", logDir);
804: }
805: logger = LogFactory.getLog("helma.server");
806: }
807:
808: return logger;
809: }
810:
811: /**
812: * Get the Home directory of this server.
813: */
814: public File getHopHome() {
815: return hopHome;
816: }
817:
818: /**
819: * Get the main Server instance.
820: */
821: public static Server getServer() {
822: return server;
823: }
824:
825: /**
826: * Get the Server's XML-RPC web server.
827: */
828: public static WebServer getXmlRpcServer() {
829: return server.xmlrpc;
830: }
831:
832: /**
833: *
834: *
835: * @param key ...
836: *
837: * @return ...
838: */
839: public String getProperty(String key) {
840: return (String) sysProps.get(key);
841: }
842:
843: /**
844: * Return the server.properties for this server
845: * @return the server.properties
846: */
847: public ResourceProperties getProperties() {
848: return sysProps;
849: }
850:
851: /**
852: * Return the server-wide db.properties
853: * @return the server-wide db.properties
854: */
855: public ResourceProperties getDbProperties() {
856: return dbProps;
857: }
858:
859: /**
860: * Return the apps.properties entries for a given application
861: * @param appName the app name
862: * @return the apps.properties subproperties for the given app
863: */
864: public ResourceProperties getAppsProperties(String appName) {
865: return appsProps.getSubProperties(appName + ".");
866: }
867:
868: /**
869: *
870: *
871: * @return ...
872: */
873: public File getAppsHome() {
874: String appHome = sysProps.getProperty("appHome", "");
875:
876: if (appHome.trim().length() != 0) {
877: return new File(appHome);
878: } else {
879: return new File(hopHome, "apps");
880: }
881: }
882:
883: /**
884: *
885: *
886: * @return ...
887: */
888: public File getDbHome() {
889: String dbHome = sysProps.getProperty("dbHome", "");
890:
891: if (dbHome.trim().length() != 0) {
892: return new File(dbHome);
893: } else {
894: return new File(hopHome, "db");
895: }
896: }
897:
898: /**
899: *
900: *
901: * @return ...
902: */
903: public Vector getExtensions() {
904: return extensions;
905: }
906:
907: /**
908: *
909: *
910: * @param name ...
911: */
912: public void startApplication(String name) {
913: appManager.start(name);
914: appManager.register(name);
915: }
916:
917: /**
918: *
919: *
920: * @param name ...
921: */
922: public void stopApplication(String name) {
923: appManager.stop(name);
924: }
925: }
|