blob: 1d7ed55d0f8c451963574f45455d9eba4b823898 [file] [log] [blame]
/*
* Copyright 2005 The Apache Software Foundation
*
* 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.
*
*/
package org.apache.felix.jmood.compendium;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Set;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistration;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import org.apache.felix.jmood.AgentContext;
import org.apache.felix.jmood.utils.ObjectNames;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
//import es.upm.dit.osgi.management.agent.AgentConstants;
/**
* This is the main class of the config admin module. As such, it is responsible for controlling all the issues related to it. This class implements
* the ConfigAdminManagerMXBean which defines its management interface. It creates a ConfigurationDelegate object for each available
* Configuration object.
*
*/
public class ConfigAdminManager extends NotificationBroadcasterSupport
implements MBeanRegistration, ConfigAdminManagerMBean{
/*NOTE: The spec says that ConfigurationException's should be used by management systems
* in order to inform a human manager in a suitable way. However, this is not possible unless we implement the service
* because nowhere in the spec is there a way of accesing those exceptions (unless the implementation of the cm chooses to log the exception, which is not even suggested in the spec)
*/
private MBeanServer server;
private AgentContext ac;
private ConfigurationAdmin cadmin;
public ConfigAdminManager(AgentContext ac) {
this.ac=ac;
}
/**
* This is called before the module is loaded. It initializes the module.
* @see javax.management.MBeanRegistration#preRegister(javax.management.MBeanServer, javax.management.ObjectName)
*/
public ObjectName preRegister(MBeanServer server, ObjectName name)
throws Exception {
this.server = server;
return name;
}
/**
* @see javax.management.MBeanRegistration#postRegister(java.lang.Boolean)
*/
public void postRegister(Boolean registrationDone) {}
/**
* @see javax.management.MBeanRegistration#preDeregister()
*/
public void preDeregister() throws Exception {
//Remove the service
//and remove all mbeans from this module...
unregisterMBeans();
}
/**
* @see javax.management.MBeanRegistration#postDeregister()
*/
public void postDeregister() {}
/**
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#listConfigurations(java.lang.String)
*/
public String[] listConfigurations(String filter) throws Exception {
ConfigurationAdmin cad=ac.getConfigurationAdmin();
Configuration[] confs = null;
if (cad!= null) {
confs = cad.listConfigurations(filter);
refresh();
if (confs == null)
return null;
}
String[] result = new String[confs.length];
for (int i = 0; i < confs.length; i++)
result[i] = this.getObjectName(confs[i]);
return result;
}
/**
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#getConfiguration(java.lang.String)
*/
public String getConfiguration(String pid) throws Exception {
//FIXME this should not be invoked
//if created, the configuration is attached to the management agent's location
ac.debug("ConfigAdmin, getting config for pid: "+pid);
if (pid.indexOf(':') >= 0) throw new IllegalArgumentException("pid not compliant with jmx. Please remove ':' from the pid");
ConfigurationAdmin cad=ac.getConfigurationAdmin();
if (cad != null) {
Configuration config = cad.getConfiguration(pid);
refresh();
return this.getObjectName(config);
} else
return null;
}
/**
* This method gets a configuration object related to a pid and a bundle location
* @param pid Persistent ID
* @param location Bundle location of the service
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#getConfiguration(java.lang.String, java.lang.String)
*/
public String getConfiguration(String pid, String location)
throws Exception {
//":" is reserved in objectnames, as a work around we do not permit pids containing it
if (pid.indexOf(':') >= 0) throw new IllegalArgumentException("pid not compliant with jmx. Please remove ':' from the pid");
ConfigurationAdmin cad=ac.getConfigurationAdmin();
if (cad != null) {
Configuration config = cad.getConfiguration(pid, location);
refresh();
return this.getObjectName(config);
} else
return null;
}
/**
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#createFactoryConfiguration(java.lang.String)
*/
public String createFactoryConfiguration(String pid) throws Exception {
ConfigurationAdmin cad=ac.getConfigurationAdmin();
if (cad != null) {
Configuration conf = cad.createFactoryConfiguration(pid);
refresh();
return this.getObjectName(conf);
} else
return null;
}
/**
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#createFactoryConfiguration(java.lang.String, java.lang.String)
*/
public String createFactoryConfiguration(String pid, String location)
throws Exception {
ConfigurationAdmin cad=ac.getConfigurationAdmin();
if (cad != null) {
Configuration conf = cad.createFactoryConfiguration(pid, location);
refresh();
return this.getObjectName(conf);
} else
return null;
}
/**
* Delete the configurations identified by the LDAP filter
* @param filter LDAP String representing the configurations that want to be deleted
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#deleteConfigurations(java.lang.String)
*/
public void deleteConfigurations(String filter) throws Exception {
ConfigurationAdmin cad=ac.getConfigurationAdmin();
Configuration[] confs = null;
if (cad!= null) {
confs = cad.listConfigurations(filter);
}
if (confs != null)
for (int i = 0; i < confs.length; i++) {
confs[i].delete();
}
refresh();
}
/**
* Removes a property from all the configurations selected by an LDAP expression
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#removePropertyFromConfigurations(java.lang.String, java.lang.String)
*/
public void removePropertyFromConfigurations(String filter, String name)
throws Exception {
ConfigurationAdmin cad=ac.getConfigurationAdmin();
Configuration[] confs = null;
if (cad != null) {
confs = cad.listConfigurations(filter);
}
if (confs != null)
for (int i = 0; i < confs.length; i++) {
Dictionary dic = confs[i].getProperties();
Enumeration keys = dic.keys();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
if (key.equals(name)) {
dic.remove(key);
try {
confs[i].update(dic);
} catch (IOException e) {
ac.error("Unexpected exception", (Exception)e);
}
}
}
}
}
/**
* Updates or adds a property to configurations selected by an LDAP expression
* Arrays and vectors not supported
* @see org.apache.felix.jmood.compendium.ConfigAdminManagerMBean#addPropertyToConfigurations(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
*/
public void addPropertyToConfigurations(
String filter,
String name,
String value,
String type)
throws Exception {
if (isValidType(type)) {
ConfigurationAdmin cad=ac.getConfigurationAdmin();
Configuration[] confs = null;
if (cad != null) {
confs = cad.listConfigurations(filter);
}
if (confs != null)
for (int i = 0; i < confs.length; i++) {
Dictionary dic = confs[i].getProperties();
dic.put(name, castValueToType(type, value));
try {
confs[i].update(dic);
} catch (IOException e) {
ac.error("Unexpected exception", (Exception)e);
}
}
}
}
/**
*
* Validate that the value type is supported
* @param type
*/
protected static boolean isValidType(String type) {
String[] validTypes =
{
"String",
"Integer",
"Long",
"Float",
"Double",
"Byte",
"Short",
"Character",
"Boolean",
"BigInteger",
"BigDecimal" };
for (int i = 0; i < validTypes.length; i++) {
if (validTypes[i].equalsIgnoreCase(type))
return true;
}
return false;
}
protected static Object castValueToType(String type, String value) {
value = value.equals("") ? null : value;
if (type.equals("String")) {
return value == null ? new String() : new String(value);
} else if (type.equals("Integer")) {
return value == null ? new Integer(0) : new Integer(value);
} else if (type.equals("Long")) {
return value == null ? new Long(0) : new Long(value);
} else if (type.equals("Float")) {
return value == null ? new Float(0) : new Float(value);
} else if (type.equals("Double")) {
return value == null ? new Double(0) : new Double(value);
} else if (type.equals("Byte")) {
return value == null ? new Byte("0") : new Byte(value);
} else if (type.equals("Short")) {
return value == null ? new Short("0") : new Short(value);
} else if (type.equals("BigInteger")) {
return value == null ? new BigInteger("0") : new BigInteger(value);
} else if (type.equals("BigDecimal")) {
return value == null ? new BigDecimal(0) : new BigDecimal(value);
} else if (type.equals("Character")) {
return value == null
? new Character('a')
: new Character(value.charAt(0));
} else if (type.equals("Boolean")) {
return value == null ? new Boolean(false) : new Boolean(value);
} else {
// Unsupported type
return null;
}
}
private void registerMBeans() throws Exception{
ConfigurationAdmin cad=ac.getConfigurationAdmin();
if (cad==null) {
ac.debug("could not add any conf mbean, conf admin not available");
return;
}
ac.debug("creating mbeans for existing config objects");
Configuration[] confs = null;
//confs contains the new config objects
//The old ones are in configObjects, whose key is the object name.
confs = cad.listConfigurations(null);
if (confs!=null) {
ac.debug("Existing conf objects: ");
for(int i=0;i<confs.length;i++) {
ac.debug("\t"+confs[i].getPid());
//now we add the new ones
String oname = this.getObjectName(confs[i]);
server.registerMBean(
new ConfigurationDelegate(confs[i], ac),
new ObjectName(oname));
ac.debug("Succesfully registered? "+!server.queryMBeans(new ObjectName(oname), null).isEmpty());
}
}
}
public synchronized void refresh() throws Exception {
//Extremely innefficient but KISS
unregisterMBeans();
registerMBeans();
}
public boolean isAvailable() {
return ac.getConfigurationAdmin()==null?false:true;
}
private void unregisterMBeans() throws MalformedObjectNameException, NullPointerException, InstanceNotFoundException, MBeanRegistrationException{
Set set =
server.queryNames(
new ObjectName(ObjectNames.ALL_CM_OBJECT),
null);
Iterator it = set.iterator();
while (it.hasNext()) {
ObjectName oname=(ObjectName) it.next();
ac.debug("Unregistering config mbean: "+oname);
server.unregisterMBean(oname);
}
}
private String getObjectName(Configuration configuration) {
StringBuffer posfix = new StringBuffer();
posfix.append("pid=" + configuration.getPid());
if (configuration.getFactoryPid() != null)
posfix.append(
",isFactory=true,FactoryPid=" + configuration.getFactoryPid());
else
posfix.append(",isFactory=false");
String oname = ObjectNames.CM_OBJECT + posfix.toString();
return oname;
}
}