package org.jolokia.backend;
/*
* Copyright 2009-2013 Roland Huss
*
* 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.
*/
import java.io.IOException;
import java.util.*;
import javax.management.*;
import org.jolokia.backend.executor.AbstractMBeanServerExecutor;
import org.jolokia.backend.executor.NotChangedException;
import org.jolokia.detector.ServerDetector;
import org.jolokia.handler.JsonRequestHandler;
import org.jolokia.request.JmxRequest;
/**
* Singleton responsible for doing the merging of all MBeanServer detected.
* It provides a single entry point for all supported JMX operations and has the
* facility to detect MBeanServers by delegating the lookup to various
* {@link ServerDetector}s, to {@link MBeanServerFactory#findMBeanServer(String)}
* and finally to the PlatformMBeanServer
*
*
* It also has a special treatment for the so called "JolokiaMBeanServer" which is
* always hidden from JSR-160 and provides some extra functionality like JSONMBeans.
*
* @author roland
* @since 17.01.13
*/
public class MBeanServerExecutorLocal extends AbstractMBeanServerExecutor implements NotificationListener {
// Set of MBeanServers found
private MBeanServers mbeanServers;
/**
* Constructor with a given list of destectors
*
* @param pDetectors list of detectors for the MBeanServers. Must not be null.
*/
public MBeanServerExecutorLocal(List<ServerDetector> pDetectors) {
init(pDetectors);
}
/**
* Constructor with no detectors
*/
public MBeanServerExecutorLocal() {
this(Collections.<ServerDetector>emptyList());
}
/**
* Use various ways for getting to the MBeanServer which should be exposed via this manager
* servlet.
*
* <ul>
<li>Add the Jolokia private MBeanServer</li>
* <li>Ask the given server detectors for MBeanServer so that can used container specific lookup
* algorithms
* <li>Use {@link javax.management.MBeanServerFactory#findMBeanServer(String)} for
* registered MBeanServer and take the <b>first</b> one in the returned list
* <li>Finally, use the {@link java.lang.management.ManagementFactory#getPlatformMBeanServer()}
* </ul>
*
* @throws IllegalStateException if no MBeanServer could be found.
* @param pDetectors detectors which might have extra possibilities to add MBeanServers
*/
private synchronized void init(List<ServerDetector> pDetectors) {
// Create the MBeanServerList
mbeanServers = new MBeanServers(pDetectors,this);
// Register for registers/deregister of MBean changes in order to update lastUpdateTime
registerForMBeanNotifications();
}
/**
* Handle a single request
*
* @param pRequestHandler the handler which can deal with this request
* @param pJmxReq the request to execute
* @return the return value
*
* @throws MBeanException
* @throws ReflectionException
* @throws AttributeNotFoundException
* @throws InstanceNotFoundException
*/
public <R extends JmxRequest> Object handleRequest(JsonRequestHandler<R> pRequestHandler, R pJmxReq)
throws MBeanException, ReflectionException, AttributeNotFoundException, InstanceNotFoundException, NotChangedException {
AttributeNotFoundException attrException = null;
InstanceNotFoundException objNotFoundException = null;
for (MBeanServerConnection conn : getMBeanServers()) {
try {
return pRequestHandler.handleRequest(conn, pJmxReq);
} catch (InstanceNotFoundException exp) {
// Remember exceptions for later use
objNotFoundException = exp;
} catch (AttributeNotFoundException exp) {
attrException = exp;
} catch (IOException exp) {
throw new IllegalStateException("I/O Error while dispatching",exp);
}
}
if (attrException != null) {
throw attrException;
}
// Must be there, otherwise we would not have left the loop
throw objNotFoundException;
}
/**
* Lifecycle method called at the end of life for this object.
*/
public void destroy() {
unregisterFromMBeanNotifications();
mbeanServers.destroy();
}
/**
* Get a string representation of all servers
*
* @return string representation of the servers along with some statistics.
*/
public String getServersInfo() {
return mbeanServers.dump();
}
// ==============================================================================
/** {@inheritDoc} */
@Override
protected Set<MBeanServerConnection> getMBeanServers() {
return mbeanServers.getMBeanServers();
}
/**
* {@inheritDoc}
*/
@Override
protected MBeanServerConnection getJolokiaMBeanServer() {
return mbeanServers.getJolokiaMBeanServer();
}
}