/*
   * (non-Javadoc)
   *
   * @see
   * org.eclipse.ptp.rtsystem.IRuntimeSystem#startup(org.eclipse.core.runtime
   * .IProgressMonitor)
   */
  public void startup(IProgressMonitor monitor) throws CoreException {
    SubMonitor subMon = SubMonitor.convert(monitor, 100);

    synchronized (this) {
      startupMonitor = subMon;
    }

    initialize();

    subMon.subTask(Messages.AbstractToolRuntimeSystem_1);

    DebugUtil.trace(
        DebugUtil.RTS_TRACING,
        "RTS {0}: startup",
        getResourceManager().getConfiguration().getName()); // $NON-NLS-1$

    try {
      remoteServices =
          PTPRemoteCorePlugin.getDefault()
              .getRemoteServices(
                  getResourceManager().getControlConfiguration().getRemoteServicesId(),
                  subMon.newChild(10));
      if (remoteServices == null) {
        throw new CoreException(
            new Status(
                IStatus.ERROR,
                RMCorePlugin.PLUGIN_ID,
                Messages.AbstractToolRuntimeSystem_Exception_NoRemoteServices));
      }

      IRemoteConnectionManager connectionManager = remoteServices.getConnectionManager();
      Assert.isNotNull(connectionManager);

      subMon.worked(10);
      subMon.subTask(Messages.AbstractToolRuntimeSystem_2);

      connection =
          connectionManager.getConnection(
              getResourceManager().getControlConfiguration().getConnectionName());
      if (connection == null) {
        throw new CoreException(
            new Status(
                IStatus.ERROR,
                RMCorePlugin.PLUGIN_ID,
                Messages.AbstractToolRuntimeSystem_Exception_NoConnection));
      }

      if (!connection.isOpen()) {
        try {
          connection.open(subMon.newChild(50));
        } catch (RemoteConnectionException e) {
          throw new CoreException(
              new Status(IStatus.ERROR, RMCorePlugin.PLUGIN_ID, e.getMessage()));
        }
      }

      if (subMon.isCanceled()) {
        connection.close();
        return;
      }

      try {
        doStartup(subMon.newChild(40));
      } catch (CoreException e) {
        connection.close();
        throw e;
      }

      if (subMon.isCanceled()) {
        connection.close();
        return;
      }

      /*
       * Wait for discover job to complete so we can check it's status and
       * throw an exception if it fails.
       */
      Job discoverJob = createDiscoverJob();
      if (discoverJob != null) {
        /*
         * Disable error messages being displayed on job's progress
         * monitor. These are handled by the progress service starting
         * the RM.
         */
        discoverJob.setProperty(
            IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
        discoverJob.schedule();
        try {
          discoverJob.join();
        } catch (InterruptedException e) {
          // Just check result
        }
        IStatus status = discoverJob.getResult();
        if (!status.isOK()) {
          throw new CoreException(status);
        }
      }

      if (jobQueueThread == null) {
        jobQueueThread =
            new Thread(
                new JobRunner(), Messages.AbstractToolRuntimeSystem_JobQueueManagerThreadTitle);
        jobQueueThread.start();
      }

      /*
       * Register for connection events
       */
      connection.addConnectionChangeListener(fConnectionChangeHandler);

      fireRuntimeRunningStateEvent(eventFactory.newRuntimeRunningStateEvent());
    } finally {
      synchronized (this) {
        startupMonitor = null;
      }
      if (monitor != null) {
        monitor.done();
      }
    }
  }
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.ptp.rtsystem.IRuntimeSystem#shutdown()
   */
  public void shutdown() throws CoreException {
    DebugUtil.trace(
        DebugUtil.RTS_TRACING,
        "RTS {0}: shutdown",
        getResourceManager().getConfiguration().getName()); // $NON-NLS-1$

    /*
     * Remove listener to avoid re-entry
     */
    if (connection != null) {
      connection.removeConnectionChangeListener(fConnectionChangeHandler);
    }

    try {
      stopEvents();
    } catch (CoreException e) {
      // Ignore exception and shutdown anyway
      RMCorePlugin.log(e);
    }

    try {
      doShutdown();
    } finally {

      /*
       * Stop jobs that might be in the pending queue. Also stop the
       * thread that dispatches pending jobs.
       */
      if (jobQueueThread != null) {
        jobQueueThread.interrupt();
        for (Job job : pendingJobQueue) {
          job.cancel();
        }
      }

      /*
       * Stop jobs that are running or that already finished.
       */
      Iterator<Job> iterator = jobs.values().iterator();
      while (iterator.hasNext()) {
        Job job = iterator.next();
        job.cancel();
        iterator.remove();
      }

      synchronized (this) {
        if (startupMonitor != null) {
          startupMonitor.setCanceled(true);
        }
      }

      /*
       * Close the the connection.
       */
      if (connection != null) {
        connection.close();
      }

      jobQueueThread = null;
      fireRuntimeShutdownStateEvent(eventFactory.newRuntimeShutdownStateEvent());
    }
  }