Java tutorial
/* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.catalina.core; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.catalina.Connector; import org.apache.catalina.Container; import org.apache.catalina.Engine; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleException; import org.apache.catalina.LifecycleListener; import org.apache.catalina.Server; import org.apache.catalina.Service; import org.apache.catalina.ServerFactory; import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.StringManager; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.modeler.Registry; /** * Standard implementation of the <code>Service</code> interface. The * associated Container is generally an instance of Engine, but this is * not required. * * @author Craig R. McClanahan */ public class StandardService implements Lifecycle, Service, MBeanRegistration { private static Log log = LogFactory.getLog(StandardService.class); // ----------------------------------------------------- Instance Variables /** * The set of Connectors associated with this Service. */ private Connector connectors[] = new Connector[0]; /** * The Container associated with this Service. */ private Container container = null; /** * The debugging detail level for this component. */ private int debug = 0; /** * Descriptive information about this component implementation. */ private static final String info = "org.apache.catalina.core.StandardService/1.0"; /** * Has this component been initialized? */ private boolean initialized = false; /** * The name of this service. */ private String name = null; /** * The lifecycle event support for this component. */ private LifecycleSupport lifecycle = new LifecycleSupport(this); /** * The string manager for this package. */ private static final StringManager sm = StringManager.getManager(Constants.Package); /** * The <code>Server</code> that owns this Service, if any. */ private Server server = null; /** * Has this component been started? */ private boolean started = false; /** * The property change support for this component. */ protected PropertyChangeSupport support = new PropertyChangeSupport(this); // ------------------------------------------------------------- Properties /** * Return the <code>Container</code> that handles requests for all * <code>Connectors</code> associated with this Service. */ public Container getContainer() { return (this.container); } /** * Set the <code>Container</code> that handles requests for all * <code>Connectors</code> associated with this Service. * * @param container The new Container */ public void setContainer(Container container) { Container oldContainer = this.container; if ((oldContainer != null) && (oldContainer instanceof Engine)) ((Engine) oldContainer).setService(null); this.container = container; if ((this.container != null) && (this.container instanceof Engine)) ((Engine) this.container).setService(this); if (started && (this.container != null) && (this.container instanceof Lifecycle)) { try { ((Lifecycle) this.container).start(); } catch (LifecycleException e) { ; } } synchronized (connectors) { for (int i = 0; i < connectors.length; i++) connectors[i].setContainer(this.container); } if (started && (oldContainer != null) && (oldContainer instanceof Lifecycle)) { try { ((Lifecycle) oldContainer).stop(); } catch (LifecycleException e) { ; } } // Report this property change to interested listeners support.firePropertyChange("container", oldContainer, this.container); } public ObjectName getContainerName() { if (container instanceof ContainerBase) { return ((ContainerBase) container).getJmxName(); } return null; } /** * Return the debugging detail level of this component. */ public int getDebug() { return (this.debug); } /** * Set the debugging detail level of this component. * * @param debug The new debugging detail level */ public void setDebug(int debug) { this.debug = debug; } /** * Return descriptive information about this Service implementation and * the corresponding version number, in the format * <code><description>/<version></code>. */ public String getInfo() { return (this.info); } /** * Return the name of this Service. */ public String getName() { return (this.name); } /** * Set the name of this Service. * * @param name The new service name */ public void setName(String name) { this.name = name; } /** * Return the <code>Server</code> with which we are associated (if any). */ public Server getServer() { return (this.server); } /** * Set the <code>Server</code> with which we are associated (if any). * * @param server The server that owns this Service */ public void setServer(Server server) { this.server = server; } // --------------------------------------------------------- Public Methods /** * Add a new Connector to the set of defined Connectors, and associate it * with this Service's Container. * * @param connector The Connector to be added */ public void addConnector(Connector connector) { synchronized (connectors) { connector.setContainer(this.container); connector.setService(this); Connector results[] = new Connector[connectors.length + 1]; System.arraycopy(connectors, 0, results, 0, connectors.length); results[connectors.length] = connector; connectors = results; if (initialized) { try { connector.initialize(); } catch (LifecycleException e) { e.printStackTrace(System.err); } } if (started && (connector instanceof Lifecycle)) { try { ((Lifecycle) connector).start(); } catch (LifecycleException e) { ; } } // Report this property change to interested listeners support.firePropertyChange("connector", null, connector); } } public ObjectName[] getConnectorNames() { ObjectName results[] = new ObjectName[connectors.length]; for (int i = 0; i < results.length; i++) { // if it's a coyote connector //if( connectors[i] instanceof CoyoteConnector ) { // results[i]=((CoyoteConnector)connectors[i]).getJmxName(); //} } return results; } /** * Add a property change listener to this component. * * @param listener The listener to add */ public void addPropertyChangeListener(PropertyChangeListener listener) { support.addPropertyChangeListener(listener); } /** * Find and return the set of Connectors associated with this Service. */ public Connector[] findConnectors() { return (connectors); } /** * Remove the specified Connector from the set associated from this * Service. The removed Connector will also be disassociated from our * Container. * * @param connector The Connector to be removed */ public void removeConnector(Connector connector) { synchronized (connectors) { int j = -1; for (int i = 0; i < connectors.length; i++) { if (connector == connectors[i]) { j = i; break; } } if (j < 0) return; if (started && (connectors[j] instanceof Lifecycle)) { try { ((Lifecycle) connectors[j]).stop(); } catch (LifecycleException e) { ; } } connectors[j].setContainer(null); connector.setService(null); int k = 0; Connector results[] = new Connector[connectors.length - 1]; for (int i = 0; i < connectors.length; i++) { if (i != j) results[k++] = connectors[i]; } connectors = results; // Report this property change to interested listeners support.firePropertyChange("connector", connector, null); } } /** * Remove a property change listener from this component. * * @param listener The listener to remove */ public void removePropertyChangeListener(PropertyChangeListener listener) { support.removePropertyChangeListener(listener); } /** * Return a String representation of this component. */ public String toString() { StringBuffer sb = new StringBuffer("StandardService["); sb.append(getName()); sb.append("]"); return (sb.toString()); } // ------------------------------------------------------ Lifecycle Methods /** * Add a LifecycleEvent listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } /** * Get the lifecycle listeners associated with this lifecycle. If this * Lifecycle has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners() { return lifecycle.findLifecycleListeners(); } /** * Remove a LifecycleEvent listener from this component. * * @param listener The listener to remove */ public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } /** * Prepare for the beginning of active use of the public methods of this * component. This method should be called before any of the public * methods of this component are utilized. It should also send a * LifecycleEvent of type START_EVENT to any registered listeners. * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ public void start() throws LifecycleException { // Validate and update our current component state if (started) { log.info(sm.getString("standardService.start.started")); } if (!initialized) init(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); log.info(sm.getString("standardService.start.name", this.name)); lifecycle.fireLifecycleEvent(START_EVENT, null); started = true; // Start our defined Container first if (container != null) { synchronized (container) { if (container instanceof Lifecycle) { ((Lifecycle) container).start(); } } } // Start our defined Connectors second synchronized (connectors) { for (int i = 0; i < connectors.length; i++) { if (connectors[i] instanceof Lifecycle) ((Lifecycle) connectors[i]).start(); } } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); } /** * Gracefully terminate the active use of the public methods of this * component. This method should be the last one called on a given * instance of this component. It should also send a LifecycleEvent * of type STOP_EVENT to any registered listeners. * * @exception LifecycleException if this component detects a fatal error * that needs to be reported */ public void stop() throws LifecycleException { // Validate and update our current component state if (!started) { return; } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null); lifecycle.fireLifecycleEvent(STOP_EVENT, null); log.info(sm.getString("standardService.stop.name", this.name)); started = false; // Stop our defined Connectors first synchronized (connectors) { for (int i = 0; i < connectors.length; i++) { if (connectors[i] instanceof Lifecycle) ((Lifecycle) connectors[i]).stop(); } } // Stop our defined Container second if (container != null) { synchronized (container) { if (container instanceof Lifecycle) { ((Lifecycle) container).stop(); } } } if (oname == controller) { // we registered ourself on init(). // That should be the typical case - this object is just for // backward compat, nobody should bother to load it explicitely Registry.getRegistry().unregisterComponent(oname); } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null); } /** * Invoke a pre-startup initialization. This is used to allow connectors * to bind to restricted ports under Unix operating environments. */ public void initialize() throws LifecycleException { // Service shouldn't be used with embeded, so it doesn't matter if (initialized) { log.info(sm.getString("standardService.initialize.initialized")); return; } initialized = true; if (oname == null) { try { // Hack - Server should be deprecated... Container engine = this.getContainer(); domain = engine.getName(); oname = new ObjectName(domain + ":type=Service,serviceName=" + name); this.controller = oname; Registry.getRegistry().registerComponent(this, oname, null); } catch (Exception e) { log.error("Error registering ", e); } } if (server == null) { // Register with the server // HACK: ServerFactory should be removed... ServerFactory.getServer().addService(this); } // Initialize our defined Connectors synchronized (connectors) { for (int i = 0; i < connectors.length; i++) { connectors[i].initialize(); } } } public void destroy() throws LifecycleException { if (started) stop(); // unregister should be here probably } public void init() { try { initialize(); } catch (Throwable t) { t.printStackTrace(); } } protected String type; protected String domain; protected String suffix; protected ObjectName oname; protected ObjectName controller; protected MBeanServer mserver; public ObjectName getObjectName() { return oname; } public String getDomain() { return domain; } public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { oname = name; mserver = server; domain = name.getDomain(); return name; } public void postRegister(Boolean registrationDone) { } public void preDeregister() throws Exception { } public void postDeregister() { } }