Esempio n. 1
0
  private void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();

    // Serialize local snapshots cache
    if (!isUsingSharedSnapshotCache()) {
      out.writeObject(objectStore.getDataRowCache());
    }
  }
Esempio n. 2
0
  /**
   * Creates a new DataContext with parent DataChannel and ObjectStore.
   *
   * @since 1.2
   */
  public DataContext(DataChannel channel, ObjectStore objectStore) {

    // inject self as parent context
    if (objectStore != null) {
      this.objectStore = objectStore;
      objectStore.setContext(this);
    }

    if (channel != null) {
      attachToChannel(channel);
    }

    if (objectStore != null) {
      DataDomain domain = getParentDataDomain();
      this.usingSharedSnaphsotCache =
          domain != null && objectStore.getDataRowCache() == domain.getSharedSnapshotCache();
    }
  }
Esempio n. 3
0
  /**
   * If the parent channel is a DataContext, reverts local changes to make this context look like
   * the parent, if the parent channel is a DataDomain, reverts all changes.
   *
   * @since 1.2
   */
  @Override
  public void rollbackChangesLocally() {
    if (objectStore.hasChanges()) {
      GraphDiff diff = getObjectStore().getChanges();

      getObjectStore().objectsRolledBack();
      fireDataChannelRolledback(this, diff);
    }
  }
Esempio n. 4
0
  // serialization support
  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {

    // TODO: most of this should be in the superclass, especially the code
    // connecting
    // super transient ivars

    // read non-transient properties
    in.defaultReadObject();

    // deserialize local snapshots cache
    if (!isUsingSharedSnapshotCache()) {
      DataRowStore cache = (DataRowStore) in.readObject();
      objectStore.setDataRowCache(cache);
    }

    // CayenneDataObjects have a transient DataContext
    // because at deserialize time the datacontext may need to be different
    // than the one at serialize time (for programmer defined reasons).
    // So, when a DataObject is resurrected because it's DataContext was
    // serialized, it will then set the objects DataContext to the correct
    // one
    // If deserialized "otherwise", it will not have a DataContext.

    synchronized (getObjectStore()) {
      Iterator<?> it = objectStore.getObjectIterator();
      while (it.hasNext()) {
        Persistent object = (Persistent) it.next();
        object.setObjectContext(this);
      }
    }

    // ... deferring initialization of transient properties of this context
    // till first
    // access, so that it can attach to Cayenne runtime using appropriate
    // thread
    // injector.
  }
Esempio n. 5
0
  /**
   * Reverts any changes that have occurred to objects registered with DataContext; also performs
   * cascading rollback of all parent DataContexts.
   */
  @Override
  public void rollbackChanges() {

    if (objectStore.hasChanges()) {
      GraphDiff diff = getObjectStore().getChanges();

      // call channel with changes BEFORE reverting them, so that any
      // interceptors
      // could record them

      if (channel != null) {
        channel.onSync(this, diff, DataChannel.ROLLBACK_CASCADE_SYNC);
      }

      getObjectStore().objectsRolledBack();
      fireDataChannelRolledback(this, diff);
    } else {
      if (channel != null) {
        channel.onSync(this, new CompoundDiff(), DataChannel.ROLLBACK_CASCADE_SYNC);
      }
    }
  }
Esempio n. 6
0
  /**
   * Synchronizes with the parent channel, performing a flush or a commit.
   *
   * @since 1.2
   */
  GraphDiff flushToParent(boolean cascade) {

    if (this.getChannel() == null) {
      throw new CayenneRuntimeException("Cannot commit changes - channel is not set.");
    }

    int syncType = cascade ? DataChannel.FLUSH_CASCADE_SYNC : DataChannel.FLUSH_NOCASCADE_SYNC;

    ObjectStore objectStore = getObjectStore();
    GraphDiff parentChanges = null;

    // prevent multiple commits occurring simultaneously
    synchronized (objectStore) {
      ObjectStoreGraphDiff changes = objectStore.getChanges();
      boolean noop =
          isValidatingObjectsOnCommit() ? changes.validateAndCheckNoop() : changes.isNoop();

      if (noop) {
        // need to clear phantom changes
        objectStore.postprocessAfterPhantomCommit();
      } else {

        try {
          parentChanges = getChannel().onSync(this, changes, syncType);

          // note that this is a hack resulting from a fix to
          // CAY-766... To
          // support
          // valid object state in PostPersist callback,
          // 'postprocessAfterCommit' is
          // invoked by DataDomain.onSync(..). Unless the parent is
          // DataContext,
          // and
          // this method is not invoked!! As a result, PostPersist
          // will contain
          // temp
          // ObjectIds in nested contexts and perm ones in flat
          // contexts.
          // Pending better callback design .....
          if (objectStore.hasChanges()) {
            objectStore.postprocessAfterCommit(parentChanges);
          }

          // this event is caught by peer nested DataContexts to
          // synchronize the
          // state
          fireDataChannelCommitted(this, changes);
        }
        // "catch" is needed to unwrap OptimisticLockExceptions
        catch (CayenneRuntimeException ex) {
          Throwable unwound = Util.unwindException(ex);

          if (unwound instanceof CayenneRuntimeException) {
            throw (CayenneRuntimeException) unwound;
          } else {
            throw new CayenneRuntimeException("Commit Exception", unwound);
          }
        }
      }

      // merge changes from parent as well as changes caused by lifecycle
      // event
      // callbacks/listeners...

      CompoundDiff diff = new CompoundDiff();

      diff.addAll(objectStore.getLifecycleEventInducedChanges());
      if (parentChanges != null) {
        diff.add(parentChanges);
      }

      // this event is caught by child DataContexts to update temporary
      // ObjectIds with permanent
      if (!diff.isNoop()) {
        fireDataChannelCommitted(getChannel(), diff);
      }

      return diff;
    }
  }