| /* |
| * Copyright 1999-2002,2004 The Apache Software Foundation. |
| * |
| * Licensed 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.IndexedPropertyDescriptor; |
| import java.beans.Introspector; |
| import java.beans.PropertyChangeListener; |
| import java.beans.PropertyChangeSupport; |
| import java.beans.PropertyDescriptor; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.net.InetAddress; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| import java.security.AccessControlException; |
| import java.sql.Timestamp; |
| import java.util.Random; |
| |
| import javax.management.MBeanRegistration; |
| import javax.management.MBeanServer; |
| import javax.management.ObjectName; |
| import javax.naming.directory.DirContext; |
| |
| import org.apache.catalina.Container; |
| import org.apache.catalina.Context; |
| import org.apache.catalina.Engine; |
| import org.apache.catalina.Host; |
| 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.Server; |
| import org.apache.catalina.ServerFactory; |
| import org.apache.catalina.Service; |
| import org.apache.catalina.Store; |
| import org.apache.catalina.Valve; |
| import org.apache.catalina.connector.Connector; |
| import org.apache.catalina.deploy.ApplicationParameter; |
| import org.apache.catalina.deploy.ContextEjb; |
| import org.apache.catalina.deploy.ContextEnvironment; |
| import org.apache.catalina.deploy.ContextLocalEjb; |
| import org.apache.catalina.deploy.ContextResource; |
| import org.apache.catalina.deploy.ContextResourceEnvRef; |
| import org.apache.catalina.deploy.ContextResourceLink; |
| import org.apache.catalina.deploy.NamingResources; |
| import org.apache.catalina.loader.WebappLoader; |
| import org.apache.catalina.session.PersistentManager; |
| import org.apache.catalina.session.StandardManager; |
| 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; |
| import org.apache.coyote.ProtocolHandler; |
| import org.apache.tomcat.util.IntrospectionUtils; |
| |
| |
| |
| /** |
| * Standard implementation of the <b>Server</b> interface, available for use |
| * (but not required) when deploying and starting Catalina. |
| * |
| * @author Craig R. McClanahan |
| * @version $Revision$ $Date$ |
| */ |
| |
| public final class StandardServer |
| implements Lifecycle, Server, MBeanRegistration |
| { |
| private static Log log = LogFactory.getLog(StandardServer.class); |
| |
| |
| // -------------------------------------------------------------- Constants |
| |
| |
| /** |
| * The set of class/property combinations that should <strong>NOT</strong> |
| * be persisted because they are automatically calculated. |
| */ |
| private static String exceptions[][] = { |
| { "org.apache.catalina.core.StandardEngine", "domain" }, |
| { "org.apache.catalina.core.StandardHost", "domain" }, |
| { "org.apache.catalina.core.StandardContext", "available" }, |
| { "org.apache.catalina.core.StandardContext", "configFile" }, |
| { "org.apache.catalina.core.StandardContext", "configured" }, |
| { "org.apache.catalina.core.StandardContext", "distributable" }, |
| { "org.apache.catalina.core.StandardContext", "domain" }, |
| { "org.apache.catalina.core.StandardContext", "engineName" }, |
| { "org.apache.catalina.core.StandardContext", "name" }, |
| { "org.apache.catalina.core.StandardContext", "override" }, |
| { "org.apache.catalina.core.StandardContext", "publicId" }, |
| { "org.apache.catalina.core.StandardContext", "replaceWelcomeFiles" }, |
| { "org.apache.catalina.core.StandardContext", "sessionTimeout" }, |
| { "org.apache.catalina.core.StandardContext", "startupTime" }, |
| { "org.apache.catalina.core.StandardContext", "tldScanTime" }, |
| //{ "org.apache.catalina.core.StandardContext", "workDir" }, |
| { "org.apache.catalina.session.StandardManager", "distributable" }, |
| { "org.apache.catalina.session.StandardManager", "entropy" }, |
| { "org.apache.coyote.http11.Http11Protocol", "port"}, |
| { "org.apache.coyote.http11.Http11Protocol", "soTimeout"}, |
| { "org.apache.jk.server.JkCoyoteHandler", "name"}, |
| |
| }; |
| |
| |
| /** |
| * The set of classes that represent persistable properties. |
| */ |
| private static Class persistables[] = { |
| String.class, |
| Integer.class, Integer.TYPE, |
| Boolean.class, Boolean.TYPE, |
| Byte.class, Byte.TYPE, |
| Character.class, Character.TYPE, |
| Double.class, Double.TYPE, |
| Float.class, Float.TYPE, |
| Long.class, Long.TYPE, |
| Short.class, Short.TYPE, |
| }; |
| |
| |
| /** |
| * The set of class names that should be skipped when persisting state, |
| * because the corresponding listeners, valves, etc. are configured |
| * automatically at startup time. |
| */ |
| private static String skippables[] = { |
| "org.apache.catalina.authenticator.BasicAuthenticator", |
| "org.apache.catalina.authenticator.DigestAuthenticator", |
| "org.apache.catalina.authenticator.FormAuthenticator", |
| "org.apache.catalina.authenticator.NonLoginAuthenticator", |
| "org.apache.catalina.authenticator.SSLAuthenticator", |
| "org.apache.catalina.core.NamingContextListener", |
| "org.apache.catalina.core.StandardContextValve", |
| "org.apache.catalina.core.StandardDefaultContext", |
| "org.apache.catalina.core.StandardEngineValve", |
| "org.apache.catalina.core.StandardHostValve", |
| "org.apache.catalina.startup.ContextConfig", |
| "org.apache.catalina.startup.EngineConfig", |
| "org.apache.catalina.startup.HostConfig", |
| "org.apache.catalina.valves.CertificatesValve", |
| "org.apache.catalina.valves.ErrorReportValve", |
| "org.apache.catalina.valves.RequestListenerValve", |
| }; |
| |
| |
| /** |
| * The set of class names that are the standard implementations of |
| * components, and hence should not be persisted. |
| */ |
| private static String standardImplementations[] = { |
| "org.apache.catalina.core.StandardServer", |
| "org.apache.catalina.core.StandardService", |
| "org.apache.coyote.tomcat5.CoyoteConnector", |
| "org.apache.catalina.core.StandardEngine", |
| "org.apache.catalina.core.StandardHost", |
| "org.apache.catalina.core.StandardContext", |
| "org.apache.coyote.http11.Http11Protocol", |
| "org.apache.jk.server.JkCoyoteHandler" |
| |
| }; |
| |
| |
| /** |
| * ServerLifecycleListener classname. |
| */ |
| private static String SERVER_LISTENER_CLASS_NAME = |
| "org.apache.catalina.mbeans.ServerLifecycleListener"; |
| |
| |
| // ------------------------------------------------------------ Constructor |
| |
| |
| /** |
| * Construct a default instance of this class. |
| */ |
| public StandardServer() { |
| |
| super(); |
| ServerFactory.setServer(this); |
| |
| globalNamingResources = new NamingResources(); |
| globalNamingResources.setContainer(this); |
| |
| if (isUseNaming()) { |
| if (namingContextListener == null) { |
| namingContextListener = new NamingContextListener(); |
| addLifecycleListener(namingContextListener); |
| } |
| } |
| |
| } |
| |
| |
| // ----------------------------------------------------- Instance Variables |
| |
| |
| /** |
| * Global naming resources context. |
| */ |
| private javax.naming.Context globalNamingContext = null; |
| |
| |
| /** |
| * Global naming resources. |
| */ |
| private NamingResources globalNamingResources = null; |
| |
| |
| /** |
| * Descriptive information about this Server implementation. |
| */ |
| private static final String info = |
| "org.apache.catalina.core.StandardServer/1.0"; |
| |
| |
| /** |
| * The lifecycle event support for this component. |
| */ |
| private LifecycleSupport lifecycle = new LifecycleSupport(this); |
| |
| |
| /** |
| * The naming context listener for this web application. |
| */ |
| private NamingContextListener namingContextListener = null; |
| |
| |
| /** |
| * The port number on which we wait for shutdown commands. |
| */ |
| private int port = 8005; |
| |
| |
| /** |
| * A random number generator that is <strong>only</strong> used if |
| * the shutdown command string is longer than 1024 characters. |
| */ |
| private Random random = null; |
| |
| |
| /** |
| * The set of Services associated with this Server. |
| */ |
| private Service services[] = new Service[0]; |
| |
| |
| /** |
| * The shutdown command string we are looking for. |
| */ |
| private String shutdown = "SHUTDOWN"; |
| |
| |
| /** |
| * The string manager for this package. |
| */ |
| private static final StringManager sm = |
| StringManager.getManager(Constants.Package); |
| |
| |
| /** |
| * Has this component been started? |
| */ |
| private boolean started = false; |
| |
| |
| /** |
| * Has this component been initialized? |
| */ |
| private boolean initialized = false; |
| |
| |
| /** |
| * The property change support for this component. |
| */ |
| protected PropertyChangeSupport support = new PropertyChangeSupport(this); |
| |
| |
| // ------------------------------------------------------------- Properties |
| |
| |
| /** |
| * Return the global naming resources context. |
| */ |
| public javax.naming.Context getGlobalNamingContext() { |
| |
| return (this.globalNamingContext); |
| |
| } |
| |
| |
| /** |
| * Set the global naming resources context. |
| * |
| * @param globalNamingContext The new global naming resource context |
| */ |
| public void setGlobalNamingContext |
| (javax.naming.Context globalNamingContext) { |
| |
| this.globalNamingContext = globalNamingContext; |
| |
| } |
| |
| |
| /** |
| * Return the global naming resources. |
| */ |
| public NamingResources getGlobalNamingResources() { |
| |
| return (this.globalNamingResources); |
| |
| } |
| |
| |
| /** |
| * Set the global naming resources. |
| * |
| * @param globalNamingResources The new global naming resources |
| */ |
| public void setGlobalNamingResources |
| (NamingResources globalNamingResources) { |
| |
| NamingResources oldGlobalNamingResources = |
| this.globalNamingResources; |
| this.globalNamingResources = globalNamingResources; |
| this.globalNamingResources.setContainer(this); |
| support.firePropertyChange("globalNamingResources", |
| oldGlobalNamingResources, |
| this.globalNamingResources); |
| |
| } |
| |
| |
| /** |
| * Return descriptive information about this Server implementation and |
| * the corresponding version number, in the format |
| * <code><description>/<version></code>. |
| */ |
| public String getInfo() { |
| |
| return (info); |
| |
| } |
| |
| |
| /** |
| * Return the port number we listen to for shutdown commands. |
| */ |
| public int getPort() { |
| |
| return (this.port); |
| |
| } |
| |
| |
| /** |
| * Set the port number we listen to for shutdown commands. |
| * |
| * @param port The new port number |
| */ |
| public void setPort(int port) { |
| |
| this.port = port; |
| |
| } |
| |
| |
| /** |
| * Return the shutdown command string we are waiting for. |
| */ |
| public String getShutdown() { |
| |
| return (this.shutdown); |
| |
| } |
| |
| |
| /** |
| * Set the shutdown command we are waiting for. |
| * |
| * @param shutdown The new shutdown command |
| */ |
| public void setShutdown(String shutdown) { |
| |
| this.shutdown = shutdown; |
| |
| } |
| |
| |
| // --------------------------------------------------------- Server Methods |
| |
| |
| /** |
| * Add a new Service to the set of defined Services. |
| * |
| * @param service The Service to be added |
| */ |
| public void addService(Service service) { |
| |
| service.setServer(this); |
| |
| synchronized (services) { |
| Service results[] = new Service[services.length + 1]; |
| System.arraycopy(services, 0, results, 0, services.length); |
| results[services.length] = service; |
| services = results; |
| |
| if (initialized) { |
| try { |
| service.initialize(); |
| } catch (LifecycleException e) { |
| e.printStackTrace(System.err); |
| } |
| } |
| |
| if (started && (service instanceof Lifecycle)) { |
| try { |
| ((Lifecycle) service).start(); |
| } catch (LifecycleException e) { |
| ; |
| } |
| } |
| |
| // Report this property change to interested listeners |
| support.firePropertyChange("service", null, service); |
| } |
| |
| } |
| |
| |
| /** |
| * Wait until a proper shutdown command is received, then return. |
| */ |
| public void await() { |
| |
| // Set up a server socket to wait on |
| ServerSocket serverSocket = null; |
| try { |
| serverSocket = |
| new ServerSocket(port, 1, |
| InetAddress.getByName("127.0.0.1")); |
| } catch (IOException e) { |
| System.err.println("StandardServer.await: create[" + port |
| + "]: " + e); |
| e.printStackTrace(); |
| System.exit(1); |
| } |
| |
| // Loop waiting for a connection and a valid command |
| while (true) { |
| |
| // Wait for the next connection |
| Socket socket = null; |
| InputStream stream = null; |
| try { |
| socket = serverSocket.accept(); |
| socket.setSoTimeout(10 * 1000); // Ten seconds |
| stream = socket.getInputStream(); |
| } catch (AccessControlException ace) { |
| System.err.println("StandardServer.accept security exception: " |
| + ace.getMessage()); |
| continue; |
| } catch (IOException e) { |
| System.err.println("StandardServer.await: accept: " + e); |
| e.printStackTrace(); |
| System.exit(1); |
| } |
| |
| // Read a set of characters from the socket |
| StringBuffer command = new StringBuffer(); |
| int expected = 1024; // Cut off to avoid DoS attack |
| while (expected < shutdown.length()) { |
| if (random == null) |
| random = new Random(System.currentTimeMillis()); |
| expected += (random.nextInt() % 1024); |
| } |
| while (expected > 0) { |
| int ch = -1; |
| try { |
| ch = stream.read(); |
| } catch (IOException e) { |
| System.err.println("StandardServer.await: read: " + e); |
| e.printStackTrace(); |
| ch = -1; |
| } |
| if (ch < 32) // Control character or EOF terminates loop |
| break; |
| command.append((char) ch); |
| expected--; |
| } |
| |
| // Close the socket now that we are done with it |
| try { |
| socket.close(); |
| } catch (IOException e) { |
| ; |
| } |
| |
| // Match against our command string |
| boolean match = command.toString().equals(shutdown); |
| if (match) { |
| break; |
| } else |
| System.err.println("StandardServer.await: Invalid command '" + |
| command.toString() + "' received"); |
| |
| } |
| |
| // Close the server socket and return |
| try { |
| serverSocket.close(); |
| } catch (IOException e) { |
| ; |
| } |
| |
| } |
| |
| |
| /** |
| * Return the specified Service (if it exists); otherwise return |
| * <code>null</code>. |
| * |
| * @param name Name of the Service to be returned |
| */ |
| public Service findService(String name) { |
| |
| if (name == null) { |
| return (null); |
| } |
| synchronized (services) { |
| for (int i = 0; i < services.length; i++) { |
| if (name.equals(services[i].getName())) { |
| return (services[i]); |
| } |
| } |
| } |
| return (null); |
| |
| } |
| |
| |
| /** |
| * Return the set of Services defined within this Server. |
| */ |
| public Service[] findServices() { |
| |
| return (services); |
| |
| } |
| |
| /** |
| * Return the JMX service names. |
| */ |
| public ObjectName[] getServiceNames() { |
| ObjectName onames[]=new ObjectName[ services.length ]; |
| for( int i=0; i<services.length; i++ ) { |
| onames[i]=((StandardService)services[i]).getObjectName(); |
| } |
| return onames; |
| } |
| |
| |
| /** |
| * Remove the specified Service from the set associated from this |
| * Server. |
| * |
| * @param service The Service to be removed |
| */ |
| public void removeService(Service service) { |
| |
| synchronized (services) { |
| int j = -1; |
| for (int i = 0; i < services.length; i++) { |
| if (service == services[i]) { |
| j = i; |
| break; |
| } |
| } |
| if (j < 0) |
| return; |
| if (services[j] instanceof Lifecycle) { |
| try { |
| ((Lifecycle) services[j]).stop(); |
| } catch (LifecycleException e) { |
| ; |
| } |
| } |
| int k = 0; |
| Service results[] = new Service[services.length - 1]; |
| for (int i = 0; i < services.length; i++) { |
| if (i != j) |
| results[k++] = services[i]; |
| } |
| services = results; |
| |
| // Report this property change to interested listeners |
| support.firePropertyChange("service", service, null); |
| } |
| |
| } |
| |
| |
| // --------------------------------------------------------- Public Methods |
| |
| |
| /** |
| * Add a property change listener to this component. |
| * |
| * @param listener The listener to add |
| */ |
| public void addPropertyChangeListener(PropertyChangeListener listener) { |
| |
| support.addPropertyChangeListener(listener); |
| |
| } |
| |
| |
| /** |
| * 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("StandardServer["); |
| sb.append(getPort()); |
| sb.append("]"); |
| return (sb.toString()); |
| |
| } |
| |
| |
| /** |
| * Write the configuration information for this entire <code>Server</code> |
| * out to the server.xml configuration file. |
| * |
| * @exception javax.management.InstanceNotFoundException if the managed resource object |
| * cannot be found |
| * @exception javax.management.MBeanException if the initializer of the object throws |
| * an exception, or persistence is not supported |
| * @exception javax.management.RuntimeOperationsException if an exception is reported |
| * by the persistence mechanism |
| */ |
| public synchronized void storeConfig() throws Exception { |
| |
| // Calculate file objects for the old and new configuration files. |
| String configFile = "conf/server.xml"; // FIXME - configurable? |
| File configOld = new File(configFile); |
| if (!configOld.isAbsolute()) { |
| configOld = new File(System.getProperty("catalina.base"), |
| configFile); |
| } |
| File configNew = new File(configFile + ".new"); |
| if (!configNew.isAbsolute()) { |
| configNew = new File(System.getProperty("catalina.base"), |
| configFile + ".new"); |
| } |
| String ts = (new Timestamp(System.currentTimeMillis())).toString(); |
| // yyyy-mm-dd hh:mm:ss |
| // 0123456789012345678 |
| StringBuffer sb = new StringBuffer("."); |
| sb.append(ts.substring(0, 10)); |
| sb.append('.'); |
| sb.append(ts.substring(11, 13)); |
| sb.append('-'); |
| sb.append(ts.substring(14, 16)); |
| sb.append('-'); |
| sb.append(ts.substring(17, 19)); |
| File configSave = new File(configFile + sb.toString()); |
| if (!configSave.isAbsolute()) { |
| configSave = new File(System.getProperty("catalina.base"), |
| configFile + sb.toString()); |
| } |
| |
| // Open an output writer for the new configuration file |
| PrintWriter writer = null; |
| try { |
| writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(configNew), "UTF8")); |
| } catch (IOException e) { |
| if (writer != null) { |
| try { |
| writer.close(); |
| } catch (Throwable t) { |
| ; |
| } |
| } |
| throw (e); |
| } |
| |
| // Store the state of this Server MBean |
| // (which will recursively store everything |
| try { |
| storeServer(writer, 0, this); |
| } catch (Exception e) { |
| if (writer != null) { |
| try { |
| writer.close(); |
| } catch (Throwable t) { |
| ; |
| } |
| } |
| throw (e); |
| } |
| |
| // Flush and close the output file |
| try { |
| writer.flush(); |
| } catch (Exception e) { |
| throw (e); |
| } |
| try { |
| writer.close(); |
| } catch (Exception e) { |
| throw (e); |
| } |
| |
| // Shuffle old->save and new->old |
| if (configOld.renameTo(configSave)) { |
| if (configNew.renameTo(configOld)) { |
| return; |
| } else { |
| configSave.renameTo(configOld); |
| throw new IOException("Cannot rename " + |
| configNew.getAbsolutePath() + " to " + |
| configOld.getAbsolutePath()); |
| } |
| } else { |
| throw new IOException("Cannot rename " + |
| configOld.getAbsolutePath() + " to " + |
| configSave.getAbsolutePath()); |
| } |
| |
| } |
| |
| |
| /** |
| * Write the configuration information for <code>Context</code> |
| * out to the specified configuration file. |
| * |
| * @exception javax.management.InstanceNotFoundException if the managed resource object |
| * cannot be found |
| * @exception javax.management.MBeanException if the initializer of the object throws |
| * an exception, or persistence is not supported |
| * @exception javax.management.RuntimeOperationsException if an exception is reported |
| * by the persistence mechanism |
| */ |
| public synchronized void storeContext(Context context) throws Exception { |
| |
| String configFile = context.getConfigFile(); |
| |
| if (configFile != null) { |
| File config = new File(configFile); |
| if (!config.isAbsolute()) { |
| config = new File(System.getProperty("catalina.base"), |
| configFile); |
| } |
| |
| // Open an output writer for the new configuration file |
| PrintWriter writer = null; |
| try { |
| writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(config), "UTF8")); |
| } catch (IOException e) { |
| if (writer != null) { |
| try { |
| writer.close(); |
| } catch (Throwable t) { |
| ; |
| } |
| } |
| throw (e); |
| } |
| |
| writer.println("<?xml version='1.0' encoding='utf-8'?>"); |
| writer.print("<Context"); |
| storeAttributes(writer, context); |
| writer.println(">"); |
| writer.println("</Context>"); |
| |
| // Flush and close the output file |
| try { |
| writer.flush(); |
| } catch (Exception e) { |
| throw (e); |
| } |
| try { |
| writer.close(); |
| } catch (Exception e) { |
| throw (e); |
| } |
| } |
| |
| } |
| |
| |
| // -------------------------------------------------------- Private Methods |
| |
| |
| /** Given a string, this method replaces all occurrences of |
| * '<', '>', '&', and '"'. |
| */ |
| |
| private String convertStr(String input) { |
| |
| StringBuffer filtered = new StringBuffer(input.length()); |
| char c; |
| for(int i=0; i<input.length(); i++) { |
| c = input.charAt(i); |
| if (c == '<') { |
| filtered.append("<"); |
| } else if (c == '>') { |
| filtered.append(">"); |
| } else if (c == '\'') { |
| filtered.append("'"); |
| } else if (c == '"') { |
| filtered.append("""); |
| } else if (c == '&') { |
| filtered.append("&"); |
| } else { |
| filtered.append(c); |
| } |
| } |
| return(filtered.toString()); |
| } |
| |
| |
| /** |
| * Is this an instance of the default <code>Loader</code> configuration, |
| * with all-default properties? |
| * |
| * @param loader Loader to be tested |
| */ |
| private boolean isDefaultLoader(Loader loader) { |
| |
| if (!(loader instanceof WebappLoader)) { |
| return (false); |
| } |
| WebappLoader wloader = (WebappLoader) loader; |
| if ((wloader.getDelegate() != false) || |
| !wloader.getLoaderClass().equals |
| ("org.apache.catalina.loader.WebappClassLoader")) { |
| return (false); |
| } |
| return (true); |
| |
| } |
| |
| |
| /** |
| * Is this an instance of the default <code>Manager</code> configuration, |
| * with all-default properties? |
| * |
| * @param manager Manager to be tested |
| */ |
| private boolean isDefaultManager(Manager manager) { |
| |
| if (!(manager instanceof StandardManager)) { |
| return (false); |
| } |
| StandardManager smanager = (StandardManager) manager; |
| if (!smanager.getPathname().equals("SESSIONS.ser") || |
| !smanager.getRandomClass().equals("java.security.SecureRandom") || |
| (smanager.getMaxActiveSessions() != -1) || |
| !smanager.getAlgorithm().equals("MD5")) { |
| return (false); |
| } |
| return (true); |
| |
| } |
| |
| |
| /** |
| * Is the specified class name + property name combination an |
| * exception that should not be persisted? |
| * |
| * @param className The class name to check |
| * @param property The property name to check |
| */ |
| private boolean isException(String className, String property) { |
| |
| for (int i = 0; i < exceptions.length; i++) { |
| if (className.equals(exceptions[i][0]) && |
| property.equals(exceptions[i][1])) { |
| return (true); |
| } |
| } |
| return (false); |
| |
| } |
| |
| |
| /** |
| * Is the specified property type one for which we should generate |
| * a persistence attribute? |
| * |
| * @param clazz Java class to be tested |
| */ |
| private boolean isPersistable(Class clazz) { |
| |
| for (int i = 0; i < persistables.length; i++) { |
| if (persistables[i] == clazz) { |
| return (true); |
| } |
| } |
| return (false); |
| |
| } |
| |
| |
| /** |
| * Is the specified class name one that should be skipped because |
| * the corresponding component is configured automatically at |
| * startup time? |
| * |
| * @param className Class name to be tested |
| */ |
| private boolean isSkippable(String className) { |
| |
| for (int i = 0; i < skippables.length; i++) { |
| if (skippables[i].equals(className)) { |
| return (true); |
| } |
| } |
| return (false); |
| |
| } |
| |
| |
| /** |
| * Store the relevant attributes of the specified JavaBean, plus a |
| * <code>className</code> attribute defining the fully qualified |
| * Java class name of the bean. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param bean Bean whose properties are to be rendered as attributes, |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeAttributes(PrintWriter writer, |
| Object bean) throws Exception { |
| |
| storeAttributes(writer, true, bean); |
| |
| } |
| |
| |
| /** |
| * Store the relevant attributes of the specified JavaBean. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param include Should we include a <code>className</code> attribute? |
| * @param bean Bean whose properties are to be rendered as attributes, |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeAttributes(PrintWriter writer, boolean include, |
| Object bean) throws Exception { |
| |
| // FIXME: Add support for storing all attributes |
| |
| // Render the relevant properties of this bean |
| String className = bean.getClass().getName(); |
| // Render a className attribute if requested |
| if (include) { |
| for (int i = 0; i < standardImplementations.length; i++) { |
| if (className.equals(standardImplementations[i])) { |
| include = false; |
| } |
| } |
| if (include) { |
| writer.print(" className=\""); |
| writer.print(bean.getClass().getName()); |
| writer.print("\""); |
| } |
| } |
| |
| // Acquire the list of properties for this bean |
| PropertyDescriptor descriptors[] = |
| Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); |
| if (descriptors == null) { |
| descriptors = new PropertyDescriptor[0]; |
| } |
| |
| // Create blank instance |
| Object bean2 = bean.getClass().newInstance(); |
| for (int i = 0; i < descriptors.length; i++) { |
| if (descriptors[i] instanceof IndexedPropertyDescriptor) { |
| continue; // Indexed properties are not persisted |
| } |
| if (!isPersistable(descriptors[i].getPropertyType()) || |
| (descriptors[i].getReadMethod() == null) || |
| (descriptors[i].getWriteMethod() == null)) { |
| continue; // Must be a read-write primitive or String |
| } |
| Object value = |
| IntrospectionUtils.getProperty(bean, |
| descriptors[i].getName()); |
| Object value2 = |
| IntrospectionUtils.getProperty(bean2, |
| descriptors[i].getName()); |
| if (value == null) { |
| continue; // Null values are not persisted |
| } |
| if (isException(className, descriptors[i].getName())) { |
| continue; // Skip the specified exceptions |
| } |
| if (value.equals(value2)) { |
| // The property has its default value |
| continue; |
| } |
| if (!(value instanceof String)) { |
| value = value.toString(); |
| } |
| writer.print(' '); |
| writer.print(descriptors[i].getName()); |
| writer.print("=\""); |
| String strValue = convertStr((String) value); |
| writer.print(strValue); |
| writer.print("\""); |
| } |
| |
| } |
| |
| |
| /** |
| * Store the specified Connector properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param connector Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeConnector(PrintWriter writer, int indent, |
| Connector connector) throws Exception { |
| |
| // Store the beginning of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Connector"); |
| storeAttributes(writer, connector); |
| |
| if (connector instanceof Connector) { |
| ProtocolHandler protocolHandler = |
| ((Connector)connector).getProtocolHandler(); |
| storeAttributes(writer, protocolHandler); |
| } |
| |
| writer.println(">"); |
| |
| // Store nested <Listener> elements |
| if (connector instanceof Lifecycle) { |
| LifecycleListener listeners[] = |
| ((Lifecycle) connector).findLifecycleListeners(); |
| if (listeners == null) { |
| listeners = new LifecycleListener[0]; |
| } |
| for (int i = 0; i < listeners.length; i++) { |
| if (listeners[i].getClass().getName().equals |
| (SERVER_LISTENER_CLASS_NAME)) { |
| continue; |
| } |
| storeListener(writer, indent + 2, listeners[i]); |
| } |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Connector>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Context properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param context Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeContext(PrintWriter writer, int indent, |
| Context context) throws Exception { |
| |
| String configFile = context.getConfigFile(); |
| |
| if (configFile != null) { |
| |
| File config = new File(configFile); |
| if (!config.isAbsolute()) { |
| config = new File(System.getProperty("catalina.base"), |
| configFile); |
| } |
| |
| // Open an output writer for the new configuration file |
| writer = null; |
| try { |
| writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(config), "UTF8")); |
| } catch (IOException e) { |
| if (writer != null) { |
| try { |
| writer.close(); |
| } catch (Throwable t) { |
| ; |
| } |
| } |
| throw (e); |
| } |
| |
| writer.println("<?xml version='1.0' encoding='utf-8'?>"); |
| indent = 0; |
| |
| } |
| |
| // Store the beginning of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| |
| writer.print("<Context"); |
| storeAttributes(writer, context); |
| writer.println(">"); |
| |
| // Store nested <InstanceListener> elements |
| String iListeners[] = context.findInstanceListeners(); |
| for (int i = 0; i < iListeners.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<InstanceListener>"); |
| writer.print(iListeners[i]); |
| writer.println("</InstanceListener>"); |
| } |
| |
| // Store nested <Listener> elements |
| if (context instanceof Lifecycle) { |
| LifecycleListener listeners[] = |
| ((Lifecycle) context).findLifecycleListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| if (listeners[i].getClass().getName().equals |
| (SERVER_LISTENER_CLASS_NAME)) { |
| continue; |
| } |
| storeListener(writer, indent + 2, listeners[i]); |
| } |
| } |
| |
| // Store nested <Loader> element |
| Loader loader = context.getLoader(); |
| if (loader != null) { |
| storeLoader(writer, indent + 2, loader); |
| } |
| |
| // Store nested <Manager> element |
| Manager manager = context.getManager(); |
| if (manager != null) { |
| storeManager(writer, indent + 2, manager); |
| } |
| |
| // Store nested <Parameter> elements |
| ApplicationParameter[] appParams = context.findApplicationParameters(); |
| for (int i = 0; i < appParams.length; i++) { |
| for (int j = 0; j < indent + 2; j++) { |
| writer.print(' '); |
| } |
| writer.print("<Parameter"); |
| storeAttributes(writer, false, appParams[i]); |
| writer.println("/>"); |
| } |
| |
| // Store nested <Realm> element |
| Realm realm = context.getRealm(); |
| if (realm != null) { |
| Realm parentRealm = null; |
| if (context.getParent() != null) { |
| parentRealm = context.getParent().getRealm(); |
| } |
| if (realm != parentRealm) { |
| storeRealm(writer, indent + 2, realm); |
| } |
| } |
| |
| // Store nested <Resources> element |
| DirContext resources = context.getResources(); |
| if (resources != null) { |
| storeResources(writer, indent + 2, resources); |
| } |
| |
| // Store nested <Valve> elements |
| if (context instanceof Pipeline) { |
| Valve valves[] = ((Pipeline) context).getValves(); |
| for (int i = 0; i < valves.length; i++) { |
| storeValve(writer, indent + 2, valves[i]); |
| } |
| } |
| |
| // Store nested <WrapperLifecycle> elements |
| String wLifecycles[] = context.findWrapperLifecycles(); |
| for (int i = 0; i < wLifecycles.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<WrapperLifecycle>"); |
| writer.print(wLifecycles[i]); |
| writer.println("</WrapperLifecycle>"); |
| } |
| |
| // Store nested <WrapperListener> elements |
| String wListeners[] = context.findWrapperListeners(); |
| for (int i = 0; i < wListeners.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<WrapperListener>"); |
| writer.print(wListeners[i]); |
| writer.println("</WrapperListener>"); |
| } |
| |
| // Store nested naming resources elements |
| NamingResources nresources = context.getNamingResources(); |
| if (nresources != null) { |
| storeNamingResources(writer, indent + 2, nresources); |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Context>"); |
| |
| if (configFile != null) { |
| |
| // Flush and close the output file |
| try { |
| writer.flush(); |
| } catch (Exception e) { |
| throw (e); |
| } |
| try { |
| writer.close(); |
| } catch (Exception e) { |
| throw (e); |
| } |
| } |
| |
| } |
| |
| |
| /** |
| * Store the specified Engine properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param engine Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeEngine(PrintWriter writer, int indent, |
| Engine engine) throws Exception { |
| |
| // Store the beginning of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Engine"); |
| storeAttributes(writer, engine); |
| writer.println(">"); |
| |
| // Store nested <Host> elements (or other relevant containers) |
| Container children[] = engine.findChildren(); |
| for (int i = 0; i < children.length; i++) { |
| if (children[i] instanceof Context) { |
| storeContext(writer, indent + 2, (Context) children[i]); |
| } else if (children[i] instanceof Engine) { |
| storeEngine(writer, indent + 2, (Engine) children[i]); |
| } else if (children[i] instanceof Host) { |
| storeHost(writer, indent + 2, (Host) children[i]); |
| } |
| } |
| |
| // Store nested <Listener> elements |
| if (engine instanceof Lifecycle) { |
| LifecycleListener listeners[] = |
| ((Lifecycle) engine).findLifecycleListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| if (listeners[i].getClass().getName().equals |
| (SERVER_LISTENER_CLASS_NAME)) { |
| continue; |
| } |
| storeListener(writer, indent + 2, listeners[i]); |
| } |
| } |
| |
| // Store nested <Realm> element |
| Realm realm = engine.getRealm(); |
| if (realm != null) { |
| Realm parentRealm = null; |
| if (engine.getParent() != null) { |
| parentRealm = engine.getParent().getRealm(); |
| } |
| if (realm != parentRealm) { |
| storeRealm(writer, indent + 2, realm); |
| } |
| } |
| |
| // Store nested <Valve> elements |
| if (engine instanceof Pipeline) { |
| Valve valves[] = ((Pipeline) engine).getValves(); |
| for (int i = 0; i < valves.length; i++) { |
| storeValve(writer, indent + 2, valves[i]); |
| } |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Engine>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Host properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param host Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeHost(PrintWriter writer, int indent, |
| Host host) throws Exception { |
| |
| // Store the beginning of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Host"); |
| storeAttributes(writer, host); |
| writer.println(">"); |
| |
| // Store nested <Alias> elements |
| String aliases[] = host.findAliases(); |
| for (int i = 0; i < aliases.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<Alias>"); |
| writer.print(aliases[i]); |
| writer.println("</Alias>"); |
| } |
| |
| // Store nested <Cluster> elements |
| ; // FIXME - But it's not supported by any standard Host implementation |
| |
| // Store nested <Context> elements (or other relevant containers) |
| Container children[] = host.findChildren(); |
| for (int i = 0; i < children.length; i++) { |
| if (children[i] instanceof Context) { |
| storeContext(writer, indent + 2, (Context) children[i]); |
| } else if (children[i] instanceof Engine) { |
| storeEngine(writer, indent + 2, (Engine) children[i]); |
| } else if (children[i] instanceof Host) { |
| storeHost(writer, indent + 2, (Host) children[i]); |
| } |
| } |
| |
| // Store nested <Listener> elements |
| if (host instanceof Lifecycle) { |
| LifecycleListener listeners[] = |
| ((Lifecycle) host).findLifecycleListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| if (listeners[i].getClass().getName().equals |
| (SERVER_LISTENER_CLASS_NAME)) { |
| continue; |
| } |
| storeListener(writer, indent + 2, listeners[i]); |
| } |
| } |
| |
| // Store nested <Realm> element |
| Realm realm = host.getRealm(); |
| if (realm != null) { |
| Realm parentRealm = null; |
| if (host.getParent() != null) { |
| parentRealm = host.getParent().getRealm(); |
| } |
| if (realm != parentRealm) { |
| storeRealm(writer, indent + 2, realm); |
| } |
| } |
| |
| // Store nested <Valve> elements |
| if (host instanceof Pipeline) { |
| Valve valves[] = ((Pipeline) host).getValves(); |
| for (int i = 0; i < valves.length; i++) { |
| storeValve(writer, indent + 2, valves[i]); |
| } |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Host>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Listener properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param listener Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeListener(PrintWriter writer, int indent, |
| LifecycleListener listener) throws Exception { |
| |
| if (isSkippable(listener.getClass().getName())) { |
| return; |
| } |
| |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Listener"); |
| storeAttributes(writer, listener); |
| writer.println("/>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Loader properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param loader Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeLoader(PrintWriter writer, int indent, |
| Loader loader) throws Exception { |
| |
| if (isDefaultLoader(loader)) { |
| return; |
| } |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Loader"); |
| storeAttributes(writer, loader); |
| writer.println("/>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Manager properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param manager Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeManager(PrintWriter writer, int indent, |
| Manager manager) throws Exception { |
| |
| if (isDefaultManager(manager)) { |
| return; |
| } |
| |
| // Store the beginning of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Manager"); |
| storeAttributes(writer, manager); |
| writer.println(">"); |
| |
| // Store nested <Store> element |
| if (manager instanceof PersistentManager) { |
| Store store = ((PersistentManager) manager).getStore(); |
| if (store != null) { |
| storeStore(writer, indent + 2, store); |
| } |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Manager>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified NamingResources properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param resources Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeNamingResources(PrintWriter writer, int indent, |
| NamingResources resources) |
| throws Exception { |
| |
| // FIXME: Store extra attributes for some of these |
| |
| // Store nested <Ejb> elements |
| ContextEjb[] ejbs = resources.findEjbs(); |
| if (ejbs.length > 0) { |
| for (int i = 0; i < ejbs.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<Ejb"); |
| storeAttributes(writer, false, ejbs[i]); |
| writer.println("/>"); |
| } |
| } |
| |
| // Store nested <Environment> elements |
| ContextEnvironment[] envs = resources.findEnvironments(); |
| if (envs.length > 0) { |
| for (int i = 0; i < envs.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<Environment"); |
| storeAttributes(writer, false, envs[i]); |
| writer.println("/>"); |
| } |
| } |
| |
| // Store nested <LocalEjb> elements |
| ContextLocalEjb[] lejbs = resources.findLocalEjbs(); |
| if (lejbs.length > 0) { |
| for (int i = 0; i < lejbs.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<LocalEjb"); |
| storeAttributes(writer, false, lejbs[i]); |
| writer.println("/>"); |
| } |
| } |
| |
| // Store nested <Resource> elements |
| ContextResource[] dresources = resources.findResources(); |
| for (int i = 0; i < dresources.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<Resource"); |
| storeAttributes(writer, false, dresources[i]); |
| writer.println("/>"); |
| } |
| |
| // Store nested <ResourceEnvRef> elements |
| ContextResourceEnvRef[] eresources = resources.findResourceEnvRefs(); |
| for (int i = 0; i < eresources.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.println("<ResourceEnvRef"); |
| storeAttributes(writer, false, eresources[i]); |
| writer.println("</ResourceEnvRef>"); |
| } |
| |
| // Store nested <ResourceLink> elements |
| ContextResourceLink[] resourceLinks = resources.findResourceLinks(); |
| for (int i = 0; i < resourceLinks.length; i++) { |
| for (int j = 0; j < indent; j++) { |
| writer.print(' '); |
| } |
| writer.print("<ResourceLink"); |
| storeAttributes(writer, false, resourceLinks[i]); |
| writer.println("/>"); |
| } |
| |
| } |
| |
| |
| /** |
| * Store the specified Realm properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param realm Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeRealm(PrintWriter writer, int indent, |
| Realm realm) throws Exception { |
| |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Realm"); |
| storeAttributes(writer, realm); |
| writer.println("/>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Resources properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param resources Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeResources(PrintWriter writer, int indent, |
| DirContext resources) throws Exception { |
| |
| if (resources instanceof org.apache.naming.resources.FileDirContext) { |
| return; |
| } |
| if (resources instanceof org.apache.naming.resources.ProxyDirContext) { |
| return; |
| } |
| if (resources instanceof org.apache.naming.resources.WARDirContext) { |
| return; |
| } |
| |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Resources"); |
| storeAttributes(writer, resources); |
| writer.println("/>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Server properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param server Object to be stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeServer(PrintWriter writer, int indent, |
| Server server) throws Exception { |
| |
| // Store the beginning of this element |
| writer.println("<?xml version='1.0' encoding='utf-8'?>"); |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Server"); |
| storeAttributes(writer, server); |
| writer.println(">"); |
| |
| // Store nested <Listener> elements |
| if (server instanceof Lifecycle) { |
| LifecycleListener listeners[] = |
| ((Lifecycle) server).findLifecycleListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| storeListener(writer, indent + 2, listeners[i]); |
| } |
| } |
| |
| // Store nested <GlobalNamingResources> element |
| NamingResources globalNamingResources = |
| server.getGlobalNamingResources(); |
| if (globalNamingResources != null) { |
| for (int i = 0; i < indent + 2; i++) { |
| writer.print(' '); |
| } |
| writer.println("<GlobalNamingResources>"); |
| storeNamingResources(writer, indent + 4, globalNamingResources); |
| for (int i = 0; i < indent + 2; i++) { |
| writer.print(' '); |
| } |
| writer.println("</GlobalNamingResources>"); |
| } |
| |
| // Store nested <Service> elements |
| Service services[] = server.findServices(); |
| for (int i = 0; i < services.length; i++) { |
| storeService(writer, indent + 2, services[i]); |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Server>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Service properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param service Object to be stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeService(PrintWriter writer, int indent, |
| Service service) throws Exception { |
| |
| // Store the beginning of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Service"); |
| storeAttributes(writer, service); |
| writer.println(">"); |
| |
| // Store nested <Connector> elements |
| Connector connectors[] = service.findConnectors(); |
| for (int i = 0; i < connectors.length; i++) { |
| storeConnector(writer, indent + 2, connectors[i]); |
| } |
| |
| // Store nested <Engine> element (or other appropriate container) |
| Container container = service.getContainer(); |
| if (container != null) { |
| if (container instanceof Context) { |
| storeContext(writer, indent + 2, (Context) container); |
| } else if (container instanceof Engine) { |
| storeEngine(writer, indent + 2, (Engine) container); |
| } else if (container instanceof Host) { |
| storeHost(writer, indent + 2, (Host) container); |
| } |
| } |
| |
| // Store nested <Listener> elements |
| if (service instanceof Lifecycle) { |
| LifecycleListener listeners[] = |
| ((Lifecycle) service).findLifecycleListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| if (listeners[i].getClass().getName().equals |
| (SERVER_LISTENER_CLASS_NAME)) { |
| continue; |
| } |
| storeListener(writer, indent + 2, listeners[i]); |
| } |
| } |
| |
| // Store the ending of this element |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.println("</Service>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Store properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param store Object whose properties are being stored |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeStore(PrintWriter writer, int indent, |
| Store store) throws Exception { |
| |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Store"); |
| storeAttributes(writer, store); |
| writer.println("/>"); |
| |
| } |
| |
| |
| /** |
| * Store the specified Valve properties. |
| * |
| * @param writer PrintWriter to which we are storing |
| * @param indent Number of spaces to indent this element |
| * @param valve Object whose properties are being valved |
| * |
| * @exception Exception if an exception occurs while storing |
| */ |
| private void storeValve(PrintWriter writer, int indent, |
| Valve valve) throws Exception { |
| |
| if (isSkippable(valve.getClass().getName())) { |
| return; |
| } |
| |
| for (int i = 0; i < indent; i++) { |
| writer.print(' '); |
| } |
| writer.print("<Valve"); |
| storeAttributes(writer, valve); |
| writer.println("/>"); |
| |
| } |
| |
| |
| /** |
| * Return <code>true</code> if the specified client and server addresses |
| * are the same. This method works around a bug in the IBM 1.1.8 JVM on |
| * Linux, where the address bytes are returned reversed in some |
| * circumstances. |
| * |
| * @param server The server's InetAddress |
| * @param client The client's InetAddress |
| */ |
| private boolean isSameAddress(InetAddress server, InetAddress client) { |
| |
| // Compare the byte array versions of the two addresses |
| byte serverAddr[] = server.getAddress(); |
| byte clientAddr[] = client.getAddress(); |
| if (serverAddr.length != clientAddr.length) |
| return (false); |
| boolean match = true; |
| for (int i = 0; i < serverAddr.length; i++) { |
| if (serverAddr[i] != clientAddr[i]) { |
| match = false; |
| break; |
| } |
| } |
| if (match) |
| return (true); |
| |
| // Compare the reversed form of the two addresses |
| for (int i = 0; i < serverAddr.length; i++) { |
| if (serverAddr[i] != clientAddr[(serverAddr.length-1)-i]) |
| return (false); |
| } |
| return (true); |
| |
| } |
| |
| |
| /** |
| * Return true if naming should be used. |
| */ |
| private boolean isUseNaming() { |
| boolean useNaming = true; |
| // Reading the "catalina.useNaming" environment variable |
| String useNamingProperty = System.getProperty("catalina.useNaming"); |
| if ((useNamingProperty != null) |
| && (useNamingProperty.equals("false"))) { |
| useNaming = false; |
| } |
| return useNaming; |
| } |
| |
| |
| // ------------------------------------------------------ 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.debug(sm.getString("standardServer.start.started")); |
| return; |
| } |
| |
| // Notify our interested LifecycleListeners |
| lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); |
| |
| lifecycle.fireLifecycleEvent(START_EVENT, null); |
| started = true; |
| |
| // Start our defined Services |
| synchronized (services) { |
| for (int i = 0; i < services.length; i++) { |
| if (services[i] instanceof Lifecycle) |
| ((Lifecycle) services[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); |
| started = false; |
| |
| // Stop our defined Services |
| for (int i = 0; i < services.length; i++) { |
| if (services[i] instanceof Lifecycle) |
| ((Lifecycle) services[i]).stop(); |
| } |
| |
| // Notify our interested LifecycleListeners |
| lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null); |
| |
| } |
| |
| public void init() throws Exception { |
| initialize(); |
| } |
| |
| /** |
| * 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 |
| { |
| if (initialized) { |
| log.info(sm.getString("standardServer.initialize.initialized")); |
| return; |
| } |
| initialized = true; |
| |
| if( oname==null ) { |
| try { |
| oname=new ObjectName( "Catalina:type=Server"); |
| Registry.getRegistry(null, null) |
| .registerComponent(this, oname, null ); |
| } catch (Exception e) { |
| log.error("Error registering ",e); |
| } |
| } |
| |
| // Initialize our defined Services |
| for (int i = 0; i < services.length; i++) { |
| services[i].initialize(); |
| } |
| } |
| |
| protected String type; |
| protected String domain; |
| protected String suffix; |
| protected ObjectName oname; |
| 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() { |
| } |
| |
| } |