/*******************************************************************************
* Copyright (c) 1998, 2008 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Guy Pelletier (Oracle), March 6, 2008
* - New file introduced for bug 221658.
* 05/16/2008-1.0M8 Guy Pelletier
* - 218084: Implement metadata merging functionality between mapping files
* 12/12/2008-1.1 Guy Pelletier
* - 249860: Implement table per class inheritance support.
******************************************************************************/
package org.eclipse.persistence.internal.jpa.metadata.accessors.classes;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import org.eclipse.persistence.exceptions.EntityManagerSetupException;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataMethod;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredFields;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredMethods;
import org.eclipse.persistence.internal.security.PrivilegedGetField;
import org.eclipse.persistence.internal.security.PrivilegedGetMethod;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
/**
* INTERNAL:
* Common helper methods for the metadata processing. Security sensitive methods
* from this class must remain package accessible only.
*
* @author Guy Pelletier
* @since EclipseLink 1.0
*/
public class MetadataHelper {
public static final String PERSISTENCE_PACKAGE_PREFIX = "javax.persistence";
/**
* INTERNAL:
* Get the declared methods from a class using the doPriveleged security
* access. This call returns all methods (private, protected, package and
* public) on the given class ONLY. It does not traverse the superclasses.
*/
static Method[] getDeclaredMethods(Class cls) {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
return (Method[])AccessController.doPrivileged(new PrivilegedGetDeclaredMethods(cls));
} catch (PrivilegedActionException exception) {
// we will not get here, there are no checked exceptions in this call
return null;
}
} else {
return org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getDeclaredMethods(cls);
}
}
/**
* INTERNAL:
* Helper method that will return a given field based on the provided attribute name.
*/
static Field getFieldForName(String fieldName, Class javaClass) {
Field field = null;
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
field = (Field)AccessController.doPrivileged(new PrivilegedGetField(javaClass, fieldName, false));
} catch (PrivilegedActionException exception) {
return null;
}
} else {
field = PrivilegedAccessHelper.getField(javaClass, fieldName, false);
}
} catch (NoSuchFieldException nsfex) {
return null;
}
return field;
}
/**
* INTERNAL:
* Get the declared fields from a class using the doPriveleged security
* access.
*/
static Field[] getFields(Class cls) {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
return (Field[])AccessController.doPrivileged(new PrivilegedGetDeclaredFields(cls));
} catch (PrivilegedActionException exception) {
// no checked exceptions are thrown, so we should not get here
return null;
}
} else {
return PrivilegedAccessHelper.getDeclaredFields(cls);
}
}
/**
* INTERNAL:
* If the methodName passed in is a declared method on cls, then return
* the methodName. Otherwise return null to indicate it does not exist.
*/
static Method getMethod(String methodName, Class cls, Class[] params) {
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
try {
return AccessController.doPrivileged(new PrivilegedGetMethod(cls, methodName, params, true));
} catch (PrivilegedActionException exception) {
return null;
}
} else {
return PrivilegedAccessHelper.getMethod(cls, methodName, params, true);
}
} catch (NoSuchMethodException e1) {
return null;
}
}
/**
* INTERNAL:
* Method to convert an xyz property name into a getXyz or isXyz method.
*/
static Method getMethodForPropertyName(String propertyName, Class cls) {
Method method;
String leadingChar = String.valueOf(propertyName.charAt(0)).toUpperCase();
String restOfName = propertyName.substring(1);
// Look for a getPropertyName() method
method = MetadataHelper.getMethod(MetadataMethod.GET_PROPERTY_METHOD_PREFIX.concat(leadingChar).concat(restOfName), cls, new Class[]{});
if (method == null) {
// Look for an isPropertyName() method
method = MetadataHelper.getMethod(MetadataMethod.IS_PROPERTY_METHOD_PREFIX.concat(leadingChar).concat(restOfName), cls, new Class[]{});
}
return method;
}
/**
* INTERNAL:
* Invoke the specified named method on the object, handling the necessary
* exceptions.
*/
static Object invokeMethod(String methodName, Object target) {
Method method = null;
try {
method = Helper.getDeclaredMethod(target.getClass(), methodName);
} catch (NoSuchMethodException e) {
EntityManagerSetupException.methodInvocationFailed(method, target,e);
}
if (method != null) {
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
try {
return AccessController.doPrivileged(new PrivilegedMethodInvoker(method, target));
} catch (PrivilegedActionException exception) {
Exception throwableException = exception.getException();
if (throwableException instanceof IllegalAccessException) {
throw EntityManagerSetupException.cannotAccessMethodOnObject(method, target);
} else {
throw EntityManagerSetupException.methodInvocationFailed(method, target, throwableException);
}
}
} else {
return PrivilegedAccessHelper.invokeMethod(method, target);
}
} catch (IllegalAccessException ex1) {
throw EntityManagerSetupException.cannotAccessMethodOnObject(method, target);
} catch (InvocationTargetException ex2) {
throw EntityManagerSetupException.methodInvocationFailed(method, target, ex2);
}
} else {
return null;
}
}
}