@Override
  public Proxy<?>[] releaseProxy(boolean destroy) {
    if (connectionStateMachine.isConnected()) {
      setConnectionState(ConnectionState.DISCONNECTING, null);
    }

    if (this.proxy != null) {
      this.proxy.removeProxyListener(proxyListener);
      if (this.directoryProxy != null && this.directoryProxy != this.proxy) {
        this.directoryProxy.removeProxyListener(proxyListener);
      }
    }
    Proxy<?>[] p = super.releaseProxy(destroy);
    if (connectionStateMachine.getConnectionState() == ConnectionState.DISCONNECTING) {
      setConnectionState(ConnectionState.DISCONNECTED, null);
    }

    if (destroy) {
      setConnectionState(ConnectionState.DESTROYED, null);
      linkListeners.clear();
      responseListeners.clear();
    }

    return p;
  }
  /** @param connectionState The connectionState to set. */
  protected void setConnectionState(ConnectionState connectionState, Throwable error) {
    boolean change = false;

    try {
      change = connectionStateMachine.requestNextConnectionState(connectionState);
    } catch (IllegalStateException e) {
      Logger.getLogger(this.getClass()).error("Internal error.", e);
      throw e;
    }

    if (!change) {
      return;
    }

    LinkListener<Linkable>[] l = (LinkListener<Linkable>[]) linkListeners.toArray();

    ConnectionEvent<Linkable> e = new ConnectionEvent<Linkable>(this, connectionState, error);
    lastConnectionEvent = e;

    if (connectionState == ConnectionState.CONNECTED) {

      if (hasDynamicValueListeners() && defaultMonitor == null) {
        getDefaultMonitor();
      }

      for (MonitorProxyWrapper<T, ? extends SimpleProperty<T>> mpw : monitors) {
        if (!mpw.isInitialized()) {
          try {
            MonitorProxy mp = proxy.createMonitor(mpw, mpw.getInitialParameters());
            mpw.initialize(mp);
          } catch (RemoteException e1) {
            // TODO mark mpw for removal from monitors?
            // if yes, it has to be done outside loop
          }
        }
      }

      for (int i = 0; i < l.length; i++) {
        try {
          l[i].connected(e);
        } catch (Exception ex) {
          Logger.getLogger(DynamicValuePropertyImpl.class)
              .warn("Exception in event handler, continuing.", ex);
        }
      }
    } else if (connectionState == ConnectionState.CONNECTION_FAILED) {
      for (int i = 0; i < l.length; i++) {
        try {
          l[i].connectionFailed(e);
        } catch (Exception ex) {
          Logger.getLogger(DynamicValuePropertyImpl.class)
              .warn("Exception in event handler, continuing.", ex);
        }
      }
    } else if (connectionState == ConnectionState.CONNECTION_LOST) {
      for (int i = 0; i < l.length; i++) {
        try {
          l[i].connectionLost(e);
        } catch (Exception ex) {
          Logger.getLogger(DynamicValuePropertyImpl.class)
              .warn("Exception in event handler, continuing.", ex);
        }
      }
    } else if (connectionState == ConnectionState.DISCONNECTED) {
      for (int i = 0; i < l.length; i++) {
        try {
          l[i].disconnected(e);
        } catch (Exception ex) {
          Logger.getLogger(DynamicValuePropertyImpl.class)
              .warn("Exception in event handler, continuing.", ex);
        }
      }
    } else if (connectionState == ConnectionState.DESTROYED) {
      for (int i = 0; i < l.length; i++) {
        try {
          l[i].destroyed(e);
        } catch (Exception ex) {
          Logger.getLogger(DynamicValuePropertyImpl.class)
              .warn("Exception in event handler, continuing.", ex);
        }
      }
    } else if (connectionState == ConnectionState.OPERATIONAL) {
      for (int i = 0; i < l.length; i++) {
        try {
          l[i].operational(e);
        } catch (Exception ex) {
          Logger.getLogger(DynamicValuePropertyImpl.class)
              .warn("Exception in event handler, continuing.", ex);
        }
      }
    }
  }
 /** @return Returns the connectionState. */
 public ConnectionState getConnectionState() {
   return connectionStateMachine.getConnectionState();
 }
 /* (non-Javadoc)
  * @see org.csstudio.dal.context.Linkable#isConnectionFailed()
  */
 public boolean isConnectionFailed() {
   return connectionStateMachine.isConnectionFailed();
 }
 /* (non-Javadoc)
  * @see org.csstudio.dal.context.Linkable#isConnectionAlive()
  */
 public boolean isConnectionAlive() {
   return connectionStateMachine.isConnectionAlive();
 }
 /* (non-Javadoc)
  * @see org.csstudio.dal.context.Linkable#isDestroyed()
  */
 public boolean isDestroyed() {
   return connectionStateMachine.isDestroyed();
 }
 /** @see Linkable#isOperational(); */
 public boolean isOperational() {
   return connectionStateMachine.isOperational();
 }