Esempio n. 1
0
  /**
   * Return an <code>Entry</code> object built out of this <code>EntryRep</code> This is used by the
   * client-side proxy to convert the <code>EntryRep</code> it gets from the space server into the
   * actual <code>Entry</code> object it represents.
   *
   * @throws UnusableEntryException One or more fields in the entry cannot be deserialized, or the
   *     class for the entry type itself cannot be deserialized.
   */
  Entry entry() throws UnusableEntryException {
    ObjectInputStream objIn = null;
    try {
      ArrayList badFields = null;
      ArrayList except = null;

      realClass = ClassLoading.loadClass(codebase, className, null, integrity, null);

      if (findHash(realClass, false).longValue() != hash)
        throw throwNewUnusableEntryException(
            new IncompatibleClassChangeError(realClass + " changed"));

      Entry entryObj = (Entry) realClass.newInstance();

      Field[] fields = getFields(realClass);

      /*
       * Loop through the fields, ensuring no primitives and
       * checking for wildcards.
       */
      int nvals = 0; // index into this.values[]
      for (int i = 0; i < fields.length; i++) {
        Throwable nested = null;
        try {
          if (!usableField(fields[i])) continue;

          final MarshalledInstance val = values[nvals++];
          Object value = (val == null ? null : val.get(integrity));
          fields[i].set(entryObj, value);
        } catch (Throwable e) {
          nested = e;
        }

        if (nested != null) { // some problem occurred
          if (badFields == null) {
            badFields = new ArrayList(fields.length);
            except = new ArrayList(fields.length);
          }
          badFields.add(fields[i].getName());
          except.add(nested);
        }
      }

      /* See if any fields have vanished from the class,
       * because of the hashing this should never happen but
       * throwing an exception that provides more info
       * (instead of AssertionError) seems harmless.
       */
      if (nvals < values.length) {
        throw throwNewUnusableEntryException(
            entryObj, // should this be null?
            null, // array of bad-field names
            new Throwable[] { // array of exceptions
              new IncompatibleClassChangeError(
                  "A usable field has been removed from "
                      + entryObj.getClass().getName()
                      + " since this EntryRep was created")
            });
      }

      // if there were any bad fields, throw the exception
      if (badFields != null) {
        String[] bf = (String[]) badFields.toArray(new String[badFields.size()]);
        Throwable[] ex = (Throwable[]) except.toArray(new Throwable[bf.length]);
        throw throwNewUnusableEntryException(entryObj, bf, ex);
      }

      // everything fine, return the entry
      return entryObj;
    } catch (InstantiationException e) {
      /*
       * If this happens outside a per-field deserialization then
       * this is a complete failure  The per-field ones are caught
       * inside the per-field loop.
       */
      throw throwNewUnusableEntryException(e);
    } catch (ClassNotFoundException e) {
      // see above
      throw throwNewUnusableEntryException(
          "Encountered a " + "ClassNotFoundException while unmarshalling " + className, e);
    } catch (IllegalAccessException e) {
      // see above
      throw throwNewUnusableEntryException(e);
    } catch (RuntimeException e) {
      // see above
      throw throwNewUnusableEntryException(
          "Encountered a " + "RuntimeException while unmarshalling " + className, e);
    } catch (MalformedURLException e) {
      // see above
      throw throwNewUnusableEntryException(
          "Malformed URL " + "associated with entry of type " + className, e);
    } catch (MarshalException e) {
      // because we call findHash() w/ false, should never happen
      throw new AssertionError(e);
    }
  }
Esempio n. 2
0
  /**
   * Create a serialized form of the entry. If <code>validate</code> is <code>true</code>, basic
   * sanity checks are done on the class to ensure that it meets the requirements to be an <code>
   * Entry</code>. <code>validate</code> is <code>false</code> only when creating the stand-in
   * object for "match any", which is never actually marshalled on the wire and so which doesn't
   * need to be "proper".
   */
  private EntryRep(Entry entry, boolean validate) throws MarshalException {
    realClass = entry.getClass();
    if (validate) ensureValidClass(realClass);
    className = realClass.getName();
    codebase = RMIClassLoader.getClassAnnotation(realClass);

    /*
     * Build up the per-field and superclass information through
     * the reflection API.
     */
    final Field[] fields = getFields(realClass);
    int numFields = fields.length;

    // collect the usable field values in vals[0..nvals-1]
    MarshalledInstance[] vals = new MarshalledInstance[numFields];
    int nvals = 0;

    for (int fnum = 0; fnum < fields.length; fnum++) {
      final Field field = fields[fnum];
      if (!usableField(field)) continue;

      final Object fieldValue;
      try {
        fieldValue = field.get(entry);
      } catch (IllegalAccessException e) {
        /* In general between using getFields() and
         * ensureValidClass this should never happen, however
         * there appear to be a few screw cases and
         * IllegalArgumentException seems appropriate.
         */
        final IllegalArgumentException iae =
            new IllegalArgumentException("Couldn't access field " + field);
        iae.initCause(e);
        throw throwRuntime(iae);
      }

      if (fieldValue == null) {
        vals[nvals] = null;
      } else {
        try {
          vals[nvals] = new MarshalledInstance(fieldValue);
        } catch (IOException e) {
          throw throwNewMarshalException(
              "Can't marshal field " + field + " with value " + fieldValue, e);
        }
      }

      nvals++;
    }

    // copy the vals with the correct length
    this.values = new MarshalledInstance[nvals];
    System.arraycopy(vals, 0, this.values, 0, nvals);

    try {
      hash = findHash(realClass, true).longValue();
    } catch (UnusableEntryException e) {
      // Will never happen when we pass true to findHash
      throw new AssertionError(e);
    }

    // Loop through the supertypes, making a list of all superclasses.
    ArrayList sclasses = new ArrayList();
    ArrayList shashes = new ArrayList();
    for (Class c = realClass.getSuperclass(); c != Object.class; c = c.getSuperclass()) {
      try {
        sclasses.add(c.getName());
        shashes.add(findHash(c, true));
      } catch (ClassCastException cce) {
        break; // not Serializable
      } catch (UnusableEntryException e) {
        // Will never happen when we pass true to findHash
        throw new AssertionError(e);
      }
    }
    superclasses = (String[]) sclasses.toArray(new String[sclasses.size()]);
    hashes = new long[shashes.size()];
    for (int i = 0; i < hashes.length; i++) {
      hashes[i] = ((Long) shashes.get(i)).longValue();
    }
  }