public final void close() throws SailException {
    // obtain an exclusive lock so that any further operations on this
    // connection (including those from any concurrent threads) are blocked.
    connectionLock.writeLock().lock();

    try {
      if (isOpen) {
        try {
          while (true) {
            SailBaseIteration ci = null;

            synchronized (activeIterations) {
              if (activeIterations.isEmpty()) {
                break;
              } else {
                ci = activeIterations.remove(0);
              }
            }

            try {
              ci.forceClose();
            } catch (SailException e) {
              throw e;
            } catch (Exception e) {
              throw new SailException(e);
            }
          }

          assert activeIterations.isEmpty();

          if (txnActive) {
            logger.warn("Rolling back transaction due to connection close", new Throwable());
            try {
              // Use internal method to avoid deadlock: the public
              // rollback method will try to obtain a connection
              // lock
              rollbackInternal();
            } finally {
              txnActive = false;
            }
          }

          closeInternal();
        } finally {
          isOpen = false;
          sailBase.connectionClosed(this);
        }
      }
    } finally {
      // Release the exclusive lock. Any threads waiting to obtain a
      // non-exclusive read lock will get one and then fail with an
      // IllegalStateException, because the connection is no longer open.
      connectionLock.writeLock().unlock();
    }
  }
 protected void executeInternal(
     UpdateExpr updateExpr, Dataset dataset, BindingSet bindings, boolean includeInferred)
     throws SailException {
   /*
    * TODO this method should really be defined abstract, but for
    * backward-compatibility purposes with third-party SAIL implementations
    * we provide a default implementation for now.
    */
   ValueFactory vf = sailBase.getValueFactory();
   SailUpdateExecutor executor = new SailUpdateExecutor(this, vf, false);
   executor.executeUpdate(updateExpr, dataset, bindings, includeInferred);
 }