org.eclipse.persistence.jaxb.javamodel.reflection.JavaClassImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.jaxb.javamodel.reflection;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.javamodel.JavaAnnotation;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaClassInstanceOf;
import org.eclipse.persistence.jaxb.javamodel.JavaConstructor;
import org.eclipse.persistence.jaxb.javamodel.JavaField;
import org.eclipse.persistence.jaxb.javamodel.JavaMethod;
import org.eclipse.persistence.jaxb.javamodel.JavaPackage;
/**
* INTERNAL:
* Purpose:A wrapper class for a JDK Class. This implementation
* of the EclipseLink JAXB 2.X Java model simply makes reflective calls on the
* underlying JDK object.
*
*
Responsibilities:
*
* - Provide access to the underlying JDK Class' name, package,
* method/field names and parameters, annotations, etc.
*
*
* @since Oracle TopLink 11.1.1.0.0
* @see org.eclipse.persistence.jaxb.javamodel.JavaClass
* @see java.lang.Class
*/
public class JavaClassImpl implements JavaClass {
protected ParameterizedType jType;
protected Class jClass;
protected JavaModelImpl javaModelImpl;
protected boolean isMetadataComplete;
protected JavaClass superClassOverride;
protected static final String XML_REGISTRY_CLASS_NAME = "jakarta.xml.bind.annotation.XmlRegistry";
public JavaClassImpl(Class javaClass, JavaModelImpl javaModelImpl) {
this.jClass = javaClass;
this.javaModelImpl = javaModelImpl;
isMetadataComplete = false;
}
public JavaClassImpl(ParameterizedType javaType, Class javaClass, JavaModelImpl javaModelImpl) {
this.jType = javaType;
this.jClass = javaClass;
this.javaModelImpl = javaModelImpl;
isMetadataComplete = false;
}
public void setJavaModelImpl(JavaModelImpl javaModel) {
this.javaModelImpl = javaModel;
}
@Override
public Collection getActualTypeArguments() {
ArrayList argCollection = new ArrayList();
if (jType != null) {
Type[] params = jType.getActualTypeArguments();
for (Type type : params) {
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
argCollection.add(new JavaClassImpl(pt, (Class) pt.getRawType(), javaModelImpl));
} else if(type instanceof WildcardType){
Type[] upperTypes = ((WildcardType)type).getUpperBounds();
if(upperTypes.length >0){
Type upperType = upperTypes[0];
if(upperType instanceof Class){
argCollection.add(javaModelImpl.getClass((Class) upperType));
}
}
} else if (type instanceof Class) {
argCollection.add(javaModelImpl.getClass((Class) type));
} else if(type instanceof GenericArrayType) {
Class genericTypeClass = (Class)((GenericArrayType)type).getGenericComponentType();
genericTypeClass = java.lang.reflect.Array.newInstance(genericTypeClass, 0).getClass();
argCollection.add(javaModelImpl.getClass(genericTypeClass));
} else if(type instanceof TypeVariable) {
Type[] boundTypes = ((TypeVariable) type).getBounds();
if(boundTypes.length > 0) {
Type boundType = boundTypes[0];
if(boundType instanceof Class) {
argCollection.add(javaModelImpl.getClass((Class) boundType));
}
}
}
}
}
return argCollection;
}
@Override
public String toString() {
return getName();
}
/**
* Assumes JavaType is a JavaClassImpl instance
*/
@Override
public JavaAnnotation getAnnotation(JavaClass arg0) {
// the only annotation we will return if isMetadataComplete == true is XmlRegistry
if (arg0 != null && (!isMetadataComplete || arg0.getQualifiedName().equals(XML_REGISTRY_CLASS_NAME))) {
Class annotationClass = ((JavaClassImpl) arg0).getJavaClass();
if (javaModelImpl.getAnnotationHelper().isAnnotationPresent(getAnnotatedElement(), annotationClass)) {
return new JavaAnnotationImpl(this.javaModelImpl.getAnnotationHelper().getAnnotation(getAnnotatedElement(), annotationClass));
}
}
return null;
}
@Override
public Collection getAnnotations() {
List annotationCollection = new ArrayList();
if (!isMetadataComplete) {
Annotation[] annotations = javaModelImpl.getAnnotationHelper().getAnnotations(getAnnotatedElement());
for (Annotation annotation : annotations) {
annotationCollection.add(new JavaAnnotationImpl(annotation));
}
}
return annotationCollection;
}
@Override
public Collection getDeclaredClasses() {
List classCollection = new ArrayList();
Class[] classes = jClass.getDeclaredClasses();
for (Class javaClass : classes) {
classCollection.add(javaModelImpl.getClass(javaClass));
}
return classCollection;
}
@Override
public JavaField getDeclaredField(String arg0) {
try {
return getJavaField(jClass.getDeclaredField(arg0));
} catch (NoSuchFieldException nsfe) {
return null;
}
}
@Override
public Collection getDeclaredFields() {
List fieldCollection = new ArrayList();
Field[] fields = PrivilegedAccessHelper.getDeclaredFields(jClass);
for (Field field : fields) {
field.setAccessible(true);
fieldCollection.add(getJavaField(field));
}
return fieldCollection;
}
/**
* Assumes JavaType[] contains JavaClassImpl instances
*/
@Override
public JavaMethod getDeclaredMethod(String arg0, JavaClass[] arg1) {
if (arg1 == null) {
arg1 = new JavaClass[0];
}
Class[] params = new Class[arg1.length];
for (int i=0; i methodCollection = new ArrayList();
Method[] methods = jClass.getDeclaredMethods();
for (Method method : methods) {
methodCollection.add(getJavaMethod(method));
}
return methodCollection;
}
@Override
public JavaConstructor getConstructor(JavaClass[] paramTypes) {
if (paramTypes == null) {
paramTypes = new JavaClass[0];
}
Class[] params = new Class[paramTypes.length];
for (int i=0; i constructorCollection = new ArrayList(constructors.length);
for(Constructor next:constructors) {
constructorCollection.add(new JavaConstructorImpl(next, javaModelImpl));
}
return constructorCollection;
}
@Override
public Collection getDeclaredConstructors() {
Constructor[] constructors = this.jClass.getDeclaredConstructors();
ArrayList constructorCollection = new ArrayList(constructors.length);
for(Constructor next:constructors) {
constructorCollection.add(new JavaConstructorImpl(next, javaModelImpl));
}
return constructorCollection;
}
public JavaField getField(String arg0) {
try {
Field field = PrivilegedAccessHelper.getField(jClass, arg0, true);
return getJavaField(field);
} catch (NoSuchFieldException nsfe) {
return null;
}
}
public Collection getFields() {
ArrayList fieldCollection = new ArrayList();
Field[] fields = PrivilegedAccessHelper.getFields(jClass);
for (Field field : fields) {
fieldCollection.add(getJavaField(field));
}
return fieldCollection;
}
public Class getJavaClass() {
return jClass;
}
/**
* Assumes JavaType[] contains JavaClassImpl instances
*/
@Override
public JavaMethod getMethod(String arg0, JavaClass[] arg1) {
if (arg1 == null) {
arg1 = new JavaClass[0];
}
Class[] params = new Class[arg1.length];
for (int i=0; i methodCollection = new ArrayList();
Method[] methods = PrivilegedAccessHelper.getMethods(jClass);
for (Method method : methods) {
methodCollection.add(getJavaMethod(method));
}
return methodCollection;
}
@Override
public String getName() {
return jClass.getName();
}
@Override
public JavaPackage getPackage() {
return new JavaPackageImpl(jClass.getPackage(), javaModelImpl, isMetadataComplete);
}
@Override
public String getPackageName() {
if(jClass.getPackage() != null){
return jClass.getPackage().getName();
}else{
Class nonInnerClass = jClass;
Class enclosingClass = jClass.getEnclosingClass();
while(enclosingClass != null){
nonInnerClass = enclosingClass;
enclosingClass = nonInnerClass.getEnclosingClass();
}
String className = nonInnerClass.getCanonicalName();
if(className !=null){
int index = className.lastIndexOf('.');
if(index > -1){
return className.substring(0, index);
}
}
}
return null;
}
@Override
public String getQualifiedName() {
return jClass.getName();
}
@Override
public String getRawName() {
return jClass.getCanonicalName();
}
@Override
public JavaClass getSuperclass() {
if(this.superClassOverride != null) {
return this.superClassOverride;
}
if(jClass.isInterface()) {
Class[] superInterfaces = jClass.getInterfaces();
if(superInterfaces != null) {
if(superInterfaces.length == 1) {
return javaModelImpl.getClass(superInterfaces[0]);
} else {
Class parent = null;
for(Class next:superInterfaces) {
if(!(next.getName().startsWith("java.")
|| next.getName().startsWith("javax.")
|| next.getName().startsWith("jakarta."))) {
if(parent == null) {
parent = next;
} else {
throw JAXBException.invalidInterface(jClass.getName());
}
}
}
return javaModelImpl.getClass(parent);
}
}
}
return javaModelImpl.getClass(jClass.getSuperclass());
}
@Override
public Type[] getGenericInterfaces() {
return jClass.getGenericInterfaces();
}
@Override
public Type getGenericSuperclass() {
return jClass.getGenericSuperclass();
}
@Override
public boolean hasActualTypeArguments() {
return getActualTypeArguments().size() > 0;
}
public JavaField getJavaField(Field field) {
return new JavaFieldImpl(field, javaModelImpl, isMetadataComplete);
}
public JavaMethod getJavaMethod(Method method) {
return new JavaMethodImpl(method, javaModelImpl, isMetadataComplete);
}
public JavaClass getOwningClass() {
return javaModelImpl.getClass(jClass.getEnclosingClass());
}
@Override
public boolean isAnnotation() {
return jClass.isAnnotation();
}
@Override
public boolean isArray() {
return jClass.isArray();
}
public AnnotatedElement getAnnotatedElement() {
return jClass;
}
@Override
public boolean isAssignableFrom(JavaClass arg0) {
if (!(arg0 instanceof JavaClassImpl)) {
return false;
}
if(hasCustomSuperClass(arg0)) {
return this.customIsAssignableFrom(arg0);
}
return jClass.isAssignableFrom(((JavaClassImpl) arg0).getJavaClass());
}
private boolean customIsAssignableFrom(JavaClass arg0) {
JavaClassImpl jClass = (JavaClassImpl)arg0;
Class cls = jClass.getJavaClass();
if(cls == this.jClass) {
return true;
}
Class[] interfaces = cls.getInterfaces();
for(Class nextInterface:interfaces) {
if(nextInterface == this.jClass) {
return true;
}
if(customIsAssignableFrom(javaModelImpl.getClass(nextInterface))) {
return true;
}
}
if(!(jClass.isInterface())) {
JavaClassImpl superJavaClass = (JavaClassImpl)jClass.getSuperclass();
if(superJavaClass.getName().equals("java.lang.Object")) {
return this.jClass == superJavaClass.getJavaClass();
}
return customIsAssignableFrom(superJavaClass);
}
return false;
}
private boolean hasCustomSuperClass(JavaClass arg0) {
if(arg0 == null) {
return false;
}
if(!this.javaModelImpl.hasXmlBindings()) {
return false;
}
if(!(arg0.getClass() == this.getClass())) {
return false;
}
if(arg0.getName().equals("java.lang.Object")) {
return false;
}
JavaClassImpl jClass = (JavaClassImpl)arg0;
return jClass.getSuperClassOverride() != null || hasCustomSuperClass(jClass.getSuperclass());
}
@Override
public boolean isEnum() {
return jClass.isEnum();
}
@Override
public boolean isInterface() {
return jClass.isInterface();
}
@Override
public boolean isMemberClass() {
return jClass.isMemberClass();
}
@Override
public boolean isPrimitive() {
return jClass.isPrimitive();
}
@Override
public boolean isAbstract() {
return Modifier.isAbstract(getModifiers());
}
@Override
public boolean isPrivate() {
return Modifier.isPrivate(getModifiers());
}
@Override
public boolean isProtected() {
return Modifier.isProtected(getModifiers());
}
@Override
public boolean isPublic() {
return Modifier.isPublic(getModifiers());
}
@Override
public boolean isStatic() {
return Modifier.isStatic(getModifiers());
}
@Override
public int getModifiers() {
return jClass.getModifiers();
}
@Override
public boolean isFinal() {
return Modifier.isFinal(getModifiers());
}
@Override
public boolean isSynthetic() {
return jClass.isSynthetic();
}
@Override
public JavaClassInstanceOf instanceOf() {
return JavaClassInstanceOf.JAVA_CLASS_IMPL;
}
@Override
public JavaClass getComponentType() {
if(!isArray()) {
return null;
}
return javaModelImpl.getClass(this.jClass.getComponentType());
}
public JavaClass getSuperClassOverride() {
return superClassOverride;
}
public void setSuperClassOverride(JavaClass superClassOverride) {
this.superClassOverride = superClassOverride;
}
/**
* Set the indicator for XML metadata complete - if true,
* annotations will be ignored.
*
* @param isMetadataComplete
*/
void setIsMetadataComplete(Boolean isMetadataComplete) {
if(isMetadataComplete != null){
this.isMetadataComplete = isMetadataComplete;
}
}
@Override
public JavaAnnotation getDeclaredAnnotation(JavaClass arg0) {
// the only annotation we will return if isMetadataComplete == true is XmlRegistry
if (arg0 != null && (!isMetadataComplete || arg0.getQualifiedName().equals(XML_REGISTRY_CLASS_NAME))) {
Class annotationClass = ((JavaClassImpl) arg0).getJavaClass();
Annotation[] annotations = javaModelImpl.getAnnotationHelper().getDeclaredAnnotations(getAnnotatedElement());
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(annotationClass)) {
return new JavaAnnotationImpl(annotation);
}
}
}
return null;
}
@Override
public Collection getDeclaredAnnotations() {
List annotationCollection = new ArrayList();
if (!isMetadataComplete) {
Annotation[] annotations = javaModelImpl.getAnnotationHelper().getDeclaredAnnotations(getAnnotatedElement());
for (Annotation annotation : annotations) {
annotationCollection.add(new JavaAnnotationImpl(annotation));
}
}
return annotationCollection;
}
}