All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.jaxb.javamodel.xjc.XJCJavaClassImpl Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 2011, 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:
//     Rick Barkhouse - 2.1 - Initial implementation
package org.eclipse.persistence.jaxb.javamodel.xjc;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.javamodel.*;

import com.sun.codemodel.ClassType;
import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMods;
import com.sun.codemodel.JPrimitiveType;
import com.sun.codemodel.JType;
import com.sun.codemodel.JTypeVar;

/**
 * INTERNAL:
 * 

* Purpose: JavaClass implementation wrapping XJC's JDefinedClass. * Used when bootstrapping a DynamicJAXBContext from an XML Schema. *

* *

* Responsibilities: *

*
    *
  • Provide Class information from the underlying JDefinedClass.
  • *
* * @since EclipseLink 2.1 * * @see org.eclipse.persistence.jaxb.javamodel.JavaClass */ public class XJCJavaClassImpl implements JavaClass { private JDefinedClass xjcClass; private JCodeModel jCodeModel; private JavaModel javaModel; private boolean isArray; private boolean isPrimitive; private JavaClass arg; private DynamicClassLoader dynamicClassLoader; private static Field JDEFINEDCLASS_ANNOTATIONS = null; private static Field JDEFINEDCLASS_MODS = null; private static Field JDEFINEDCLASS_SUPERCLASS = null; private static Field JTYPEVAR_BOUND = null; private static final Map jPrimitiveTypes = new HashMap(); static { JCodeModel tempCodeModel = new JCodeModel(); jPrimitiveTypes.put("java.lang.Boolean", tempCodeModel.BOOLEAN); jPrimitiveTypes.put("java.lang.Byte", tempCodeModel.BYTE); jPrimitiveTypes.put("java.lang.Character", tempCodeModel.CHAR); jPrimitiveTypes.put("java.lang.Double", tempCodeModel.DOUBLE); jPrimitiveTypes.put("java.lang.Float", tempCodeModel.FLOAT); jPrimitiveTypes.put("java.lang.Integer", tempCodeModel.INT); jPrimitiveTypes.put("java.lang.Long", tempCodeModel.LONG); jPrimitiveTypes.put("java.lang.Short", tempCodeModel.SHORT); try { JDEFINEDCLASS_ANNOTATIONS = PrivilegedAccessHelper.getDeclaredField(JDefinedClass.class, "annotations", true); JDEFINEDCLASS_MODS = PrivilegedAccessHelper.getDeclaredField(JDefinedClass.class, "mods", true); JDEFINEDCLASS_SUPERCLASS = PrivilegedAccessHelper.getDeclaredField(JDefinedClass.class, "superClass", true); JTYPEVAR_BOUND = PrivilegedAccessHelper.getDeclaredField(JTypeVar.class, "bound", true); } catch (Exception e) { throw JAXBException.errorCreatingDynamicJAXBContext(e); } } /** * Construct a new instance of XJCJavaClassImpl. * * @param jDefinedClass - the XJC JDefinedClass to be wrapped. * @param codeModel - the XJC JCodeModel this class belongs to. * @param loader - the ClassLoader used to bootstrap the DynamicJAXBContext. */ public XJCJavaClassImpl(JDefinedClass jDefinedClass, JCodeModel codeModel, DynamicClassLoader loader) { this(jDefinedClass, codeModel, loader, false, false); } /** * Construct a new instance of XJCJavaClassImpl. * * @param jDefinedClass - the XJC JDefinedClass to be wrapped. * @param codeModel - the XJC JCodeModel this class belongs to. * @param loader - the ClassLoader used to bootstrap the DynamicJAXBContext. * @param isArray - indicates that this class is an array type. * @param isPrimitive - indicates that this class is a primitive type. */ public XJCJavaClassImpl(JDefinedClass jDefinedClass, JCodeModel codeModel, DynamicClassLoader loader, boolean isArray, boolean isPrimitive) { this.xjcClass = jDefinedClass; this.jCodeModel = codeModel; this.dynamicClassLoader = loader; this.isArray = isArray; this.isPrimitive = isPrimitive; } // ======================================================================== public void setActualTypeArgument(JavaClass javaClass){ arg = javaClass; } /** * Return the "actual" type from a parameterized type. For example, if this * JavaClass represents List<Employee, this method will return the * Employee JavaClass. * * @return a Collection containing the actual type's JavaClass. */ @Override public Collection getActualTypeArguments() { JTypeVar[] typeParams = xjcClass.typeParams(); if (null == typeParams || 0 == typeParams.length ) { if(arg != null){ java.util.List theList = new ArrayList(1); theList.add(arg); return theList; }else{ return new ArrayList(0); } } try { ArrayList typeArguments = new ArrayList(1); JTypeVar var = typeParams[typeParams.length - 1]; JClass xjcBoundClass = (JClass) PrivilegedAccessHelper.getValueFromField(JTYPEVAR_BOUND, var); JType basis = null; try { // Check to see if this type has a 'basis' field. // This would indicate it is a "parameterized type" (e.g. List). // Cannot cache this field because JNarrowedClass is a protected class. Field basisField = PrivilegedAccessHelper.getDeclaredField(xjcBoundClass.getClass(), "basis", true); basis = (JClass) PrivilegedAccessHelper.getValueFromField(basisField, xjcBoundClass); } catch (Exception e) { // "basis" field not found } JavaClass boundClass; if (basis != null) { boundClass = this.javaModel.getClass(basis.fullName()); } else if (javaModel != null) { boundClass = this.javaModel.getClass(xjcBoundClass.fullName()); } else { JDefinedClass c = jCodeModel._getClass(xjcBoundClass.fullName()); boundClass = new XJCJavaClassImpl(c, jCodeModel, dynamicClassLoader); } typeArguments.add(boundClass); return typeArguments; } catch (Exception e) { return new ArrayList(0); } } /** * If this JavaClass is an array type, return the type of the * array components. * * @return JavaClass of this array's component type, or null if * this is not an array type. */ @Override public JavaClass getComponentType() { if (!isArray()) { return null; } return javaModel.getClass(this.xjcClass.fullName()); } /** * Return the JavaConstructor for this JavaClass that has the * provided parameter types. * * @param parameterTypes the parameter list used to identify the constructor. * * @return the JavaConstructor with the signature matching parameterTypes. */ @Override public JavaConstructor getConstructor(JavaClass[] parameterTypes) { JType[] xjcParameterTypes = new JType[parameterTypes.length]; for (int i = 0; i < parameterTypes.length; i++) { JavaClass pType = parameterTypes[i]; String className = pType.getQualifiedName(); JType xjcType = null; if (pType.isPrimitive()) { xjcType = jPrimitiveTypes.get(className); } else { xjcType = jCodeModel._getClass(className); } xjcParameterTypes[i] = xjcType; } JMethod constructor = xjcClass.getConstructor(xjcParameterTypes); return new XJCJavaConstructorImpl(constructor, jCodeModel, dynamicClassLoader, this); } /** * Return all of the JavaConstructors for this JavaClass. * * @return A Collection containing this JavaClass' JavaConstructors. */ @Override @SuppressWarnings("unchecked") public Collection getConstructors() { ArrayList constructors = new ArrayList(); Iterator it = xjcClass.constructors(); while (it.hasNext()) { constructors.add(new XJCJavaConstructorImpl(it.next(), jCodeModel, dynamicClassLoader, this)); } return constructors; } /** * Return this JavaClass' inner classes. * * @return A Collection<JavaClass> containing this JavaClass' inner classes. */ @Override public Collection getDeclaredClasses() { ArrayList declaredClasses = new ArrayList(); Iterator it = xjcClass.classes(); while (it.hasNext()) { XJCJavaClassImpl dc; if (javaModel != null) { dc = (XJCJavaClassImpl) this.javaModel.getClass(it.next().fullName()); } else { dc = new XJCJavaClassImpl(it.next(), jCodeModel, dynamicClassLoader); } declaredClasses.add(dc); } return declaredClasses; } /** * Return the declared JavaConstructor for this JavaClass that has the * provided parameter types. * * @param parameterTypes the parameter list used to identify the constructor. * * @return the JavaConstructor with the signature matching parameterTypes. */ @Override public JavaConstructor getDeclaredConstructor(JavaClass[] parameterTypes) { return getConstructor(parameterTypes); } /** * Return all of the declared JavaConstructors for this JavaClass. * * @return A Collection containing this JavaClass' JavaConstructors. */ @Override public Collection getDeclaredConstructors() { return getConstructors(); } /** * Return the declared JavaField for this JavaClass, identified * by fieldName. * * @param fieldName the name of the JavaField to return. * * @return the JavaField named fieldName from this JavaClass. */ @Override public JavaField getDeclaredField(String fieldName) { JFieldVar xjcField = xjcClass.fields().get(fieldName); return new XJCJavaFieldImpl(xjcField, jCodeModel, dynamicClassLoader, this); } /** * Return all of the declared JavaFields for this JavaClass. * * @return A Collection containing this JavaClass' JavaFields. */ @Override public Collection getDeclaredFields() { Collection xjcFields = xjcClass.fields().values(); ArrayList fields = new ArrayList(xjcFields.size()); for (JFieldVar jField : xjcFields) { fields.add(new XJCJavaFieldImpl(jField, jCodeModel, dynamicClassLoader, this)); } return fields; } /** * Return the declared JavaMethod for this JavaClass, * identified by name, with the signature matching args. * * @param name the name of the JavaMethod to return. * @param args the parameter list used to identify the method. * * @return the matching JavaMethod from this JavaClass. */ @Override public JavaMethod getDeclaredMethod(String name, JavaClass[] args) { return getMethod(name, args); } /** * Return all of the declared JavaMethods for this JavaClass. * * @return A Collection containing this JavaClass' JavaMethods. */ @Override public Collection getDeclaredMethods() { return getMethods(); } /** * Return the JavaMethod for this JavaClass, identified * by name, with the signature matching args. * * @param name the name of the JavaMethod to return. * @param args the parameter list used to identify the method. * * @return the matching JavaMethod from this JavaClass. */ @Override public JavaMethod getMethod(String name, JavaClass[] args) { Collection xjcMethods = xjcClass.methods(); for (JMethod xjcMethod : xjcMethods) { JType[] params = xjcMethod.listParamTypes(); boolean argsAreEqual = argsAreEqual(args, params); if (xjcMethod.name().equals(name) && argsAreEqual) { return new XJCJavaMethodImpl(xjcMethod, jCodeModel, dynamicClassLoader, this); } } return null; } private boolean argsAreEqual(JavaClass[] elinkArgs, JType[] xjcArgs) { if (elinkArgs == null && xjcArgs == null) { return true; } if (elinkArgs != null && xjcArgs == null) { return false; } if (elinkArgs == null && xjcArgs != null) { return false; } if (elinkArgs.length != xjcArgs.length) { return false; } for (int i = 0; i < elinkArgs.length; i++) { JavaClass elinkClass = elinkArgs[i]; JType xjcClass = xjcArgs[i]; if (!elinkClass.getQualifiedName().equals(xjcClass.fullName())) { return false; } } return true; } /** * Return all of the JavaMethods for this JavaClass. * * @return A Collection containing this JavaClass' JavaMethods. */ @Override public Collection getMethods() { Collection xjcMethods = xjcClass.methods(); ArrayList elinkMethods = new ArrayList(xjcMethods.size()); for (JMethod xjcMethod : xjcMethods) { elinkMethods.add(new XJCJavaMethodImpl(xjcMethod, jCodeModel, dynamicClassLoader, this)); } return elinkMethods; } /** * Returns the Java language modifiers for this JavaClass, encoded in an integer. * * @return the int representing the modifiers for this class. * * @see java.lang.reflect.Modifier */ @Override public int getModifiers() { JMods xjcMods = null; try { xjcMods = (JMods) PrivilegedAccessHelper.getValueFromField(JDEFINEDCLASS_MODS, xjcClass); } catch (Exception e) { return 0; } return xjcMods.getValue(); } /** * Returns the name of this JavaClass. * * @return the String name of this JavaClass. */ @Override public String getName() { return getQualifiedName(); } /** * Returns the JavaPackage that this JavaClass belongs to. * * @return the JavaPackage of this JavaClass. */ @Override public JavaPackage getPackage() { return new XJCJavaPackageImpl(xjcClass.getPackage(), dynamicClassLoader); } /** * Returns the package name of this JavaClass. * * @return the String name of this JavaClass' JavaPackage. */ @Override public String getPackageName() { return xjcClass._package().name(); } /** * Returns the fully-qualified name of this JavaClass. * * @return the String name of this JavaClass. */ @Override public String getQualifiedName() { if(isArray) { if(this.isPrimitive) { return getPrimitiveArrayNameFor(xjcClass.fullName()); } return "[L" + xjcClass.fullName(); } return xjcClass.fullName(); } private String getPrimitiveArrayNameFor(String fullName) { Class componentClass = ConversionManager.getPrimitiveClass(fullName); if(componentClass != null) { if(componentClass == ClassConstants.PBYTE) { return ClassConstants.APBYTE.getName(); } if(componentClass == ClassConstants.PCHAR) { return ClassConstants.APCHAR.getName(); } if(componentClass == ClassConstants.PBOOLEAN) { return boolean[].class.getName(); } if(componentClass == ClassConstants.PDOUBLE) { return double[].class.getName(); } if(componentClass == ClassConstants.PFLOAT) { return float[].class.getName(); } if(componentClass == ClassConstants.PINT) { return int[].class.getName(); } if(componentClass == ClassConstants.PLONG) { return long[].class.getName(); } if(componentClass == ClassConstants.PSHORT) { return short[].class.getName(); } } return fullName; } /** * Returns the raw name of this JavaClass. Array types will * have "[]" appended to the name. * * @return the String raw name of this JavaClass. */ @Override public String getRawName() { if(isArray) { return xjcClass.fullName() + "[]"; } return xjcClass.fullName(); } /** * Returns the super class of this JavaClass. * * @return JavaClass representing the super class of this JavaClass. */ @Override public JavaClass getSuperclass() { try { JClass superClass = (JClass) PrivilegedAccessHelper.getValueFromField(JDEFINEDCLASS_SUPERCLASS, xjcClass); if (superClass == null) // if null -> no need to continue return null; if (superClass instanceof JDefinedClass) { if (javaModel != null) { return this.javaModel.getClass(superClass.fullName()); } return new XJCJavaClassImpl((JDefinedClass) superClass, jCodeModel, dynamicClassLoader); } else { if (javaModel != null) { return this.javaModel.getClass(superClass.fullName()); } return new XJCJavaClassImpl((JDefinedClass) superClass, jCodeModel, dynamicClassLoader); } } catch (Exception e) { return null; } } @Override public Type[] getGenericInterfaces() { return new Type[0]; } @Override public Type getGenericSuperclass() { return null; } /** * Indicates if this JavaClass has actual type arguments, i.e. is a * parameterized type (for example, List<Employee). * * @return true if this JavaClass is parameterized, otherwise false. */ @Override public boolean hasActualTypeArguments() { return xjcClass.typeParams().length > 0; } /** * Indicates if this JavaClass is abstract. * * @return true if this JavaClass is abstract, otherwise false. */ @Override public boolean isAbstract() { return xjcClass.isAbstract(); } /** * Indicates if this JavaClass is an Annotation. * * @return true if this JavaClass is an Annotation, otherwise false. */ @Override public boolean isAnnotation() { return xjcClass.isAnnotationTypeDeclaration(); } /** * Indicates if this JavaClass is an Array type. * * @return true if this JavaClass is an Array type, otherwise false. */ @Override public boolean isArray() { if (this.isArray) { return true; } return this.xjcClass.isArray(); } /** * Indicates if this JavaClass is either the same as, or is a superclass of, * the javaClass argument. * * @param javaClass the Class to test. * * @return true if this JavaClass is assignable from * javaClass, otherwise false. * * @see java.lang.Class#isAssignableFrom(Class) */ @Override public boolean isAssignableFrom(JavaClass javaClass) { if (javaClass == null) { return false; } XJCJavaClassImpl javaClassImpl = (XJCJavaClassImpl) javaClass; JClass someClass = javaClassImpl.xjcClass; return xjcClass.isAssignableFrom(someClass); } /** * Indicates if this JavaClass is an enum. * * @return true if this JavaClass is an enum, otherwise false. */ @Override public boolean isEnum() { return xjcClass.getClassType().equals(ClassType.ENUM); } /** * Indicates if this JavaClass is final. * * @return true if this JavaClass is final, otherwise false. */ @Override public boolean isFinal() { return Modifier.isFinal(getModifiers()); } /** * Indicates if this JavaClass is an interface. * * @return true if this JavaClass is an interface, otherwise false. */ @Override public boolean isInterface() { return xjcClass.isInterface(); } /** * Indicates if this JavaClass is an inner Class. * * @return true if this JavaClass is an inner Class, otherwise false. */ @Override public boolean isMemberClass() { return this.xjcClass.outer() != null; } /** * Indicates if this JavaClass represents a primitive type. * * @return true if this JavaClass represents a primitive type, otherwise false. */ @Override public boolean isPrimitive() { return false; } /** * Indicates if this JavaClass is private. * * @return true if this JavaClass is private, otherwise false. */ @Override public boolean isPrivate() { return Modifier.isPrivate(getModifiers()); } /** * Indicates if this JavaClass is protected. * * @return true if this JavaClass is protected, otherwise false. */ @Override public boolean isProtected() { return Modifier.isProtected(getModifiers()); } /** * Indicates if this JavaClass is public. * * @return true if this JavaClass is public, otherwise false. */ @Override public boolean isPublic() { return Modifier.isPublic(getModifiers()); } /** * Indicates if this JavaClass is static. * * @return true if this JavaClass is static, otherwise false. */ @Override public boolean isStatic() { return Modifier.isStatic(getModifiers()); } /** * Not supported. */ @Override public boolean isSynthetic() { throw new UnsupportedOperationException("isSynthetic"); } @Override public JavaClassInstanceOf instanceOf() { return JavaClassInstanceOf.XJC_JAVA_CLASS_IMPL; } /** * If this JavaClass is annotated with an Annotation matching aClass, * return its JavaAnnotation representation. * * @param aClass a JavaClass representing the Annotation to look for. * * @return the JavaAnnotation represented by aClass, if one exists, otherwise return null. */ @Override @SuppressWarnings("unchecked") public JavaAnnotation getAnnotation(JavaClass aClass) { if (aClass != null) { Collection annotations = null; try { annotations = (Collection) PrivilegedAccessHelper.getValueFromField(JDEFINEDCLASS_ANNOTATIONS, xjcClass); } catch (Exception e) { } if (annotations == null) { return null; } for (JAnnotationUse annotationUse : annotations) { XJCJavaAnnotationImpl xjcAnnotation = new XJCJavaAnnotationImpl(annotationUse, dynamicClassLoader); String myAnnotationClass = xjcAnnotation.getJavaAnnotationClass().getCanonicalName(); String annotationClass = aClass.getQualifiedName(); if (myAnnotationClass.equals(annotationClass)) { return xjcAnnotation; } } // Didn't find annotation so return null return null; } // aClass was null so return null return null; } /** * Return all of the Annotations for this JavaClass. * * @return A Collection containing this JavaClass' JavaAnnotations. */ @Override @SuppressWarnings("unchecked") public Collection getAnnotations() { ArrayList annotationsList = new ArrayList(); Collection annotations = null; try { annotations = (Collection) PrivilegedAccessHelper.getValueFromField(JDEFINEDCLASS_ANNOTATIONS, xjcClass); } catch (Exception e) { } if (annotations == null) { return annotationsList; } for (JAnnotationUse annotationUse : annotations) { XJCJavaAnnotationImpl xjcAnnotation = new XJCJavaAnnotationImpl(annotationUse, dynamicClassLoader); annotationsList.add(xjcAnnotation); } return annotationsList; } /** * Not supported. */ @Override public JavaAnnotation getDeclaredAnnotation(JavaClass arg0) { return getAnnotation(arg0); } /** * Not supported. */ @Override public Collection getDeclaredAnnotations() { return getAnnotations(); } /** * Get this JavaClass' JavaModel. * * @return The JavaModel associated with this JavaClass. */ public JavaModel getJavaModel() { return javaModel; } /** * Set this JavaClass' JavaModel. * * @param javaModel The JavaModel to set. */ public void setJavaModel(JavaModel javaModel) { this.javaModel = javaModel; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy