Java tutorial
/** * This file is part of JEMMA - http://jemma.energy-home.org * (C) Copyright 2013 Telecom Italia (http://www.telecomitalia.it) * * JEMMA is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License (LGPL) version 3 * or later as published by the Free Software Foundation, which accompanies * this distribution and is available at http://www.gnu.org/licenses/lgpl.html * * JEMMA 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 Lesser General Public License (LGPL) for more details. * */ package org.energy_home.jemma.ah.internal.hac.lib; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.net.URL; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.eclipse.equinox.internal.util.timer.Timer; import org.eclipse.equinox.internal.util.timer.TimerListener; import org.energy_home.jemma.ah.hac.ApplianceException; import org.energy_home.jemma.ah.hac.HacException; import org.energy_home.jemma.ah.hac.IAppliance; import org.energy_home.jemma.ah.hac.IApplianceFactory; import org.energy_home.jemma.ah.hac.ICategory; import org.energy_home.jemma.ah.hac.ILocation; import org.energy_home.jemma.ah.hac.IManagedAppliance; import org.energy_home.jemma.ah.hac.lib.ApplianceFactory; import org.energy_home.jemma.ah.hac.lib.ext.ApplianceManager; import org.energy_home.jemma.ah.hac.lib.ext.Category; import org.energy_home.jemma.ah.hac.lib.ext.IAppliancesProxy; import org.energy_home.jemma.ah.hac.lib.ext.IHacService; import org.energy_home.jemma.ah.hac.lib.ext.INetworkManager; import org.energy_home.jemma.ah.hac.lib.ext.Location; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.FrameworkEvent; import org.osgi.framework.FrameworkListener; import org.osgi.framework.ServiceRegistration; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.InputSource; import org.xml.sax.SAXException; public class HacService implements TimerListener, FrameworkListener, IHacService { private static final Logger LOG = LoggerFactory.getLogger(HacService.class); private static String replaceIvalidPidChars(String appliancePid) { char[] chars = appliancePid.toCharArray(); for (int i = 0; i < chars.length; i++) { if (!Character.isDigit(chars[i]) && !Character.isLetter(chars[i])) chars[i] = '-'; } return new String(chars); } private boolean permitAlternateDefaultConfiguration = false; /** * Dictionary that permits to retrieve the IManagedAppliance service from * its pid */ private Hashtable pid2appliance = new Hashtable(); /** dictionary of currently available IManagedAppliance services */ private Vector appliances = new Vector(); protected Vector installingAppliances = new Vector(); /** dictionary the appliances pids */ private Vector appliancePids = new Vector(); /** DB for Locations */ // private Locations locations = new Locations(); /** DB for Categories */ private Categories categories = new Categories(); static final int saveTimerId = 1; // private PreferencesService prefsService = null; // private HacDriverLocator hacDriverLocator = null; private Timer timer = null; private Vector applianceFactories = new Vector(); private ConfigurationAdmin configAdmin; private Hashtable type2applianceFactory = new Hashtable(); private DocumentBuilderFactory factory; private BundleContext bc; private boolean saveConfigurationToCurrent = true; private static final String servicePid = "org.telecomitalia.hac"; //TODO: check merge, path was empty in 3.3.0 //private final static String SCENARIOS_PATH = "xml/scenarios/"; private final static String SCENARIOS_PATH = ""; private String defaultConfig = "defaultconfig"; private String configurationFilename = "hac-config"; private int saveTimeout = 1; Hashtable factorypids2configuration = new Hashtable(); private Object lockHacService = new Object(); private int newAppliancePid = 0; private Hashtable pid2configurations = new Hashtable(); private LocationsService locationsDb; private ServiceRegistration locationsServiceReg; private boolean useManagedApplianceServiceTracker = true; private ManagedApplianceServiceTracker managedApplianceServiceTracker = null; // private CoreAppliance coreAppliance = null; private boolean patched = false; // true if an upgrade from 2.2.8 to 3.0.5 (hac.lib) has been detected. private boolean enableUpdatePatch = false; public IApplianceFactory getFactoryFromManagedAppliance(IManagedAppliance appliance) { if (appliance == null) return null; return (IApplianceFactory) type2applianceFactory.get(appliance.getDescriptor().getType()); } protected void activate(ComponentContext ctxt) { synchronized (lockHacService) { this.bc = ctxt.getBundleContext(); if (permitAlternateDefaultConfiguration) { String defaultConfigProp = this.bc.getProperty("org.telecomitalia.hac.configuration"); if (defaultConfigProp != null) { defaultConfig = defaultConfigProp; } } this.createLocationService(); loadCurrentConfig(); this.bc.addFrameworkListener(this); if (useManagedApplianceServiceTracker) { this.managedApplianceServiceTracker = new ManagedApplianceServiceTracker(bc, this); this.managedApplianceServiceTracker.open(); } // Core appliance no more used (now exported service clusters have been implemented by AppliancesProxy) // try { // coreAppliance = new CoreAppliance(); // coreAppliance.start(bc); // } catch (ApplianceException e) { // log.error("Error while creating core appliance", e); // } } } private void createLocationService() { locationsDb = new LocationsService(); locationsDb.setConfigurationAdmin(configAdmin); Dictionary props = new Hashtable(); props.put(Constants.SERVICE_PID, "org.energy_home.jemma.osgi.ah.hac.locations"); locationsServiceReg = bc.registerService(ManagedServiceFactory.class.getName(), locationsDb, props); } private void disposeLocationService() { if (locationsServiceReg != null) { locationsDb.unsetConfigurationAdmin(configAdmin); locationsServiceReg.unregister(); locationsDb = null; } } protected void deactivate(ComponentContext ctxt) { synchronized (lockHacService) { disposeLocationService(); Led.setLed(0); this.bc.removeFrameworkListener(this); LOG.debug("deactivated"); // coreAppliance.stop(); if (this.managedApplianceServiceTracker != null) this.managedApplianceServiceTracker.close(); } } public void modified(ComponentContext ctxt, Map props) { synchronized (lockHacService) { update(props); } } public void setDocumentBuilderFactory(DocumentBuilderFactory r) { synchronized (lockHacService) { factory = r; factory.setValidating(false); factory.setNamespaceAware(false); factory.setCoalescing(false); } } public void unsetDocumentBuilderFactory(DocumentBuilderFactory r) { synchronized (lockHacService) { if (factory == r) factory = null; } } /** * Called by DS when a new IManagedAppliance service is detected in OSGi * * @param appliance * The IManagedAppliance service object * @throws ApplianceException */ public void setManagedAppliance(IManagedAppliance appliance, Map appProps) throws ApplianceException { synchronized (lockHacService) { /* * Internally to the hac applications are identified by their pid * that should be unique and persistent. * * This helps to maintain a coherence when the HAC or an Appliance * is restarted. */ String appliancePid = appliance.getPid(); if (appliancePid == null) { LOG.warn("the managed appliance doesn't have an associated pid, discarding it!"); return; } if (!pid2appliance.contains(appliancePid)) { pid2appliance.put(appliancePid, appliance); } else { LOG.warn("discarding appliance because it has a duplicated appliance.pid"); return; } String appStatus = (String) appProps.get("ah.status"); if (appStatus != null && (appStatus.equals("installing"))) { LOG.debug("New appliance to install detected: " + appliancePid); installingAppliances.add(appliance); } else { appliances.add(appliance); } ((ApplianceManager) appliance.getApplianceManager()).setHacService(this); String applianceName = null; Configuration c; try { c = getApplianceCAConfiguration(appliancePid); } catch (Exception e) { LOG.warn(e.getMessage(), e); return; } applianceName = (String) appProps.get(IAppliance.APPLIANCE_NAME_PROPERTY); // If no name is assigned to the appliance, a unique name is // created and assigned if (applianceName == null) { if (c == null) { String factoryPid = (String) appProps.get(IAppliance.APPLIANCE_TYPE_PROPERTY); if (factoryPid == null) { if (!appliance.isSingleton()) LOG.debug( "the appliance doesn't have the ah.app.type property set and is not a singleton"); return; } IApplianceFactory applianceFactory = this.getApplianceFactory(factoryPid); if (applianceFactory == null) { LOG.debug("no factory for type " + factoryPid); return; } try { Configuration[] configurations = this.getApplianceCAConfigurations(appliancePid); if (configurations == null) { c = this.configAdmin.createFactoryConfiguration(factoryPid, null); LOG.debug("created configuration for appliance.pid " + appliancePid); } } catch (Exception e) { LOG.warn(e.getMessage(), e); return; } } Dictionary props = new Hashtable(); for (Iterator iterator = appProps.keySet().iterator(); iterator.hasNext();) { Object type = (Object) iterator.next(); props.put(type, appProps.get(type)); } if (applianceName == null) { String namePrefix = appliance.getDescriptor().getFriendlyName(); applianceName = createUniqueName(namePrefix); props.put(IAppliance.APPLIANCE_NAME_PROPERTY, applianceName); } try { c.update(props); } catch (IOException e) { LOG.debug(e.getMessage()); } } } } protected void unsetManagedAppliance(IManagedAppliance appliance) { synchronized (lockHacService) { String appliancePid = appliance.getPid(); if (appliancePid == null) { return; } appliancePids.remove(appliancePid); pid2appliance.remove(appliancePid); appliances.remove(appliance); installingAppliances.remove(appliance); } } protected void updatedManagedAppliance(IManagedAppliance appliance, final Map props) { LOG.debug("called updated method"); // this method is called when the service properties are updated synchronized (lockHacService) { String appliancePid = appliance.getPid(); if (appliancePid == null) { LOG.warn("the managed appliance doesn't have an associated pid, discarding it!"); return; } Object a = pid2appliance.get(appliancePid); if (a == null) { LOG.debug("updated unknown appliance " + appliancePid); return; } String appStatus = (String) props.get("ah.status"); if (appStatus != null && (appStatus.equals("installing"))) { // !!!Multieps: a concurrent update can occur (device access and // configuration admin can concurrenlty attach and update the // application) LOG.debug("appliance with installing state detected. Why? The appliance pid is " + appliancePid); return; } else { // !!!Multieps: a concurrent update can occur (device access and // configuration admin can concurrently attach and update the // application) if (installingAppliances.contains(appliance)) installingAppliances.remove(appliance); if (!appliances.contains(appliance)) { appliances.add(appliance); } } } } private Configuration getApplianceCAConfiguration(String appliancePid) throws Exception { Configuration[] configurations; configurations = this.configAdmin.listConfigurations("(appliance.pid=" + appliancePid + ")"); if (configurations == null) { return null; } return configurations[0]; } private Configuration[] getApplianceCAConfigurations(String appliancePid) throws Exception { return this.configAdmin.listConfigurations("(appliance.pid=" + appliancePid + ")"); } public void setConfigurationAdmin(ConfigurationAdmin configAdmin) { synchronized (lockHacService) { this.configAdmin = configAdmin; } } public void unsetConfigurationAdmin(ConfigurationAdmin configAdmin) { synchronized (lockHacService) { if (this.configAdmin == configAdmin) { this.configAdmin = null; } } } public void setApplianceFactory(IApplianceFactory s, Map props) throws HacException { synchronized (lockHacService) { String type = (String) props.get("service.pid"); if ((type == null) || (type != null) && (type.length() == 0)) { LOG.debug("the appliance factory doesn't have the service.pid set"); throw new HacException("type missing in appliance factory " + s.getName()); } if (type2applianceFactory.get(type) != null) { LOG.debug("two different appliance factories serve the same type '" + s.getDescriptor().getType() + "'"); return; } applianceFactories.add(s); type2applianceFactory.put(type, s); s.init(); } } public void unsetApplianceFactory(IApplianceFactory s) { synchronized (lockHacService) { String type = s.getDescriptor().getType(); applianceFactories.remove(s); type2applianceFactory.remove(type); LOG.debug("removed IApplianceType " + type); } } public void setTimer(Timer timer) { synchronized (lockHacService) { this.timer = timer; } } public void unsetTimer(Timer timer) { synchronized (lockHacService) { if (this.timer == timer) this.timer = null; } } protected synchronized Dictionary getAvailableConfigurations(String type) { Dictionary configurations = (Dictionary) factorypids2configuration.get(type); return configurations; } /** * Creates a factory configuration object if it doesn't exist, yet * * @param type * @param pid * @param props */ protected void createConfiguration(String factoryPid, String pid, Dictionary props) { if (pid == null) pid = generatePid(); Configuration c = null; LOG.debug("adding configuration for appliance " + pid); try { Configuration[] configurations = getApplianceCAConfigurations(pid); if (configurations == null) { c = this.configAdmin.createFactoryConfiguration(factoryPid, null); // remove old property service.pid props.remove(Constants.SERVICE_PID); props.put("appliance.pid", pid); LOG.debug("created configuration for appliance.pid " + pid); c.update(props); } } catch (Exception e) { LOG.warn(e.getMessage(), e); } } /** * Create an appliance given its type (i.e. factory type) and properties. * The props dictionary may be filled with the properties that have to be * assigned to the new appliance. * * @param factoryPid * The type of the new appliance * @param props * The properties of the new appliance * @return the pid of the newly created appliance. */ protected String createApplianceByFactory(String factoryPid, Dictionary props) throws HacException { synchronized (lockHacService) { ApplianceFactory applianceFactoryService = this.getApplianceFactory(factoryPid); if (applianceFactoryService == null) throw new HacException("unable to find an appliance factory for type '" + factoryPid + "'"); // check if the property dictionary contains the ah.app.name // property String friendlyName = applianceFactoryService.getDescriptor().getFriendlyName(); String pid; if (friendlyName != null) { pid = generateUniquePid(friendlyName); } else { pid = this.generatePid(); } if ((props.get(IAppliance.APPLIANCE_NAME_PROPERTY) == null) && (friendlyName != null)) { String name = createUniqueName(friendlyName); props.put(IAppliance.APPLIANCE_NAME_PROPERTY, name); } createConfiguration(factoryPid, pid, props); return pid; } } protected void deleteConfiguration(String type, String pid) { LOG.debug("delete configuration for device " + pid); Dictionary configurations = getAvailableConfigurations(type); if (configurations != null) { configurations.remove(pid); } } /** * Retrieves the last saved configuration or the default one if not * available. */ private void loadCurrentConfig() { boolean res = loadConfiguration(configurationFilename, true); if (!res) { /* switch to factory default */ if ((defaultConfig != null) && !defaultConfig.equals("")) { LOG.debug("no saved configuration found, try to load '" + defaultConfig + "'"); if (loadConfiguration(defaultConfig, false)) { // log.debug("configuration '" + defaultConfig + // "' loaded successfully"); } else { LOG.debug("no saved configuration found and unable to read configuration '" + defaultConfig + "'"); } } else { LOG.debug( "no saved configuration found and no configuration specified. Skip loading configuration"); } } } /** * Stores the current hac configuration */ protected void storeCurrentConfiguration() { takeConfigurationSnapshot(configurationFilename); } protected void timerStart(int event, int timePeriod) { Timer time = (Timer) getTimer(); time.notifyAfter(this, timePeriod, event); } protected Timer getTimer() { return timer; } protected void timerCancel(int event) { Timer time = (Timer) getTimer(); time.removeListener(this, event); } private String generatePid() { return Integer.toString(newAppliancePid++); } private String generateUniquePid(String prefix) { int count = 1; String generatedPid; while (true) { // Multieps: modified pid format with prefix used in hap service to // identify an appliance pid generatedPid = "ah.app." + replaceIvalidPidChars(prefix) + Integer.toString(count); Vector app = browseAppliances(IAppliance.APPLIANCE_PID_PROPERTY_KEY, generatedPid); if (app.size() == 0) { break; } count++; } return generatedPid; } public String createUniqueName(String rootName) { int count = 1; String proposedName; Vector applNames; while (true) { proposedName = rootName + " " + Integer.toString(count); applNames = browseAppliances(IAppliance.APPLIANCE_NAME_PROPERTY_KEY, proposedName); if (applNames.size() == 0) { // found a not used name break; } count++; } return proposedName; } /* * HacService interface-related methods */ protected boolean add(IManagedAppliance managedAppliance) { if (appliances.indexOf(managedAppliance) != -1) { return true; } Iterator it = appliances.iterator(); String name = managedAppliance.getDescriptor().getType(); boolean found = false; while (it.hasNext()) { IManagedAppliance d = (IManagedAppliance) it.next(); if (name == d.getDescriptor().getType()) { found = true; break; } } if (found) { LOG.debug("device names must be unique"); return false; } appliances.add(managedAppliance); // objects.put(new Integer(managedAppliance.hashCode()), // managedAppliance); pid2appliance.put(managedAppliance.getPid(), managedAppliance); return true; } public Vector getAppliances() { synchronized (lockHacService) { Vector list = new Vector(); for (Iterator iterator = appliances.iterator(); iterator.hasNext();) { IAppliance object = (IAppliance) iterator.next(); list.add(object.getPid()); } return list; } } public Vector browseAppliances(int key_type, String key_value) { synchronized (lockHacService) { Vector result = new Vector(); LOG.debug("called browseDevices"); IManagedAppliance d = null; if (key_type == IAppliance.APPLIANCE_TYPE_PROPERTY_KEY) { if (key_value.compareTo("") == 0) { // return the list of devices as it is! return appliances; } Iterator it = appliances.iterator(); while (it.hasNext()) { d = (IManagedAppliance) it.next(); if ((d.getDescriptor().getType() != null) && (d.getDescriptor().getType().compareTo(key_value) == 0)) { result.add(d); } } } else if (key_type == IAppliance.APPLIANCE_LOCATION_PID_PROPERTY_KEY) { // returns the list of devices at the specific location if (key_value.compareTo("") == 0) { return appliances; } Iterator it = appliances.iterator(); while (it.hasNext()) { d = (IManagedAppliance) it.next(); if (d != null) { String locationPid = (String) d.getConfiguration() .get(IAppliance.APPLIANCE_LOCATION_PID_PROPERTY); if (locationPid != null && locationPid.equals(key_value)) result.add(d); } } } else if (key_type == IAppliance.APPLIANCE_CATEGORY_PID_PROPERTY_KEY) { // returns the list of devices at the specific location if (key_value.compareTo("") == 0) { return appliances; } Iterator it = appliances.iterator(); while (it.hasNext()) { d = (IManagedAppliance) it.next(); if (d != null) { String categoryPid = (String) d.getConfiguration() .get(IAppliance.APPLIANCE_CATEGORY_PID_PROPERTY); if (categoryPid != null && categoryPid.equals(key_value)) result.add(d); } } } else if (key_type == IAppliance.APPLIANCE_NAME_PROPERTY_KEY) { // returns the list of devices at the specific location if (key_value.compareTo("") == 0) { return appliances; } Iterator it = appliances.iterator(); while (it.hasNext()) { d = (IManagedAppliance) it.next(); if (d != null) { Dictionary c = d.getConfiguration(); String name = (String) c.get(IAppliance.APPLIANCE_NAME_PROPERTY); if (name != null && name.equals(key_value)) result.add(d); } } } else if (key_type == IAppliance.APPLIANCE_PID_PROPERTY_KEY) { IAppliance appliance = (IAppliance) this.pid2appliance.get(key_value); if (appliance != null) result.add(appliance); } return result; } } public ILocation[] getLocations() { synchronized (lockHacService) { return this.locationsDb.getLocations(); } } public ICategory[] getCategories() { synchronized (lockHacService) { return categories.getCategories(); } } public Location addLocation(Location location) throws HacException { synchronized (lockHacService) { return this.locationsDb.add(location); } } public void addCategory(ICategory category) throws HacException { synchronized (lockHacService) { categories.add(category); this.configUpdated(); } } protected void configUpdated() { this.saveConfigurationDelayed(); } public boolean removeAppliance(String appliancePid) { if (appliancePid.equals(IAppliancesProxy.PROXY_APPLIANCE_PID)) throw new IllegalArgumentException("Appliances proxy appliance cannot be deleted!"); synchronized (lockHacService) { IManagedAppliance appliance = (IManagedAppliance) this.pid2appliance.get(appliancePid); this.removeDevice(appliance); if (appliance != null) { try { Configuration configuration = this.getApplianceCAConfiguration(appliancePid); if (configuration != null) { configuration.delete(); } return true; } catch (Exception e) { LOG.warn(e.getMessage(), e); } } return false; } } public boolean removeDevice(IManagedAppliance device) { synchronized (lockHacService) { if (appliances.contains(device)) { appliances.remove(device); return true; } return false; } } /** * Hac drivers can be connected each other if they are compatible each * other. In order to be compatible they should have in common at least one * cluster id. * * * @return */ public Vector getConnectableDevices() { synchronized (lockHacService) { return null; } } public void timer(int event) { switch (event) { case saveTimerId: saveConfiguration(); break; } } /** * * @param props */ private void update(Map props) { LOG.debug("received configuration"); // boolean enableAutoInstall = getProperty(props, // PROP_ENABLE_AUTOINSTALL, DEFAULT_ENABLE_AUTOINSTALL); // enableAutoInstall } public void clean() { synchronized (lockHacService) { try { Configuration[] configurations = configAdmin.listConfigurations("(appliance.pid=*)"); if (configurations != null) for (int i = 0; i < configurations.length; i++) { configurations[i].delete(); } } catch (IOException e) { LOG.warn("exception deleting configurations", e); } catch (Exception e) { LOG.warn("exception deleting configurations", e); } categories.clear(); locationsDb.clear(); this.saveConfiguration(); } } protected boolean saveConfiguration() { return saveConfiguration(configurationFilename); } /** * Save the current configuration after the specified delay. If this method * is called again within the delay, the timer is rearmed. * * @param delay * Delay in seconds */ protected void saveConfigurationDelayed() { timerCancel(saveTimerId); if (saveConfigurationToCurrent) { timerStart(saveTimerId, saveTimeout); } } protected boolean saveConfiguration(String configName) { timerCancel(saveTimerId); return takeConfigurationSnapshot(configName); } protected ApplianceFactory getApplianceFactory(String type) { return (ApplianceFactory) type2applianceFactory.get(type); } /** * Takes a snapshot of the current configuration and name it 'configName' */ protected boolean takeConfigurationSnapshot(String configName) { Document doc = createDoc(); Element configurationEl = doc.createElement("configuration"); doc.appendChild(configurationEl); Element categoriesEl = doc.createElement("categories"); configurationEl.appendChild(categoriesEl); Iterator it = categories.iterator(); Category category = null; while (it.hasNext()) { category = (Category) it.next(); Element categoryEl = doc.createElement("category"); categoriesEl.appendChild(categoryEl); categoryEl.setAttribute("pid", category.getPid()); categoryEl.setAttribute("name", category.getName()); categoryEl.setAttribute("icon", category.getIconName()); } String xmlConfig = doc2xmlString(doc); if (LOG.isDebugEnabled()) LOG.debug(xmlConfig); // save the configuration on the filesystem File configFile = bc.getDataFile(SCENARIOS_PATH + configName + ".xml"); if (LOG.isDebugEnabled()) { LOG.debug("saving configuration into " + configFile.getPath()); } if (!configFile.isFile()) { try { // check if the parent directory exists, otherwise create it and // all the parent dirs File scenariosDir = configFile.getParentFile(); if (!scenariosDir.exists()) { scenariosDir.mkdirs(); } // create the file if (!configFile.createNewFile()) { return false; } } catch (IOException e1) { LOG.warn("unable to create file " + configFile.getPath(), e1); return false; } } FileOutputStream fos; try { fos = new FileOutputStream(configFile); fos.write(xmlConfig.getBytes()); fos.close(); } catch (FileNotFoundException e) { LOG.warn("unable to open file " + configFile + " for writing.", e); return false; } catch (IOException e) { LOG.warn("unable to write file " + configFile, e); return false; } LOG.debug("configuration '" + configName + "' saved successfully"); return true; } // private void prop2dom(Document doc, Element father, String name, Object // value) { // Element el = null; // // if (name != null) { // el = doc.createElement("property"); // el.setAttribute("name", name); // } else { // el = doc.createElement("item"); // } // // father.appendChild(el); // // String text; // if (value instanceof String) { // text = value.toString(); // setTextContent(doc, el, text); // } else if (value instanceof AttributeValue) { // text = value.toString(); // setTextContent(doc, el, text); // } else if (value instanceof Vector) { // Vector v = (Vector) value; // for (int i = 0; i < v.size(); i++) { // Object item = v.get(i); // prop2dom(doc, el, null, item); // } // } else { // log.warn("property '" + value.getClass().getName() + // "'is of an unsupported class"); // return; // } // // el.setAttribute("type", value.getClass().getName()); // } /** * Load HAC configuration. It is useful to describe the algorithm used to * instantiate the virtual appliances trough virtual appliances factory * services Each <va></va> section contains the properties of the virtual * appliance that the section represents. The load procedure stores all * these properties and tries to match them in an already installed bundles * or to download them on demand. * * The procedure for doing that is identical to the Device Attachment * Algorithm described in the "Device Access Specification v1.1" The * HacService implements the DeviceLocator interface but doesn't register * it. * * * 1. If a DRIVER_ID property is present, the algorithm tries to locate an * already registered IApplianceType service exposing the same DERVICE_ID * property. If such an IApplianceType service is not found, an attempt to * download the maching driver bundle. If the * * * @param configName * Filename. The filename must not include the .xml extension * * @param storageArea * If this parameter is true the configuration file is got from * the r/w data area reserved to the bundle * * @return true if the configuration has been read and applied correctly. In * case of errors returns false */ protected boolean loadConfiguration(String configName, boolean storageArea) { synchronized (lockHacService) { File configFile; InputStream stream = null; if (configName == null) { configName = "defaultconfig"; storageArea = true; } LOG.debug("try to load '" + configName + "'"); try { if (storageArea) { String configFilename = SCENARIOS_PATH + configName + ".xml"; if (getProperty("org.energy_home.jemma.ah.updatepatch", enableUpdatePatch)) { patched = PatchUpdateBug.patchUpdateBugOnHacLib(bc, configFilename); } configFile = bc.getDataFile(configFilename); LOG.debug("storage area is " + configFile); stream = new FileInputStream(configFile); } else { File f = new File(configName); if (f.isAbsolute()) { stream = new FileInputStream(configName); } else { String configFilename = SCENARIOS_PATH + configName + ".xml"; URL url = bc.getBundle().getEntry(configFilename); if (url == null) { LOG.debug("unable to open file " + configFilename); return false; } stream = url.openStream(); } } } catch (FileNotFoundException e) { LOG.warn("no saved configuration '" + configName + "'", e); return false; } catch (IOException e) { LOG.warn("unable to open file " + configName, e); return false; } categories.clear(); try { factory.setNamespaceAware(true); factory.setValidating(false); DocumentBuilder parser = factory.newDocumentBuilder(); Document doc = parser.parse(new InputSource(stream)); // parses the configuration file and updates the current // configuration present in memory traverseConfigurationTree(doc); } catch (IOException e) { LOG.warn(e.getMessage(), e); return false; } catch (SAXException e) { LOG.warn(e.getMessage(), e); return false; } catch (Exception e) { LOG.warn(e.getMessage(), e); return false; } if (stream != null) { try { stream.close(); } catch (IOException e) { LOG.warn(e.getMessage(), e); return false; } } if (patched && (getProperty("it.telecomitalia.ah.updatepatch", enableUpdatePatch))) { PatchUpdateBug.moveFactoryConfigurations(configAdmin, LocationsService.FACTORY_PID); } LOG.debug("loaded successfully the previously saved configuration"); return true; } } public void updated(Dictionary props) throws ConfigurationException { LOG.debug("received props"); } protected String doc2xmlString(Document doc) { final String XML_VERSION = "1.0"; final String XML_ENCODING = "UTF-8"; StringWriter strWriter = null; XMLSerializer probeMsgSerializer = null; OutputFormat outFormat = null; String xmlStr = null; try { probeMsgSerializer = new XMLSerializer(); strWriter = new StringWriter(); outFormat = new OutputFormat(); // Setup format settings outFormat.setEncoding(XML_ENCODING); outFormat.setVersion(XML_VERSION); outFormat.setIndenting(true); outFormat.setIndent(4); // Define a Writer probeMsgSerializer.setOutputCharStream(strWriter); // Apply the format settings probeMsgSerializer.setOutputFormat(outFormat); // Serialize XML Document probeMsgSerializer.serialize(doc); xmlStr = strWriter.toString(); strWriter.close(); } catch (IOException ioEx) { LOG.error("exception: " + ioEx); return null; } return xmlStr; } Node lastNode; Hashtable properties; Object prop; private boolean loadLocations = false; private boolean loadAppliances = false; protected void traverseConfigurationTree(Node node) { lastNode = node; int nodeType = node.getNodeType(); switch (nodeType) { case Node.DOCUMENT_NODE: traverseConfigurationTree(((Document) node).getDocumentElement()); break; // print element with attributes case Node.ELEMENT_NODE: NamedNodeMap attrs = node.getAttributes(); String tag = node.getNodeName(); if ((tag == "location") && (loadLocations)) { String name = attrs.getNamedItem("name").getNodeValue(); String icon = attrs.getNamedItem("icon").getNodeValue(); String pid = attrs.getNamedItem("pid").getNodeValue(); try { this.locationsDb.add(new Location(pid, name, icon)); } catch (HacException e) { // this is a duplicate location, skip it by putting a log // message LOG.warn("error while adding location found reading configuration file", e); } } if (tag == "category") { String name = attrs.getNamedItem("name").getNodeValue(); String icon = attrs.getNamedItem("icon").getNodeValue(); String pid = attrs.getNamedItem("pid").getNodeValue(); try { categories.add(new Category(pid, name, icon)); } catch (HacException e) { // this is a duplicate location, skip it by putting a log // message LOG.warn("error while adding location found reading configuration file", e); } } else if ((tag == "appliance") && (loadAppliances)) { /* * String name = attrs.getNamedItem("name").getNodeValue(); * if (log.isDebugEnabled()) log.debug("reading va " + name); */ properties = new Hashtable(); } else if ((tag == "property") && (lastNode != null) && (properties != null)) { // log.debug("last node is " + lastNode.getNodeName()); String name = attrs.getNamedItem("name").getNodeValue(); // Node item = attrs.getNamedItem("type"); // String type = null; // // if (item != null) { // type = item.getNodeValue(); // } Object propValue = traversePropertyNode(lastNode); if (propValue == null) { LOG.debug("null property " + name); } else { properties.put(name, propValue); } } NodeList children = node.getChildNodes(); if (children != null) { int len = children.getLength(); for (int i = 0; i < len; i++) { traverseConfigurationTree(children.item(i)); } if (tag.equals("appliance")) { // we traversed all appliances children, its time to // instantiate the // driver try { String appliancePid = (String) properties.get(Constants.SERVICE_PID); if (appliancePid == null) { // for backward compatibility appliancePid = (String) properties.get(IAppliance.APPLIANCE_PID); } String type = (String) properties.get(IAppliance.APPLIANCE_TYPE_PROPERTY); if ((appliancePid != null) && (type != null)) { String locationPid = (String) properties .get(IAppliance.APPLIANCE_LOCATION_PID_PROPERTY); String categoryPid = (String) properties .get(IAppliance.APPLIANCE_CATEGORY_PID_PROPERTY); if ((locationPid != null) && (this.locationsDb.getByPid(locationPid) == null)) { LOG.debug("WARNING: device " + servicePid + " specifies an unknown location pid"); } else if ((categoryPid != null) && (this.categories.getCategoryByPid(categoryPid) == null)) { LOG.debug("WARNING: device " + servicePid + " specifies an unknown category pid"); } else { createConfiguration(type, appliancePid, properties); } } else { LOG.debug("during reading configuration: unable to retrieve driver pid"); } } catch (Exception e) { LOG.warn(e.getMessage(), e); } } } break; case Node.TEXT_NODE: break; } } private Object traversePropertyNode(Node node) { int nodeType = node.getNodeType(); switch (nodeType) { // print element with attributes case Node.ELEMENT_NODE: NamedNodeMap attrs = node.getAttributes(); String tag = node.getNodeName(); Node item = attrs.getNamedItem("type"); String type = null; if (item != null) { type = item.getNodeValue(); } if (tag.equals("item") || tag.equals("property")) { if (type == null) { return getTextContent(node); } else if (type.equals("java.lang.String")) { return getTextContent(node); } else if (type.equals("java.util.Vector")) { NodeList children = node.getChildNodes(); int len = children.getLength(); Vector container = new Vector(); for (int i = 0; i < len; i++) { Object res = traversePropertyNode(children.item(i)); if (res != null) { container.add(res); LOG.debug("added to vector " + res.toString()); } } return container; } } } return null; } private String getTextContent(Node node) { NodeList childs = node.getChildNodes(); for (int i = 0; i < childs.getLength(); i++) { Node child = childs.item(i); int nodeType = child.getNodeType(); switch (nodeType) { case Node.TEXT_NODE: return child.getNodeValue(); } } return null; } private void setTextContent(Document doc, Node node, String text) { Text textNode = doc.createTextNode(text); node.appendChild(textNode); } public void frameworkEvent(FrameworkEvent fe) { if (fe.getType() == FrameworkEvent.STARTED) { // loadCurrentConfig(); // applyConfigurations(); Led.setLed(1); } if (LOG.isDebugEnabled()) { LOG.debug(fe.toString() + " type " + fe.getType()); } } public Location getLocation(String locationPid) { synchronized (lockHacService) { return this.locationsDb.getByPid(locationPid); } } public Category getCategory(String categoryPid) { synchronized (lockHacService) { return this.categories.getCategoryByPid(categoryPid); } } public void updateLocation(Location location) { // TODO: not yet implemented } // public boolean updateConfiguration() { // synchronized (lockHacService) { // Iterator it = appliances.iterator(); // // String data = "[ "; // // while (it.hasNext()) { // IManagedAppliance appliance = (IManagedAppliance) it.next(); // IApplianceFactory applianceFactory = // getFactoryFromManagedAppliance(appliance); // String info; // // try { // // // convert info to json // info = "{"; // // if (appliance.getAttachedDevice().getPid() != null) { // info += "\"ieee_address\": \"" + appliance.getAttachedDevice().getPid() + // "\", "; // } else { // continue; // } // // info += "\"name\": \"" + appliance.getDescriptor().getType() + "\""; // // Location location = null; // String locationPid = (String) // appliance.getConfig().get(IApplianceManager.APPLIANCE_LOCATION_PID_PROPERTY); // if (locationPid != null) { // location = this.locationsDb.getByPid(locationPid); // } // // if (location != null) { // info += ", \"location\": \"" + location.getName() + "\""; // } // Category category = null; // String categoryPid = (String) // appliance.getConfig().get(IApplianceManager.APPLIANCE_CATEGORY_PID_PROPERTY); // if (categoryPid != null) { // category = this.categories.getCategoryByPid(categoryPid); // info += ", \"category\": \"" + category.getName() + "\""; // } // // info += "}"; // // data += info; // } catch (Exception e) { // continue; // } // } // data += " ]"; // // boolean result = postConfiguration(data); // if (result) { // log.info("configuration successfully sent to WSNC"); // } else { // log.error("sending configuration to WSNC"); // } // // return result; // } // } public boolean postConfiguration(String data) { synchronized (lockHacService) { // url of the energy at home application String applUrl = bc.getProperty("org.energy_home.jemma.energyathome.url"); if (applUrl == null) { applUrl = "http://163.162.180.229:8282/energyathome"; } String wsncId = bc.getProperty("org.telecomitalia.gal.wsnc.id"); if (wsncId == null) { return false; } HttpClient client = new HttpClient(); PostMethod method = new PostMethod(applUrl + "/store?n=" + wsncId); InputStream inputStream = null; method.setRequestEntity(new StringRequestEntity(data)); // Execute the method. int statusCode = 0; try { statusCode = client.executeMethod(method); } catch (HttpException e) { LOG.warn(e.getMessage(), e); return false; } catch (IOException e) { LOG.warn(e.getMessage(), e); return false; } if (statusCode != HttpStatus.SC_OK) { LOG.warn("method failed: " + method.getStatusLine()); return false; } String responseBody = null; try { responseBody = method.getResponseBodyAsString(); } catch (IOException e1) { LOG.warn(e1.getMessage(), e1); return false; } if (LOG.isDebugEnabled()) LOG.debug(new String(responseBody)); return true; } } private static String removeExtension(String s) { String separator = System.getProperty("file.separator"); String filename; // Remove the path upto the filename. int lastSeparatorIndex = s.lastIndexOf(separator); if (lastSeparatorIndex == -1) { filename = s; } else { filename = s.substring(lastSeparatorIndex + 1); } // Remove the extension. int extensionIndex = filename.lastIndexOf("."); if (extensionIndex == -1) return filename; return filename.substring(0, extensionIndex); } private Vector listConfigurations(boolean builtIn) { Vector configurations = new Vector(); if (builtIn) { // gets demos present in the RO area Enumeration paths = bc.getBundle().getEntryPaths(SCENARIOS_PATH); while (paths.hasMoreElements()) { String path = (String) paths.nextElement(); if (path.endsWith(".xml")) { // xml file File f = new File(path); String name = removeExtension(f.getName()); configurations.add(name); } } } if (!builtIn) { // read in storage area (i.e. user scenarios) File scenariosDir = bc.getDataFile(SCENARIOS_PATH); String[] files = scenariosDir.list(); for (int i = 0; i < files.length; i++) { if (files[i].endsWith(".xml")) { String name = removeExtension(files[i]); configurations.add(name); } } } return configurations; } public synchronized boolean reset(int level) { synchronized (lockHacService) { if (level == 0) { try { this.clean(); File configFilesDirectory = bc.getDataFile(SCENARIOS_PATH); if (LOG.isDebugEnabled()) { LOG.debug("deleting directory " + configFilesDirectory.getPath()); } boolean deleted = false; if (configFilesDirectory.isDirectory()) { deleted = deleteDirectory(configFilesDirectory); } } catch (Exception e) { LOG.warn("during reset exception contains '" + e.getMessage() + "'", e); return false; } } else if (level == 1) { try { int time = 4; LOG.debug("shutdown in " + (time * 60) + " seconds"); String osName = System.getProperty("os.name"); String shutdownCommand = null; if (osName.equals("Linux")) { shutdownCommand = "/sbin/shutdown now"; } if (shutdownCommand != null) { Runtime.getRuntime().exec(shutdownCommand); return true; } else { return false; } } catch (IOException e) { LOG.warn("exception during shutdown " + e.getMessage(), e); } } else if (level == 2) { this.clean(); } // reset successful return true; } } protected static boolean deleteDirectory(File path) { if (path.exists()) { File[] files = path.listFiles(); for (int i = 0; i < files.length; i++) { if (files[i].isDirectory()) { deleteDirectory(files[i]); } else { files[i].delete(); } } } return (path.delete()); } protected Document createDoc() { DocumentBuilder docBuilder = null; try { docBuilder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { LOG.error(e.getMessage()); return null; } Document doc = docBuilder.newDocument(); return doc; } /****** IAppliancesManager exposed services ******/ // public void updateConfiguration(String pid, Dictionary props) throws // HacException { // synchronized (lockHacService) { // IManagedAppliance managedAppliance = (IManagedAppliance) // pid2appliance.get(pid); // if (managedAppliance == null) // throw new HacException("Auhtorization error: invalid appliance pid"); // // // FIXME: agganciare al configuration admin Service // // saveConfigurationDelayed(); // } // } // // public boolean setConfiguration(String configName) { // return false; // } protected Configuration createFactoryConfiguration(String factoryPid) { FactoryConfigurationImpl configuration = new FactoryConfigurationImpl(factoryPid); this.factorypids2configuration.put(factoryPid, configuration); return configuration; } protected Configuration getConfiguration(String pid) { Configuration configuration = (Configuration) this.pid2configurations.get(pid); if (configuration == null) { // configuration = new ConfigurationImpl(pid); } return configuration; } protected Vector getFactories() { synchronized (lockHacService) { return this.applianceFactories; } } protected IManagedAppliance getAppliance(String appliancePid) { synchronized (lockHacService) { IManagedAppliance appliance = (IManagedAppliance) this.pid2appliance.get(appliancePid); return appliance; } } public String[] getInquiredAppliances() { synchronized (lockHacService) { String[] appliancePids = new String[this.installingAppliances.size()]; for (int i = 0; i < this.installingAppliances.size(); i++) { appliancePids[i] = ((IManagedAppliance) this.installingAppliances.get(i)).getPid(); } return appliancePids; } } public void enableAppliance(String appliancePid) throws HacException { this.installAppliance(appliancePid); } public void installAppliance(String appliancePid, Dictionary props) throws HacException { synchronized (lockHacService) { IManagedAppliance appliance = (IManagedAppliance) this.pid2appliance.get(appliancePid); if (appliance == null) { throw new HacException("an appliance can be installed only if has been already created"); } if (!this.installingAppliances.contains(appliance)) { throw new HacException("an appliance can be installed only if has been already created"); } String factoryPid = (String) props.get(IAppliance.APPLIANCE_TYPE_PROPERTY); IApplianceFactory applianceFactory = this.getApplianceFactory(factoryPid); if (applianceFactory == null) { throw new HacException("unable to find a factory"); } try { Configuration c = this.getApplianceCAConfiguration(appliancePid); if (c == null) { c = this.configAdmin.createFactoryConfiguration(factoryPid, null); // FIXME: la seguente riga deve essere scommentata? // overwrite // any property service.pid // props.remove(Constants.SERVICE_PID); props.put("appliance.pid", appliancePid); LOG.debug("created configuration for appliance.pid " + appliancePid); } // remove the ah.status properties to force appliance // installation props.remove("ah.status"); c.update(props); this.installingAppliances.remove(appliance); } catch (Exception e) { LOG.debug(e.getMessage()); throw new HacException("unable to install appliance"); } } } public void installAppliance(String appliancePid) throws HacException { synchronized (lockHacService) { IManagedAppliance appliance = (IManagedAppliance) this.pid2appliance.get(appliancePid); if (appliance == null) { throw new HacException("an appliance can be installed only if has been already created"); } if (!this.installingAppliances.contains(appliance)) { throw new HacException("an appliance can be installed only if has been already created"); } try { Configuration c = this.getApplianceCAConfiguration(appliancePid); if (c == null) { throw new HacException("an appliance can be installed only if has been already created"); } Dictionary props = c.getProperties(); // remove the ah.status properties to force appliance // installation props.remove("ah.status"); c.update(props); this.installingAppliances.remove(appliance); } catch (Exception e) { LOG.debug(e.getMessage()); throw new HacException("unable to install appliance"); } } } public void updateAppliance(String appliancePid, Dictionary props) throws HacException { synchronized (lockHacService) { IManagedAppliance managedAppliance = (IManagedAppliance) pid2appliance.get(appliancePid); if (managedAppliance == null) throw new HacException("unable to update appliance because it doesn't exist" + appliancePid); Configuration c; try { c = this.getApplianceCAConfiguration(appliancePid); if (c == null) { throw new HacException("unable to update appliance because it doesn't exist" + appliancePid); } this.checkAndUpdateProperties(managedAppliance, c, props); c.update(props); } catch (Exception e) { LOG.debug(e.getMessage()); throw new HacException(e.getMessage()); } } } public void createAppliance(String appliancePid, Dictionary props) throws HacException { if (appliancePid.equals(IAppliancesProxy.PROXY_APPLIANCE_PID)) throw new IllegalArgumentException("Appliances proxy appliance cannot be created!"); synchronized (lockHacService) { IManagedAppliance managedAppliance = (IManagedAppliance) pid2appliance.get(appliancePid); if (managedAppliance != null) throw new HacException("appliance " + appliancePid + " already exists"); Configuration c; try { c = this.getApplianceCAConfiguration(appliancePid); if (c != null) { throw new HacException("appliance " + appliancePid + " already exists"); } String factoryPid = (String) props.get(IAppliance.APPLIANCE_TYPE_PROPERTY); if (factoryPid != null) { c = this.configAdmin.createFactoryConfiguration(factoryPid, null); props.put("appliance.pid", appliancePid); LOG.debug("created factory configuration for appliance.pid " + appliancePid); } else { c = this.configAdmin.getConfiguration(appliancePid); props.put("appliance.pid", appliancePid); LOG.debug("created factory configuration for appliance.pid " + appliancePid); } c.update(props); } catch (Exception e) { LOG.debug(e.getMessage()); throw new HacException(e.getMessage()); } } } //TODO: check merge, method below missing in 3.3.0 private void manageMultiEndPointConfiguration(Dictionary props, Dictionary oldProps, String applianceProperty, String endPointsProperty) { String value = (String) props.get(applianceProperty); String[] values = (String[]) props.get(endPointsProperty); if (values == null) { values = (String[]) oldProps.get(endPointsProperty); } if (value == null && values != null && values.length > 0) { // If no appliance property is present and end point 0 property is present, the appliance property is created/aligned props.put(applianceProperty, values[0]); } if (value != null && values != null && values.length > 0 && !value.equals(values[0])) { // If appliance property is present and end point properties are already present or updated, // all end point corresponding properties are reset to appliance property for (int i = 0; i < values.length; i++) { values[i] = (String) value; } props.put(endPointsProperty, values); } } /** * Checks and adds or updates some properties contained in * the configuration. The props dictionary is changed. * * @param c * The Configuration Admin configuration. * @param props * The new property set * @param name * The name of the property of c that must not be overridden. * @throws HacException */ private void checkAndUpdateProperties(IManagedAppliance managedAppliance, Configuration c, Dictionary props) throws HacException { // don't override the appliance type property. Fatal error if // this property is not set for the appliance Dictionary oldProps = c.getProperties(); String applianceType = (String) oldProps.get(IAppliance.APPLIANCE_TYPE_PROPERTY); if (applianceType == null) { // FIXME: nella configurazione NON compare mai la ah.app.type // property!!!!! Perche? LOG.warn(IAppliance.APPLIANCE_TYPE_PROPERTY + " property not found in record"); } // Restore some key properties: it seems it does not associate to new service registration properties // that are not included in last change to configuration (it also avoid to have some properties // can contains invalid values) props.put(IAppliance.APPLIANCE_TYPE_PROPERTY, managedAppliance.getDescriptor().getType()); props.put(IAppliance.APPLIANCE_PID, managedAppliance.getPid()); props.put(IAppliance.APPLIANCE_EPS_IDS_PROPERTY, managedAppliance.getEndPointIds()); props.put(IAppliance.APPLIANCE_EPS_TYPES_PROPERTY, managedAppliance.getEndPointTypes()); props.put(IAppliance.APPLIANCE_EPS_IDS_PROPERTY, managedAppliance.getEndPointIds()); props.put(IAppliance.APPLIANCE_EPS_TYPES_PROPERTY, managedAppliance.getEndPointTypes()); Dictionary customConfig = managedAppliance.getCustomConfiguration(); if (customConfig != null) { for (Enumeration e = customConfig.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); // Custom properties that are invalid are filtered if (key.startsWith(IAppliance.APPLIANCE_CUSTOM_PROPERTIES_PREXIF)) ; props.put(key, customConfig.get(key)); } } //TODO: check merge, 5 lines below were missing in 3.3.0 // For compatibility with old applications (i.e. green@home), appliance common property is always managed manageMultiEndPointConfiguration(props, oldProps, IAppliance.APPLIANCE_NAME_PROPERTY, IAppliance.END_POINT_NAMES_PROPERTY); manageMultiEndPointConfiguration(props, oldProps, IAppliance.APPLIANCE_CATEGORY_PID_PROPERTY, IAppliance.END_POINT_CATEGORY_PIDS_PROPERTY); manageMultiEndPointConfiguration(props, oldProps, IAppliance.APPLIANCE_LOCATION_PID_PROPERTY, IAppliance.END_POINT_LOCATION_PIDS_PROPERTY); manageMultiEndPointConfiguration(props, oldProps, IAppliance.APPLIANCE_ICON_PROPERTY, IAppliance.END_POINT_LOCATION_PIDS_PROPERTY); } private Map networkManagers = new HashMap(1); public void addNetworkManager(INetworkManager manager, Map properties) { synchronized (networkManagers) { String key = (String) properties.get("network.type"); if (key == null) LOG.debug("addNetworkManager: received invalid network type property"); else { LOG.debug("Adding network manager for " + key); networkManagers.put(key, manager); } } } public void removeNetworkManager(INetworkManager manager, Map properties) { synchronized (networkManagers) { String key = (String) properties.get("network.type"); if (key == null) LOG.debug("removeNetworkManager: received invalid network type property"); else { LOG.debug("Removing network manager for " + key); networkManagers.remove(key); } } } public Dictionary getManagedConfiguration(String appliancePid) { Configuration c = null; try { c = getApplianceCAConfiguration(appliancePid); } catch (Exception e) { LOG.error("getManagedConfiguration(" + appliancePid + ") error", e); } if (c != null) return c.getProperties(); return null; } public boolean isNetworkOpen(String networkType) throws HacException { if (networkType == null) throw new HacException("isNetworkOpen: network type cannot be null"); INetworkManager nm = (INetworkManager) networkManagers.get(networkType); if (nm == null) throw new HacException("isNetworkOpen: network type " + networkType + " not available"); try { return nm.isNetworkOpen(); } catch (Exception e) { String msg = "isNetworkOpen: error while opening network " + networkType; LOG.debug(msg, e); throw new HacException(msg); } } public void openNetwork(String networkType) throws HacException { if (networkType == null) throw new HacException("openNetwork: network type cannot be null"); INetworkManager nm = (INetworkManager) networkManagers.get(networkType); if (nm == null) throw new HacException("openNetwork: network type " + networkType + " not available"); try { nm.openNetwork(); } catch (Exception e) { String msg = "openNetwork: error while opening network " + networkType; LOG.debug(msg, e); throw new HacException(msg); } } public void openNetwork(String networkType, int duration) throws HacException { if (networkType == null) throw new HacException("openNetwork: network type cannot be null"); INetworkManager nm = (INetworkManager) networkManagers.get(networkType); if (nm == null) throw new HacException("openNetwork: network type " + networkType + " not available"); try { nm.openNetwork(duration); } catch (Exception e) { String msg = "openNetwork: error while opening network " + networkType; LOG.debug(msg, e); throw new HacException(msg); } } public void closeNetwork(String networkType) throws HacException { if (networkType == null) throw new HacException("closeNetwork: network type cannot be null"); INetworkManager nm = (INetworkManager) networkManagers.get(networkType); if (nm == null) throw new HacException("closeNetwork: network type " + networkType + " not available"); try { nm.closeNetwork(); } catch (Exception e) { String msg = "closeNetwork: error while opening network " + networkType; LOG.debug(msg, e); throw new HacException(msg); } } public void removeCategory(String categoryPid) throws HacException { synchronized (lockHacService) { categories.remove(categoryPid); } } boolean getProperty(String name, boolean defaultValue) { String value = System.getProperty(name); if (value != null) { if (value.equals("true")) { return true; } else if (value.equals("false")) { return false; } } return defaultValue; } }