001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.catalina.startup;
018:
019: import java.beans.PropertyChangeListener;
020: import java.beans.PropertyChangeSupport;
021: import java.io.File;
022: import java.io.IOException;
023: import java.net.InetAddress;
024:
025: import org.apache.catalina.Connector;
026: import org.apache.catalina.Container;
027: import org.apache.catalina.Context;
028: import org.apache.catalina.Engine;
029: import org.apache.catalina.Host;
030: import org.apache.catalina.Lifecycle;
031: import org.apache.catalina.LifecycleException;
032: import org.apache.catalina.LifecycleListener;
033: import org.apache.catalina.Loader;
034: import org.apache.catalina.Logger;
035: import org.apache.catalina.Realm;
036: import org.apache.catalina.core.StandardContext;
037: import org.apache.catalina.core.StandardEngine;
038: import org.apache.catalina.core.StandardHost;
039: import org.apache.catalina.core.StandardService;
040: import org.apache.catalina.loader.WebappLoader;
041: import org.apache.catalina.logger.FileLogger;
042: import org.apache.catalina.net.ServerSocketFactory;
043: import org.apache.catalina.security.SecurityConfig;
044: import org.apache.catalina.util.LifecycleSupport;
045: import org.apache.catalina.util.StringManager;
046: import org.apache.commons.logging.Log;
047: import org.apache.commons.logging.LogFactory;
048: import org.apache.tomcat.util.IntrospectionUtils;
049:
050: /**
051: * Convenience class to embed a Catalina servlet container environment
052: * inside another application. You must call the methods of this class in the
053: * following order to ensure correct operation.
054: *
055: * <ul>
056: * <li>Instantiate a new instance of this class.</li>
057: * <li>Set the relevant properties of this object itself. In particular,
058: * you will want to establish the default Logger to be used, as well
059: * as the default Realm if you are using container-managed security.</li>
060: * <li>Call <code>createEngine()</code> to create an Engine object, and then
061: * call its property setters as desired.</li>
062: * <li>Call <code>createHost()</code> to create at least one virtual Host
063: * associated with the newly created Engine, and then call its property
064: * setters as desired. After you customize this Host, add it to the
065: * corresponding Engine with <code>engine.addChild(host)</code>.</li>
066: * <li>Call <code>createContext()</code> to create at least one Context
067: * associated with each newly created Host, and then call its property
068: * setters as desired. You <strong>SHOULD</strong> create a Context with
069: * a pathname equal to a zero-length string, which will be used to process
070: * all requests not mapped to some other Context. After you customize
071: * this Context, add it to the corresponding Host with
072: * <code>host.addChild(context)</code>.</li>
073: * <li>Call <code>addEngine()</code> to attach this Engine to the set of
074: * defined Engines for this object.</li>
075: * <li>Call <code>createConnector()</code> to create at least one TCP/IP
076: * connector, and then call its property setters as desired.</li>
077: * <li>Call <code>addConnector()</code> to attach this Connector to the set
078: * of defined Connectors for this object. The added Connector will use
079: * the most recently added Engine to process its received requests.</li>
080: * <li>Repeat the above series of steps as often as required (although there
081: * will typically be only one Engine instance created).</li>
082: * <li>Call <code>start()</code> to initiate normal operations of all the
083: * attached components.</li>
084: * </ul>
085: *
086: * After normal operations have begun, you can add and remove Connectors,
087: * Engines, Hosts, and Contexts on the fly. However, once you have removed
088: * a particular component, it must be thrown away -- you can create a new one
089: * with the same characteristics if you merely want to do a restart.
090: * <p>
091: * To initiate a normal shutdown, call the <code>stop()</code> method of
092: * this object.
093: * <p>
094: * <strong>IMPLEMENTATION NOTE</strong>: The <code>main()</code> method of
095: * this class is a simple example that exercizes the features of dynamically
096: * starting and stopping various components. You can execute this by executing
097: * the following steps (on a Unix platform):
098: * <pre>
099: * cd $CATALINA_HOME
100: * ./bin/catalina.sh embedded
101: * </pre>
102: *
103: * @author Craig R. McClanahan
104: * @version $Revision: 1.16 $ $Date: 2004/06/10 18:59:48 $
105: */
106:
107: public class Embedded extends StandardService implements Lifecycle {
108: private static Log log = LogFactory.getLog(Embedded.class);
109:
110: // ----------------------------------------------------------- Constructors
111:
112: /**
113: * Construct a new instance of this class with default properties.
114: */
115: public Embedded() {
116:
117: this (null, null);
118:
119: }
120:
121: /**
122: * Construct a new instance of this class with specified properties.
123: *
124: * @param logger Logger implementation to be inherited by all components
125: * (unless overridden further down the container hierarchy)
126: * @param realm Realm implementation to be inherited by all components
127: * (unless overridden further down the container hierarchy)
128: */
129: public Embedded(Logger logger, Realm realm) {
130:
131: super ();
132: setLogger(logger);
133: setRealm(realm);
134: setSecurityProtection();
135:
136: }
137:
138: // ----------------------------------------------------- Instance Variables
139:
140: /**
141: * Is naming enabled ?
142: */
143: protected boolean useNaming = true;
144:
145: /**
146: * The set of Engines that have been deployed in this server. Normally
147: * there will only be one.
148: */
149: protected Engine engines[] = new Engine[0];
150:
151: /**
152: * Descriptive information about this server implementation.
153: */
154: protected static final String info = "org.apache.catalina.startup.Embedded/1.0";
155:
156: /**
157: * The lifecycle event support for this component.
158: */
159: protected LifecycleSupport lifecycle = new LifecycleSupport(this );
160:
161: /**
162: * The default logger to be used by this component itself. Unless this
163: * is overridden, log messages will be writted to standard output.
164: */
165: protected Logger logger = null;
166:
167: /**
168: * The default realm to be used by all containers associated with
169: * this compoennt.
170: */
171: protected Realm realm = null;
172:
173: /**
174: * The string manager for this package.
175: */
176: protected static StringManager sm = StringManager
177: .getManager(Constants.Package);
178:
179: /**
180: * The socket factory that will be used when a <code>secure</code>
181: * Connector is created. If a standard Connector is created, the
182: * internal (to the Connector class default socket factory class)
183: * will be used instead.
184: */
185: protected String socketFactory = "org.apache.catalina.net.SSLSocketFactory";
186:
187: /**
188: * Has this component been started yet?
189: */
190: protected boolean started = false;
191:
192: /**
193: * Use await.
194: */
195: protected boolean await = false;
196:
197: // ------------------------------------------------------------- Properties
198:
199: /**
200: * Return true if naming is enabled.
201: */
202: public boolean isUseNaming() {
203:
204: return (this .useNaming);
205:
206: }
207:
208: /**
209: * Enables or disables naming support.
210: *
211: * @param useNaming The new use naming value
212: */
213: public void setUseNaming(boolean useNaming) {
214:
215: boolean oldUseNaming = this .useNaming;
216: this .useNaming = useNaming;
217: support.firePropertyChange("useNaming", new Boolean(
218: oldUseNaming), new Boolean(this .useNaming));
219:
220: }
221:
222: /**
223: * Return the Logger for this component.
224: */
225: public Logger getLogger() {
226:
227: return (this .logger);
228:
229: }
230:
231: /**
232: * Set the Logger for this component.
233: *
234: * @param logger The new logger
235: */
236: public void setLogger(Logger logger) {
237:
238: Logger oldLogger = this .logger;
239: this .logger = logger;
240: support.firePropertyChange("logger", oldLogger, this .logger);
241:
242: }
243:
244: /**
245: * Return the default Realm for our Containers.
246: */
247: public Realm getRealm() {
248:
249: return (this .realm);
250:
251: }
252:
253: /**
254: * Set the default Realm for our Containers.
255: *
256: * @param realm The new default realm
257: */
258: public void setRealm(Realm realm) {
259:
260: Realm oldRealm = this .realm;
261: this .realm = realm;
262: support.firePropertyChange("realm", oldRealm, this .realm);
263:
264: }
265:
266: /**
267: * Return the secure socket factory class name.
268: */
269: public String getSocketFactory() {
270:
271: return (this .socketFactory);
272:
273: }
274:
275: /**
276: * Set the secure socket factory class name.
277: *
278: * @param socketFactory The new secure socket factory class name
279: */
280: public void setSocketFactory(String socketFactory) {
281:
282: this .socketFactory = socketFactory;
283:
284: }
285:
286: public void setAwait(boolean b) {
287: await = b;
288: }
289:
290: public boolean isAwait() {
291: return await;
292: }
293:
294: public void setCatalinaHome(String s) {
295: System.setProperty("catalina.home", s);
296: }
297:
298: public void setCatalinaBase(String s) {
299: System.setProperty("catalina.base", s);
300: }
301:
302: public String getCatalinaHome() {
303: return System.getProperty("catalina.home");
304: }
305:
306: public String getCatalinaBase() {
307: return System.getProperty("catalina.base");
308: }
309:
310: // --------------------------------------------------------- Public Methods
311:
312: /**
313: * Add a new Connector to the set of defined Connectors. The newly
314: * added Connector will be associated with the most recently added Engine.
315: *
316: * @param connector The connector to be added
317: *
318: * @exception IllegalStateException if no engines have been added yet
319: */
320: public synchronized void addConnector(Connector connector) {
321:
322: if (log.isDebugEnabled()) {
323: log.debug("Adding connector (" + connector.getInfo() + ")");
324: }
325:
326: // Make sure we have a Container to send requests to
327: if (engines.length < 1)
328: throw new IllegalStateException(sm
329: .getString("embedded.noEngines"));
330:
331: /*
332: * Add the connector. This will set the connector's container to the
333: * most recently added Engine
334: */
335: super .addConnector(connector);
336: }
337:
338: /**
339: * Add a new Engine to the set of defined Engines.
340: *
341: * @param engine The engine to be added
342: */
343: public synchronized void addEngine(Engine engine) {
344:
345: if (log.isDebugEnabled())
346: log.debug("Adding engine (" + engine.getInfo() + ")");
347:
348: // Add this Engine to our set of defined Engines
349: Engine results[] = new Engine[engines.length + 1];
350: for (int i = 0; i < engines.length; i++)
351: results[i] = engines[i];
352: results[engines.length] = engine;
353: engines = results;
354:
355: // Start this Engine if necessary
356: if (started && (engine instanceof Lifecycle)) {
357: try {
358: ((Lifecycle) engine).start();
359: } catch (LifecycleException e) {
360: log.error("Engine.start", e);
361: }
362: }
363:
364: this .container = engine;
365: }
366:
367: /**
368: * Create, configure, and return a new TCP/IP socket connector
369: * based on the specified properties.
370: *
371: * @param address InetAddress to bind to, or <code>null</code> if the
372: * connector is supposed to bind to all addresses on this server
373: * @param port Port number to listen to
374: * @param secure true if the generated connector is supposed to be
375: * SSL-enabled, and false otherwise
376: */
377: public Connector createConnector(InetAddress address, int port,
378: boolean secure) {
379: return createConnector(address != null ? address.toString()
380: : null, port, secure);
381: }
382:
383: public Connector createConnector(String address, int port,
384: boolean secure) {
385: String protocol = "http";
386: if (secure) {
387: protocol = "https";
388: }
389:
390: return createConnector(address, port, protocol);
391: }
392:
393: public Connector createConnector(InetAddress address, int port,
394: String protocol) {
395: return createConnector(address != null ? address.toString()
396: : null, port, protocol);
397: }
398:
399: public Connector createConnector(String address, int port,
400: String protocol) {
401:
402: Connector connector = null;
403:
404: if (address != null) {
405: /*
406: * InetAddress.toString() returns a string of the form
407: * "<hostname>/<literal_IP>". Get the latter part, so that the
408: * address can be parsed (back) into an InetAddress using
409: * InetAddress.getByName().
410: */
411: int index = address.indexOf('/');
412: if (index != -1) {
413: address = address.substring(index + 1);
414: }
415: }
416:
417: if (log.isDebugEnabled()) {
418: log.debug("Creating connector for address='"
419: + ((address == null) ? "ALL" : address)
420: + "' port='" + port + "' protocol='" + protocol
421: + "'");
422: }
423:
424: try {
425:
426: Class clazz = Class
427: .forName("org.apache.coyote.tomcat5.CoyoteConnector");
428: connector = (Connector) clazz.newInstance();
429:
430: if (address != null) {
431: IntrospectionUtils.setProperty(connector, "address", ""
432: + address);
433: }
434: IntrospectionUtils
435: .setProperty(connector, "port", "" + port);
436:
437: if (protocol.equals("ajp")) {
438: IntrospectionUtils.setProperty(connector,
439: "protocolHandlerClassName",
440: "org.apache.jk.server.JkCoyoteHandler");
441: } else if (protocol.equals("memory")) {
442: IntrospectionUtils
443: .setProperty(connector,
444: "protocolHandlerClassName",
445: "org.apache.coyote.memory.MemoryProtocolHandler");
446: } else if (protocol.equals("https")) {
447: connector.setScheme("https");
448: connector.setSecure(true);
449: try {
450: Class serverSocketFactoryClass = Class
451: .forName("org.apache.coyote.tomcat5.CoyoteServerSocketFactory");
452: ServerSocketFactory factory = (ServerSocketFactory) serverSocketFactoryClass
453: .newInstance();
454: connector.setFactory(factory);
455: } catch (Exception e) {
456: log
457: .error("Couldn't load SSL server socket factory.");
458: }
459: }
460:
461: } catch (Exception e) {
462: log.error("Couldn't create connector.");
463: }
464:
465: return (connector);
466:
467: }
468:
469: /**
470: * Create, configure, and return a Context that will process all
471: * HTTP requests received from one of the associated Connectors,
472: * and directed to the specified context path on the virtual host
473: * to which this Context is connected.
474: * <p>
475: * After you have customized the properties, listeners, and Valves
476: * for this Context, you must attach it to the corresponding Host
477: * by calling:
478: * <pre>
479: * host.addChild(context);
480: * </pre>
481: * which will also cause the Context to be started if the Host has
482: * already been started.
483: *
484: * @param path Context path of this application ("" for the default
485: * application for this host, must start with a slash otherwise)
486: * @param docBase Absolute pathname to the document base directory
487: * for this web application
488: *
489: * @exception IllegalArgumentException if an invalid parameter
490: * is specified
491: */
492: public Context createContext(String path, String docBase) {
493:
494: if (log.isDebugEnabled())
495: log.debug("Creating context '" + path + "' with docBase '"
496: + docBase + "'");
497:
498: StandardContext context = new StandardContext();
499:
500: context.setDebug(debug);
501: context.setDocBase(docBase);
502: context.setPath(path);
503:
504: ContextConfig config = new ContextConfig();
505: config.setDebug(debug);
506: ((Lifecycle) context).addLifecycleListener(config);
507:
508: return (context);
509:
510: }
511:
512: /**
513: * Create, configure, and return an Engine that will process all
514: * HTTP requests received from one of the associated Connectors,
515: * based on the specified properties.
516: */
517: public Engine createEngine() {
518:
519: if (log.isDebugEnabled())
520: log.debug("Creating engine");
521:
522: StandardEngine engine = new StandardEngine();
523:
524: engine.setDebug(debug);
525: // Default host will be set to the first host added
526: engine.setLogger(logger); // Inherited by all children
527: engine.setRealm(realm); // Inherited by all children
528:
529: return (engine);
530:
531: }
532:
533: /**
534: * Create, configure, and return a Host that will process all
535: * HTTP requests received from one of the associated Connectors,
536: * and directed to the specified virtual host.
537: * <p>
538: * After you have customized the properties, listeners, and Valves
539: * for this Host, you must attach it to the corresponding Engine
540: * by calling:
541: * <pre>
542: * engine.addChild(host);
543: * </pre>
544: * which will also cause the Host to be started if the Engine has
545: * already been started. If this is the default (or only) Host you
546: * will be defining, you may also tell the Engine to pass all requests
547: * not assigned to another virtual host to this one:
548: * <pre>
549: * engine.setDefaultHost(host.getName());
550: * </pre>
551: *
552: * @param name Canonical name of this virtual host
553: * @param appBase Absolute pathname to the application base directory
554: * for this virtual host
555: *
556: * @exception IllegalArgumentException if an invalid parameter
557: * is specified
558: */
559: public Host createHost(String name, String appBase) {
560:
561: if (log.isDebugEnabled())
562: log.debug("Creating host '" + name + "' with appBase '"
563: + appBase + "'");
564:
565: StandardHost host = new StandardHost();
566:
567: host.setAppBase(appBase);
568: host.setDebug(debug);
569: host.setName(name);
570:
571: return (host);
572:
573: }
574:
575: /**
576: * Create and return a class loader manager that can be customized, and
577: * then attached to a Context, before it is started.
578: *
579: * @param parent ClassLoader that will be the parent of the one
580: * created by this Loader
581: */
582: public Loader createLoader(ClassLoader parent) {
583:
584: if (log.isDebugEnabled())
585: log.debug("Creating Loader with parent class loader '"
586: + parent + "'");
587:
588: WebappLoader loader = new WebappLoader(parent);
589: return (loader);
590:
591: }
592:
593: /**
594: * Return descriptive information about this Server implementation and
595: * the corresponding version number, in the format
596: * <code><description>/<version></code>.
597: */
598: public String getInfo() {
599:
600: return (info);
601:
602: }
603:
604: /**
605: * Remove the specified Context from the set of defined Contexts for its
606: * associated Host. If this is the last Context for this Host, the Host
607: * will also be removed.
608: *
609: * @param context The Context to be removed
610: */
611: public synchronized void removeContext(Context context) {
612:
613: if (log.isDebugEnabled())
614: log.debug("Removing context[" + context.getPath() + "]");
615:
616: // Is this Context actually among those that are defined?
617: boolean found = false;
618: for (int i = 0; i < engines.length; i++) {
619: Container hosts[] = engines[i].findChildren();
620: for (int j = 0; j < hosts.length; j++) {
621: Container contexts[] = hosts[j].findChildren();
622: for (int k = 0; k < contexts.length; k++) {
623: if (context == (Context) contexts[k]) {
624: found = true;
625: break;
626: }
627: }
628: if (found)
629: break;
630: }
631: if (found)
632: break;
633: }
634: if (!found)
635: return;
636:
637: // Remove this Context from the associated Host
638: if (log.isDebugEnabled())
639: log.debug(" Removing this Context");
640: context.getParent().removeChild(context);
641:
642: }
643:
644: /**
645: * Remove the specified Engine from the set of defined Engines, along with
646: * all of its related Hosts and Contexts. All associated Connectors are
647: * also removed.
648: *
649: * @param engine The Engine to be removed
650: */
651: public synchronized void removeEngine(Engine engine) {
652:
653: if (log.isDebugEnabled())
654: log.debug("Removing engine (" + engine.getInfo() + ")");
655:
656: // Is the specified Engine actually defined?
657: int j = -1;
658: for (int i = 0; i < engines.length; i++) {
659: if (engine == engines[i]) {
660: j = i;
661: break;
662: }
663: }
664: if (j < 0)
665: return;
666:
667: // Remove any Connector that is using this Engine
668: if (log.isDebugEnabled())
669: log.debug(" Removing related Containers");
670: while (true) {
671: int n = -1;
672: for (int i = 0; i < connectors.length; i++) {
673: if (connectors[i].getContainer() == (Container) engine) {
674: n = i;
675: break;
676: }
677: }
678: if (n < 0)
679: break;
680: removeConnector(connectors[n]);
681: }
682:
683: // Stop this Engine if necessary
684: if (engine instanceof Lifecycle) {
685: if (log.isDebugEnabled())
686: log.debug(" Stopping this Engine");
687: try {
688: ((Lifecycle) engine).stop();
689: } catch (LifecycleException e) {
690: log.error("Engine.stop", e);
691: }
692: }
693:
694: // Remove this Engine from our set of defined Engines
695: if (log.isDebugEnabled())
696: log.debug(" Removing this Engine");
697: int k = 0;
698: Engine results[] = new Engine[engines.length - 1];
699: for (int i = 0; i < engines.length; i++) {
700: if (i != j)
701: results[k++] = engines[i];
702: }
703: engines = results;
704:
705: }
706:
707: /**
708: * Remove the specified Host, along with all of its related Contexts,
709: * from the set of defined Hosts for its associated Engine. If this is
710: * the last Host for this Engine, the Engine will also be removed.
711: *
712: * @param host The Host to be removed
713: */
714: public synchronized void removeHost(Host host) {
715:
716: if (log.isDebugEnabled())
717: log.debug("Removing host[" + host.getName() + "]");
718:
719: // Is this Host actually among those that are defined?
720: boolean found = false;
721: for (int i = 0; i < engines.length; i++) {
722: Container hosts[] = engines[i].findChildren();
723: for (int j = 0; j < hosts.length; j++) {
724: if (host == (Host) hosts[j]) {
725: found = true;
726: break;
727:
728: }
729: }
730: if (found)
731: break;
732: }
733: if (!found)
734: return;
735:
736: // Remove this Host from the associated Engine
737: if (log.isDebugEnabled())
738: log.debug(" Removing this Host");
739: host.getParent().removeChild(host);
740:
741: }
742:
743: // ------------------------------------------------------ Lifecycle Methods
744:
745: /**
746: * Add a lifecycle event listener to this component.
747: *
748: * @param listener The listener to add
749: */
750: public void addLifecycleListener(LifecycleListener listener) {
751:
752: lifecycle.addLifecycleListener(listener);
753:
754: }
755:
756: /**
757: * Get the lifecycle listeners associated with this lifecycle. If this
758: * Lifecycle has no listeners registered, a zero-length array is returned.
759: */
760: public LifecycleListener[] findLifecycleListeners() {
761:
762: return lifecycle.findLifecycleListeners();
763:
764: }
765:
766: /**
767: * Remove a lifecycle event listener from this component.
768: *
769: * @param listener The listener to remove
770: */
771: public void removeLifecycleListener(LifecycleListener listener) {
772:
773: lifecycle.removeLifecycleListener(listener);
774:
775: }
776:
777: /**
778: * Prepare for the beginning of active use of the public methods of this
779: * component. This method should be called after <code>configure()</code>,
780: * and before any of the public methods of the component are utilized.
781: *
782: * @exception LifecycleException if this component detects a fatal error
783: * that prevents this component from being used
784: */
785: public void start() throws LifecycleException {
786:
787: if (log.isInfoEnabled())
788: log.info("Starting tomcat server");
789:
790: // Validate the setup of our required system properties
791: initDirs();
792:
793: // Initialize some naming specific properties
794: initNaming();
795:
796: // Validate and update our current component state
797: if (started)
798: throw new LifecycleException(sm
799: .getString("embedded.alreadyStarted"));
800: lifecycle.fireLifecycleEvent(START_EVENT, null);
801: started = true;
802: initialized = true;
803:
804: // Start our defined Engines first
805: for (int i = 0; i < engines.length; i++) {
806: if (engines[i] instanceof Lifecycle)
807: ((Lifecycle) engines[i]).start();
808: }
809:
810: // Start our defined Connectors second
811: for (int i = 0; i < connectors.length; i++) {
812: connectors[i].initialize();
813: if (connectors[i] instanceof Lifecycle)
814: ((Lifecycle) connectors[i]).start();
815: }
816:
817: }
818:
819: /**
820: * Gracefully terminate the active use of the public methods of this
821: * component. This method should be the last one called on a given
822: * instance of this component.
823: *
824: * @exception LifecycleException if this component detects a fatal error
825: * that needs to be reported
826: */
827: public void stop() throws LifecycleException {
828:
829: if (log.isDebugEnabled())
830: log.debug("Stopping embedded server");
831:
832: // Validate and update our current component state
833: if (!started)
834: throw new LifecycleException(sm
835: .getString("embedded.notStarted"));
836: lifecycle.fireLifecycleEvent(STOP_EVENT, null);
837: started = false;
838:
839: // Stop our defined Connectors first
840: for (int i = 0; i < connectors.length; i++) {
841: if (connectors[i] instanceof Lifecycle)
842: ((Lifecycle) connectors[i]).stop();
843: }
844:
845: // Stop our defined Engines second
846: for (int i = 0; i < engines.length; i++) {
847: if (engines[i] instanceof Lifecycle)
848: ((Lifecycle) engines[i]).stop();
849: }
850:
851: }
852:
853: // ------------------------------------------------------ Protected Methods
854:
855: /** Initialize naming - this should only enable java:env and root naming.
856: * If tomcat is embeded in an application that already defines those -
857: * it shouldn't do it.
858: *
859: * XXX The 2 should be separated, you may want to enable java: but not
860: * the initial context and the reverse
861: * XXX Can we "guess" - i.e. lookup java: and if something is returned assume
862: * false ?
863: * XXX We have a major problem with the current setting for java: url
864: */
865: protected void initNaming() {
866: // Setting additional variables
867: if (!useNaming) {
868: log.info("Catalina naming disabled");
869: System.setProperty("catalina.useNaming", "false");
870: } else {
871: System.setProperty("catalina.useNaming", "true");
872: String value = "org.apache.naming";
873: String oldValue = System
874: .getProperty(javax.naming.Context.URL_PKG_PREFIXES);
875: if (oldValue != null) {
876: value = value + ":" + oldValue;
877: }
878: System.setProperty(javax.naming.Context.URL_PKG_PREFIXES,
879: value);
880: if (log.isDebugEnabled())
881: log.debug("Setting naming prefix=" + value);
882: value = System
883: .getProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY);
884: if (value == null) {
885: System.setProperty(
886: javax.naming.Context.INITIAL_CONTEXT_FACTORY,
887: "org.apache.naming.java.javaURLContextFactory");
888: } else {
889: log
890: .debug("INITIAL_CONTEXT_FACTORY alread set "
891: + value);
892: }
893: }
894: }
895:
896: protected void initDirs() {
897:
898: String catalinaHome = System.getProperty("catalina.home");
899: if (catalinaHome == null) {
900: // Backwards compatibility patch for J2EE RI 1.3
901: String j2eeHome = System
902: .getProperty("com.sun.enterprise.home");
903: if (j2eeHome != null) {
904: catalinaHome = System
905: .getProperty("com.sun.enterprise.home");
906: } else if (System.getProperty("catalina.base") != null) {
907: catalinaHome = System.getProperty("catalina.base");
908: } else {
909: // Use IntrospectionUtils and guess the dir
910: catalinaHome = IntrospectionUtils.guessInstall(
911: "catalina.home", "catalina.base",
912: "catalina.jar");
913: if (catalinaHome == null) {
914: catalinaHome = IntrospectionUtils.guessInstall(
915: "tomcat.install", "catalina.home",
916: "tomcat.jar");
917: }
918: }
919: }
920: if (catalinaHome != null) {
921: File home = new File(catalinaHome);
922: if (!home.isAbsolute()) {
923: try {
924: catalinaHome = home.getCanonicalPath();
925: } catch (IOException e) {
926: catalinaHome = home.getAbsolutePath();
927: }
928: }
929: System.setProperty("catalina.home", catalinaHome);
930: }
931:
932: if (System.getProperty("catalina.base") == null) {
933: System.setProperty("catalina.base", System
934: .getProperty("catalina.home"));
935: } else {
936: String catalinaBase = System.getProperty("catalina.base");
937: File base = new File(catalinaBase);
938: if (!base.isAbsolute()) {
939: try {
940: catalinaBase = base.getCanonicalPath();
941: } catch (IOException e) {
942: catalinaBase = base.getAbsolutePath();
943: }
944: }
945: System.setProperty("catalina.base", catalinaBase);
946: }
947:
948: }
949:
950: // -------------------------------------------------------- Private Methods
951:
952: /**
953: * Customize the specified context to have its own log file instead of
954: * inheriting the default one. This is just an example of what you can
955: * do; pretty much anything (such as installing special Valves) can
956: * be done prior to calling <code>start()</code>.
957: *
958: * @param context Context to receive a specialized logger
959: */
960: private static void customize(Context context) {
961:
962: // Create a customized file logger for this context
963: String basename = context.getPath();
964: if (basename.length() < 1)
965: basename = "ROOT";
966: else
967: basename = basename.substring(1);
968:
969: FileLogger special = new FileLogger();
970: special.setPrefix(basename + "_log.");
971: special.setSuffix(".txt");
972: special.setTimestamp(true);
973:
974: // Override the default logger for this context
975: context.setLogger(special);
976:
977: }
978:
979: /**
980: * Set the security package access/protection.
981: */
982: protected void setSecurityProtection() {
983: SecurityConfig securityConfig = SecurityConfig.newInstance();
984: securityConfig.setPackageDefinition();
985: securityConfig.setPackageAccess();
986: }
987:
988: }
|