| /******************************************************************************* |
| * Copyright (c) 1998, 2014 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 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:
|
| * Oracle - initial API and implementation from Oracle TopLink
|
| ******************************************************************************/
|
| package org.eclipse.persistence.jaxb.javamodel.reflection;
|
| |
| import org.eclipse.persistence.exceptions.JAXBException; |
| import org.eclipse.persistence.internal.security.PrivilegedAccessHelper; |
| import org.eclipse.persistence.jaxb.javamodel.*; |
| |
| 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; |
| |
| /** |
| * INTERNAL: |
| * <p><b>Purpose:</b>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.
|
| *
|
| * <p><b>Responsibilities:</b>
|
| * <ul>
|
| * <li>Provide access to the underlying JDK Class' name, package,
|
| * method/field names and parameters, annotations, etc.</li>
|
| * </ul>
|
| *
|
| * @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 String XML_REGISTRY_CLASS_NAME = "javax.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;
|
| } |
| public Collection getActualTypeArguments() { |
| ArrayList<JavaClass> argCollection = new ArrayList<JavaClass>(); |
| 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;
|
| }
|
|
|
| public String toString() {
|
| return getName();
|
| }
|
|
|
| /**
|
| * Assumes JavaType is a JavaClassImpl instance
|
| */
|
| 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;
|
| }
|
|
|
| public Collection getAnnotations() {
|
| ArrayList<JavaAnnotation> annotationCollection = new ArrayList<JavaAnnotation>();
|
| if (!isMetadataComplete) {
|
| Annotation[] annotations = javaModelImpl.getAnnotationHelper().getAnnotations(getAnnotatedElement());
|
| for (Annotation annotation : annotations) {
|
| annotationCollection.add(new JavaAnnotationImpl(annotation));
|
| }
|
| }
|
| return annotationCollection;
|
| }
|
|
|
| public Collection getDeclaredClasses() {
|
| ArrayList<JavaClass> classCollection = new ArrayList<JavaClass>();
|
| Class[] classes = jClass.getDeclaredClasses();
|
| for (Class javaClass : classes) {
|
| classCollection.add(javaModelImpl.getClass(javaClass));
|
| }
|
| return classCollection;
|
| }
|
|
|
| public JavaField getDeclaredField(String arg0) {
|
| try {
|
| return getJavaField(jClass.getDeclaredField(arg0));
|
| } catch (NoSuchFieldException nsfe) {
|
| return null;
|
| }
|
| }
|
|
|
| public Collection getDeclaredFields() { |
| ArrayList<JavaField> fieldCollection = new ArrayList<JavaField>(); |
| Field[] fields = PrivilegedAccessHelper.getDeclaredFields(jClass); |
| |
| for (Field field : fields) { |
| field.setAccessible(true); |
| fieldCollection.add(getJavaField(field)); |
| } |
| return fieldCollection;
|
| }
|
|
|
| /**
|
| * Assumes JavaType[] contains JavaClassImpl instances
|
| */
|
| 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<arg1.length; i++) {
|
| JavaClass jType = arg1[i];
|
| if (jType != null) {
|
| params[i] = ((JavaClassImpl) jType).getJavaClass();
|
| }
|
| }
|
| try {
|
| return getJavaMethod(jClass.getDeclaredMethod(arg0, params));
|
| } catch (NoSuchMethodException nsme) {
|
| return null;
|
| }
|
| }
|
|
|
| public Collection getDeclaredMethods() {
|
| ArrayList<JavaMethod> methodCollection = new ArrayList<JavaMethod>();
|
| Method[] methods = jClass.getDeclaredMethods();
|
| for (Method method : methods) {
|
| methodCollection.add(getJavaMethod(method));
|
| }
|
| return methodCollection;
|
| }
|
|
|
| public JavaConstructor getConstructor(JavaClass[] paramTypes) {
|
| if (paramTypes == null) {
|
| paramTypes = new JavaClass[0];
|
| }
|
| Class[] params = new Class[paramTypes.length];
|
| for (int i=0; i<paramTypes.length; i++) {
|
| JavaClass jType = paramTypes[i];
|
| if (jType != null) {
|
| params[i] = ((JavaClassImpl) jType).getJavaClass();
|
| }
|
| }
|
| try {
|
| Constructor constructor = PrivilegedAccessHelper.getConstructorFor(jClass, params, true);
|
| return new JavaConstructorImpl(constructor, javaModelImpl);
|
| } catch (NoSuchMethodException nsme) {
|
| return null;
|
| }
|
| }
|
|
|
| public JavaConstructor getDeclaredConstructor(JavaClass[] paramTypes) {
|
| if (paramTypes == null) {
|
| paramTypes = new JavaClass[0];
|
| }
|
| Class[] params = new Class[paramTypes.length];
|
| for (int i=0; i<paramTypes.length; i++) {
|
| JavaClass jType = paramTypes[i];
|
| if (jType != null) {
|
| params[i] = ((JavaClassImpl) jType).getJavaClass();
|
| }
|
| }
|
| try {
|
| return new JavaConstructorImpl(PrivilegedAccessHelper.getDeclaredConstructorFor(this.jClass, params, true), javaModelImpl);
|
| } catch (NoSuchMethodException nsme) {
|
| return null;
|
| }
|
| }
|
|
|
| public Collection getConstructors() {
|
| Constructor[] constructors = this.jClass.getConstructors();
|
| ArrayList<JavaConstructor> constructorCollection = new ArrayList(constructors.length);
|
| for(Constructor next:constructors) {
|
| constructorCollection.add(new JavaConstructorImpl(next, javaModelImpl));
|
| }
|
| return constructorCollection;
|
| }
|
|
|
| public Collection getDeclaredConstructors() {
|
| Constructor[] constructors = this.jClass.getDeclaredConstructors();
|
| ArrayList<JavaConstructor> 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<JavaField> fieldCollection = new ArrayList<JavaField>();
|
| 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
|
| */
|
| 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<arg1.length; i++) {
|
| JavaClass jType = arg1[i];
|
| if (jType != null) {
|
| params[i] = ((JavaClassImpl) jType).getJavaClass();
|
| }
|
| }
|
| try {
|
| Method method = PrivilegedAccessHelper.getMethod(jClass, arg0, params, true);
|
| return getJavaMethod(method);
|
| } catch (NoSuchMethodException nsme) {
|
| return null;
|
| }
|
| }
|
|
|
| public Collection getMethods() {
|
| ArrayList<JavaMethod> methodCollection = new ArrayList<JavaMethod>();
|
| Method[] methods = PrivilegedAccessHelper.getMethods(jClass);
|
| for (Method method : methods) {
|
| methodCollection.add(getJavaMethod(method));
|
| }
|
| return methodCollection;
|
| }
|
|
|
| public String getName() {
|
| return jClass.getName();
|
| }
|
|
|
| public JavaPackage getPackage() {
|
| return new JavaPackageImpl(jClass.getPackage(), javaModelImpl, isMetadataComplete);
|
| }
|
|
|
| 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;
|
| }
|
|
|
| public String getQualifiedName() {
|
| return jClass.getName();
|
| }
|
|
|
| public String getRawName() {
|
| return jClass.getCanonicalName();
|
| }
|
|
|
| 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."))) {
|
| 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();
|
| }
|
|
|
| public Type getGenericSuperclass() {
|
| return jClass.getGenericSuperclass();
|
| }
|
|
|
| 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());
|
| }
|
|
|
| public boolean isAnnotation() {
|
| return jClass.isAnnotation();
|
| }
|
|
|
| public boolean isArray() {
|
| return jClass.isArray();
|
| }
|
|
|
| public AnnotatedElement getAnnotatedElement() {
|
| return jClass;
|
| }
|
|
|
| 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;
|
| if(jClass.getSuperClassOverride() != null) {
|
| return true;
|
| }
|
| return hasCustomSuperClass(jClass.getSuperclass());
|
| }
|
|
|
| public boolean isEnum() {
|
| return jClass.isEnum();
|
| }
|
|
|
| public boolean isInterface() {
|
| return jClass.isInterface();
|
| }
|
|
|
| public boolean isMemberClass() {
|
| return jClass.isMemberClass();
|
| }
|
|
|
| public boolean isPrimitive() {
|
| return jClass.isPrimitive();
|
| }
|
|
|
| public boolean isAbstract() {
|
| return Modifier.isAbstract(getModifiers());
|
| }
|
|
|
| public boolean isPrivate() {
|
| return Modifier.isPrivate(getModifiers());
|
| }
|
|
|
| public boolean isProtected() {
|
| return Modifier.isProtected(getModifiers());
|
| }
|
|
|
| public boolean isPublic() {
|
| return Modifier.isPublic(getModifiers());
|
| }
|
|
|
| public boolean isStatic() {
|
| return Modifier.isStatic(getModifiers());
|
| }
|
|
|
| public int getModifiers() {
|
| return jClass.getModifiers();
|
| }
|
|
|
| public boolean isFinal() {
|
| return Modifier.isFinal(getModifiers());
|
| }
|
|
|
| public boolean isSynthetic() {
|
| return jClass.isSynthetic(); |
| } |
| |
| @Override |
| public JavaClassInstanceOf instanceOf() { |
| return JavaClassInstanceOf.JAVA_CLASS_IMPL; |
| } |
| |
| 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;
|
| }
|
| }
|
|
|
| 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;
|
| }
|
|
|
| public Collection getDeclaredAnnotations() {
|
| ArrayList<JavaAnnotation> annotationCollection = new ArrayList<JavaAnnotation>();
|
| if (!isMetadataComplete) {
|
| Annotation[] annotations = javaModelImpl.getAnnotationHelper().getDeclaredAnnotations(getAnnotatedElement());
|
| for (Annotation annotation : annotations) {
|
| annotationCollection.add(new JavaAnnotationImpl(annotation));
|
| }
|
| }
|
| return annotationCollection; |
| } |
| |
| } |