You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2021/03/25 23:32:16 UTC
[tomee-jakarta] branch master updated: Remove Eclipselink patches
now that we're using v3
This is an automated email from the ASF dual-hosted git repository.
dblevins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee-jakarta.git
The following commit(s) were added to refs/heads/master by this push:
new 06c65c1 Remove Eclipselink patches now that we're using v3
06c65c1 is described below
commit 06c65c160597e299a1d95b35e0f74502068fd3f9
Author: David Blevins <da...@gmail.com>
AuthorDate: Thu Mar 25 16:31:52 2021 -0700
Remove Eclipselink patches now that we're using v3
---
pom.xml | 1 -
tomee/tomee-plume-webapp/pom.xml | 1 -
.../jpa/deployment/JavaSECMPInitializer.java | 372 --------
.../accessors/objects/MetadataAsmFactory.java | 712 ---------------
.../metadata/accessors/objects/MetadataClass.java | 628 -------------
.../eclipse/persistence/jaxb/javamodel/Helper.java | 478 ----------
.../jaxb/javamodel/reflection/JavaClassImpl.java | 576 ------------
.../persistence/jaxb/rs/MOXyJsonProvider.java | 986 ---------------------
.../persistence/jpa/rs/PersistenceFactoryBase.java | 266 ------
9 files changed, 4020 deletions(-)
diff --git a/pom.xml b/pom.xml
index 5f67911..e8124c4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -115,7 +115,6 @@
<tomcat.version>10.0.4</tomcat.version>
<tomee.build.name>${project.groupId}.tomee.tomee</tomee.build.name>
<tomee.version>8.0.7-SNAPSHOT</tomee.version>
- <version.eclipselink>2.7.7</version.eclipselink>
<version.eclipselink>3.0.0</version.eclipselink>
<version.groovy>2.4.12</version.groovy>
<version.hsqldb>2.3.2</version.hsqldb>
diff --git a/tomee/tomee-plume-webapp/pom.xml b/tomee/tomee-plume-webapp/pom.xml
index 665618c..62dcf04 100644
--- a/tomee/tomee-plume-webapp/pom.xml
+++ b/tomee/tomee-plume-webapp/pom.xml
@@ -284,7 +284,6 @@
<select>tomee-plume-webapp-transformed-.*\.war</select>
<patchSources>
<source>${project.basedir}/../../transform/src/patch/java/</source>
- <source>${project.basedir}/src/patch/java/</source>
</patchSources>
<replacements>
<openejb-version.properties>${project.build.outputDirectory}/openejb-version.properties</openejb-version.properties>
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/deployment/JavaSECMPInitializer.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/deployment/JavaSECMPInitializer.java
deleted file mode 100644
index 3b773b3..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/deployment/JavaSECMPInitializer.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 1998, 2018 IBM Corporation. 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
-// tware - 1.0RC1 - refactor for OSGi
-// zhao jianyong - Bug 324627 - JarList stream is not explicitly closed after use in JavaSECMPInitializer
-package org.eclipse.persistence.internal.jpa.deployment;
-
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.ProtectionDomain;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
-import jakarta.persistence.PersistenceException;
-import jakarta.persistence.spi.ClassTransformer;
-import jakarta.persistence.spi.PersistenceUnitInfo;
-
-import org.eclipse.persistence.config.PersistenceUnitProperties;
-import org.eclipse.persistence.exceptions.EntityManagerSetupException;
-import org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider;
-import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
-import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
-import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
-import org.eclipse.persistence.logging.AbstractSessionLog;
-import org.eclipse.persistence.logging.SessionLog;
-
-/**
- * INTERNAL:
- *
- * JavaSECMPInitializer is used to bootstrap the deployment of EntityBeans in EJB 3.0
- * when deployed in a non-managed setting
- *
- * It is called internally by our Provider
- *
- * @see org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider
- */
-public class JavaSECMPInitializer extends JPAInitializer {
-
- // Used when byte code enhancing
- public static Instrumentation globalInstrumentation;
- // Adding this flag because globalInstrumentation could be set to null after weaving is done.
- protected static boolean usesAgent;
- // Adding this flag to know that within a JEE container so weaving should be enabled without an agent for non managed persistence units.
- protected static boolean isInContainer;
- // Indicates whether has been initialized - that could be done only once.
- protected static boolean isInitialized;
- // Singleton corresponding to the main class loader. Created only if agent is used.
- protected static JavaSECMPInitializer initializer;
- // Used as a lock in getJavaSECMPInitializer.
- private static final Object initializationLock = new Object();
-
- public static boolean isInContainer() {
- return isInContainer;
- }
- public static void setIsInContainer(boolean isInContainer) {
- JavaSECMPInitializer.isInContainer = isInContainer;
- }
-
- /**
- * Get the singleton entityContainer.
- */
- public static JavaSECMPInitializer getJavaSECMPInitializer() {
- return getJavaSECMPInitializer(Thread.currentThread().getContextClassLoader(), null, false);
- }
- public static JavaSECMPInitializer getJavaSECMPInitializer(ClassLoader classLoader) {
- return getJavaSECMPInitializer(classLoader, null, false);
- }
- public static JavaSECMPInitializer getJavaSECMPInitializerFromAgent() {
- return getJavaSECMPInitializer(Thread.currentThread().getContextClassLoader(), null, true);
- }
- public static JavaSECMPInitializer getJavaSECMPInitializerFromMain(Map m) {
- return getJavaSECMPInitializer(Thread.currentThread().getContextClassLoader(), m, false);
- }
- public static JavaSECMPInitializer getJavaSECMPInitializer(ClassLoader classLoader, Map m, boolean fromAgent) {
- if(!isInitialized) {
- if(globalInstrumentation != null) {
- synchronized(initializationLock) {
- if(!isInitialized) {
- initializeTopLinkLoggingFile();
- if(fromAgent) {
- AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.WEAVER, "cmp_init_initialize_from_agent", (Object[])null);
- }
- usesAgent = true;
- initializer = new JavaSECMPInitializer(classLoader);
- initializer.initialize(m != null ? m : new HashMap(0));
- // all the transformers have been added to instrumentation, don't need it any more.
- globalInstrumentation = null;
- }
- }
- }
- isInitialized = true;
- }
- if(initializer != null && initializer.getInitializationClassLoader() == classLoader) {
- return initializer;
- } else {
- // when agent is not used initializer does not need to be initialized.
- return new JavaSECMPInitializer(classLoader);
- }
- }
-
- /**
- * User should not instantiate JavaSECMPInitializer.
- */
- protected JavaSECMPInitializer() {
- super();
- }
-
- protected JavaSECMPInitializer(ClassLoader loader) {
- super();
- this.initializationClassloader = loader;
- }
-
- /**
- * Check whether weaving is possible and update the properties and variable as appropriate
- * @param properties The list of properties to check for weaving and update if weaving is not needed
- */
- @Override
- public void checkWeaving(Map properties){
- String weaving = EntityManagerFactoryProvider.getConfigPropertyAsString(PersistenceUnitProperties.WEAVING, properties, null);
- // Check usesAgent instead of globalInstrumentation!=null because globalInstrumentation is set to null after initialization,
- // but we still have to keep weaving so that the resulting projects correspond to the woven (during initialization) classes.
- if (!usesAgent && !isInContainer) {
- if (weaving == null) {
- properties.put(PersistenceUnitProperties.WEAVING, "false");
- weaving = "false";
- } else if (weaving.equalsIgnoreCase("true")) {
- throw new PersistenceException(EntityManagerSetupException.wrongWeavingPropertyValue());
- }
- }
- if ((weaving != null) && ((weaving.equalsIgnoreCase("false")) || (weaving.equalsIgnoreCase("static")))){
- shouldCreateInternalLoader = false;
- }
- }
-
- /**
- * Create a temporary class loader that can be used to inspect classes and then
- * thrown away. This allows classes to be introspected prior to loading them
- * with application's main class loader enabling weaving.
- */
- @Override
- protected ClassLoader createTempLoader(Collection col) {
- return createTempLoader(col, true);
- }
-
- @Override
- protected ClassLoader createTempLoader(Collection col, boolean shouldOverrideLoadClassForCollectionMembers) {
- if (!shouldCreateInternalLoader) {
- return Thread.currentThread().getContextClassLoader();
- }
-
- ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
- if (!(currentLoader instanceof URLClassLoader)) {
- //we can't create a TempEntityLoader so just use the current one
- //shouldn't be a problem (and should only occur) in JavaSE
- return currentLoader;
- }
- URL[] urlPath = ((URLClassLoader)currentLoader).getURLs();
-
- ClassLoader tempLoader = null;
- if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
- try {
- Class[] argsClasses = new Class[] { URL[].class, ClassLoader.class, Collection.class, boolean.class };
- Object[] args = new Object[] { urlPath, currentLoader, col, shouldOverrideLoadClassForCollectionMembers };
- Constructor classLoaderConstructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor(TempEntityLoader.class, argsClasses, true));
- tempLoader = (ClassLoader) AccessController.doPrivileged(new PrivilegedInvokeConstructor(classLoaderConstructor, args));
- } catch (PrivilegedActionException privilegedException) {
- throw new PersistenceException(EntityManagerSetupException.failedToInstantiateTemporaryClassLoader(privilegedException));
- }
- } else {
- tempLoader = new TempEntityLoader(urlPath, currentLoader, col, shouldOverrideLoadClassForCollectionMembers);
- }
-
- AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.WEAVER, "cmp_init_tempLoader_created", tempLoader);
- AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.WEAVER, "cmp_init_shouldOverrideLoadClassForCollectionMembers", Boolean.valueOf(shouldOverrideLoadClassForCollectionMembers));
-
- return tempLoader;
- }
-
- /**
- * INTERNAL:
- * Should be called only by the agent. (when weaving classes)
- * If succeeded return true, false otherwise.
- */
- protected static void initializeFromAgent(Instrumentation instrumentation) throws Exception {
- // Squirrel away the instrumentation for later
- globalInstrumentation = instrumentation;
- getJavaSECMPInitializerFromAgent();
- }
-
- /**
- * Usually JavaSECMPInitializer is initialized from agent during premain
- * to ensure that the classes to be weaved haven't been loaded before initialization.
- * However, in this case initialization can't be debugged.
- * In order to be able to debug initialization specify
- * in java options -javaagent with parameter "main": (note: a separate eclipselink-agent.jar is no longer required)
- * -javaagent:c:\trunk\eclipselink.jar=main
- * that causes instrumentation to be cached during premain and postpones initialization until main.
- * With initialization done in main (during the first createEntityManagerFactory call)
- * there's a danger of the classes to be weaved being already loaded.
- * In that situation initializeFromMain should be called before any classes are loaded.
- * The sure-to-work method would be to create a new runnable class with a main method
- * consisting of just two lines: calling initializeFromMain
- * followed by reflective call to the main method of the original runnable class.
- * The same could be achieved by calling PersistenceProvider.createEntityManagerFactory method instead
- * of JavaSECMPInitializer.initializeFromMain method,
- * however initializeFromMain might be more convenient because it
- * doesn't require a persistence unit name.
- * The method doesn't do anything if JavaSECMPInitializer has been already initialized.
- * @param m - a map containing the set of properties to instantiate with.
- */
- public static void initializeFromMain(Map m) {
- getJavaSECMPInitializerFromMain(m);
- }
-
- /**
- * The version of initializeFromMain that passes an empty map.
- */
- public static void initializeFromMain() {
- initializeFromMain(new HashMap());
- }
-
- /**
- * Register a transformer. In this case, we use the instrumentation to add a transformer for the
- * JavaSE environment
- * @param transformer
- * @param persistenceUnitInfo
- */
- @Override
- public void registerTransformer(final ClassTransformer transformer, PersistenceUnitInfo persistenceUnitInfo, Map properties){
- if ((transformer != null) && (globalInstrumentation != null)) {
- AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.WEAVER, "cmp_init_register_transformer", persistenceUnitInfo.getPersistenceUnitName());
- globalInstrumentation.addTransformer(new ClassFileTransformer() {
- // adapt ClassTransformer to ClassFileTransformer interface
- @Override
- public byte[] transform(
- ClassLoader loader, String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer) throws IllegalClassFormatException {
- return transformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
- }
- });
- } else if (transformer == null) {
- AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.WEAVER, "cmp_init_transformer_is_null", null, true);
- } else if (globalInstrumentation == null) {
- AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.WEAVER, "cmp_init_globalInstrumentation_is_null", null, true);
- }
- }
-
- /**
- * Indicates whether puName uniquely defines the persistence unit.
- * usesAgent means that it is a stand alone SE case.
- * Otherwise it could be an application server case where different persistence units
- * may have the same name: that could happen if they are loaded by different classloaders;
- * the common case is the same persistence unit jar deployed in several applications.
- */
- @Override
- public boolean isPersistenceUnitUniquelyDefinedByName() {
- return usesAgent;
- }
-
- /**
- * Indicates whether initialization has already occurred.
- */
- public static boolean isInitialized() {
- return isInitialized;
- }
-
- /**
- * Indicates whether Java agent and globalInstrumentation was used.
- */
- public static boolean usesAgent() {
- return usesAgent;
- }
-
- /**
- * Indicates whether initialPuInfos and initialEmSetupImpls are used.
- */
- @Override
- protected boolean keepAllPredeployedPersistenceUnits() {
- return usesAgent;
- }
-
- /*********************************/
- /***** Temporary Classloader *****/
- /*********************************/
- /**
- * This class loader is provided at initialization time to allow us to temporarily load
- * domain classes so we can examine them for annotations. After they are loaded we will throw this
- * class loader away. Transformers can then be registered on the real class loader to allow
- * weaving to occur.
- *
- * It selectively loads classes based on the list of classnames it is instantiated with. Classes
- * not on that list are allowed to be loaded by the parent.
- */
- public static class TempEntityLoader extends URLClassLoader {
- Collection classNames;
- boolean shouldOverrideLoadClassForCollectionMembers;
-
- //added to resolved gf #589 - without this, the orm.xml url would be returned twice
- @Override
- public Enumeration<URL> getResources(String name) throws java.io.IOException {
- return this.getParent().getResources(name);
- }
-
- public TempEntityLoader(URL[] urls, ClassLoader parent, Collection classNames, boolean shouldOverrideLoadClassForCollectionMembers) {
- super(urls, parent);
- this.classNames = classNames;
- this.shouldOverrideLoadClassForCollectionMembers = shouldOverrideLoadClassForCollectionMembers;
- }
-
- public TempEntityLoader(URL[] urls, ClassLoader parent, Collection classNames) {
- this(urls, parent, classNames, true);
- }
-
- // Indicates if the classLoad should be overridden for the passed className.
- // Returns true in case the class should NOT be loaded by parent classLoader.
- protected boolean shouldOverrideLoadClass(String name) {
- if (shouldOverrideLoadClassForCollectionMembers) {
- // Override classLoad if the name is in collection
- return (classNames != null) && classNames.contains(name);
- } else {
- // Directly opposite: Override classLoad if the name is NOT in collection.
- // Forced to check for java. and javax. packages here, because even if the class
- // has been loaded by parent loader we would load it again
- // (see comment in loadClass)
- return !name.startsWith("java.") && !name.startsWith("javax.") && !name.startsWith("jakarta.") && ((classNames == null) || !classNames.contains(name));
- }
- }
-
- @Override
- protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
- if (shouldOverrideLoadClass(name)) {
- // First, check if the class has already been loaded.
- // Note that the check only for classes loaded by this loader,
- // it doesn't return true if the class has been loaded by parent loader
- // (forced to live with that because findLoadedClass method defined as final protected:
- // neither can override it nor call it on the parent loader)
- Class c = findLoadedClass(name);
- if (c == null) {
- c = findClass(name);
- }
- if (resolve) {
- resolveClass(c);
- }
- return c;
- } else {
- return super.loadClass(name, resolve);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataAsmFactory.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataAsmFactory.java
deleted file mode 100644
index 04fce33..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataAsmFactory.java
+++ /dev/null
@@ -1,712 +0,0 @@
-/*
- * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 1998, 2018 Hans Harz, Andrew Rustleund, IBM Corporation. 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:
-// James Sutherland - initial impl
-// 05/14/2010-2.1 Guy Pelletier
-// - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
-// Hans Harz, Andrew Rustleund - Bug 324862 - IndexOutOfBoundsException in
-// DatabaseSessionImpl.initializeDescriptors because @MapKey Annotation is not found.
-// 04/21/2011-2.3 dclarke: Upgraded to support ASM 3.3.1
-// 08/10/2011-2.3 Lloyd Fernandes : Bug 336133 - Validation error during processing on parameterized generic OneToMany Entity relationship from MappedSuperclass
-// 10/05/2012-2.4.1 Guy Pelletier
-// - 373092: Exceptions using generics, embedded key and entity inheritance
-// 19/04/2014-2.6 Lukas Jungmann
-// - 429992: JavaSE 8/ASM 5.0.1 support (EclipseLink silently ignores Entity classes with lambda expressions)
-// 11/05/2015-2.6 Dalia Abo Sheasha
-// - 480787 : Wrap several privileged method calls with a doPrivileged block
-package org.eclipse.persistence.internal.jpa.metadata.accessors.objects;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.persistence.internal.helper.Helper;
-import org.eclipse.persistence.internal.jpa.metadata.MetadataDescriptor;
-import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
-import org.eclipse.persistence.internal.libraries.asm.AnnotationVisitor;
-import org.eclipse.persistence.internal.libraries.asm.Attribute;
-import org.eclipse.persistence.internal.libraries.asm.ClassReader;
-import org.eclipse.persistence.internal.libraries.asm.ClassVisitor;
-import org.eclipse.persistence.internal.libraries.asm.EclipseLinkClassReader;
-import org.eclipse.persistence.internal.libraries.asm.FieldVisitor;
-import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
-import org.eclipse.persistence.internal.libraries.asm.Opcodes;
-import org.eclipse.persistence.internal.libraries.asm.Type;
-import org.eclipse.persistence.internal.localization.ExceptionLocalization;
-import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
-import org.eclipse.persistence.logging.AbstractSessionLog;
-import org.eclipse.persistence.logging.SessionLog;
-import org.eclipse.persistence.logging.SessionLogEntry;
-
-/**
- * INTERNAL: A metadata factory that uses ASM technology and no reflection
- * whatsoever to process the metadata model.
- *
- * @author James Sutherland
- * @since EclipseLink 1.2
- */
-public class MetadataAsmFactory extends MetadataFactory {
- /** Set of primitive type codes. */
- public static final String PRIMITIVES = "VJIBZCSFD";
- /** Set of desc token characters. */
- public static final String TOKENS = "()<>;";
-
- /**
- * INTERNAL:
- */
- public MetadataAsmFactory(MetadataLogger logger, ClassLoader loader) {
- super(logger, loader);
-
- addMetadataClass("I", new MetadataClass(this, int.class));
- addMetadataClass("J", new MetadataClass(this, long.class));
- addMetadataClass("S", new MetadataClass(this, short.class));
- addMetadataClass("Z", new MetadataClass(this, boolean.class));
- addMetadataClass("F", new MetadataClass(this, float.class));
- addMetadataClass("D", new MetadataClass(this, double.class));
- addMetadataClass("C", new MetadataClass(this, char.class));
- addMetadataClass("B", new MetadataClass(this, byte.class));
- }
-
- /**
- * Build the class metadata for the class name using ASM to read the class
- * byte codes.
- */
- protected void buildClassMetadata(MetadataClass metadataClass, String className, boolean isLazy) {
- ClassMetadataVisitor visitor = new ClassMetadataVisitor(metadataClass, isLazy);
- InputStream stream = null;
- try {
- String resourceString = className.replace('.', '/') + ".class";
- if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
- final String f_resourceString = resourceString;
- stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
- @Override
- public InputStream run() {
- return m_loader.getResourceAsStream(f_resourceString);
- }
- });
- } else {
- stream = m_loader.getResourceAsStream(resourceString);
- }
-
- ClassReader reader = new ClassReader(stream);
- Attribute[] attributes = new Attribute[0];
- reader.accept(visitor, attributes, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
- } catch (IllegalArgumentException iae) {
- // class was probably compiled with some newer than officially
- // supported and tested JDK
- // in such case log a warning and try to re-read the class
- // without class version check
- SessionLog log = getLogger().getSession() != null
- ? getLogger().getSession().getSessionLog() : AbstractSessionLog.getLog();
- if (log.shouldLog(SessionLog.SEVERE, SessionLog.METADATA)) {
- SessionLogEntry entry = new SessionLogEntry(getLogger().getSession(), SessionLog.SEVERE, SessionLog.METADATA, iae);
- entry.setMessage(ExceptionLocalization.buildMessage("unsupported_classfile_version", new Object[] { className }));
- log.log(entry);
- }
- if (stream != null) {
- try {
- ClassReader reader = new EclipseLinkClassReader(stream);
- Attribute[] attributes = new Attribute[0];
- reader.accept(visitor, attributes, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
- } catch (Exception e) {
- if (log.shouldLog(SessionLog.SEVERE, SessionLog.METADATA)) {
- SessionLogEntry entry = new SessionLogEntry(getLogger().getSession(), SessionLog.SEVERE, SessionLog.METADATA, e);
- entry.setMessage(ExceptionLocalization.buildMessage("unsupported_classfile_version", new Object[] { className }));
- log.log(entry);
- }
- addMetadataClass(getVirtualMetadataClass(className));
- }
- } else {
- addMetadataClass(getVirtualMetadataClass(className));
- }
- } catch (Exception exception) {
- SessionLog log = getLogger().getSession() != null
- ? getLogger().getSession().getSessionLog() : AbstractSessionLog.getLog();
- if (log.shouldLog(SessionLog.FINEST, SessionLog.METADATA)) {
- log.logThrowable(SessionLog.FINEST, SessionLog.METADATA, exception);
- }
- addMetadataClass(getVirtualMetadataClass(className));
- } finally {
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException ignore) {
- // Ignore.
- }
- }
- }
-
- /**
- * Return the class metadata for the class name.
- */
- @Override
- public MetadataClass getMetadataClass(String className) {
- return getMetadataClass(className, false);
- }
-
- /**
- * Return the class metadata for the class name.
- */
- @Override
- public MetadataClass getMetadataClass(String className, boolean isLazy) {
- if (className == null) {
- return null;
- }
-
- MetadataClass metaClass = m_metadataClasses.get(className);
- if ((metaClass == null) || (!isLazy && metaClass.isLazy())) {
- if (metaClass != null) {
- metaClass.setIsLazy(false);
- }
- buildClassMetadata(metaClass, className, isLazy);
- metaClass = m_metadataClasses.get(className);
- }
-
- return metaClass;
- }
-
- /**
- * INTERNAL: This method resolves generic types based on the ASM class
- * metadata. Unless every other factory (e.g. APT mirror factory) respects
- * the generic format as built from ASM this method will not work since it
- * is very tied to it.
- */
- @Override
- public void resolveGenericTypes(MetadataClass child, List<String> genericTypes, MetadataClass parent, MetadataDescriptor descriptor) {
- // If we have a generic parent we need to grab our generic types
- // that may be used (and therefore need to be resolved) to map
- // accessors correctly.
- if (genericTypes != null) {
- // The generic types provided map to its parents generic types. The
- // generics also include the superclass, and interfaces. The parent
- // generics include the type and ":" and class.
-
- List<String> parentGenericTypes = parent.getGenericType();
- if (parentGenericTypes != null) {
- List genericParentTemp = new ArrayList(genericTypes);
- genericParentTemp.removeAll(child.getInterfaces());
-
- int size = genericParentTemp.size();
- int parentIndex = 0;
-
- for (int index = genericTypes.indexOf(parent.getName()) + 1; index < size; index++) {
- String actualTypeArgument = genericTypes.get(index);
- // Ignore extra types on the end of the child, such as
- // interface generics.
- if (parentIndex >= parentGenericTypes.size()) {
- break;
- }
- String variable = parentGenericTypes.get(parentIndex);
-
- // if we get as far as the superclass name in the parent generic type list,
- // there is nothing more to process. We have processed all the generics in the type definition
- if (variable.equals(parent.getSuperclassName())){
- break;
- }
- parentIndex = parentIndex + 3;
-
- // We are building bottom up and need to link up any
- // TypeVariables with the actual class from the originating
- // entity.
- if (actualTypeArgument.length() == 1) {
- index++;
- actualTypeArgument = genericTypes.get(index);
- descriptor.addGenericType(variable, descriptor.getGenericType(actualTypeArgument));
- } else {
- descriptor.addGenericType(variable, actualTypeArgument);
- }
- }
- }
- }
- }
-
- /**
- * Walk the class byte codes and collect the class info.
- */
- public class ClassMetadataVisitor extends ClassVisitor {
-
- private boolean isLazy;
- private boolean processedMemeber;
- private MetadataClass classMetadata;
-
- ClassMetadataVisitor(MetadataClass metadataClass, boolean isLazy) {
- super(Opcodes.ASM7);
- this.isLazy = isLazy;
- this.classMetadata = metadataClass;
- }
-
- @Override
- public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- String className = toClassName(name);
- if ((this.classMetadata == null) || !this.classMetadata.getName().equals(className)) {
- this.classMetadata = new MetadataClass(MetadataAsmFactory.this, className, isLazy);
- addMetadataClass(this.classMetadata);
- }
- this.classMetadata.setName(className);
- this.classMetadata.setSuperclassName(toClassName(superName));
- this.classMetadata.setModifiers(access);
- this.classMetadata.setGenericType(processDescription(signature, true));
-
- for (String interfaceName : interfaces) {
- this.classMetadata.addInterface(toClassName(interfaceName));
- }
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
- this.processedMemeber = true;
- if (this.classMetadata.isLazy()) {
- return null;
- }
- return new MetadataFieldVisitor(this.classMetadata, access, name, desc, signature, value);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- this.processedMemeber = true;
- if (this.classMetadata.isLazy() || name.indexOf("init>") != -1) {
- return null;
- }
- return new MetadataMethodVisitor(this.classMetadata, access, name, signature, desc, exceptions);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- boolean isJPA = false;
- if (desc.startsWith("Lkotlin")) {
- //ignore kotlin annotations
- return null;
- }
- if (desc.startsWith("Ljava")) {
- char c = desc.charAt(5);
- //ignore annotations from 'java' namespace
- if (c == '/') {
- return null;
- }
- //ignore annotations from other then 'javax/persistence' namespace
- if (desc.regionMatches(5, "x/", 0, 2)) {
- if (desc.regionMatches(7, "persistence", 0, "persistence".length())) {
- isJPA = true;
- } else {
- return null;
- }
- }
- }
- if (desc.startsWith("Ljakarta")) {
- //ignore annotations from other then 'jakarta/persistence' namespace
- if (desc.regionMatches(9, "persistence", 0, "persistence".length())) {
- isJPA = true;
- } else {
- return null;
- }
- }
- if (!this.processedMemeber && this.classMetadata.isLazy()) {
- this.classMetadata.setIsLazy(false);
- }
- //this currently forbids us to use meta-annotations defined in EclipseLink packages
- return new MetadataAnnotationVisitor(this.classMetadata, desc, isJPA || desc.startsWith("Lorg/eclipse/persistence"));
- }
-
- }
-
- /**
- * {@link AnnotationVisitor} used to process class, field , and method
- * annotations populating a {@link MetadataAnnotation} and its nested state.
- *
- * @see MetadataAnnotationArrayVisitor for population of array attributes
- */
- class MetadataAnnotationVisitor extends AnnotationVisitor {
-
- /**
- * Element the annotation is being applied to. If this is null the
- * {@link MetadataAnnotation} being constructed is a nested annotation
- * and is already referenced from its parent.
- */
- private MetadataAnnotatedElement element;
-
- /**
- * {@link MetadataAnnotation} being populated
- */
- private MetadataAnnotation annotation;
-
- MetadataAnnotationVisitor(MetadataAnnotatedElement element, String name) {
- this(element, name, true);
- }
-
- MetadataAnnotationVisitor(MetadataAnnotatedElement element, String name, boolean isRegular) {
- super(Opcodes.ASM7);
- this.element = element;
- this.annotation = new MetadataAnnotation();
- this.annotation.setName(processDescription(name, false).get(0));
- this.annotation.setIsMeta(!isRegular);
- }
-
- public MetadataAnnotationVisitor(MetadataAnnotation annotation) {
- super(Opcodes.ASM7);
- this.annotation = annotation;
- }
-
- @Override
- public void visit(String name, Object value) {
- this.annotation.addAttribute(name, annotationValue(null, value));
- }
-
- @Override
- public void visitEnum(String name, String desc, String value) {
- this.annotation.addAttribute(name, annotationValue(desc, value));
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- MetadataAnnotation mda = new MetadataAnnotation();
- mda.setName(processDescription(desc, false).get(0));
- this.annotation.addAttribute(name, mda);
- return new MetadataAnnotationVisitor(mda);
- }
-
- @Override
- public AnnotationVisitor visitArray(String name) {
- return new MetadataAnnotationArrayVisitor(this.annotation, name);
- }
-
- @Override
- public void visitEnd() {
- if (this.element != null) {
- if (this.annotation.isMeta()) {
- this.element.addMetaAnnotation(this.annotation);
- } else {
- this.element.addAnnotation(this.annotation);
- }
- }
- }
- }
-
- /**
- * Specialized visitor to handle the population of arrays of annotation
- * values.
- */
- class MetadataAnnotationArrayVisitor extends AnnotationVisitor {
-
- private MetadataAnnotation annotation;
-
- private String attributeName;
-
- private List<Object> values;
-
- public MetadataAnnotationArrayVisitor(MetadataAnnotation annotation, String name) {
- super(Opcodes.ASM7);
- this.annotation = annotation;
- this.attributeName = name;
- this.values = new ArrayList<Object>();
- }
-
- @Override
- public void visit(String name, Object value) {
- this.values.add(annotationValue(null, value));
- }
-
- @Override
- public void visitEnum(String name, String desc, String value) {
- this.values.add(annotationValue(desc, value));
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- MetadataAnnotation mda = new MetadataAnnotation();
- mda.setName(processDescription(desc, false).get(0));
- this.values.add(mda);
- return new MetadataAnnotationVisitor(mda);
- }
-
- @Override
- public void visitEnd() {
- this.annotation.addAttribute(this.attributeName, this.values.toArray());
- }
- }
-
- /**
- * Factory for the creation of {@link MetadataField} handling basic type,
- * generics, and annotations.
- */
- class MetadataFieldVisitor extends FieldVisitor {
-
- private MetadataField field;
-
- public MetadataFieldVisitor(MetadataClass classMetadata, int access, String name, String desc, String signature, Object value) {
- super(Opcodes.ASM7);
- this.field = new MetadataField(classMetadata);
- this.field.setModifiers(access);
- this.field.setName(name);
- this.field.setAttributeName(name);
- this.field.setGenericType(processDescription(signature, true));
- this.field.setType(processDescription(desc, false).get(0));
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (desc.startsWith("Ljavax/persistence") || desc.startsWith("Ljakarta/persistence")
- || desc.startsWith("Lorg/eclipse/persistence")) {
- return new MetadataAnnotationVisitor(this.field, desc);
- }
- return null;
- }
-
- @Override
- public void visitEnd() {
- this.field.getDeclaringClass().addField(this.field);
- }
- }
-
- /**
- * Factory for the creation of {@link MetadataMethod} handling basic type,
- * generics, and annotations.
- */
- // Note: Subclassed EmptyListener to minimize signature requirements for
- // ignored MethodVisitor API
- class MetadataMethodVisitor extends MethodVisitor {
-
- private MetadataMethod method;
-
- public MetadataMethodVisitor(MetadataClass classMetadata, int access, String name, String desc, String signature, String[] exceptions) {
- super(Opcodes.ASM7);
- this.method = new MetadataMethod(MetadataAsmFactory.this, classMetadata);
-
- this.method.setName(name);
- this.method.setAttributeName(Helper.getAttributeNameFromMethodName(name));
- this.method.setModifiers(access);
-
- this.method.setGenericType(processDescription(desc, true));
-
- List<String> argumentNames = processDescription(signature, false);
- if (argumentNames != null && !argumentNames.isEmpty()) {
- this.method.setReturnType(argumentNames.get(argumentNames.size() - 1));
- argumentNames.remove(argumentNames.size() - 1);
- this.method.setParameters(argumentNames);
- }
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (desc.startsWith("Ljavax/persistence") || desc.startsWith("Ljakarta/persistence")
- || desc.startsWith("Lorg/eclipse/persistence")) {
- return new MetadataAnnotationVisitor(this.method, desc);
- }
- return null;
- }
-
- /**
- * At the end of visiting this method add it to the
- * {@link MetadataClass} and handle duplicate method names by chaining
- * them.
- */
- @Override
- public void visitEnd() {
- MetadataClass classMetadata = this.method.getMetadataClass();
-
- MetadataMethod existing = classMetadata.getMethods().get(this.method.getName());
- if (existing == null) {
- classMetadata.getMethods().put(this.method.getName(), this.method);
- } else {
- // Handle methods with the same name.
- while (existing.getNext() != null) {
- existing = existing.getNext();
- }
- existing.setNext(this.method);
- }
- }
-
- }
-
- /**
- * Get MetadataClass for a class which can not be found
- * @param className class which has not been found
- * @return MetadataClass
- */
- private MetadataClass getVirtualMetadataClass(String className) {
- // Some basic types can't be found, so can just be registered
- // (i.e. arrays). Also, VIRTUAL classes may also not exist,
- // therefore, tag the MetadataClass as loadable false. This will be
- // used to determine if a class will be dynamically created or not.
- MetadataClass metadataClass = new MetadataClass(this, className, false);
- // If the class is a JDK class, then maybe there is a class loader
- // issues,
- // since it is a JDK class, just use reflection.
- if ((className.length() > 5) && className.substring(0, 5).equals("java.")) {
- try {
- Class reflectClass = Class.forName(className);
- if (reflectClass.getSuperclass() != null) {
- metadataClass.setSuperclassName(reflectClass.getSuperclass().getName());
- }
- for (Class reflectInterface : reflectClass.getInterfaces()) {
- metadataClass.addInterface(reflectInterface.getName());
- }
- } catch (Exception failed) {
- SessionLog log = getLogger().getSession() != null
- ? getLogger().getSession().getSessionLog() : AbstractSessionLog.getLog();
- if (log.shouldLog(SessionLog.FINE, SessionLog.METADATA)) {
- log.logThrowable(SessionLog.FINE, SessionLog.METADATA, failed);
- }
- metadataClass.setIsAccessible(false);
- }
- } else {
- metadataClass.setIsAccessible(false);
- }
- return metadataClass;
- }
-
- /**
- * Process the byte-code argument description and return the array of Java
- * class names. i.e.
- * "(Lorg/foo/Bar;Z)Ljava/lang/Boolean;"=>[org.foo.Bar,boolean
- * ,java.lang.Boolean]
- */
- private static List<String> processDescription(String desc, boolean isGeneric) {
- if (desc == null) {
- return null;
- }
- List<String> arguments = new ArrayList<String>();
- int index = 0;
- int length = desc.length();
- boolean isGenericTyped=false;
- // PERF: Use char array to make char index faster (note this is a heavily optimized method, be very careful on changes)
- char[] chars = desc.toCharArray();
- while (index < length) {
- char next = chars[index];
- if (('(' != next) && (')' != next) && ('<' != next) && ('>' != next) && (';' != next)) {
- if (next == 'L') {
- index++;
- int start = index;
- next = chars[index];
- while (('(' != next) && (')' != next) && ('<' != next) && ('>' != next) && (';' != next)) {
- index++;
- next = chars[index];
- }
- arguments.add(toClassName(desc.substring(start, index)));
- if(isGenericTyped) {
- isGenericTyped=false;
- if(next == '<') {
- int cnt = 1;
- while((cnt > 0) && (++index<desc.length())) {
- switch (desc.charAt(index)) {
- case '<': cnt ++; break;
- case '>': cnt --; break;
- }
- }
- }
- }
- } else if (!isGeneric && (PRIMITIVES.indexOf(next) != -1)) {
- // Primitives.
- arguments.add(getPrimitiveName(next));
- } else if (next == '[') {
- // Arrays.
- int start = index;
- index++;
- next = chars[index];
- // Nested arrays.
- while (next == '[') {
- index++;
- next = chars[index];
- }
- if (PRIMITIVES.indexOf(next) == -1) {
- while (next != ';') {
- index++;
- next = chars[index];
- }
- arguments.add(toClassName(desc.substring(start, index + 1)));
- } else {
- arguments.add(desc.substring(start, index + 1));
- }
- } else {
- // Is a generic type variable.
- int start = index;
- int end = start;
-
- char myNext = next;
-
- while (':' != myNext && '(' != myNext && ')' != myNext && '<' != myNext && '>' != myNext && ';' != myNext && end < length - 1) {
- end++;
- myNext = chars[end];
- }
-
- if (myNext == ':') {
- arguments.add(desc.substring(start, end));
- isGenericTyped=true;
- index = end;
- arguments.add(":");
- if(desc.charAt(index+1)==':') {
- index ++;
- }
- } else if (myNext == ';' && next == 'T') {
- arguments.add(new String(new char[] { next }));
- arguments.add(desc.substring(start + 1, end));
- index = end - 1;
- } else {
- arguments.add(new String(new char[] { next }));
- }
- }
- }
- index++;
- }
- return arguments;
-
- }
-
- /**
- * Return the Java type name for the primitive code.
- */
- private static String getPrimitiveName(char primitive) {
- if (primitive == 'V') {
- return "void";
- } else if (primitive == 'I') {
- return "int";
- } else if (primitive == 'Z') {
- return "boolean";
- } else if (primitive == 'J') {
- return "long";
- } else if (primitive == 'F') {
- return "float";
- } else if (primitive == 'D') {
- return "double";
- } else if (primitive == 'B') {
- return "byte";
- } else if (primitive == 'C') {
- return "char";
- } else if (primitive == 'S') {
- return "short";
- } else {
- return new String(new char[] { primitive });
- }
- }
-
- private static String toClassName(String classDescription) {
- if (classDescription == null) {
- return "void";
- }
- return classDescription.replace('/', '.');
- }
-
- /**
- * Convert the annotation value into the value used in the meta model
- */
- private static Object annotationValue(String description, Object value) {
- if (value instanceof Type) {
- return ((Type) value).getClassName();
- }
- return value;
- }
-}
\ No newline at end of file
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataClass.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataClass.java
deleted file mode 100644
index 0670e30..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataClass.java
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * 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
-// 05/16/2008-1.0M8 Guy Pelletier
-// - 218084: Implement metadata merging functionality between mapping files
-// 03/08/2010-2.1 Guy Pelletier
-// - 303632: Add attribute-type for mapping attributes to EclipseLink-ORM
-// 05/04/2010-2.1 Guy Pelletier
-// - 309373: Add parent class attribute to EclipseLink-ORM
-// 05/14/2010-2.1 Guy Pelletier
-// - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
-// 01/25/2011-2.3 Guy Pelletier
-// - 333488: Serializable attribute being defaulted to a variable one to one mapping and causing exception
-// 07/16/2013-2.5.1 Guy Pelletier
-// - 412384: Applying Converter for parameterized basic-type for joda-time's DateTime does not work
-package org.eclipse.persistence.internal.jpa.metadata.accessors.objects;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.persistence.internal.helper.Helper;
-import org.eclipse.persistence.internal.libraries.asm.Opcodes;
-
-/**
- * INTERNAL:
- * An object to hold onto a valid JPA decorated class.
- *
- * @author Guy Pelletier
- * @since TopLink 10.1.3/EJB 3.0 Preview
- */
-public class MetadataClass extends MetadataAnnotatedElement {
- protected boolean m_isLazy;
- protected boolean m_isAccessible;
- protected boolean m_isPrimitive;
- protected boolean m_isJDK;
- protected int m_modifiers;
-
- // Stores the implements interfaces of this class.
- protected List<String> m_interfaces;
-
- // Stores a list of enclosed classes found inside this metadata class.
- // E.g. inner classes, enums etc.
- protected List<MetadataClass> m_enclosedClasses;
-
- // Store the classes field metadata, keyed by the field's name.
- protected Map<String, MetadataField> m_fields;
-
- // Store the classes method metadata, keyed by the method's name.
- // Method's next is used if multiple method with the same name.
- protected Map<String, MetadataMethod> m_methods;
-
- protected MetadataClass m_superclass;
- protected String m_superclassName;
-
- /**
- * Create the metadata class with the class name.
- */
- public MetadataClass(MetadataFactory factory, String name, boolean isLazy) {
- super(factory);
- setName(name);
-
- // By default, set the type to be the same as the name. The canonical
- // model generator relies on types which in most cases is the name, but
- // the generator resolves generic types a little differently to
- // correctly generate model classes.
- setType(name);
-
- m_isAccessible = true;
- m_isLazy = isLazy;
- }
-
- /**
- * Create the metadata class with the class name.
- */
- public MetadataClass(MetadataFactory factory, String name) {
- this(factory, name, false);
- }
-
- /**
- * Create the metadata class based on the class.
- * Mainly used for primitive defaults.
- */
- public MetadataClass(MetadataFactory factory, Class cls) {
- this(factory, cls.getName(), false);
- m_isPrimitive = cls.isPrimitive();
- }
-
- /**
- * INTERNAL:
- */
- public void addEnclosedClass(MetadataClass enclosedClass) {
- if (m_enclosedClasses == null) {
- m_enclosedClasses = new ArrayList<MetadataClass>();
- }
-
- m_enclosedClasses.add(enclosedClass);
- }
-
- /**
- * INTERNAL:
- */
- public void addField(MetadataField field) {
- if (m_fields == null) {
- m_fields = new HashMap<String, MetadataField>();
- }
-
- m_fields.put(field.getName(), field);
- }
-
- /**
- * INTERNAL:
- */
- public void addInterface(String interfaceName) {
- if (m_interfaces == null) {
- m_interfaces = new ArrayList<String>();
- }
-
- m_interfaces.add(interfaceName);
- }
-
- /**
- * INTERNAL:
- */
- public void addMethod(MetadataMethod method) {
- if (m_methods == null) {
- m_methods = new HashMap<String, MetadataMethod>();
- }
-
- m_methods.put(method.getName(), method);
- }
-
- /**
- * Allow comparison to Java classes and Metadata classes.
- */
- @Override
- public boolean equals(Object object) {
- if (object instanceof Class) {
- if (getName() == null) {
- // Void's name is null.
- return ((Class)object).getName() == null;
- }
-
- return getName().equals(((Class)object).getName());
- }
-
- return super.equals(object);
- }
-
- /**
- * INTERNAL:
- * Return if this class is or extends, or super class extends the class.
- */
- public boolean extendsClass(Class javaClass) {
- return extendsClass(javaClass.getName());
- }
-
- /**
- * INTERNAL:
- * Return if this class is or extends, or super class extends the class.
- */
- public boolean extendsClass(String className) {
- if (getName() == null) {
- return className == null;
- }
-
- if (getName().equals(className)) {
- return true;
- }
-
- if (getSuperclassName() == null) {
- return false;
- }
-
- if (getSuperclassName().equals(className)) {
- return true;
- }
-
- return getSuperclass().extendsClass(className);
- }
-
- /**
- * INTERNAL:
- * Return if this class is or extends, or super class extends the interface.
- */
- public boolean extendsInterface(Class javaClass) {
- return extendsInterface(javaClass.getName());
- }
-
- /**
- * INTERNAL:
- * Return if this class is or extends, or super class extends the interface.
- */
- public boolean extendsInterface(String className) {
- if (getName() == null) {
- return false;
- }
-
- if (getName().equals(className)) {
- return true;
- }
-
- if (getInterfaces().contains(className)) {
- return true;
- }
-
- for (String interfaceName : getInterfaces()) {
- if (getMetadataClass(interfaceName).extendsInterface(className)) {
- return true;
- }
- }
-
- if (getSuperclassName() == null) {
- return false;
- }
-
- return getSuperclass().extendsInterface(className);
- }
-
- /**
- * INTERNAL:
- * Return the list of classes defined within this metadata class. E.g.
- * enums and inner classes.
- */
- public List<MetadataClass> getEnclosedClasses() {
- if (m_enclosedClasses == null) {
- m_enclosedClasses = new ArrayList<MetadataClass>();
- }
-
- return m_enclosedClasses;
- }
-
- /**
- * INTERNAL:
- * Return the field with the name.
- * Search for any declared or inherited field.
- */
- public MetadataField getField(String name) {
- return getField(name, true);
- }
-
- /**
- * INTERNAL:
- * Return the field with the name.
- * Search for any declared or inherited field.
- */
- public MetadataField getField(String name, boolean checkSuperClass) {
- MetadataField field = getFields().get(name);
-
- if (checkSuperClass && (field == null) && (getSuperclassName() != null)) {
- return getSuperclass().getField(name);
- }
-
- return field;
- }
-
- /**
- * INTERNAL:
- */
- public Map<String, MetadataField> getFields() {
- if (m_fields == null) {
- m_fields = new HashMap<String, MetadataField>();
-
- if (m_isLazy) {
- m_factory.getMetadataClass(getName(), false);
- }
- }
-
- return m_fields;
- }
-
- /**
- * INTERNAL:
- */
- public List<String> getInterfaces() {
- if (m_interfaces == null) {
- m_interfaces = new ArrayList<String>();
- }
-
- return m_interfaces;
- }
-
- /**
- * INTERNAL:
- * Return the method with the name and no arguments.
- */
- protected MetadataMethod getMethod(String name) {
- return getMethods().get(name);
- }
-
- /**
- * INTERNAL:
- * Return the method with the name and argument types.
- */
- public MetadataMethod getMethod(String name, Class[] arguments) {
- List<String> argumentNames = new ArrayList<String>(arguments.length);
-
- for (int index = 0; index < arguments.length; index++) {
- argumentNames.add(arguments[index].getName());
- }
-
- return getMethod(name, argumentNames);
- }
-
- /**
- * INTERNAL:
- * Return the method with the name and argument types (class names).
- */
- public MetadataMethod getMethod(String name, List<String> arguments) {
- return getMethod(name, arguments, true);
- }
-
- /**
- * INTERNAL:
- * Return the method with the name and argument types (class names).
- */
- public MetadataMethod getMethod(String name, List<String> arguments, boolean checkSuperClass) {
- MetadataMethod method = getMethods().get(name);
-
- while ((method != null) && !method.getParameters().equals(arguments)) {
- method = method.getNext();
- }
-
- if (checkSuperClass && (method == null) && (getSuperclassName() != null)) {
- return getSuperclass().getMethod(name, arguments);
- }
-
- return method;
- }
-
- /**
- * INTERNAL:
- * Return the method with the name and argument types (class names).
- */
- public MetadataMethod getMethod(String name, String[] arguments) {
- return getMethod(name, Arrays.asList(arguments));
- }
-
- /**
- * INTERNAL:
- * Return the method for the given property name.
- */
- public MetadataMethod getMethodForPropertyName(String propertyName) {
- MetadataMethod method;
-
- String leadingChar = String.valueOf(propertyName.charAt(0)).toUpperCase();
- String restOfName = propertyName.substring(1);
-
- // Look for a getPropertyName() method
- method = getMethod(Helper.GET_PROPERTY_METHOD_PREFIX.concat(leadingChar).concat(restOfName), new String[]{});
-
- if (method == null) {
- // Look for an isPropertyName() method
- method = getMethod(Helper.IS_PROPERTY_METHOD_PREFIX.concat(leadingChar).concat(restOfName), new String[]{});
- }
-
- if (method != null) {
- method.setSetMethod(method.getSetMethod(this));
- }
-
- return method;
- }
-
- /**
- * INTERNAL:
- */
- public Map<String, MetadataMethod> getMethods() {
- if (m_methods == null) {
- m_methods = new HashMap<String, MetadataMethod>();
-
- if (m_isLazy) {
- m_factory.getMetadataClass(getName(), false);
- }
- }
- return m_methods;
- }
-
- /**
- * INTERNAL:
- */
- @Override
- public int getModifiers() {
- return m_modifiers;
- }
-
- /**
- * INTERNAL:
- */
- public MetadataClass getSuperclass() {
- if (m_superclass == null) {
- m_superclass = getMetadataClass(m_superclassName);
- }
-
- return m_superclass;
- }
-
- /**
- * INTERNAL:
- */
- public String getSuperclassName() {
- return m_superclassName;
- }
-
- /**
- * Return the ASM type name.
- */
- public String getTypeName() {
- if (isArray()) {
- return getName().replace('.', '/');
- } else if (isPrimitive()) {
- if (getName().equals("int")) {
- return "I";
- } else if (getName().equals("long")) {
- return "J";
- } else if (getName().equals("short")) {
- return "S";
- } else if (getName().equals("boolean")) {
- return "Z";
- } else if (getName().equals("float")) {
- return "F";
- } else if (getName().equals("double")) {
- return "D";
- } else if (getName().equals("char")) {
- return "C";
- } else if (getName().equals("byte")) {
- return "B";
- }
- }
- return "L" + getName().replace('.', '/') + ";";
- }
-
- /**
- * INTERNAL:
- * Return true is this class accessible to be found.
- */
- public boolean isAccessible() {
- return m_isAccessible;
- }
-
- /**
- * INTERNAL:
- * Return if this class is an array type.
- */
- public boolean isArray() {
- return (getName() != null) && (getName().charAt(0) == '[');
- }
-
- /**
- * INTERNAL:
- * Return if this is extends Collection.
- */
- public boolean isCollection() {
- return extendsInterface(Collection.class);
- }
-
- /**
- * INTERNAL:
- * Return if this is extends Enum.
- */
- public boolean isEnum() {
- return extendsClass(Enum.class);
- }
-
- /**
- * INTERNAL:
- * Return if this is an interface (super is null).
- */
- public boolean isInterface() {
- return (Opcodes.ACC_INTERFACE & m_modifiers) != 0;
- }
-
- /**
- * INTERNAL:
- * Return if this is a JDK (java/javax) class.
- */
- public boolean isJDK() {
- return m_isJDK;
- }
-
- /**
- * INTERNAL:
- */
- public boolean isLazy() {
- return m_isLazy;
- }
-
- /**
- * INTERNAL:
- * Return if this is extends List.
- */
- public boolean isList() {
- return extendsInterface(List.class);
- }
-
- /**
- * INTERNAL:
- * Return if this is extends Map.
- */
- public boolean isMap() {
- return extendsInterface(Map.class);
- }
-
- /**
- * INTERNAL:
- * Return if this is Object class.
- */
- public boolean isObject() {
- return getName().equals(Object.class.getName());
- }
-
- /**
- * INTERNAL:
- * Return if this is a primitive.
- */
- public boolean isPrimitive() {
- return m_isPrimitive;
- }
-
- /**
- * INTERNAL:
- * Return if this class extends Serializable or is an array type.
- */
- public boolean isSerializable() {
- if (isArray()) {
- return true;
- }
-
- return extendsInterface(Serializable.class);
- }
-
- /**
- * INTENAL:
- * Return true is this class is the Serializable.class interface.
- */
- public boolean isSerializableInterface() {
- return getName().equals(Serializable.class.getName());
- }
-
- /**
- * INTERNAL:
- * Return true if this extends Set.
- */
- public boolean isSet() {
- return extendsInterface(Set.class);
- }
-
- /**
- * INTERNAL:
- * Return if this is the void class.
- */
- public boolean isVoid() {
- return getName().equals(void.class.getName()) || getName().equals(Void.class.getName());
- }
-
- /**
- * INTERNAL:
- */
- public void setIsAccessible(boolean isAccessible) {
- m_isAccessible = isAccessible;
- }
-
- /**
- * INTERNAL:
- */
- public void setIsJDK(boolean isJDK) {
- m_isJDK = isJDK;
- }
-
- /**
- * INTERNAL:
- */
- public void setIsLazy(boolean isLazy) {
- m_isLazy = isLazy;
- }
-
- /**
- * INTERNAL:
- */
- @Override
- public void setModifiers(int modifiers) {
- m_modifiers = modifiers;
- }
-
- /**
- * INTERNAL:
- */
- @Override
- public void setName(String name) {
- super.setName(name);
-
- if ((!MetadataFactory.ALLOW_JDK) && (name.startsWith("java.")
- || name.startsWith("javax.") || name.startsWith("jakarta.")
- || name.startsWith("org.eclipse.persistence.internal."))) {
- setIsJDK(true);
- }
- }
-
- /**
- * INTERNAL:
- */
- public void setSuperclass(MetadataClass superclass) {
- m_superclass = superclass;
- }
-
- /**
- * INTERNAL:
- */
- public void setSuperclassName(String superclass) {
- m_superclassName = superclass;
- }
-}
\ No newline at end of file
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/javamodel/Helper.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/javamodel/Helper.java
deleted file mode 100644
index a8318eb..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/javamodel/Helper.java
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
- * 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;
-
-import static org.eclipse.persistence.jaxb.JAXBContextFactory.PKG_SEPARATOR;
-import static org.eclipse.persistence.jaxb.compiler.XMLProcessor.DEFAULT;
-
-import java.lang.annotation.Annotation;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
-
-import jakarta.xml.bind.JAXBElement;
-
-import org.eclipse.persistence.internal.oxm.Constants;
-
-/**
- * INTERNAL:
- * <p><b>Purpose:</b>To provide helper methods and constants to assist
- * in integrating TopLink JAXB 2.0 Generation with the JDEV JOT APIs.
- * <p><b>Responsibilities:</b>
- * <ul>
- * <li>Make available a map of JOT - XML type pairs</li>
- * <li>Redirect method calls to the current JavaModel implementation as
- * required</li>
- * <li>Provide methods for accessing generics, annotations, etc. on a
- * given implementaiton's classes</li>
- * <li>Provide a dynamic proxy instance for a given JavaAnnotation in
- * the JOT implementation (for reflection a Java SDK annotation is
- * returned)</li>
- * </ul>
- *
- * @since Oracle TopLink 11.1.1.0.0
- * @see JavaModel
- * @see AnnotationProxy
- *
- */
-public class Helper {
- protected ClassLoader loader;
- protected JavaModel jModel;
- private HashMap xmlToJavaTypeMap;
- private boolean facets;
-
- public final static String APBYTE = "byte[]";
- public final static String BIGDECIMAL = "java.math.BigDecimal";
- public final static String BIGINTEGER = "java.math.BigInteger";
- public final static String PBOOLEAN = "boolean";
- public final static String PBYTE = "byte";
- public final static String CALENDAR = "java.util.Calendar";
- public final static String CHARACTER = "java.lang.Character";
- public final static String CHAR = "char";
- public final static String OBJECT = "java.lang.Object";
- public final static String CLASS = "java.lang.Class";
- public final static String PDOUBLE = "double";
- public final static String PFLOAT = "float";
- public final static String PINT = "int";
- public final static String PLONG = "long";
- public final static String PSHORT = "short";
- public final static String QNAME_CLASS = "javax.xml.namespace.QName";
- public final static String STRING = "java.lang.String";
- public final static String ABYTE = "java.lang.Byte[]";
- public final static String BOOLEAN = "java.lang.Boolean";
- public final static String BYTE = "java.lang.Byte";
- public final static String GREGORIAN_CALENDAR = "java.util.GregorianCalendar";
- public final static String DOUBLE = "java.lang.Double";
- public final static String FLOAT = "java.lang.Float";
- public final static String INTEGER = "java.lang.Integer";
- public final static String UUID = "java.util.UUID";
- public final static String LONG = "java.lang.Long";
- public final static String SHORT = "java.lang.Short";
- public final static String UTIL_DATE = "java.util.Date";
- public final static String SQL_DATE = "java.sql.Date";
- public final static String SQL_TIME = "java.sql.Time";
- public final static String SQL_TIMESTAMP = "java.sql.Timestamp";
- public final static String DURATION = "javax.xml.datatype.Duration";
- public final static String XMLGREGORIANCALENDAR = "javax.xml.datatype.XMLGregorianCalendar";
- public final static String URI = "java.net.URI";
- public final static String URL = "java.net.URL";
- protected final static String JAVA_PKG = "java.";
- protected final static String JAVAX_PKG = "javax.";
- protected final static String JAKARTA_PKG = "jakarta.";
- protected final static String JAVAX_WS_PKG = "javax.xml.ws.";
- protected final static String JAKARTA_WS_PKG = "jakarta.xml.ws.";
- protected final static String JAVAX_RPC_PKG = "javax.xml.rpc.";
- protected final static String JAKARTA_RPC_PKG = "jakarta.xml.rpc.";
-
- private JavaClass collectionClass;
- private JavaClass setClass;
- private JavaClass listClass;
- private JavaClass mapClass;
- private JavaClass jaxbElementClass;
- private JavaClass objectClass;
-
- /**
- * INTERNAL:
- * This is the preferred constructor.
- *
- * This constructor builds the map of XML-Java type pairs,
- * and sets the JavaModel and ClassLoader.
- *
- * @param model
- */
- public Helper(JavaModel model) {
- xmlToJavaTypeMap = buildXMLToJavaTypeMap();
- setJavaModel(model);
- setClassLoader(model.getClassLoader());
- collectionClass = getJavaClass(CoreClassConstants.Collection_Class);
- listClass = getJavaClass(CoreClassConstants.List_Class);
- setClass = getJavaClass(CoreClassConstants.Set_Class);
- mapClass = getJavaClass(CoreClassConstants.Map_Class);
- jaxbElementClass = getJavaClass(JAXBElement.class);
- objectClass = getJavaClass(CoreClassConstants.OBJECT);
- }
-
- /**
- * Builds a map of Java types to XML types.
- *
- * @return
- */
- private HashMap buildXMLToJavaTypeMap() {
- HashMap javaTypes = new HashMap();
- // jaxb 2.0 spec pairs
- javaTypes.put(APBYTE, Constants.BASE_64_BINARY_QNAME);
- javaTypes.put(BIGDECIMAL, Constants.DECIMAL_QNAME);
- javaTypes.put(BIGINTEGER, Constants.INTEGER_QNAME);
- javaTypes.put(PBOOLEAN, Constants.BOOLEAN_QNAME);
- javaTypes.put(PBYTE, Constants.BYTE_QNAME);
- javaTypes.put(CALENDAR, Constants.DATE_TIME_QNAME);
- javaTypes.put(PDOUBLE, Constants.DOUBLE_QNAME);
- javaTypes.put(PFLOAT, Constants.FLOAT_QNAME);
- javaTypes.put(PINT, Constants.INT_QNAME);
- javaTypes.put(PLONG, Constants.LONG_QNAME);
- javaTypes.put(PSHORT, Constants.SHORT_QNAME);
- javaTypes.put(QNAME_CLASS, Constants.QNAME_QNAME);
- javaTypes.put(STRING, Constants.STRING_QNAME);
- javaTypes.put(CHAR, Constants.STRING_QNAME);
- javaTypes.put(CHARACTER, Constants.STRING_QNAME);
- // other pairs
- javaTypes.put(ABYTE, Constants.BYTE_QNAME);
- javaTypes.put(BOOLEAN, Constants.BOOLEAN_QNAME);
- javaTypes.put(BYTE, Constants.BYTE_QNAME);
- javaTypes.put(CLASS, Constants.STRING_QNAME);
- javaTypes.put(GREGORIAN_CALENDAR, Constants.DATE_TIME_QNAME);
- javaTypes.put(DOUBLE, Constants.DOUBLE_QNAME);
- javaTypes.put(FLOAT, Constants.FLOAT_QNAME);
- javaTypes.put(INTEGER, Constants.INT_QNAME);
- javaTypes.put(LONG, Constants.LONG_QNAME);
- javaTypes.put(OBJECT, Constants.ANY_TYPE_QNAME);
- javaTypes.put(SHORT, Constants.SHORT_QNAME);
- javaTypes.put(UTIL_DATE, Constants.DATE_TIME_QNAME);
- javaTypes.put(SQL_DATE, Constants.DATE_QNAME);
- javaTypes.put(SQL_TIME, Constants.TIME_QNAME);
- javaTypes.put(SQL_TIMESTAMP, Constants.DATE_TIME_QNAME);
- javaTypes.put(DURATION, Constants.DURATION_QNAME);
- javaTypes.put(UUID, Constants.STRING_QNAME);
- javaTypes.put(URI, Constants.STRING_QNAME);
- javaTypes.put(URL, Constants.ANY_URI_QNAME);
- return javaTypes;
- }
-
- /**
- * Return a given method's generic return type as a JavaClass.
- *
- * @param meth
- * @return
- */
- public JavaClass getGenericReturnType(JavaMethod meth) {
- JavaClass result = meth.getReturnType();
- JavaClass jClass = null;
- if (result == null) { return null; }
-
- Collection args = result.getActualTypeArguments();
- if (args.size() >0) {
- jClass = (JavaClass) args.iterator().next();
- }
- return jClass;
- }
-
- /**
- * Return a JavaClass instance created based the provided class.
- * This assumes that the provided class exists on the classpath
- * - null is returned otherwise.
- *
- * @param javaClass
- * @return
- */
- public JavaClass getJavaClass(Class javaClass) {
- return jModel.getClass(javaClass);
- }
-
- /**
- * Return array of JavaClass instances created based on the provided classes.
- * This assumes provided classes exist on the classpath.
- *
- * @param classes
- * @return JavaClass array
- */
- public JavaClass[] getJavaClassArray(Class... classes) {
- if (0 == classes.length) {
- return new JavaClass[0];
- }
- JavaClass[] result = new JavaClass[classes.length];
- int i = 0;
- for (Class clazz : classes) {
- result[i++] = getJavaClass(clazz);
- }
- return result;
- }
-
- /**
- * Return a JavaClass instance created based on fully qualified
- * class name. This assumes that a class with the provided name
- * exists on the classpath - null is returned otherwise.
- *
- * @param javaClassName
- * @return
- */
- public JavaClass getJavaClass(String javaClassName) {
- return jModel.getClass(javaClassName);
- }
-
- /**
- * Return a map of default Java types to XML types.
- * @return
- */
- public HashMap getXMLToJavaTypeMap() {
- return xmlToJavaTypeMap;
- }
-
- /**
- * Returns a either a dynamic proxy instance that allows an element
- * to be treated as an annotation (for JOT), or a Java annotation
- * (for Reflection), or null if the specified annotation does not
- * exist.
- * Intended to be used in conjunction with isAnnotationPresent.
- *
- * @param element
- * @param annotationClass
- * @return
- * @see #isAnnotationPresent
- */
- public Annotation getAnnotation(JavaHasAnnotations element, Class annotationClass) {
- JavaAnnotation janno = element.getAnnotation(jModel.getClass(annotationClass));
- if (janno == null) {
- return null;
- }
- return jModel.getAnnotation(janno, annotationClass);
- }
-
- /**
- * Returns a JavaClass instance wrapping the provided field's resolved
- * type.
- *
- * @param field
- * @return
- */
- public JavaClass getType(JavaField field) {
- JavaClass type = field.getResolvedType();
- try {
- return jModel.getClass(type.getRawName());
- } catch (Exception x) {}
- return null;
- }
-
- /**
- * Return a JavaClass instance based on the @see jakarta.xml.bind.JAXBElement .
- *
- * Replacement of direct access to JAXBELEMENT_CLASS field.
- *
- * @return
- */
- public JavaClass getJaxbElementClass() {
- return jaxbElementClass;
- }
-
- /**
- * Return a JavaClass instance based on the @see java.lang.Object .
- *
- * Replacement of direct access to OBJECT_CLASS field.
- *
- * @return
- */
- public JavaClass getObjectClass() {
- return objectClass;
- }
-
- /**
- * Indicates if element contains a given annotation.
- *
- * @param element
- * @param annotationClass
- * @return
- */
- public boolean isAnnotationPresent(JavaHasAnnotations element, Class annotationClass) {
- if (element == null || annotationClass == null) {
- return false;
- }
- return (element.getAnnotation(jModel.getClass(annotationClass)) != null);
- }
-
- /**
- * Indicates if a given JavaClass is a built-in Java type.
- *
- * A JavaClass is considered to be a built-in type if:
- * 1 - the XMLToJavaTypeMap map contains a key equal to the provided
- * JavaClass' raw name
- * 2 - the provided JavaClass' raw name starts with "java."
- * 3 - the provided JavaClass' raw name starts with "javax.", with
- * the exception of "jakarta.xml.ws." and "javax.xml.rpc"
- * @param jClass
- * @return
- */
- public boolean isBuiltInJavaType(JavaClass jClass) {
- String rawName = jClass.getRawName();
- if(null == rawName) {
- return true;
- }
- return (getXMLToJavaTypeMap().containsKey(rawName) || rawName.startsWith(JAVA_PKG) || ((rawName.startsWith(JAVAX_PKG) || rawName.startsWith(JAKARTA_PKG)) && !(
- rawName.startsWith(JAVAX_WS_PKG) ||
- rawName.startsWith(JAVAX_RPC_PKG) ||
- rawName.startsWith(JAKARTA_WS_PKG) ||
- rawName.startsWith(JAKARTA_RPC_PKG)
- )));
- }
-
- public void setClassLoader(ClassLoader loader) {
- this.loader = loader;
- }
-
- public void setJavaModel(JavaModel model) {
- jModel = model;
- }
- public ClassLoader getClassLoader() {
- return loader;
- }
-
- public Class getClassForJavaClass(JavaClass javaClass){
- String javaClassName = javaClass.getRawName();
- if (javaClass.isPrimitive() || javaClass.isArray() && javaClass.getComponentType().isPrimitive()){
- if (CoreClassConstants.APBYTE.getCanonicalName().equals(javaClassName)){
- return Byte[].class;
- }
- if (CoreClassConstants.PBYTE.getCanonicalName().equals(javaClassName)){
- return Byte.class;
- }
- if (CoreClassConstants.PBOOLEAN.getCanonicalName().equals(javaClassName)){
- return Boolean.class;
- }
- if (CoreClassConstants.PSHORT.getCanonicalName().equals(javaClassName)){
- return Short.class;
- }
- if (CoreClassConstants.PFLOAT.getCanonicalName().equals(javaClassName)){
- return Float.class;
- }
- if (CoreClassConstants.PCHAR.getCanonicalName().equals(javaClassName)){
- return Character.class;
- }
- if (CoreClassConstants.PDOUBLE.getCanonicalName().equals(javaClassName)){
- return Double.class;
- }
- if (CoreClassConstants.PINT.getCanonicalName().equals(javaClassName)){
- return Integer.class;
- }
- if (CoreClassConstants.PLONG.getCanonicalName().equals(javaClassName)){
- return Long.class;
- }
- return null;
- }
- return org.eclipse.persistence.internal.helper.Helper.getClassFromClasseName(javaClass.getQualifiedName(), loader);
- }
-
- /**
- * Convenience method to determine if a class exists in a given ArrayList.
- */
- public boolean classExistsInArray(JavaClass theClass, List<JavaClass> existingClasses) {
- for (JavaClass jClass : existingClasses) {
- if (areClassesEqual(jClass, theClass)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Convenience method to determine if two JavaClass instances are equal.
- *
- * @param classA
- * @param classB
- * @return
- */
- private boolean areClassesEqual(JavaClass classA, JavaClass classB) {
- if (classA == classB) {
- return true;
- }
- if (!(classA.getQualifiedName().equals(classB.getQualifiedName()))) {
- return false;
- }
-
- Collection classAargs = classA.getActualTypeArguments();
- Collection classBargs = classB.getActualTypeArguments();
- if (classAargs != null) {
- if (classBargs == null) {
- return false;
- }
- if (classAargs.size() != classBargs.size()) {
- return false;
- }
-
- Iterator classAargsIter = classAargs.iterator();
- Iterator classBargsIter = classBargs.iterator();
-
- while(classAargsIter.hasNext()){
- JavaClass nestedClassA = (JavaClass) classAargsIter.next();
- JavaClass nestedClassB = (JavaClass) classBargsIter.next();
- if (!areClassesEqual(nestedClassA, nestedClassB)) {
- return false;
- }
- }
- return true;
- }
- if (classBargs == null) {
- return true;
- }
- return false;
- }
-
-
- /**
- * Prepends a package name to a given java type name, if it is not already present.
- *
- * @param javaTypeName Java type name that may/may not contain 'packageName'
- * @param packageName package name to prepend to javaTypeName if not already
- * @return fully qualified java type name
- */
- public static String getQualifiedJavaTypeName(String javaTypeName, String packageName) {
- // prepend the package name if not already present
- if (packageName != null && packageName.length() > 0 && !packageName.equals(DEFAULT) && !javaTypeName.contains(PKG_SEPARATOR)) {
- return packageName + PKG_SEPARATOR + javaTypeName;
- }
- return javaTypeName;
- }
-
- public boolean isCollectionType(JavaClass type) {
- if (collectionClass.isAssignableFrom(type)
- || listClass.isAssignableFrom(type)
- || setClass.isAssignableFrom(type)) {
- return true;
- }
- return false;
- }
-
- public boolean isMapType(JavaClass type) {
- return mapClass.isAssignableFrom(type);
- }
-
- public boolean isFacets() {
- return facets;
- }
-
- public void setFacets(boolean facets) {
- this.facets = facets;
- }
-}
\ No newline at end of file
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/javamodel/reflection/JavaClassImpl.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/javamodel/reflection/JavaClassImpl.java
deleted file mode 100644
index a1c74ba..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/javamodel/reflection/JavaClassImpl.java
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- * 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:
- * <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 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;
- }
- 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<JavaAnnotation> getAnnotations() {
- List<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<JavaClass> getDeclaredClasses() {
- List<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<JavaField> getDeclaredFields() {
- List<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.")
- || 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();
- }
-
- 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;
- return jClass.getSuperClassOverride() != null || 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() {
- List<JavaAnnotation> annotationCollection = new ArrayList<JavaAnnotation>();
- if (!isMetadataComplete) {
- Annotation[] annotations = javaModelImpl.getAnnotationHelper().getDeclaredAnnotations(getAnnotatedElement());
- for (Annotation annotation : annotations) {
- annotationCollection.add(new JavaAnnotationImpl(annotation));
- }
- }
- return annotationCollection;
- }
-
-}
\ No newline at end of file
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/rs/MOXyJsonProvider.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/rs/MOXyJsonProvider.java
deleted file mode 100644
index 7bce14a..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jaxb/rs/MOXyJsonProvider.java
+++ /dev/null
@@ -1,986 +0,0 @@
-/*
- * Copyright (c) 2012, 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:
-// Blaise Doughan - 2.4 - initial implementation
-package org.eclipse.persistence.jaxb.rs;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.lang.reflect.WildcardType;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableSet;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import jakarta.activation.DataSource;
-import jakarta.ws.rs.Consumes;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.WebApplicationException;
-import jakarta.ws.rs.core.Context;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Response.ResponseBuilder;
-import jakarta.ws.rs.core.Response.Status;
-import jakarta.ws.rs.core.StreamingOutput;
-import jakarta.ws.rs.ext.ContextResolver;
-import jakarta.ws.rs.ext.MessageBodyReader;
-import jakarta.ws.rs.ext.MessageBodyWriter;
-import jakarta.ws.rs.ext.Provider;
-import jakarta.ws.rs.ext.Providers;
-import jakarta.xml.bind.JAXBContext;
-import jakarta.xml.bind.JAXBElement;
-import jakarta.xml.bind.JAXBException;
-import jakarta.xml.bind.JAXBIntrospector;
-import jakarta.xml.bind.Marshaller;
-import jakarta.xml.bind.UnmarshalException;
-import jakarta.xml.bind.Unmarshaller;
-import javax.xml.namespace.QName;
-import javax.xml.transform.stream.StreamSource;
-
-import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
-import org.eclipse.persistence.internal.helper.Helper;
-import org.eclipse.persistence.internal.oxm.Constants;
-import org.eclipse.persistence.internal.queries.CollectionContainerPolicy;
-import org.eclipse.persistence.internal.queries.ContainerPolicy;
-import org.eclipse.persistence.jaxb.JAXBContextFactory;
-import org.eclipse.persistence.jaxb.MarshallerProperties;
-import org.eclipse.persistence.jaxb.UnmarshallerProperties;
-import org.eclipse.persistence.logging.AbstractSessionLog;
-import org.eclipse.persistence.logging.SessionLog;
-import org.eclipse.persistence.oxm.JSONWithPadding;
-
-/**
- * <p>This is an implementation of <i>MessageBodyReader</i>/<i>MessageBodyWriter
- * </i> that can be used to enable EclipseLink JAXB (MOXy) as the JSON
- * provider.</p>
- * <p>
- * <b>Supported Media Type Patterns</b>
- * <ul>
- * <li>*/json (i.e. application/json and text/json)</li>
- * <li>*/*+json</li>
- * </ul>
- *
- * <p>Below are some different usage options.</p>
- *
- * <b>Option #1 - <i>MOXyJsonProvider</i> Default Behavior</b>
- * <p>You can use the <i>Application</i> class to specify that
- * <i>MOXyJsonProvider</i> should be used with your JAX-RS application.</p>
- * <pre>
- * package org.example;
-
- * import java.util.*;
- * import javax.ws.rs.core.Application;
- * import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
- *
- * public class ExampleApplication extends Application {
- *
- * @Override
- * public Set<Class<?>> getClasses() {
- * HashSet<Class<?>> set = new HashSet<Class<?>>(2);
- * set.add(MOXyJsonProvider.class);
- * set.add(ExampleService.class);
- * return set;
- * }
- *
- * }
- * </pre>
- *
- * <b>Option #2 - Customize <i>MOXyJsonProvider</i></b>
- * <p>You can use the <i>Application</i> class to specify a configured instance
- * of <i>MOXyJsonProvider</i> should be used with your JAX-RS application.</p>
- * <pre>
- * package org.example;
- *
- * import java.util.*;
- * import javax.ws.rs.core.Application;
- * import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
- *
- * public class CustomerApplication extends Application {
- *
- * @Override
- * public Set<Class<?>> getClasses() {
- * HashSet<Class<?>> set = new HashSet<Class<?>>(1);
- * set.add(ExampleService.class);
- * return set;
- * }
-
- * @Override
- * public Set<Object> getSingletons() {
- * moxyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
- * moxyJsonProvider.setFormattedOutput(true);
- * moxyJsonProvider.setIncludeRoot(true);
- *
- * HashSet<Object> set = new HashSet<Object>(2);
- * set.add(moxyJsonProvider);
- * return set;
- * }
- *
- * }
- * </pre>
- * <b>Option #3 - Extend MOXyJsonProvider</b>
- * <p>You can use MOXyJsonProvider for creating your own
- * <i>MessageBodyReader</i>/<i>MessageBodyWriter</i>.</p>
- * <pre>
- * package org.example;
- *
- * import java.lang.annotation.Annotation;
- * import java.lang.reflect.Type;
- *
- * import javax.ws.rs.*;
- * import javax.ws.rs.core.*;
- * import javax.ws.rs.ext.Provider;
- * import javax.xml.bind.*;
- *
- * import org.eclipse.persistence.jaxb.MarshallerProperties;
- * import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
- *
- * @Provider
- * @Produces(MediaType.APPLICATION_JSON)
- * @Consumes(MediaType.APPLICATION_JSON)
- * public class CustomerJSONProvider extends MOXyJsonProvider {
-
- * @Override
- * public boolean isReadable(Class<?> type, Type genericType,
- * Annotation[] annotations, MediaType mediaType) {
- * return getDomainClass(genericType) == Customer.class;
- * }
- *
- * @Override
- * public boolean isWriteable(Class<?> type, Type genericType,
- * Annotation[] annotations, MediaType mediaType) {
- * return isReadable(type, genericType, annotations, mediaType);
- * }
- *
- * @Override
- * protected void preReadFrom(Class<Object> type, Type genericType,
- * Annotation[] annotations, MediaType mediaType,
- * MultivaluedMap<String, String> httpHeaders,
- * Unmarshaller unmarshaller) throws JAXBException {
- * unmarshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
- * }
- *
- * @Override
- * protected void preWriteTo(Object object, Class<?> type, Type genericType,
- * Annotation[] annotations, MediaType mediaType,
- * MultivaluedMap<String, Object> httpHeaders, Marshaller marshaller)
- * throws JAXBException {
- * marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
- * }
- *
- * }
- * </pre>
- * @since 2.4
- */
-@Produces({MediaType.APPLICATION_JSON, MediaType.WILDCARD, "application/x-javascript"})
-@Consumes({MediaType.APPLICATION_JSON, MediaType.WILDCARD})
-public class MOXyJsonProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object>{
-
- private static final String APPLICATION_XJAVASCRIPT = "application/x-javascript";
- private static final String CHARSET = "charset";
- private static final QName EMPTY_STRING_QNAME = new QName("");
- private static final String JSON = "json";
- private static final String PLUS_JSON = "+json";
-
- @Context
- protected Providers providers;
-
- private String attributePrefix = null;
- private Map<Set<Class<?>>, JAXBContext> contextCache = new HashMap<Set<Class<?>>, JAXBContext>();
- private boolean formattedOutput = false;
- private boolean includeRoot = false;
- private boolean marshalEmptyCollections = true;
- private Map<String, String> namespacePrefixMapper;
- private char namespaceSeperator = Constants.DOT;
- private String valueWrapper;
- private boolean wrapperAsArrayName = false;
-
- /**
- * The value that will be prepended to all keys that are mapped to an XML
- * attribute. By default there is no attribute prefix.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_ATTRIBUTE_PREFIX
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_ATTRIBUTE_PREFIX
- */
- public String getAttributePrefix() {
- return attributePrefix;
- }
-
- /**
- * A convenience method to get the domain class (i.e. <i>Customer</i> or <i>Foo, Bar</i>) from
- * the parameter/return type (i.e. <i>Customer</i>, <i>List<Customer></i>,
- * <i>JAXBElement<Customer></i>, <i>JAXBElement<? extends Customer></i>,
- * <i>List<JAXBElement<Customer>></i>, or
- * <i>List<JAXBElement<? extends Customer>></i>
- * <i>List<Foo<Bar>></i>).
- * @param genericType - The parameter/return type of the JAX-RS operation.
- * @return The corresponding domain classes.
- */
- protected Set<Class<?>> getDomainClasses(Type genericType) {
- if(null == genericType) {
- return asSet(Object.class);
- }
- if(genericType instanceof Class && genericType != JAXBElement.class) {
- Class<?> clazz = (Class<?>) genericType;
- if(clazz.isArray()) {
- return getDomainClasses(clazz.getComponentType());
- }
- return asSet(clazz);
- } else if(genericType instanceof ParameterizedType) {
- Set<Class<?>> result = new LinkedHashSet<Class<?>>();
- result.add((Class<?>)((ParameterizedType) genericType).getRawType());
- Type[] types = ((ParameterizedType) genericType).getActualTypeArguments();
- if(types.length > 0){
- for (Type upperType : types) {
- result.addAll(getDomainClasses(upperType));
- }
- }
- return result;
- } else if (genericType instanceof GenericArrayType) {
- GenericArrayType genericArrayType = (GenericArrayType) genericType;
- return getDomainClasses(genericArrayType.getGenericComponentType());
- } else if(genericType instanceof WildcardType) {
- Set<Class<?>> result = new LinkedHashSet<Class<?>>();
- Type[] upperTypes = ((WildcardType)genericType).getUpperBounds();
- if(upperTypes.length > 0){
- for (Type upperType : upperTypes) {
- result.addAll(getDomainClasses(upperType));
- }
- } else {
- result.add(Object.class);
- }
- return result;
- } else {
- return asSet(Object.class);
- }
- }
-
- private Set<Class<?>> asSet(Class<?> clazz) {
- Set<Class<?>> result = new LinkedHashSet<>();
- result.add(clazz);
- return result;
- }
-
- /**
- * Return the <i>JAXBContext</i> that corresponds to the domain class. This
- * method does the following:
- * <ol>
- * <li>If an EclipseLink JAXB (MOXy) <i>JAXBContext</i> is available from
- * a <i>ContextResolver</i> then use it.</li>
- * <li>If an existing <i>JAXBContext</i> was not found in step one, then
- * create a new one on the domain class.</li>
- * </ol>
- * @param domainClasses - The domain classes we need a <i>JAXBContext</i> for.
- * @param annotations - The annotations corresponding to domain object.
- * @param mediaType - The media type for the HTTP entity.
- * @param httpHeaders - HTTP headers associated with HTTP entity.
- * @return
- * @throws JAXBException
- */
- protected JAXBContext getJAXBContext(Set<Class<?>> domainClasses, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, ?> httpHeaders) throws JAXBException {
-
- JAXBContext jaxbContext = contextCache.get(domainClasses);
- if(null != jaxbContext) {
- return jaxbContext;
- }
-
- synchronized (contextCache) {
- jaxbContext = contextCache.get(domainClasses);
- if(null != jaxbContext) {
- return jaxbContext;
- }
-
- ContextResolver<JAXBContext> resolver = null;
- if(null != providers) {
- resolver = providers.getContextResolver(JAXBContext.class, mediaType);
- }
-
- if (null != resolver && domainClasses.size() == 1) {
- jaxbContext = resolver.getContext(domainClasses.iterator().next());
- }
-
- if(null == jaxbContext) {
- jaxbContext = JAXBContextFactory.createContext(domainClasses.toArray(new Class[0]), null);
- contextCache.put(domainClasses, jaxbContext);
- return jaxbContext;
- } else if (jaxbContext instanceof org.eclipse.persistence.jaxb.JAXBContext) {
- return jaxbContext;
- } else {
- jaxbContext = JAXBContextFactory.createContext(domainClasses.toArray(new Class[0]), null);
- contextCache.put(domainClasses, jaxbContext);
- return jaxbContext;
- }
- }
- }
-
- private JAXBContext getJAXBContext(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- if(null == genericType) {
- genericType = type;
- }
-
- try {
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
- return getJAXBContext(domainClasses, annotations, mediaType, null);
- } catch(JAXBException e) {
- AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, SessionLog.MOXY, e);
- return null;
- }
- }
-
- /**
- * By default the JSON-binding will ignore namespace qualification. If this
- * property is set the portion of the key before the namespace separator
- * will be used to determine the namespace URI.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#NAMESPACE_PREFIX_MAPPER
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_PREFIX_MAPPER
- */
- public Map<String, String> getNamespacePrefixMapper() {
- return namespacePrefixMapper;
- }
-
- /**
- * This character (default is '.') separates the prefix from the key name.
- * It is only used if namespace qualification has been enabled be setting a
- * namespace prefix mapper.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_NAMESPACE_SEPARATOR
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_SEPARATOR
- */
- public char getNamespaceSeparator() {
- return this.namespaceSeperator;
- }
-
- /*
- * @return -1 since the size of the JSON message is not known.
- * @see javax.ws.rs.ext.MessageBodyWriter#getSize(java.lang.Object, java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], javax.ws.rs.core.MediaType)
- */
- @Override
- public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- return -1;
- }
-
- /**
- * The key that will correspond to the property mapped with @XmlValue. This
- * key will only be used if there are other mapped properties.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_VALUE_WRAPPER
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_VALUE_WRAPPER
- */
- public String getValueWrapper() {
- return valueWrapper;
- }
-
- /**
- * @return true if the JSON output should be formatted (default is false).
- */
- public boolean isFormattedOutput() {
- return formattedOutput;
- }
-
- /**
- * @return true if the root node is included in the JSON message (default is
- * false).
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_INCLUDE_ROOT
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_INCLUDE_ROOT
- */
- public boolean isIncludeRoot() {
- return includeRoot;
- }
-
- /**
- * If true empty collections will be marshalled as empty arrays, else the
- * collection will not be marshalled to JSON (default is true).
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_MARSHAL_EMPTY_COLLECTIONS
- */
- public boolean isMarshalEmptyCollections() {
- return marshalEmptyCollections;
- }
-
- /**
- * @return true indicating that <i>MOXyJsonProvider</i> will
- * be used for the JSON binding if the media type is of the following
- * patterns */json or */*+json, and the type is not assignable from
- * any of (or a Collection or JAXBElement of) the following:
- * <ul>
- * <li>byte[]</li>
- * <li>java.io.File</li>
- * <li>java.io.InputStream</li>
- * <li>java.io.Reader</li>
- * <li>java.lang.Object</li>
- * <li>java.lang.String</li>
- * <li>javax.activation.DataSource</li>
- * </ul>
- */
- @Override
- public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- if(!supportsMediaType(mediaType)) {
- return false;
- } else if(CoreClassConstants.APBYTE == type || CoreClassConstants.STRING == type) {
- return false;
- } else if(Map.class.isAssignableFrom(type)) {
- return false;
- } else if(File.class.isAssignableFrom(type)) {
- return false;
- } else if(DataSource.class.isAssignableFrom(type)) {
- return false;
- } else if(InputStream.class.isAssignableFrom(type)) {
- return false;
- } else if(Reader.class.isAssignableFrom(type)) {
- return false;
- } else if(Object.class == type) {
- return false;
- } else if(type.isPrimitive()) {
- return false;
- } else if(type.isArray() && (type.getComponentType().isArray() || type.getComponentType().isPrimitive() || type.getComponentType().getPackage().getName().startsWith("java."))) {
- return false;
- } else if(JAXBElement.class.isAssignableFrom(type)) {
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
- for (Class<?> domainClass : domainClasses) {
- if (isReadable(domainClass, null, annotations, mediaType) || String.class == domainClass) {
- return true;
- }
- }
- return false;
- } else if(Collection.class.isAssignableFrom(type)) {
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
- for (Class<?> domainClass : domainClasses) {
- if (isReadable(domainClass, null, annotations, mediaType) || String.class == domainClass) {
- return true;
- }
- }
- return false;
- } else {
- return null != getJAXBContext(type, genericType, annotations, mediaType);
- }
- }
-
- /**
- * If true the grouping element will be used as the JSON key.
- *
- * <p><b>Example</b></p>
- * <p>Given the following class:</p>
- * <pre>
- * @XmlAccessorType(XmlAccessType.FIELD)
- * public class Customer {
- *
- * @XmlElementWrapper(name="phone-numbers")
- * @XmlElement(name="phone-number")
- * private {@literal List<PhoneNumber>} phoneNumbers;
- *
- * }
- * </pre>
- * <p>If the property is set to false (the default) the JSON output will be:</p>
- * <pre>
- * {
- * "phone-numbers" : {
- * "phone-number" : [ {
- * ...
- * }, {
- * ...
- * }]
- * }
- * }
- * </pre>
- * <p>And if the property is set to true, then the JSON output will be:</p>
- * <pre>
- * {
- * "phone-numbers" : [ {
- * ...
- * }, {
- * ...
- * }]
- * }
- * </pre>
- * @since 2.4.2
- * @see org.eclipse.persistence.jaxb.JAXBContextProperties#JSON_WRAPPER_AS_ARRAY_NAME
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
- */
- public boolean isWrapperAsArrayName() {
- return wrapperAsArrayName;
- }
-
- /**
- * @return true indicating that <i>MOXyJsonProvider</i> will
- * be used for the JSON binding if the media type is of the following
- * patterns */json or */*+json, and the type is not assignable from
- * any of (or a Collection or JAXBElement of) the following:
- * <ul>
- * <li>byte[]</li>
- * <li>java.io.File</li>
- * <li>java.lang.Object</li>
- * <li>java.lang.String</li>
- * <li>jakarta.activation.DataSource</li>
- * <li>jakarta.ws.rs.core.StreamingOutput</li>
- * </ul>
- */
- @Override
- public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- if(type == JSONWithPadding.class && APPLICATION_XJAVASCRIPT.equals(mediaType.toString())) {
- return true;
- }
- if(!supportsMediaType(mediaType)) {
- return false;
- } else if(CoreClassConstants.APBYTE == type || CoreClassConstants.STRING == type || type.isPrimitive()) {
- return false;
- } else if(Map.class.isAssignableFrom(type)) {
- return false;
- } else if(File.class.isAssignableFrom(type)) {
- return false;
- } else if(DataSource.class.isAssignableFrom(type)) {
- return false;
- } else if(StreamingOutput.class.isAssignableFrom(type)) {
- return false;
- } else if(Object.class == type) {
- return false;
- } else if(type.isPrimitive()) {
- return false;
- } else if(type.isArray() && (String.class.equals(type.getComponentType()) || type.getComponentType().isPrimitive() || Helper.isPrimitiveWrapper(type.getComponentType()))) {
- return true;
- } else if(type.isArray() && (type.getComponentType().isArray() || type.getComponentType().isPrimitive() || type.getComponentType().getPackage().getName().startsWith("java."))) {
- return false;
- } else if(JAXBElement.class.isAssignableFrom(type)) {
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
-
- for (Class<?> domainClass : domainClasses) {
- if (isWriteable(domainClass, null, annotations, mediaType) || domainClass == String.class) {
- return true;
- }
- }
-
- return false;
- } else if(Collection.class.isAssignableFrom(type)) {
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
-
- //special case for List<JAXBElement<String>>
- //this is quick fix, MOXyJsonProvider should be refactored as stated in issue #459541
- if (domainClasses.size() == 3) {
- Class[] domainArray = domainClasses.toArray(new Class[domainClasses.size()]);
- if (JAXBElement.class.isAssignableFrom(domainArray[1]) && String.class == domainArray[2]) {
- return true;
- }
- }
-
- for (Class<?> domainClass : domainClasses) {
-
- if (String.class.equals(domainClass) || domainClass.isPrimitive() || Helper.isPrimitiveWrapper(domainClass)) {
- return true;
- }
-
- String packageName = domainClass.getPackage().getName();
- if(null == packageName || !packageName.startsWith("java.")) {
- if (isWriteable(domainClass, null, annotations, mediaType)) {
- return true;
- }
- }
- }
- return false;
- } else {
- return null != getJAXBContext(type, genericType, annotations, mediaType);
- }
- }
-
- /**
- * Subclasses of <i>MOXyJsonProvider</i> can override this method to
- * customize the instance of <i>Unmarshaller</i> that will be used to
- * unmarshal the JSON message in the readFrom call.
- * @param type - The Class to be unmarshalled (i.e. <i>Customer</i> or
- * <i>List</i>)
- * @param genericType - The type of object to be unmarshalled (i.e
- * <i>Customer</i> or <i>List<Customer></i>).
- * @param annotations - The annotations corresponding to domain object.
- * @param mediaType - The media type for the HTTP entity.
- * @param httpHeaders - HTTP headers associated with HTTP entity.
- * @param unmarshaller - The instance of <i>Unmarshaller</i> that will be
- * used to unmarshal the JSON message.
- * @throws JAXBException
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties
- */
- protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, Unmarshaller unmarshaller) throws JAXBException {
- }
-
- /**
- * Subclasses of <i>MOXyJsonProvider</i> can override this method to
- * customize the instance of <i>Marshaller</i> that will be used to marshal
- * the domain objects to JSON in the writeTo call.
- * @param object - The domain object that will be marshalled to JSON.
- * @param type - The Class to be marshalled (i.e. <i>Customer</i> or
- * <i>List</i>)
- * @param genericType - The type of object to be marshalled (i.e
- * <i>Customer</i> or <i>List<Customer></i>).
- * @param annotations - The annotations corresponding to domain object.
- * @param mediaType - The media type for the HTTP entity.
- * @param httpHeaders - HTTP headers associated with HTTP entity.
- * @param marshaller - The instance of <i>Marshaller</i> that will be used
- * to marshal the domain object to JSON.
- * @throws JAXBException
- * @see org.eclipse.persistence.jaxb.MarshallerProperties
- */
- protected void preWriteTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, Marshaller marshaller) throws JAXBException {
- }
-
- /*
- * @see javax.ws.rs.ext.MessageBodyReader#readFrom(java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], javax.ws.rs.core.MediaType, javax.ws.rs.core.MultivaluedMap, java.io.InputStream)
- */
- @Override
- public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
- try {
- if(null == genericType) {
- genericType = type;
- }
-
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
- JAXBContext jaxbContext = getJAXBContext(domainClasses, annotations, mediaType, httpHeaders);
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
- unmarshaller.setProperty(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX, attributePrefix);
- unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);
- unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER, namespacePrefixMapper);
- unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_SEPARATOR, namespaceSeperator);
- if(null != valueWrapper) {
- unmarshaller.setProperty(UnmarshallerProperties.JSON_VALUE_WRAPPER, valueWrapper);
- }
- unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, wrapperAsArrayName);
- preReadFrom(type, genericType, annotations, mediaType, httpHeaders, unmarshaller);
-
- StreamSource jsonSource;
- Map<String, String> mediaTypeParameters = null;
- if(null != mediaType) {
- mediaTypeParameters = mediaType.getParameters();
- }
- if(null != mediaTypeParameters && mediaTypeParameters.containsKey(CHARSET)) {
- String charSet = mediaTypeParameters.get(CHARSET);
- Reader entityReader = new InputStreamReader(entityStream, charSet);
- jsonSource = new StreamSource(entityReader);
- } else {
- jsonSource = new StreamSource(entityStream);
- }
-
- Class<?> domainClass = getDomainClass(domainClasses);
- JAXBElement<?> jaxbElement = unmarshaller.unmarshal(jsonSource, domainClass);
- if(type.isAssignableFrom(JAXBElement.class)) {
- return jaxbElement;
- } else {
- Object value = jaxbElement.getValue();
- if(value instanceof ArrayList) {
- if(type.isArray()) {
- ArrayList<Object> arrayList = (ArrayList<Object>) value;
- int arrayListSize = arrayList.size();
- boolean wrapItemInJAXBElement = wrapItemInJAXBElement(genericType);
- Object array;
- if(wrapItemInJAXBElement) {
- array = Array.newInstance(JAXBElement.class, arrayListSize);
- } else {
- array = Array.newInstance(domainClass, arrayListSize);
- }
- for(int x=0; x<arrayListSize; x++) {
- Object element = handleJAXBElement(arrayList.get(x), domainClass, wrapItemInJAXBElement);
- Array.set(array, x, element);
- }
- return array;
- } else {
- ContainerPolicy containerPolicy;
- if(type.isAssignableFrom(List.class) || type.isAssignableFrom(ArrayList.class) || type.isAssignableFrom(Collection.class)) {
- containerPolicy = new CollectionContainerPolicy(ArrayList.class);
- } else if(type.isAssignableFrom(Set.class)) {
- containerPolicy = new CollectionContainerPolicy(HashSet.class);
- } else if(type.isAssignableFrom(Deque.class) || type.isAssignableFrom(Queue.class)) {
- containerPolicy = new CollectionContainerPolicy(LinkedList.class);
- } else if(type.isAssignableFrom(NavigableSet.class) || type.isAssignableFrom(SortedSet.class)) {
- containerPolicy = new CollectionContainerPolicy(TreeSet.class);
- } else {
- containerPolicy = new CollectionContainerPolicy(type);
- }
- Object container = containerPolicy.containerInstance();
- boolean wrapItemInJAXBElement = wrapItemInJAXBElement(genericType);
- for(Object element : (Collection<Object>) value) {
- element = handleJAXBElement(element, domainClass, wrapItemInJAXBElement);
- containerPolicy.addInto(element, container, null);
- }
- return container;
- }
- } else {
- return value;
- }
- }
- } catch(UnmarshalException unmarshalException) {
- ResponseBuilder builder = Response.status(Status.BAD_REQUEST);
- throw new WebApplicationException(unmarshalException, builder.build());
- } catch(JAXBException jaxbException) {
- throw new WebApplicationException(jaxbException);
- }
- }
-
- /**
- * Get first non java class if exists.
- *
- * @param domainClasses
- * @return first domain class or first generic class or just the first class from the list
- */
- public Class<?> getDomainClass(Set<Class<?>> domainClasses) {
-
- if (domainClasses.size() == 1) {
- return domainClasses.iterator().next();
- }
-
- boolean isStringPresent = false;
-
- for (Class<?> clazz : domainClasses) {
- if (!clazz.getName().startsWith("java.")
- && !clazz.getName().startsWith("javax.")
- && !clazz.getName().startsWith("jakarta.")
- && !java.util.List.class.isAssignableFrom(clazz)) {
- return clazz;
- } else if (clazz == String.class) {
- isStringPresent = true;
- }
- }
-
- if (isStringPresent) {
- return String.class;
- }
-
- //handle simple generic case
- if (domainClasses.size() >= 2) {
- Iterator<Class<?>> it = domainClasses.iterator();
- it.next();
- return it.next();
- }
-
- return domainClasses.iterator().next();
- }
-
- private boolean wrapItemInJAXBElement(Type genericType) {
- if(genericType == JAXBElement.class) {
- return true;
- } else if(genericType instanceof GenericArrayType) {
- return wrapItemInJAXBElement(((GenericArrayType) genericType).getGenericComponentType());
- } else if(genericType instanceof ParameterizedType) {
- ParameterizedType parameterizedType = (ParameterizedType) genericType;
- Type actualType = parameterizedType.getActualTypeArguments()[0];
- return wrapItemInJAXBElement(parameterizedType.getOwnerType()) || wrapItemInJAXBElement(parameterizedType.getRawType()) || wrapItemInJAXBElement(actualType);
- } else {
- return false;
- }
- }
-
- private Object handleJAXBElement(Object element, Class domainClass, boolean wrapItemInJAXBElement) {
- if(wrapItemInJAXBElement) {
- if(element instanceof JAXBElement) {
- return element;
- } else {
- return new JAXBElement(EMPTY_STRING_QNAME, domainClass, element);
- }
- } else {
- return JAXBIntrospector.getValue(element);
- }
- }
-
- /**
- * Specify a value that will be prepended to all keys that are mapped to an
- * XML attribute. By default there is no attribute prefix.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_ATTRIBUTE_PREFIX
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_ATTRIBUTE_PREFIX
- */
- public void setAttributePrefix(String attributePrefix) {
- this.attributePrefix = attributePrefix;
- }
-
- /**
- * Specify if the JSON output should be formatted (default is false).
- * @param formattedOutput - true if the output should be formatted, else
- * false.
- */
- public void setFormattedOutput(boolean formattedOutput) {
- this.formattedOutput = formattedOutput;
- }
-
- /**
- * Specify if the root node should be included in the JSON message (default
- * is false).
- * @param includeRoot - true if the message includes the root node, else
- * false.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_INCLUDE_ROOT
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_INCLUDE_ROOT
- */
- public void setIncludeRoot(boolean includeRoot) {
- this.includeRoot = includeRoot;
- }
-
- /**
- * If true empty collections will be marshalled as empty arrays, else the
- * collection will not be marshalled to JSON (default is true).
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_MARSHAL_EMPTY_COLLECTIONS
- */
- public void setMarshalEmptyCollections(boolean marshalEmptyCollections) {
- this.marshalEmptyCollections = marshalEmptyCollections;
- }
-
- /**
- * By default the JSON-binding will ignore namespace qualification. If this
- * property is set then a prefix corresponding to the namespace URI and a
- * namespace separator will be prefixed to the key.
- * include it you can specify a Map of namespace URI to prefix.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#NAMESPACE_PREFIX_MAPPER
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_PREFIX_MAPPER
- */
- public void setNamespacePrefixMapper(Map<String, String> namespacePrefixMapper) {
- this.namespacePrefixMapper = namespacePrefixMapper;
- }
-
- /**
- * This character (default is '.') separates the prefix from the key name.
- * It is only used if namespace qualification has been enabled be setting a
- * namespace prefix mapper.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_NAMESPACE_SEPARATOR
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_SEPARATOR
- */
- public void setNamespaceSeparator(char namespaceSeparator) {
- this.namespaceSeperator = namespaceSeparator;
- }
-
- /**
- * If true the grouping element will be used as the JSON key.
- *
- * <p><b>Example</b></p>
- * <p>Given the following class:</p>
- * <pre>
- * @XmlAccessorType(XmlAccessType.FIELD)
- * public class Customer {
- *
- * @XmlElementWrapper(name="phone-numbers")
- * @XmlElement(name="phone-number")
- * private {@literal List<PhoneNumber>} phoneNumbers;
- *
- * }
- * </pre>
- * <p>If the property is set to false (the default) the JSON output will be:</p>
- * <pre>
- * {
- * "phone-numbers" : {
- * "phone-number" : [ {
- * ...
- * }, {
- * ...
- * }]
- * }
- * }
- * </pre>
- * <p>And if the property is set to true, then the JSON output will be:</p>
- * <pre>
- * {
- * "phone-numbers" : [ {
- * ...
- * }, {
- * ...
- * }]
- * }
- * </pre>
- * @since 2.4.2
- * @see org.eclipse.persistence.jaxb.JAXBContextProperties#JSON_WRAPPER_AS_ARRAY_NAME
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
- */
- public void setWrapperAsArrayName(boolean wrapperAsArrayName) {
- this.wrapperAsArrayName = wrapperAsArrayName;
- }
-
- /**
- * Specify the key that will correspond to the property mapped with
- * {@literal @XmlValue}. This key will only be used if there are other mapped
- * properties.
- * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_VALUE_WRAPPER
- * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_VALUE_WRAPPER
- */
- public void setValueWrapper(String valueWrapper) {
- this.valueWrapper = valueWrapper;
- }
-
- /**
- * @return true for all media types of the pattern */json and
- * */*+json.
- */
- protected boolean supportsMediaType(MediaType mediaType) {
- if(null == mediaType) {
- return true;
- }
- String subtype = mediaType.getSubtype();
- return subtype.equals(JSON) || subtype.endsWith(PLUS_JSON);
- }
-
- /**
- * @see javax.ws.rs.ext.MessageBodyWriter#writeTo(java.lang.Object, java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], javax.ws.rs.core.MediaType, javax.ws.rs.core.MultivaluedMap, java.io.OutputStream)
- */
- @Override
- public void writeTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
- try {
- if(null == genericType) {
- genericType = type;
- }
-
- Set<Class<?>> domainClasses = getDomainClasses(genericType);
- JAXBContext jaxbContext = getJAXBContext(domainClasses, annotations, mediaType, httpHeaders);
- Marshaller marshaller = jaxbContext.createMarshaller();
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formattedOutput);
- marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
- marshaller.setProperty(MarshallerProperties.JSON_ATTRIBUTE_PREFIX, attributePrefix);
- marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);
- marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, marshalEmptyCollections);
- marshaller.setProperty(MarshallerProperties.JSON_NAMESPACE_SEPARATOR, namespaceSeperator);
- if(null != valueWrapper) {
- marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, valueWrapper);
- }
- marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, wrapperAsArrayName);
- marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespacePrefixMapper);
-
- Map<String, String> mediaTypeParameters = null;
- if(null != mediaType) {
- mediaTypeParameters = mediaType.getParameters();
- }
- if(null != mediaTypeParameters && mediaTypeParameters.containsKey(CHARSET)) {
- String charSet = mediaTypeParameters.get(CHARSET);
- marshaller.setProperty(Marshaller.JAXB_ENCODING, charSet);
- }
-
- preWriteTo(object, type, genericType, annotations, mediaType, httpHeaders, marshaller);
- if (domainClasses.size() == 1) {
- Class<?> domainClass = domainClasses.iterator().next();
- if(!(List.class.isAssignableFrom(type) || type.isArray()) && domainClass.getPackage().getName().startsWith("java.")) {
- object = new JAXBElement(new QName((String) marshaller.getProperty(MarshallerProperties.JSON_VALUE_WRAPPER)), domainClass, object);
- }
- }
-
- marshaller.marshal(object, entityStream);
- } catch(JAXBException jaxbException) {
- throw new WebApplicationException(jaxbException);
- }
- }
-
-}
\ No newline at end of file
diff --git a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jpa/rs/PersistenceFactoryBase.java b/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jpa/rs/PersistenceFactoryBase.java
deleted file mode 100644
index c83fdf6..0000000
--- a/tomee/tomee-plume-webapp/src/patch/java/org/eclipse/persistence/jpa/rs/PersistenceFactoryBase.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (c) 2011, 2018 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:
-// dclarke/tware - initial implementation
-// gonural - version based persistence context
-// Dmitry Kornilov - JPARS 2.0 related changes
-package org.eclipse.persistence.jpa.rs;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import jakarta.persistence.EntityManagerFactory;
-import jakarta.persistence.Persistence;
-
-import org.eclipse.persistence.config.PersistenceUnitProperties;
-import org.eclipse.persistence.dynamic.DynamicClassLoader;
-import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
-import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl;
-import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor;
-import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
-import org.eclipse.persistence.jpa.Archive;
-import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
-import org.eclipse.persistence.jpa.rs.features.ServiceVersion;
-import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
-
-/**
- * Manages the PersistenceContexts that are used by a JPA-RS deployment. Provides a single point to bootstrap
- * and look up PersistenceContexts.
- *
- * @author tware
- */
-public class PersistenceFactoryBase implements PersistenceContextFactory {
- protected final Map<String, Set<PersistenceContext>> dynamicPersistenceContexts = new HashMap<>();
-
- /**
- * Bootstrap a PersistenceContext based on an pre-existing EntityManagerFactory.
- *
- * @param name persistence context name
- * @param emf entity manager factory
- * @param baseURI base URI
- * @param version JPARS version. See {@link ServiceVersion} for more details.
- * @param replace Indicates that existing persistence context with given name and version must be replaced
- * with the newly created one. If false passed the newly created context is not added to cache at all.
- * @return newly created persistence context
- */
- public PersistenceContext bootstrapPersistenceContext(String name, EntityManagerFactory emf, URI baseURI, String version, boolean replace) {
- final PersistenceContext persistenceContext = new PersistenceContext(name, (EntityManagerFactoryImpl) emf, baseURI, ServiceVersion.fromCode(version));
-
- if (replace) {
- addReplacePersistenceContext(persistenceContext);
- }
-
- return persistenceContext;
- }
-
- /**
- * Stop the factory. Remove all the PersistenceContexts.
- */
- @Override
- public void close() {
- synchronized (this) {
- for (Set<PersistenceContext> contextSet : dynamicPersistenceContexts.values()) {
- if (contextSet != null) {
- for (PersistenceContext context : contextSet) {
- context.stop();
- }
- }
- }
- dynamicPersistenceContexts.clear();
- }
- }
-
- /**
- * Close the PersistenceContext of a given name and clean it out of our list of PersistenceContexts.
- *
- * @param name name of the persistence context to close.
- */
- @Override
- public void closePersistenceContext(String name) {
- synchronized (this) {
- Set<PersistenceContext> contextSet = dynamicPersistenceContexts.get(name);
- if (contextSet != null) {
- for (PersistenceContext context : contextSet) {
- context.stop();
- }
- }
- dynamicPersistenceContexts.remove(name);
- }
- }
-
- /**
- * Close the PersistenceContext and clean it out of our list of PersistenceContexts.
- *
- * @param name name of the persistence context to close.
- * @param version persistence context version
- */
- public void closePersistenceContext(String name, String version) {
- synchronized (this) {
- final Set<PersistenceContext> contextSet = dynamicPersistenceContexts.get(name);
- if (contextSet != null) {
- for (Iterator<PersistenceContext> iter = contextSet.iterator(); iter.hasNext();) {
- PersistenceContext context = iter.next();
- if (context.getVersion().equals(version)) {
- context.stop();
- iter.remove();
- break;
- }
- }
-
- if (contextSet.size() == 0) {
- dynamicPersistenceContexts.remove(name);
- } else {
- dynamicPersistenceContexts.put(name, contextSet);
- }
- }
- }
- }
-
- /**
- * Provide an initial set of properties for bootstrapping PersistenceContexts.
- * @param dcl
- * @param originalProperties
- * @return
- */
- protected static Map<String, Object> createProperties(DynamicClassLoader dcl, Map<String, ?> originalProperties) {
- Map<String, Object> properties = new HashMap<>();
-
- properties.put(PersistenceUnitProperties.CLASSLOADER, dcl);
- properties.put(PersistenceUnitProperties.WEAVING, "static");
-
- // For now we'll copy the connection info from admin PU
- for (Map.Entry<String, ?> entry : originalProperties.entrySet()) {
- if (entry.getKey().startsWith("javax") || entry.getKey().startsWith("jakarta") || entry.getKey().startsWith("eclipselink.log") || entry.getKey().startsWith("eclipselink.target-server")) {
- properties.put(entry.getKey(), entry.getValue());
- }
- }
- return properties;
- }
-
- /**
- * Gets existing persistence context or create new based on given parameters if it doesn't exist.
- */
- @Override
- public PersistenceContext get(String persistenceUnitName, URI defaultURI, String version, Map<String, Object> initializationProperties) {
- PersistenceContext persistenceContext = getDynamicPersistenceContext(persistenceUnitName, version);
-
- if (persistenceContext == null) {
- try {
- DynamicClassLoader dcl = new DynamicClassLoader(Thread.currentThread().getContextClassLoader());
- Map<String, Object> properties = new HashMap<>();
- properties.put(PersistenceUnitProperties.CLASSLOADER, dcl);
- if (initializationProperties != null) {
- properties.putAll(initializationProperties);
- }
-
- EntityManagerFactoryImpl factory = (EntityManagerFactoryImpl) Persistence.createEntityManagerFactory(persistenceUnitName, properties);
- ClassLoader sessionLoader = factory.getServerSession().getLoader();
- if (!DynamicClassLoader.class.isAssignableFrom(sessionLoader.getClass())) {
- properties = new HashMap<>();
- dcl = new DynamicClassLoader(sessionLoader);
- properties.put(PersistenceUnitProperties.CLASSLOADER, dcl);
- if (initializationProperties != null) {
- properties.putAll(initializationProperties);
- }
- factory.refreshMetadata(properties);
- }
-
- persistenceContext = bootstrapPersistenceContext(persistenceUnitName, factory, defaultURI, version, true);
- } catch (Exception e) {
- JPARSLogger.exception("exception_creating_persistence_context", new Object[] { persistenceUnitName, e.toString() }, e);
- }
- }
-
- if ((persistenceContext != null) && (!persistenceContext.isWeavingEnabled())) {
- JPARSLogger.error(persistenceContext.getServerSession().getSessionLog(), "weaving_required_for_relationships", new Object[] {});
- throw JPARSException.invalidConfiguration();
- }
-
- return persistenceContext;
- }
-
- /**
- * Returns names of all currently cached persistence contexts.
- */
- @Override
- public Set<String> getPersistenceContextNames() {
- Set<String> contextNames = new HashSet<>();
- try {
- Set<Archive> archives = PersistenceUnitProcessor.findPersistenceArchives();
- for (Archive archive : archives) {
- List<SEPersistenceUnitInfo> infos = PersistenceUnitProcessor.processPersistenceArchive(archive, Thread.currentThread().getContextClassLoader());
- for (SEPersistenceUnitInfo info : infos) {
- if (!info.getPersistenceUnitName().equals("jpa-rs")) {
- if (EntityManagerSetupImpl.mustBeCompositeMember(info)) {
- continue;
- }
- contextNames.add(info.getPersistenceUnitName());
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- contextNames.addAll(dynamicPersistenceContexts.keySet());
- return contextNames;
- }
-
- /**
- * Gets cached persistence context by its name and JPARS version.
- *
- * @param name persistent unit name.
- * @param version JPARS version. See {@link ServiceVersion} for more details.
- * @return persistence context or null if doesn't exist.
- */
- public PersistenceContext getDynamicPersistenceContext(String name, String version) {
- synchronized (this) {
- Set<PersistenceContext> persistenceContextSet = dynamicPersistenceContexts.get(name);
- if (persistenceContextSet != null) {
- for (PersistenceContext persistenceContext : persistenceContextSet) {
- if ((name != null) && (version != null)) {
- if ((name.equals(persistenceContext.getName())) && (version.equals(persistenceContext.getVersion()))) {
- return persistenceContext;
- }
- } else if (((version == null) && (persistenceContext.getVersion() == null)) &&
- ((name != null) && (name.equals(persistenceContext.getName())))) {
- return persistenceContext;
- }
- }
- }
- }
- return null;
- }
-
- protected void addReplacePersistenceContext(PersistenceContext persistenceContext) {
- synchronized (this) {
- final PersistenceContext existingContext = getDynamicPersistenceContext(persistenceContext.getName(), persistenceContext.getVersion());
-
- Set<PersistenceContext> persistenceContextSet = dynamicPersistenceContexts.get(persistenceContext.getName());
- if (persistenceContextSet == null) {
- persistenceContextSet = new HashSet<>();
- }
-
- if (existingContext != null) {
- persistenceContextSet.remove(existingContext);
- }
-
- persistenceContextSet.add(persistenceContext);
- dynamicPersistenceContexts.put(persistenceContext.getName(), persistenceContextSet);
- }
- }
-}
\ No newline at end of file