boolean suspendEnvironmentSpi(Environment env, String templateName, int line)
      throws RemoteException {
    RmiDebuggedEnvironmentImpl denv =
        (RmiDebuggedEnvironmentImpl) RmiDebuggedEnvironmentImpl.getCachedWrapperFor(env);

    synchronized (suspendedEnvironments) {
      suspendedEnvironments.add(denv);
    }
    try {
      EnvironmentSuspendedEvent breakpointEvent =
          new EnvironmentSuspendedEvent(this, templateName, line, denv);

      synchronized (listeners) {
        for (Iterator iter = listeners.values().iterator(); iter.hasNext(); ) {
          DebuggerListener listener = (DebuggerListener) iter.next();
          listener.environmentSuspended(breakpointEvent);
        }
      }
      synchronized (denv) {
        try {
          denv.wait();
        } catch (InterruptedException e) {; // Intentionally ignored
        }
      }
      return denv.isStopped();
    } finally {
      synchronized (suspendedEnvironments) {
        suspendedEnvironments.remove(denv);
      }
    }
  }
  void shutdownSpi() {
    server.stop();
    try {
      UnicastRemoteObject.unexportObject(this.debugger, true);
    } catch (Exception e) {
    }

    RmiDebuggedEnvironmentImpl.cleanup();
  }