|  | /* | 
|  | * 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.util; | 
|  |  | 
|  | import javax.management.InstanceNotFoundException; | 
|  | import javax.management.MBeanRegistrationException; | 
|  | import javax.management.MBeanServer; | 
|  | import javax.management.MalformedObjectNameException; | 
|  | import javax.management.ObjectName; | 
|  |  | 
|  | import org.apache.catalina.Globals; | 
|  | import org.apache.catalina.JmxEnabled; | 
|  | import org.apache.catalina.LifecycleException; | 
|  | import org.apache.juli.logging.Log; | 
|  | import org.apache.juli.logging.LogFactory; | 
|  | import org.apache.tomcat.util.modeler.Registry; | 
|  | import org.apache.tomcat.util.res.StringManager; | 
|  |  | 
|  | public abstract class LifecycleMBeanBase extends LifecycleBase | 
|  | implements JmxEnabled { | 
|  |  | 
|  | private static final Log log = LogFactory.getLog(LifecycleMBeanBase.class); | 
|  |  | 
|  | private static final StringManager sm = | 
|  | StringManager.getManager("org.apache.catalina.util"); | 
|  |  | 
|  |  | 
|  | /* Cache components of the MBean registration. */ | 
|  | private String domain = null; | 
|  | private ObjectName oname = null; | 
|  | protected MBeanServer mserver = null; | 
|  |  | 
|  | /** | 
|  | * Sub-classes wishing to perform additional initialization should override | 
|  | * this method, ensuring that super.initInternal() is the first call in the | 
|  | * overriding method. | 
|  | */ | 
|  | @Override | 
|  | protected void initInternal() throws LifecycleException { | 
|  |  | 
|  | // If oname is not null then registration has already happened via | 
|  | // preRegister(). | 
|  | if (oname == null) { | 
|  | mserver = Registry.getRegistry(null, null).getMBeanServer(); | 
|  |  | 
|  | oname = register(this, getObjectNameKeyProperties()); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Sub-classes wishing to perform additional clean-up should override this | 
|  | * method, ensuring that super.destroyInternal() is the last call in the | 
|  | * overriding method. | 
|  | */ | 
|  | @Override | 
|  | protected void destroyInternal() throws LifecycleException { | 
|  | unregister(oname); | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Specify the domain under which this component should be registered. Used | 
|  | * with components that cannot (easily) navigate the component hierarchy to | 
|  | * determine the correct domain to use. | 
|  | */ | 
|  | @Override | 
|  | public final void setDomain(String domain) { | 
|  | this.domain = domain; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Obtain the domain under which this component will be / has been | 
|  | * registered. | 
|  | */ | 
|  | @Override | 
|  | public final String getDomain() { | 
|  | if (domain == null) { | 
|  | domain = getDomainInternal(); | 
|  | } | 
|  |  | 
|  | if (domain == null) { | 
|  | domain = Globals.DEFAULT_MBEAN_DOMAIN; | 
|  | } | 
|  |  | 
|  | return domain; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Method implemented by sub-classes to identify the domain in which MBeans | 
|  | * should be registered. | 
|  | * | 
|  | * @return  The name of the domain to use to register MBeans. | 
|  | */ | 
|  | protected abstract String getDomainInternal(); | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Obtain the name under which this component has been registered with JMX. | 
|  | */ | 
|  | @Override | 
|  | public final ObjectName getObjectName() { | 
|  | return oname; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Allow sub-classes to specify the key properties component of the | 
|  | * {@link ObjectName} that will be used to register this component. | 
|  | * | 
|  | * @return  The string representation of the key properties component of the | 
|  | *          desired {@link ObjectName} | 
|  | */ | 
|  | protected abstract String getObjectNameKeyProperties(); | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Utility method to enable sub-classes to easily register additional | 
|  | * components that don't implement {@link JmxEnabled} with an MBean server. | 
|  | * <br> | 
|  | * Note: This method should only be used once {@link #initInternal()} has | 
|  | * been called and before {@link #destroyInternal()} has been called. | 
|  | * | 
|  | * @param obj                       The object the register | 
|  | * @param objectNameKeyProperties   The key properties component of the | 
|  | *                                  object name to use to register the | 
|  | *                                  object | 
|  | * | 
|  | * @return  The name used to register the object | 
|  | */ | 
|  | protected final ObjectName register(Object obj, | 
|  | String objectNameKeyProperties) { | 
|  |  | 
|  | // Construct an object name with the right domain | 
|  | StringBuilder name = new StringBuilder(getDomain()); | 
|  | name.append(':'); | 
|  | name.append(objectNameKeyProperties); | 
|  |  | 
|  | ObjectName on = null; | 
|  |  | 
|  | try { | 
|  | on = new ObjectName(name.toString()); | 
|  |  | 
|  | Registry.getRegistry(null, null).registerComponent(obj, on, null); | 
|  | } catch (MalformedObjectNameException e) { | 
|  | log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name), | 
|  | e); | 
|  | } catch (Exception e) { | 
|  | log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name), | 
|  | e); | 
|  | } | 
|  |  | 
|  | return on; | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Utility method to enable sub-classes to easily unregister additional | 
|  | * components that don't implement {@link JmxEnabled} with an MBean server. | 
|  | * <br> | 
|  | * Note: This method should only be used once {@link #initInternal()} has | 
|  | * been called and before {@link #destroyInternal()} has been called. | 
|  | * | 
|  | * @param on    The name of the component to unregister | 
|  | */ | 
|  | protected final void unregister(ObjectName on) { | 
|  |  | 
|  | // If null ObjectName, just return without complaint | 
|  | if (on == null) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | // If the MBeanServer is null, log a warning & return | 
|  | if (mserver == null) { | 
|  | log.warn(sm.getString("lifecycleMBeanBase.unregisterNoServer", on)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | try { | 
|  | mserver.unregisterMBean(on); | 
|  | } catch (MBeanRegistrationException e) { | 
|  | log.warn(sm.getString("lifecycleMBeanBase.unregisterFail", on), e); | 
|  | } catch (InstanceNotFoundException e) { | 
|  | log.warn(sm.getString("lifecycleMBeanBase.unregisterFail", on), e); | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Not used - NOOP. | 
|  | */ | 
|  | @Override | 
|  | public final void postDeregister() { | 
|  | // NOOP | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Not used - NOOP. | 
|  | */ | 
|  | @Override | 
|  | public final void postRegister(Boolean registrationDone) { | 
|  | // NOOP | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Not used - NOOP. | 
|  | */ | 
|  | @Override | 
|  | public final void preDeregister() throws Exception { | 
|  | // NOOP | 
|  | } | 
|  |  | 
|  |  | 
|  | /** | 
|  | * Allows the object to be registered with an alternative | 
|  | * {@link MBeanServer} and/or {@link ObjectName}. | 
|  | */ | 
|  | @Override | 
|  | public final ObjectName preRegister(MBeanServer server, ObjectName name) | 
|  | throws Exception { | 
|  |  | 
|  | this.mserver = server; | 
|  | this.oname = name; | 
|  | this.domain = name.getDomain(); | 
|  |  | 
|  | return oname; | 
|  | } | 
|  |  | 
|  | } |