package io.eguan.webui.jmx;
/*
* #%L
* Project eguan
* %%
* Copyright (C) 2012 - 2017 Oodrive
* %%
* 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.
* #L%
*/
import io.eguan.configuration.MetaConfiguration;
import io.eguan.vold.model.VvrObjectNameFactory;
import io.eguan.webui.JmxServerUrlConfigKey;
import io.eguan.webui.VvrManagerUi;
import io.eguan.webui.WebUiConfigurationContext;
import io.eguan.webui.model.DeviceModel;
import io.eguan.webui.model.ModelCreator;
import io.eguan.webui.model.SnapshotModel;
import io.eguan.webui.model.VvrManagerModel;
import io.eguan.webui.model.VvrModel;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import javax.management.AttributeChangeNotification;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanServerDelegate;
import javax.management.MBeanServerNotification;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.relation.MBeanServerNotificationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The class handles the JMX connection and create object model via JMX.
*
* @author oodrive
* @author ebredzinski
*
*/
public final class JmxHandler implements NotificationListener, ModelCreator {
private static final Logger LOGGER = LoggerFactory.getLogger(JmxHandler.class);
private JmxClient jmxClient;
private final VvrManagerUi vvrUi;
private UUID ownerUuid;
private final InputStream configInput;
/**
* Context to load as default from internal resources.
*/
private static final String DEFAULT_CONFIG_RESOURCE = "/webuiConfig.cfg";
public JmxHandler(final VvrManagerUi vvrUi) {
final Class<? extends JmxHandler> clazz = getClass();
this.vvrUi = vvrUi;
this.configInput = clazz.getResourceAsStream(DEFAULT_CONFIG_RESOURCE);
}
@Override
public final DeviceModel createDeviceModel(final VvrModel vvr, final UUID deviceUuid) {
return new JmxDeviceModel(jmxClient.getConnection(), ownerUuid, vvr, deviceUuid);
}
@Override
public final SnapshotModel createSnapshotModel(final VvrModel vvr, final UUID snapshotUuid) {
return new JmxSnapshotModel(jmxClient.getConnection(), ownerUuid, vvr, snapshotUuid);
}
@Override
public final VvrModel createVvrModel(final UUID vvrUuid) {
final ObjectName vvrObjectName = VvrObjectNameFactory.newVvrObjectName(ownerUuid, vvrUuid);
try {
jmxClient.getConnection().addNotificationListener(vvrObjectName, this, null, null);
}
catch (InstanceNotFoundException | IOException e) {
LOGGER.error("Can not add a listener", e);
}
return new JmxVvrModel(jmxClient.getConnection(), ownerUuid, vvrUuid);
}
@Override
public final VvrManagerModel createVvrManagerModel() {
return new JmxVvrManagerModel(jmxClient.getConnection(), ownerUuid);
}
@Override
public final void handleNotification(final Notification notification, final Object handback) {
if (notification instanceof MBeanServerNotification) {
final MBeanServerNotification mbs = (MBeanServerNotification) notification;
final ObjectName objectname = mbs.getMBeanName();
if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(mbs.getType())) {
LOGGER.debug("MBean registered=" + objectname);
vvrUi.access(new Runnable() {
@Override
public void run() {
if (isVvr(objectname)) {
vvrUi.addVvr(getVvrUuid(objectname));
}
else if (isSnapshot(objectname)) {
vvrUi.addSnapshot(getVvrUuid(objectname), getSnapshotUuid(objectname));
}
else if (isDevice(objectname)) {
vvrUi.addDevice(getVvrUuid(objectname), getDeviceUuid(objectname));
}
}
});
}
else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(mbs.getType())) {
LOGGER.debug("MBean unregistered=" + objectname);
vvrUi.access(new Runnable() {
@Override
public void run() {
if (isVvr(objectname)) {
vvrUi.removeVvr(getVvrUuid(objectname));
}
else if (isSnapshot(objectname)) {
vvrUi.removeSnapshot(getVvrUuid(objectname), getSnapshotUuid(objectname));
}
else if (isDevice(objectname)) {
vvrUi.removeDevice(getVvrUuid(objectname), getDeviceUuid(objectname));
}
}
});
}
}
else if (notification instanceof AttributeChangeNotification) {
LOGGER.debug("MBean changed=" + notification.getSource());
final AttributeChangeNotification attrNotif = (AttributeChangeNotification) notification;
final ObjectName objectname = (ObjectName) notification.getSource();
vvrUi.access(new Runnable() {
@Override
public void run() {
if (isVvr(objectname)) {
if (isName(attrNotif.getAttributeName())) {
vvrUi.modifyVvrName(getVvrUuid(objectname), (String) attrNotif.getNewValue());
}
}
else if (isSnapshot(objectname)) {
if (isName(attrNotif.getAttributeName())) {
vvrUi.modifySnapshotName(getVvrUuid(objectname), getSnapshotUuid(objectname),
(String) attrNotif.getNewValue());
}
else if (isDescription(attrNotif.getAttributeName())) {
vvrUi.modifySnapshotDescription(getVvrUuid(objectname), getSnapshotUuid(objectname),
(String) attrNotif.getNewValue());
}
}
else if (isDevice(objectname)) {
if (isName(attrNotif.getAttributeName())) {
vvrUi.modifyDeviceName(getVvrUuid(objectname), getDeviceUuid(objectname),
(String) attrNotif.getNewValue());
}
else if (isDescription(attrNotif.getAttributeName())) {
vvrUi.modifyDeviceDescription(getVvrUuid(objectname), getDeviceUuid(objectname),
(String) attrNotif.getNewValue());
}
}
}
});
}
}
/**
* Disconnect to the MBean server.
*/
public final void disconnect() {
try {
jmxClient.getConnection().removeNotificationListener(MBeanServerDelegate.DELEGATE_NAME, this);
}
catch (final Exception e) {
LOGGER.error("Can not disconnect", e);
}
}
/**
* Connect on the MBean server
*
* @throws Exception
*/
public final void connect() throws Exception {
jmxClient = new JmxClient();
final MetaConfiguration configuration = MetaConfiguration.newConfiguration(configInput,
WebUiConfigurationContext.getInstance());
final String serverUrl = JmxServerUrlConfigKey.getInstance().getTypedValue(configuration);
ownerUuid = jmxClient.connect(serverUrl);
LOGGER.debug("Connect on=" + ownerUuid);
final MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter();
filter.enableAllObjectNames();
jmxClient.getConnection().addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, this, filter, null);
}
/**
* Gets UUID for vvr ObjectName.
*
* @param vvrObjectName
*
* @return the UUID
*/
static final UUID getVvrUuid(final ObjectName vvrObjectName) {
return UUID.fromString(vvrObjectName.getKeyProperty("vvr"));
}
/**
* Gets UUID from snapshot ObjectName
*
* @param snapshotObjectName
* @return
*/
static final UUID getSnapshotUuid(final ObjectName snapshotObjectName) {
return UUID.fromString(snapshotObjectName.getKeyProperty("snapshot"));
}
/**
* Gets UUID from device object name
*
* @param deviceObjectName
* @return
*/
static final UUID getDeviceUuid(final ObjectName deviceObjectName) {
return UUID.fromString(deviceObjectName.getKeyProperty("device"));
}
private final boolean isVvr(final ObjectName vvrObjectName) {
return vvrObjectName.getKeyProperty("type").equals("Vvr");
}
private final boolean isSnapshot(final ObjectName snapshotObjectName) {
return snapshotObjectName.getKeyProperty("type").equals("Snapshot");
}
private final boolean isDevice(final ObjectName deviceObjectName) {
return deviceObjectName.getKeyProperty("type").equals("Device");
}
private final boolean isName(final String attributes) {
return attributes.equals("Name");
}
private final boolean isDescription(final String attributes) {
return attributes.equals("Description");
}
}