/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.management.j2ee;
import java.security.InvalidParameterException;
import java.util.Hashtable;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.JMException;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.Notification;
import javax.management.ObjectName;
import org.jboss.logging.Logger;
import org.jboss.management.j2ee.statistics.StatisticsProvider;
import org.jboss.mx.util.JBossNotificationBroadcasterSupport;
import org.jboss.mx.util.ObjectNameConverter;
/**
* Root class of the JBoss JSR-77 implementation of J2EEManagedObject.
*
* @author <a href="mailto:andreas@jboss.org">Andreas Schaefer</a>
* @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
* @author <a href="mailto:thomas.diesler@jboss.org">Thomas Diesler</a>
* @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
* @version $Revision: 81025 $
*/
public abstract class J2EEManagedObject extends JBossNotificationBroadcasterSupport
implements J2EEManagedObjectMBean, MBeanRegistration
{
// Constants -----------------------------------------------------
public static final String TYPE = "j2eeType";
public static final String NAME = "name";
// Attributes ----------------------------------------------------
private static Logger log = Logger.getLogger(J2EEManagedObject.class);
private ObjectName parentName = null;
private ObjectName name = null;
protected MBeanServer server;
// Static --------------------------------------------------------
/**
* Retrieves the type out of an JSR-77 object name
*
* @param pName Object Name to check if null then
* it will be treated like NO type found
* @return The type of the given Object Name or an EMPTY
* string if either Object Name null or type not found
*/
protected static String getType(String pName)
{
String lType = null;
if (pName != null)
{
ObjectName oname = newObjectName(pName);
lType = (String) oname.getKeyPropertyList().get(TYPE);
}
// Return an empty string if type not found
return lType == null ? "" : lType;
}
/**
* Retrieves the type out of an JSR-77 object name
*
* @param pName Object Name to check if null then
* it will be treated like NO type found
* @return The type of the given Object Name or an EMPTY
* string if either Object Name null or type not found
*/
protected static String getType(ObjectName pName)
{
String lType = null;
if (pName != null)
{
lType = (String) pName.getKeyPropertyList().get(TYPE);
}
// Return an empty string if type not found
return lType == null ? "" : lType;
}
/**
* Return the ObjectName that is represented by the given string.
*
* @param pName a object name
*/
protected static ObjectName newObjectName(String pName)
{
try
{
return new ObjectName(pName);
}
catch (MalformedObjectNameException e)
{
throw new IllegalArgumentException("Invalid object name: " + pName);
}
}
protected static ObjectName removeObject(MBeanServer pServer, String pSearchCriteria)
throws JMException
{
ObjectName lSearch = ObjectNameConverter.convert(pSearchCriteria);
log.debug("removeObject(), search for: " + pSearchCriteria + ", search criteria: " + lSearch);
Set lNames = pServer.queryNames(lSearch, null);
if (!lNames.isEmpty())
{
ObjectName lName = (ObjectName) lNames.iterator().next();
pServer.unregisterMBean(lName);
return lName;
}
return null;
}
protected static ObjectName removeObject(MBeanServer pServer, String pName, String pSearchCriteria)
throws JMException
{
String lEncryptedName = ObjectNameConverter.convertCharacters(pName, true);
ObjectName lSearch = new ObjectName(pSearchCriteria + "," + NAME + "=" + lEncryptedName);
log.debug("removeObject(), name: " + pName + ", encrypted name: " + lEncryptedName + ", search criteria: " + lSearch);
Set lNames = pServer.queryNames(lSearch, null);
if (!lNames.isEmpty())
{
ObjectName lName = (ObjectName) lNames.iterator().next();
pServer.unregisterMBean(lName);
return lName;
}
return null;
}
// Constructors --------------------------------------------------
/**
* Constructor for the root J2EEDomain object
*
* @param domainName domain portion to use for the JMX ObjectName
* @param j2eeType JSR77 j2ee-type of the resource being created
* @param resName Name of the managed resource
* @throws InvalidParameterException If the given Domain Name, Type or Name is null
*/
public J2EEManagedObject(String domainName, String j2eeType, String resName)
throws MalformedObjectNameException
{
log = Logger.getLogger(getClass());
if (domainName == null)
{
throw new InvalidParameterException("Domain Name must be set");
}
Hashtable lProperties = new Hashtable();
lProperties.put(TYPE, j2eeType);
lProperties.put(NAME, resName);
name = ObjectNameConverter.convert(domainName, lProperties);
log.debug("ctor, name: " + name);
}
/**
* Constructor for any Managed Object except the root J2EEMangement.
*
* @param j2eeType JSR77 j2ee-type of the resource being created
* @param resName name of the resource
* @param jsr77ParentName Object Name of the parent of this Managed Object
* which must be defined
* @throws InvalidParameterException If the given Type, Name or Parent is null
*/
public J2EEManagedObject(String j2eeType, String resName, ObjectName jsr77ParentName)
throws MalformedObjectNameException,
InvalidParentException
{
log = Logger.getLogger(getClass());
Hashtable lProperties = getParentKeys(jsr77ParentName);
lProperties.put(TYPE, j2eeType);
lProperties.put(NAME, resName);
name = ObjectNameConverter.convert(J2EEDomain.getDomainName(), lProperties);
setparent(jsr77ParentName.getCanonicalName());
}
// Public --------------------------------------------------------
public Logger getLog()
{
return log;
}
public MBeanServer getServer()
{
return server;
}
public ObjectName getObjectName()
{
return name;
}
// J2EEManagedObjectMBean implementation ----------------------------------------------
/**
* @jmx:managed-attribute
*/
public String getobjectName()
{
return name.getCanonicalName();
}
/**
* @jmx:managed-attribute
*/
public String getparent()
{
String parent = null;
if (parentName != null)
parent = parentName.getCanonicalName();
return parent;
}
/**
* @jmx:managed-attribute
*/
public void setparent(String pParent) throws InvalidParentException
{
if (pParent == null)
{
throw new InvalidParameterException("Parent must be set");
}
parentName = newObjectName(pParent);
}
/**
* @jmx:managed-operation
*/
public void addChild(ObjectName pChild)
{
}
/**
* @jmx:managed-operation
*/
public void removeChild(ObjectName pChild)
{
}
/**
* @jmx:managed-attribute
*/
public boolean isstateManageable()
{
return this instanceof StateManageable;
}
/**
* @jmx:managed-attribute
*/
public boolean isstatisticsProvider()
{
return this instanceof StatisticsProvider;
}
/**
* @jmx:managed-attribute
*/
public boolean iseventProvider()
{
return this instanceof EventProvider;
}
// MBeanRegistration implementation ------------------------------
public ObjectName preRegister(MBeanServer server, ObjectName name)
{
this.server = server;
return name;
}
/**
* Last steps to be done after MBean is registered on MBeanServer. This
* method is made final because it contains vital steps mandatory to all
* J2EEManagedObjects. To perform your own Post-Creation steps please
* override {@link #postCreation postCreation()} method.
*/
public final void postRegister(Boolean registrationDone)
{
// This try-catch block is here because of debugging purposes because
// runtime exception in JMX client is a awful thing to figure out
try
{
log.debug("postRegister(), parent: " + parentName);
if (registrationDone.booleanValue())
{
// Let the subclass handle post creation steps
postCreation();
if (parentName != null)
{
try
{
// Notify the parent about its new child
if (parentName.getKeyProperty("name").compareTo("null") != 0)
{
getServer().invoke(parentName,
"addChild",
new Object[]{name},
new String[]{ObjectName.class.getName()});
}
else
{
ObjectName j2eeServerName = J2EEDomain.getDomainServerName(server);
server.invoke(j2eeServerName,
"addChild",
new Object[]{name},
new String[]{ObjectName.class.getName()});
}
}
catch (JMException e)
{
log.debug("Failed to add child", e);
registrationDone = Boolean.FALSE;
}
}
}
}
catch (RuntimeException re)
{
log.debug("postRegister() caught this exception", re);
throw re;
}
}
/**
* Last steps to be done before MBean is unregistered on MBeanServer. This
* method is made final because it contains vital steps mandatory to all
* J2EEManagedObjects. To perform your own Pre-Destruction steps please
* override {@link #preDestruction preDestruction()} method.
*/
public final void preDeregister()
throws Exception
{
log.debug("preDeregister(), parent: " + parentName);
// Only remove child if it is a child (root has not parent)
if (parentName != null)
{
try
{
// Notify the parent about the removal of its child
server.invoke(parentName,
"removeChild",
new Object[]{name},
new String[]{ObjectName.class.getName()});
}
catch (InstanceNotFoundException infe)
{
}
preDestruction();
}
}
public void postDeregister()
{
server = null;
}
/**
* An overload of the super sendNotification that only takes the event
* type and msg. The source will be set to the managed object name, the
* sequence will be the getNextNotificationSequenceNumber() value, and the
* timestamp System.currentTimeMillis().
*
* @param type the notification event type
* @param info the notification event msg info
*/
public void sendNotification(String type, String info)
{
Notification msg = new Notification(type, this.getObjectName(),
this.getNextNotificationSequenceNumber(),
System.currentTimeMillis(),
info);
super.sendNotification(msg);
}
// Object overrides ---------------------------------------------------
public String toString()
{
return "J2EEManagedObject [ name: " + name + ", parent: " + parentName + " ];";
}
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
protected void postCreation()
{
}
protected void preDestruction()
{
}
/**
* This method can be overwritten by any subclass which must
* return <parent-j2eeType> indicating its parents. By
* default it returns an empty hashtable instance.
*
* @param pParent The direct parent of this class
* @return An empty hashtable
*/
protected Hashtable getParentKeys(ObjectName pParent)
{
return new Hashtable();
}
/**
* The <code>getNextNotificationSequenceNumber</code> method returns
* the next sequence number for use in notifications.
*
* @return a <code>long</code> value
*/
protected long getNextNotificationSequenceNumber()
{
return super.nextNotificationSequenceNumber();
}
// Private -------------------------------------------------------
// Inner classes -------------------------------------------------
}