Coverage Report - argos.deploy.ComponentManager
 
Classes in this File Line Coverage Branch Coverage Complexity
ComponentManager
0%
0/217
0%
0/82
0
 
 1  
 /*
 2  
 Copyright (c) 2006, University of Tromsø
 3  
 All rights reserved.
 4  
 
 5  
 Redistribution and use in source and binary forms, with or without 
 6  
 modification, are permitted provided that the following conditions are met:
 7  
 
 8  
  * Redistributions of source code must retain the above copyright notice, this list 
 9  
    of conditions and the following disclaimer.
 10  
 
 11  
  * Redistributions in binary form must reproduce the above copyright notice, this 
 12  
    list of conditions and the following disclaimer in the documentation and/or other 
 13  
    materials provided with the distribution.
 14  
 
 15  
  * Neither the name of the University of Tromsø nor the names of its contributors may 
 16  
    be used to endorse or promote products derived from this software without specific 
 17  
    prior written permission.
 18  
 
 19  
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 20  
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
 21  
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
 22  
 SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 23  
 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 24  
 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
 25  
 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 26  
 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 27  
 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 
 28  
 DAMAGE.
 29  
 */
 30  
 
 31  
 package argos.deploy;
 32  
 
 33  
 import java.io.File;
 34  
 import java.lang.management.ManagementFactory;
 35  
 import java.util.ArrayList;
 36  
 import java.util.Collections;
 37  
 import java.util.HashMap;
 38  
 import java.util.List;
 39  
 import java.util.Map;
 40  
 import java.util.logging.Level;
 41  
 import java.util.logging.Logger;
 42  
 
 43  
 import javax.management.MBeanNotificationInfo;
 44  
 import javax.management.MBeanServer;
 45  
 import javax.management.Notification;
 46  
 import javax.management.ObjectName;
 47  
 
 48  
 import argos.Argos;
 49  
 import argos.annotation.Description;
 50  
 import argos.annotation.Impact;
 51  
 import argos.annotation.NotificationInfo;
 52  
 import argos.annotation.NotificationSender;
 53  
 import argos.config.Config;
 54  
 import argos.metadata.CircleException;
 55  
 import argos.metadata.ComponentMetaInfo;
 56  
 import argos.metadata.DependencyMissingException;
 57  
 import argos.metadata.Running;
 58  
 import argos.metadata.ServiceMetaInfo;
 59  
 import argos.naming.NamingService;
 60  
 import argos.proxy.NotificationProxy;
 61  
 import argos.util.graph.Graph;
 62  
 import argos.util.graph.Node;
 63  
 
 64  
 /**
 65  
  * ComponentManager is the control center for Argos, it handles deployment,
 66  
  * redployment and stopping of services. Deployment of new service files is 
 67  
  * done by calling the public method deploy(). When this method is called it 
 68  
  * is assumed that the service is not running already. If the service is already
 69  
  * running the loading of that service will fail. To redploy a service the 
 70  
  * method redeploy() is to be used. <p>
 71  
  * 
 72  
  * Redeploy() will stop the services that are needed to be stopped including 
 73  
  * any depending services before it calls deploy() and brings those services 
 74  
  * up again.<p>
 75  
  * 
 76  
  * Stopping is done in the public method stop(), it will stop the given services
 77  
  * and all services that are dependant on the stopped services.<p>
 78  
  * 
 79  
  * argos.deploy.HotDeployer is the class that will call these methods. 
 80  
  * It is however possible to call control the ComponentManager through JMX. 
 81  
  * For this the methods startService(String filename) and 
 82  
  * startService(String serviceName) has been added. 
 83  
  */
 84  
 
 85  
 @Description("This mbean is responsible to loading and stoping components, in the right order")
 86  
 public class ComponentManager {
 87  0
         private static final Logger logger = Logger.getLogger(ComponentManager.class.getName());
 88  0
         private static ComponentManager singelton = new ComponentManager();
 89  
         
 90  
         /**
 91  
          * This constant is added to notifications when a service has started. 
 92  
          * That means that the micro kernel has done everything it is suppose 
 93  
          * to do to stop the service.
 94  
          */
 95  
         public static final String SERVICE_STARTED = "SERVICE_STARTED";
 96  
         
 97  
         /**
 98  
          * This constant is added to notifications when the micro kernel has 
 99  
          * done everything it is suppose to do to stop the service.
 100  
          */
 101  
         public static final String SERVICE_STOPPED = "SERVICE_STOPPED";
 102  
         
 103  
         /**
 104  
          * This constant is added to notifications when a service is about 
 105  
          * to be loaded. That is after the class loader has been created 
 106  
          * but before any thing else is done.
 107  
          */
 108  
         public static final String SERVICE_LOADING = "SERVICE_LOADING";
 109  
         
 110  
         /**
 111  
          * This constant is added to notifications when a service has failed 
 112  
          * loading.
 113  
          */
 114  
         public static final String SERVICE_FAILED = "SERVICE_FAILED";
 115  
         
 116  
         
 117  
         public static final String COMPONENT_STOPPED = "COMPONENT_STOPPED";
 118  
         
 119  
         public static final String STOPPING_COMPONENT = "STOPPING_COMPONENT";
 120  
         
 121  
         public static final String STOPPING_SERVICE = "STOPPING_SERVICE";
 122  
         
 123  
         /**
 124  
          * NotifictionProxy used to send out events. See constants for 
 125  
          * what events can be sent out.
 126  
          */
 127  
         @NotificationSender public NotificationProxy proxy;
 128  
         
 129  
         private Map<ComponentMetaInfo, ComponentRunner> runners;
 130  
         private long sequence;
 131  
         
 132  
         private ComponentManager() {
 133  0
                 super();
 134  0
                 runners = new HashMap<ComponentMetaInfo, ComponentRunner>();
 135  0
                 sequence = 0;
 136  
                 
 137  0
                 ServiceMetaInfo.cleanUpTempFolder();
 138  0
                 File dir = new File(Argos.TEMP_DIR);
 139  0
                 dir.mkdir();
 140  0
         }
 141  
         
 142  
         @Description("Loads a list of services.")
 143  
         @Impact(Impact.ACTION)
 144  
         public void deploy(List<File> files) {
 145  0
                 List<ServiceMetaInfo> services = new ArrayList<ServiceMetaInfo>();
 146  0
                 for(File file : files) {
 147  
                         try {
 148  0
                                 ServiceMetaInfo meta = new ServiceMetaInfo(file);
 149  0
                                 services.add(meta);
 150  
                         }
 151  0
                         catch (Exception e) {
 152  0
                                 logger.log(Level.SEVERE, "Unable to deploy file " + file.getName() + ": " + 
 153  
                                                 e.getMessage(), e);
 154  0
                                 HotDeployer.getInstance().addIgnore(file);
 155  0
                         }
 156  
                 }
 157  
                 
 158  0
                 deployServices(services);
 159  0
         }
 160  
         
 161  
         private void deployServices(List<ServiceMetaInfo> services) {
 162  
                 //Reset dependencies in case this method is calling itself
 163  0
                 for(ServiceMetaInfo service : services) {
 164  0
                         service.resetDependencies();
 165  
                 }
 166  
                 
 167  
                 //Setup dependencies
 168  0
                 for(ServiceMetaInfo service : services) {
 169  
                         try {
 170  0
                                 service.setupDependencies(services);
 171  
                         }
 172  0
                         catch(DependencyMissingException e) {
 173  0
                                 services.remove(service);
 174  0
                                 service.resetDependencies();
 175  0
                                 HotDeployer.getInstance().addIgnore(service.getFile());
 176  0
                                 logger.log(Level.SEVERE, "Loading " + service.getName() + 
 177  
                                                 " failed: " + e.getMessage(), e);
 178  
                                 //Restart
 179  0
                                 deployServices(services);
 180  0
                                 return;
 181  0
                         }
 182  
                 }
 183  
                 
 184  
                 //Find Service circles
 185  0
                 List<Node> circle = Graph.findCircle(services);
 186  0
                 if(circle != null) {
 187  0
                         logger.severe(CircleException.createExceptionMessage(circle));
 188  0
                         for(Node node : circle) {
 189  0
                                 ServiceMetaInfo service = (ServiceMetaInfo) node;
 190  0
                                 HotDeployer.getInstance().addIgnore(service.getFile());
 191  0
                                 service.resetDependencies();
 192  0
                                 logger.log(Level.SEVERE, "Loading " + service.getName() + " failed.");
 193  0
                         }
 194  
                         //Restart
 195  0
                         services.removeAll(circle);
 196  0
                         deployServices(services);
 197  0
                         return;
 198  
                 }
 199  
                 
 200  
                 //Find component circles
 201  0
                 for(ServiceMetaInfo service : services) {
 202  0
                         circle = Graph.findCircle(service.getComponentMetaInfo());
 203  0
                         if(circle != null) {
 204  0
                                 logger.severe(CircleException.createExceptionMessage(circle));
 205  
                                 //Restart
 206  0
                                 for(Node node : circle) {
 207  0
                                         ComponentMetaInfo comp = (ComponentMetaInfo) node;
 208  0
                                         HotDeployer.getInstance().addIgnore(comp.getService().getFile());
 209  0
                                         services.remove(comp.getService());
 210  0
                                         comp.getService().resetDependencies();
 211  0
                                 }
 212  0
                                 logger.log(Level.SEVERE, "Loading " + service.getName() + "failed.");
 213  0
                                 deployServices(services);
 214  0
                                 return;
 215  
                         }
 216  
                 }
 217  
                 
 218  
                 //Sort
 219  0
                 Collections.sort(services);
 220  
                 
 221  
                 //Start
 222  0
                 for(int i = 0; i < services.size(); i++) {
 223  0
                         ServiceMetaInfo service = services.get(i);
 224  0
                         if(!start(service)) {
 225  0
                                 List<ServiceMetaInfo> deploy = new ArrayList<ServiceMetaInfo>();
 226  0
                                 for(int j = i + 1; j < services.size(); j++) {
 227  0
                                         deploy.add(services.get(j));
 228  
                                 }
 229  0
                                 HotDeployer.getInstance().addIgnore(service.getFile());
 230  0
                                 service.resetDependencies();
 231  0
                                 deployServices(deploy);
 232  0
                                 return;
 233  
                         }
 234  
                 }
 235  0
         }
 236  
         
 237  
         @Impact(Impact.ACTION)
 238  
         @Description("Starts the given service.")
 239  
         public boolean start(ServiceMetaInfo meta) {
 240  0
                 if(meta.isRunning()) {
 241  0
                         logger.warning("Tried starting service " + meta.getName() + " which is already running.");
 242  
                 }
 243  
                 else {
 244  
                         //Create temp file to avoid file locking in windows
 245  0
                         if(!meta.createTempFile()) {
 246  0
                                 return false;
 247  
                         }
 248  
                         
 249  0
                         setupClassLoader(meta);
 250  0
                         send(SERVICE_LOADING, meta);
 251  
                         
 252  
                         //Start components
 253  0
                         List<ComponentMetaInfo> started = new ArrayList<ComponentMetaInfo>();
 254  0
                         List<ComponentMetaInfo> components = meta.getComponentMetaInfo();
 255  0
                         Collections.sort(components);
 256  0
                         for(ComponentMetaInfo comp : components) {
 257  
                                 
 258  0
                                 if(start(comp)) {
 259  0
                                         started.add(comp);
 260  
                                 }
 261  
                                 else {
 262  
                                         //Component loading failed, stopping service
 263  0
                                         logger.severe("Starting " + comp.getName() + " failed.");
 264  0
                                         for(ComponentMetaInfo stopComp : started) {
 265  0
                                                 logger.severe("Stopping " + stopComp.getName() + ".");
 266  0
                                                 stop(stopComp);
 267  
                                         }
 268  0
                                         HotDeployer.getInstance().addIgnore(meta.getFile());
 269  0
                                         send(SERVICE_FAILED, meta);
 270  0
                                         return false;
 271  
                                 }
 272  
                         }
 273  0
                         NamingService.getInstance().addService(meta);
 274  0
                         meta.setRunning(true);
 275  0
                         send(SERVICE_STARTED, meta);
 276  
                         
 277  
                         String logMsg;
 278  0
                         if(meta.getName().startsWith(Config.BANG_BANG)) {
 279  0
                                 logMsg = "BangBang service " + meta + " started.";
 280  
                         }
 281  
                         else {
 282  0
                                 logMsg = "Service " + meta + " was started.";
 283  
                         }
 284  0
                         logger.info(logMsg);
 285  
                 }
 286  0
                 return true;
 287  
         }
 288  
         
 289  
         private boolean start(ComponentMetaInfo meta) {
 290  0
                 if(meta.isRunning()) {
 291  0
                         logger.warning("Tried starting component " + meta.getName() + " which is already running.");
 292  0
                         return true;
 293  
                         
 294  
                 }
 295  
                 else {
 296  0
                         ComponentRunner runner = new ComponentRunner(meta);
 297  0
                         Object component = runner.start();
 298  0
                         if(component == null) {
 299  0
                                 return false;
 300  
                         }
 301  
                         else {
 302  0
                                 runners.put(meta, runner);
 303  0
                                 NamingService.getInstance().addComponent(meta, component);
 304  0
                                 meta.setRunning(true);
 305  0
                                 return true;
 306  
                         }
 307  
                 }
 308  
         }
 309  
         
 310  
         private void setupClassLoader(ServiceMetaInfo meta) {
 311  0
                 List<ServiceMetaInfo> services = new ArrayList<ServiceMetaInfo>();
 312  0
                 for(String service : meta.getDependencies()) {
 313  0
                         ServiceMetaInfo depends = NamingService.getInstance().getServiceByName(service);
 314  0
                         if(depends == null) {
 315  0
                                 logger.severe("Unable to create class loader for service " + meta.getName() + 
 316  
                                                 " dependencies not in place, bug?");
 317  
                         }
 318  
                         else {
 319  0
                                 services.add(depends);
 320  
                         }
 321  0
                 }
 322  
                 
 323  
                 //Remove redundant class loaders (services)
 324  0
                 for(int i = 0; i < services.size(); i++) {
 325  0
                         ServiceMetaInfo s1 = services.get(i);
 326  0
                         for(int j = 0; i < services.size(); j++) {
 327  0
                                 ServiceMetaInfo s2 = services.get(j);
 328  0
                                 if(i == j) {
 329  0
                                         break;
 330  
                                 }
 331  0
                                 if(s1.dependsOn(s2)) {
 332  0
                                         services.remove(j);
 333  0
                                         if(j <= i) {
 334  0
                                                 i--;
 335  
                                         }
 336  0
                                         j--;
 337  
                                 }
 338  
                         }
 339  
                 }
 340  
                 
 341  0
                 List<OpenClassLoader> loaders = new ArrayList<OpenClassLoader>();
 342  0
                 for(ServiceMetaInfo service: services) {
 343  0
                         loaders.add(new OpenClassLoader(service.getClassLoader()));
 344  
                 }
 345  
                 
 346  0
                 if(loaders.isEmpty()) {
 347  0
                         meta.setClassLoader(JarClassloader.getInstance(meta));
 348  
                 }
 349  0
                 else if(loaders.size() == 1) {
 350  0
                         meta.setClassLoader(JarClassloader.getInstance(meta, loaders.get(0)));
 351  
                 }
 352  
                 else {
 353  
                         //Create chain of classloaders
 354  0
                         meta.setClassLoader(JarClassloader.getInstance(meta, new ChainClassLoader(loaders)));
 355  0
                         logger.info("Service " + meta.getName() + " using chain classloader.");
 356  
                 }
 357  0
         }
 358  
         
 359  
         /**
 360  
          * This method will redploy the given files by stopping all the files 
 361  
          * and then deploying them with the deploy method.
 362  
          * 
 363  
          * @param files        Files that will be redeployed
 364  
          */
 365  
         @Description("Redeployes the given services")
 366  
         @Impact(Impact.ACTION)
 367  
         public void redeploy(List<File> files) {
 368  0
                 List<ServiceMetaInfo> metas = new ArrayList<ServiceMetaInfo>();
 369  0
                 for(File file : files) {
 370  0
                         ServiceMetaInfo meta = NamingService.getInstance().getServiceByFile(file);
 371  0
                         if(meta == null) {
 372  0
                                 logger.warning("Cant redploy not loaded file " + file.getName() + ".");
 373  
                         }
 374  
                         else {
 375  0
                                 metas.add(meta);
 376  
                         }
 377  0
                 }
 378  0
                 List<File> stopped = stop(metas);
 379  0
                 List<File> stopped2 = new ArrayList<File>();
 380  0
                 for(File file : stopped) {
 381  0
                         stopped2.add(new File(Config.get(Config.DEFAULT_DEPLOY_FOLDER) + "/" + 
 382  
                                         file.getName()));
 383  
                 }
 384  0
                 deploy(stopped2);
 385  0
         }
 386  
         
 387  
         /**
 388  
          * This methods stops the given services and the services that depends on them.
 389  
          * 
 390  
          * @param metadatas        The services meta information
 391  
          * @return        A list of files (services) that were actually stopped.
 392  
          */
 393  
         @Description("Stops the given services")
 394  
         @Impact(Impact.ACTION)
 395  
         public List<File> stop(List<ServiceMetaInfo> services) {
 396  0
                 List<File> stopped = new ArrayList<File>();
 397  0
                 for(ServiceMetaInfo meta : services) {
 398  0
                         stop(meta, stopped);
 399  
                 }
 400  0
                 return stopped;
 401  
         }
 402  
         
 403  
         private void stop(ServiceMetaInfo service, List<File> files) {
 404  0
                 for(Node node : service.dependsOnThis) {
 405  0
                         stop((ServiceMetaInfo) node, files);
 406  
                 }
 407  0
                 stop(service);
 408  0
                 files.add(service.getTempFile());
 409  0
         }
 410  
         
 411  
         @Impact(Impact.ACTION)
 412  
         @Description("Stops the given service.")
 413  
         public void stop(ServiceMetaInfo service) {
 414  0
                 if(service.isRunning()) {
 415  0
                         send(STOPPING_SERVICE, service);
 416  0
                         stop(service.getComponentMetaInfo());
 417  0
                         service.cleanUp();
 418  0
                         NamingService.getInstance().removeService(service);
 419  0
                         service.setRunning(false);
 420  
                         
 421  0
                         MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
 422  
                         try {
 423  0
                                 ObjectName classLoaderName = new ObjectName("Classloaders:name=" + service.getName());
 424  0
                                 if(!mbeanServer.isRegistered(classLoaderName)) {
 425  0
                                         mbeanServer.unregisterMBean(classLoaderName);
 426  
                                 }
 427  
                         }
 428  0
                         catch(Exception e) {
 429  0
                                 logger.log(Level.WARNING, "Unable to remove classloader for service " + 
 430  
                                                 service.getName(), e);
 431  0
                         }
 432  
                         
 433  0
                         send(SERVICE_STOPPED, service);
 434  0
                         logger.info("Stopped service " + service.getName());
 435  0
                 }
 436  
                 else {
 437  0
                         logger.warning("Trying to stop service " + service.getName() + " that is not running.");
 438  
                 }
 439  0
         }
 440  
         
 441  
         @Impact(Impact.ACTION)
 442  
         @Description("Stops the given component.")
 443  
         public void stop(ComponentMetaInfo component) {
 444  0
                 if(component.isRunning()) {
 445  0
                         ComponentRunner runner = runners.get(component);
 446  0
                         if(runner != null) {
 447  0
                                 send(STOPPING_COMPONENT, component);
 448  0
                                 for(Node temp : component.dependsOnThis) {
 449  0
                                         stop((ComponentMetaInfo) temp);
 450  
                                 }
 451  0
                                 runner.stop();
 452  0
                                 runners.remove(component);
 453  0
                                 NamingService.getInstance().removeComponent(component);
 454  0
                                 component.setRunning(false);
 455  0
                                 logger.info("Stopped component: " + component.getName());
 456  0
                                 send(COMPONENT_STOPPED, component);
 457  
                         }
 458  0
                 }
 459  
                 else {
 460  0
                         logger.warning("Trying to stop component " + component.getName() + " that is not running.");
 461  
                 }
 462  0
         }
 463  
         
 464  
         private void stop(List<ComponentMetaInfo> components) {
 465  0
                 for(ComponentMetaInfo component : components) {
 466  0
                         stop(component);
 467  
                 }
 468  0
         }
 469  
         
 470  
         /**
 471  
          * This method will stop a service and only this service
 472  
          * @param name         The name of the service that will be stopped
 473  
          * @return        True if the service was stopped, false otherwise.
 474  
          */
 475  
         @Description("Stops a service by service name.")
 476  
         @Impact(Impact.ACTION)
 477  
         public boolean stopService(String name) {
 478  0
                 ServiceMetaInfo service = NamingService.getInstance().getServiceByName(name);
 479  0
                 if(service == null) {
 480  0
                         return false;
 481  
                 }
 482  
                 else {
 483  0
                         HotDeployer.getInstance().addIgnore(service.getFile());
 484  0
                         stop(service);
 485  0
                         return true;
 486  
                 }
 487  
         }
 488  
         
 489  
         /**
 490  
          * This method will start a service by filename.
 491  
          * @param name        The filename
 492  
          * @return        True if the service was started, false if not.
 493  
          */
 494  
         @Description("Starts a service by filename.")
 495  
         @Impact(Impact.ACTION)
 496  
         public boolean startService(String name) {
 497  0
                 String filename = Config.get(Config.DEFAULT_DEPLOY_FOLDER) + "/" + name;
 498  0
                 return HotDeployer.getInstance().removeIgnore(new File(filename));
 499  
         }
 500  
         
 501  
         /**
 502  
          * This method will stopp all services that has been deployed.
 503  
          */
 504  
         @Description("Stops all loaded services")
 505  
         @Impact(Impact.INFO)
 506  
         public void shutdown() {
 507  0
                 HotDeployer.getInstance().stopDeployer();
 508  0
                 stop(NamingService.getInstance().getAllServices());
 509  0
         }
 510  
         
 511  
         /**
 512  
          * This method returns the types of notifications this object can broadcast
 513  
          * 
 514  
          * @return        Types of notifications
 515  
          */
 516  
         @NotificationInfo
 517  
         public MBeanNotificationInfo[] getNotificationInfo() {
 518  0
                 MBeanNotificationInfo[] not = new MBeanNotificationInfo[7];
 519  0
                 not[0] = new MBeanNotificationInfo(new String[]{SERVICE_STARTED}, 
 520  
                                 Notification.class.getClass().getName(), "Emitted when a new service is started.");
 521  0
                 not[1] = new MBeanNotificationInfo(new String[]{SERVICE_STOPPED}, 
 522  
                                 Notification.class.getClass().getName(), "Emitted when a service is stopped.");
 523  0
                 not[2] = new MBeanNotificationInfo(new String[]{SERVICE_LOADING}, 
 524  
                                 Notification.class.getClass().getName(), "Emitted when a service is loading.");
 525  0
                 not[3] = new MBeanNotificationInfo(new String[]{SERVICE_FAILED}, 
 526  
                                 Notification.class.getClass().getName(), "Emitted when a service failed loading.");
 527  0
                 not[4] = new MBeanNotificationInfo(new String[]{COMPONENT_STOPPED}, 
 528  
                                 Notification.class.getClass().getName(), "Emitted when a component has been stopped.");
 529  0
                 not[5] = new MBeanNotificationInfo(new String[]{STOPPING_COMPONENT}, 
 530  
                                 Notification.class.getClass().getName(), "Emitted when a component is being stopped.");
 531  0
                 not[6] = new MBeanNotificationInfo(new String[]{STOPPING_SERVICE}, 
 532  
                                 Notification.class.getClass().getName(), "Emitted when a service is being stopped.");
 533  0
                 return not;
 534  
                 
 535  
         }
 536  
         
 537  
         /**
 538  
          * Gets the singelton instance of this class
 539  
          * @return        Singelton of ComponentManager
 540  
          */
 541  
         public static ComponentManager getInstance() {
 542  0
                 return singelton;
 543  
         }
 544  
         
 545  
         private void send(String type, Running metadata) {
 546  0
                 Notification not = new Notification(type, Notification.class.getClass().getName(), 
 547  
                                 sequence++, metadata.getName());
 548  0
                 not.setUserData(metadata);
 549  0
                 proxy.send(not);
 550  0
         }
 551  
 }