com.gemstone.gemfire.management.internal.FederationComponent Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.management.internal;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.management.ObjectName;
import com.gemstone.gemfire.DataSerializable;
import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.DataSerializableFixedID;
import com.gemstone.gemfire.internal.shared.Version;
import com.gemstone.gemfire.management.ManagementException;
/**
* Central component for federation It consists of an Object State as well as
* some meta data for the Object being federated.
*
* @author rishim
*
*/
public class FederationComponent implements java.io.Serializable, DataSerializable, DataSerializableFixedID {
private static final String THIS_COMPONENT = FederationComponent.class
.getName();
/**
*
*/
private static final long serialVersionUID = 3123549507449088591L;
/**
* Name of the MBean. This name will be replicated at Managing Node
*/
private String objectName;
/**
* Name if the interface class . It will determine the interface for MBean at
* Managing Node side
*/
private String interfaceClassName;
/**
* Flag to determine if MBean emits notification or not.
*/
private boolean notificationEmitter;
/**
* This Map holds the object state as property-value Every component should be
* serializable
*/
private Map objectState = new HashMap();
/**
* Log writer
*/
private transient LogWriterI18n logger = InternalDistributedSystem
.getLoggerI18n();
private transient Map getterMethodMap;
private transient Object mbeanObject;
private transient Class mbeanInterfaceClass;
private transient Map oldObjectState = new HashMap();
private transient final Map methodHandlerMap = OpenTypeUtil.newMap();
private transient boolean prevRefreshChangeDetected = false;
/**
*
* @param objectName
* ObjectName of the MBean
* @param interfaceClass
* interface class of the MBean
* @param notificationEmitter
* specifies whether this MBean is going to emit notifications
*/
public FederationComponent(Object object, ObjectName objectName,
Class interfaceClass, boolean notificationEmitter) {
this.objectName = objectName.toString();
this.interfaceClassName = interfaceClass.getCanonicalName();
this.mbeanInterfaceClass = interfaceClass;
this.notificationEmitter = notificationEmitter;
this.mbeanObject = object;
getterMethodMap = new HashMap();
initGetters(interfaceClass);
}
public FederationComponent(){
}
// Introspect the mbeanInterface and initialize this object's maps.
//
private void initGetters(Class> mbeanInterface) {
final Method[] methodArray = mbeanInterface.getMethods();
for (Method m : methodArray) {
String name = m.getName();
String attrName = "";
if (name.startsWith("get")) {
attrName = name.substring(3);
} else if (name.startsWith("is") && m.getReturnType() == boolean.class) {
attrName = name.substring(2);
}
if (attrName.length() != 0 && m.getParameterTypes().length == 0
&& m.getReturnType() != void.class) { // For Getters
m.setAccessible(true);
getterMethodMap.put(attrName, m);
methodHandlerMap.put(m, new OpenMethod(m));
}
}
}
/**
* gets the Canonical name of the MBean interface
*
* @return mbean interface class name
*/
public String getMBeanInterfaceClass() {
return interfaceClassName;
}
/**
* True if this MBean is a notification emitter.
*
* @return whether its a notification emitter or not
*/
public boolean isNotificationEmitter() {
return notificationEmitter;
}
/**
* This method will get called from Management Thread. This will dynamically
* invoke the MBeans getter methods and set them in ObjectState Map.
*
* In Future releases we can implement the delta propagation here
*
* @return true if the refresh detects that the state changed. It will return
* false if two consecutive refresh calls results in no state change.
* This indicates to the LocalManager whether to send the MBean state
* to Manager or not.
* @throws ManagementException
*/
public boolean refreshObjectState(boolean keepOldState) {
boolean changeDetected = false;
Object[] args = null;
if(keepOldState){
oldObjectState.putAll(objectState);
}
for (Map.Entry gettorMethodEntry: getterMethodMap.entrySet()) {
String property = gettorMethodEntry.getKey();
Object propertyValue = null;
try {
Method m = gettorMethodEntry.getValue();
propertyValue = m.invoke(mbeanObject, args);
//To Handle open types in getter values
OpenMethod op = methodHandlerMap.get(m);
propertyValue = op.convertReturnValueToOpenType(propertyValue);
} catch (Exception e) {
propertyValue = null;
if (logger.finerEnabled()) {
logger.finer(e.getMessage());
}
}
Object oldValue = objectState.put(property, propertyValue);
if (!changeDetected) {
if (propertyValue != null) {
if (!propertyValue.equals(oldValue)) {
changeDetected = true;
}
} else { // new value is null
if (oldValue != null) {
changeDetected = true;
}
}
}
}
boolean retVal = prevRefreshChangeDetected || changeDetected;
prevRefreshChangeDetected = changeDetected;
return retVal;
}
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof FederationComponent) {
FederationComponent anotherFedComp = (FederationComponent) anObject;
if (anotherFedComp.interfaceClassName.equals(this.interfaceClassName)
&& anotherFedComp.notificationEmitter == this.notificationEmitter
&& anotherFedComp.objectState.equals(this.objectState)
&& anotherFedComp.objectName.equals(this.objectName))
return true;
}
return false;
}
public int hashCode() {
return objectName.hashCode();
}
/**
* Managing node will get Object state by calling this method
*
* @param propertyName
* @return value of the given property
*/
public Object getValue(String propertyName) {
return objectState.get(propertyName);
}
public String toString() {
if (Boolean.getBoolean("debug.Management")) {
return " ObjectName = " + objectName + ",InterfaceClassName = "
+ interfaceClassName + ", NotificationEmitter = "
+ notificationEmitter + ", ObjectState = " + objectState.toString();
} else {
return "ObjectName = " + objectName;
}
}
public Map getObjectState(){
return objectState;
}
public Map getOldState(){
return oldObjectState;
}
@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
this.notificationEmitter = DataSerializer.readPrimitiveBoolean(in);
this.interfaceClassName = DataSerializer.readString(in);
this.objectState = DataSerializer.readHashMap(in);
this.objectName = DataSerializer.readString(in);
}
@Override
public void toData(DataOutput out) throws IOException {
DataSerializer.writePrimitiveBoolean(this.notificationEmitter, out);
DataSerializer.writeString(this.interfaceClassName, out);
DataSerializer.writeHashMap((HashMap, ?>) objectState, out);
DataSerializer.writeString(this.objectName, out);
}
@Override
public int getDSFID() {
return DataSerializableFixedID.MGMT_FEDERATION_COMPONENT;
}
public Object getMBeanObject(){
return mbeanObject;
}
public Class getInterfaceClass(){
return mbeanInterfaceClass;
}
@Override
public Version[] getSerializationVersions() {
return null;
}
}