All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gemstone.gemfire.management.internal.FederationComponent Maven / Gradle / Ivy

/*
 * 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;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy