org.rifidi.edge.configuration.RifidiService.java Source code

Java tutorial

Introduction

Here is the source code for org.rifidi.edge.configuration.RifidiService.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Transcends, LLC.
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU 
 * General Public License as published by the Free Software Foundation; either version 2 of the 
 * License, or (at your option) any later version. This program is distributed in the hope that it will 
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You 
 * should have received a copy of the GNU General Public License along with this program; if not, 
 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 
 * USA. 
 * http://www.gnu.org/licenses/gpl-2.0.html
 *******************************************************************************/
package org.rifidi.edge.configuration;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.ReflectionException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;

/**
 * Interface for rifidi services.
 * 
 * @author Jochen Mader - jochen@pramari.com
 * @author Kyle Neumeier - kyle@pramari.com
 */
public abstract class RifidiService {

    /** The object that allows us to unregister the OSGi service */
    private ServiceRegistration serviceRegistration;
    /** The ID for this service */
    private volatile String ID;
    /** The logger for this class */
    private static final Log logger = LogFactory.getLog(RifidiService.class);
    /** Names of properties mapped to their annotations */
    protected final Map<String, Property> nameToProperty;
    /** Names of properties mapped to their getter */
    protected final Map<String, Method> nameToMethod;
    /** Names of operations mapped to their annotations */
    protected final Map<String, Operation> nameToOperation;

    /**
     * Constructor.
     */
    public RifidiService() {
        this.nameToProperty = new HashMap<String, Property>();
        this.nameToOperation = new HashMap<String, Operation>();
        this.nameToMethod = new HashMap<String, Method>();
        Class<?> clazz = this.getClass();
        if (clazz.isAnnotationPresent(JMXMBean.class)) {
            // check method annotations
            for (Method method : clazz.getMethods()) {
                // scan for operations annotation
                if (method.isAnnotationPresent(Operation.class)) {
                    nameToOperation.put(method.getName(), (Operation) method.getAnnotation(Operation.class));
                }
                // scan for property annotation
                if (method.isAnnotationPresent(Property.class)) {
                    nameToProperty.put(method.getName().substring(3),
                            (Property) method.getAnnotation(Property.class));
                    nameToMethod.put(method.getName().substring(3), method);
                }
            }
        }
    }

    /**
     * Get an attribute.
     * 
     * @param attributeName
     * @return
     */
    public Attribute getAttribute(String attributeName) {
        try {
            Object value = nameToMethod.get(attributeName).invoke(this);
            return new Attribute(attributeName, value);
        } catch (IllegalArgumentException e) {
            logger.error(e);
        } catch (IllegalAccessException e) {
            logger.error(e);
        } catch (InvocationTargetException e) {
            logger.error(e);
        }
        return null;
    }

    /**
     * Get all attributes and their values.
     * 
     * @return
     */
    public AttributeList getAttributes() {
        AttributeList ret = new AttributeList();
        for (String name : nameToMethod.keySet()) {
            try {

                Object value = nameToMethod.get(name).invoke(this);
                ret.add(new Attribute(name, value));
            } catch (IllegalArgumentException e) {
                logger.error("Error when invoking getter " + nameToMethod.get(name) + ": " + e);
            } catch (IllegalAccessException e) {
                logger.error("Error when invoking getter " + nameToMethod.get(name) + ": " + e);
            } catch (InvocationTargetException e) {
                logger.error("Error when invoking getter " + nameToMethod.get(name) + ": " + e);
            }
        }
        return ret;
    }

    /**
     * Get a list of attributes.
     * 
     * @param attributeNames
     * @return
     */
    public AttributeList getAttributes(Collection<String> attributeNames) {
        AttributeList ret = new AttributeList();
        try {
            for (String name : nameToMethod.keySet()) {
                if (attributeNames.contains(name)) {
                    Object value = nameToMethod.get(name).invoke(this);
                    ret.add(new Attribute(name, value));
                }
            }
            return ret;
        } catch (IllegalArgumentException e) {
            logger.error(e);
        } catch (IllegalAccessException e) {
            logger.error(e);
        } catch (InvocationTargetException e) {
            logger.error(e);
        }
        return ret;
    }

    /**
     * Private helper method so I don't have to duplicate JMS Notification calls
     * 
     * @param attribute
     * @throws AttributeNotFoundException
     * @throws InvalidAttributeValueException
     * @throws MBeanException
     * @throws ReflectionException
     */
    private void _setAttribute(Attribute attribute)
            throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        // for now we go through the individual setters
        if (nameToProperty.containsKey(attribute.getName())) {
            try {
                Property prop = nameToProperty.get(attribute.getName());
                Method method = this.getClass().getMethod("set" + attribute.getName(),
                        PropertyType.getClassFromType(prop.type()));

                // if attribute is a string, but is supposed to be another
                // type, convert it
                if ((attribute.getValue() instanceof String) && prop.type() != PropertyType.PT_STRING) {
                    attribute = new Attribute(attribute.getName(),
                            PropertyType.convert((String) attribute.getValue(), prop.type()));
                }
                method.invoke(this, attribute.getValue());
                return;
            } catch (SecurityException e) {
                logger.error(e);
            } catch (NoSuchMethodException e) {
                logger.error(e);
            } catch (IllegalArgumentException e) {
                logger.error(e);
            } catch (IllegalAccessException e) {
                logger.error(e);
            } catch (InvocationTargetException e) {
                logger.error(e);
            }
        }
        logger.warn("Unknown attribute: " + attribute);
        // throw new AttributeNotFoundException();
    }

    /**
     * Set an attribute.
     * 
     * @param attribute
     */
    public void setAttribute(Attribute attribute) {
        try {
            _setAttribute(attribute);
        } catch (AttributeNotFoundException e) {
            logger.error("Error when setting attribute " + attribute.getName() + " " + e);
        } catch (InvalidAttributeValueException e) {
            logger.error("Error when setting attribute " + attribute.getName() + " " + e);
        } catch (MBeanException e) {
            logger.error("Error when setting attribute " + attribute.getName() + " " + e);
        } catch (ReflectionException e) {
            logger.error("Error when setting attribute " + attribute.getName() + " " + e);
        }
    }

    /**
     * Set several attributes.
     * 
     * @param attributes
     */
    public void setAttributes(AttributeList attributes) {
        for (Attribute attribute : attributes.asList()) {
            try {
                _setAttribute(attribute);
            } catch (AttributeNotFoundException e) {
                logger.error(e);
            } catch (InvalidAttributeValueException e) {
                logger.error(e);
            } catch (MBeanException e) {
                logger.error(e);
            } catch (ReflectionException e) {
                logger.error(e);
            }
        }
    }

    /**
     * Id of the service. This ID has be unique for the whole application.
     * 
     * @return
     */
    public String getID() {
        return ID;
    }

    /**
     * Set the ID of the service. This can only be done once. Further calls have
     * to be ignored.
     * 
     * @param id
     */
    public void setID(String id) {
        if (ID == null) {
            this.ID = id;
        } else {
            logger.warn("Already set the ID for this Service " + ID);
        }
    }

    /**
     * This method should be called to register the service to OSGi
     * 
     * @param context
     *            The BundleContext to use to register the service
     * @param interfaces
     *            The Interfaces to register the service under
     * @param params
     *            OSGi service params
     */
    protected void register(final BundleContext context, final Collection<String> interfaces,
            final Map<String, String> params) {
        interfaces.add(RifidiService.class.getName());
        String[] serviceInterfaces = new String[interfaces.size()];
        serviceInterfaces = interfaces.toArray(serviceInterfaces);
        Hashtable<String, String> parms = new Hashtable<String, String>();
        parms.put("serviceid", getID());
        parms.putAll(params);
        this.serviceRegistration = context.registerService(serviceInterfaces, this, parms);
    }

    /**
     * Unregister this service from the OSGi registry. Should normally be called
     * when the RifidiService is destroyed
     */
    protected void unregister() {
        if (serviceRegistration != null) {
            serviceRegistration.unregister();
        } else {
            logger.warn("Service has not been registered " + ID);
        }
    }

    /**
     * Get the MBean info.
     * 
     * @return
     */
    public abstract MBeanInfo getMBeanInfo();

    /**
     * Destroy the RifidiService. Should normally at least unregister this
     * service
     */
    protected abstract void destroy();
}