/**
  * Perform the undo. All validity checks have already occurred.
  *
  * @param monitor
  * @param operation
  */
 private IStatus doUndo(IProgressMonitor monitor, IAdaptable info, IUndoableOperation operation)
     throws ExecutionException {
   IStatus status = getUndoApproval(operation, info);
   if (status.isOK()) {
     notifyAboutToUndo(operation);
     try {
       status = operation.undo(monitor, info);
     } catch (OperationCanceledException e) {
       status = Status.CANCEL_STATUS;
     } catch (ExecutionException e) {
       notifyNotOK(operation);
       if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
         Tracing.printTrace(
             "OPERATIONHISTORY", //$NON-NLS-1$
             "ExecutionException while undoing " + operation); // $NON-NLS-1$
       }
       throw e;
     } catch (Exception e) {
       notifyNotOK(operation);
       if (DEBUG_OPERATION_HISTORY_UNEXPECTED) {
         Tracing.printTrace(
             "OPERATIONHISTORY", //$NON-NLS-1$
             "Exception while undoing " + operation); // $NON-NLS-1$
       }
       throw new ExecutionException(
           "While undoing the operation, an exception occurred", e); // $NON-NLS-1$
     }
   }
   // if successful, the operation is removed from the undo history and
   // placed in the redo history.
   if (status.isOK()) {
     boolean addedToRedo = true;
     synchronized (undoRedoHistoryLock) {
       undoList.remove(operation);
       if (checkRedoLimit(operation)) {
         redoList.add(operation);
       } else {
         addedToRedo = false;
       }
     }
     // dispose the operation since we could not add it to the
     // stack and will no longer have a reference to it.
     if (!addedToRedo) {
       operation.dispose();
     }
     // notification occurs after the undo and redo histories are
     // adjusted
     notifyUndone(operation);
   } else {
     notifyNotOK(operation, status);
   }
   return status;
 }