blob: cc0a0ae6ca949495cb6f8a371bb2341face9b136 [file] [log] [blame]
/*
* 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.felix.mosgi.jmx.agent;
import java.util.StringTokenizer;
//import java.lang.management.ManagementFactory;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.Constants;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.InvalidSyntaxException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.MalformedObjectNameException;
import javax.management.MBeanServerFactory;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.NotCompliantMBeanException;
import org.osgi.service.log.LogService;
import org.apache.felix.framework.cache.BundleCache;
public class AgentActivator implements BundleActivator, ServiceListener {
private MBeanServer server;
private ServiceRegistration serverRegistration;
static private BundleContext bc;
private String version = null;
//BundleActivator interface
public void start(BundleContext context) throws Exception {
AgentActivator.bc=context;
this.version=(String)bc.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);
AgentActivator.log(LogService.LOG_INFO, "Starting JMX Agent "+version,null);
StringTokenizer st=new StringTokenizer(System.getProperty("java.version"), ".");
st.nextToken();
int minorVersion = Integer.parseInt(st.nextToken());
this.startAgent(minorVersion);
this.registerExistingMBeans();
bc.addServiceListener(this);
}
public void stop(BundleContext context) throws Exception {
AgentActivator.log(LogService.LOG_INFO, "JMX Agent stopping "+version,null);
// MBeanServerFactory.releaseMBeanServer(this.server);
this.unregisterExistingMBeans();
this.serverRegistration.unregister();
AgentActivator.log(LogService.LOG_INFO, "JMX Agent stopped "+version,null);
AgentActivator.bc=null;
this.serverRegistration=null;
this.server=null;
}
// Service Listener Interface
public void serviceChanged(ServiceEvent serviceEvent) {
ServiceReference serviceReference = serviceEvent.getServiceReference();
if (isMBean(serviceReference)) {
if (serviceEvent.getType() == ServiceEvent.REGISTERED) {
this.register(serviceReference);
} else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING) {
this.unregister(serviceReference);
} else if (serviceEvent.getType() == ServiceEvent.MODIFIED) {
this.unregister(serviceReference);
this.register(serviceReference);
}
}
}
private static void log(int prio, String message, Throwable t){
if (AgentActivator.bc!=null){
ServiceReference logSR=AgentActivator.bc.getServiceReference(LogService.class.getName());
if (logSR!=null){
((LogService)AgentActivator.bc.getService(logSR)).log(prio, message, t);
}else{
System.out.println("No Log Service");
}
}else{
System.out.println(AgentActivator.class.getName()+": No bundleContext");
}
}
private void startAgent(int minor){
if ( minor >= 5 ){
this.server = java.lang.management.ManagementFactory.getPlatformMBeanServer();
AgentActivator.log(LogService.LOG_DEBUG, "A jdk1.5 agent started "+this.server,null);
}else {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
this.server = MBeanServerFactory.createMBeanServer();
AgentActivator.log(LogService.LOG_DEBUG, "A lightweight agent started "+this.server,null);
}
this.serverRegistration=bc.registerService(MBeanServer.class.getName(), this.server, null);
AgentActivator.log(LogService.LOG_INFO, "JMX Agent started "+version,null);
}
private boolean isMBean(ServiceReference serviceReference) {
String[] objectClasses = (String[]) serviceReference.getProperty(Constants.OBJECTCLASS);
if (objectClasses == null){
return false;
}
int i = 0;
for (; i < objectClasses.length; i++) {
if (objectClasses[i].endsWith("MBean")){
break;
}
// "Static MBean interfaces" ends by "MBean"
if (objectClasses[i].equals(DynamicMBean.class.getName())){
break;
}
}
if (i == objectClasses.length){
return false;
}
return true;
}
private void registerExistingMBeans() {
ServiceReference[] serviceReferences = null;
try {
serviceReferences = bc.getServiceReferences(null, null);
} catch (InvalidSyntaxException e) {
// Never Thrown
}
if (serviceReferences == null){
return;
}
for (int i = 0; i < serviceReferences.length; i++) {
if (isMBean(serviceReferences[i])){
this.register(serviceReferences[i]);
}
}
}
private void unregisterExistingMBeans() {
ServiceReference[] serviceReferences = null;
try {
serviceReferences = bc.getServiceReferences(null, null);
} catch (InvalidSyntaxException e) {
// never thrown
}
if (serviceReferences == null){
return;
}
for (int i = 0; i < serviceReferences.length; i++) {
if (isMBean(serviceReferences[i])){
unregister(serviceReferences[i]);
}
}
}
private void register(ServiceReference serviceReference) {
String name = this.getObjectNameString(serviceReference);
Object mbean = bc.getService(serviceReference);
ObjectName objectName = null;
try {
// Unique identification of MBeans
objectName = new ObjectName(name);
} catch (MalformedObjectNameException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
try {
// Uniquely identify the MBean and register it with the MBeanServer
server.registerMBean(mbean, objectName);
} catch (InstanceAlreadyExistsException e1) {
e1.printStackTrace();
} catch (MBeanRegistrationException e1) {
e1.printStackTrace();
} catch (NotCompliantMBeanException e1) {
e1.printStackTrace();
}
}
private void unregister(ServiceReference serviceReference) {
String name = getObjectNameString(serviceReference);
try {
// TODO check if unregisterMBean occurs really
server.unregisterMBean(new ObjectName(name));
} catch (InstanceNotFoundException e) {
// do nothing;
} catch (Exception e) {
e.printStackTrace();
}
}
private String getObjectNameString(ServiceReference serviceReference) {
String objectName = (String) serviceReference.getProperty(org.apache.felix.mosgi.jmx.agent.Constants.OBJECTNAME);
if (objectName != null){
// If objectName starts with the colon character (:), the domain part of the object name is the domain of the agent.
if(objectName.startsWith(":")){
// invokes the getDefaultDomain() method of the Framework class to obtain this information.
objectName=server.getDefaultDomain()+objectName;
}
return objectName;
}
System.out.println("No "+org.apache.felix.mosgi.jmx.agent.Constants.OBJECTNAME+" constant for "+serviceReference+" MBean. Trying to build it");
String[] objectClasses = (String[]) serviceReference.getProperty(Constants.OBJECTCLASS);
if (objectClasses == null){
return null;
}
int i = 0;
for (; i < objectClasses.length; i++) {
if (objectClasses[i].endsWith("MBean")){
break;
}
}
// TODO do nothing if there is several MBean inplemented interfaces
if (i == objectClasses.length){
return null;
}
StringBuffer sb=new StringBuffer(server.getDefaultDomain());
sb.append(":");
sb.append("BundleId=");
sb.append(serviceReference.getBundle().getBundleId());
sb.append(", ServiceId=");
sb.append(serviceReference.getProperty(Constants.SERVICE_ID));
sb.append(", ObjectClass=");
sb.append(objectClasses[i]);
Object servicePID=serviceReference.getProperty(Constants.SERVICE_PID);
if (servicePID==null){
sb.append(", servicePID=NA");
}else{
sb.append(", servicePID=");
sb.append(servicePID);
}
System.out.println("==>"+sb.toString());
return sb.toString();
}
}