/* * 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;
/** * 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
*/
publicclass StandardService extends LifecycleMBeanBase implements Service {
privatestaticfinal Log log = LogFactory.getLog(StandardService.class); privatestaticfinal StringManager sm = StringManager.getManager(StandardService.class);
/** * The name of this service.
*/ private String name = null;
/** * The <code>Server</code> that owns this Service, if any.
*/ private Server server = null;
/** * The property change support for this component.
*/ protectedfinal PropertyChangeSupport support = new PropertyChangeSupport(this);
/** * The set of Connectors associated with this Service.
*/ protected Connector connectors[] = new Connector[0]; privatefinal Object connectorsLock = new Object();
/** * The list of executors held by the service.
*/ protectedfinal ArrayList<Executor> executors = new ArrayList<>();
private Engine engine = null;
private ClassLoader parentClassLoader = null;
/** * Mapper.
*/ protectedfinal Mapper mapper = new Mapper();
// Report this property change to interested listeners
support.firePropertyChange("container", oldEngine, this.engine);
}
/** * Return the name of this Service.
*/
@Override public String getName() { return name;
}
/** * Set the name of this Service. * * @param name The new service name
*/
@Override publicvoid setName(String name) { this.name = name;
}
/** * Return the <code>Server</code> with which we are associated (if any).
*/
@Override public Server getServer() { returnthis.server;
}
/** * Set the <code>Server</code> with which we are associated (if any). * * @param server The server that owns this Service
*/
@Override publicvoid 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
*/
@Override publicvoid addConnector(Connector connector) {
// Report this property change to interested listeners
support.firePropertyChange("connector", null, connector);
}
public ObjectName[] getConnectorNames() { synchronized (connectorsLock) {
ObjectName results[] = new ObjectName[connectors.length]; for (int i = 0; i < results.length; i++) {
results[i] = connectors[i].getObjectName();
} return results;
}
}
/** * Add a property change listener to this component. * * @param listener The listener to add
*/ publicvoid addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
/** * Find and return the set of Connectors associated with this Service.
*/
@Override public Connector[] findConnectors() { synchronized (connectorsLock) { // shallow copy return connectors.clone();
}
}
/** * 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
*/
@Override publicvoid removeConnector(Connector connector) {
synchronized (connectorsLock) { int j = -1; for (int i = 0; i < connectors.length; i++) { if (connector == connectors[i]) {
j = i; break;
}
} if (j < 0) { return;
} if (connectors[j].getState().isAvailable()) { try {
connectors[j].stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.connector.stopFailed", connectors[j]), e);
}
}
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
*/ publicvoid removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
/** * Return a String representation of this component.
*/
@Override public String toString() {
StringBuilder sb = new StringBuilder("StandardService[");
sb.append(getName());
sb.append(']'); return sb.toString();
}
/** * Adds a named executor to the service * * @param ex Executor
*/
@Override publicvoid addExecutor(Executor ex) { synchronized (executors) { if (!executors.contains(ex)) {
executors.add(ex); if (getState().isAvailable()) { try {
ex.start();
} catch (LifecycleException x) {
log.error(sm.getString("standardService.executor.start"), x);
}
}
}
}
}
/** * Retrieves executor by name, null if not found * * @param executorName String * * @return Executor
*/
@Override public Executor getExecutor(String executorName) { synchronized (executors) { for (Executor executor : executors) { if (executorName.equals(executor.getName())) { return executor;
}
}
} returnnull;
}
/** * Removes an executor from the service * * @param ex Executor
*/
@Override publicvoid removeExecutor(Executor ex) { synchronized (executors) { if (executors.remove(ex) && getState().isAvailable()) { try {
ex.stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.executor.stop"), e);
}
}
}
}
/** * Start nested components ({@link Executor}s, {@link Connector}s and {@link Container}s) and implement the * requirements of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error that prevents this component from being * used
*/
@Override protectedvoid startInternal() throws LifecycleException {
if (log.isInfoEnabled()) {
log.info(sm.getString("standardService.start.name", this.name));
}
setState(LifecycleState.STARTING);
// Start our defined Container first if (engine != null) { synchronized (engine) {
engine.start();
}
}
// Start our defined Connectors second synchronized (connectorsLock) { for (Connector connector : connectors) { // If it has already failed, don't try and start it if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
}
}
}
/** * Stop nested components ({@link Executor}s, {@link Connector}s and {@link Container}s) and implement the * requirements of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}. * * @exception LifecycleException if this component detects a fatal error that needs to be reported
*/
@Override protectedvoid stopInternal() throws LifecycleException {
synchronized (connectorsLock) { // Initiate a graceful stop for each connector // This will only work if the bindOnInit==false which is not the // default. for (Connector connector : connectors) {
connector.getProtocolHandler().closeServerSocketGraceful();
}
// Wait for the graceful shutdown to complete long waitMillis = gracefulStopAwaitMillis; if (waitMillis > 0) { for (Connector connector : connectors) {
waitMillis = connector.getProtocolHandler().awaitConnectionsClose(waitMillis);
}
}
// Pause the connectors for (Connector connector : connectors) {
connector.pause();
}
}
if (log.isInfoEnabled()) {
log.info(sm.getString("standardService.stop.name", this.name));
}
setState(LifecycleState.STOPPING);
// Stop our defined Container once the Connectors are all paused if (engine != null) { synchronized (engine) {
engine.stop();
}
}
// Now stop the connectors synchronized (connectorsLock) { for (Connector connector : connectors) { if (!LifecycleState.STARTED.equals(connector.getState())) { // Connectors only need stopping if they are currently // started. They may have failed to start or may have been // stopped (e.g. via a JMX call) continue;
}
connector.stop();
}
}
// If the Server failed to start, the mapperListener won't have been // started if (mapperListener.getState() != LifecycleState.INITIALIZED) {
mapperListener.stop();
}
/** * Invoke a pre-startup initialization. This is used to allow connectors to bind to restricted ports under Unix * operating environments.
*/
@Override protectedvoid initInternal() throws LifecycleException {
super.initInternal();
if (engine != null) {
engine.init();
}
// Initialize any Executors for (Executor executor : findExecutors()) { if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
// Destroy our defined Connectors synchronized (connectorsLock) { for (Connector connector : connectors) {
connector.destroy();
}
}
// Destroy any Executors for (Executor executor : findExecutors()) {
executor.destroy();
}
if (engine != null) {
engine.destroy();
}
super.destroyInternal();
}
/** * Return the parent class loader for this component.
*/
@Override public ClassLoader getParentClassLoader() { if (parentClassLoader != null) { return parentClassLoader;
} if (server != null) { return server.getParentClassLoader();
} return ClassLoader.getSystemClassLoader();
}
/** * Set the parent class loader for this server. * * @param parent The new parent class loader
*/
@Override publicvoid setParentClassLoader(ClassLoader parent) {
ClassLoader oldParentClassLoader = this.parentClassLoader; this.parentClassLoader = parent;
support.firePropertyChange("parentClassLoader", oldParentClassLoader, this.parentClassLoader);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.