alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  
* <td align=center>Container * <td>Child container added to this Container. * </tr> * <tr> * <td align=center>addValve * <td align=center>Valve * <td>Valve added to this Container. * </tr> * <tr> * <td align=center>removeChild * <td align=center>Container * <td>Child container removed from this Container. * </tr> * <tr> * <td align=center>removeValve * <td align=center>Valve * <td>Valve removed from this Container. * </tr> * <tr> * <td align=center>start * <td align=center>null * <td>Container was started. * </tr> * <tr> * <td align=center>stop * <td align=center>null * <td>Container was stopped. * </tr> * </table> * Subclasses that fire additional events should document them in the * class comments of the implementation class. * * @author Craig R. McClanahan */ public abstract class ContainerBase implements Container, Lifecycle, Pipeline, MBeanRegistration, Serializable { private static org.apache.juli.logging.Log log= org.apache.juli.logging.LogFactory.getLog( ContainerBase.class ); /** * Perform addChild with the permissions of this class. * addChild can be called with the XML parser on the stack, * this allows the XML parser to have fewer privileges than * Tomcat. */ protected class PrivilegedAddChild implements PrivilegedAction { private Container child; PrivilegedAddChild(Container child) { this.child = child; } public Object run() { addChildInternal(child); return null; } } // ----------------------------------------------------- Instance Variables /** * The child Containers belonging to this Container, keyed by name. */ protected HashMap children = new HashMap(); /** * The processor delay for this component. */ protected int backgroundProcessorDelay = -1; /** * The lifecycle event support for this component. */ protected LifecycleSupport lifecycle = new LifecycleSupport(this); /** * The container event listeners for this Container. */ protected ArrayList listeners = new ArrayList(); /** * The Loader implementation with which this Container is associated. */ protected Loader loader = null; /** * The Logger implementation with which this Container is associated. */ protected Log logger = null; /** * Associated logger name. */ protected String logName = null; /** * The Manager implementation with which this Container is associated. */ protected Manager manager = null; /** * The cluster with which this Container is associated. */ protected Cluster cluster = null; /** * The human-readable name of this Container. */ protected String name = null; /** * The parent Container to which this Container is a child. */ protected Container parent = null; /** * The parent class loader to be configured when we install a Loader. */ protected ClassLoader parentClassLoader = null; /** * The Pipeline object with which this Container is associated. */ protected Pipeline pipeline = new StandardPipeline(this); /** * The Realm with which this Container is associated. */ protected Realm realm = null; /** * The resources DirContext object with which this Container is associated. */ protected DirContext resources = null; /** * The string manager for this package. */ protected static StringManager sm = StringManager.getManager(Constants.Package); /** * Has this component been started? */ protected boolean started = false; protected boolean initialized=false; /** * Will children be started automatically when they are added. */ protected boolean startChildren = true; /** * The property change support for this component. */ protected PropertyChangeSupport support = new PropertyChangeSupport(this); /** * The background thread. */ private Thread thread = null; /** * The background thread completion semaphore. */ private boolean threadDone = false; // ------------------------------------------------------------- Properties /** * Get the delay between the invocation of the backgroundProcess method on * this container and its children. Child containers will not be invoked * if their delay value is not negative (which would mean they are using * their own thread). Setting this to a positive value will cause * a thread to be spawn. After waiting the specified amount of time, * the thread will invoke the executePeriodic method on this container * and all its children. */ public int getBackgroundProcessorDelay() { return backgroundProcessorDelay; } /** * Set the delay between the invocation of the execute method on this * container and its children. * * @param delay The delay in seconds between the invocation of * backgroundProcess methods */ public void setBackgroundProcessorDelay(int delay) { backgroundProcessorDelay = delay; } /** * Return descriptive information about this Container implementation and * the corresponding version number, in the format * <code><description>/<version>. */ public String getInfo() { return this.getClass().getName(); } /** * Return the Loader with which this Container is associated. If there is * no associated Loader, return the Loader associated with our parent * Container (if any); otherwise, return <code>null. */ public Loader getLoader() { if (loader != null) return (loader); if (parent != null) return (parent.getLoader()); return (null); } /** * Set the Loader with which this Container is associated. * * @param loader The newly associated loader */ public synchronized void setLoader(Loader loader) { // Change components if necessary Loader oldLoader = this.loader; if (oldLoader == loader) return; this.loader = loader; // Stop the old component if necessary if (started && (oldLoader != null) && (oldLoader instanceof Lifecycle)) { try { ((Lifecycle) oldLoader).stop(); } catch (LifecycleException e) { log.error("ContainerBase.setLoader: stop: ", e); } } // Start the new component if necessary if (loader != null) loader.setContainer(this); if (started && (loader != null) && (loader instanceof Lifecycle)) { try { ((Lifecycle) loader).start(); } catch (LifecycleException e) { log.error("ContainerBase.setLoader: start: ", e); } } // Report this property change to interested listeners support.firePropertyChange("loader", oldLoader, this.loader); } /** * Return the Logger with which this Container is associated. If there is * no associated Logger, return the Logger associated with our parent * Container (if any); otherwise return <code>null. */ public Log getLogger() { if (logger != null) return (logger); logger = LogFactory.getLog(logName()); return (logger); } /** * Return the Manager with which this Container is associated. If there is * no associated Manager, return the Manager associated with our parent * Container (if any); otherwise return <code>null. */ public Manager getManager() { if (manager != null) return (manager); if (parent != null) return (parent.getManager()); return (null); } /** * Set the Manager with which this Container is associated. * * @param manager The newly associated Manager */ public synchronized void setManager(Manager manager) { // Change components if necessary Manager oldManager = this.manager; if (oldManager == manager) return; this.manager = manager; // Stop the old component if necessary if (started && (oldManager != null) && (oldManager instanceof Lifecycle)) { try { ((Lifecycle) oldManager).stop(); } catch (LifecycleException e) { log.error("ContainerBase.setManager: stop: ", e); } } // Start the new component if necessary if (manager != null) manager.setContainer(this); if (started && (manager != null) && (manager instanceof Lifecycle)) { try { ((Lifecycle) manager).start(); } catch (LifecycleException e) { log.error("ContainerBase.setManager: start: ", e); } } // Report this property change to interested listeners support.firePropertyChange("manager", oldManager, this.manager); } /** * Return an object which may be utilized for mapping to this component. */ public Object getMappingObject() { return this; } /** * Return the Cluster with which this Container is associated. If there is * no associated Cluster, return the Cluster associated with our parent * Container (if any); otherwise return <code>null. */ public Cluster getCluster() { if (cluster != null) return (cluster); if (parent != null) return (parent.getCluster()); return (null); } /** * Set the Cluster with which this Container is associated. * * @param cluster The newly associated Cluster */ public synchronized void setCluster(Cluster cluster) { // Change components if necessary Cluster oldCluster = this.cluster; if (oldCluster == cluster) return; this.cluster = cluster; // Stop the old component if necessary if (started && (oldCluster != null) && (oldCluster instanceof Lifecycle)) { try { ((Lifecycle) oldCluster).stop(); } catch (LifecycleException e) { log.error("ContainerBase.setCluster: stop: ", e); } } // Start the new component if necessary if (cluster != null) cluster.setContainer(this); if (started && (cluster != null) && (cluster instanceof Lifecycle)) { try { ((Lifecycle) cluster).start(); } catch (LifecycleException e) { log.error("ContainerBase.setCluster: start: ", e); } } // Report this property change to interested listeners support.firePropertyChange("cluster", oldCluster, this.cluster); } /** * Return a name string (suitable for use by humans) that describes this * Container. Within the set of child containers belonging to a particular * parent, Container names must be unique. */ public String getName() { return (name); } /** * Set a name string (suitable for use by humans) that describes this * Container. Within the set of child containers belonging to a particular * parent, Container names must be unique. * * @param name New name of this container * * @exception IllegalStateException if this Container has already been * added to the children of a parent Container (after which the name * may not be changed) */ public void setName(String name) { String oldName = this.name; this.name = name; support.firePropertyChange("name", oldName, this.name); } /** * Return if children of this container will be started automatically when * they are added to this container. */ public boolean getStartChildren() { return (startChildren); } /** * Set if children of this container will be started automatically when * they are added to this container. * * @param startChildren New value of the startChildren flag */ public void setStartChildren(boolean startChildren) { boolean oldStartChildren = this.startChildren; this.startChildren = startChildren; support.firePropertyChange("startChildren", oldStartChildren, this.startChildren); } /** * Return the Container for which this Container is a child, if there is * one. If there is no defined parent, return <code>null. */ public Container getParent() { return (parent); } /** * Set the parent Container to which this Container is being added as a * child. This Container may refuse to become attached to the specified * Container by throwing an exception. * * @param container Container to which this Container is being added * as a child * * @exception IllegalArgumentException if this Container refuses to become * attached to the specified Container */ public void setParent(Container container) { Container oldParent = this.parent; this.parent = container; support.firePropertyChange("parent", oldParent, this.parent); } /** * Return the parent class loader (if any) for this web application. * This call is meaningful only <strong>after a Loader has * been configured. */ public ClassLoader getParentClassLoader() { if (parentClassLoader != null) return (parentClassLoader); if (parent != null) { return (parent.getParentClassLoader()); } return (ClassLoader.getSystemClassLoader()); } /** * Set the parent class loader (if any) for this web application. * This call is meaningful only <strong>before a Loader has * been configured, and the specified value (if non-null) should be * passed as an argument to the class loader constructor. * * * @param parent The new parent class loader */ public void setParentClassLoader(ClassLoader parent) { ClassLoader oldParentClassLoader = this.parentClassLoader; this.parentClassLoader = parent; support.firePropertyChange("parentClassLoader", oldParentClassLoader, this.parentClassLoader); } /** * Return the Pipeline object that manages the Valves associated with * this Container. */ public Pipeline getPipeline() { return (this.pipeline); } /** * Return the Realm with which this Container is associated. If there is * no associated Realm, return the Realm associated with our parent * Container (if any); otherwise return <code>null. */ public Realm getRealm() { if (realm != null) return (realm); if (parent != null) return (parent.getRealm()); return (null); } /** * Set the Realm with which this Container is associated. * * @param realm The newly associated Realm */ public synchronized void setRealm(Realm realm) { // Change components if necessary Realm oldRealm = this.realm; if (oldRealm == realm) return; this.realm = realm; // Stop the old component if necessary if (started && (oldRealm != null) && (oldRealm instanceof Lifecycle)) { try { ((Lifecycle) oldRealm).stop(); } catch (LifecycleException e) { log.error("ContainerBase.setRealm: stop: ", e); } } // Start the new component if necessary if (realm != null) realm.setContainer(this); if (started && (realm != null) && (realm instanceof Lifecycle)) { try { ((Lifecycle) realm).start(); } catch (LifecycleException e) { log.error("ContainerBase.setRealm: start: ", e); } } // Report this property change to interested listeners support.firePropertyChange("realm", oldRealm, this.realm); } /** * Return the resources DirContext object with which this Container is * associated. If there is no associated resources object, return the * resources associated with our parent Container (if any); otherwise * return <code>null. */ public DirContext getResources() { if (resources != null) return (resources); if (parent != null) return (parent.getResources()); return (null); } /** * Set the resources DirContext object with which this Container is * associated. * * @param resources The newly associated DirContext */ public synchronized void setResources(DirContext resources) { // Called from StandardContext.setResources() // <- StandardContext.start() // <- ContainerBase.addChildInternal() // Change components if necessary DirContext oldResources = this.resources; if (oldResources == resources) return; Hashtable env = new Hashtable(); if (getParent() != null) env.put(ProxyDirContext.HOST, getParent().getName()); env.put(ProxyDirContext.CONTEXT, getName()); this.resources = new ProxyDirContext(env, resources); // Report this property change to interested listeners support.firePropertyChange("resources", oldResources, this.resources); } // ------------------------------------------------------ Container Methods /** * Add a new child Container to those associated with this Container, * if supported. Prior to adding this Container to the set of children, * the child's <code>setParent() method must be called, with this * Container as an argument. This method may thrown an * <code>IllegalArgumentException if this Container chooses not * to be attached to the specified Container, in which case it is not added * * @param child New child Container to be added * * @exception IllegalArgumentException if this exception is thrown by * the <code>setParent() method of the child Container * @exception IllegalArgumentException if the new child does not have * a name unique from that of existing children of this Container * @exception IllegalStateException if this Container does not support * child Containers */ public void addChild(Container child) { if (Globals.IS_SECURITY_ENABLED) { PrivilegedAction dp = new PrivilegedAddChild(child); AccessController.doPrivileged(dp); } else { addChildInternal(child); } } private void addChildInternal(Container child) { if( log.isDebugEnabled() ) log.debug("Add child " + child + " " + this); synchronized(children) { if (children.get(child.getName()) != null) throw new IllegalArgumentException("addChild: Child name '" + child.getName() + "' is not unique"); child.setParent(this); // May throw IAE children.put(child.getName(), child); // Start child if (started && startChildren && (child instanceof Lifecycle)) { boolean success = false; try { ((Lifecycle) child).start(); success = true; } catch (LifecycleException e) { log.error("ContainerBase.addChild: start: ", e); throw new IllegalStateException ("ContainerBase.addChild: start: " + e); } finally { if (!success) { children.remove(child.getName()); } } } fireContainerEvent(ADD_CHILD_EVENT, child); } } /** * Add a container event listener to this component. * * @param listener The listener to add */ public void addContainerListener(ContainerListener listener) { synchronized (listeners) { listeners.add(listener); } } /** * Add a property change listener to this component. * * @param listener The listener to add */ public void addPropertyChangeListener(PropertyChangeListener listener) { support.addPropertyChangeListener(listener); } /** * Return the child Container, associated with this Container, with * the specified name (if any); otherwise, return <code>null * * @param name Name of the child Container to be retrieved */ public Container findChild(String name) { if (name == null) return (null); synchronized (children) { // Required by post-start changes return ((Container) children.get(name)); } } /** * Return the set of children Containers associated with this Container. * If this Container has no children, a zero-length array is returned. */ public Container[] findChildren() { synchronized (children) { Container results[] = new Container[children.size()]; return ((Container[]) children.values().toArray(results)); } } /** * Return the set of container listeners associated with this Container. * If this Container has no registered container listeners, a zero-length * array is returned. */ public ContainerListener[] findContainerListeners() { synchronized (listeners) { ContainerListener[] results = new ContainerListener[listeners.size()]; return ((ContainerListener[]) listeners.toArray(results)); } } /** * Process the specified Request, to produce the corresponding Response, * by invoking the first Valve in our pipeline (if any), or the basic * Valve otherwise. * * @param request Request to be processed * @param response Response to be produced * * @exception IllegalStateException if neither a pipeline or a basic * Valve have been configured for this Container * @exception IOException if an input/output error occurred while * processing * @exception ServletException if a ServletException was thrown * while processing this request */ public void invoke(Request request, Response response) throws IOException, ServletException { pipeline.getFirst().invoke(request, response); } /** * Remove an existing child Container from association with this parent * Container. * * @param child Existing child Container to be removed */ public void removeChild(Container child) { synchronized(children) { if (children.get(child.getName()) == null) return; children.remove(child.getName()); } if (started && (child instanceof Lifecycle)) { try { if( child instanceof ContainerBase ) { if( ((ContainerBase)child).started ) { ((Lifecycle) child).stop(); } } else { ((Lifecycle) child).stop(); } } catch (LifecycleException e) { log.error("ContainerBase.removeChild: stop: ", e); } } fireContainerEvent(REMOVE_CHILD_EVENT, child); // child.setParent(null); } /** * Remove a container event listener from this component. * * @param listener The listener to remove */ public void removeContainerListener(ContainerListener listener) { synchronized (listeners) { listeners.remove(listener); } } /** * Remove a property change listener from this component. * * @param listener The listener to remove */ public void removePropertyChangeListener(PropertyChangeListener listener) { support.removePropertyChangeListener(listener); } // ------------------------------------------------------ Lifecycle Methods /** * Add a lifecycle event 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 lifecycle event listener from this component. * * @param listener The listener to remove */ public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } /** * Prepare for active use of the public methods of this Component. * * @exception LifecycleException if this component detects a fatal error * that prevents it from being started */ public synchronized void start() throws LifecycleException { // Validate and update our current component state if (started) { if(log.isInfoEnabled()) log.info(sm.getString("containerBase.alreadyStarted", logName())); return; } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); started = true; // Start our subordinate components, if any if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); logger = null; getLogger(); if ((logger != null) && (logger instanceof Lifecycle)) ((Lifecycle) logger).start(); if ((manager != null) && (manager instanceof Lifecycle)) ((Lifecycle) manager).start(); if ((cluster != null) && (cluster instanceof Lifecycle)) ((Lifecycle) cluster).start(); if ((realm != null) && (realm instanceof Lifecycle)) ((Lifecycle) realm).start(); if ((resources != null) && (resources instanceof Lifecycle)) ((Lifecycle) resources).start(); // Start our child containers, if any Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } // Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null); // Start our thread threadStart(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null); } /** * Gracefully shut down active use of the public methods of this Component. * * @exception LifecycleException if this component detects a fatal error * that needs to be reported */ public synchronized void stop() throws LifecycleException { // Validate and update our current component state if (!started) { if(log.isInfoEnabled()) log.info(sm.getString("containerBase.notStarted", logName())); return; } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null); // Stop our thread threadStop(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(STOP_EVENT, null); started = false; // Stop the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) { ((Lifecycle) pipeline).stop(); } // Stop our child containers, if any Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).stop(); } // Remove children - so next start can work children = findChildren(); for (int i = 0; i < children.length; i++) { removeChild(children[i]); } // Stop our subordinate components, if any if ((resources != null) && (resources instanceof Lifecycle)) { ((Lifecycle) resources).stop(); } if ((realm != null) && (realm instanceof Lifecycle)) { ((Lifecycle) realm).stop(); } if ((cluster != null) && (cluster instanceof Lifecycle)) { ((Lifecycle) cluster).stop(); } if ((manager != null) && (manager instanceof Lifecycle)) { ((Lifecycle) manager).stop(); } if ((logger != null) && (logger instanceof Lifecycle)) { ((Lifecycle) logger).stop(); } if ((loader != null) && (loader instanceof Lifecycle)) { ((Lifecycle) loader).stop(); } // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null); } /** Init method, part of the MBean lifecycle. * If the container was added via JMX, it'll register itself with the * parent, using the ObjectName conventions to locate the parent. * * If the container was added directly and it doesn't have an ObjectName, * it'll create a name and register itself with the JMX console. On destroy(), * the object will unregister. * * @throws Exception */ public void init() throws Exception { if( this.getParent() == null ) { // "Life" update ObjectName parentName=getParentName(); //log.info("Register " + parentName ); if( parentName != null && mserver.isRegistered(parentName)) { mserver.invoke(parentName, "addChild", new Object[] { this }, new String[] {"org.apache.catalina.Container"}); } } initialized=true; } public ObjectName getParentName() throws MalformedObjectNameException { return null; } public void destroy() throws Exception { if( started ) { stop(); } initialized=false; // unregister this component if ( oname != null ) { try { if( controller == oname ) { Registry.getRegistry(null, null) .unregisterComponent(oname); if(log.isDebugEnabled()) log.debug("unregistering " + oname); } } catch( Throwable t ) { log.error("Error unregistering ", t ); } } if (parent != null) { parent.removeChild(this); } // Stop our child containers, if any Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { removeChild(children[i]); } } // ------------------------------------------------------- Pipeline Methods /** * Add a new Valve to the end of the pipeline associated with this * Container. Prior to adding the Valve, the Valve's * <code>setContainer method must be called, with this Container * as an argument. The method may throw an * <code>IllegalArgumentException if this Valve chooses not to * be associated with this Container, or <code>IllegalStateException * if it is already associated with a different Container. * * @param valve Valve to be added * * @exception IllegalArgumentException if this Container refused to * accept the specified Valve * @exception IllegalArgumentException if the specifie Valve refuses to be * associated with this Container * @exception IllegalStateException if the specified Valve is already * associated with a different Container */ public synchronized void addValve(Valve valve) { pipeline.addValve(valve); fireContainerEvent(ADD_VALVE_EVENT, valve); } public ObjectName[] getValveObjectNames() { return ((StandardPipeline)pipeline).getValveObjectNames(); } /** * <p>Return the Valve instance that has been distinguished as the basic * Valve for this Pipeline (if any). */ public Valve getBasic() { return (pipeline.getBasic()); } /** * Return the first valve in the pipeline. */ public Valve getFirst() { return (pipeline.getFirst()); } /** * Return the set of Valves in the pipeline associated with this * Container, including the basic Valve (if any). If there are no * such Valves, a zero-length array is returned. */ public Valve[] getValves() { return (pipeline.getValves()); } /** * Remove the specified Valve from the pipeline associated with this * Container, if it is found; otherwise, do nothing. * * @param valve Valve to be removed */ public synchronized void removeValve(Valve valve) { pipeline.removeValve(valve); fireContainerEvent(REMOVE_VALVE_EVENT, valve); } /** * <p>Set the Valve instance that has been distinguished as the basic * Valve for this Pipeline (if any). Prioer to setting the basic Valve, * the Valve's <code>setContainer() will be called, if it * implements <code>Contained, with the owning Container as an * argument. The method may throw an <code>IllegalArgumentException * if this Valve chooses not to be associated with this Container, or * <code>IllegalStateException if it is already associated with * a different Container.</p> * * @param valve Valve to be distinguished as the basic Valve */ public void setBasic(Valve valve) { pipeline.setBasic(valve); } /** * Execute a periodic task, such as reloading, etc. This method will be * invoked inside the classloading context of this container. Unexpected * throwables will be caught and logged. */ public void backgroundProcess() { if (!started) return; if (cluster != null) { try { cluster.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e); } } if (loader != null) { try { loader.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString("containerBase.backgroundProcess.loader", loader), e); } } if (manager != null) { try { manager.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString("containerBase.backgroundProcess.manager", manager), e); } } if (realm != null) { try { realm.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e); } } Valve current = pipeline.getFirst(); while (current != null) { try { current.backgroundProcess(); } catch (Exception e) { log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e); } current = current.getNext(); } lifecycle.fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null); } // ------------------------------------------------------ Protected Methods /** * Notify all container event listeners that a particular event has * occurred for this Container. The default implementation performs * this notification synchronously using the calling thread. * * @param type Event type * @param data Event data */ public void fireContainerEvent(String type, Object data) { if (listeners.size() < 1) return; ContainerEvent event = new ContainerEvent(this, type, data); ContainerListener list[] = new ContainerListener[0]; synchronized (listeners) { list = (ContainerListener[]) listeners.toArray(list); } for (int i = 0; i < list.length; i++) ((ContainerListener) list[i]).containerEvent(event); } /** * Return the abbreviated name of this container for logging messsages */ protected String logName() { if (logName != null) { return logName; } String loggerName = null; Container current = this; while (current != null) { String name = current.getName(); if ((name == null) || (name.equals(""))) { name = "/"; } loggerName = "[" + name + "]" + ((loggerName != null) ? ("." + loggerName) : ""); current = current.getParent(); } logName = ContainerBase.class.getName() + "." + loggerName; return logName; } // -------------------- JMX and Registration -------------------- protected String type; protected String domain; protected String suffix; protected ObjectName oname; protected ObjectName controller; protected transient MBeanServer mserver; public ObjectName getJmxName() { return oname; } public String getObjectName() { if (oname != null) { return oname.toString(); } else return null; } public String getDomain() { if( domain==null ) { Container parent=this; while( parent != null && !( parent instanceof StandardEngine) ) { parent=parent.getParent(); } if( parent instanceof StandardEngine ) { domain=((StandardEngine)parent).getDomain(); } } return domain; } public void setDomain(String domain) { this.domain=domain; } public String getType() { return type; } protected String getJSR77Suffix() { return suffix; } public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { oname=name; mserver=server; if (name == null ){ return null; } domain=name.getDomain(); type=name.getKeyProperty("type"); if( type==null ) { type=name.getKeyProperty("j2eeType"); } String j2eeApp=name.getKeyProperty("J2EEApplication"); String j2eeServer=name.getKeyProperty("J2EEServer"); if( j2eeApp==null ) { j2eeApp="none"; } if( j2eeServer==null ) { j2eeServer="none"; } suffix=",J2EEApplication=" + j2eeApp + ",J2EEServer=" + j2eeServer; return name; } public void postRegister(Boolean registrationDone) { } public void preDeregister() throws Exception { } public void postDeregister() { } public ObjectName[] getChildren() { ObjectName result[]=new ObjectName[children.size()]; Iterator it=children.values().iterator(); int i=0; while( it.hasNext() ) { Object next=it.next(); if( next instanceof ContainerBase ) { result[i++]=((ContainerBase)next).getJmxName(); } } return result; } public ObjectName createObjectName(String domain, ObjectName parent) throws Exception { if( log.isDebugEnabled()) log.debug("Create ObjectName " + domain + " " + parent ); return null; } public String getContainerSuffix() { Container container=this; Container context=null; Container host=null; Container servlet=null; StringBuffer suffix=new StringBuffer(); if( container instanceof StandardHost ) { host=container; } else if( container instanceof StandardContext ) { host=container.getParent(); context=container; } else if( container instanceof StandardWrapper ) { context=container.getParent(); host=context.getParent(); servlet=container; } if( context!=null ) { String path=((StandardContext)context).getPath(); suffix.append(",path=").append((path.equals("")) ? "/" : path); } if( host!=null ) suffix.append(",host=").append( host.getName() ); if( servlet != null ) { String name=container.getName(); suffix.append(",servlet="); suffix.append((name=="") ? "/" : name); } return suffix.toString(); } /** * Start the background thread that will periodically check for * session timeouts. */ protected void threadStart() { if (thread != null) return; if (backgroundProcessorDelay <= 0) return; threadDone = false; String threadName = "ContainerBackgroundProcessor[" + toString() + "]"; thread = new Thread(new ContainerBackgroundProcessor(), threadName); thread.setDaemon(true); thread.start(); } /** * Stop the background thread that is periodically checking for * session timeouts. */ protected void threadStop() { if (thread == null) return; threadDone = true; thread.interrupt(); try { thread.join(); } catch (InterruptedException e) { ; } thread = null; } // -------------------------------------- ContainerExecuteDelay Inner Class /** * Private thread class to invoke the backgroundProcess method * of this container and its children after a fixed delay. */ protected class ContainerBackgroundProcessor implements Runnable { public void run() { while (!threadDone) { try { Thread.sleep(backgroundProcessorDelay * 1000L); } catch (InterruptedException e) { ; } if (!threadDone) { Container parent = (Container) getMappingObject(); ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (parent.getLoader() != null) { cl = parent.getLoader().getClassLoader(); } processChildren(parent, cl); } } } protected void processChildren(Container container, ClassLoader cl) { try { if (container.getLoader() != null) { Thread.currentThread().setContextClassLoader (container.getLoader().getClassLoader()); } container.backgroundProcess(); } catch (Throwable t) { log.error("Exception invoking periodic operation: ", t); } finally { Thread.currentThread().setContextClassLoader(cl); } Container[] children = container.findChildren(); for (int i = 0; i < children.length; i++) { if (children[i].getBackgroundProcessorDelay() <= 0) { processChildren(children[i], cl); } } } } }

Other Tomcat examples (source code examples)

Here is a short list of links related to this Tomcat ContainerBase.java source code file:

Tomcat example source code file (ContainerBase.java)

This example Tomcat source code file (ContainerBase.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Tomcat tags/keywords

bean, classloader, container, container, containerlistener, exception, io, javabean, lifecycle, lifecycle, lifecycleexception, management, object, objectname, objectname, security, string, string, util, valve

The Tomcat ContainerBase.java source code

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.apache.catalina.core;


import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;

import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.naming.directory.DirContext;
import javax.servlet.ServletException;

import org.apache.catalina.Cluster;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerEvent;
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Globals;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.Loader;
import org.apache.catalina.Manager;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Realm;
import org.apache.catalina.Valve;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.util.LifecycleSupport;
import org.apache.catalina.util.StringManager;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.naming.resources.ProxyDirContext;
import org.apache.tomcat.util.modeler.Registry;


/**
 * Abstract implementation of the <b>Container interface, providing common
 * functionality required by nearly every implementation.  Classes extending
 * this base class must implement <code>getInfo(), and may implement
 * a replacement for <code>invoke().
 * <p>
 * All subclasses of this abstract base class will include support for a
 * Pipeline object that defines the processing to be performed for each request
 * received by the <code>invoke() method of this class, utilizing the
 * "Chain of Responsibility" design pattern.  A subclass should encapsulate its
 * own processing functionality as a <code>Valve, and configure this
 * Valve into the pipeline by calling <code>setBasic().
 * <p>
 * This implementation fires property change events, per the JavaBeans design
 * pattern, for changes in singleton properties.  In addition, it fires the
 * following <code>ContainerEvent events to listeners who register
 * themselves with <code>addContainerListener():
 * <table border=1>
 *   <tr>
 *     <th>Type
 *     <th>Data
 *     <th>Description
 *   </tr>
 *   <tr>
 *     <td align=center>addChild
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.