Author: ppoddar
Date: Tue Sep 26 12:23:48 2006
New Revision: 450158
URL: http://svn.apache.org/viewvc?view=rev&rev=450158
Log:
Applying the constraints that the entity listner class
a) must have a no-arg constructor
b) multiple methods of the same class must not register for the same event
(JPA Spec Section 3.5)
Modified:
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
Modified:
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java?view=diff&rev=450158&r1=450157&r2=450158
==============================================================================
---
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
(original)
+++
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
Tue Sep 26 12:23:48 2006
@@ -45,6 +45,8 @@
private boolean _interface = true;
private boolean _pcRegistry = true;
private int _callback = CALLBACK_RETHROW;
+ private boolean _allowsMultipleMethodsOnSameCallback = true;
+ private boolean _allowsMissingCallbackConstructor = true;
/**
* Whether to attempt to use the information from registered classes
@@ -352,6 +354,22 @@
return UnsupportedOperationException.class;
}
+ public boolean getAllowsMultipleMethodsOnSameCallback() {
+ return _allowsMultipleMethodsOnSameCallback;
+ }
+
+ public void setAllowsMultipleMethodsOnSameCallback(boolean flag) {
+ _allowsMultipleMethodsOnSameCallback = flag;
+ }
+
+ public boolean getAllowsMissingCallbackConstructor() {
+ return _allowsMissingCallbackConstructor;
+ }
+
+ public void setAllowsMissingCallbackConstructor(boolean flag) {
+ _allowsMissingCallbackConstructor = flag;
+ }
+
/**
* Helper method; returns true if the given class appears to be
* user-defined.
Modified:
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java?view=diff&rev=450158&r1=450157&r2=450158
==============================================================================
---
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java
(original)
+++
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataDefaults.java
Tue Sep 26 12:23:48 2006
@@ -49,7 +49,17 @@
* event type. Defaults to false.
*/
public boolean getCallbacksBeforeListeners(int type);
+
+ /** Flags if multiple methods of the same class can handle the same
+ * callback event.
+ */
+ public boolean getAllowsMultipleMethodsOnSameCallback();
+ /** Flags if it allowed for the callback listener class not to have a
no-arg
+ * constructor.
+ */
+ public boolean getAllowsMissingCallbackConstructor();
+
/**
* Whether to ignore members which are not persistent by default
* during metadata population. Defaults to true.
Modified:
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java?view=diff&rev=450158&r1=450157&r2=450158
==============================================================================
---
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java
(original)
+++
incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/NoneMetaDataFactory.java
Tue Sep 26 12:23:48 2006
@@ -122,4 +122,12 @@
public Class getUnimplementedExceptionType() {
return null;
}
+
+ public boolean getAllowsMultipleMethodsOnSameCallback() {
+ return true;
+ }
+
+ public boolean getAllowsMissingCallbackConstructor() {
+ return true;
+ }
}
Modified:
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java?view=diff&rev=450158&r1=450157&r2=450158
==============================================================================
---
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
(original)
+++
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
Tue Sep 26 12:23:48 2006
@@ -84,6 +84,7 @@
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.util.Localizer.Message;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.DelegatingMetaDataFactory;
import org.apache.openjpa.meta.FieldMetaData;
@@ -98,12 +99,13 @@
import org.apache.openjpa.meta.UpdateStrategies;
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.meta.ValueStrategies;
+import org.apache.openjpa.meta.MetaDataDefaults;
import static org.apache.openjpa.persistence.MetaDataTag.*;
-import static org.apache.openjpa.persistence.MetaDataTag.LRS;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.UnsupportedException;
+import org.apache.openjpa.util.UserException;
import serp.util.Numbers;
import serp.util.Strings;
@@ -769,7 +771,7 @@
* @param sups whether to scan superclasses
* @param listener whether this is a listener or not
*/
- public static Collection<LifecycleCallbacks>[] parseCallbackMethods
+ public Collection<LifecycleCallbacks>[] parseCallbackMethods
(Class cls, Collection<LifecycleCallbacks>[] callbacks, boolean sups,
boolean listener) {
// first sort / filter based on inheritance
@@ -813,9 +815,15 @@
for (int i = 0; events != null && i < events.length; i++) {
int e = events[i];
- if (callbacks[e] == null)
- callbacks[e] = new ArrayList(3);
+ if (!verifyHasNoArgConstructor(cls))
+ continue;
+ if (!verifyMultipleMethodsOnSameEvent(cls, callbacks[e],
m,
+ tag))
+ continue;
+ if (callbacks[e] == null)
+ callbacks[e] = new ArrayList(3);
+
if (listener) {
callbacks[e].add(new BeanLifecycleCallbacks(cls, m,
false));
@@ -829,6 +837,51 @@
return callbacks;
}
+ private boolean verifyMultipleMethodsOnSameEvent(Class cls,
+ Collection<LifecycleCallbacks> callbacks, Method method,
+ MetaDataTag tag) {
+ boolean result = true;
+ if (callbacks == null || callbacks.isEmpty())
+ return true;
+ MetaDataDefaults defaults = getRepository().getMetaDataFactory().
+ getDefaults();
+ for (LifecycleCallbacks lc: callbacks) {
+ if (!(lc instanceof MethodLifecycleCallbacks))
+ continue;
+ Method exists = ((MethodLifecycleCallbacks)lc).getCallbackMethod();
+ if (exists.getDeclaringClass().equals(method.getDeclaringClass()))
{
+ result = false;
+ Object[] args = new Object[]{method.getDeclaringClass()
+ .getName(), method.getName(), exists.getName(),
+ tag.toString()};
+ if (defaults.getAllowsMultipleMethodsOnSameCallback()) {
+ _log.warn(_loc.get("multiple-methods-on-callback",
+ args));
+ } else {
+ throw new UserException(
+ _loc.get("multiple-methods-on-callback-error", args));
+ }
+ }
+ }
+ return result;
+ }
+
+ private boolean verifyHasNoArgConstructor(Class cls) {
+ MetaDataDefaults defaults = getRepository().getMetaDataFactory().
+ getDefaults();
+ try {
+ cls.getConstructor(new Class[]{});
+ return true;
+ } catch (Throwable t) {
+ Message msg = _loc.get("missing-no-arg-constructor",
cls.getName());
+ if (defaults.getAllowsMissingCallbackConstructor())
+ _log.warn(msg);
+ else
+ throw new UserException(msg, t);
+ }
+ return false;
+ }
+
/**
* Store lifecycle metadata.
*/
Modified:
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java?view=diff&rev=450158&r1=450157&r2=450158
==============================================================================
---
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
(original)
+++
incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/XMLPersistenceMetaDataParser.java
Tue Sep 26 12:23:48 2006
@@ -1485,9 +1485,9 @@
throws SAXException {
_listener = classForName(attrs.getValue("class"));
boolean system = currentElement() == null;
- Collection<LifecycleCallbacks>[] parsed =
- AnnotationPersistenceMetaDataParser.parseCallbackMethods(_listener,
- null, true, true);
+ Collection<LifecycleCallbacks>[] parsed =
+ new AnnotationPersistenceMetaDataParser(_conf).parseCallbackMethods
+ (_listener, null, true, true);
if (parsed == null)
return true;
@@ -1593,8 +1593,8 @@
Class supCls = cls.getDescribedType().getSuperclass();
Collection<LifecycleCallbacks>[] supCalls = null;
if (!Object.class.equals(supCls)) {
- supCalls = AnnotationPersistenceMetaDataParser.parseCallbackMethods
- (supCls, null, true, false);
+ supCalls = new AnnotationPersistenceMetaDataParser(_conf).
+ parseCallbackMethods(supCls, null, true, false);
}
if (supCalls != null) {
for (int event : LifecycleEvent.ALL_EVENTS) {
Modified:
incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties?view=diff&rev=450158&r1=450157&r2=450158
==============================================================================
---
incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
(original)
+++
incubator/openjpa/trunk/openjpa-persistence/src/main/resources/org/apache/openjpa/persistence/localizer.properties
Tue Sep 26 12:23:48 2006
@@ -91,4 +91,12 @@
system-listener-err: An error occurred invoking system entity listener \
callback on instance "{0}".
no-transaction: Cannot perform operation with no transaction.
-
+multiple-methods-on-callback: Class "{0}" declares method "{1}" as well \
+ as "{2}" for handling the same "{3}" callback.
+multiple-methods-on-callback-error: Class "{0}" declares method "{1}" as well \
+ as "{2}" for handling the same "{3}" callback. \
+ "AllowsMultipleMethodsOnSameCallback" property of MetaDataDefaults can
be \
+ set to true to supress this exception.
+missing-no-arg-constructor: Entity listener class "{0}" must declare a no-arg \
+ constructor. "AllowsNoArgConstructorCallback" property of
MetaDataDefaults \
+ can be set to true to ignore this exception.