/**
   * PUBLIC: Return a session broker that behaves as a client session broker. An acquire session
   * broker is done under the covers on each session inside the session broker, and a new broker is
   * returned.
   *
   * <p>NOTE: when finished with the client broker, it should be releases. See
   * releaseClientSessionBroker.
   */
  public SessionBroker acquireClientSessionBroker() {
    log(SessionLog.FINER, SessionLog.CONNECTION, "acquire_client_session_broker");
    SessionBroker clientBroker = copySessionBroker();
    clientBroker.parent = this;
    clientBroker
        .getIdentityMapAccessorInstance()
        .setIdentityMapManager(getIdentityMapAccessorInstance().getIdentityMapManager());
    clientBroker.commitManager = getCommitManager();
    clientBroker.commandManager = getCommandManager();
    clientBroker.externalTransactionController = getExternalTransactionController();
    clientBroker.setServerPlatform(getServerPlatform());
    String sessionName;
    AbstractSession serverSession;
    Iterator names = this.getSessionsByName().keySet().iterator();
    while (names.hasNext()) {
      sessionName = (String) names.next();
      serverSession = getSessionForName(sessionName);
      if (serverSession instanceof org.eclipse.persistence.sessions.server.ServerSession) {
        if (serverSession.getProject().hasIsolatedClasses()) {
          throw ValidationException.isolatedDataNotSupportedInSessionBroker(sessionName);
        }
        clientBroker.internalRegisterSession(
            sessionName,
            ((org.eclipse.persistence.sessions.server.ServerSession) serverSession)
                .acquireClientSession());
      } else {
        throw ValidationException.cannotAcquireClientSessionFromSession();
      }
    }

    clientBroker.initializeSequencing();
    return clientBroker;
  }
  /**
   * INTERNAL: Return the results from exeucting the database query. the arguments should be a
   * database row with raw data values. Find the correct child session to broker the query to, and
   * return the result of the session executing the query.
   */
  public Object internalExecuteQuery(DatabaseQuery query, AbstractRecord row)
      throws DatabaseException, QueryException {
    AbstractSession sessionByQuery = getSessionForQuery(query);

    // Note, this disables local profilers.
    return sessionByQuery.internalExecuteQuery(query, row);
  }
  /**
   * PUBLIC: set the integrityChecker. IntegrityChecker holds all the ClassDescriptor Exceptions.
   */
  public void setIntegrityChecker(IntegrityChecker integrityChecker) {
    super.setIntegrityChecker(integrityChecker);

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      session.setIntegrityChecker(integrityChecker);
    }
  }
  /**
   * PUBLIC: Set the message log.
   *
   * @see #logMessages()
   */
  public void setLog(Writer log) {
    super.setLog(log);

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      session.setLog(log);
    }
  }
  /**
   * PUBLIC: Set the profiler for the session. This allows for performance operations to be
   * profiled.
   */
  public void setProfiler(SessionProfiler profiler) {
    super.setProfiler(profiler);

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      session.setProfiler(profiler);
    }
  }
  /** PUBLIC: Return if this session is a server session broker. */
  public boolean isServerSessionBroker() {
    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      if (session.isServerSession()) {
        return true;
      }
    }

    return false;
  }
 /**
  * PUBLIC: Release the session. This does nothing by default, but allows for other sessions such
  * as the ClientSession to do something.
  */
 public void release() {
   if (isClientSessionBroker()) {
     log(SessionLog.FINER, SessionLog.CONNECTION, "releasing_client_session_broker");
   }
   AbstractSession session;
   for (Iterator enumtr = getSessionsByName().values().iterator(); enumtr.hasNext(); ) {
     session = (AbstractSession) enumtr.next();
     session.release();
   }
   super.release();
 }
 /**
  * INTERNAL: This method notifies the accessor that a particular sets of writes has completed.
  * This notification can be used for such thing as flushing the batch mechanism
  */
 public void writesCompleted() {
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     if (!session.isConnected()) {
       throw DatabaseException.databaseAccessorNotConnected();
     }
   }
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.writesCompleted();
   }
 }
 /**
  * INTERNAL: Commit the transaction on all child sessions. This assumes that the commit of the
  * transaction will not fail because all of the modification has already taken place and no errors
  * would have occurred.
  */
 protected void basicCommitTransaction() throws DatabaseException {
   // Do one last check it make sure that all sessions are still connected.
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     if (!session.isConnected()) {
       throw DatabaseException.databaseAccessorNotConnected();
     }
   }
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.commitTransaction();
   }
 }
 /** INTERNAL: Rollback the transaction on all child sessions. */
 protected void basicRollbackTransaction() throws DatabaseException {
   DatabaseException globalException = null;
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     try {
       session.rollbackTransaction();
     } catch (DatabaseException exception) {
       globalException = exception;
     }
   }
   if (globalException != null) {
     throw globalException;
   }
 }
  /** PUBLIC: Return if all sessions are still connected to the database. */
  public boolean isConnected() {
    if ((getSessionsByName() == null) || (getSessionsByName().isEmpty())) {
      return false;
    }

    for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
      AbstractSession session = (AbstractSession) sessionEnum.next();
      if (!session.isConnected()) {
        return false;
      }
    }

    return true;
  }
  /**
   * INTERNAL: Register the session under its name. All of the session's descriptors must have
   * already been registered. The session should not be connected and descriptors should not be
   * initialized. Used for client session broker
   */
  public void internalRegisterSession(String name, AbstractSession session) {
    // Bug#3911318  Removed session brokers and sessions point to the same descriptors.
    // They don't need to be reassigned.  Also the code to add read only classes has been removed
    // because client broker and server broker point to the same project.
    session.setIsInBroker(true);
    getSessionsByName().put(name, session);
    session.setBroker(this);
    session.setName(name);

    /*       // The keys/classes must also be used as some descriptors may be under multiple classes.
          Iterator classes = session.getDescriptors().keySet().iterator();
          while (classes.hasNext()) {
              Class descriptorClass = (Class)classes.next();
              getSessionNamesByClass().put(descriptorClass, session);
          }
    */ }
  /**
   * PUBLIC: Register the session under its name. All of the session's descriptors must have already
   * been registered. The session should not be connected and descriptors should not be initialized.
   */
  public void registerSession(String name, AbstractSession session) {
    session.setIsInBroker(true);
    getSessionsByName().put(name, session);
    session.setBroker(this);
    session.setName(name);

    // The keys/classes must also be used as some descriptors may be under multiple classes.
    Iterator descriptors = session.getDescriptors().values().iterator();
    Iterator classes = session.getDescriptors().keySet().iterator();
    while (descriptors.hasNext()) {
      ClassDescriptor descriptor = (ClassDescriptor) descriptors.next();
      Class descriptorClass = (Class) classes.next();
      getSessionNamesByClass().put(descriptorClass, name);
      getDescriptors().put(descriptorClass, descriptor);
    }
  }
  /** INTERNAL: Acquires a special historical session for reading objects as of a past time. */
  public org.eclipse.persistence.sessions.Session acquireHistoricalSession(AsOfClause clause)
      throws ValidationException {
    if (isServerSessionBroker()) {
      throw ValidationException.cannotAcquireHistoricalSession();
    }

    // ? logMessage("acquire_client_session_broker", (Object[])null);
    SessionBroker historicalBroker = copySessionBroker();
    String sessionName;
    AbstractSession session;
    Iterator names = this.getSessionsByName().keySet().iterator();
    while (names.hasNext()) {
      sessionName = (String) names.next();
      session = getSessionForName(sessionName);
      historicalBroker.registerSession(sessionName, session.acquireHistoricalSession(clause));
    }
    return historicalBroker;
  }
 /** INTERNAL: Begin the transaction on all child sessions. */
 protected void basicBeginTransaction() throws DatabaseException {
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.beginTransaction();
   }
 }
  /**
   * INTERNAL: Gets the session which this query will be executed on. Generally will be called
   * immediately before the call is translated, which is immediately before session.executeCall.
   *
   * <p>Since the execution session also knows the correct datasource platform to execute on, it is
   * often used in the mappings where the platform is needed for type conversion, or where calls are
   * translated.
   *
   * <p>Is also the session with the accessor. Will return a ClientSession if it is in transaction
   * and has a write connection.
   *
   * @return a session with a live accessor
   * @param query may store session name or reference class for brokers case
   */
  public AbstractSession getExecutionSession(DatabaseQuery query) {
    AbstractSession sessionByQuery = getSessionForQuery(query);

    // Always forward to a registered session.
    return sessionByQuery.getExecutionSession(query);
  }
 /**
  * INTERNAL: Called in the end of beforeCompletion of external transaction sychronization
  * listener. Close the managed sql connection corresponding to the external transaction, if
  * applicable releases accessor.
  */
 public void releaseJTSConnection() {
   for (Iterator sessionEnum = getSessionsByName().values().iterator(); sessionEnum.hasNext(); ) {
     AbstractSession session = (AbstractSession) sessionEnum.next();
     session.releaseJTSConnection();
   }
 }