mirror of https://github.com/apache/openjpa.git
Improve error message when checking metadata access types; correct recursive method to always include superclass information.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@614606 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
3aa60007dd
commit
13dd4f2252
|
@ -24,6 +24,7 @@ import java.lang.reflect.Method;
|
|||
import java.lang.reflect.Modifier;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.openjpa.enhance.PCRegistry;
|
||||
import org.apache.openjpa.enhance.Reflection;
|
||||
|
@ -153,9 +154,17 @@ public abstract class AbstractMetaDataDefaults
|
|||
// the same time
|
||||
access = getAccessType(meta);
|
||||
if ((access & ClassMetaData.ACCESS_FIELD) != 0
|
||||
&& (access & ClassMetaData.ACCESS_PROPERTY) != 0)
|
||||
throw new UserException(_loc.get("access-field-and-prop",
|
||||
meta.getDescribedType().getName()));
|
||||
&& (access & ClassMetaData.ACCESS_PROPERTY) != 0) {
|
||||
List fields = getFieldAccessNames(meta);
|
||||
List props = getPropertyAccessNames(meta);
|
||||
if (fields != null || props != null)
|
||||
throw new UserException(_loc.get(
|
||||
"access-field-and-prop-hints",
|
||||
meta.getDescribedType().getName(), fields, props));
|
||||
else
|
||||
throw new UserException(_loc.get("access-field-and-prop",
|
||||
meta.getDescribedType().getName()));
|
||||
}
|
||||
}
|
||||
meta.setAccessType(access);
|
||||
|
||||
|
@ -263,6 +272,34 @@ public abstract class AbstractMetaDataDefaults
|
|||
return ClassMetaData.ACCESS_FIELD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of fields in <code>meta</code> that use field access,
|
||||
* or <code>null</code> if a list of fields is unobtainable. An empty list
|
||||
* should be returned if the list of fields is obtainable, but there
|
||||
* happens to be no field access in <code>meta</code>.
|
||||
*
|
||||
* This is used for error reporting purposes only, so need not be efficient.
|
||||
*
|
||||
* This implementation returns <code>null</code>.
|
||||
*/
|
||||
protected List getFieldAccessNames(ClassMetaData meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of methods in <code>meta</code> that use property access,
|
||||
* or <code>null</code> if a list of methods is unobtainable. An empty list
|
||||
* should be returned if the list of methods is obtainable, but there
|
||||
* happens to be no property access in <code>meta</code>.
|
||||
*
|
||||
* This is used for error reporting purposes only, so need not be efficient.
|
||||
*
|
||||
* This implementation returns <code>null</code>.
|
||||
*/
|
||||
protected List getPropertyAccessNames(ClassMetaData meta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the field name for the given member. This will only be invoked
|
||||
* on members of the right type (field vs. method). Return null if the
|
||||
|
|
|
@ -267,6 +267,10 @@ lifecycle-resolved: Could add the following callback adapters to "{0}", as \
|
|||
the lifecycle metadata is already resolved: {1}
|
||||
access-field-and-prop: Type "{0}" attempts to use both field and property \
|
||||
access. Only one access method is permitted.
|
||||
access-field-and-prop-hints: Type "{0}" attempts to use both field and \
|
||||
property access. Only one access method is permitted. Field access is used \
|
||||
on the following fields: {1}. Property access is used on the following \
|
||||
methods: {2}.
|
||||
unsupported-id-type: Type "{0}" declares field "{1}" as a primary key, but \
|
||||
keys of type "{2}" are not supported.
|
||||
empty-fg-name: Attempt to add an unnamed fetch group to "{0}".
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.jdbc.annotations;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
import org.apache.openjpa.persistence.test.PersistenceTestCase;
|
||||
|
||||
public class TestMixedAccess extends PersistenceTestCase {
|
||||
|
||||
public void testMixedAccessEntityError() {
|
||||
try {
|
||||
EntityManagerFactory emf = createEMF(UnenhancedMixedAccess.class);
|
||||
emf.createEntityManager().close();
|
||||
} catch (RuntimeException e) {
|
||||
String msg = e.getMessage();
|
||||
if (!(msg.contains("UnenhancedMixedAccess.id") &&
|
||||
msg.contains("UnenhancedMixedAccess.getStringField")))
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public void testInappropriateTransientError() {
|
||||
try {
|
||||
EntityManagerFactory emf = createEMF(
|
||||
UnenhancedInappropriateTransient.class);
|
||||
emf.createEntityManager().close();
|
||||
} catch (RuntimeException e) {
|
||||
String msg = e.getMessage();
|
||||
if (!(msg.contains("UnenhancedInappropriateTransient.id") &&
|
||||
msg.contains("UnenhancedInappropriateTransient.prePersist")))
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.jdbc.annotations;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.PrePersist;
|
||||
|
||||
@Entity
|
||||
public class UnenhancedInappropriateTransient {
|
||||
|
||||
@Id private int id;
|
||||
|
||||
@Transient @PrePersist public void prePersist() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.openjpa.persistence.jdbc.annotations;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
@Entity
|
||||
public class UnenhancedMixedAccess {
|
||||
|
||||
@Id private int id;
|
||||
|
||||
@Transient public String getStringField() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setStringField(String str) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
|
@ -257,22 +259,36 @@ public class PersistenceMetaDataDefaults
|
|||
return ClassMetaData.ACCESS_UNKNOWN;
|
||||
|
||||
int access = 0;
|
||||
if (usesAccess((Field[]) AccessController.doPrivileged(
|
||||
J2DoPriv5Helper.getDeclaredFieldsAction(cls))))
|
||||
if (annotated((Field[]) AccessController.doPrivileged(
|
||||
J2DoPriv5Helper.getDeclaredFieldsAction(cls))).size() > 0)
|
||||
access |= ClassMetaData.ACCESS_FIELD;
|
||||
if (usesAccess((Method[]) AccessController.doPrivileged(
|
||||
J2DoPriv5Helper.getDeclaredMethodsAction(cls)))
|
||||
if (annotated((Method[]) AccessController.doPrivileged(
|
||||
J2DoPriv5Helper.getDeclaredMethodsAction(cls))).size() > 0
|
||||
|| cls.isInterface()) // OpenJPA managed ifaces must use prop access
|
||||
access |= ClassMetaData.ACCESS_PROPERTY;
|
||||
return (access == 0) ? getAccessType(cls.getSuperclass()) : access;
|
||||
return getAccessType(cls.getSuperclass()) | access;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getFieldAccessNames(ClassMetaData meta) {
|
||||
return annotated((Field[]) AccessController.doPrivileged(
|
||||
J2DoPriv5Helper.getDeclaredFieldsAction(meta.getDescribedType())));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List getPropertyAccessNames(ClassMetaData meta) {
|
||||
return annotated((Method[]) AccessController.doPrivileged(
|
||||
J2DoPriv5Helper.getDeclaredMethodsAction(meta.getDescribedType())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given members have persistence annotations.
|
||||
* Return the members of <code>members</code> that have persistence
|
||||
* annotations.
|
||||
*/
|
||||
private static boolean usesAccess(AnnotatedElement[] members) {
|
||||
private static List annotated(AnnotatedElement[] members) {
|
||||
Annotation[] annos;
|
||||
String name;
|
||||
List annotated = new ArrayList(members.length);
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
annos = (Annotation[]) AccessController.doPrivileged(J2DoPriv5Helper
|
||||
.getAnnotationsAction(members[i]));
|
||||
|
@ -281,10 +297,10 @@ public class PersistenceMetaDataDefaults
|
|||
if ((name.startsWith("javax.persistence.")
|
||||
|| name.startsWith("org.apache.openjpa.persistence."))
|
||||
&& !_ignoredAnnos.contains(name))
|
||||
return true;
|
||||
annotated.add(members[i]);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return annotated;
|
||||
}
|
||||
|
||||
protected boolean isDefaultPersistent(ClassMetaData meta, Member member,
|
||||
|
|
Loading…
Reference in New Issue