diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java index 35ec29cfd..5c2e2a3e4 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java @@ -90,8 +90,9 @@ public class PCEnhancer { public static final int ENHANCE_NONE = 0; public static final int ENHANCE_AWARE = 2 << 0; - public static final int ENHANCE_PC = 2 << 1; - public static final int ENHANCE_OID = 2 << 2; + public static final int ENHANCE_INTERFACE = 2 << 1; + public static final int ENHANCE_PC = 2 << 2; + public static final int ENHANCE_OID = 2 << 3; private static final String PRE = "pc"; private static final Class PCTYPE = PersistenceCapable.class; @@ -127,7 +128,7 @@ public class PCEnhancer { * Constructor. Supply configuration and type to enhance. */ public PCEnhancer(OpenJPAConfiguration conf, Class type) { - this(conf, new Project().loadClass(type), null); + this(conf, new Project().loadClass(type), (MetaDataRepository) null); } /** @@ -163,6 +164,17 @@ public class PCEnhancer { _meta = _repos.getMetaData(type.getType(), null, false); } + /** + * Constructor. Supply configuration, type, and metadata. + */ + public PCEnhancer(OpenJPAConfiguration conf, BCClass type, + ClassMetaData meta) { + _pc = type; + _log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE); + _repos = meta.getRepository(); + _meta = meta; + } + /** * Return the bytecode representation of the class being manipulated. */ @@ -266,6 +278,10 @@ public class PCEnhancer { _log.trace(_loc.get("enhance-start", _pc.getType())); try { + // if managed interface, skip + if (_pc.isInterface()) + return ENHANCE_INTERFACE; + // check if already enhanced Class[] interfaces = _pc.getDeclaredInterfaceTypes(); for (int i = 0; i < interfaces.length; i++) { @@ -612,13 +628,13 @@ public class PCEnhancer { String prefix = (get) ? PRE + "Get" : PRE + "Set"; methodName = prefix + name; if (get) { - mi.setMethod(owner.getDescribedType().getName(), + mi.setMethod(getType(owner).getName(), methodName, typeName, new String[] - { owner.getDescribedType().getName() }); + { getType(owner).getName() }); } else { - mi.setMethod(owner.getDescribedType().getName(), + mi.setMethod(getType(owner).getName(), methodName, "void", new String[] - { owner.getDescribedType().getName(), typeName }); + { getType(owner).getName(), typeName }); } } } @@ -659,6 +675,10 @@ public class PCEnhancer { if (owner.getName().equals(Object.class.getName())) return null; + // managed interface + if (_meta != null && _meta.getDescribedType().isInterface()) + return _meta; + return _repos.getMetaData(owner, null, false); } @@ -722,8 +742,9 @@ public class PCEnhancer { // super.pcClearFields () if (_meta.getPCSuperclass() != null) { code.aload().setThis(); - code.invokespecial().setMethod(_meta.getPCSuperclass(), - PRE + "ClearFields", void.class, null); + code.invokespecial().setMethod(getType(_meta. + getPCSuperclassMetaData()), PRE + "ClearFields", void.class, + null); } FieldMetaData[] fmds = _meta.getDeclaredFields(); @@ -849,7 +870,8 @@ public class PCEnhancer { // return + .pcGetManagedFieldCount () code.constant().setValue(_meta.getDeclaredFields().length); if (_meta.getPCSuperclass() != null) { - code.invokestatic().setMethod(_meta.getPCSuperclass().getName(), + code.invokestatic().setMethod(getType(_meta. + getPCSuperclassMetaData()).getName(), PRE + "GetManagedFieldCount", int.class.getName(), null); code.iadd(); } @@ -1039,14 +1061,15 @@ public class PCEnhancer { loadManagedInstance(code, false); String[] args; if (copy) { - args = new String[]{ _meta.getPCSuperclass().getName(), - int.class.getName() }; + args = new String[]{ getType(_meta.getPCSuperclassMetaData()). + getName(), int.class.getName() }; code.aload().setParam(0); } else args = new String[]{ int.class.getName() }; code.iload().setParam(fieldNumber); - code.invokespecial().setMethod(_meta.getPCSuperclass(). - getName(), name, void.class.getName(), args); + code.invokespecial().setMethod(getType(_meta. + getPCSuperclassMetaData()).getName(), name, + void.class.getName(), args); code.vreturn(); } else throwException(code, IllegalArgumentException.class); @@ -1442,7 +1465,8 @@ public class PCEnhancer { loadManagedInstance(code, false); for (int i = 0; i < args.length; i++) code.aload().setParam(i); - code.invokespecial().setMethod(_meta.getPCSuperclass().getName(), + code.invokespecial().setMethod(getType(_meta. + getPCSuperclassMetaData()).getName(), PRE + "CopyKeyFieldsToObjectId", void.class.getName(), args); } @@ -1535,7 +1559,8 @@ public class PCEnhancer { loadManagedInstance(code, false); for (int i = 0; i < args.length; i++) code.aload().setParam(i); - code.invokespecial().setMethod(_meta.getPCSuperclass().getName(), + code.invokespecial().setMethod(getType(_meta. + getPCSuperclassMetaData()).getName(), PRE + "CopyKeyFieldsFromObjectId", void.class.getName(), args); } @@ -1729,14 +1754,14 @@ public class PCEnhancer { // new ObjectId (cls, oid) code.anew().setType(ObjectId.class); code.dup(); - code.classconstant().setClass(_meta.getDescribedType()); + code.classconstant().setClass(getType(_meta)); } // new (); code.anew().setType(oidType); code.dup(); if (_meta.isOpenJPAIdentity() || (obj && usesClsString == Boolean.TRUE)) - code.classconstant().setClass(_meta.getDescribedType()); + code.classconstant().setClass(getType(_meta)); if (obj) { code.aload().setParam(0); code.checkcast().setType(String.class); @@ -1926,12 +1951,14 @@ public class PCEnhancer { Code code = getOrCreateClassInitCode(true); if (_meta.getPCSuperclass() != null) { // pcInheritedFieldCount = .pcGetManagedFieldCount() - code.invokestatic().setMethod(_meta.getPCSuperclass().getName(), + code.invokestatic().setMethod(getType(_meta. + getPCSuperclassMetaData()).getName(), PRE + "GetManagedFieldCount", int.class.getName(), null); code.putstatic().setField(INHERIT, int.class); // pcPCSuperclass = ; - code.classconstant().setClass(_meta.getPCSuperclass()); + code.classconstant().setClass(getType(_meta. + getPCSuperclassMetaData())); code.putstatic().setField(SUPER, Class.class); } @@ -2961,7 +2988,7 @@ public class PCEnhancer { // readUnmanaged (in); loadManagedInstance(code, false); code.aload().setParam(0); - code.invokevirtual().setMethod(_meta.getDescribedType(), + code.invokevirtual().setMethod(getType(_meta), PRE + "ReadUnmanaged", void.class, inargs); if (detachedState) { @@ -3013,8 +3040,9 @@ public class PCEnhancer { if (parentDetachable) { loadManagedInstance(code, false); code.aload().setParam(0); - code.invokespecial().setMethod(_meta.getPCSuperclass(), - PRE + "ReadUnmanaged", void.class, inargs); + code.invokespecial().setMethod(getType(_meta. + getPCSuperclassMetaData()), PRE + "ReadUnmanaged", void.class, + inargs); } // read declared unmanaged serializable fields @@ -3091,7 +3119,7 @@ public class PCEnhancer { Code code = meth.getCode(true); // super.writeExternal (out); - Class sup = _meta.getDescribedType().getSuperclass(); + Class sup = getType(_meta).getSuperclass(); if (!parentDetachable && Externalizable.class.isAssignableFrom(sup)) { loadManagedInstance(code, false); code.aload().setParam(0); @@ -3102,7 +3130,7 @@ public class PCEnhancer { // writeUnmanaged (out); loadManagedInstance(code, false); code.aload().setParam(0); - code.invokevirtual().setMethod(_meta.getDescribedType(), + code.invokevirtual().setMethod(getType(_meta), PRE + "WriteUnmanaged", void.class, outargs); JumpInstruction go2 = null; @@ -3169,8 +3197,9 @@ public class PCEnhancer { if (parentDetachable) { loadManagedInstance(code, false); code.aload().setParam(0); - code.invokespecial().setMethod(_meta.getPCSuperclass(), - PRE + "WriteUnmanaged", void.class, outargs); + code.invokespecial().setMethod(getType(_meta. + getPCSuperclassMetaData()), PRE + "WriteUnmanaged", void.class, + outargs); } // write declared unmanaged serializable fields @@ -3316,7 +3345,7 @@ public class PCEnhancer { // static void pcSet (XXX inst, value) BCField field = _pc.getDeclaredField(fmd.getName()); setter = _pc.declareMethod(PRE + "Set" + fmd.getName(), void.class, - new Class[]{ _meta.getDescribedType(), fmd.getDeclaredType() }); + new Class[]{ getType(_meta), fmd.getDeclaredType() }); setter.setAccessFlags(field.getAccessFlags() & ~Constants.ACCESS_TRANSIENT & ~Constants.ACCESS_VOLATILE); setter.setStatic(true); @@ -3337,6 +3366,17 @@ public class PCEnhancer { return setter; } + /** + * Return the concrete type for the given class, i.e. impl for managed + * interfaces + */ + public Class getType(ClassMetaData meta) { + if (meta.getInterfaceImpl() != null) + return meta.getInterfaceImpl(); + return meta.getDescribedType(); + } + + /** * Move code-related attributes from one method to another. */ @@ -3479,6 +3519,8 @@ public class PCEnhancer { status = enhancer.run(); if (status == ENHANCE_NONE) log.info(_loc.get("enhance-norun")); + else if (status == ENHANCE_INTERFACE) + log.info(_loc.get("enhance-interface")); else if (status == ENHANCE_AWARE) { log.info(_loc.get("enhance-aware")); enhancer.record(); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java index 729e22f2e..51ff98d9c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java @@ -2494,6 +2494,9 @@ public class BrokerImpl PersistenceCapable copy; PCState state; + Class type = meta.getDescribedType(); + if (type.isInterface()) + type = meta.getInterfaceImpl(); if (obj != null) { // give copy and the original instance the same state manager // so that we can copy fields from one to the other @@ -2512,8 +2515,7 @@ public class BrokerImpl // copy the instance. we do this even if it doesn't already // have a state manager in case it is later assigned to a // PC field; at that point it's too late to copy - copy = PCRegistry.newInstance(meta.getDescribedType(), - copySM, false); + copy = PCRegistry.newInstance(type, copySM, false); int[] fields = new int[meta.getFields().length]; for (int i = 0; i < fields.length; i++) fields[i] = i; @@ -2527,8 +2529,7 @@ public class BrokerImpl pc.pcReplaceStateManager(null); } } else { - copy = PCRegistry.newInstance(meta.getDescribedType(), sm, - false); + copy = PCRegistry.newInstance(type, sm, false); if ((_flags & FLAG_ACTIVE) != 0 && !_optimistic) state = PCState.ECLEAN; else @@ -3986,8 +3987,11 @@ public class BrokerImpl public Object newInstance(Class cls) { assertOpen(); - //### JDO2 - if (cls.isInterface() || Modifier.isAbstract(cls.getModifiers())) + if (cls.isInterface()) { + ClassMetaData meta = _conf.getMetaDataRepositoryInstance(). + getMetaData(cls, _loader, true); + cls = meta.getInterfaceImpl(); + } else if (Modifier.isAbstract(cls.getModifiers())) throw new UnsupportedOperationException(_loc.get ("new-abstract", cls).getMessage()); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java index 3c7442831..db1cbf004 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java @@ -241,6 +241,8 @@ public class StateManagerImpl } _meta = sub; } + if (cls.isInterface()) + cls = _meta.getInterfaceImpl(); PersistenceCapable inst = PCRegistry.newInstance(cls, this, _oid, true); if (inst == null) { diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java index 4e27140a9..4ab3b9c37 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java @@ -41,6 +41,7 @@ public abstract class AbstractMetaDataDefaults private int _access = ClassMetaData.ACCESS_FIELD; private boolean _ignore = true; + private boolean _interface = true; private boolean _pcRegistry = true; private int _callback = CALLBACK_RETHROW; @@ -170,7 +171,8 @@ public abstract class AbstractMetaDataDefaults */ private void populateFromReflection(ClassMetaData meta) { Member[] members; - if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD) + boolean iface = meta.getDescribedType().isInterface(); + if (meta.getAccessType() == ClassMetaData.ACCESS_FIELD && !iface) members = meta.getDescribedType().getDeclaredFields(); else members = meta.getDescribedType().getDeclaredMethods(); @@ -263,6 +265,14 @@ public abstract class AbstractMetaDataDefaults protected abstract boolean isDefaultPersistent(ClassMetaData meta, Member member, String name); + public void setDeclaredInterfacePersistent(boolean pers) { + _interface = pers; + } + + public boolean isDeclaredInterfacePersistent() { + return _interface; + } + public Member getBackingMember(FieldMetaData fmd) { if (fmd == null) return null; @@ -321,6 +331,10 @@ public abstract class AbstractMetaDataDefaults new String[]{ name, clsName, "get" + capName, "is" + capName })); } + public Class getUnimplementedExceptionType() { + return UnsupportedOperationException.class; + } + /** * Helper method; returns true if the given class appears to be * user-defined. diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java index af47d0c57..8d271f09c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java @@ -140,6 +140,8 @@ public class ClassMetaData private Boolean _openjpaId = null; private Boolean _extent = null; private Boolean _embedded = null; + private Boolean _interface = null; + private Class _impl = null; private int _identity = -1; private int _idStrategy = ValueStrategies.NONE; private int _accessType = ACCESS_UNKNOWN; @@ -215,9 +217,8 @@ public class ClassMetaData * an embedded value changes its declared type. */ protected void setDescribedType(Class type) { - if (type.isInterface()) - throw new MetaDataException(_loc.get("interface", type)); - if ("java.lang.Enum".equals(type.getSuperclass().getName())) + if (type.getSuperclass() != null && "java.lang.Enum".equals + (type.getSuperclass().getName())) throw new MetaDataException(_loc.get("enum", type)); _type = type; } @@ -669,6 +670,38 @@ public class ClassMetaData _embedded = (embed) ? Boolean.TRUE : Boolean.FALSE; } + /** + * Whether the type is a managed interface. + */ + public boolean isManagedInterface() { + if (!_type.isInterface()) + return false; + return _interface == null ? false : _interface.booleanValue(); + } + + /** + * Whether the type is a managed interface + */ + public void setManagedInterface(boolean managedInterface) { + if (!_type.isInterface()) + throw new MetaDataException(_loc.get("not-interface", _type)); + _interface = managedInterface ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Return the managed interface implementor if any. + */ + public Class getInterfaceImpl() { + return _impl; + } + + /** + * Set the managed interface implementor class. + */ + public void setInterfaceImpl(Class impl) { + _impl = impl; + } + /** * Return the number of fields that use impl or intermediate data, in * order to create a compacted array for storage of said data. @@ -1481,7 +1514,19 @@ public class ClassMetaData log.trace(_loc.get((embed) ? "resolve-embed-meta" : "resolve-meta", this + "@" + System.identityHashCode(this))); - if (runtime && !PersistenceCapable.class.isAssignableFrom(_type)) + if (_type.isInterface()) { + if (!embed && _interface != Boolean.TRUE) + throw new MetaDataException(_loc.get("interface", _type)); + + if (runtime) { + _impl = _repos.getImplGenerator().createImpl(this); + if (!embed) + _repos.setInterfaceImpl(this, _impl); + } + } + + if (runtime && !_type.isInterface() && + !PersistenceCapable.class.isAssignableFrom(_type)) throw new MetaDataException(_loc.get("not-enhanced", _type)); // are we the target of an embedded value? @@ -2113,6 +2158,8 @@ public class ClassMetaData _objectId = meta.getObjectIdType(); _extent = (meta.getRequiresExtent()) ? Boolean.TRUE : Boolean.FALSE; _embedded = (meta.isEmbeddedOnly()) ? Boolean.TRUE : Boolean.FALSE; + _interface = (meta.isManagedInterface()) ? Boolean.TRUE : Boolean.FALSE; + _impl = meta.getInterfaceImpl(); _identity = meta.getIdentityType(); _idStrategy = meta.getIdentityStrategy(); _seqName = meta.getIdentitySequenceName(); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java index c4f267774..0a8954694 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InheritanceComparator.java @@ -62,8 +62,14 @@ class InheritanceComparator int i1 = levels(c1); int i2 = levels(c2); - if (i1 == i2) + if (i1 == i2) { + // sort simple interfaces as well as simple order test will fail. + if (c1.isAssignableFrom(o2.getClass())) + return -1; + if (c2.isAssignableFrom(o1.getClass())) + return 1; return c1.getName().compareTo(c2.getName()); + } return i1 - i2; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java index cf072abc4..63564dac9 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java @@ -50,6 +50,12 @@ public interface MetaDataDefaults */ public void setIgnoreNonPersistent(boolean ignore); + /** + * Whether declared interfaces of a class are treated as persistent + * types. Defaults to true. + */ + public boolean isDeclaredInterfacePersistent(); + /** * Populate the given metadata with default settings. * @@ -61,4 +67,10 @@ public interface MetaDataDefaults * Return the backing member for the given field metadata. */ public Member getBackingMember(FieldMetaData field); + + /** + * Return a runtime exception class to throw for un-implemented + * managed interface methods. + */ + public Class getUnimplementedExceptionType(); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataInheritanceComparator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataInheritanceComparator.java index 503ec37ce..1c5e0c4d1 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataInheritanceComparator.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataInheritanceComparator.java @@ -25,7 +25,11 @@ public class MetaDataInheritanceComparator extends InheritanceComparator { protected Class toClass(Object elem) { - return (elem == null) ? null - : ((ClassMetaData) elem).getDescribedType(); + if (elem == null) + return null; + ClassMetaData meta = (ClassMetaData) elem; + if (meta.getInterfaceImpl() != null) + return meta.getInterfaceImpl(); + return meta.getDescribedType(); } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java index 0dd1276ba..81bf0756b 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java @@ -105,6 +105,7 @@ public class MetaDataRepository private final Map _metas = new HashMap(); private final Map _oids = Collections.synchronizedMap(new HashMap()); private final Map _impls = Collections.synchronizedMap(new HashMap()); + private final Map _ifaces = Collections.synchronizedMap(new HashMap()); private final Map _queries = new HashMap(); private final Map _seqs = new HashMap(); private final Map _aliases = Collections.synchronizedMap(new HashMap()); @@ -116,6 +117,7 @@ public class MetaDataRepository private OpenJPAConfiguration _conf = null; private Log _log = null; private MetaDataFactory _factory = null; + private InterfaceImplGenerator _implGen = null; private int _resMode = MODE_META | MODE_MAPPING; private int _sourceMode = MODE_META | MODE_MAPPING | MODE_QUERY; private int _validate = VALIDATE_META | VALIDATE_UNENHANCED; @@ -541,6 +543,18 @@ public class MetaDataRepository } else sup = sup.getSuperclass(); } + if (meta.getDescribedType().isInterface()) { + Class[] sups = meta.getDescribedType().getInterfaces(); + for (int i = 0; i < sups.length; i++) { + supMeta = getMetaData(sups[i], meta.getEnvClassLoader(), + false); + if (supMeta != null) { + meta.setPCSuperclass(sup); + meta.setPCSuperclassMetaData(supMeta); + break; + } + } + } if (_log.isTraceEnabled()) _log.trace(_loc.get("assigned-sup", meta, meta.getPCSuperclass())); @@ -845,12 +859,41 @@ public class MetaDataRepository if (cls == null) return false; if (_metas.remove(cls) != null) { + Class impl = (Class) _ifaces.remove(cls); + if (impl != null) + _metas.remove(impl); _count--; return true; } return false; } + + /** + * Add the given metadata as declared interface implementation. + */ + public void addDeclaredInterfaceImpl(ClassMetaData meta, Class iface) { + synchronized (_impls) { + addToCollection(_impls, iface, meta.getDescribedType(), false); + } + } + + /** + * Set the implementation for the given managed interface. + */ + synchronized void setInterfaceImpl(ClassMetaData meta, Class impl) { + if (!meta.isManagedInterface()) + throw new MetaDataException(_loc.get("not-managed-interface", + meta, impl)); + _ifaces.put(meta.getDescribedType(), impl); + _metas.put(impl, meta); + } + synchronized InterfaceImplGenerator getImplGenerator() { + if (_implGen == null) + _implGen = new InterfaceImplGenerator(this); + return _implGen; + } + /** * Return the least-derived class metadata for the given application * identity object. @@ -1274,6 +1317,8 @@ public class MetaDataRepository * Update the list of implementations of base classes and interfaces. */ private void updateImpls(Class cls, Class leastDerived, Class check) { + if (_factory.getDefaults().isDeclaredInterfacePersistent()) + return; // allow users to query on common non-pc superclasses Class sup = check.getSuperclass(); if (leastDerived == cls && sup != null && sup != Object.class) { diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java index 5b522202c..0ec15ffd5 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java @@ -104,10 +104,18 @@ public class NoneMetaDataFactory public void setIgnoreNonPersistent(boolean ignore) { } + public boolean isDeclaredInterfacePersistent() { + return false; + } + public void populate(ClassMetaData meta, int access) { } public Member getBackingMember(FieldMetaData fmd) { return null; } + + public Class getUnimplementedExceptionType() { + return null; + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java index b44ace791..12a5eb93b 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java @@ -257,8 +257,11 @@ public class ApplicationIds { // to the original oid values, then copy its key fields to a new // oid instance if (!Modifier.isAbstract(meta.getDescribedType().getModifiers())) { - PersistenceCapable pc = PCRegistry.newInstance - (meta.getDescribedType(), null, oid, false); + Class type = meta.getDescribedType(); + if (meta.getInterfaceImpl() != null) + type = meta.getInterfaceImpl(); + PersistenceCapable pc = PCRegistry.newInstance(type, null, oid, + false); Object copy = pc.pcNewObjectIdInstance(); pc.pcCopyKeyFieldsToObjectId(copy); return copy; diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties index 2991f5725..32552403d 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/enhance/localizer.properties @@ -24,6 +24,7 @@ enhance-running-oids: Enhancer running on oid: {0} enhance-aware: The class does not have metadata - enhanced as persistence-aware. enhance-norun: The class is already persistence capable - no enhancement \ performed. +enhance-interface: The class is a managed interface - no enhancement performed. enhance-usage: Usage: java org.apache.openjpa.enhance.PCEnhancer\n\ \t[-properties/-p ]\n\ \t[- ]*\n\ diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties index e0e094935..e817c643e 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties @@ -4,8 +4,8 @@ unloaded-detached: Attempt to access an unloaded field of detached instance \ "{0}". meta-unknownid: Cannot manipulate identity of type "{0}": it''s identity type \ is unknown. -new-abstract: Cannot create an instance of "{0}": abstract classes and \ - interfaces are not yet supported. +new-abstract: Cannot create an instance of "{0}": abstract classes are not \ + yet supported. bad-new-query: Attempt to construct a query from an extent or class. You must \ pass a (possibly null) query string or template to the query factory \ method when creating the query. diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties index 497d31181..41e7d3e81 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/meta/localizer.properties @@ -18,6 +18,8 @@ clear-repos: Clearing metadata repository "{0}". process-registered: Processing registered persistence-capable class "{0}". assigned-sup: Set persistence-capable superclass of "{0}" to "{1}". found-pcs: Found {0} classes with metadata in {1} milliseconds. +not-managed-interface: Cannot set type "{1}" as interface "{0}" implementor. \ + "{0}" is not a managed interface. unmanaged-sup-field: Superclass field "{0}" is mapped in the metadata for \ subclass "{1}", but is not a persistent field. bad-discover-class: The class "{0}" listed in the openjpa.MetaDataFactory \ @@ -180,7 +182,10 @@ bad-update-strategy: "{0}" declares a read only value of "{1}". \ bad-update-strategy-hint: "{0}" declares a read only value of \ "{1}". This is not a recognized strategy, though it closely resembles \ the standard strategy "{2}". Available strategies are: {3} -interface: Type "{0}" is an interface and therefore cannot be made persistent. +not-interface: Can't set type "{0}" to be a managed interface as it is not \ + and interface. +interface: The type "{0}" is an unmanaged interface and therefore cannot be \ + made persistent. enum: Type "{0}" is an enumeration and therefore cannot be made persistent. bad-drop: The metadata for some of the following classes may not have \ been dropped: {0}