@Override
 public DatastoreTable getDatastoreClass(String className, ClassLoaderResolver clr) {
   try {
     // We see the occasional race condition when multiple threads concurrently
     // perform an operation using a persistence-capable class for which DataNucleus
     // has not yet generated the meta-data.  The result is usually
     // AbstractMemberMetaData objects with the same column listed twice in the meta-data.
     // Locking at this level is a bit more coarse-grained than I'd like but once the
     // meta-data has been built this will return super fast so it shouldn't be an issue.
     synchronized (this) {
       return (DatastoreTable) super.getDatastoreClass(className, clr);
     }
   } catch (NoTableManagedException e) {
     // Our parent class throws this when the class isn't PersistenceCapable also.
     Class cls = clr.classForName(className);
     ApiAdapter api = getApiAdapter();
     if (cls != null && !cls.isInterface() && !api.isPersistable(cls)) {
       throw new NoTableManagedException(
           "Class "
               + className
               + " does not seem to have been enhanced. You may want to rerun "
               + "the enhancer and check for errors in the output.");
       // Suggest you address why this method is being called before any check on whether it is
       // persistable
       // then you can remove this error message
     }
     throw e;
   }
 }
Exemplo n.º 2
0
  /**
   * Method to populate any defaults, and check the validity of the MetaData.
   *
   * @param clr ClassLoaderResolver to use for loading any key/value types
   * @param primary the primary ClassLoader to use (or null)
   * @param mmgr MetaData manager
   */
  public void populate(ClassLoaderResolver clr, ClassLoader primary, MetaDataManager mmgr) {
    AbstractMemberMetaData mmd = (AbstractMemberMetaData) parent;
    if (!StringUtils.isWhitespace(key.type) && key.type.indexOf(',') > 0) {
      throw new InvalidMetaDataException(LOCALISER, "044143", mmd.getName(), mmd.getClassName());
    }
    if (!StringUtils.isWhitespace(value.type) && value.type.indexOf(',') > 0) {
      throw new InvalidMetaDataException(LOCALISER, "044144", mmd.getName(), mmd.getClassName());
    }

    ApiAdapter api = mmgr.getApiAdapter();

    // Make sure the type in "key", "value" is set
    key.populate(
        ((AbstractMemberMetaData) parent).getAbstractClassMetaData().getPackageName(),
        clr,
        primary,
        mmgr);
    value.populate(
        ((AbstractMemberMetaData) parent).getAbstractClassMetaData().getPackageName(),
        clr,
        primary,
        mmgr);

    // Check the field type and see if it is castable to a Map
    Class field_type = getMemberMetaData().getType();
    if (!java.util.Map.class.isAssignableFrom(field_type)) {
      throw new InvalidMetaDataException(
          LOCALISER, "044145", getFieldName(), getMemberMetaData().getClassName(false));
    }

    if (java.util.Properties.class.isAssignableFrom(field_type)) {
      // Properties defaults to <String, String>
      if (key.type == null) {
        key.type = String.class.getName();
      }
      if (value.type == null) {
        value.type = String.class.getName();
      }
    }

    // "key-type"
    if (key.type == null) {
      throw new InvalidMetaDataException(
          LOCALISER, "044146", getFieldName(), getMemberMetaData().getClassName(false));
    }

    // Check that the key type exists
    Class keyTypeClass = null;
    try {
      keyTypeClass = clr.classForName(key.type, primary);
    } catch (ClassNotResolvedException cnre) {
      try {
        // Maybe the user specified a java.lang class without fully-qualifying it
        // This is beyond the scope of the JDO spec which expects java.lang cases to be
        // fully-qualified
        keyTypeClass = clr.classForName(ClassUtils.getJavaLangClassForType(key.type), primary);
      } catch (ClassNotResolvedException cnre2) {
        throw new InvalidMetaDataException(
            LOCALISER, "044147", getFieldName(), getMemberMetaData().getClassName(false), key.type);
      }
    }

    if (!keyTypeClass.getName().equals(key.type)) {
      // The value-type has been resolved from what was specified in the MetaData - update to the
      // fully-qualified name
      NucleusLogger.METADATA.info(
          LOCALISER.msg(
              "044148",
              getFieldName(),
              getMemberMetaData().getClassName(false),
              key.type,
              keyTypeClass.getName()));
      key.type = keyTypeClass.getName();
    }

    // "embedded-key"
    if (key.embedded == null) {
      // Assign default for "embedded-key" based on 18.13.2 of JDO 2 spec
      if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(keyTypeClass)) {
        key.embedded = Boolean.TRUE;
      } else if (api.isPersistable(keyTypeClass)
          || Object.class.isAssignableFrom(keyTypeClass)
          || keyTypeClass.isInterface()) {
        key.embedded = Boolean.FALSE;
      } else {
        key.embedded = Boolean.TRUE;
      }
    }
    if (Boolean.FALSE.equals(key.embedded)) {
      // If the user has set a non-PC/non-Interface as not embedded, correct it since not supported.
      // Note : this fails when using in the enhancer since not yet PC
      if (!api.isPersistable(keyTypeClass)
          && !keyTypeClass.isInterface()
          && keyTypeClass != java.lang.Object.class) {
        key.embedded = Boolean.TRUE;
      }
    }
    KeyMetaData keymd = ((AbstractMemberMetaData) parent).getKeyMetaData();
    if (keymd != null && keymd.getEmbeddedMetaData() != null) {
      // If the user has specified <embedded>, set to true
      key.embedded = Boolean.TRUE;
    }

    // "value-type"
    if (value.type == null) {
      throw new InvalidMetaDataException(
          LOCALISER, "044149", getFieldName(), getMemberMetaData().getClassName(false));
    }

    // Check that the value-type exists
    Class valueTypeClass = null;
    try {
      valueTypeClass = clr.classForName(value.type);
    } catch (ClassNotResolvedException cnre) {
      try {
        // Maybe the user specified a java.lang class without fully-qualifying it
        // This is beyond the scope of the JDO spec which expects java.lang cases to be
        // fully-qualified
        valueTypeClass = clr.classForName(ClassUtils.getJavaLangClassForType(value.type));
      } catch (ClassNotResolvedException cnre2) {
        throw new InvalidMetaDataException(
            LOCALISER,
            "044150",
            getFieldName(),
            getMemberMetaData().getClassName(false),
            value.type);
      }
    }

    if (!valueTypeClass.getName().equals(value.type)) {
      // The value-type has been resolved from what was specified in the MetaData - update to the
      // fully-qualified name
      NucleusLogger.METADATA.info(
          LOCALISER.msg(
              "044151",
              getFieldName(),
              getMemberMetaData().getClassName(false),
              value.type,
              valueTypeClass.getName()));
      value.type = valueTypeClass.getName();
    }

    // "embedded-value"
    if (value.embedded == null) {
      // Assign default for "embedded-value" based on 18.13.2 of JDO 2 spec
      if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(valueTypeClass)) {
        value.embedded = Boolean.TRUE;
      } else if (api.isPersistable(valueTypeClass)
          || Object.class.isAssignableFrom(valueTypeClass)
          || valueTypeClass.isInterface()) {
        value.embedded = Boolean.FALSE;
      } else {
        value.embedded = Boolean.TRUE;
      }
    }
    if (value.embedded == Boolean.FALSE) {
      // If the user has set a non-PC/non-Interface as not embedded, correct it since not supported.
      // Note : this fails when using in the enhancer since not yet PC
      if (!api.isPersistable(valueTypeClass)
          && !valueTypeClass.isInterface()
          && valueTypeClass != java.lang.Object.class) {
        value.embedded = Boolean.TRUE;
      }
    }
    ValueMetaData valuemd = ((AbstractMemberMetaData) parent).getValueMetaData();
    if (valuemd != null && valuemd.getEmbeddedMetaData() != null) {
      // If the user has specified <embedded>, set to true
      value.embedded = Boolean.TRUE;
    }

    key.classMetaData = mmgr.getMetaDataForClassInternal(keyTypeClass, clr);
    value.classMetaData = mmgr.getMetaDataForClassInternal(valueTypeClass, clr);

    // Cater for Key with mapped-by needing to be PK (for JPA)
    if (keymd != null
        && keymd.mappedBy != null
        && keymd.mappedBy.equals("#PK")) // Special value set by JPAMetaDataHandler
    {
      // Need to set the mapped-by of <key> to be the PK of the <value>
      if (value.classMetaData.getNoOfPrimaryKeyMembers() != 1) {
        // TODO Localise this
        throw new NucleusUserException(
            "DataNucleus does not support use of <map-key> with no name field when the"
                + " value class has a composite primary key");
      }
      int[] valuePkFieldNums = value.classMetaData.getPKMemberPositions();
      keymd.mappedBy =
          value.classMetaData.getMetaDataForManagedMemberAtAbsolutePosition(valuePkFieldNums[0])
              .name;
    }

    // Make sure anything in the superclass is populated too
    super.populate(clr, primary, mmgr);

    setPopulated();
  }
Exemplo n.º 3
0
  /**
   * Method to populate any defaults, and check the validity of the MetaData.
   *
   * @param clr ClassLoaderResolver to use for any loading operations
   * @param primary the primary ClassLoader to use (or null)
   * @param mmgr MetaData manager
   */
  public void populate(ClassLoaderResolver clr, ClassLoader primary, MetaDataManager mmgr) {
    AbstractMemberMetaData mmd = (AbstractMemberMetaData) parent;
    if (!StringUtils.isWhitespace(element.type) && element.type.indexOf(',') > 0) {
      throw new InvalidMetaDataException(LOCALISER, "044131", mmd.getName(), mmd.getClassName());
    }

    // Make sure the type in "element" is set
    element.populate(
        ((AbstractMemberMetaData) parent).getAbstractClassMetaData().getPackageName(),
        clr,
        primary,
        mmgr);

    // Check the field type and see if it is castable to a Collection
    Class field_type = getMemberMetaData().getType();
    if (!java.util.Collection.class.isAssignableFrom(field_type)) {
      throw new InvalidMetaDataException(
          LOCALISER, "044132", getFieldName(), getMemberMetaData().getClassName(false));
    }

    // "element-type"
    if (element.type == null) {
      throw new InvalidMetaDataException(
          LOCALISER, "044133", getFieldName(), getMemberMetaData().getClassName(false));
    }

    // Check that the element type exists
    Class elementTypeClass = null;
    try {
      elementTypeClass = clr.classForName(element.type, primary);
    } catch (ClassNotResolvedException cnre) {
      throw new InvalidMetaDataException(
          LOCALISER,
          "044134",
          getFieldName(),
          getMemberMetaData().getClassName(false),
          element.type);
    }

    if (!elementTypeClass.getName().equals(element.type)) {
      // The element-type has been resolved from what was specified in the MetaData - update to the
      // fully-qualified name
      NucleusLogger.METADATA.info(
          LOCALISER.msg(
              "044135",
              getFieldName(),
              getMemberMetaData().getClassName(false),
              element.type,
              elementTypeClass.getName()));
      element.type = elementTypeClass.getName();
    }

    // "embedded-element"
    ApiAdapter api = mmgr.getApiAdapter();
    if (element.embedded == null) {
      // Assign default for "embedded-element" based on 18.13.1 of JDO 2 spec
      // Note : this fails when using in the enhancer since not yet PC
      if (mmgr.getNucleusContext().getTypeManager().isDefaultEmbeddedType(elementTypeClass)) {
        element.embedded = Boolean.TRUE;
      } else if (api.isPersistable(elementTypeClass)
          || Object.class.isAssignableFrom(elementTypeClass)
          || elementTypeClass.isInterface()) {
        element.embedded = Boolean.FALSE;
      } else {
        element.embedded = Boolean.TRUE;
      }
    }
    if (Boolean.FALSE.equals(element.embedded)) {
      // If the user has set a non-PC/non-Interface as not embedded, correct it since not supported.
      // Note : this fails when using in the enhancer since not yet PC
      if (!api.isPersistable(elementTypeClass)
          && !elementTypeClass.isInterface()
          && elementTypeClass != java.lang.Object.class) {
        element.embedded = Boolean.TRUE;
      }
    }

    ElementMetaData elemmd = ((AbstractMemberMetaData) parent).getElementMetaData();
    if (elemmd != null && elemmd.getEmbeddedMetaData() != null) {
      element.embedded = Boolean.TRUE;
    }

    if (Boolean.TRUE.equals(element.dependent)) {
      // If the user has set a non-PC/non-reference as dependent, correct it since not valid.
      // Note : this fails when using in the enhancer since not yet PC
      if (!api.isPersistable(elementTypeClass)
          && !elementTypeClass.isInterface()
          && elementTypeClass != java.lang.Object.class) {
        element.dependent = Boolean.FALSE;
      }
    }

    // Keep a reference to the MetaData for the element
    element.classMetaData = mmgr.getMetaDataForClassInternal(elementTypeClass, clr);

    // Make sure anything in the superclass is populated too
    super.populate(clr, primary, mmgr);

    setPopulated();
  }