/** * Copyright 2014 Telefonica Investigación y Desarrollo, S.A.U <br> * This file is part of FI-WARE project. * <p> * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. * </p> * <p> * You may obtain a copy of the License at:<br> * <br> * http://www.apache.org/licenses/LICENSE-2.0 * </p> * <p> * 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. * </p> * <p> * See the License for the specific language governing permissions and limitations under the License. * </p> * <p> * For those usages not covered by the Apache version 2.0 License please contact with opensource@tid.es * </p> */ package com.telefonica.euro_iaas.commons.properties; import java.util.Iterator; import java.util.Properties; import java.util.SortedSet; import java.util.TreeSet; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; import javax.management.InvalidAttributeValueException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.ReflectionException; /** * Utility MBean that exposes a PropertiesUtil through JMX. * * @author Sergio Arroyo */ public class PropertiesProviderMBean implements DynamicMBean { private final String namespace; private final PropertiesProvider propUtil; private Properties properties; /** * Constructor of the class. * * @param namespace * The namespace * @param propUtil * The PropertiesUtil to expose through JMX * @param classForLoading * Reference class for class loading */ public PropertiesProviderMBean(final String namespace, final PropertiesProvider propUtil) { this.namespace = namespace; this.properties = propUtil.load(namespace); this.propUtil = propUtil; } /** * @see javax.management.DynamicMBean#getAttribute(java.lang.String) */ public synchronized String getAttribute(String name) throws AttributeNotFoundException { String value = properties.getProperty(name); if (value != null) { return value; } else { throw new AttributeNotFoundException("No such property: " + name); } } /** * @see DynamicMBean#setAttribute(javax.management.Attribute) */ public synchronized void setAttribute(Attribute attribute) throws InvalidAttributeValueException, MBeanException, AttributeNotFoundException { String name = attribute.getName(); if (properties.getProperty(name) == null) { throw new AttributeNotFoundException(name); } Object value = attribute.getValue(); if (!(value instanceof String)) { throw new InvalidAttributeValueException("Attribute value not a string: " + value); } // Store the current property value. It is needed if there is a // validation problem String currentValue = properties.getProperty(name); properties.setProperty(name, (String) value); try { save(); } catch (Exception e) { // If the current value is not restored next calls to this method // will launch a validation exception, because this.properties // contains an invalid value (the one that launched this exception) properties.setProperty(name, currentValue); throw new InvalidAttributeValueException(e.getMessage()); } } /** * @see javax.management.DynamicMBean#getAttributes(java.lang.String[]) */ public synchronized AttributeList getAttributes(String[] names) { AttributeList list = new AttributeList(); for (String name : names) { String value = properties.getProperty(name); if (value != null) { list.add(new Attribute(name, value)); } } return list; } /** * @see DynamicMBean#setAttributes(javax.management.AttributeList) */ public synchronized AttributeList setAttributes(AttributeList list) { Attribute[] attrs = (Attribute[]) list.toArray(new Attribute[0]); AttributeList retlist = new AttributeList(); for (Attribute attr : attrs) { String name = attr.getName(); Object value = attr.getValue(); if (properties.getProperty(name) != null && value instanceof String) { properties.setProperty(name, (String) value); retlist.add(new Attribute(name, value)); } } save(); return retlist; } /** * @see javax.management.DynamicMBean#invoke(java.lang.String, java.lang.Object[], java.lang.String[]) */ public Object invoke(String name, Object[] args, String[] sig) throws MBeanException, ReflectionException { if (name.equals("reload") && (args == null || args.length == 0) && (sig == null || sig.length == 0)) { load(); return null; } throw new ReflectionException(new NoSuchMethodException(name)); } /** * @see javax.management.DynamicMBean#getMBeanInfo() */ public synchronized MBeanInfo getMBeanInfo() { SortedSet<String> names = new TreeSet<String>(); for (Object name : properties.keySet()) names.add((String) name); MBeanAttributeInfo[] attrs = new MBeanAttributeInfo[names.size()]; Iterator<String> it = names.iterator(); for (int i = 0; i < attrs.length; i++) { String name = it.next(); attrs[i] = new MBeanAttributeInfo(name, "java.lang.String", "Property " + name, true, // isReadable true, // isWritable false); // isIs } MBeanOperationInfo[] opers = { new MBeanOperationInfo("reload", "Reload properties from file", null, // no // parameters "void", MBeanOperationInfo.ACTION) }; return new MBeanInfo(this.getClass().getName(), "Property Manager MBean", attrs, null, // constructors opers, null); // notifications } /** * Load a properties util. */ private void load() { properties = propUtil.load(namespace); } /** * Stores a properties util. * * @throws InvalidPropertyValueException * If there is a validation problem */ private void save() { propUtil.store(properties, namespace); } }