/**
   * Reinstantiates a serialized session from the data passed in. This will first call
   * createSession() so that we get a fresh instance with all the managers set and all the transient
   * fields validated. Then it calls Session.readObjectData(byte[]) to deserialize the object
   *
   * @param data - a byte array containing session data
   * @return a valid Session object, null if an error occurs
   */
  protected Session readSession(byte[] data, String sessionId) {
    try {
      ReplicationStream session_in = getReplicationStream(data);

      Session session = sessionId != null ? this.findSession(sessionId) : null;
      boolean isNew = (session == null);
      // clear the old values from the existing session
      if (session != null) {
        ReplicatedSession rs = (ReplicatedSession) session;
        rs.expire(false); // cleans up the previous values, since we are not doing removes
        session = null;
      } // end if

      if (session == null) {
        session = createSession(null, false, false);
        sessions.remove(session.getIdInternal());
      }

      boolean hasPrincipal = session_in.readBoolean();
      SerializablePrincipal p = null;
      if (hasPrincipal) p = (SerializablePrincipal) session_in.readObject();
      ((ReplicatedSession) session).readObjectData(session_in);
      if (hasPrincipal) session.setPrincipal(p.getPrincipal(getContainer().getRealm()));
      ((ReplicatedSession) session).setId(sessionId, isNew);
      ReplicatedSession rsession = (ReplicatedSession) session;
      rsession.setAccessCount(1);
      session.setManager(this);
      session.setValid(true);
      rsession.setLastAccessedTime(System.currentTimeMillis());
      rsession.setThisAccessedTime(System.currentTimeMillis());
      ((ReplicatedSession) session).setAccessCount(0);
      session.setNew(false);
      if (log.isTraceEnabled())
        log.trace(
            "Session loaded id="
                + sessionId
                + " actualId="
                + session.getId()
                + " exists="
                + this.sessions.containsKey(sessionId)
                + " valid="
                + rsession.isValid());
      return session;

    } catch (Exception x) {
      log.error("Failed to deserialize the session!", x);
    }
    return null;
  }