All Downloads are FREE. Search and download functionalities are using the official Maven repository.

flex.management.BaseControl Maven / Gradle / Ivy

/*
 * 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 flex.management;

import flex.management.runtime.AdminConsoleDisplayRegistrar;
import flex.messaging.FlexContext;

import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanRegistration;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.servlet.ServletConfig;

/**
 * The implementation of the BaseControlMBean interface. This
 * abstract class provides the core functionality that all Flex control MBeans
 * require.
 * 

* Defining concrete implementations of getId() and * getType() are left to subclasses, but this base class does * provide access to the parent MBean for each instance. This class also * implements the MBeanRegistration interface, and it * automatically stores a reference to the MBean server in each instance upon * registration. Subclasses may choose to override none, any, or all of the * methods defined by the MBeanRegistration interface, but any * overrides should be sure to invoke the overridden method with a call to their * superclass. *

* The register() method provides a simple and consistent way to * register instances with the MBean server, and the * getObjectName() method gaurantees consistent, well-formed * ObjectNames for all MBean instances.

*/ public abstract class BaseControl implements BaseControlMBean, MBeanRegistration { /** * The prefix used for the domain part of control MBean names. */ public static final String DOMAIN_PREFIX = "flex.runtime"; private static final int MALFORMED_OBJECTNAME = 10400; private static final int UNREG_EXCEPTION = 10401; private static final int UNREG_NOTFOUND = 10402; private static final int REG_EXCEPTION = 10403; private static final int REG_ALREADYEXISTS = 10404; private static final int REG_NOTCOMPLIANT = 10405; private static final int DISABLE_MANAGEMENT = 10426; protected Date startTimestamp; private BaseControl parent; private ObjectName objectName; private ObjectName registeredObjectName; private MBeanServer server; private boolean registered = false; private AdminConsoleDisplayRegistrar registrar; // Implements flex.management.BaseControlMBean.getId; inherits javadoc // specification. public abstract String getId(); // Implements flex.management.BaseControlMBean.getType; inherits javadoc // specification. public abstract String getType(); // Implements flex.management.BaseControlMBean.getParent; inherits javadoc // specification. public final ObjectName getParent() { return (parent != null) ? parent.getObjectName() : null; } /** * Returns an identifier for the application that hosts the component that * this control manages. * * @return An identifier for the application that hosts the component this * control manages. */ public String getApplicationId() { String id = null; // Our base implementation attempts to use the current servlet context // name as our application identifier. ServletConfig config = FlexContext.getServletConfig(); if (config != null) { id = config.getServletContext().getServletContextName(); } return (id != null) ? id.replace(":", "") : ""; } /** * Set the register object. * @param registrar the registrar to set */ protected void setRegistrar(AdminConsoleDisplayRegistrar registrar) { this.registrar = registrar; } /** * Return the registar object. * @return the registrar */ public AdminConsoleDisplayRegistrar getRegistrar() { if ((parent == null) && (this.registrar == null)) { return new AdminConsoleDisplayRegistrar(null); } return (this.registrar != null) ? this.registrar : parent.getRegistrar(); } /** * Constructs a BaseControl instance that references its * parent; the parent may be null for root control MBeans. * * @param parent The parent BaseControl for this instance or * null if this instance is the root of a control hierarchy. */ public BaseControl(BaseControl parent) { this.parent = parent; } /** * Returns the parent BaseControl of this instance. * * @return The parent BaseControl. */ public final BaseControl getParentControl() { return parent; } /** * The MBeanServer that this instance is registered with. If * this instance has not been registered this method returns * null. * * @return The MBeanServer that this instance is registered * with. */ public final MBeanServer getMBeanServer() { return server; } /** * Registers this instance with the MBean server. * * It may throw ManagementException If an MBeanRegistrationException * or InstanceAlreadyExistsException is thrown while * registering this MBean, the typed exception is wrapped in a * runtime ManagementException and rethrown. */ public final void register() { if (!registered) { MBeanServer server = MBeanServerLocatorFactory.getMBeanServerLocator().getMBeanServer(); ObjectName name = getObjectName(); try { if (server.isRegistered(name)) { server.unregisterMBean(name); } registeredObjectName = server.registerMBean(this, name).getObjectName(); registered = true; onRegistrationComplete(); } catch (ManagementException me) { throw me; } catch (MBeanRegistrationException mre) { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(REG_EXCEPTION, new Object[] {name.toString()}); me.setRootCause(mre); throw me; } catch (InstanceAlreadyExistsException iaee) { // If registration is not working at all, inform the user that // they may // work around the issue by disabling management (no MBeans will // be registered). if (!server.isRegistered(name)) { ManagementException me = new ManagementException(); me.setMessage(DISABLE_MANAGEMENT, new Object[] {name.toString()}); throw me; } else { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(REG_ALREADYEXISTS, new Object[] {name.toString()}); throw me; } } catch (NotCompliantMBeanException ncme) { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(REG_NOTCOMPLIANT, new Object[] {name.toString()}); throw me; } catch (InstanceNotFoundException infe) { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(UNREG_NOTFOUND, new Object[] {name.toString()}); throw me; } } } /** * This method is called after the MBean has been registered and after the * MBean server has returned the registeredObjectName. Classes that need * access to the actual Object name should override this method rather than * the postRegister method. */ protected void onRegistrationComplete() { } /** * Unregisters this instance from the MBean server if it has been registered * previously. */ public final void unregister() { if (registered) { // This method may be called when the JVM is being unloaded, so if // our // external error strings are loaded as missing, fall back to // hard-coded // strings. try { if (server.isRegistered(registeredObjectName)) { server.unregisterMBean(registeredObjectName); } registeredObjectName = null; registered = false; } catch (ManagementException me) { throw me; } catch (MBeanRegistrationException mre) { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(UNREG_EXCEPTION, new Object[] {registeredObjectName.toString()}); if (me.getMessage().indexOf(Integer.toString(UNREG_EXCEPTION)) != -1) { me.setMessage("The MBean named, '" + registeredObjectName.toString() + "', could not be unregistered because its preDeregister() method threw an exception."); } me.setRootCause(mre); throw me; } catch (InstanceNotFoundException infe) { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(UNREG_NOTFOUND, new Object[] {registeredObjectName.toString()}); if (me.getMessage().indexOf(Integer.toString(UNREG_NOTFOUND)) != -1) { me.setMessage("The MBean named, '" + registeredObjectName.toString() + "', could not be unregistered because it is not currently registered."); } throw me; } } } /** * Returns the ObjectName for this instance, according to the * following format: * {domain}[.{appId}]:type={type}[,{parent type}={parent id}]*[,server={server}]?,id={id}. *
    *
  • domain: The domain specified by the DOMAIN_PREFIX * constant followed by the application identifier if one is available.
  • *
  • type: The short type name of the resource managed by * the MBean. * - The MessageBrokerControlMBean manages * the flex.messaging.MessageBroker so: * type=MessageBroker
  • *
  • id: The id value for the resource managed by this * MBean. If no name or id is available on the resource, an id will be * fabricated according to this strategy: * * id = {type} + N (where N is a numeric increment for instances * of this type)
  • *
  • * optional containment keys
  • *
* The runtime MBean model is hierarchical, with all MBeans ultimately * contained by the root MessageBrokerControlMBean. The * ObjectNames used for these MBeans describe this * containment in the following fashion. First, the 'type' key for a * contained MBean indicates the containment hierarchy for the bean. So, the * ObjectName for an RTMPEndpointControlMBean * would be: type=MessageBroker.RTMPEndpoint * * In addition to the hierarchical 'type' key, the full * ObjectName for this RTMPEndpointControlMBean * also contains a containment key: * MessageBroker=MessageBroker1 * * Optional containment keys have the format: * {parent type}={parent name}. A containment key is added for * each ancestor up to the root of the hierarchy and these keys allow the * ObjectName for any MBean instance to fully describe its * specific location in the hierarchy. To complete the example, the full * ObjectName for the example * RTMPEndpointControlMBean would be: * flex:type=MessageBroker.RTMPEndpoint,MessageBroker=MessageBroker1,id=RTMPEndpoint1 *

* If the MBean is registered with the MBean server, this method returns the * ObjectName that the MBean was registered under and this * value may contain additional key-value pairs injected by the container or * MBean server. *

* * @return The ObjectName for this instance. */ public final ObjectName getObjectName() { if (registered) return registeredObjectName; if (objectName == null) { StringBuffer buffer = new StringBuffer(); buffer.append(DOMAIN_PREFIX); String appId = getApplicationId(); if (appId != null && appId.length() > 0) { buffer.append('.'); buffer.append(appId); } buffer.append(":type="); // Build hierarchical type value. List types = new ArrayList(); List ids = new ArrayList(); types.add(getType()); ids.add(getId()); BaseControl ancestor = parent; while (ancestor != null) { types.add(ancestor.getType()); ids.add(ancestor.getId()); ancestor = ancestor.getParentControl(); } for (int i = types.size() - 1; i >= 0; --i) { buffer.append((String)types.get(i)); if (i > 0) { buffer.append('.'); } } buffer.append(','); // Add containment keys. for (int i = ids.size() - 1; i >= 1; --i) { buffer.append((String)types.get(i)); buffer.append('='); buffer.append((String)ids.get(i)); buffer.append(','); } buffer.append("id="); buffer.append(getId()); String name = buffer.toString(); // TODO: Seth: add server identifier key if we're running in a // cluster? try { objectName = new ObjectName(name); } catch (MalformedObjectNameException mone) { // Rethrow with useful message if this ever happens. ManagementException me = new ManagementException(); me.setMessage(MALFORMED_OBJECTNAME, new Object[] {name}); throw me; } } return objectName; } /** * Implements javax.management.MBeanRegistration.preRegister. * Allows the MBean to perform any operations it needs before being * registered in the MBean server. This base implementation stores a * reference to the MBean server that may be accessed via * getMBeanServer(). If subclasses override, they must call * super.preRegister(). * * @param server The Mbean server in which the MBean will be registered. * @param name The object name of the MBean. * @return The name the MBean will be registered under. * @throws Exception when the process failed */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { this.server = server; return (name == null) ? getObjectName() : name; } /** * Implements javax.management.MBeanRegistration.postRegister. * Allows the MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed. This * base implementation is a no-op that may be overridden. * * @param registrationDone Indicates whether or not the MBean was * successfully registered in the MBean server. */ public void postRegister(Boolean registrationDone) { // No-op. } /** * Implements javax.management.MBeanRegistration.preDeregister. * Allows the MBean to perform any operations needed after having been * unregistered in the MBean server. This base implementation is a no-op * that may be overridden. * @throws Exception when the process failed */ public void preDeregister() throws Exception { // No-op. } /** * Implements javax.management.MBeanRegistration.postDeregister. * Allows the MBean to perform any operations it needs before being * unregistered by the MBean server. This base implementation is a no-op * that may be overridden. */ public void postDeregister() { // No-op. } /** * Sets the start timestamp for the managed component. * * @param value The start timestamp for the managed component. */ public void setStartTimestamp(Date value) { startTimestamp = value; } /** * Returns the difference between a start and end timestamps in * minutes. Differences of less than one minute are rounded up to * one minute to avoid frequency calculations reporting infinite * message frequencies. * @param startTime The start timestamp in milliseconds. * @param endTime The end timestamp in milliseconds. * @return The difference between a start and end timestamps in minutes. */ protected double differenceInMinutes(long startTime, long endTime) { double minutes = (endTime - startTime) / 60000d; if (minutes > 1d) { return minutes; } else { return 1d; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy