You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by jg...@apache.org on 2020/06/19 10:22:38 UTC
[tomee] 01/03: Using new repository
This is an automated email from the ASF dual-hosted git repository.
jgallimore pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomee.git
commit e48dc4a20d33595dc1ceb7cc7399d012c658a4dd
Author: Jonathan Gallimore <jo...@jrg.me.uk>
AuthorDate: Fri Jun 19 11:21:10 2020 +0100
Using new repository
---
jakarta/pom.xml | 336 ---
jakarta/src/main/assembly/tomee-microprofile.xml | 38 -
jakarta/src/main/assembly/tomee-plume.xml | 38 -
jakarta/src/main/assembly/tomee-plus.xml | 38 -
jakarta/src/main/assembly/tomee-webprofile.xml | 38 -
.../catalina/loader/WebappClassLoaderBase.java | 2725 --------------------
.../apache/cxf/jaxb/JAXBContextInitializer.java | 611 -----
.../openjpa/enhance/PCClassFileTransformer.java | 254 --
.../openjpa/lib/meta/ClassMetaDataIterator.java | 203 --
.../openjpa/lib/util/TemporaryClassLoader.java | 123 -
.../openjpa/meta/AbstractMetaDataDefaults.java | 422 ---
.../MbeansDescriptorsIntrospectionSource.java | 392 ---
.../webbeans/proxy/AbstractProxyFactory.java | 737 ------
.../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 --
.../org/quartz/core/QuartzSchedulerMBeanImpl.java | 1011 --------
pom.xml | 1 -
22 files changed, 10985 deletions(-)
diff --git a/jakarta/pom.xml b/jakarta/pom.xml
deleted file mode 100644
index 0044d1d..0000000
--- a/jakarta/pom.xml
+++ /dev/null
@@ -1,336 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- $Rev: 600338 $ $Date: 2007-12-02 09:08:04 -0800 (Sun, 02 Dec 2007) $ -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-
- <parent>
- <artifactId>tomee-project</artifactId>
- <groupId>org.apache.tomee</groupId>
- <version>8.0.3-SNAPSHOT</version>
- </parent>
-
- <modelVersion>4.0.0</modelVersion>
- <artifactId>apache-tomee</artifactId>
- <version>9.0.0-M1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>TomEE :: TomEE :: Apache TomEE 9</name>
-
- <properties>
- <tomee.version>8.0.3</tomee.version>
- <tomee.build.name>${project.groupId}.tomee.tomee</tomee.build.name>
- <webprofile.work-dir>${project.build.directory}/webprofile-work-dir</webprofile.work-dir>
- <plus.work-dir>${project.build.directory}/plus-work-dir</plus.work-dir>
- <plume.work-dir>${project.build.directory}/plume-work-dir</plume.work-dir>
- <microprofile.work-dir>${project.build.directory}/microprofile-work-dir</microprofile.work-dir>
- </properties>
-
- <dependencies>
- <dependency> <!-- to be sure to have it -->
- <groupId>${project.groupId}</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>webprofile</classifier>
- <type>zip</type>
- <scope>provided</scope>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency> <!-- to be sure to have it -->
- <groupId>${project.groupId}</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>microprofile</classifier>
- <type>zip</type>
- <scope>provided</scope>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency> <!-- to be sure to have it -->
- <groupId>${project.groupId}</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>plume</classifier>
- <type>zip</type>
- <scope>provided</scope>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency> <!-- to be sure to have it -->
- <groupId>${project.groupId}</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>plus</classifier>
- <type>zip</type>
- <scope>provided</scope>
- <exclusions>
- <exclusion>
- <groupId>*</groupId>
- <artifactId>*</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- </dependencies>
-
- <build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>false</filtering>
- </resource>
- </resources>
-
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>unpack-webprofile</id>
- <phase>process-resources</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.tomee</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>webprofile</classifier>
- <type>zip</type>
- <outputDirectory>${webprofile.work-dir}</outputDirectory>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- <execution>
- <id>unpack-microprofile</id>
- <phase>process-resources</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.tomee</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>microprofile</classifier>
- <type>zip</type>
- <outputDirectory>${microprofile.work-dir}</outputDirectory>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- <execution>
- <id>unpack-plume</id>
- <phase>process-resources</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.tomee</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>plume</classifier>
- <type>zip</type>
- <outputDirectory>${plume.work-dir}</outputDirectory>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- <execution>
- <id>unpack-plus</id>
- <phase>process-resources</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.apache.tomee</groupId>
- <artifactId>apache-tomee</artifactId>
- <version>${tomee.version}</version>
- <classifier>plus</classifier>
- <type>zip</type>
- <outputDirectory>${plus.work-dir}</outputDirectory>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <executions>
- <execution>
- <id>webprofile</id>
- <phase>package</phase>
- <configuration>
- <descriptors>
- <descriptor>src/main/assembly/tomee-webprofile.xml</descriptor>
- </descriptors>
- <attach>false</attach>
- <appendAssemblyId>false</appendAssemblyId>
- <finalName>apache-tomee-webprofile-${project.version}</finalName>
- </configuration>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- <execution>
- <id>plus</id>
- <phase>package</phase>
- <configuration>
- <descriptors>
- <descriptor>src/main/assembly/tomee-plus.xml</descriptor>
- </descriptors>
- <attach>false</attach>
- <appendAssemblyId>false</appendAssemblyId>
- <finalName>apache-tomee-plus-${project.version}</finalName>
- </configuration>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- <execution>
- <id>plume</id>
- <phase>package</phase>
- <configuration>
- <descriptors>
- <descriptor>src/main/assembly/tomee-plume.xml</descriptor>
- </descriptors>
- <attach>false</attach>
- <appendAssemblyId>false</appendAssemblyId>
- <finalName>apache-tomee-plume-${project.version}</finalName>
- </configuration>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- <execution>
- <id>microprofile</id>
- <phase>package</phase>
- <configuration>
- <descriptors>
- <descriptor>src/main/assembly/tomee-microprofile.xml</descriptor>
- </descriptors>
- <attach>false</attach>
- <appendAssemblyId>false</appendAssemblyId>
- <finalName>apache-tomee-microprofile-${project.version}</finalName>
- </configuration>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <phase>package</phase>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <configuration>
- <artifacts>
- <artifact>
- <file>${project.build.directory}/apache-tomee-webprofile-${project.version}.zip</file>
- <type>zip</type>
- <classifier>webprofile</classifier>
- </artifact>
- <artifact>
- <file>${project.build.directory}/apache-tomee-plus-${project.version}.zip</file>
- <type>zip</type>
- <classifier>plus</classifier>
- </artifact>
- <artifact>
- <file>${project.build.directory}/apache-tomee-plume-${project.version}.zip</file>
- <type>zip</type>
- <classifier>plume</classifier>
- </artifact>
- <artifact>
- <file>${project.build.directory}/apache-tomee-microprofile-${project.version}.zip</file>
- <type>zip</type>
- <classifier>microprofile</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.tomitribe.transformer</groupId>
- <artifactId>org.eclipse.transformer.maven</artifactId>
- <version>0.1.1a</version>
- <executions>
- <execution>
- <goals>
- <goal>run</goal>
- </goals>
- <phase>package</phase>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.tomee.patch</groupId>
- <artifactId>tomee-patch-plugin</artifactId>
- <version>0.1</version>
- <configuration>
- <select>apache-tomee.*\.zip</select>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>run</goal>
- </goals>
- <phase>package</phase>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
-</project>
diff --git a/jakarta/src/main/assembly/tomee-microprofile.xml b/jakarta/src/main/assembly/tomee-microprofile.xml
deleted file mode 100644
index 6a1e49b..0000000
--- a/jakarta/src/main/assembly/tomee-microprofile.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- $Rev: 576067 $ $Date: 2007-09-16 03:17:08 -0700 (Sun, 16 Sep 2007) $ -->
-
-<assembly>
- <id>tomee-microprofile</id>
- <formats>
- <format>zip</format>
- </formats>
- <includeBaseDirectory>false</includeBaseDirectory>
- <fileSets>
- <fileSet>
- <directory>${microprofile.work-dir}/apache-tomee-microprofile-${tomee.version}</directory>
- <outputDirectory>/apache-tomee-microprofile-${project.version}</outputDirectory>
- <includes>
- <include>**/*</include>
- </includes>
- </fileSet>
- </fileSets>
-</assembly>
-
diff --git a/jakarta/src/main/assembly/tomee-plume.xml b/jakarta/src/main/assembly/tomee-plume.xml
deleted file mode 100644
index bb71e05..0000000
--- a/jakarta/src/main/assembly/tomee-plume.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- $Rev: 576067 $ $Date: 2007-09-16 03:17:08 -0700 (Sun, 16 Sep 2007) $ -->
-
-<assembly>
- <id>tomee-plume</id>
- <formats>
- <format>zip</format>
- </formats>
- <includeBaseDirectory>false</includeBaseDirectory>
- <fileSets>
- <fileSet>
- <directory>${plume.work-dir}/apache-tomee-plume-${tomee.version}</directory>
- <outputDirectory>/apache-tomee-plume-${project.version}</outputDirectory>
- <includes>
- <include>**/*</include>
- </includes>
- </fileSet>
- </fileSets>
-</assembly>
-
diff --git a/jakarta/src/main/assembly/tomee-plus.xml b/jakarta/src/main/assembly/tomee-plus.xml
deleted file mode 100644
index e0c5708..0000000
--- a/jakarta/src/main/assembly/tomee-plus.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- $Rev: 576067 $ $Date: 2007-09-16 03:17:08 -0700 (Sun, 16 Sep 2007) $ -->
-
-<assembly>
- <id>tomee-plus</id>
- <formats>
- <format>zip</format>
- </formats>
- <includeBaseDirectory>false</includeBaseDirectory>
- <fileSets>
- <fileSet>
- <directory>${plus.work-dir}/apache-tomee-plus-${tomee.version}</directory>
- <outputDirectory>/apache-tomee-plus-${project.version}</outputDirectory>
- <includes>
- <include>**/*</include>
- </includes>
- </fileSet>
- </fileSets>
-</assembly>
-
diff --git a/jakarta/src/main/assembly/tomee-webprofile.xml b/jakarta/src/main/assembly/tomee-webprofile.xml
deleted file mode 100644
index 1777653..0000000
--- a/jakarta/src/main/assembly/tomee-webprofile.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- $Rev: 576067 $ $Date: 2007-09-16 03:17:08 -0700 (Sun, 16 Sep 2007) $ -->
-
-<assembly>
- <id>tomee-webprofile</id>
- <formats>
- <format>zip</format>
- </formats>
- <includeBaseDirectory>false</includeBaseDirectory>
- <fileSets>
- <fileSet>
- <directory>${webprofile.work-dir}/apache-tomee-webprofile-${tomee.version}</directory>
- <outputDirectory>/apache-tomee-webprofile-${project.version}</outputDirectory>
- <includes>
- <include>**/*</include>
- </includes>
- </fileSet>
- </fileSets>
-</assembly>
-
diff --git a/jakarta/src/patch/java/org/apache/catalina/loader/WebappClassLoaderBase.java b/jakarta/src/patch/java/org/apache/catalina/loader/WebappClassLoaderBase.java
deleted file mode 100644
index 2e75d4c..0000000
--- a/jakarta/src/patch/java/org/apache/catalina/loader/WebappClassLoaderBase.java
+++ /dev/null
@@ -1,2725 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.catalina.loader;
-
-import java.io.File;
-import java.io.FilePermission;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.ref.Reference;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessControlException;
-import java.security.AccessController;
-import java.security.CodeSource;
-import java.security.Permission;
-import java.security.PermissionCollection;
-import java.security.Policy;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.security.cert.Certificate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ConcurrentModificationException;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.jar.Attributes;
-import java.util.jar.Attributes.Name;
-import java.util.jar.Manifest;
-
-import org.apache.catalina.Container;
-import org.apache.catalina.Globals;
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.LifecycleState;
-import org.apache.catalina.WebResource;
-import org.apache.catalina.WebResourceRoot;
-import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
-import org.apache.juli.WebappProperties;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.InstrumentableClassLoader;
-import org.apache.tomcat.util.ExceptionUtils;
-import org.apache.tomcat.util.IntrospectionUtils;
-import org.apache.tomcat.util.compat.JreCompat;
-import org.apache.tomcat.util.res.StringManager;
-import org.apache.tomcat.util.security.PermissionCheck;
-
-/**
- * Specialized web application class loader.
- * <p>
- * This class loader is a full reimplementation of the
- * <code>URLClassLoader</code> from the JDK. It is designed to be fully
- * compatible with a normal <code>URLClassLoader</code>, although its internal
- * behavior may be completely different.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - By default, this class loader follows
- * the delegation model required by the specification. The system class
- * loader will be queried first, then the local repositories, and only then
- * delegation to the parent class loader will occur. This allows the web
- * application to override any shared class except the classes from J2SE.
- * Special handling is provided from the JAXP XML parser interfaces, the JNDI
- * interfaces, and the classes from the servlet API, which are never loaded
- * from the webapp repositories. The <code>delegate</code> property
- * allows an application to modify this behavior to move the parent class loader
- * ahead of the local repositories.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - Due to limitations in Jasper
- * compilation technology, any repository which contains classes from
- * the servlet API will be ignored by the class loader.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - The class loader generates source
- * URLs which include the full JAR URL when a class is loaded from a JAR file,
- * which allows setting security permission at the class level, even when a
- * class is contained inside a JAR.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - Local repositories are searched in
- * the order they are added via the initial constructor.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - No check for sealing violations or
- * security is made unless a security manager is present.
- * <p>
- * <strong>IMPLEMENTATION NOTE</strong> - As of 8.0, this class
- * loader implements {@link InstrumentableClassLoader}, permitting web
- * application classes to instrument other classes in the same web
- * application. It does not permit instrumentation of system or container
- * classes or classes in other web apps.
- *
- * @author Remy Maucherat
- * @author Craig R. McClanahan
- */
-public abstract class WebappClassLoaderBase extends URLClassLoader
- implements Lifecycle, InstrumentableClassLoader, WebappProperties, PermissionCheck {
-
- private static final Log log = LogFactory.getLog(WebappClassLoaderBase.class);
-
- /**
- * List of ThreadGroup names to ignore when scanning for web application
- * started threads that need to be shut down.
- */
- private static final List<String> JVM_THREAD_GROUP_NAMES = new ArrayList<>();
-
- private static final String JVM_THREAD_GROUP_SYSTEM = "system";
-
- private static final String CLASS_FILE_SUFFIX = ".class";
-
- static {
- if (!JreCompat.isGraalAvailable()) {
- ClassLoader.registerAsParallelCapable();
- }
- JVM_THREAD_GROUP_NAMES.add(JVM_THREAD_GROUP_SYSTEM);
- JVM_THREAD_GROUP_NAMES.add("RMI Runtime");
- }
-
- protected class PrivilegedFindClassByName implements PrivilegedAction<Class<?>> {
-
- private final String name;
-
- PrivilegedFindClassByName(String name) {
- this.name = name;
- }
-
- @Override
- public Class<?> run() {
- return findClassInternal(name);
- }
- }
-
-
- protected static final class PrivilegedGetClassLoader implements PrivilegedAction<ClassLoader> {
-
- private final Class<?> clazz;
-
- public PrivilegedGetClassLoader(Class<?> clazz){
- this.clazz = clazz;
- }
-
- @Override
- public ClassLoader run() {
- return clazz.getClassLoader();
- }
- }
-
-
- protected final class PrivilegedJavaseGetResource implements PrivilegedAction<URL> {
-
- private final String name;
-
- public PrivilegedJavaseGetResource(String name) {
- this.name = name;
- }
-
- @Override
- public URL run() {
- return javaseClassLoader.getResource(name);
- }
- }
-
-
- // ------------------------------------------------------- Static Variables
-
- /**
- * The string manager for this package.
- */
- protected static final StringManager sm =
- StringManager.getManager(Constants.Package);
-
-
- // ----------------------------------------------------------- Constructors
-
- /**
- * Construct a new ClassLoader with no defined repositories and no
- * parent ClassLoader.
- */
- protected WebappClassLoaderBase() {
-
- super(new URL[0]);
-
- ClassLoader p = getParent();
- if (p == null) {
- p = getSystemClassLoader();
- }
- this.parent = p;
-
- ClassLoader j = String.class.getClassLoader();
- if (j == null) {
- j = getSystemClassLoader();
- while (j.getParent() != null) {
- j = j.getParent();
- }
- }
- this.javaseClassLoader = j;
-
- securityManager = System.getSecurityManager();
- if (securityManager != null) {
- refreshPolicy();
- }
- }
-
-
- /**
- * Construct a new ClassLoader with no defined repositories and the given
- * parent ClassLoader.
- * <p>
- * Method is used via reflection -
- * see {@link WebappLoader#createClassLoader()}
- *
- * @param parent Our parent class loader
- */
- protected WebappClassLoaderBase(ClassLoader parent) {
-
- super(new URL[0], parent);
-
- ClassLoader p = getParent();
- if (p == null) {
- p = getSystemClassLoader();
- }
- this.parent = p;
-
- ClassLoader j = String.class.getClassLoader();
- if (j == null) {
- j = getSystemClassLoader();
- while (j.getParent() != null) {
- j = j.getParent();
- }
- }
- this.javaseClassLoader = j;
-
- securityManager = System.getSecurityManager();
- if (securityManager != null) {
- refreshPolicy();
- }
- }
-
-
- // ----------------------------------------------------- Instance Variables
-
- /**
- * Associated web resources for this webapp.
- */
- protected WebResourceRoot resources = null;
-
-
- /**
- * The cache of ResourceEntry for classes and resources we have loaded,
- * keyed by resource path, not binary name. Path is used as the key since
- * resources may be requested by binary name (classes) or path (other
- * resources such as property files) and the mapping from binary name to
- * path is unambiguous but the reverse mapping is ambiguous.
- */
- protected final Map<String, ResourceEntry> resourceEntries =
- new ConcurrentHashMap<>();
-
-
- /**
- * Should this class loader delegate to the parent class loader
- * <strong>before</strong> searching its own repositories (i.e. the
- * usual Java2 delegation model)? If set to <code>false</code>,
- * this class loader will search its own repositories first, and
- * delegate to the parent only if the class or resource is not
- * found locally. Note that the default, <code>false</code>, is
- * the behavior called for by the servlet specification.
- */
- protected boolean delegate = false;
-
-
- private final Map<String,Long> jarModificationTimes = new HashMap<>();
-
-
- /**
- * A list of read File Permission's required if this loader is for a web
- * application context.
- */
- protected final ArrayList<Permission> permissionList = new ArrayList<>();
-
-
- /**
- * The PermissionCollection for each CodeSource for a web
- * application context.
- */
- protected final HashMap<String, PermissionCollection> loaderPC = new HashMap<>();
-
-
- /**
- * Instance of the SecurityManager installed.
- */
- protected final SecurityManager securityManager;
-
-
- /**
- * The parent class loader.
- */
- protected final ClassLoader parent;
-
-
- /**
- * The bootstrap class loader used to load the JavaSE classes. In some
- * implementations this class loader is always <code>null</code> and in
- * those cases {@link ClassLoader#getParent()} will be called recursively on
- * the system class loader and the last non-null result used.
- */
- private ClassLoader javaseClassLoader;
-
-
- /**
- * Enables the RMI Target memory leak detection to be controlled. This is
- * necessary since the detection can only work on Java 9 if some of the
- * modularity checks are disabled.
- */
- private boolean clearReferencesRmiTargets = true;
-
- /**
- * Should Tomcat attempt to terminate threads that have been started by the
- * web application? Stopping threads is performed via the deprecated (for
- * good reason) <code>Thread.stop()</code> method and is likely to result in
- * instability. As such, enabling this should be viewed as an option of last
- * resort in a development environment and is not recommended in a
- * production environment. If not specified, the default value of
- * <code>false</code> will be used.
- */
- private boolean clearReferencesStopThreads = false;
-
- /**
- * Should Tomcat attempt to terminate any {@link java.util.TimerThread}s
- * that have been started by the web application? If not specified, the
- * default value of <code>false</code> will be used.
- */
- private boolean clearReferencesStopTimerThreads = false;
-
- /**
- * Should Tomcat call
- * {@link org.apache.juli.logging.LogFactory#release(ClassLoader)}
- * when the class loader is stopped? If not specified, the default value
- * of <code>true</code> is used. Changing the default setting is likely to
- * lead to memory leaks and other issues.
- */
- private boolean clearReferencesLogFactoryRelease = true;
-
- /**
- * If an HttpClient keep-alive timer thread has been started by this web
- * application and is still running, should Tomcat change the context class
- * loader from the current {@link ClassLoader} to
- * {@link ClassLoader#getParent()} to prevent a memory leak? Note that the
- * keep-alive timer thread will stop on its own once the keep-alives all
- * expire however, on a busy system that might not happen for some time.
- */
- private boolean clearReferencesHttpClientKeepAliveThread = true;
-
- /**
- * Should Tomcat attempt to clear references to classes loaded by this class
- * loader from the ObjectStreamClass caches?
- */
- private boolean clearReferencesObjectStreamClassCaches = true;
-
- /**
- * Should Tomcat attempt to clear references to classes loaded by this class
- * loader from ThreadLocals?
- */
- private boolean clearReferencesThreadLocals = true;
-
- /**
- * Should Tomcat skip the memory leak checks when the web application is
- * stopped as part of the process of shutting down the JVM?
- */
- private boolean skipMemoryLeakChecksOnJvmShutdown = false;
-
- /**
- * Holds the class file transformers decorating this class loader. The
- * CopyOnWriteArrayList is thread safe. It is expensive on writes, but
- * those should be rare. It is very fast on reads, since synchronization
- * is not actually used. Importantly, the ClassLoader will never block
- * iterating over the transformers while loading a class.
- */
- private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<>();
-
-
- /**
- * Flag that indicates that {@link #addURL(URL)} has been called which
- * creates a requirement to check the super class when searching for
- * resources.
- */
- private boolean hasExternalRepositories = false;
-
-
- /**
- * Repositories managed by this class rather than the super class.
- */
- private List<URL> localRepositories = new ArrayList<>();
-
-
- private volatile LifecycleState state = LifecycleState.NEW;
-
-
- // ------------------------------------------------------------- Properties
-
- /**
- * @return associated resources.
- */
- public WebResourceRoot getResources() {
- return this.resources;
- }
-
-
- /**
- * Set associated resources.
- * @param resources the resources from which the classloader will
- * load the classes
- */
- public void setResources(WebResourceRoot resources) {
- this.resources = resources;
- }
-
-
- /**
- * @return the context name for this class loader.
- */
- public String getContextName() {
- if (resources == null) {
- return "Unknown";
- } else {
- return resources.getContext().getBaseName();
- }
- }
-
-
- /**
- * Return the "delegate first" flag for this class loader.
- * @return <code>true</code> if the class lookup will delegate to
- * the parent first. The default in Tomcat is <code>false</code>.
- */
- public boolean getDelegate() {
- return this.delegate;
- }
-
-
- /**
- * Set the "delegate first" flag for this class loader.
- * If this flag is true, this class loader delegates
- * to the parent class loader
- * <strong>before</strong> searching its own repositories, as
- * in an ordinary (non-servlet) chain of Java class loaders.
- * If set to <code>false</code> (the default),
- * this class loader will search its own repositories first, and
- * delegate to the parent only if the class or resource is not
- * found locally, as per the servlet specification.
- *
- * @param delegate The new "delegate first" flag
- */
- public void setDelegate(boolean delegate) {
- this.delegate = delegate;
- }
-
-
- /**
- * If there is a Java SecurityManager create a read permission for the
- * target of the given URL as appropriate.
- *
- * @param url URL for a file or directory on local system
- */
- void addPermission(URL url) {
- if (url == null) {
- return;
- }
- if (securityManager != null) {
- String protocol = url.getProtocol();
- if ("file".equalsIgnoreCase(protocol)) {
- URI uri;
- File f;
- String path;
- try {
- uri = url.toURI();
- f = new File(uri);
- path = f.getCanonicalPath();
- } catch (IOException | URISyntaxException e) {
- log.warn(sm.getString(
- "webappClassLoader.addPermisionNoCanonicalFile",
- url.toExternalForm()));
- return;
- }
- if (f.isFile()) {
- // Allow the file to be read
- addPermission(new FilePermission(path, "read"));
- } else if (f.isDirectory()) {
- addPermission(new FilePermission(path, "read"));
- addPermission(new FilePermission(
- path + File.separator + "-", "read"));
- } else {
- // File does not exist - ignore (shouldn't happen)
- }
- } else {
- // Unsupported URL protocol
- log.warn(sm.getString(
- "webappClassLoader.addPermisionNoProtocol",
- protocol, url.toExternalForm()));
- }
- }
- }
-
-
- /**
- * If there is a Java SecurityManager create a Permission.
- *
- * @param permission The permission
- */
- void addPermission(Permission permission) {
- if ((securityManager != null) && (permission != null)) {
- permissionList.add(permission);
- }
- }
-
-
- public boolean getClearReferencesRmiTargets() {
- return this.clearReferencesRmiTargets;
- }
-
-
- public void setClearReferencesRmiTargets(boolean clearReferencesRmiTargets) {
- this.clearReferencesRmiTargets = clearReferencesRmiTargets;
- }
-
-
- /**
- * @return the clearReferencesStopThreads flag for this Context.
- */
- public boolean getClearReferencesStopThreads() {
- return this.clearReferencesStopThreads;
- }
-
-
- /**
- * Set the clearReferencesStopThreads feature for this Context.
- *
- * @param clearReferencesStopThreads The new flag value
- */
- public void setClearReferencesStopThreads(
- boolean clearReferencesStopThreads) {
- this.clearReferencesStopThreads = clearReferencesStopThreads;
- }
-
-
- /**
- * @return the clearReferencesStopTimerThreads flag for this Context.
- */
- public boolean getClearReferencesStopTimerThreads() {
- return this.clearReferencesStopTimerThreads;
- }
-
-
- /**
- * Set the clearReferencesStopTimerThreads feature for this Context.
- *
- * @param clearReferencesStopTimerThreads The new flag value
- */
- public void setClearReferencesStopTimerThreads(
- boolean clearReferencesStopTimerThreads) {
- this.clearReferencesStopTimerThreads = clearReferencesStopTimerThreads;
- }
-
-
- /**
- * @return the clearReferencesLogFactoryRelease flag for this Context.
- */
- public boolean getClearReferencesLogFactoryRelease() {
- return this.clearReferencesLogFactoryRelease;
- }
-
-
- /**
- * Set the clearReferencesLogFactoryRelease feature for this Context.
- *
- * @param clearReferencesLogFactoryRelease The new flag value
- */
- public void setClearReferencesLogFactoryRelease(
- boolean clearReferencesLogFactoryRelease) {
- this.clearReferencesLogFactoryRelease =
- clearReferencesLogFactoryRelease;
- }
-
-
- /**
- * @return the clearReferencesHttpClientKeepAliveThread flag for this
- * Context.
- */
- public boolean getClearReferencesHttpClientKeepAliveThread() {
- return this.clearReferencesHttpClientKeepAliveThread;
- }
-
-
- /**
- * Set the clearReferencesHttpClientKeepAliveThread feature for this
- * Context.
- *
- * @param clearReferencesHttpClientKeepAliveThread The new flag value
- */
- public void setClearReferencesHttpClientKeepAliveThread(
- boolean clearReferencesHttpClientKeepAliveThread) {
- this.clearReferencesHttpClientKeepAliveThread =
- clearReferencesHttpClientKeepAliveThread;
- }
-
-
- public boolean getClearReferencesObjectStreamClassCaches() {
- return clearReferencesObjectStreamClassCaches;
- }
-
-
- public void setClearReferencesObjectStreamClassCaches(
- boolean clearReferencesObjectStreamClassCaches) {
- this.clearReferencesObjectStreamClassCaches = clearReferencesObjectStreamClassCaches;
- }
-
-
- public boolean getClearReferencesThreadLocals() {
- return clearReferencesThreadLocals;
- }
-
-
- public void setClearReferencesThreadLocals(boolean clearReferencesThreadLocals) {
- this.clearReferencesThreadLocals = clearReferencesThreadLocals;
- }
-
-
- public boolean getSkipMemoryLeakChecksOnJvmShutdown() {
- return skipMemoryLeakChecksOnJvmShutdown;
- }
-
-
- public void setSkipMemoryLeakChecksOnJvmShutdown(boolean skipMemoryLeakChecksOnJvmShutdown) {
- this.skipMemoryLeakChecksOnJvmShutdown = skipMemoryLeakChecksOnJvmShutdown;
- }
-
-
- // ------------------------------------------------------- Reloader Methods
-
- /**
- * Adds the specified class file transformer to this class loader. The
- * transformer will then be able to modify the bytecode of any classes
- * loaded by this class loader after the invocation of this method.
- *
- * @param transformer The transformer to add to the class loader
- */
- @Override
- public void addTransformer(ClassFileTransformer transformer) {
-
- if (transformer == null) {
- throw new IllegalArgumentException(sm.getString(
- "webappClassLoader.addTransformer.illegalArgument", getContextName()));
- }
-
- if (this.transformers.contains(transformer)) {
- // if the same instance of this transformer was already added, bail out
- log.warn(sm.getString("webappClassLoader.addTransformer.duplicate",
- transformer, getContextName()));
- return;
- }
- this.transformers.add(transformer);
-
- log.info(sm.getString("webappClassLoader.addTransformer", transformer, getContextName()));
- }
-
- /**
- * Removes the specified class file transformer from this class loader.
- * It will no longer be able to modify the byte code of any classes
- * loaded by the class loader after the invocation of this method.
- * However, any classes already modified by this transformer will
- * remain transformed.
- *
- * @param transformer The transformer to remove
- */
- @Override
- public void removeTransformer(ClassFileTransformer transformer) {
-
- if (transformer == null) {
- return;
- }
-
- if (this.transformers.remove(transformer)) {
- log.info(sm.getString("webappClassLoader.removeTransformer",
- transformer, getContextName()));
- }
- }
-
- protected void copyStateWithoutTransformers(WebappClassLoaderBase base) {
- base.resources = this.resources;
- base.delegate = this.delegate;
- base.state = LifecycleState.NEW;
- base.clearReferencesStopThreads = this.clearReferencesStopThreads;
- base.clearReferencesStopTimerThreads = this.clearReferencesStopTimerThreads;
- base.clearReferencesLogFactoryRelease = this.clearReferencesLogFactoryRelease;
- base.clearReferencesHttpClientKeepAliveThread = this.clearReferencesHttpClientKeepAliveThread;
- base.jarModificationTimes.putAll(this.jarModificationTimes);
- base.permissionList.addAll(this.permissionList);
- base.loaderPC.putAll(this.loaderPC);
- }
-
- /**
- * Have one or more classes or resources been modified so that a reload
- * is appropriate?
- * @return <code>true</code> if there's been a modification
- */
- public boolean modified() {
-
- if (log.isDebugEnabled())
- log.debug("modified()");
-
- for (Entry<String,ResourceEntry> entry : resourceEntries.entrySet()) {
- long cachedLastModified = entry.getValue().lastModified;
- long lastModified = resources.getClassLoaderResource(
- entry.getKey()).getLastModified();
- if (lastModified != cachedLastModified) {
- if( log.isDebugEnabled() )
- log.debug(sm.getString("webappClassLoader.resourceModified",
- entry.getKey(),
- new Date(cachedLastModified),
- new Date(lastModified)));
- return true;
- }
- }
-
- // Check if JARs have been added or removed
- WebResource[] jars = resources.listResources("/WEB-INF/lib");
- // Filter out non-JAR resources
-
- int jarCount = 0;
- for (WebResource jar : jars) {
- if (jar.getName().endsWith(".jar") && jar.isFile() && jar.canRead()) {
- jarCount++;
- Long recordedLastModified = jarModificationTimes.get(jar.getName());
- if (recordedLastModified == null) {
- // Jar has been added
- log.info(sm.getString("webappClassLoader.jarsAdded",
- resources.getContext().getName()));
- return true;
- }
- if (recordedLastModified.longValue() != jar.getLastModified()) {
- // Jar has been changed
- log.info(sm.getString("webappClassLoader.jarsModified",
- resources.getContext().getName()));
- return true;
- }
- }
- }
-
- if (jarCount < jarModificationTimes.size()){
- log.info(sm.getString("webappClassLoader.jarsRemoved",
- resources.getContext().getName()));
- return true;
- }
-
-
- // No classes have been modified
- return false;
- }
-
-
- @Override
- public String toString() {
-
- StringBuilder sb = new StringBuilder(this.getClass().getSimpleName());
- sb.append("\r\n context: ");
- sb.append(getContextName());
- sb.append("\r\n delegate: ");
- sb.append(delegate);
- sb.append("\r\n");
- if (this.parent != null) {
- sb.append("----------> Parent Classloader:\r\n");
- sb.append(this.parent.toString());
- sb.append("\r\n");
- }
- if (this.transformers.size() > 0) {
- sb.append("----------> Class file transformers:\r\n");
- for (ClassFileTransformer transformer : this.transformers) {
- sb.append(transformer).append("\r\n");
- }
- }
- return sb.toString();
- }
-
-
- // ---------------------------------------------------- ClassLoader Methods
-
-
- // Note: exposed for use by tests
- protected final Class<?> doDefineClass(String name, byte[] b, int off, int len,
- ProtectionDomain protectionDomain) {
- return super.defineClass(name, b, off, len, protectionDomain);
- }
-
- /**
- * Find the specified class in our local repositories, if possible. If
- * not found, throw <code>ClassNotFoundException</code>.
- *
- * @param name The binary name of the class to be loaded
- *
- * @exception ClassNotFoundException if the class was not found
- */
- @Override
- public Class<?> findClass(String name) throws ClassNotFoundException {
-
- if (log.isDebugEnabled())
- log.debug(" findClass(" + name + ")");
-
- checkStateForClassLoading(name);
-
- // (1) Permission to define this class when using a SecurityManager
- if (securityManager != null) {
- int i = name.lastIndexOf('.');
- if (i >= 0) {
- try {
- if (log.isTraceEnabled())
- log.trace(" securityManager.checkPackageDefinition");
- securityManager.checkPackageDefinition(name.substring(0,i));
- } catch (Exception se) {
- if (log.isTraceEnabled())
- log.trace(" -->Exception-->ClassNotFoundException", se);
- throw new ClassNotFoundException(name, se);
- }
- }
- }
-
- // Ask our superclass to locate this class, if possible
- // (throws ClassNotFoundException if it is not found)
- Class<?> clazz = null;
- try {
- if (log.isTraceEnabled())
- log.trace(" findClassInternal(" + name + ")");
- try {
- if (securityManager != null) {
- PrivilegedAction<Class<?>> dp =
- new PrivilegedFindClassByName(name);
- clazz = AccessController.doPrivileged(dp);
- } else {
- clazz = findClassInternal(name);
- }
- } catch(AccessControlException ace) {
- log.warn(sm.getString("webappClassLoader.securityException", name,
- ace.getMessage()), ace);
- throw new ClassNotFoundException(name, ace);
- } catch (RuntimeException e) {
- if (log.isTraceEnabled())
- log.trace(" -->RuntimeException Rethrown", e);
- throw e;
- }
- if ((clazz == null) && hasExternalRepositories) {
- try {
- clazz = super.findClass(name);
- } catch(AccessControlException ace) {
- log.warn(sm.getString("webappClassLoader.securityException", name,
- ace.getMessage()), ace);
- throw new ClassNotFoundException(name, ace);
- } catch (RuntimeException e) {
- if (log.isTraceEnabled())
- log.trace(" -->RuntimeException Rethrown", e);
- throw e;
- }
- }
- if (clazz == null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning ClassNotFoundException");
- throw new ClassNotFoundException(name);
- }
- } catch (ClassNotFoundException e) {
- if (log.isTraceEnabled())
- log.trace(" --> Passing on ClassNotFoundException");
- throw e;
- }
-
- // Return the class we have located
- if (log.isTraceEnabled())
- log.debug(" Returning class " + clazz);
-
- if (log.isTraceEnabled()) {
- ClassLoader cl;
- if (Globals.IS_SECURITY_ENABLED){
- cl = AccessController.doPrivileged(
- new PrivilegedGetClassLoader(clazz));
- } else {
- cl = clazz.getClassLoader();
- }
- log.debug(" Loaded by " + cl.toString());
- }
- return clazz;
-
- }
-
-
- /**
- * Find the specified resource in our local repository, and return a
- * <code>URL</code> referring to it, or <code>null</code> if this resource
- * cannot be found.
- *
- * @param name Name of the resource to be found
- */
- @Override
- public URL findResource(final String name) {
-
- if (log.isDebugEnabled())
- log.debug(" findResource(" + name + ")");
-
- checkStateForResourceLoading(name);
-
- URL url = null;
-
- String path = nameToPath(name);
-
- WebResource resource = resources.getClassLoaderResource(path);
- if (resource.exists()) {
- url = resource.getURL();
- trackLastModified(path, resource);
- }
-
- if ((url == null) && hasExternalRepositories) {
- url = super.findResource(name);
- }
-
- if (log.isDebugEnabled()) {
- if (url != null)
- log.debug(" --> Returning '" + url.toString() + "'");
- else
- log.debug(" --> Resource not found, returning null");
- }
- return url;
- }
-
-
- private void trackLastModified(String path, WebResource resource) {
- if (resourceEntries.containsKey(path)) {
- return;
- }
- ResourceEntry entry = new ResourceEntry();
- entry.lastModified = resource.getLastModified();
- synchronized(resourceEntries) {
- resourceEntries.putIfAbsent(path, entry);
- }
- }
-
-
- /**
- * Return an enumeration of <code>URLs</code> representing all of the
- * resources with the given name. If no resources with this name are
- * found, return an empty enumeration.
- *
- * @param name Name of the resources to be found
- *
- * @exception IOException if an input/output error occurs
- */
- @Override
- public Enumeration<URL> findResources(String name) throws IOException {
-
- if (log.isDebugEnabled())
- log.debug(" findResources(" + name + ")");
-
- checkStateForResourceLoading(name);
-
- LinkedHashSet<URL> result = new LinkedHashSet<>();
-
- String path = nameToPath(name);
-
- WebResource[] webResources = resources.getClassLoaderResources(path);
- for (WebResource webResource : webResources) {
- if (webResource.exists()) {
- result.add(webResource.getURL());
- }
- }
-
- // Adding the results of a call to the superclass
- if (hasExternalRepositories) {
- Enumeration<URL> otherResourcePaths = super.findResources(name);
- while (otherResourcePaths.hasMoreElements()) {
- result.add(otherResourcePaths.nextElement());
- }
- }
-
- return Collections.enumeration(result);
- }
-
-
- /**
- * Find the resource with the given name. A resource is some data
- * (images, audio, text, etc.) that can be accessed by class code in a
- * way that is independent of the location of the code. The name of a
- * resource is a "/"-separated path name that identifies the resource.
- * If the resource cannot be found, return <code>null</code>.
- * <p>
- * This method searches according to the following algorithm, returning
- * as soon as it finds the appropriate URL. If the resource cannot be
- * found, returns <code>null</code>.
- * <ul>
- * <li>If the <code>delegate</code> property is set to <code>true</code>,
- * call the <code>getResource()</code> method of the parent class
- * loader, if any.</li>
- * <li>Call <code>findResource()</code> to find this resource in our
- * locally defined repositories.</li>
- * <li>Call the <code>getResource()</code> method of the parent class
- * loader, if any.</li>
- * </ul>
- *
- * @param name Name of the resource to return a URL for
- */
- @Override
- public URL getResource(String name) {
-
- if (log.isDebugEnabled())
- log.debug("getResource(" + name + ")");
-
- checkStateForResourceLoading(name);
-
- URL url = null;
-
- boolean delegateFirst = delegate || filter(name, false);
-
- // (1) Delegate to parent if requested
- if (delegateFirst) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader " + parent);
- url = parent.getResource(name);
- if (url != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning '" + url.toString() + "'");
- return url;
- }
- }
-
- // (2) Search local repositories
- url = findResource(name);
- if (url != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning '" + url.toString() + "'");
- return url;
- }
-
- // (3) Delegate to parent unconditionally if not already attempted
- if (!delegateFirst) {
- url = parent.getResource(name);
- if (url != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning '" + url.toString() + "'");
- return url;
- }
- }
-
- // (4) Resource was not found
- if (log.isDebugEnabled())
- log.debug(" --> Resource not found, returning null");
- return null;
-
- }
-
-
- @Override
- public Enumeration<URL> getResources(String name) throws IOException {
-
- Enumeration<URL> parentResources = getParent().getResources(name);
- Enumeration<URL> localResources = findResources(name);
-
- // Need to combine these enumerations. The order in which the
- // Enumerations are combined depends on how delegation is configured
- boolean delegateFirst = delegate || filter(name, false);
-
- if (delegateFirst) {
- return new CombinedEnumeration(parentResources, localResources);
- } else {
- return new CombinedEnumeration(localResources, parentResources);
- }
- }
-
-
- /**
- * Find the resource with the given name, and return an input stream
- * that can be used for reading it. The search order is as described
- * for <code>getResource()</code>, after checking to see if the resource
- * data has been previously cached. If the resource cannot be found,
- * return <code>null</code>.
- *
- * @param name Name of the resource to return an input stream for
- */
- @Override
- public InputStream getResourceAsStream(String name) {
-
- if (log.isDebugEnabled())
- log.debug("getResourceAsStream(" + name + ")");
-
- checkStateForResourceLoading(name);
-
- InputStream stream = null;
-
- boolean delegateFirst = delegate || filter(name, false);
-
- // (1) Delegate to parent if requested
- if (delegateFirst) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader " + parent);
- stream = parent.getResourceAsStream(name);
- if (stream != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from parent");
- return stream;
- }
- }
-
- // (2) Search local repositories
- if (log.isDebugEnabled())
- log.debug(" Searching local repositories");
- String path = nameToPath(name);
- WebResource resource = resources.getClassLoaderResource(path);
- if (resource.exists()) {
- stream = resource.getInputStream();
- trackLastModified(path, resource);
- }
- try {
- if (hasExternalRepositories && stream == null) {
- URL url = super.findResource(name);
- if (url != null) {
- stream = url.openStream();
- }
- }
- } catch (IOException e) {
- // Ignore
- }
- if (stream != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from local");
- return stream;
- }
-
- // (3) Delegate to parent unconditionally
- if (!delegateFirst) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader unconditionally " + parent);
- stream = parent.getResourceAsStream(name);
- if (stream != null) {
- if (log.isDebugEnabled())
- log.debug(" --> Returning stream from parent");
- return stream;
- }
- }
-
- // (4) Resource was not found
- if (log.isDebugEnabled())
- log.debug(" --> Resource not found, returning null");
- return null;
- }
-
-
- /**
- * Load the class with the specified name. This method searches for
- * classes in the same manner as <code>loadClass(String, boolean)</code>
- * with <code>false</code> as the second argument.
- *
- * @param name The binary name of the class to be loaded
- *
- * @exception ClassNotFoundException if the class was not found
- */
- @Override
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- return loadClass(name, false);
- }
-
-
- /**
- * Load the class with the specified name, searching using the following
- * algorithm until it finds and returns the class. If the class cannot
- * be found, returns <code>ClassNotFoundException</code>.
- * <ul>
- * <li>Call <code>findLoadedClass(String)</code> to check if the
- * class has already been loaded. If it has, the same
- * <code>Class</code> object is returned.</li>
- * <li>If the <code>delegate</code> property is set to <code>true</code>,
- * call the <code>loadClass()</code> method of the parent class
- * loader, if any.</li>
- * <li>Call <code>findClass()</code> to find this class in our locally
- * defined repositories.</li>
- * <li>Call the <code>loadClass()</code> method of our parent
- * class loader, if any.</li>
- * </ul>
- * If the class was found using the above steps, and the
- * <code>resolve</code> flag is <code>true</code>, this method will then
- * call <code>resolveClass(Class)</code> on the resulting Class object.
- *
- * @param name The binary name of the class to be loaded
- * @param resolve If <code>true</code> then resolve the class
- *
- * @exception ClassNotFoundException if the class was not found
- */
- @Override
- public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-
- synchronized (JreCompat.isGraalAvailable() ? this : getClassLoadingLock(name)) {
- if (log.isDebugEnabled())
- log.debug("loadClass(" + name + ", " + resolve + ")");
- Class<?> clazz = null;
-
- // Log access to stopped class loader
- checkStateForClassLoading(name);
-
- // (0) Check our previously loaded local class cache
- clazz = findLoadedClass0(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Returning class from cache");
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
-
- // (0.1) Check our previously loaded class cache
- clazz = JreCompat.isGraalAvailable() ? null : findLoadedClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Returning class from cache");
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
-
- // (0.2) Try loading the class with the system class loader, to prevent
- // the webapp from overriding Java SE classes. This implements
- // SRV.10.7.2
- String resourceName = binaryNameToPath(name, false);
-
- ClassLoader javaseLoader = getJavaseClassLoader();
- boolean tryLoadingFromJavaseLoader;
- try {
- // Use getResource as it won't trigger an expensive
- // ClassNotFoundException if the resource is not available from
- // the Java SE class loader. However (see
- // https://bz.apache.org/bugzilla/show_bug.cgi?id=58125 for
- // details) when running under a security manager in rare cases
- // this call may trigger a ClassCircularityError.
- // See https://bz.apache.org/bugzilla/show_bug.cgi?id=61424 for
- // details of how this may trigger a StackOverflowError
- // Given these reported errors, catch Throwable to ensure any
- // other edge cases are also caught
- URL url;
- if (securityManager != null) {
- PrivilegedAction<URL> dp = new PrivilegedJavaseGetResource(resourceName);
- url = AccessController.doPrivileged(dp);
- } else {
- url = javaseLoader.getResource(resourceName);
- }
- tryLoadingFromJavaseLoader = (url != null);
- } catch (Throwable t) {
- // Swallow all exceptions apart from those that must be re-thrown
- ExceptionUtils.handleThrowable(t);
- // The getResource() trick won't work for this class. We have to
- // try loading it directly and accept that we might get a
- // ClassNotFoundException.
- tryLoadingFromJavaseLoader = true;
- }
-
- if (tryLoadingFromJavaseLoader) {
- try {
- clazz = javaseLoader.loadClass(name);
- if (clazz != null) {
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
- } catch (ClassNotFoundException e) {
- // Ignore
- }
- }
-
- // (0.5) Permission to access this class when using a SecurityManager
- if (securityManager != null) {
- int i = name.lastIndexOf('.');
- if (i >= 0) {
- try {
- securityManager.checkPackageAccess(name.substring(0,i));
- } catch (SecurityException se) {
- String error = sm.getString("webappClassLoader.restrictedPackage", name);
- log.info(error, se);
- throw new ClassNotFoundException(error, se);
- }
- }
- }
-
- boolean delegateLoad = delegate || filter(name, true);
-
- // (1) Delegate to our parent if requested
- if (delegateLoad) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader1 " + parent);
- try {
- clazz = Class.forName(name, false, parent);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from parent");
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
- } catch (ClassNotFoundException e) {
- // Ignore
- }
- }
-
- // (2) Search local repositories
- if (log.isDebugEnabled())
- log.debug(" Searching local repositories");
- try {
- clazz = findClass(name);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from local repository");
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
- } catch (ClassNotFoundException e) {
- // Ignore
- }
-
- // (3) Delegate to parent unconditionally
- if (!delegateLoad) {
- if (log.isDebugEnabled())
- log.debug(" Delegating to parent classloader at end: " + parent);
- try {
- clazz = Class.forName(name, false, parent);
- if (clazz != null) {
- if (log.isDebugEnabled())
- log.debug(" Loading class from parent");
- if (resolve)
- resolveClass(clazz);
- return clazz;
- }
- } catch (ClassNotFoundException e) {
- // Ignore
- }
- }
- }
-
- throw new ClassNotFoundException(name);
- }
-
-
- protected void checkStateForClassLoading(String className) throws ClassNotFoundException {
- // It is not permitted to load new classes once the web application has
- // been stopped.
- try {
- checkStateForResourceLoading(className);
- } catch (IllegalStateException ise) {
- throw new ClassNotFoundException(ise.getMessage(), ise);
- }
- }
-
-
- protected void checkStateForResourceLoading(String resource) throws IllegalStateException {
- // It is not permitted to load resources once the web application has
- // been stopped.
- if (!state.isAvailable()) {
- String msg = sm.getString("webappClassLoader.stopped", resource);
- IllegalStateException ise = new IllegalStateException(msg);
- log.info(msg, ise);
- throw ise;
- }
- }
-
- /**
- * Get the Permissions for a CodeSource. If this instance
- * of WebappClassLoaderBase is for a web application context,
- * add read FilePermission for the appropriate resources.
- *
- * @param codeSource where the code was loaded from
- * @return PermissionCollection for CodeSource
- */
- @Override
- protected PermissionCollection getPermissions(CodeSource codeSource) {
- String codeUrl = codeSource.getLocation().toString();
- PermissionCollection pc;
- if ((pc = loaderPC.get(codeUrl)) == null) {
- pc = super.getPermissions(codeSource);
- if (pc != null) {
- for (Permission p : permissionList) {
- pc.add(p);
- }
- loaderPC.put(codeUrl,pc);
- }
- }
- return pc;
- }
-
-
- @Override
- public boolean check(Permission permission) {
- if (!Globals.IS_SECURITY_ENABLED) {
- return true;
- }
- Policy currentPolicy = Policy.getPolicy();
- if (currentPolicy != null) {
- URL contextRootUrl = resources.getResource("/").getCodeBase();
- CodeSource cs = new CodeSource(contextRootUrl, (Certificate[]) null);
- PermissionCollection pc = currentPolicy.getPermissions(cs);
- if (pc.implies(permission)) {
- return true;
- }
- }
- return false;
- }
-
-
- /**
- * {@inheritDoc}
- * <p>
- * Note that list of URLs returned by this method may not be complete. The
- * web application class loader accesses class loader resources via the
- * {@link WebResourceRoot} which supports the arbitrary mapping of
- * additional files, directories and contents of JAR files under
- * WEB-INF/classes. Any such resources will not be included in the URLs
- * returned here.
- */
- @Override
- public URL[] getURLs() {
- ArrayList<URL> result = new ArrayList<>();
- result.addAll(localRepositories);
- result.addAll(Arrays.asList(super.getURLs()));
- return result.toArray(new URL[0]);
- }
-
-
- // ------------------------------------------------------ Lifecycle Methods
-
-
- /**
- * Add a lifecycle event listener to this component.
- *
- * @param listener The listener to add
- */
- @Override
- public void addLifecycleListener(LifecycleListener listener) {
- // NOOP
- }
-
-
- /**
- * Get the lifecycle listeners associated with this lifecycle. If this
- * Lifecycle has no listeners registered, a zero-length array is returned.
- */
- @Override
- public LifecycleListener[] findLifecycleListeners() {
- return new LifecycleListener[0];
- }
-
-
- /**
- * Remove a lifecycle event listener from this component.
- *
- * @param listener The listener to remove
- */
- @Override
- public void removeLifecycleListener(LifecycleListener listener) {
- // NOOP
- }
-
-
- /**
- * Obtain the current state of the source component.
- *
- * @return The current state of the source component.
- */
- @Override
- public LifecycleState getState() {
- return state;
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getStateName() {
- return getState().toString();
- }
-
-
- @Override
- public void init() {
- state = LifecycleState.INITIALIZED;
- }
-
-
- /**
- * Start the class loader.
- *
- * @exception LifecycleException if a lifecycle error occurs
- */
- @Override
- public void start() throws LifecycleException {
-
- state = LifecycleState.STARTING_PREP;
-
- WebResource[] classesResources = resources.getResources("/WEB-INF/classes");
- for (WebResource classes : classesResources) {
- if (classes.isDirectory() && classes.canRead()) {
- localRepositories.add(classes.getURL());
- }
- }
- WebResource[] jars = resources.listResources("/WEB-INF/lib");
- for (WebResource jar : jars) {
- if (jar.getName().endsWith(".jar") && jar.isFile() && jar.canRead()) {
- localRepositories.add(jar.getURL());
- jarModificationTimes.put(
- jar.getName(), Long.valueOf(jar.getLastModified()));
- }
- }
-
- state = LifecycleState.STARTED;
- }
-
-
- /**
- * Stop the class loader.
- *
- * @exception LifecycleException if a lifecycle error occurs
- */
- @Override
- public void stop() throws LifecycleException {
-
- state = LifecycleState.STOPPING_PREP;
-
- // Clearing references should be done before setting started to
- // false, due to possible side effects
- clearReferences();
-
- state = LifecycleState.STOPPING;
-
- resourceEntries.clear();
- jarModificationTimes.clear();
- resources = null;
-
- permissionList.clear();
- loaderPC.clear();
-
- state = LifecycleState.STOPPED;
- }
-
-
- @Override
- public void destroy() {
- state = LifecycleState.DESTROYING;
-
- try {
- super.close();
- } catch (IOException ioe) {
- log.warn(sm.getString("webappClassLoader.superCloseFail"), ioe);
- }
- state = LifecycleState.DESTROYED;
- }
-
-
- // ------------------------------------------------------ Protected Methods
-
- protected ClassLoader getJavaseClassLoader() {
- return javaseClassLoader;
- }
-
- protected void setJavaseClassLoader(ClassLoader classLoader) {
- if (classLoader == null) {
- throw new IllegalArgumentException(
- sm.getString("webappClassLoader.javaseClassLoaderNull"));
- }
- javaseClassLoader = classLoader;
- }
-
- /**
- * Clear references.
- */
- protected void clearReferences() {
-
- // If the JVM is shutting down, skip the memory leak checks
- if (skipMemoryLeakChecksOnJvmShutdown
- && !resources.getContext().getParent().getState().isAvailable()) {
- // During reloading / redeployment the parent is expected to be
- // available. Parent is not available so this might be a JVM
- // shutdown.
- try {
- Thread dummyHook = new Thread();
- Runtime.getRuntime().addShutdownHook(dummyHook);
- Runtime.getRuntime().removeShutdownHook(dummyHook);
- } catch (IllegalStateException ise) {
- return;
- }
- }
-
- if (!JreCompat.isGraalAvailable()) {
- // De-register any remaining JDBC drivers
- clearReferencesJdbc();
- }
-
- // Stop any threads the web application started
- clearReferencesThreads();
-
- // Clear any references retained in the serialization caches
- if (clearReferencesObjectStreamClassCaches && !JreCompat.isGraalAvailable()) {
- clearReferencesObjectStreamClassCaches();
- }
-
- // Check for leaks triggered by ThreadLocals loaded by this class loader
- if (clearReferencesThreadLocals && !JreCompat.isGraalAvailable()) {
- checkThreadLocalsForLeaks();
- }
-
- // Clear RMI Targets loaded by this class loader
- if (clearReferencesRmiTargets) {
- clearReferencesRmiTargets();
- }
-
- // Clear the IntrospectionUtils cache.
- IntrospectionUtils.clear();
-
- // Clear the classloader reference in common-logging
- if (clearReferencesLogFactoryRelease) {
- org.apache.juli.logging.LogFactory.release(this);
- }
-
- // Clear the classloader reference in the VM's bean introspector
- java.beans.Introspector.flushCaches();
-
- // Clear any custom URLStreamHandlers
- TomcatURLStreamHandlerFactory.release(this);
- }
-
-
- /**
- * Deregister any JDBC drivers registered by the webapp that the webapp
- * forgot. This is made unnecessary complex because a) DriverManager
- * checks the class loader of the calling class (it would be much easier
- * if it checked the context class loader) b) using reflection would
- * create a dependency on the DriverManager implementation which can,
- * and has, changed.
- *
- * We can't just create an instance of JdbcLeakPrevention as it will be
- * loaded by the common class loader (since it's .class file is in the
- * $CATALINA_HOME/lib directory). This would fail DriverManager's check
- * on the class loader of the calling class. So, we load the bytes via
- * our parent class loader but define the class with this class loader
- * so the JdbcLeakPrevention looks like a webapp class to the
- * DriverManager.
- *
- * If only apps cleaned up after themselves...
- */
- private final void clearReferencesJdbc() {
- // We know roughly how big the class will be (~ 1K) so allow 2k as a
- // starting point
- byte[] classBytes = new byte[2048];
- int offset = 0;
- try (InputStream is = getResourceAsStream(
- "org/apache/catalina/loader/JdbcLeakPrevention.class")) {
- int read = is.read(classBytes, offset, classBytes.length-offset);
- while (read > -1) {
- offset += read;
- if (offset == classBytes.length) {
- // Buffer full - double size
- byte[] tmp = new byte[classBytes.length * 2];
- System.arraycopy(classBytes, 0, tmp, 0, classBytes.length);
- classBytes = tmp;
- }
- read = is.read(classBytes, offset, classBytes.length-offset);
- }
- Class<?> lpClass =
- defineClass("org.apache.catalina.loader.JdbcLeakPrevention",
- classBytes, 0, offset, this.getClass().getProtectionDomain());
- Object obj = lpClass.getConstructor().newInstance();
- @SuppressWarnings("unchecked")
- List<String> driverNames = (List<String>) obj.getClass().getMethod(
- "clearJdbcDriverRegistrations").invoke(obj);
- for (String name : driverNames) {
- log.warn(sm.getString("webappClassLoader.clearJdbc",
- getContextName(), name));
- }
- } catch (Exception e) {
- // So many things to go wrong above...
- Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
- ExceptionUtils.handleThrowable(t);
- log.warn(sm.getString(
- "webappClassLoader.jdbcRemoveFailed", getContextName()), t);
- }
- }
-
-
- @SuppressWarnings("deprecation") // thread.stop()
- private void clearReferencesThreads() {
- Thread[] threads = getThreads();
- List<Thread> threadsToStop = new ArrayList<>();
-
- // Iterate over the set of threads
- for (Thread thread : threads) {
- if (thread != null) {
- ClassLoader ccl = thread.getContextClassLoader();
- if (ccl == this) {
- // Don't warn about this thread
- if (thread == Thread.currentThread()) {
- continue;
- }
-
- final String threadName = thread.getName();
-
- // JVM controlled threads
- ThreadGroup tg = thread.getThreadGroup();
- if (tg != null && JVM_THREAD_GROUP_NAMES.contains(tg.getName())) {
- // HttpClient keep-alive threads
- if (clearReferencesHttpClientKeepAliveThread &&
- threadName.equals("Keep-Alive-Timer")) {
- thread.setContextClassLoader(parent);
- log.debug(sm.getString("webappClassLoader.checkThreadsHttpClient"));
- }
-
- // Don't warn about remaining JVM controlled threads
- continue;
- }
-
- // Skip threads that have already died
- if (!thread.isAlive()) {
- continue;
- }
-
- // TimerThread can be stopped safely so treat separately
- // "java.util.TimerThread" in Sun/Oracle JDK
- // "java.util.Timer$TimerImpl" in Apache Harmony and in IBM JDK
- if (thread.getClass().getName().startsWith("java.util.Timer") &&
- clearReferencesStopTimerThreads) {
- clearReferencesStopTimerThread(thread);
- continue;
- }
-
- if (isRequestThread(thread)) {
- log.warn(sm.getString("webappClassLoader.stackTraceRequestThread",
- getContextName(), threadName, getStackTrace(thread)));
- } else {
- log.warn(sm.getString("webappClassLoader.stackTrace",
- getContextName(), threadName, getStackTrace(thread)));
- }
-
- // Don't try and stop the threads unless explicitly
- // configured to do so
- if (!clearReferencesStopThreads) {
- continue;
- }
-
- // If the thread has been started via an executor, try
- // shutting down the executor
- boolean usingExecutor = false;
- try {
-
- // Runnable wrapped by Thread
- // "target" in Sun/Oracle JDK
- // "runnable" in IBM JDK
- // "action" in Apache Harmony
- Object target = null;
- for (String fieldName : new String[] { "target", "runnable", "action" }) {
- try {
- Field targetField = thread.getClass().getDeclaredField(fieldName);
- targetField.setAccessible(true);
- target = targetField.get(thread);
- break;
- } catch (NoSuchFieldException nfe) {
- continue;
- }
- }
-
- // "java.util.concurrent" code is in public domain,
- // so all implementations are similar
- if (target != null && target.getClass().getCanonicalName() != null &&
- target.getClass().getCanonicalName().equals(
- "java.util.concurrent.ThreadPoolExecutor.Worker")) {
- Field executorField = target.getClass().getDeclaredField("this$0");
- executorField.setAccessible(true);
- Object executor = executorField.get(target);
- if (executor instanceof ThreadPoolExecutor) {
- ((ThreadPoolExecutor) executor).shutdownNow();
- usingExecutor = true;
- }
- }
- } catch (SecurityException | NoSuchFieldException | IllegalArgumentException |
- IllegalAccessException e) {
- log.warn(sm.getString("webappClassLoader.stopThreadFail",
- thread.getName(), getContextName()), e);
- }
-
- // Stopping an executor automatically interrupts the
- // associated threads. For non-executor threads, interrupt
- // them here.
- if (!usingExecutor && !thread.isInterrupted()) {
- thread.interrupt();
- }
-
- // Threads are expected to take a short time to stop after
- // being interrupted. Make a note of all threads that are
- // expected to stop to enable them to be checked at the end
- // of this method.
- threadsToStop.add(thread);
- }
- }
- }
-
- // If thread stopping is enabled, threads should have been stopped above
- // when the executor was shut down or the thread was interrupted but
- // that depends on the thread correctly handling the interrupt. Check
- // each thread and if any are still running give all threads up to a
- // total of 2 seconds to shutdown.
- int count = 0;
- for (Thread t : threadsToStop) {
- while (t.isAlive() && count < 100) {
- try {
- Thread.sleep(20);
- } catch (InterruptedException e) {
- // Quit the while loop
- break;
- }
- count++;
- }
- if (t.isAlive()) {
- // This method is deprecated and for good reason. This is
- // very risky code but is the only option at this point.
- // A *very* good reason for apps to do this clean-up
- // themselves.
- t.stop();
- }
- }
- }
-
-
- /*
- * Look at a threads stack trace to see if it is a request thread or not. It
- * isn't perfect, but it should be good-enough for most cases.
- */
- private boolean isRequestThread(Thread thread) {
-
- StackTraceElement[] elements = thread.getStackTrace();
-
- if (elements == null || elements.length == 0) {
- // Must have stopped already. Too late to ignore it. Assume not a
- // request processing thread.
- return false;
- }
-
- // Step through the methods in reverse order looking for calls to any
- // CoyoteAdapter method. All request threads will have this unless
- // Tomcat has been heavily modified - in which case there isn't much we
- // can do.
- for (int i = 0; i < elements.length; i++) {
- StackTraceElement element = elements[elements.length - (i+1)];
- if ("org.apache.catalina.connector.CoyoteAdapter".equals(
- element.getClassName())) {
- return true;
- }
- }
- return false;
- }
-
-
- private void clearReferencesStopTimerThread(Thread thread) {
-
- // Need to get references to:
- // in Sun/Oracle JDK:
- // - newTasksMayBeScheduled field (in java.util.TimerThread)
- // - queue field
- // - queue.clear()
- // in IBM JDK, Apache Harmony:
- // - cancel() method (in java.util.Timer$TimerImpl)
-
- try {
-
- try {
- Field newTasksMayBeScheduledField =
- thread.getClass().getDeclaredField("newTasksMayBeScheduled");
- newTasksMayBeScheduledField.setAccessible(true);
- Field queueField = thread.getClass().getDeclaredField("queue");
- queueField.setAccessible(true);
-
- Object queue = queueField.get(thread);
-
- Method clearMethod = queue.getClass().getDeclaredMethod("clear");
- clearMethod.setAccessible(true);
-
- synchronized(queue) {
- newTasksMayBeScheduledField.setBoolean(thread, false);
- clearMethod.invoke(queue);
- // In case queue was already empty. Should only be one
- // thread waiting but use notifyAll() to be safe.
- queue.notifyAll();
- }
-
- }catch (NoSuchFieldException nfe){
- Method cancelMethod = thread.getClass().getDeclaredMethod("cancel");
- synchronized(thread) {
- cancelMethod.setAccessible(true);
- cancelMethod.invoke(thread);
- }
- }
-
- log.warn(sm.getString("webappClassLoader.warnTimerThread",
- getContextName(), thread.getName()));
-
- } catch (Exception e) {
- // So many things to go wrong above...
- Throwable t = ExceptionUtils.unwrapInvocationTargetException(e);
- ExceptionUtils.handleThrowable(t);
- log.warn(sm.getString(
- "webappClassLoader.stopTimerThreadFail",
- thread.getName(), getContextName()), t);
- }
- }
-
- private void checkThreadLocalsForLeaks() {
- Thread[] threads = getThreads();
-
- try {
- // Make the fields in the Thread class that store ThreadLocals
- // accessible
- Field threadLocalsField =
- Thread.class.getDeclaredField("threadLocals");
- threadLocalsField.setAccessible(true);
- Field inheritableThreadLocalsField =
- Thread.class.getDeclaredField("inheritableThreadLocals");
- inheritableThreadLocalsField.setAccessible(true);
- // Make the underlying array of ThreadLoad.ThreadLocalMap.Entry objects
- // accessible
- Class<?> tlmClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
- Field tableField = tlmClass.getDeclaredField("table");
- tableField.setAccessible(true);
- Method expungeStaleEntriesMethod = tlmClass.getDeclaredMethod("expungeStaleEntries");
- expungeStaleEntriesMethod.setAccessible(true);
-
- for (Thread thread : threads) {
- Object threadLocalMap;
- if (thread != null) {
-
- // Clear the first map
- threadLocalMap = threadLocalsField.get(thread);
- if (null != threadLocalMap) {
- expungeStaleEntriesMethod.invoke(threadLocalMap);
- checkThreadLocalMapForLeaks(threadLocalMap, tableField);
- }
-
- // Clear the second map
- threadLocalMap = inheritableThreadLocalsField.get(thread);
- if (null != threadLocalMap) {
- expungeStaleEntriesMethod.invoke(threadLocalMap);
- checkThreadLocalMapForLeaks(threadLocalMap, tableField);
- }
- }
- }
- } catch (Throwable t) {
- JreCompat jreCompat = JreCompat.getInstance();
- if (jreCompat.isInstanceOfInaccessibleObjectException(t)) {
- // Must be running on Java 9 without the necessary command line
- // options.
- log.warn(sm.getString("webappClassLoader.addExportsThreadLocal"));
- } else {
- ExceptionUtils.handleThrowable(t);
- log.warn(sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaksFail",
- getContextName()), t);
- }
- }
- }
-
-
- /**
- * Analyzes the given thread local map object. Also pass in the field that
- * points to the internal table to save re-calculating it on every
- * call to this method.
- */
- private void checkThreadLocalMapForLeaks(Object map,
- Field internalTableField) throws IllegalAccessException,
- NoSuchFieldException {
- if (map != null) {
- Object[] table = (Object[]) internalTableField.get(map);
- if (table != null) {
- for (Object obj : table) {
- if (obj != null) {
- boolean keyLoadedByWebapp = false;
- boolean valueLoadedByWebapp = false;
- // Check the key
- Object key = ((Reference<?>) obj).get();
- if (this.equals(key) || loadedByThisOrChild(key)) {
- keyLoadedByWebapp = true;
- }
- // Check the value
- Field valueField =
- obj.getClass().getDeclaredField("value");
- valueField.setAccessible(true);
- Object value = valueField.get(obj);
- if (this.equals(value) || loadedByThisOrChild(value)) {
- valueLoadedByWebapp = true;
- }
- if (keyLoadedByWebapp || valueLoadedByWebapp) {
- Object[] args = new Object[5];
- args[0] = getContextName();
- if (key != null) {
- args[1] = getPrettyClassName(key.getClass());
- try {
- args[2] = key.toString();
- } catch (Exception e) {
- log.warn(sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaks.badKey",
- args[1]), e);
- args[2] = sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaks.unknown");
- }
- }
- if (value != null) {
- args[3] = getPrettyClassName(value.getClass());
- try {
- args[4] = value.toString();
- } catch (Exception e) {
- log.warn(sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaks.badValue",
- args[3]), e);
- args[4] = sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaks.unknown");
- }
- }
- if (valueLoadedByWebapp) {
- log.error(sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaks",
- args));
- } else if (value == null) {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaksNull",
- args));
- }
- } else {
- if (log.isDebugEnabled()) {
- log.debug(sm.getString(
- "webappClassLoader.checkThreadLocalsForLeaksNone",
- args));
- }
- }
- }
- }
- }
- }
- }
- }
-
- private String getPrettyClassName(Class<?> clazz) {
- String name = clazz.getCanonicalName();
- if (name==null){
- name = clazz.getName();
- }
- return name;
- }
-
- private String getStackTrace(Thread thread) {
- StringBuilder builder = new StringBuilder();
- for (StackTraceElement ste : thread.getStackTrace()) {
- builder.append("\n ").append(ste);
- }
- return builder.toString();
- }
-
- /**
- * @param o object to test, may be null
- * @return <code>true</code> if o has been loaded by the current classloader
- * or one of its descendants.
- */
- private boolean loadedByThisOrChild(Object o) {
- if (o == null) {
- return false;
- }
-
- Class<?> clazz;
- if (o instanceof Class) {
- clazz = (Class<?>) o;
- } else {
- clazz = o.getClass();
- }
-
- ClassLoader cl = clazz.getClassLoader();
- while (cl != null) {
- if (cl == this) {
- return true;
- }
- cl = cl.getParent();
- }
-
- if (o instanceof Collection<?>) {
- Iterator<?> iter = ((Collection<?>) o).iterator();
- try {
- while (iter.hasNext()) {
- Object entry = iter.next();
- if (loadedByThisOrChild(entry)) {
- return true;
- }
- }
- } catch (ConcurrentModificationException e) {
- log.warn(sm.getString(
- "webappClassLoader.loadedByThisOrChildFail", clazz.getName(), getContextName()),
- e);
- }
- }
- return false;
- }
-
- /*
- * Get the set of current threads as an array.
- */
- private Thread[] getThreads() {
- // Get the current thread group
- ThreadGroup tg = Thread.currentThread().getThreadGroup();
- // Find the root thread group
- try {
- while (tg.getParent() != null) {
- tg = tg.getParent();
- }
- } catch (SecurityException se) {
- String msg = sm.getString(
- "webappClassLoader.getThreadGroupError", tg.getName());
- if (log.isDebugEnabled()) {
- log.debug(msg, se);
- } else {
- log.warn(msg);
- }
- }
-
- int threadCountGuess = tg.activeCount() + 50;
- Thread[] threads = new Thread[threadCountGuess];
- int threadCountActual = tg.enumerate(threads);
- // Make sure we don't miss any threads
- while (threadCountActual == threadCountGuess) {
- threadCountGuess *=2;
- threads = new Thread[threadCountGuess];
- // Note tg.enumerate(Thread[]) silently ignores any threads that
- // can't fit into the array
- threadCountActual = tg.enumerate(threads);
- }
-
- return threads;
- }
-
-
- /**
- * This depends on the internals of the Sun JVM so it does everything by
- * reflection.
- */
- private void clearReferencesRmiTargets() {
- try {
- // Need access to the ccl field of sun.rmi.transport.Target to find
- // the leaks
- Class<?> objectTargetClass =
- Class.forName("sun.rmi.transport.Target");
- Field cclField = objectTargetClass.getDeclaredField("ccl");
- cclField.setAccessible(true);
- // Need access to the stub field to report the leaks
- Field stubField = objectTargetClass.getDeclaredField("stub");
- stubField.setAccessible(true);
-
- // Clear the objTable map
- Class<?> objectTableClass = Class.forName("sun.rmi.transport.ObjectTable");
- Field objTableField = objectTableClass.getDeclaredField("objTable");
- objTableField.setAccessible(true);
- Object objTable = objTableField.get(null);
- if (objTable == null) {
- return;
- }
- Field tableLockField = objectTableClass.getDeclaredField("tableLock");
- tableLockField.setAccessible(true);
- Object tableLock = tableLockField.get(null);
-
- synchronized (tableLock) {
- // Iterate over the values in the table
- if (objTable instanceof Map<?,?>) {
- Iterator<?> iter = ((Map<?,?>) objTable).values().iterator();
- while (iter.hasNext()) {
- Object obj = iter.next();
- Object cclObject = cclField.get(obj);
- if (this == cclObject) {
- iter.remove();
- Object stubObject = stubField.get(obj);
- log.error(sm.getString("webappClassLoader.clearRmi",
- stubObject.getClass().getName(), stubObject));
- }
- }
- }
-
- // Clear the implTable map
- Field implTableField = objectTableClass.getDeclaredField("implTable");
- implTableField.setAccessible(true);
- Object implTable = implTableField.get(null);
- if (implTable == null) {
- return;
- }
-
- // Iterate over the values in the table
- if (implTable instanceof Map<?,?>) {
- Iterator<?> iter = ((Map<?,?>) implTable).values().iterator();
- while (iter.hasNext()) {
- Object obj = iter.next();
- Object cclObject = cclField.get(obj);
- if (this == cclObject) {
- iter.remove();
- }
- }
- }
- }
- } catch (ClassNotFoundException e) {
- log.info(sm.getString("webappClassLoader.clearRmiInfo",
- getContextName()), e);
- } catch (SecurityException | NoSuchFieldException | IllegalArgumentException |
- IllegalAccessException e) {
- log.warn(sm.getString("webappClassLoader.clearRmiFail",
- getContextName()), e);
- } catch (Exception e) {
- JreCompat jreCompat = JreCompat.getInstance();
- if (jreCompat.isInstanceOfInaccessibleObjectException(e)) {
- // Must be running on Java 9 without the necessary command line
- // options.
- log.warn(sm.getString("webappClassLoader.addExportsRmi"));
- } else {
- // Re-throw all other exceptions
- throw e;
- }
- }
- }
-
-
- private void clearReferencesObjectStreamClassCaches() {
- try {
- Class<?> clazz = Class.forName("java.io.ObjectStreamClass$Caches");
- clearCache(clazz, "localDescs");
- clearCache(clazz, "reflectors");
- } catch (ReflectiveOperationException | SecurityException | ClassCastException e) {
- log.warn(sm.getString(
- "webappClassLoader.clearObjectStreamClassCachesFail", getContextName()), e);
- }
- }
-
-
- private void clearCache(Class<?> target, String mapName)
- throws ReflectiveOperationException, SecurityException, ClassCastException {
- Field f = target.getDeclaredField(mapName);
- f.setAccessible(true);
- Map<?,?> map = (Map<?,?>) f.get(null);
- Iterator<?> keys = map.keySet().iterator();
- while (keys.hasNext()) {
- Object key = keys.next();
- if (key instanceof Reference) {
- Object clazz = ((Reference<?>) key).get();
- if (loadedByThisOrChild(clazz)) {
- keys.remove();
- }
- }
- }
- }
-
-
- /**
- * Find specified class in local repositories.
- *
- * @param name The binary name of the class to be loaded
- *
- * @return the loaded class, or null if the class isn't found
- */
- protected Class<?> findClassInternal(String name) {
-
- checkStateForResourceLoading(name);
-
- if (name == null) {
- return null;
- }
- String path = binaryNameToPath(name, true);
-
- ResourceEntry entry = resourceEntries.get(path);
- WebResource resource = null;
-
- if (entry == null) {
- resource = resources.getClassLoaderResource(path);
-
- if (!resource.exists()) {
- return null;
- }
-
- entry = new ResourceEntry();
- entry.lastModified = resource.getLastModified();
-
- // Add the entry in the local resource repository
- synchronized (resourceEntries) {
- // Ensures that all the threads which may be in a race to load
- // a particular class all end up with the same ResourceEntry
- // instance
- ResourceEntry entry2 = resourceEntries.get(path);
- if (entry2 == null) {
- resourceEntries.put(path, entry);
- } else {
- entry = entry2;
- }
- }
- }
-
- Class<?> clazz = entry.loadedClass;
- if (clazz != null)
- return clazz;
-
- synchronized (JreCompat.isGraalAvailable() ? this : getClassLoadingLock(name)) {
- clazz = entry.loadedClass;
- if (clazz != null)
- return clazz;
-
- if (resource == null) {
- resource = resources.getClassLoaderResource(path);
- }
-
- if (!resource.exists()) {
- return null;
- }
-
- byte[] binaryContent = resource.getContent();
- if (binaryContent == null) {
- // Something went wrong reading the class bytes (and will have
- // been logged at debug level).
- return null;
- }
- Manifest manifest = resource.getManifest();
- URL codeBase = resource.getCodeBase();
- Certificate[] certificates = resource.getCertificates();
-
- if (transformers.size() > 0) {
- // If the resource is a class just being loaded, decorate it
- // with any attached transformers
-
- // Ignore leading '/' and trailing CLASS_FILE_SUFFIX
- // Should be cheaper than replacing '.' by '/' in class name.
- String internalName = path.substring(1, path.length() - CLASS_FILE_SUFFIX.length());
-
- for (ClassFileTransformer transformer : this.transformers) {
- try {
- byte[] transformed = transformer.transform(
- this, internalName, null, null, binaryContent);
- if (transformed != null) {
- binaryContent = transformed;
- }
- } catch (IllegalClassFormatException e) {
- log.error(sm.getString("webappClassLoader.transformError", name), e);
- return null;
- }
- }
- }
-
- // Looking up the package
- String packageName = null;
- int pos = name.lastIndexOf('.');
- if (pos != -1)
- packageName = name.substring(0, pos);
-
- Package pkg = null;
-
- if (packageName != null) {
- pkg = getPackage(packageName);
- // Define the package (if null)
- if (pkg == null) {
- try {
- if (manifest == null) {
- definePackage(packageName, null, null, null, null, null, null, null);
- } else {
- definePackage(packageName, manifest, codeBase);
- }
- } catch (IllegalArgumentException e) {
- // Ignore: normal error due to dual definition of package
- }
- pkg = getPackage(packageName);
- }
- }
-
- if (securityManager != null) {
-
- // Checking sealing
- if (pkg != null) {
- boolean sealCheck = true;
- if (pkg.isSealed()) {
- sealCheck = pkg.isSealed(codeBase);
- } else {
- sealCheck = (manifest == null) || !isPackageSealed(packageName, manifest);
- }
- if (!sealCheck)
- throw new SecurityException
- ("Sealing violation loading " + name + " : Package "
- + packageName + " is sealed.");
- }
-
- }
-
- try {
- clazz = defineClass(name, binaryContent, 0,
- binaryContent.length, new CodeSource(codeBase, certificates));
- } catch (UnsupportedClassVersionError ucve) {
- throw new UnsupportedClassVersionError(
- ucve.getLocalizedMessage() + " " +
- sm.getString("webappClassLoader.wrongVersion",
- name));
- }
- entry.loadedClass = clazz;
- }
-
- return clazz;
- }
-
-
- private String binaryNameToPath(String binaryName, boolean withLeadingSlash) {
- // 1 for leading '/', 6 for ".class"
- StringBuilder path = new StringBuilder(7 + binaryName.length());
- if (withLeadingSlash) {
- path.append('/');
- }
- path.append(binaryName.replace('.', '/'));
- path.append(CLASS_FILE_SUFFIX);
- return path.toString();
- }
-
-
- private String nameToPath(String name) {
- if (name.startsWith("/")) {
- return name;
- }
- StringBuilder path = new StringBuilder(
- 1 + name.length());
- path.append('/');
- path.append(name);
- return path.toString();
- }
-
-
- /**
- * Returns true if the specified package name is sealed according to the
- * given manifest.
- *
- * @param name Path name to check
- * @param man Associated manifest
- * @return <code>true</code> if the manifest associated says it is sealed
- */
- protected boolean isPackageSealed(String name, Manifest man) {
-
- String path = name.replace('.', '/') + '/';
- Attributes attr = man.getAttributes(path);
- String sealed = null;
- if (attr != null) {
- sealed = attr.getValue(Name.SEALED);
- }
- if (sealed == null) {
- if ((attr = man.getMainAttributes()) != null) {
- sealed = attr.getValue(Name.SEALED);
- }
- }
- return "true".equalsIgnoreCase(sealed);
-
- }
-
-
- /**
- * Finds the class with the given name if it has previously been
- * loaded and cached by this class loader, and return the Class object.
- * If this class has not been cached, return <code>null</code>.
- *
- * @param name The binary name of the resource to return
- * @return a loaded class
- */
- protected Class<?> findLoadedClass0(String name) {
-
- String path = binaryNameToPath(name, true);
-
- ResourceEntry entry = resourceEntries.get(path);
- if (entry != null) {
- return entry.loadedClass;
- }
- return null;
- }
-
-
- /**
- * Refresh the system policy file, to pick up eventual changes.
- */
- protected void refreshPolicy() {
-
- try {
- // The policy file may have been modified to adjust
- // permissions, so we're reloading it when loading or
- // reloading a Context
- Policy policy = Policy.getPolicy();
- policy.refresh();
- } catch (AccessControlException e) {
- // Some policy files may restrict this, even for the core,
- // so this exception is ignored
- }
-
- }
-
-
- /**
- * Filter classes.
- *
- * @param name class name
- * @param isClassName <code>true</code> if name is a class name,
- * <code>false</code> if name is a resource name
- * @return <code>true</code> if the class should be filtered
- */
- protected boolean filter(String name, boolean isClassName) {
-
- if (name == null)
- return false;
-
- char ch;
- if (name.startsWith("jakarta")) {
- /* 7 == length("jakarta") */
- if (name.length() == 7) {
- return false;
- }
- ch = name.charAt(7);
- if (isClassName && ch == '.') {
- /* 8 == length("jakarta.") */
- if (name.startsWith("servlet.jsp.jstl.", 8)) {
- return false;
- }
- if (name.startsWith("el.", 8) ||
- name.startsWith("servlet.", 8) ||
- name.startsWith("websocket.", 8) ||
- name.startsWith("security.auth.message.", 8)) {
- return true;
- }
- } else if (!isClassName && ch == '/') {
- /* 8 == length("jakarta/") */
- if (name.startsWith("servlet/jsp/jstl/", 8)) {
- return false;
- }
- if (name.startsWith("el/", 8) ||
- name.startsWith("servlet/", 8) ||
- name.startsWith("websocket/", 8) ||
- name.startsWith("security/auth/message/", 8)) {
- return true;
- }
- }
- } else if (name.startsWith("javax")) {
- /* 5 == length("javax") */
- if (name.length() == 5) {
- return false;
- }
- ch = name.charAt(5);
- if (isClassName && ch == '.') {
- /* 6 == length("javax.") */
- if (name.startsWith("websocket.", 6)) {
- return true;
- }
- } else if (!isClassName && ch == '/') {
- /* 6 == length("javax/") */
- if (name.startsWith("websocket/", 6)) {
- return true;
- }
- }
- } else if (name.startsWith("org")) {
- /* 3 == length("org") */
- if (name.length() == 3) {
- return false;
- }
- ch = name.charAt(3);
- if (isClassName && ch == '.') {
- /* 4 == length("org.") */
- if (name.startsWith("apache.", 4)) {
- /* 11 == length("org.apache.") */
- if (name.startsWith("tomcat.jdbc.", 11)) {
- return false;
- }
- if (name.startsWith("el.", 11) ||
- name.startsWith("catalina.", 11) ||
- name.startsWith("jasper.", 11) ||
- name.startsWith("juli.", 11) ||
- name.startsWith("tomcat.", 11) ||
- name.startsWith("naming.", 11) ||
- name.startsWith("coyote.", 11)) {
- return true;
- }
- }
- } else if (!isClassName && ch == '/') {
- /* 4 == length("org/") */
- if (name.startsWith("apache/", 4)) {
- /* 11 == length("org/apache/") */
- if (name.startsWith("tomcat/jdbc/", 11)) {
- return false;
- }
- if (name.startsWith("el/", 11) ||
- name.startsWith("catalina/", 11) ||
- name.startsWith("jasper/", 11) ||
- name.startsWith("juli/", 11) ||
- name.startsWith("tomcat/", 11) ||
- name.startsWith("naming/", 11) ||
- name.startsWith("coyote/", 11)) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
-
- @Override
- protected void addURL(URL url) {
- super.addURL(url);
- hasExternalRepositories = true;
- }
-
-
- @Override
- public String getWebappName() {
- return getContextName();
- }
-
-
- @Override
- public String getHostName() {
- if (resources != null) {
- Container host = resources.getContext().getParent();
- if (host != null) {
- return host.getName();
- }
- }
- return null;
- }
-
-
- @Override
- public String getServiceName() {
- if (resources != null) {
- Container host = resources.getContext().getParent();
- if (host != null) {
- Container engine = host.getParent();
- if (engine != null) {
- return engine.getName();
- }
- }
- }
- return null;
- }
-
-
- @Override
- public boolean hasLoggingConfig() {
- if (Globals.IS_SECURITY_ENABLED) {
- Boolean result = AccessController.doPrivileged(new PrivilegedHasLoggingConfig());
- return result.booleanValue();
- } else {
- return findResource("logging.properties") != null;
- }
- }
-
-
- private class PrivilegedHasLoggingConfig implements PrivilegedAction<Boolean> {
-
- @Override
- public Boolean run() {
- return Boolean.valueOf(findResource("logging.properties") != null);
- }
- }
-
-
- private static class CombinedEnumeration implements Enumeration<URL> {
-
- private final Enumeration<URL>[] sources;
- private int index = 0;
-
- public CombinedEnumeration(Enumeration<URL> enum1, Enumeration<URL> enum2) {
- @SuppressWarnings("unchecked")
- Enumeration<URL>[] sources = new Enumeration[] { enum1, enum2 };
- this.sources = sources;
- }
-
-
- @Override
- public boolean hasMoreElements() {
- return inc();
- }
-
-
- @Override
- public URL nextElement() {
- if (inc()) {
- return sources[index].nextElement();
- }
- throw new NoSuchElementException();
- }
-
-
- private boolean inc() {
- while (index < sources.length) {
- if (sources[index].hasMoreElements()) {
- return true;
- }
- index++;
- }
- return false;
- }
- }
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/apache/cxf/jaxb/JAXBContextInitializer.java b/jakarta/src/patch/java/org/apache/cxf/jaxb/JAXBContextInitializer.java
deleted file mode 100644
index 37b2d07..0000000
--- a/jakarta/src/patch/java/org/apache/cxf/jaxb/JAXBContextInitializer.java
+++ /dev/null
@@ -1,611 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.cxf.jaxb;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-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.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jakarta.xml.bind.annotation.XmlAccessType;
-import jakarta.xml.bind.annotation.XmlAttribute;
-import jakarta.xml.bind.annotation.XmlElement;
-import jakarta.xml.bind.annotation.XmlRootElement;
-import jakarta.xml.bind.annotation.XmlSeeAlso;
-import jakarta.xml.bind.annotation.XmlTransient;
-import jakarta.xml.bind.annotation.XmlType;
-import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
-import javax.xml.namespace.QName;
-
-import org.apache.cxf.common.classloader.ClassLoaderUtils;
-import org.apache.cxf.common.jaxb.JAXBUtils;
-import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.common.util.ASMHelper;
-import org.apache.cxf.common.util.ASMHelper.ClassWriter;
-import org.apache.cxf.common.util.ASMHelper.MethodVisitor;
-import org.apache.cxf.common.util.ASMHelper.Opcodes;
-import org.apache.cxf.common.util.ReflectionUtil;
-import org.apache.cxf.common.util.StringUtils;
-import org.apache.cxf.service.ServiceModelVisitor;
-import org.apache.cxf.service.model.MessageInfo;
-import org.apache.cxf.service.model.MessagePartInfo;
-import org.apache.cxf.service.model.OperationInfo;
-import org.apache.cxf.service.model.ServiceInfo;
-import org.apache.cxf.service.model.UnwrappedOperationInfo;
-
-/**
- * Walks the service model and sets up the classes for the context.
- */
-class JAXBContextInitializer extends ServiceModelVisitor {
- private static final Logger LOG = LogUtils.getL7dLogger(JAXBContextInitializer.class);
- private Set<Class<?>> classes;
- private Collection<Object> typeReferences;
- private Set<Class<?>> globalAdapters = new HashSet<>();
- private Map<String, Object> unmarshallerProperties;
-
- JAXBContextInitializer(ServiceInfo serviceInfo,
- Set<Class<?>> classes,
- Collection<Object> typeReferences,
- Map<String, Object> unmarshallerProperties) {
- super(serviceInfo);
- this.classes = classes;
- this.typeReferences = typeReferences;
- this.unmarshallerProperties = unmarshallerProperties;
- }
-
- @Override
- public void begin(MessagePartInfo part) {
- Class<?> clazz = part.getTypeClass();
- if (clazz == null) {
- return;
- }
-
- if (Exception.class.isAssignableFrom(clazz)) {
- //exceptions are handled special, make sure we mark it
- part.setProperty(JAXBDataBinding.class.getName() + ".CUSTOM_EXCEPTION",
- Boolean.TRUE);
- }
- boolean isFromWrapper = part.getMessageInfo().getOperation().isUnwrapped();
- if (isFromWrapper
- && !Boolean.TRUE.equals(part.getProperty("messagepart.isheader"))) {
- UnwrappedOperationInfo uop = (UnwrappedOperationInfo)part.getMessageInfo().getOperation();
- OperationInfo op = uop.getWrappedOperation();
- MessageInfo inf = null;
- if (uop.getInput() == part.getMessageInfo()) {
- inf = op.getInput();
- } else if (uop.getOutput() == part.getMessageInfo()) {
- inf = op.getOutput();
- }
- if (inf != null
- && inf.getFirstMessagePart().getTypeClass() != null) {
- //if the wrapper has a type class, we don't need to do anything
- //as everything would have been discovered when walking the
- //wrapper type (unless it's a header which wouldn't be in the wrapper)
- return;
- }
- }
- if (isFromWrapper
- && clazz.isArray()
- && !Byte.TYPE.equals(clazz.getComponentType())) {
- clazz = clazz.getComponentType();
- }
-
- Annotation[] a = (Annotation[])part.getProperty("parameter.annotations");
- checkForAdapter(clazz, a);
-
- Type genericType = (Type) part.getProperty("generic.type");
- if (genericType != null) {
- boolean isList = Collection.class.isAssignableFrom(clazz);
- if (isFromWrapper) {
- if (genericType instanceof Class
- && ((Class<?>)genericType).isArray()) {
- Class<?> cl2 = (Class<?>)genericType;
- if (cl2.isArray()
- && !Byte.TYPE.equals(cl2.getComponentType())) {
- genericType = cl2.getComponentType();
- }
- addType(genericType);
- } else if (!isList) {
- addType(genericType);
- }
- } else {
- addType(genericType, true);
- }
-
- if (isList
- && genericType instanceof ParameterizedType) {
- ParameterizedType pt = (ParameterizedType) genericType;
- if (pt.getActualTypeArguments().length > 0
- && pt.getActualTypeArguments()[0] instanceof Class) {
-
- Class<? extends Object> arrayCls =
- Array.newInstance((Class<?>) pt.getActualTypeArguments()[0], 0).getClass();
- clazz = arrayCls;
- part.setTypeClass(clazz);
- if (isFromWrapper) {
- addType(clazz.getComponentType(), true);
- }
- } else if (pt.getActualTypeArguments().length > 0
- && pt.getActualTypeArguments()[0] instanceof GenericArrayType) {
- GenericArrayType gat = (GenericArrayType)pt.getActualTypeArguments()[0];
- gat.getGenericComponentType();
- Class<? extends Object> arrayCls =
- Array.newInstance((Class<?>) gat.getGenericComponentType(), 0).getClass();
- clazz = Array.newInstance(arrayCls, 0).getClass();
- part.setTypeClass(clazz);
- if (isFromWrapper) {
- addType(clazz.getComponentType(), true);
- }
- }
- }
- if (isFromWrapper && isList) {
- clazz = null;
- }
- }
- if (clazz != null) {
- if (!isFromWrapper
- && clazz.getAnnotation(XmlRootElement.class) == null
- && clazz.getAnnotation(XmlType.class) != null
- && StringUtils.isEmpty(clazz.getAnnotation(XmlType.class).name())) {
- Object ref = createTypeReference(part.getName(), clazz);
- if (ref != null) {
- typeReferences.add(ref);
- }
- }
-
- addClass(clazz);
- }
- }
-
- private void checkForAdapter(Class<?> clazz, Annotation[] anns) {
- if (anns != null) {
- for (Annotation a : anns) {
- if (XmlJavaTypeAdapter.class.isAssignableFrom(a.annotationType())) {
- Type t = Utils.getTypeFromXmlAdapter((XmlJavaTypeAdapter)a);
- if (t != null) {
- addType(t);
- }
- }
- }
- }
- XmlJavaTypeAdapter xjta = clazz.getAnnotation(XmlJavaTypeAdapter.class);
- if (xjta != null) {
- Type t = Utils.getTypeFromXmlAdapter(xjta);
- if (t != null) {
- addType(t);
- }
- }
- if (clazz.getPackage() != null) {
- XmlJavaTypeAdapters adapt = clazz.getPackage().getAnnotation(XmlJavaTypeAdapters.class);
- if (adapt != null) {
- for (XmlJavaTypeAdapter a : adapt.value()) {
- globalAdapters.add(a.type());
- }
- for (XmlJavaTypeAdapter a : adapt.value()) {
- Type t = Utils.getTypeFromXmlAdapter(a);
- if (t != null) {
- addType(t);
- }
- }
- }
- }
- }
-
- private void addType(Type cls) {
- addType(cls, false);
- }
- private void addType(Type cls, boolean allowArray) {
- if (cls instanceof Class) {
- if (globalAdapters.contains(cls)) {
- return;
- }
- if (((Class<?>)cls).isArray() && !allowArray) {
- addClass(((Class<?>)cls).getComponentType());
- } else {
- addClass((Class<?>)cls);
- }
- } else if (cls instanceof ParameterizedType) {
- final ParameterizedType parameterizedType = (ParameterizedType)cls;
- addType(parameterizedType.getRawType());
- if (!parameterizedType.getRawType().equals(Enum.class)) {
- for (Type t2 : parameterizedType.getActualTypeArguments()) {
- if (shouldTypeBeAdded(t2, parameterizedType)) {
- addType(t2);
- }
- }
- }
- } else if (cls instanceof GenericArrayType) {
- Class<?> ct;
- GenericArrayType gt = (GenericArrayType)cls;
- Type componentType = gt.getGenericComponentType();
- if (componentType instanceof Class) {
- ct = (Class<?>)componentType;
- } else if (componentType instanceof ParameterizedType) {
- final ParameterizedType parameterizedType = (ParameterizedType)componentType;
- final Type rawType = parameterizedType.getRawType();
- if (rawType instanceof Class) {
- ct = (Class<?>)rawType;
- } else {
- throw new IllegalArgumentException("Unable to determine type for " + rawType);
- }
- if (!parameterizedType.getRawType().equals(Enum.class)) {
- for (Type t2 : parameterizedType.getActualTypeArguments()) {
- if (shouldTypeBeAdded(t2, parameterizedType)) {
- addType(t2);
- }
- }
- }
- } else {
- TypeVariable<?> tv = (TypeVariable<?>)componentType;
- Type[] bounds = tv.getBounds();
- if (bounds != null && bounds.length == 1) {
- if (bounds[0] instanceof Class) {
- ct = (Class<?>)bounds[0];
- } else {
- throw new IllegalArgumentException("Unable to determine type for: " + tv);
- }
- } else {
- throw new IllegalArgumentException("Unable to determine type for: " + tv);
- }
- }
- ct = Array.newInstance(ct, 0).getClass();
-
- addClass(ct);
- } else if (cls instanceof WildcardType) {
- for (Type t : ((WildcardType)cls).getUpperBounds()) {
- addType(t);
- }
- for (Type t : ((WildcardType)cls).getLowerBounds()) {
- addType(t);
- }
- } else if (cls instanceof TypeVariable) {
- for (Type t : ((TypeVariable<?>)cls).getBounds()) {
- addType(t);
- }
- }
- }
-
- private boolean shouldTypeBeAdded(final Type t2, final ParameterizedType parameterizedType) {
- if (!(t2 instanceof TypeVariable)) {
- return true;
- }
- TypeVariable<?> typeVariable = (TypeVariable<?>) t2;
- final Type[] bounds = typeVariable.getBounds();
- for (Type bound : bounds) {
- if (bound instanceof ParameterizedType && bound.equals(parameterizedType)) {
- return false;
- }
- }
- return true;
- }
-
- void addClass(Class<?> claz) {
- if (Throwable.class.isAssignableFrom(claz)) {
- if (!Throwable.class.equals(claz)
- && !Exception.class.equals(claz)) {
- walkReferences(claz);
- }
- addClass(String.class);
- } else if (claz.getName().startsWith("java.")
- || claz.getName().startsWith("javax.")
- || claz.getName().startsWith("jakarta.")) {
- return;
- } else {
- Class<?> cls = JAXBUtils.getValidClass(claz);
- if (cls == null
- && ReflectionUtil.getDeclaredConstructors(claz).length > 0
- && !Modifier.isAbstract(claz.getModifiers())) {
- if (LOG.isLoggable(Level.INFO)) {
- LOG.info("Class " + claz.getName() + " does not have a default constructor which JAXB requires.");
- }
- //there is no init(), but other constructors
- Object factory = createFactory(claz, ReflectionUtil.getDeclaredConstructors(claz)[0]);
- unmarshallerProperties.put("com.sun.xml.bind.ObjectFactory", factory);
- cls = claz;
- }
- if (null != cls) {
- if (classes.contains(cls)) {
- return;
- }
-
- if (!cls.isInterface()) {
- classes.add(cls);
- }
-
- XmlSeeAlso xsa = cls.getAnnotation(XmlSeeAlso.class);
- if (xsa != null) {
- for (Class<?> c : xsa.value()) {
- addClass(c);
- }
- }
- XmlJavaTypeAdapter xjta = cls.getAnnotation(XmlJavaTypeAdapter.class);
- if (xjta != null) {
- //has an adapter. We need to inspect the adapter and then
- //return as the adapter will handle the superclass
- //and interfaces and such
- Type t = Utils.getTypeFromXmlAdapter(xjta);
- if (t != null) {
- addType(t);
- }
- return;
- }
-
- if (cls.getSuperclass() != null) {
- //JAXB should do this, but it doesn't always.
- //in particular, older versions of jaxb don't
- addClass(cls.getSuperclass());
- }
-
- if (!cls.isInterface()) {
- walkReferences(cls);
- }
- }
- }
- }
-
- private void walkReferences(Class<?> cls) {
- if (cls == null) {
- return;
- }
- if (cls.getName().startsWith("java.")
- || cls.getName().startsWith("javax.")
- || cls.getName().startsWith("jakarta.")) {
- return;
- }
- //walk the public fields/methods to try and find all the classes. JAXB will only load the
- //EXACT classes in the fields/methods if they are in a different package. Thus,
- //subclasses won't be found and the xsi:type stuff won't work at all.
- //We'll grab the public field/method types and then add the ObjectFactory stuff
- //as well as look for jaxb.index files in those packages.
-
- XmlAccessType accessType = Utils.getXmlAccessType(cls);
-
- if (accessType != XmlAccessType.PROPERTY) { // only look for fields if we are instructed to
- //fields are accessible even if not public, must look at the declared fields
- //then walk to parents declared fields, etc...
- Field[] fields = ReflectionUtil.getDeclaredFields(cls);
- for (Field f : fields) {
- if (isFieldAccepted(f, accessType)) {
- XmlJavaTypeAdapter xjta = Utils.getFieldXJTA(f);
- if (xjta != null) {
- Type t = Utils.getTypeFromXmlAdapter(xjta);
- if (t != null) {
- addType(t);
- continue;
- }
- }
- addType(f.getGenericType());
- }
- }
- walkReferences(cls.getSuperclass());
- }
-
- if (accessType != XmlAccessType.FIELD) { // only look for methods if we are instructed to
- Method[] methods = ReflectionUtil.getDeclaredMethods(cls);
- for (Method m : methods) {
- if (isMethodAccepted(m, accessType)) {
- XmlJavaTypeAdapter xjta = Utils.getMethodXJTA(m);
- if (xjta != null) {
- Type t = Utils.getTypeFromXmlAdapter(xjta);
- if (t != null) {
- addType(t);
- continue;
- }
- }
- addType(m.getGenericReturnType());
- for (Type t : m.getGenericParameterTypes()) {
- addType(t);
- }
- }
- }
- }
- }
-
- /**
- * Checks if the field is accepted as a JAXB property.
- */
- static boolean isFieldAccepted(Field field, XmlAccessType accessType) {
- // We only accept non static fields which are not marked @XmlTransient or has transient modifier
- if (field.isAnnotationPresent(XmlTransient.class)
- || Modifier.isTransient(field.getModifiers())) {
- return false;
- }
- if (Modifier.isStatic(field.getModifiers())) {
- return field.isAnnotationPresent(XmlAttribute.class);
- }
- if (accessType == XmlAccessType.PUBLIC_MEMBER
- && !Modifier.isPublic(field.getModifiers())) {
- return false;
- }
- if (accessType == XmlAccessType.NONE
- || accessType == XmlAccessType.PROPERTY) {
- return checkJaxbAnnotation(field.getAnnotations());
- }
- return true;
- }
-
- /**
- * Checks if the method is accepted as a JAXB property getter.
- */
- static boolean isMethodAccepted(Method method, XmlAccessType accessType) {
- // We only accept non static property getters which are not marked @XmlTransient
- if (Modifier.isStatic(method.getModifiers())
- || method.isAnnotationPresent(XmlTransient.class)
- || !Modifier.isPublic(method.getModifiers())
- || "getClass".equals(method.getName())) {
- return false;
- }
-
- // must not have parameters and return type must not be void
- if (method.getReturnType() == Void.class || method.getReturnType() == Void.TYPE
- || method.getParameterTypes().length != 0
- || (method.getDeclaringClass().equals(Throwable.class)
- && !("getMessage".equals(method.getName())))
- || !(method.getName().startsWith("get")
- || method.getName().startsWith("is"))) {
- return false;
- }
- int beginIndex = 3;
- if (method.getName().startsWith("is")) {
- beginIndex = 2;
- }
-
- Method setter = null;
- try {
- setter = method.getDeclaringClass()
- .getMethod("set" + method.getName().substring(beginIndex),
- new Class[] {method.getReturnType()});
- } catch (Exception e) {
- //getter, but no setter
- }
- if (setter != null) {
- if (setter.isAnnotationPresent(XmlTransient.class)
- || !Modifier.isPublic(setter.getModifiers())) {
- return false;
- }
- } else if (!Collection.class.isAssignableFrom(method.getReturnType())
- && !Throwable.class.isAssignableFrom(method.getDeclaringClass())) {
- //no setter, it's not a collection (thus getter().add(...)), and
- //not an Exception,
- return false;
- }
-
- if (accessType == XmlAccessType.NONE
- || accessType == XmlAccessType.FIELD) {
- return checkJaxbAnnotation(method.getAnnotations());
- }
- return true;
- }
-
- /**
- * Checks if there are JAXB annotations among the annotations of the class member.
- * @param annotations the array of annotations from the class member
- * @return true if JAXB annotations are present, false otherwise
- */
- static boolean checkJaxbAnnotation(Annotation[] annotations) {
- // must check if there are any jaxb annotations
- Package jaxbAnnotationsPackage = XmlElement.class.getPackage();
- for (Annotation annotation : annotations) {
- if (annotation.annotationType().getPackage() == jaxbAnnotationsPackage) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * The TypeReference class is a sun specific class that is found in two different
- * locations depending on environment. In IBM JDK the class is not available at all.
- * So we have to load it at runtime.
- *
- * @param n
- * @param cls
- * @return initiated TypeReference
- */
- private static Object createTypeReference(QName n, Class<?> cls) {
- Class<?> refClass = null;
- try {
- refClass = ClassLoaderUtils.loadClass("com.sun.xml.bind.api.TypeReference",
- JAXBContextInitializer.class);
- } catch (Throwable ex) {
- try {
- refClass = ClassLoaderUtils.loadClass("com.sun.xml.internal.bind.api.TypeReference",
- JAXBContextInitializer.class);
- } catch (Throwable ex2) {
- //ignore
- }
- }
- if (refClass != null) {
- try {
- return refClass.getConstructor(QName.class, Type.class, new Annotation[0].getClass()) //NOPMD
- .newInstance(n, cls, new Annotation[0]);
- } catch (Throwable e) {
- //ignore
- }
- }
- return null;
- }
-
- @SuppressWarnings("unused")
- private Object createFactory(Class<?> cls, Constructor<?> contructor) {
- String newClassName = cls.getName() + "Factory";
- ASMHelper helper = new ASMHelper();
- ClassWriter cw = helper.createClassWriter();
- MethodVisitor mv;
-
- cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER,
- ASMHelper.periodToSlashes(newClassName), null, "java/lang/Object", null);
-
- cw.visitSource(cls.getSimpleName() + "Factory" + ".java", null);
-
- mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
- mv.visitCode();
- mv.visitVarInsn(Opcodes.ALOAD, 0);
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
- mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(1, 1);
- mv.visitEnd();
-
- mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "create" + cls.getSimpleName(),
- "()L" + ASMHelper.periodToSlashes(cls.getName()) + ";", null, null);
- mv.visitCode();
- String name = cls.getName().replace(".", "/");
- mv.visitTypeInsn(Opcodes.NEW, name);
- mv.visitInsn(Opcodes.DUP);
- StringBuilder paraString = new StringBuilder(32).append("(");
-
- for (Class<?> paraClass : contructor.getParameterTypes()) {
- mv.visitInsn(Opcodes.ACONST_NULL);
- paraString.append("Ljava/lang/Object;");
- }
- paraString.append(")V");
-
- mv.visitMethodInsn(Opcodes.INVOKESPECIAL, name, "<init>", paraString.toString(), false);
-
- mv.visitInsn(Opcodes.ARETURN);
- mv.visitMaxs(1, 1);
- mv.visitEnd();
-
- cw.visitEnd();
- Class<?> factoryClass = helper.loadClass(newClassName, cls, cw.toByteArray());
- try {
- return factoryClass.newInstance();
- } catch (Exception e) {
- //ignore
- }
- return null;
- }
-
-
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/apache/openjpa/enhance/PCClassFileTransformer.java b/jakarta/src/patch/java/org/apache/openjpa/enhance/PCClassFileTransformer.java
deleted file mode 100644
index ee2cdac..0000000
--- a/jakarta/src/patch/java/org/apache/openjpa/enhance/PCClassFileTransformer.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openjpa.enhance;
-
-import java.io.ByteArrayInputStream;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.security.AccessController;
-import java.security.ProtectionDomain;
-import java.util.Set;
-
-import org.apache.openjpa.conf.OpenJPAConfiguration;
-import org.apache.openjpa.lib.log.Log;
-import org.apache.openjpa.lib.util.J2DoPrivHelper;
-import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.lib.util.Options;
-import org.apache.openjpa.meta.MetaDataRepository;
-import org.apache.openjpa.util.GeneralException;
-
-import serp.bytecode.BCClass;
-import serp.bytecode.Project;
-import serp.bytecode.lowlevel.ConstantPoolTable;
-
-
-/**
- * Transformer that makes persistent classes implement the
- * {@link PersistenceCapable} interface at runtime.
- *
- * @author Abe White
- */
-public class PCClassFileTransformer
- implements ClassFileTransformer {
-
- private static final Localizer _loc = Localizer.forPackage
- (PCClassFileTransformer.class);
-
- private final MetaDataRepository _repos;
- private final PCEnhancer.Flags _flags;
- private final ClassLoader _tmpLoader;
- private final Log _log;
- private final Set _names;
- private boolean _transforming = false;
-
- /**
- * Constructor.
- *
- * @param repos metadata repository to use internally
- * @param opts enhancer configuration options
- * @param loader temporary class loader for loading intermediate classes
- */
- public PCClassFileTransformer(MetaDataRepository repos, Options opts,
- ClassLoader loader) {
- this(repos, toFlags(opts), loader, opts.removeBooleanProperty
- ("scanDevPath", "ScanDevPath", false));
- }
-
- /**
- * Create enhancer flags from the given options.
- */
- private static PCEnhancer.Flags toFlags(Options opts) {
- PCEnhancer.Flags flags = new PCEnhancer.Flags();
- flags.addDefaultConstructor = opts.removeBooleanProperty
- ("addDefaultConstructor", "AddDefaultConstructor",
- flags.addDefaultConstructor);
- flags.enforcePropertyRestrictions = opts.removeBooleanProperty
- ("enforcePropertyRestrictions", "EnforcePropertyRestrictions",
- flags.enforcePropertyRestrictions);
- return flags;
- }
-
- /**
- * Constructor.
- *
- * @param repos metadata repository to use internally
- * @param flags enhancer configuration
- * @param tmpLoader temporary class loader for loading intermediate classes
- * @param devscan whether to scan the dev classpath for persistent types
- * if none are configured
- */
- public PCClassFileTransformer(MetaDataRepository repos,
- PCEnhancer.Flags flags, ClassLoader tmpLoader, boolean devscan) {
- _repos = repos;
- _tmpLoader = tmpLoader;
-
- _log = repos.getConfiguration().
- getLog(OpenJPAConfiguration.LOG_ENHANCE);
- _flags = flags;
-
- _names = repos.getPersistentTypeNames(devscan, tmpLoader);
- if (_names == null && _log.isInfoEnabled())
- _log.info(_loc.get("runtime-enhance-pcclasses"));
- }
-
- @Override
- public byte[] transform(ClassLoader loader, String className,
- Class redef, ProtectionDomain domain, byte[] bytes)
- throws IllegalClassFormatException {
- if (loader == _tmpLoader)
- return null;
-
- // JDK bug -- OPENJPA-1676
- if (className == null) {
- return null;
- }
- // prevent re-entrant calls, which can occur if the enhancing
- // loader is used to also load OpenJPA libraries; this is to prevent
- // recursive enhancement attempts for internal openjpa libraries
- if (_transforming)
- return null;
-
- _transforming = true;
-
- return transform0(className, redef, bytes);
- }
-
- /**
- * We have to split the transform method into two methods to avoid
- * ClassCircularityError when executing method using pure-JIT JVMs
- * such as JRockit.
- */
- private byte[] transform0(String className, Class redef, byte[] bytes)
- throws IllegalClassFormatException {
-
- byte[] returnBytes = null;
- try {
- Boolean enhance = needsEnhance(className, redef, bytes);
- if (enhance != null && _log.isTraceEnabled())
- _log.trace(_loc.get("needs-runtime-enhance", className,
- enhance));
- if (enhance != Boolean.TRUE)
- return null;
-
- ClassLoader oldLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
- AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(_tmpLoader));
- try {
- PCEnhancer enhancer = new PCEnhancer(_repos.getConfiguration(),
- new Project().loadClass(new ByteArrayInputStream(bytes),
- _tmpLoader), _repos);
- enhancer.setAddDefaultConstructor(_flags.addDefaultConstructor);
- enhancer.setEnforcePropertyRestrictions
- (_flags.enforcePropertyRestrictions);
-
- if (enhancer.run() == PCEnhancer.ENHANCE_NONE)
- return null;
- BCClass pcb = enhancer.getPCBytecode();
- returnBytes = AsmAdaptor.toByteArray(pcb, pcb.toByteArray());
- return returnBytes;
- } finally {
- AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(oldLoader));
- }
- } catch (Throwable t) {
- _log.warn(_loc.get("cft-exception-thrown", className), t);
- if (t instanceof RuntimeException)
- throw (RuntimeException) t;
- if (t instanceof IllegalClassFormatException)
- throw (IllegalClassFormatException) t;
- throw new GeneralException(t);
- } finally {
- _transforming = false;
- if (returnBytes != null && _log.isTraceEnabled())
- _log.trace(_loc.get("runtime-enhance-complete", className,
- bytes.length, returnBytes.length));
- }
- }
-
- /**
- * Return whether the given class needs enhancement.
- */
- private Boolean needsEnhance(String clsName, Class redef, byte[] bytes) {
- if (redef != null) {
- Class[] intfs = redef.getInterfaces();
- for (int i = 0; i < intfs.length; i++)
- if (PersistenceCapable.class.getName().
- equals(intfs[i].getName()))
- return Boolean.valueOf(!isEnhanced(bytes));
- return null;
- }
-
- if (_names != null) {
- if (_names.contains(clsName.replace('/', '.')))
- return Boolean.valueOf(!isEnhanced(bytes));
- return null;
- }
-
- if (clsName.startsWith("java/") || clsName.startsWith("javax/") || clsName.startsWith("jakarta/"))
- return null;
- if (isEnhanced(bytes))
- return Boolean.FALSE;
-
- try {
- Class c = Class.forName(clsName.replace('/', '.'), false,
- _tmpLoader);
- if (_repos.getMetaData(c, null, false) != null)
- return Boolean.TRUE;
- return null;
- } catch (ClassNotFoundException cnfe) {
- // cannot load the class: this might mean that it is a proxy
- // or otherwise inaccessible class which can't be an entity
- return Boolean.FALSE;
- } catch (LinkageError cce) {
- // this can happen if we are loading classes that this
- // class depends on; these will never be enhanced anyway
- return Boolean.FALSE;
- } catch (RuntimeException re) {
- throw re;
- } catch (Throwable t) {
- throw new GeneralException(t);
- }
- }
-
- /**
- * Analyze the bytecode to see if the given class definition implements
- * {@link PersistenceCapable}.
- */
- private static boolean isEnhanced(byte[] b) {
- if (AsmAdaptor.use())
- {
- return AsmAdaptor.isEnhanced(b);
- }
-
- ConstantPoolTable table = new ConstantPoolTable(b);
- int idx = table.getEndIndex();
-
- idx += 6; // skip access, cls, super
- int ifaces = table.readUnsignedShort(idx);
- int clsEntry, utfEntry;
- String name;
- for (int i = 0; i < ifaces; i++) {
- idx += 2;
- clsEntry = table.readUnsignedShort(idx);
- utfEntry = table.readUnsignedShort(table.get(clsEntry));
- name = table.readString(table.get(utfEntry));
- if ("org/apache/openjpa/enhance/PersistenceCapable".equals(name))
- return true;
- }
- return false;
- }
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java b/jakarta/src/patch/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java
deleted file mode 100644
index b972512..0000000
--- a/jakarta/src/patch/java/org/apache/openjpa/lib/meta/ClassMetaDataIterator.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openjpa.lib.meta;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.NoSuchElementException;
-
-import org.apache.openjpa.lib.util.ClassUtil;
-import org.apache.openjpa.lib.util.J2DoPrivHelper;
-import org.apache.openjpa.lib.util.MultiClassLoader;
-
-/**
- * Iterator over all metadata resources that might contain the
- * metadata for a given class, starting with the most general. Assumes that
- * package-level resources are named "package.<suffix>".
- *
- * @author Abe White
- */
-public class ClassMetaDataIterator implements MetaDataIterator {
-
- private final ClassLoader _loader;
- private final List<String> _locs;
- private int _loc = -1;
- private final List<URL> _urls = new ArrayList<>(3);
- private int _url = -1;
-
- /**
- * Constructor; supply the class whose metadata to find, the suffix
- * of metadata files, and whether to parse top-down or bottom-up.
- */
- public ClassMetaDataIterator(Class<?> cls, String suffix, boolean topDown) {
- this(cls, suffix, null, topDown);
- }
-
- /**
- * Constructor; supply the class whose metadata to find, the suffix
- * of metadata files, and whether to parse top-down or bottom-up.
- */
- public ClassMetaDataIterator(Class<?> cls, String suffix,
- ClassLoader loader, boolean topDown) {
- // skip classes that can't have metadata
- if (cls != null && (cls.isPrimitive()
- || cls.getName().startsWith("java.")
- || cls.getName().startsWith("javax.")
- || cls.getName().startsWith("jakarta."))) {
- _loader = null;
- _locs = Collections.emptyList();
- return;
- }
-
- if (loader == null) {
- MultiClassLoader multi = AccessController
- .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction());
- multi.addClassLoader(MultiClassLoader.SYSTEM_LOADER);
- multi.addClassLoader(MultiClassLoader.THREAD_LOADER);
- multi.addClassLoader(getClass().getClassLoader());
- if (cls != null)
- {
- ClassLoader clsLoader = (ClassLoader)
- AccessController.doPrivileged(
- J2DoPrivHelper.getClassLoaderAction(cls));
- if (clsLoader != null)
- multi.addClassLoader(clsLoader);
- }
- loader = multi;
- }
- _loader = loader;
-
- // collect the set of all possible metadata locations; start with
- // system locations
- _locs = new ArrayList<>();
- _locs.add("META-INF/package" + suffix);
- _locs.add("WEB-INF/package" + suffix);
- _locs.add("package" + suffix);
-
- // put this legacy location at the end regardless of whether we're
- // going top down or bottom up so we don't have to parse it as often
- // during testing
- if (!topDown)
- _locs.add("system" + suffix);
-
- if (cls != null) {
- // also check:
- // 1. for each package from the top down to cls' package:
- // <path>/package<suffix>
- // <path>/<package-name><suffix> (legacy support)
- // <path>/../<package-name><suffix> (legacy support)
- // 2. <path>/<class-name><suffix>
- String pkg = ClassUtil.getPackageName(cls).replace('.', '/');
- if (pkg.length() > 0) {
- int idx, start = 0;
- String pkgName, path, upPath = "";
- do {
- idx = pkg.indexOf('/', start);
- if (idx == -1) {
- pkgName = (start == 0) ? pkg : pkg.substring(start);
- path = pkg + "/";
- } else {
- pkgName = pkg.substring(start, idx);
- path = pkg.substring(0, idx + 1);
- }
-
- _locs.add(path + "package" + suffix);
- _locs.add(path + pkgName + suffix); // legacy
- _locs.add(upPath + pkgName + suffix); // legacy
- if (idx == -1)
- _locs.add(path + ClassUtil.getClassName(cls) + suffix);
-
- start = idx + 1;
- upPath = path;
- }
- while (idx != -1);
- } else {
- // <class-name><suffix> for top-level classes
- _locs.add(cls.getName() + suffix);
- }
- }
- if (topDown)
- _locs.add("system" + suffix); // legacy
- else
- Collections.reverse(_locs);
- }
-
- @Override
- public boolean hasNext() throws IOException {
- Enumeration<URL> e;
- while (_url + 1 >= _urls.size()) {
- if (++_loc >= _locs.size())
- return false;
-
- _url = -1;
- _urls.clear();
- try {
- e = AccessController.doPrivileged(
- J2DoPrivHelper.getResourcesAction(
- _loader, _locs.get(_loc)));
- } catch (PrivilegedActionException pae) {
- throw (IOException) pae.getException();
- }
- while (e.hasMoreElements())
- _urls.add(e.nextElement());
- }
- return true;
- }
-
- @Override
- public URL next() throws IOException {
- if (!hasNext())
- throw new NoSuchElementException();
- return _urls.get(++_url);
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- if (_url == -1 || _url >= _urls.size())
- throw new IllegalStateException();
- try {
- return AccessController.doPrivileged(
- J2DoPrivHelper.openStreamAction(_urls.get(_url)));
- } catch (PrivilegedActionException pae) {
- throw (IOException) pae.getException();
- }
- }
-
- @Override
- public File getFile() throws IOException {
- if (_url == -1 || _url >= _urls.size())
- throw new IllegalStateException();
- File file = new File(URLDecoder.decode((_urls.get(_url)).getFile()));
- return ((AccessController.doPrivileged(
- J2DoPrivHelper.existsAction(file))).booleanValue()) ? file:null;
- }
-
- @Override
- public void close() {
- }
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java b/jakarta/src/patch/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java
deleted file mode 100644
index dc5a93c..0000000
--- a/jakarta/src/patch/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openjpa.lib.util;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import serp.bytecode.lowlevel.ConstantPoolTable;
-
-/**
- * ClassLoader implementation that allows classes to be temporarily
- * loaded and then thrown away. Useful for the enhancer to be able
- * to run against a class without first loading(and thus polluting)
- * the parent ClassLoader.
- *
- * @author Marc Prud'hommeaux
- */
-public class TemporaryClassLoader extends ClassLoader {
-
- public TemporaryClassLoader(ClassLoader parent) {
- super(parent);
- }
-
- @Override
- public Class loadClass(String name) throws ClassNotFoundException {
- return loadClass(name, false);
- }
-
- @Override
- protected Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException {
- // see if we've already loaded it
- Class c = findLoadedClass(name);
- if (c != null)
- return c;
-
- // bug #283. defer to system if the name is a protected name.
- // "sun." is required for JDK 1.4, which has an access check for
- // sun.reflect.GeneratedSerializationConstructorAccessor1
- if (name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("jakarta.")
- || name.startsWith("sun.") || name.startsWith("jdk.")) {
- return Class.forName(name, resolve, getClass().getClassLoader());
- }
-
- String resourceName = name.replace('.', '/') + ".class";
- InputStream resource = getResourceAsStream(resourceName);
- if (resource == null) {
- throw new ClassNotFoundException(name);
- }
-
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- byte[] b = new byte[1024];
- try {
- for (int n = 0; (n = resource.read(b, 0, b.length)) != -1;
- bout.write(b, 0, n))
- ;
- byte[] classBytes = bout.toByteArray();
- // To avoid classloader issues with the JVM (Sun and IBM), we
- // will not load Enums via the TemporaryClassLoader either.
- // Reference JIRA Issue OPENJPA-646 for more information.
- if (isAnnotation(classBytes) || isEnum(classBytes)) {
- try {
- Class<?> frameworkClass = Class.forName(name, resolve,
- getClass().getClassLoader());
- return frameworkClass;
- } catch (ClassNotFoundException e) {
- // OPENJPA-1121 continue, as it must be a user-defined class
- }
- }
-
- try {
- return defineClass(name, classBytes, 0, classBytes.length);
- } catch (SecurityException e) {
- // possible prohibited package: defer to the parent
- return super.loadClass(name, resolve);
- }
- } catch (IOException ioe) {
- // defer to the parent
- return super.loadClass(name, resolve);
- }
- }
-
- /**
- * Fast-parse the given class bytecode to determine if it is an
- * annotation class.
- */
- private static boolean isAnnotation(byte[] b) {
- if (JavaVersions.VERSION < 5)
- return false;
- int idx = ConstantPoolTable.getEndIndex(b);
- int access = ConstantPoolTable.readUnsignedShort(b, idx);
- return (access & 0x2000) != 0; // access constant for annotation type
- }
-
- /**
- * Fast-parse the given class bytecode to determine if it is an
- * enum class.
- */
- private static boolean isEnum(byte[] b) {
- if (JavaVersions.VERSION < 5)
- return false;
- int idx = ConstantPoolTable.getEndIndex(b);
- int access = ConstantPoolTable.readUnsignedShort(b, idx);
- return (access & 0x4000) != 0; // access constant for enum type
- }
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java b/jakarta/src/patch/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
deleted file mode 100644
index 03cd4fc..0000000
--- a/jakarta/src/patch/java/org/apache/openjpa/meta/AbstractMetaDataDefaults.java
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openjpa.meta;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.security.PrivilegedActionException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.openjpa.enhance.PCRegistry;
-import org.apache.openjpa.lib.log.Log;
-import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.util.OpenJPAException;
-import org.apache.openjpa.util.UserException;
-
-/**
- * Abstract implementation provides a set of generic utilities for detecting
- * persistence meta-data of Field/Member. Also provides bean-style properties
- * such as access style or identity type to be used by default when such
- * information is not derivable from available meta-data.
- *
- * @author Abe White
- * @author Pinaki Poddar
- */
-public abstract class AbstractMetaDataDefaults
- implements MetaDataDefaults {
-
- private static final Localizer _loc = Localizer.forPackage
- (AbstractMetaDataDefaults.class);
-
- private int _access = AccessCode.FIELD;
- private int _identity = ClassMetaData.ID_UNKNOWN;
- private boolean _ignore = true;
- private boolean _interface = true;
- private boolean _pcRegistry = true;
- private int _callback = CALLBACK_RETHROW;
- private boolean _unwrapped = false;
-
- /**
- * Whether to attempt to use the information from registered classes
- * to populate metadata defaults. Defaults to true.
- */
- public boolean getUsePCRegistry() {
- return _pcRegistry;
- }
-
- /**
- * Whether to attempt to use the information from registered classes
- * to populate metadata defaults. Defaults to true.
- */
- public void setUsePCRegistry(boolean pcRegistry) {
- _pcRegistry = pcRegistry;
- }
-
- /**
- * The default access type for base classes with ACCESS_UNKNOWN.
- * ACCESS_FIELD by default.
- */
- @Override
- public int getDefaultAccessType() {
- return _access;
- }
-
- /**
- * The default access type for base classes with ACCESS_UNKNOWN.
- * ACCESS_FIELD by default.
- */
- public void setDefaultAccessType(int access) {
- _access = access;
- }
-
- /**
- * The default identity type for unmapped classes without primary
- * key fields. ID_UNKNOWN by default.
- */
- @Override
- public int getDefaultIdentityType() {
- return _identity;
- }
-
- /**
- * The default identity type for unmapped classes without primary
- * key fields. ID_UNKNOWN by default.
- */
- public void setDefaultIdentityType(int identity) {
- _identity = identity;
- }
-
- @Override
- public int getCallbackMode() {
- return _callback;
- }
-
- public void setCallbackMode(int mode) {
- _callback = mode;
- }
-
- public void setCallbackMode(int mode, boolean on) {
- if (on)
- _callback |= mode;
- else
- _callback &= ~mode;
- }
-
- @Override
- public boolean getCallbacksBeforeListeners(int type) {
- return false;
- }
-
- @Override
- public boolean isDeclaredInterfacePersistent() {
- return _interface;
- }
-
- public void setDeclaredInterfacePersistent(boolean pers) {
- _interface = pers;
- }
-
- @Override
- public boolean isDataStoreObjectIdFieldUnwrapped() {
- return _unwrapped;
- }
-
- public void setDataStoreObjectIdFieldUnwrapped(boolean unwrapped) {
- _unwrapped = unwrapped;
- }
-
- public boolean getIgnoreNonPersistent() {
- return _ignore;
- }
-
- @Override
- public void setIgnoreNonPersistent(boolean ignore) {
- _ignore = ignore;
- }
-
- @Override
- public void populate(ClassMetaData meta, int access) {
- populate(meta, access, false);
- }
-
- @Override
- public void populate(ClassMetaData meta, int access, boolean ignoreTransient) {
- if (meta.getDescribedType() == Object.class)
- return;
- meta.setAccessType(access);
-
- Log log = meta.getRepository().getLog();
- if (log.isTraceEnabled())
- log.trace(_loc.get("gen-meta", meta));
- if (!_pcRegistry || !populateFromPCRegistry(meta)) {
- if (log.isTraceEnabled())
- log.trace(_loc.get("meta-reflect"));
- populateFromReflection(meta, ignoreTransient);
- }
- }
-
- /**
- * Populate the given metadata using the {@link PCRegistry}.
- */
- private boolean populateFromPCRegistry(ClassMetaData meta) {
- Class<?> cls = meta.getDescribedType();
- if (!PCRegistry.isRegistered(cls))
- return false;
- try {
- String[] fieldNames = PCRegistry.getFieldNames(cls);
- Class<?>[] fieldTypes = PCRegistry.getFieldTypes(cls);
- Member member;
- FieldMetaData fmd;
- for (int i = 0; i < fieldNames.length; i ++) {
- String property = fieldNames[i];
- member = getMemberByProperty(meta, property,
- AccessCode.UNKNOWN, true);
- if (member == null) // transient or indeterminable access
- continue;
- fmd = meta.addDeclaredField(property, fieldTypes[i]);
- fmd.backingMember(member);
- populate(fmd);
- }
- return true;
- } catch (OpenJPAException ke) {
- throw ke;
- } catch (Exception e) {
- if (e instanceof PrivilegedActionException)
- e = ((PrivilegedActionException) e).getException();
- throw new UserException(e);
- }
- }
-
- protected abstract List<Member> getPersistentMembers(ClassMetaData meta, boolean ignoreTransient);
- /**
- * Generate the given meta-data using reflection.
- * Adds FieldMetaData for each persistent state.
- * Delegate to concrete implementation to determine the persistent
- * members.
- */
- private void populateFromReflection(ClassMetaData meta, boolean ignoreTransient) {
- List<Member> members = getPersistentMembers(meta, ignoreTransient);
- boolean iface = meta.getDescribedType().isInterface();
- // If access is mixed or if the default is currently unknown,
- // process all fields, otherwise only process members of the class
- // level default access type.
-
- String name;
- boolean def;
- FieldMetaData fmd;
- for (int i = 0; i < members.size(); i++) {
- Member member = members.get(i);
- name = getFieldName(member);
- if (name == null || isReservedFieldName(name))
- continue;
-
- def = isDefaultPersistent(meta, member, name, ignoreTransient);
- if (!def && _ignore)
- continue;
-
- // passed the tests; persistent type -- we construct with
- // Object.class because setting backing member will set proper
- // type anyway
- fmd = meta.addDeclaredField(name, Object.class);
- fmd.backingMember(member);
- if (!def) {
- fmd.setExplicit(true);
- fmd.setManagement(FieldMetaData.MANAGE_NONE);
- }
- populate(fmd);
- }
- }
-
- protected void populate(FieldMetaData fmd) {
-
- }
-
- /**
- * Return the list of fields in <code>meta</code> that use field access,
- * or <code>null</code> if a list of fields is unobtainable. An empty list
- * should be returned if the list of fields is obtainable, but there
- * happens to be no field access in <code>meta</code>.
- *
- * This is used for error reporting purposes only, so need not be efficient.
- *
- * This implementation returns <code>null</code>.
- */
- protected List<String> getFieldAccessNames(ClassMetaData meta) {
- return null;
- }
-
- /**
- * Return the list of methods in <code>meta</code> that use property access,
- * or <code>null</code> if a list of methods is unobtainable. An empty list
- * should be returned if the list of methods is obtainable, but there
- * happens to be no property access in <code>meta</code>.
- *
- * This is used for error reporting purposes only, so need not be efficient.
- *
- * This implementation returns <code>null</code>.
- */
- protected List<String> getPropertyAccessNames(ClassMetaData meta) {
- return null;
- }
-
- /**
- * Return the field name for the given member. This will only be invoked
- * on members of the right type (field vs. method). Return null if the
- * member cannot be managed. Default behavior: For fields, returns the
- * field name. For getter methods, returns the minus "get" or "is" with
- * the next letter lower-cased. For other methods, returns null.
- */
- public static String getFieldName(Member member) {
- if (member instanceof Field)
- return member.getName();
- if (member instanceof Method == false)
- return null;
- Method method = (Method) member;
- String name = method.getName();
- if (isNormalGetter(method))
- name = name.substring("get".length());
- else if (isBooleanGetter(method))
- name = name.substring("is".length());
- else
- return null;
-
- if (name.length() == 1)
- return name.toLowerCase();
- return Character.toLowerCase(name.charAt(0)) + name.substring(1);
- }
-
- /**
- * Returns true if the given field name is reserved for unmanaged fields.
- */
- protected boolean isReservedFieldName(String name) {
- // names used by enhancers
- return name.startsWith("openjpa") || name.startsWith("jdo");
- }
-
- /**
- * Return true if the given member is persistent by default. This will
- * only be invoked on members of the right type (field vs. method).
- * Returns false if member is static or final by default.
- *
- * @param name the field name from {@link #getFieldName}
- */
- protected abstract boolean isDefaultPersistent(ClassMetaData meta,
- Member member, String name, boolean ignoreTransient);
-
- /**
- * Gets the backing member of the given field. If the field has not been
- * assigned a backing member then get either the instance field or the
- * getter method depending upon the access style of the defining class.
- * <br>
- * Defining class is used instead of declaring class because this method
- * may be invoked during parsing phase when declaring metadata may not be
- * available.
- */
- @Override
- public Member getBackingMember(FieldMetaData fmd) {
- if (fmd == null)
- return null;
- if (fmd.getBackingMember() != null)
- return fmd.getBackingMember();
- return getMemberByProperty(fmd.getDeclaringMetaData(), fmd.getName(),
- fmd.getAccessType(), true);
- }
-
- @Override
- public Class<?> getUnimplementedExceptionType() {
- return UnsupportedOperationException.class;
- }
-
- /**
- * Helper method; returns true if the given class appears to be
- * user-defined.
- */
- protected static boolean isUserDefined(Class<?> cls) {
- return cls != null && !cls.getName().startsWith("java.")
- && !cls.getName().startsWith ("javax.")
- && !cls.getName().startsWith ("jakarta.");
- }
-
- /**
- * Affirms if the given method matches the following signature
- * <code> public T getXXX() </code>
- * where T is any non-void type.
- */
- public static boolean isNormalGetter(Method method) {
- String methodName = method.getName();
- return startsWith(methodName, "get")
- && method.getParameterTypes().length == 0
- && method.getReturnType() != void.class;
- }
-
- /**
- * Affirms if the given method matches the following signature
- * <code> public boolean isXXX() </code>
- * <code> public Boolean isXXX() </code>
- */
- public static boolean isBooleanGetter(Method method) {
- String methodName = method.getName();
- return startsWith(methodName, "is")
- && method.getParameterTypes().length == 0
- && isBoolean(method.getReturnType());
- }
-
- /**
- * Affirms if the given method signature matches bean-style getter method
- * signature.<br>
- * <code> public T getXXX()</code> where T is any non-void type.<br>
- * or<br>
- * <code> public T isXXX()</code> where T is boolean or Boolean.<br>
- */
- public static boolean isGetter(Method method, boolean includePrivate) {
- if (method == null)
- return false;
- int mods = method.getModifiers();
- if (!(Modifier.isPublic(mods)
- || Modifier.isProtected(mods)
- || (Modifier.isPrivate(mods) && includePrivate))
- || Modifier.isNative(mods)
- || Modifier.isStatic(mods))
- return false;
- return isNormalGetter(method) || isBooleanGetter(method);
- }
-
- /**
- * Affirms if the given full string starts with the given head.
- */
- public static boolean startsWith(String full, String head) {
- return full != null && head != null && full.startsWith(head)
- && full.length() > head.length();
- }
-
- public static boolean isBoolean(Class<?> cls) {
- return cls == boolean.class || cls == Boolean.class;
- }
-
- public static List<String> toNames(List<? extends Member> members) {
- List<String> result = new ArrayList<>();
- for (Member m : members)
- result.add(m.getName());
- return result;
- }
-
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java b/jakarta/src/patch/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java
deleted file mode 100644
index 0c59207..0000000
--- a/jakarta/src/patch/java/org/apache/tomcat/util/modeler/modules/MbeansDescriptorsIntrospectionSource.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.tomcat.util.modeler.modules;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map.Entry;
-
-import javax.management.ObjectName;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.util.modeler.AttributeInfo;
-import org.apache.tomcat.util.modeler.ManagedBean;
-import org.apache.tomcat.util.modeler.OperationInfo;
-import org.apache.tomcat.util.modeler.ParameterInfo;
-import org.apache.tomcat.util.modeler.Registry;
-
-public class MbeansDescriptorsIntrospectionSource extends ModelerSource
-{
- private static final Log log = LogFactory.getLog(MbeansDescriptorsIntrospectionSource.class);
-
- private Registry registry;
- private String type;
- private final List<ObjectName> mbeans = new ArrayList<>();
-
- public void setRegistry(Registry reg) {
- this.registry=reg;
- }
-
- /**
- * Used if a single component is loaded
- *
- * @param type The type
- */
- public void setType( String type ) {
- this.type=type;
- }
-
- public void setSource( Object source ) {
- this.source=source;
- }
-
- @Override
- public List<ObjectName> loadDescriptors(Registry registry, String type,
- Object source) throws Exception {
- setRegistry(registry);
- setType(type);
- setSource(source);
- execute();
- return mbeans;
- }
-
- public void execute() throws Exception {
- if( registry==null ) registry=Registry.getRegistry(null, null);
- try {
- ManagedBean managed = createManagedBean(registry, null,
- (Class<?>)source, type);
- if( managed==null ) return;
- managed.setName( type );
-
- registry.addManagedBean(managed);
-
- } catch( Exception ex ) {
- log.error(sm.getString("modules.readDescriptorsError"), ex);
- }
- }
-
-
-
- // ------------ Implementation for non-declared introspection classes
-
- private static final Hashtable<String,String> specialMethods = new Hashtable<>();
- static {
- specialMethods.put( "preDeregister", "");
- specialMethods.put( "postDeregister", "");
- }
-
- private static final Class<?>[] supportedTypes = new Class[] {
- Boolean.class,
- Boolean.TYPE,
- Byte.class,
- Byte.TYPE,
- Character.class,
- Character.TYPE,
- Short.class,
- Short.TYPE,
- Integer.class,
- Integer.TYPE,
- Long.class,
- Long.TYPE,
- Float.class,
- Float.TYPE,
- Double.class,
- Double.TYPE,
- String.class,
- String[].class,
- BigDecimal.class,
- BigInteger.class,
- ObjectName.class,
- Object[].class,
- java.io.File.class,
- };
-
- /**
- * Check if this class is one of the supported types.
- * If the class is supported, returns true. Otherwise,
- * returns false.
- * @param ret The class to check
- * @return boolean True if class is supported
- */
- private boolean supportedType(Class<?> ret) {
- for (Class<?> supportedType : supportedTypes) {
- if (ret == supportedType) {
- return true;
- }
- }
- if (isBeanCompatible(ret)) {
- return true;
- }
- return false;
- }
-
- /**
- * Check if this class conforms to JavaBeans specifications.
- * If the class is conformant, returns true.
- *
- * @param javaType The class to check
- * @return boolean True if the class is compatible.
- */
- private boolean isBeanCompatible(Class<?> javaType) {
- // Must be a non-primitive and non array
- if (javaType.isArray() || javaType.isPrimitive()) {
- return false;
- }
-
- // Anything in the java or javax package that
- // does not have a defined mapping is excluded.
- if (javaType.getName().startsWith("java.") ||
- javaType.getName().startsWith("javax.") ||
- javaType.getName().startsWith("jakarta.")) {
- return false;
- }
-
- try {
- javaType.getConstructor(new Class[]{});
- } catch (java.lang.NoSuchMethodException e) {
- return false;
- }
-
- // Make sure superclass is compatible
- Class<?> superClass = javaType.getSuperclass();
- if (superClass != null &&
- superClass != java.lang.Object.class &&
- superClass != java.lang.Exception.class &&
- superClass != java.lang.Throwable.class) {
- if (!isBeanCompatible(superClass)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Process the methods and extract 'attributes', methods, etc.
- *
- * @param realClass The class to process
- * @param methods The methods to process
- * @param attMap The attribute map (complete)
- * @param getAttMap The readable attributes map
- * @param setAttMap The settable attributes map
- * @param invokeAttMap The invokable attributes map
- */
- private void initMethods(Class<?> realClass, Method methods[], Hashtable<String,Method> attMap,
- Hashtable<String,Method> getAttMap, Hashtable<String,Method> setAttMap,
- Hashtable<String,Method> invokeAttMap) {
-
- for (Method method : methods) {
- String name = method.getName();
-
- if (Modifier.isStatic(method.getModifiers())) {
- continue;
- }
- if (!Modifier.isPublic(method.getModifiers())) {
- if (log.isDebugEnabled()) {
- log.debug("Not public " + method);
- }
- continue;
- }
- if (method.getDeclaringClass() == Object.class) {
- continue;
- }
- Class<?> params[] = method.getParameterTypes();
-
- if (name.startsWith("get") && params.length == 0) {
- Class<?> ret = method.getReturnType();
- if (!supportedType(ret)) {
- if (log.isDebugEnabled()) {
- log.debug("Unsupported type " + method);
- }
- continue;
- }
- name = unCapitalize(name.substring(3));
-
- getAttMap.put(name, method);
- // just a marker, we don't use the value
- attMap.put(name, method);
- } else if (name.startsWith("is") && params.length == 0) {
- Class<?> ret = method.getReturnType();
- if (Boolean.TYPE != ret) {
- if (log.isDebugEnabled()) {
- log.debug("Unsupported type " + method + " " + ret);
- }
- continue;
- }
- name = unCapitalize(name.substring(2));
-
- getAttMap.put(name, method);
- // just a marker, we don't use the value
- attMap.put(name, method);
-
- } else if (name.startsWith("set") && params.length == 1) {
- if (!supportedType(params[0])) {
- if (log.isDebugEnabled()) {
- log.debug("Unsupported type " + method + " " + params[0]);
- }
- continue;
- }
- name = unCapitalize(name.substring(3));
- setAttMap.put(name, method);
- attMap.put(name, method);
- } else {
- if (params.length == 0) {
- if (specialMethods.get(method.getName()) != null) {
- continue;
- }
- invokeAttMap.put(name, method);
- } else {
- boolean supported = true;
- for (Class<?> param : params) {
- if (!supportedType(param)) {
- supported = false;
- break;
- }
- }
- if (supported) {
- invokeAttMap.put(name, method);
- }
- }
- }
- }
- }
-
- /**
- * XXX Find if the 'className' is the name of the MBean or
- * the real class ( I suppose first )
- * XXX Read (optional) descriptions from a .properties, generated
- * from source
- * XXX Deal with constructors
- *
- * @param registry The Bean registry (not used)
- * @param domain The bean domain (not used)
- * @param realClass The class to analyze
- * @param type The bean type
- * @return ManagedBean The create MBean
- */
- public ManagedBean createManagedBean(Registry registry, String domain,
- Class<?> realClass, String type)
- {
- ManagedBean mbean= new ManagedBean();
-
- Method methods[]=null;
-
- Hashtable<String,Method> attMap = new Hashtable<>();
- // key: attribute val: getter method
- Hashtable<String,Method> getAttMap = new Hashtable<>();
- // key: attribute val: setter method
- Hashtable<String,Method> setAttMap = new Hashtable<>();
- // key: operation val: invoke method
- Hashtable<String,Method> invokeAttMap = new Hashtable<>();
-
- methods = realClass.getMethods();
-
- initMethods(realClass, methods, attMap, getAttMap, setAttMap, invokeAttMap );
-
- try {
-
- Enumeration<String> en = attMap.keys();
- while( en.hasMoreElements() ) {
- String name = en.nextElement();
- AttributeInfo ai=new AttributeInfo();
- ai.setName( name );
- Method gm = getAttMap.get(name);
- if( gm!=null ) {
- //ai.setGetMethodObj( gm );
- ai.setGetMethod( gm.getName());
- Class<?> t=gm.getReturnType();
- if( t!=null )
- ai.setType( t.getName() );
- }
- Method sm = setAttMap.get(name);
- if( sm!=null ) {
- //ai.setSetMethodObj(sm);
- Class<?> t = sm.getParameterTypes()[0];
- if( t!=null )
- ai.setType( t.getName());
- ai.setSetMethod( sm.getName());
- }
- ai.setDescription("Introspected attribute " + name);
- if( log.isDebugEnabled()) log.debug("Introspected attribute " +
- name + " " + gm + " " + sm);
- if( gm==null )
- ai.setReadable(false);
- if( sm==null )
- ai.setWriteable(false);
- if( sm!=null || gm!=null )
- mbean.addAttribute(ai);
- }
-
- // This map is populated by iterating the methods (which end up as
- // values in the Map) and obtaining the key from the value. It is
- // impossible for a key to be associated with a null value.
- for (Entry<String,Method> entry : invokeAttMap.entrySet()) {
- String name = entry.getKey();
- Method m = entry.getValue();
-
- OperationInfo op=new OperationInfo();
- op.setName(name);
- op.setReturnType(m.getReturnType().getName());
- op.setDescription("Introspected operation " + name);
- Class<?> parms[] = m.getParameterTypes();
- for(int i=0; i<parms.length; i++ ) {
- ParameterInfo pi=new ParameterInfo();
- pi.setType(parms[i].getName());
- pi.setName(("param" + i).intern());
- pi.setDescription(("Introspected parameter param" + i).intern());
- op.addParameter(pi);
- }
- mbean.addOperation(op);
- }
-
- if( log.isDebugEnabled())
- log.debug("Setting name: " + type );
- mbean.setName( type );
-
- return mbean;
- } catch( Exception ex ) {
- ex.printStackTrace();
- return null;
- }
- }
-
-
- // -------------------- Utils --------------------
- /**
- * Converts the first character of the given
- * String into lower-case.
- *
- * @param name The string to convert
- * @return String
- */
- private static String unCapitalize(String name) {
- if (name == null || name.length() == 0) {
- return name;
- }
- char chars[] = name.toCharArray();
- chars[0] = Character.toLowerCase(chars[0]);
- return new String(chars);
- }
-
-}
diff --git a/jakarta/src/patch/java/org/apache/webbeans/proxy/AbstractProxyFactory.java b/jakarta/src/patch/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
deleted file mode 100644
index eec5ba5..0000000
--- a/jakarta/src/patch/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.webbeans.proxy;
-
-import static org.apache.xbean.asm7.ClassReader.SKIP_CODE;
-import static org.apache.xbean.asm7.ClassReader.SKIP_DEBUG;
-import static org.apache.xbean.asm7.ClassReader.SKIP_FRAMES;
-
-import java.io.InputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-import org.apache.webbeans.config.WebBeansContext;
-import org.apache.webbeans.exception.ProxyGenerationException;
-import org.apache.webbeans.exception.WebBeansException;
-import org.apache.webbeans.spi.DefiningClassService;
-import org.apache.xbean.asm7.ClassReader;
-import org.apache.xbean.asm7.ClassWriter;
-import org.apache.xbean.asm7.MethodVisitor;
-import org.apache.xbean.asm7.Opcodes;
-import org.apache.xbean.asm7.Type;
-import org.apache.xbean.asm7.shade.commons.EmptyVisitor;
-
-/**
- * Base class for all OWB Proxy factories
- */
-public abstract class AbstractProxyFactory
-{
- public static final int MAX_CLASSLOAD_TRIES = 10000;
-
- /**
- * This is needed as the Modifier#VARARGS is not (yet) public.
- * Note that the bitcode is the same as Modifier#TRANSIENT.
- * But 'varargs' is only for methods, whereas 'transient' is only for fields.
- */
- public static final int MODIFIER_VARARGS = 0x00000080;
-
- protected final Unsafe unsafe;
-
- private final DefiningClassService definingService;
-
- protected WebBeansContext webBeansContext;
-
- private final int javaVersion;
-
-
- /**
- * The name of the field which stores the passivationID of the Bean this proxy serves.
- * This is needed in case the proxy gets de-serialized back into a JVM
- * which didn't have this bean loaded yet.
- */
- public static final String FIELD_BEAN_PASSIVATION_ID = "owbBeanPassivationId";
-
-
- protected AbstractProxyFactory(WebBeansContext webBeansContext)
- {
- this.webBeansContext = webBeansContext;
- javaVersion = determineDefaultJavaVersion();
- unsafe = new Unsafe();
- definingService = webBeansContext.getService(DefiningClassService.class);
- }
-
- private int determineDefaultJavaVersion()
- {
- String javaVersionProp = webBeansContext.getOpenWebBeansConfiguration().getGeneratorJavaVersion();
- if (javaVersionProp == null) // try to align on the runtime
- {
- javaVersionProp = System.getProperty("java.version");
- }
- if (javaVersionProp != null)
- {
- if (javaVersionProp.startsWith("1.8"))
- {
- return Opcodes.V1_8;
- }
- else if (javaVersionProp.startsWith("9") || javaVersionProp.startsWith("1.9"))
- {
- return Opcodes.V9;
- }
- else if (javaVersionProp.startsWith("10"))
- {
- return Opcodes.V10;
- }
- else if (javaVersionProp.startsWith("11"))
- {
- return Opcodes.V11;
- }
- else if (javaVersionProp.startsWith("12"))
- {
- return Opcodes.V12;
- }
- else if (javaVersionProp.startsWith("13"))
- {
- return Opcodes.V13;
- }
- else
- {
- try
- {
- final int i = Integer.parseInt(javaVersionProp);
- if (i > 13)
- {
- return Opcodes.V13 + (i - 13);
- }
- }
- catch (final NumberFormatException nfe)
- {
- // let's default
- }
- }
- }
-
- // the fallback is the lowest one to ensure it supports all possible classes of current environments
- return Opcodes.V1_8;
- }
-
-
- protected ClassLoader getProxyClassLoader(Class<?> beanClass)
- {
- if (definingService != null)
- {
- return definingService.getProxyClassLoader(beanClass);
- }
- return webBeansContext.getApplicationBoundaryService().getBoundaryClassLoader(beanClass);
- }
-
- /**
- * @return the marker interface which should be used for this proxy.
- */
- protected abstract Class getMarkerInterface();
-
- /**
- * generate the bytecode for creating the instance variables of the class
- */
- protected abstract void createInstanceVariables(ClassWriter cw, Class<?> classToProxy, String classFileName);
-
- /**
- * generate the bytecode for serialization.
- */
- protected abstract void createSerialisation(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName);
-
- /**
- * Each of our interceptor/decorator proxies has exactly 1 constructor
- * which invokes the super ct + sets the delegation field.
- *
- * @param cw
- * @param classToProxy
- * @param classFileName
- * @throws org.apache.webbeans.exception.ProxyGenerationException
- */
- protected abstract void createConstructor(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName, Constructor<?> injectConstructor)
- throws ProxyGenerationException;
-
- /**
- * generate the bytecode for invoking all intercepted methods
- */
- protected abstract void delegateInterceptedMethods(ClassLoader classLoader, ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, Method[] interceptedMethods)
- throws ProxyGenerationException;
-
- /**
- * generate the bytecode for invoking all non-intercepted methods
- */
- protected abstract void delegateNonInterceptedMethods(ClassLoader classLoader, ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, Method[] noninterceptedMethods)
- throws ProxyGenerationException;
-
- /**
- * Detect a free classname based on the given one
- * @param proxyClassName
- * @return
- */
- protected String getUnusedProxyClassName(ClassLoader classLoader, String proxyClassName)
- {
- proxyClassName = fixPreservedPackages(proxyClassName);
-
- String finalName = proxyClassName;
-
- for (int i = 0; i < MAX_CLASSLOAD_TRIES; i++)
- {
- try
- {
- finalName = proxyClassName + i;
- Class.forName(finalName, true, classLoader);
- }
- catch (ClassNotFoundException cnfe)
- {
- // this is exactly what we need!
- return finalName;
- }
- // otherwise we continue ;)
- }
-
- throw new WebBeansException("Unable to detect a free proxy class name based on: " + proxyClassName);
- }
-
- protected <T> String getSignedClassProxyName(final Class<T> classToProxy)
- {
- // avoid java.lang.SecurityException: class's signer information
- // does not match signer information of other classes in the same package
- return "org.apache.webbeans.custom.signed." + classToProxy.getName();
- }
-
- protected String fixPreservedPackages(String proxyClassName)
- {
- proxyClassName = fixPreservedPackage(proxyClassName, "java.");
- proxyClassName = fixPreservedPackage(proxyClassName, "javax.");
- proxyClassName = fixPreservedPackage(proxyClassName, "jakarta.");
- proxyClassName = fixPreservedPackage(proxyClassName, "sun.misc.");
-
- return proxyClassName;
- }
- /**
- * Detect if the provided className is in the forbidden package.
- * If so, move it to org.apache.webbeans.custom.
- * @param forbiddenPackagePrefix including the '.', e.g. 'javax.'
- */
- private String fixPreservedPackage(String className, String forbiddenPackagePrefix)
- {
- String fixedClassName = className;
-
- if (className.startsWith(forbiddenPackagePrefix))
- {
- fixedClassName = "org.apache.webbeans.custom." + className.substring(forbiddenPackagePrefix.length());
- }
-
- return fixedClassName;
- }
-
- protected <T> Class<T> createProxyClass(ClassLoader classLoader, String proxyClassName, Class<T> classToProxy,
- Method[] interceptedMethods, Method[] nonInterceptedMethods)
- throws ProxyGenerationException
- {
- return createProxyClass(classLoader, proxyClassName, classToProxy, interceptedMethods, nonInterceptedMethods, null);
- }
-
- /**
- * @param classLoader to use for creating the class in
- * @param classToProxy the class for which a subclass will get generated
- * @param interceptedMethods the list of intercepted or decorated business methods.
- * @param nonInterceptedMethods all methods which are <b>not</b> intercepted nor decorated and shall get delegated directly
- * @param <T>
- * @return the proxy class
- */
- protected <T> Class<T> createProxyClass(ClassLoader classLoader, String proxyClassName, Class<T> classToProxy,
- Method[] interceptedMethods, Method[] nonInterceptedMethods,
- Constructor<T> constructor)
- throws ProxyGenerationException
- {
- String proxyClassFileName = proxyClassName.replace('.', '/');
-
- byte[] proxyBytes = generateProxy(classLoader,
- classToProxy,
- proxyClassName,
- proxyClassFileName,
- sortOutDuplicateMethods(interceptedMethods),
- sortOutDuplicateMethods(nonInterceptedMethods),
- constructor);
-
- if (definingService != null)
- {
- return definingService.defineAndLoad(proxyClassName, proxyBytes, classToProxy);
- }
- return unsafe.defineAndLoadClass(classLoader, proxyClassName, proxyBytes);
- }
-
- private Method[] sortOutDuplicateMethods(Method[] methods)
- {
- if (methods == null || methods.length == 0)
- {
- return null;
- }
-
- ArrayList<Method> duplicates = new ArrayList<>();
-
- for (Method outer : methods)
- {
- for (Method inner : methods)
- {
- if (inner != outer
- && hasSameSignature(outer, inner)
- && !(duplicates.contains(outer) || duplicates.contains(inner)))
- {
- duplicates.add(inner);
- }
- }
- }
-
- ArrayList<Method> outsorted = new ArrayList<>(Arrays.asList(methods));
- outsorted.removeAll(duplicates);
- return outsorted.toArray(new Method[outsorted.size()]);
- }
-
- private boolean hasSameSignature(Method a, Method b)
- {
- return a.getName().equals(b.getName())
- && a.getReturnType().equals(b.getReturnType())
- && Arrays.equals(a.getParameterTypes(), b.getParameterTypes());
- }
-
- private byte[] generateProxy(ClassLoader classLoader, Class<?> classToProxy, String proxyClassName, String proxyClassFileName,
- Method[] interceptedMethods, Method[] nonInterceptedMethods, Constructor<?> constructor)
- throws ProxyGenerationException
- {
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
- String classFileName = classToProxy.getName().replace('.', '/');
-
- String[] interfaceNames = {Type.getInternalName(getMarkerInterface())};
- String superClassName = classFileName;
-
- if (classToProxy.isInterface())
- {
- interfaceNames = new String[]{Type.getInternalName(classToProxy), interfaceNames[0]};
- superClassName = Type.getInternalName(Object.class);
- }
-
- cw.visit(findJavaVersion(classToProxy), Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER + Opcodes.ACC_SYNTHETIC, proxyClassFileName, null, superClassName, interfaceNames);
- cw.visitSource(classFileName + ".java", null);
-
- createInstanceVariables(cw, classToProxy, classFileName);
- createSerialisation(cw, proxyClassFileName, classToProxy, classFileName);
-
-
-
- // create a static String Field which contains the passivationId of the Bean or null if not PassivationCapable
- cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC,
- FIELD_BEAN_PASSIVATION_ID, Type.getDescriptor(String.class), null, null).visitEnd();
-
- createConstructor(cw, proxyClassFileName, classToProxy, classFileName, constructor);
-
-
- if (nonInterceptedMethods != null)
- {
- delegateNonInterceptedMethods(classLoader, cw, proxyClassFileName, classToProxy, nonInterceptedMethods);
- }
-
- if (interceptedMethods != null)
- {
- delegateInterceptedMethods(classLoader, cw, proxyClassFileName, classToProxy, interceptedMethods);
- }
-
- return cw.toByteArray();
- }
-
- private int findJavaVersion(final Class<?> from)
- {
- final String resource = from.getName().replace('.', '/') + ".class";
- try (final InputStream stream = from.getClassLoader().getResourceAsStream(resource))
- {
- if (stream == null)
- {
- return javaVersion;
- }
- final ClassReader reader = new ClassReader(stream);
- final VersionVisitor visitor = new VersionVisitor();
- reader.accept(visitor, SKIP_DEBUG + SKIP_CODE + SKIP_FRAMES);
- if (visitor.version != 0)
- {
- return visitor.version;
- }
- }
- catch (final Exception e)
- {
- // no-op
- }
- // mainly for JVM classes - outside the classloader, find to fallback on the JVM version
- return javaVersion;
- }
-
-
-
- protected boolean unproxyableMethod(Method delegatedMethod)
- {
- int modifiers = delegatedMethod.getModifiers();
-
- return (modifiers & (Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL | Modifier.NATIVE)) > 0 ||
- "finalize".equals(delegatedMethod.getName()) || delegatedMethod.isBridge();
- }
-
- /**
- * @return the wrapper type for a primitive, e.g. java.lang.Integer for int
- */
- protected String getWrapperType(Class<?> type)
- {
- if (Integer.TYPE.equals(type))
- {
- return Integer.class.getCanonicalName().replace('.', '/');
- }
- else if (Boolean.TYPE.equals(type))
- {
- return Boolean.class.getCanonicalName().replace('.', '/');
- }
- else if (Character.TYPE.equals(type))
- {
- return Character.class.getCanonicalName().replace('.', '/');
- }
- else if (Byte.TYPE.equals(type))
- {
- return Byte.class.getCanonicalName().replace('.', '/');
- }
- else if (Short.TYPE.equals(type))
- {
- return Short.class.getCanonicalName().replace('.', '/');
- }
- else if (Float.TYPE.equals(type))
- {
- return Float.class.getCanonicalName().replace('.', '/');
- }
- else if (Long.TYPE.equals(type))
- {
- return Long.class.getCanonicalName().replace('.', '/');
- }
- else if (Double.TYPE.equals(type))
- {
- return Double.class.getCanonicalName().replace('.', '/');
- }
- else if (Void.TYPE.equals(type))
- {
- return Void.class.getCanonicalName().replace('.', '/');
- }
-
- throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type");
- }
-
- /**
- * Returns the appropriate bytecode instruction to load a value from a variable to the stack
- *
- * @param type Type to load
- * @return Bytecode instruction to use
- */
- protected int getVarInsn(Class<?> type)
- {
- if (type.isPrimitive())
- {
- if (Integer.TYPE.equals(type))
- {
- return Opcodes.ILOAD;
- }
- else if (Boolean.TYPE.equals(type))
- {
- return Opcodes.ILOAD;
- }
- else if (Character.TYPE.equals(type))
- {
- return Opcodes.ILOAD;
- }
- else if (Byte.TYPE.equals(type))
- {
- return Opcodes.ILOAD;
- }
- else if (Short.TYPE.equals(type))
- {
- return Opcodes.ILOAD;
- }
- else if (Float.TYPE.equals(type))
- {
- return Opcodes.FLOAD;
- }
- else if (Long.TYPE.equals(type))
- {
- return Opcodes.LLOAD;
- }
- else if (Double.TYPE.equals(type))
- {
- return Opcodes.DLOAD;
- }
- }
-
- throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type");
- }
-
- /**
- * Invokes the most appropriate bytecode instruction to put a number on the stack
- *
- * @param mv
- * @param i
- */
- protected void pushIntOntoStack(MethodVisitor mv, int i)
- {
- if (i == 0)
- {
- mv.visitInsn(Opcodes.ICONST_0);
- }
- else if (i == 1)
- {
- mv.visitInsn(Opcodes.ICONST_1);
- }
- else if (i == 2)
- {
- mv.visitInsn(Opcodes.ICONST_2);
- }
- else if (i == 3)
- {
- mv.visitInsn(Opcodes.ICONST_3);
- }
- else if (i == 4)
- {
- mv.visitInsn(Opcodes.ICONST_4);
- }
- else if (i == 5)
- {
- mv.visitInsn(Opcodes.ICONST_5);
- }
- else if (i > 5 && i <= 255)
- {
- mv.visitIntInsn(Opcodes.BIPUSH, i);
- }
- else
- {
- mv.visitIntInsn(Opcodes.SIPUSH, i);
- }
- }
-
- /**
- * Gets the appropriate bytecode instruction for RETURN, according to what type we need to return
- *
- * @param type Type the needs to be returned
- * @return The matching bytecode instruction
- */
- protected int getReturnInsn(Class<?> type)
- {
- if (type.isPrimitive())
- {
- if (Void.TYPE.equals(type))
- {
- return Opcodes.RETURN;
- }
- if (Integer.TYPE.equals(type))
- {
- return Opcodes.IRETURN;
- }
- else if (Boolean.TYPE.equals(type))
- {
- return Opcodes.IRETURN;
- }
- else if (Character.TYPE.equals(type))
- {
- return Opcodes.IRETURN;
- }
- else if (Byte.TYPE.equals(type))
- {
- return Opcodes.IRETURN;
- }
- else if (Short.TYPE.equals(type))
- {
- return Opcodes.IRETURN;
- }
- else if (Float.TYPE.equals(type))
- {
- return Opcodes.FRETURN;
- }
- else if (Long.TYPE.equals(type))
- {
- return Opcodes.LRETURN;
- }
- else if (Double.TYPE.equals(type))
- {
- return Opcodes.DRETURN;
- }
- }
-
- return Opcodes.ARETURN;
- }
-
- /**
- * Gets the string to use for CHECKCAST instruction, returning the correct value for any type, including primitives and arrays
- *
- * @param returnType The type to cast to with CHECKCAST
- * @return CHECKCAST parameter
- */
- protected String getCastType(Class<?> returnType)
- {
- if (returnType.isPrimitive())
- {
- return getWrapperType(returnType);
- }
- else
- {
- return Type.getInternalName(returnType);
- }
- }
-
- /**
- * Returns the name of the Java method to call to get the primitive value from an Object - e.g. intValue for java.lang.Integer
- *
- * @param type Type whose primitive method we want to lookup
- * @return The name of the method to use
- */
- protected String getPrimitiveMethod(Class<?> type)
- {
- if (Integer.TYPE.equals(type))
- {
- return "intValue";
- }
- else if (Boolean.TYPE.equals(type))
- {
- return "booleanValue";
- }
- else if (Character.TYPE.equals(type))
- {
- return "charValue";
- }
- else if (Byte.TYPE.equals(type))
- {
- return "byteValue";
- }
- else if (Short.TYPE.equals(type))
- {
- return "shortValue";
- }
- else if (Float.TYPE.equals(type))
- {
- return "floatValue";
- }
- else if (Long.TYPE.equals(type))
- {
- return "longValue";
- }
- else if (Double.TYPE.equals(type))
- {
- return "doubleValue";
- }
-
- throw new IllegalStateException("Type: " + type.getCanonicalName() + " is not a primitive type");
- }
-
- protected void generateReturn(MethodVisitor mv, Method delegatedMethod)
- {
- Class<?> returnType = delegatedMethod.getReturnType();
- mv.visitInsn(getReturnInsn(returnType));
- }
-
- /**
- * Create an Object[] parameter which contains all the parameters of the currently invoked method
- * and store this array for use in the call stack.
- * @param mv
- * @param parameterTypes
- */
- protected void pushMethodParameterArray(MethodVisitor mv, Class<?>[] parameterTypes)
- {
- // need to construct the array of objects passed in
- // create the Object[]
- createArrayDefinition(mv, parameterTypes.length, Object.class);
-
- int index = 1;
- // push parameters into array
- for (int i = 0; i < parameterTypes.length; i++)
- {
- // keep copy of array on stack
- mv.visitInsn(Opcodes.DUP);
-
- Class<?> parameterType = parameterTypes[i];
-
- // push number onto stack
- pushIntOntoStack(mv, i);
-
- if (parameterType.isPrimitive())
- {
- String wrapperType = getWrapperType(parameterType);
- mv.visitVarInsn(getVarInsn(parameterType), index);
-
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, wrapperType, "valueOf",
- "(" + Type.getDescriptor(parameterType) + ")L" + wrapperType + ";", false);
- mv.visitInsn(Opcodes.AASTORE);
-
- if (Long.TYPE.equals(parameterType) || Double.TYPE.equals(parameterType))
- {
- index += 2;
- }
- else
- {
- index++;
- }
- }
- else
- {
- mv.visitVarInsn(Opcodes.ALOAD, index);
- mv.visitInsn(Opcodes.AASTORE);
- index++;
- }
- }
- }
-
- /**
- * pushes an array of the specified size to the method visitor. The generated bytecode will leave
- * the new array at the top of the stack.
- *
- * @param mv MethodVisitor to use
- * @param size Size of the array to create
- * @param type Type of array to create
- * @throws ProxyGenerationException
- */
- protected void createArrayDefinition(MethodVisitor mv, int size, Class<?> type)
- throws ProxyGenerationException
- {
- // create a new array of java.lang.class (2)
-
- if (size < 0)
- {
- throw new ProxyGenerationException("Array size cannot be less than zero");
- }
-
- pushIntOntoStack(mv, size);
-
- mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getCanonicalName().replace('.', '/'));
- }
-
-
- private static class VersionVisitor extends EmptyVisitor
- {
- private int version;
-
- @Override
- public void visit(final int version, final int access, final String name,
- final String signature, final String superName, final String[] interfaces)
- {
- this.version = version;
- }
- }
-}
\ No newline at end of file
diff --git a/jakarta/src/patch/java/org/eclipse/persistence/internal/jpa/deployment/JavaSECMPInitializer.java b/jakarta/src/patch/java/org/eclipse/persistence/internal/jpa/deployment/JavaSECMPInitializer.java
deleted file mode 100644
index 3b773b3..0000000
--- a/jakarta/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/jakarta/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataAsmFactory.java b/jakarta/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataAsmFactory.java
deleted file mode 100644
index 04fce33..0000000
--- a/jakarta/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/jakarta/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataClass.java b/jakarta/src/patch/java/org/eclipse/persistence/internal/jpa/metadata/accessors/objects/MetadataClass.java
deleted file mode 100644
index 0670e30..0000000
--- a/jakarta/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/jakarta/src/patch/java/org/eclipse/persistence/jaxb/javamodel/Helper.java b/jakarta/src/patch/java/org/eclipse/persistence/jaxb/javamodel/Helper.java
deleted file mode 100644
index a8318eb..0000000
--- a/jakarta/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/jakarta/src/patch/java/org/eclipse/persistence/jaxb/javamodel/reflection/JavaClassImpl.java b/jakarta/src/patch/java/org/eclipse/persistence/jaxb/javamodel/reflection/JavaClassImpl.java
deleted file mode 100644
index a1c74ba..0000000
--- a/jakarta/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/jakarta/src/patch/java/org/eclipse/persistence/jaxb/rs/MOXyJsonProvider.java b/jakarta/src/patch/java/org/eclipse/persistence/jaxb/rs/MOXyJsonProvider.java
deleted file mode 100644
index 7bce14a..0000000
--- a/jakarta/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/jakarta/src/patch/java/org/eclipse/persistence/jpa/rs/PersistenceFactoryBase.java b/jakarta/src/patch/java/org/eclipse/persistence/jpa/rs/PersistenceFactoryBase.java
deleted file mode 100644
index c83fdf6..0000000
--- a/jakarta/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);
- }
- }
... 1166 lines suppressed ...