You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by gi...@apache.org on 2005/12/23 17:18:06 UTC
svn commit: r358825 - in /cocoon/trunk: legal/ lib/core/
src/java/org/apache/cocoon/components/
src/java/org/apache/cocoon/core/container/ src/java/org/apache/cocoon/util/
Author: giacomo
Date: Fri Dec 23 08:17:55 2005
New Revision: 358825
URL: http://svn.apache.org/viewcvs?rev=358825&view=rev
Log:
added initial JMX support to the core
Added:
cocoon/trunk/legal/mx4j-jmx-3.0.1.license.txt
cocoon/trunk/lib/core/mx4j-jmx-3.0.1.jar (with props)
cocoon/trunk/src/java/org/apache/cocoon/util/JMXUtils.java
Modified:
cocoon/trunk/src/java/org/apache/cocoon/components/ComponentInfo.java
cocoon/trunk/src/java/org/apache/cocoon/core/container/CoreServiceManager.java
Added: cocoon/trunk/legal/mx4j-jmx-3.0.1.license.txt
URL: http://svn.apache.org/viewcvs/cocoon/trunk/legal/mx4j-jmx-3.0.1.license.txt?rev=358825&view=auto
==============================================================================
--- cocoon/trunk/legal/mx4j-jmx-3.0.1.license.txt (added)
+++ cocoon/trunk/legal/mx4j-jmx-3.0.1.license.txt Fri Dec 23 08:17:55 2005
@@ -0,0 +1,51 @@
+/* ====================================================================
+ * The MX4J License, Version 1.0
+ *
+ * Copyright (c) 2001 MX4J. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * MX4J project (http://mx4j.sourceforge.net)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "MX4J" and "mx4j" must not be used to endorse or promote
+ * products derived from this software without prior written
+ * permission. For written permission, please contact biorn_steedom@users.sourceforge.net
+ *
+ * 5. Products derived from this software may not be called "MX4J",
+ * nor may "MX4J" appear in their name, without prior written
+ * permission of Simone Bordet.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CARLOS QUIROZ OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of MX4J. For more information on
+ * MX4J, please see
+ * <http://mx4j.sourceforge.net>.
+ */
Added: cocoon/trunk/lib/core/mx4j-jmx-3.0.1.jar
URL: http://svn.apache.org/viewcvs/cocoon/trunk/lib/core/mx4j-jmx-3.0.1.jar?rev=358825&view=auto
==============================================================================
Binary file - no diff available.
Propchange: cocoon/trunk/lib/core/mx4j-jmx-3.0.1.jar
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: cocoon/trunk/src/java/org/apache/cocoon/components/ComponentInfo.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/ComponentInfo.java?rev=358825&r1=358824&r2=358825&view=diff
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/components/ComponentInfo.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/components/ComponentInfo.java Fri Dec 23 08:17:55 2005
@@ -16,6 +16,7 @@
package org.apache.cocoon.components;
import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.cocoon.core.container.CoreServiceManager;
/**
* Meta-information about a service
@@ -42,6 +43,8 @@
private String serviceClassName;
private Configuration configuration;
private String loggerCategory;
+ private String jmxDomain;
+ private String jmxName;
public ComponentInfo() {
this.model = MODEL_PRIMITIVE;
@@ -175,6 +178,8 @@
this.setDestroyMethodName(attr.getAttribute("destroy", null));
// logging
this.setLoggerCategory(attr.getAttribute("logger", null));
+ this.setJmxDomain(attr.getAttribute(CoreServiceManager.JMX_DOMAIN_ATTR_NAME, null));
+ this.setJmxName(attr.getAttribute(CoreServiceManager.JMX_NAME_ATTR_NAME, null));
}
public ComponentInfo duplicate() {
@@ -187,6 +192,8 @@
info.serviceClassName = this.serviceClassName;
info.configuration = this.configuration;
info.loggerCategory = this.loggerCategory;
+ info.jmxDomain = this.jmxDomain;
+ info.jmxName = this.jmxName;
return info;
}
@@ -203,5 +210,39 @@
*/
public void setLoggerCategory(String loggerCategory) {
this.loggerCategory = loggerCategory;
+ }
+
+ /**
+ * @return The JMX domain name
+ */
+ public String getJmxDomain() {
+ if (this.jmxDomain == null && this.configuration != null) {
+ this.setJmxDomain(getConfiguration().getAttribute(CoreServiceManager.JMX_DOMAIN_ATTR_NAME, null));
+ }
+ return this.jmxDomain;
+ }
+
+ /**
+ * @param The JMX domain name
+ */
+ public void setJmxDomain(final String jmxDomain) {
+ this.jmxDomain = jmxDomain;
+ }
+
+ /**
+ * @return The JMX object name (without domain prefix)
+ */
+ public String getJmxName() {
+ if (this.jmxName == null && this.configuration != null) {
+ this.setJmxName(getConfiguration().getAttribute(CoreServiceManager.JMX_NAME_ATTR_NAME, null));
+ }
+ return this.jmxName;
+ }
+
+ /**
+ * @param The JMX object name (without domain prefix)
+ */
+ public void setJmxName(final String jmxName) {
+ this.jmxName = jmxName;
}
}
Modified: cocoon/trunk/src/java/org/apache/cocoon/core/container/CoreServiceManager.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/core/container/CoreServiceManager.java?rev=358825&r1=358824&r2=358825&view=diff
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/core/container/CoreServiceManager.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/core/container/CoreServiceManager.java Fri Dec 23 08:17:55 2005
@@ -56,6 +56,7 @@
import org.apache.cocoon.core.source.SimpleSourceResolver;
import org.apache.cocoon.matching.helpers.WildcardHelper;
import org.apache.cocoon.sitemap.impl.ComponentManager;
+import org.apache.cocoon.util.JMXUtils;
import org.apache.excalibur.source.Source;
import org.apache.excalibur.source.SourceResolver;
import org.apache.excalibur.source.TraversableSource;
@@ -70,6 +71,15 @@
extends AbstractLogEnabled
implements Contextualizable, ThreadSafe, Disposable, Initializable, ServiceManager, Configurable {
+ /** The attribute containing the JMX domain name */
+ public static final String JMX_DOMAIN_ATTR_NAME = "jmx-domain";
+
+ /** The attribute containing the JMX domain name */
+ public static final String JMX_NAME_ATTR_NAME = "jmx-name";
+
+ /** The attribute containing the JMX domain name */
+ public static final String JMX_DEFAULT_DOMAIN_NAME = "Cocoon";
+
/**
* An empty configuration object, that can be used when no configuration is known but one
* is needed.
@@ -117,6 +127,8 @@
/** The resolver used to resolve includes. It is lazily loaded in {@link #setupSourceResolver()}. */
private SourceResolver cachedSourceResolver;
+ private String jmxDefaultDomain = null;
+
/** Create the ServiceManager with a parent ServiceManager */
public CoreServiceManager( final ServiceManager parent ) {
this(parent, null);
@@ -188,7 +200,6 @@
// This is the default logger for all components defined with this sitemap/manager.
if ( configuration.getAttribute("logger", null) != null ) {
this.enableLogging(this.loggerManager.getLoggerForCategory(configuration.getAttribute("logger")));
-
}
this.componentEnv = new ComponentEnvironment(this.classloader, getLogger(), this.roleManager, this.loggerManager, this.context, this);
@@ -206,6 +217,9 @@
currentURI = this.location.substring(0, pos-1);
}
+ // find possible JMX domain name
+ this.jmxDefaultDomain = configuration.getAttribute(JMX_DOMAIN_ATTR_NAME, null);
+
try {
// and load configuration with a empty list of loaded configurations
parseConfiguration(configuration, currentURI, new HashSet());
@@ -216,6 +230,19 @@
}
/**
+ * @return The default JMX domain name
+ */
+ public String getJmxDefaultDomain() {
+ if (this.jmxDefaultDomain == null) {
+ if (this.parentManager instanceof CoreServiceManager) {
+ return ((CoreServiceManager)this.parentManager).getJmxDefaultDomain();
+ }
+ return JMX_DEFAULT_DOMAIN_NAME;
+ }
+ return this.jmxDefaultDomain;
+ }
+
+ /**
* Return the service manager logger.
*/
public Logger getServiceManagerLogger() {
@@ -662,22 +689,28 @@
}
}
+ ComponentHandler handler;
if (lazyLoad) {
- return new LazyHandler(role, className, configuration, componentEnv);
- }
-
- // FIXME - we should ensure that we always get an info
- ComponentInfo info;
- if ( baseInfo != null ) {
- info = baseInfo.duplicate();
+ handler = new LazyHandler(role, className, configuration, componentEnv);
} else {
- info = new ComponentInfo();
- info.fill(configuration);
- }
- info.setConfiguration(configuration);
- info.setServiceClassName(className);
+
+ // FIXME - we should ensure that we always get an info
+ ComponentInfo info;
+ if ( baseInfo != null ) {
+ info = baseInfo.duplicate();
+ } else {
+ info = new ComponentInfo();
+ info.fill(configuration);
+ info.setJmxDomain(JMXUtils.findJmxDomain(info.getJmxDomain(), this));
+ info.setJmxName(JMXUtils.findJmxName(info.getJmxName(), className));
+ }
+ info.setConfiguration(configuration);
+ info.setServiceClassName(className);
- return AbstractComponentHandler.getComponentHandler(role, this.componentEnv, info);
+ handler = AbstractComponentHandler.getComponentHandler(role, this.componentEnv, info);
+ JMXUtils.setupJmxFor(handler, info, getLogger());
+ }
+ return handler;
}
private void parseConfiguration(final Configuration configuration, String contextURI, Set loadedURIs)
@@ -712,6 +745,8 @@
if (className == null) {
// Get the default class name for this role
final ComponentInfo info = roleManager.getDefaultServiceInfoForRole(role);
+ info.setJmxDomain(JMXUtils.findJmxDomain(info.getJmxDomain(), this));
+ info.setJmxName(JMXUtils.findJmxName(info.getJmxName(), info.getServiceClassName()));
if (info == null) {
throw new ConfigurationException("Cannot find a class for role " + role + " at " + componentConfig.getLocation());
}
Added: cocoon/trunk/src/java/org/apache/cocoon/util/JMXUtils.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/util/JMXUtils.java?rev=358825&view=auto
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/util/JMXUtils.java (added)
+++ cocoon/trunk/src/java/org/apache/cocoon/util/JMXUtils.java Fri Dec 23 08:17:55 2005
@@ -0,0 +1,197 @@
+/*
+ * Copyright 1999-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.cocoon.util;
+
+import org.apache.avalon.framework.logger.ConsoleLogger;
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.components.ComponentInfo;
+import org.apache.cocoon.core.container.CoreServiceManager;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+/**
+ * Utility methods for JMX
+ *
+ */
+public class JMXUtils {
+
+ /** The {@link MBeanServer} first found */
+ private static MBeanServer mbeanServer = getInitialMBeanServer();
+
+ /**
+ * Private c'tor: its a Utility class
+ */
+ private JMXUtils() {
+ super();
+ }
+
+ /** Get the ev. found {@link MBeanServer} */
+ public static MBeanServer getMBeanServer() {
+ return JMXUtils.mbeanServer;
+ }
+
+ /**
+ * Setup a component for possible JMX managability
+ * @param bean The bean to estabilsh JMX for
+ * @param info The component info
+ */
+ public static ObjectInstance setupJmxFor(final Object bean,
+ final ComponentInfo info)
+ {
+ return setupJmxFor(bean, info, new ConsoleLogger(ConsoleLogger.LEVEL_INFO));
+ }
+
+ /**
+ * Setup a component for possible JMX managability
+ * @param bean The bean to estabilsh JMX for
+ * @param info The component info
+ * @param logger The Logger
+ * @return
+ */
+ public static ObjectInstance setupJmxFor(final Object bean,
+ final ComponentInfo info,
+ final Logger logger)
+ {
+ if (getMBeanServer() != null) {
+ final Class clazz = bean.getClass();
+ final String mbeanClassName = clazz.getName() + "MBean";
+ ObjectName on = null;
+ Object comp = null;
+ try {
+ final Class mbeanClass = clazz.getClassLoader().loadClass(mbeanClassName);
+ final Constructor ctor = mbeanClass.getConstructor(new Class[] {clazz});
+ final Object mbean = ctor.newInstance( new Object[] {bean});
+ final String jmxDomain = info.getJmxDomain();
+ String jmxGroup = info.getConfiguration().getAttribute( CoreServiceManager.JMX_NAME_ATTR_NAME, null );
+ if (jmxGroup == null ) {
+ // otherwise construct one from the service class name
+ final StringBuffer sb = new StringBuffer();
+ final List groups = new ArrayList();
+ int i = info.getServiceClassName().indexOf('.');
+ int j = 0;
+ while(i > 0) {
+ groups.add(info.getServiceClassName().substring(j,i));
+ j = i+1;
+ i = info.getServiceClassName().indexOf('.', i+1);
+ }
+ groups.add(info.getServiceClassName().substring(j));
+ for (i = 0; i < groups.size()-1; i++) {
+ sb.append("group");
+ if (i > 0) {
+ sb.append(i);
+ }
+ sb.append('=');
+ sb.append(groups.get(i));
+ sb.append(',');
+ }
+ sb.append("item=").append(groups.get(groups.size()-1));
+ jmxGroup = sb.toString();
+ }
+ on = new ObjectName( jmxDomain + ":" + jmxGroup );
+ return mbeanServer.registerMBean(mbean,on);
+ } catch (final ClassNotFoundException cnfe) {
+ // happens if a component doesn't have a MBean to support it for management
+ logger.debug( "Class "+info.getServiceClassName()+" doesn't have a supporting MBean called " + mbeanClassName );
+ } catch (final NoSuchMethodException nsme) {
+ logger.warn( "MBean " + mbeanClassName + " doesn't have a constructor that accepts an instance of " + info.getServiceClassName(), nsme);
+ } catch (final InvocationTargetException ite) {
+ logger.warn( "Cannot instantiate class " + mbeanClassName, ite);
+ } catch (final InstantiationException ie) {
+ logger.warn( "Cannot instantiate class " + mbeanClassName, ie);
+ } catch (final IllegalAccessException iae) {
+ logger.warn( "Cannot instantiate class " + mbeanClassName, iae);
+ } catch (final MalformedObjectNameException mone) {
+ logger.warn( "Invalid ObjectName '" + on + "' for MBean " + mbeanClassName, mone);
+ } catch (final InstanceAlreadyExistsException iaee) {
+ logger.warn( "Instance for MBean " + mbeanClassName + "already exists", iaee);
+ } catch (final NotCompliantMBeanException ncme) {
+ logger.warn( "Not compliant MBean " + mbeanClassName, ncme);
+ } catch (final MBeanRegistrationException mre) {
+ logger.warn( "Cannot register MBean " + mbeanClassName, mre);
+ }
+ }
+ return null;
+ }
+
+ public static String findJmxDomain(final String pJmxDomain, final ServiceManager serviceManager) {
+ // try to find a JMX domain name first from this component configuration give as parameter
+ String jmxDomain = pJmxDomain;
+ if( jmxDomain == null )
+ {
+ // next from the CoreServiceManager managing this component
+ if( serviceManager != null && serviceManager instanceof CoreServiceManager )
+ {
+ // next from the CoreServiceManager managing this component
+ jmxDomain = ((CoreServiceManager)serviceManager).getJmxDefaultDomain();
+ } else {
+ // otherwise use default one
+ jmxDomain = CoreServiceManager.JMX_DEFAULT_DOMAIN_NAME;
+ }
+ }
+ return jmxDomain;
+ }
+
+ public static String findJmxName(final String pJmxName, final String pClassName) {
+ String jmxName = pJmxName;
+ final String className = (pClassName == null ? "unknown" : pClassName);
+ if (jmxName == null ) {
+ // otherwise construct one from the service class name
+ final StringBuffer sb = new StringBuffer();
+ final List groups = new ArrayList();
+ int i = className.indexOf('.');
+ int j = 0;
+ while(i > 0) {
+ groups.add(className.substring(j,i));
+ j = i+1;
+ i = className.indexOf('.', i+1);
+ }
+ groups.add(className.substring(j));
+ for (i = 0; i < groups.size()-1; i++) {
+ sb.append("group");
+ if (i > 0) {
+ sb.append(i);
+ }
+ sb.append('=');
+ sb.append(groups.get(i));
+ sb.append(',');
+ }
+ sb.append("item=").append(groups.get(groups.size()-1));
+ jmxName = sb.toString();
+ }
+ return jmxName;
+ }
+
+ private static MBeanServer getInitialMBeanServer() {
+ final List servers = MBeanServerFactory.findMBeanServer(null);
+ if( servers.size() > 0 ) {
+ return (MBeanServer)servers.get(0);
+ }
+ return null;
+ }
+}