You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by st...@apache.org on 2023/07/17 20:33:09 UTC
[openjpa] branch master updated: OPENJPA-2911 openjpa-lib without Serp
This is an automated email from the ASF dual-hosted git repository.
struberg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git
The following commit(s) were added to refs/heads/master by this push:
new 86c266df7 OPENJPA-2911 openjpa-lib without Serp
86c266df7 is described below
commit 86c266df7a2d2840c0f413ef3ea70741ae1bef3a
Author: Mark Struberg <st...@apache.org>
AuthorDate: Mon Jul 17 22:31:18 2023 +0200
OPENJPA-2911 openjpa-lib without Serp
---
.../openjpa/jdbc/meta/ReverseMappingTool.java | 3 +-
openjpa-kernel/pom.xml | 5 +
.../openjpa/enhance/DynamicStorageGenerator.java | 2 +-
.../org/apache/openjpa/enhance/PCEnhancer.java | 6 +-
.../apache/openjpa/enhance/SerpPrivacyHelper.java | 97 ++++++++++++
.../openjpa/meta/InterfaceImplGenerator.java | 11 +-
.../org/apache/openjpa/util/GeneratedClasses.java | 3 +-
openjpa-lib/pom.xml | 5 +-
.../lib/meta/ClassAnnotationMetaDataFilter.java | 174 ++++-----------------
.../apache/openjpa/lib/meta/ClassArgParser.java | 52 ++++--
.../apache/openjpa/lib/util/J2DoPrivHelper.java | 128 ---------------
.../org/apache/openjpa/lib/util/JavaVersions.java | 7 +-
.../openjpa/lib/util/TemporaryClassLoader.java | 48 +++---
.../apache/openjpa/lib/util/StringUtilTest.java | 2 -
.../enhance/TestEnhancementWithMultiplePUs.java | 6 +-
15 files changed, 218 insertions(+), 331 deletions(-)
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ReverseMappingTool.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ReverseMappingTool.java
index 8776d3526..58437e27a 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ReverseMappingTool.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ReverseMappingTool.java
@@ -45,6 +45,7 @@ import java.util.TreeSet;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.enhance.ApplicationIdTool;
import org.apache.openjpa.enhance.CodeGenerator;
+import org.apache.openjpa.enhance.SerpPrivacyHelper;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
@@ -183,7 +184,7 @@ public class ReverseMappingTool
private final Map _tables = new HashMap();
private final Project _project = new Project();
private final BCClassLoader _loader = AccessController
- .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(_project));
+ .doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(_project));
private StrategyInstaller _strat = null;
private String _package = null;
private File _dir = null;
diff --git a/openjpa-kernel/pom.xml b/openjpa-kernel/pom.xml
index b1eb29b08..01b139724 100644
--- a/openjpa-kernel/pom.xml
+++ b/openjpa-kernel/pom.xml
@@ -66,6 +66,11 @@
<version>4.2.0</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <!-- TODO REMOVE -->
+ <groupId>net.sourceforge.serp</groupId>
+ <artifactId>serp</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-asm9-shaded</artifactId>
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
index 9bc1fd000..e1b2b85b1 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/DynamicStorageGenerator.java
@@ -97,7 +97,7 @@ public class DynamicStorageGenerator {
// the project/classloader for the classes.
private final Project _project = new Project();
private final BCClassLoader _loader =
- AccessController.doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(
+ AccessController.doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(
_project, AccessController.doPrivileged(J2DoPrivHelper
.getClassLoaderAction(DynamicStorage.class))));
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
index 8fa4efbd0..29f0d0c8a 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCEnhancer.java
@@ -233,8 +233,7 @@ public class PCEnhancer {
* repository.
*/
public PCEnhancer(OpenJPAConfiguration conf, Class<?> type) {
- this(conf, AccessController.doPrivileged(J2DoPrivHelper
- .loadProjectClassAction(new Project(), type)),
+ this(conf, AccessController.doPrivileged(SerpPrivacyHelper.loadProjectClassAction(new Project(), type)),
(MetaDataRepository) null);
}
@@ -244,8 +243,7 @@ public class PCEnhancer {
* and then loading from <code>conf</code>'s repository.
*/
public PCEnhancer(OpenJPAConfiguration conf, ClassMetaData meta) {
- this(conf, AccessController.doPrivileged(J2DoPrivHelper
- .loadProjectClassAction(new Project(), meta.getDescribedType())),
+ this(conf, AccessController.doPrivileged(SerpPrivacyHelper.loadProjectClassAction(new Project(), meta.getDescribedType())),
meta.getRepository());
}
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java
new file mode 100644
index 000000000..7ffdab287
--- /dev/null
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/SerpPrivacyHelper.java
@@ -0,0 +1,97 @@
+/*
+ * 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.security.PrivilegedAction;
+
+import org.apache.openjpa.lib.util.J2DoPrivHelper;
+
+import serp.bytecode.BCClass;
+import serp.bytecode.BCClassLoader;
+import serp.bytecode.BCField;
+import serp.bytecode.Project;
+
+/**
+ *
+ * @Deprecated just for getting rid of Serp in one place
+ */
+public class SerpPrivacyHelper extends J2DoPrivHelper {
+
+ /**
+ * Return a PrivilegeAction object for new BCClassLoader().
+ *
+ * Requires security policy:
+ * 'permission java.lang.RuntimePermission "createClassLoader";'
+ *
+ * @return BCClassLoader
+ */
+ public static PrivilegedAction<BCClassLoader> newBCClassLoaderAction(
+ final Project project, final ClassLoader parent) {
+ return new PrivilegedAction<BCClassLoader>() {
+ @Override
+ public BCClassLoader run() {
+ return new BCClassLoader(project, parent);
+ }
+ };
+ }
+
+ public static PrivilegedAction<BCClassLoader> newBCClassLoaderAction(
+ final Project project) {
+ return new PrivilegedAction<BCClassLoader>() {
+ @Override
+ public BCClassLoader run() {
+ return new BCClassLoader(project);
+ }
+ };
+ }
+
+ /**
+ * Return a PrivilegeAction object for BCClass.getFields().
+ *
+ * Requires security policy:
+ * 'permission java.lang.RuntimePermission "getClassLoader";'
+ *
+ * @return BCField
+ */
+ public static PrivilegedAction<BCField[]> getBCClassFieldsAction(
+ final BCClass bcClass, final String fieldName) {
+ return new PrivilegedAction<BCField []>() {
+ @Override
+ public BCField [] run() {
+ return bcClass.getFields(fieldName);
+ }
+ };
+ }
+
+ /**
+ * Return a PrivilegeAction object for Project.loadClass().
+ *
+ * Requires security policy:
+ * 'permission java.lang.RuntimePermission "createClassLoader";'
+ *
+ * @return BCClass
+ */
+ public static PrivilegedAction<BCClass> loadProjectClassAction(
+ final Project project, final Class<?> clazz) {
+ return new PrivilegedAction<BCClass>() {
+ @Override
+ public BCClass run() {
+ return project.loadClass(clazz);
+ }
+ };
+ }
+}
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
index a94946da4..11324f9bc 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/InterfaceImplGenerator.java
@@ -28,6 +28,7 @@ import java.util.Set;
import java.util.WeakHashMap;
import org.apache.openjpa.enhance.PCEnhancer;
+import org.apache.openjpa.enhance.SerpPrivacyHelper;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
@@ -81,18 +82,18 @@ class InterfaceImplGenerator {
ClassLoader parentLoader = AccessController.doPrivileged(
J2DoPrivHelper.getClassLoaderAction(iface));
BCClassLoader loader = AccessController
- .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(_project,
- parentLoader));
+ .doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(_project,
+ parentLoader));
BCClassLoader enhLoader = AccessController
- .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(_enhProject,
- parentLoader));
+ .doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(_enhProject,
+ parentLoader));
BCClass bc = _project.loadClass(getClassName(meta));
bc.declareInterface(iface);
ClassMetaData sup = meta.getPCSuperclassMetaData();
if (sup != null) {
bc.setSuperclass(sup.getInterfaceImpl());
enhLoader = AccessController
- .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(
+ .doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(
_enhProject, AccessController
.doPrivileged(J2DoPrivHelper.getClassLoaderAction(sup
.getInterfaceImpl()))));
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/GeneratedClasses.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/GeneratedClasses.java
index 5073e5b6a..e72b4f5b5 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/GeneratedClasses.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/GeneratedClasses.java
@@ -20,6 +20,7 @@ package org.apache.openjpa.util;
import java.security.AccessController;
+import org.apache.openjpa.enhance.SerpPrivacyHelper;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import serp.bytecode.BCClass;
@@ -60,7 +61,7 @@ public class GeneratedClasses {
*/
public static Class loadBCClass(BCClass bc, ClassLoader loader) {
BCClassLoader bcloader = AccessController
- .doPrivileged(J2DoPrivHelper.newBCClassLoaderAction(bc
+ .doPrivileged(SerpPrivacyHelper.newBCClassLoaderAction(bc
.getProject(), loader));
try {
Class c = Class.forName(bc.getName(), true, bcloader);
diff --git a/openjpa-lib/pom.xml b/openjpa-lib/pom.xml
index abaddc10b..b65e00098 100644
--- a/openjpa-lib/pom.xml
+++ b/openjpa-lib/pom.xml
@@ -70,8 +70,9 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>net.sourceforge.serp</groupId>
- <artifactId>serp</artifactId>
+ <groupId>org.apache.xbean</groupId>
+ <artifactId>xbean-asm9-shaded</artifactId>
+ <version>${xbean.version}</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java
index 4dbe4ec90..2a35d8bf8 100644
--- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java
+++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassAnnotationMetaDataFilter.java
@@ -19,11 +19,17 @@
package org.apache.openjpa.lib.meta;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
+import org.apache.xbean.asm9.AnnotationVisitor;
+import org.apache.xbean.asm9.ClassReader;
+import org.apache.xbean.asm9.ClassVisitor;
+import org.apache.xbean.asm9.Opcodes;
+import org.apache.xbean.asm9.Type;
-import serp.bytecode.lowlevel.ConstantPoolTable;
/**
* Filter that looks for classes with one of a set of annotations.
@@ -34,10 +40,9 @@ import serp.bytecode.lowlevel.ConstantPoolTable;
*/
public class ClassAnnotationMetaDataFilter implements MetaDataFilter {
- private final String[] _annos;
+ private final Set<String> _annos;
- private static final Localizer _loc = Localizer.forPackage
- (ClassAnnotationMetaDataFilter.class);
+ private static final Localizer _loc = Localizer.forPackage(ClassAnnotationMetaDataFilter.class);
private Log _log = null;
/**
@@ -51,153 +56,26 @@ public class ClassAnnotationMetaDataFilter implements MetaDataFilter {
* Constructor; supply annotations to match against.
*/
public ClassAnnotationMetaDataFilter(Class<?>[] annos) {
- _annos = new String[annos.length];
- for (int i = 0; i < annos.length; i++)
- _annos[i] = "L" + annos[i].getName().replace('.', '/') + ";";
+ _annos = new HashSet<>();
+ for (Class<?> anno : annos) {
+ _annos.add(Type.getDescriptor(anno));
+ }
}
@Override
public boolean matches(Resource rsrc) throws IOException {
- if (_annos.length == 0 || !rsrc.getName().endsWith(".class"))
+ if (_annos.isEmpty() || !rsrc.getName().endsWith(".class")) {
return false;
-
- try {
- ConstantPoolTable table = new ConstantPoolTable(rsrc.getContent());
- int idx = table.getEndIndex();
- idx += 6; // skip access, cls, super
-
- // skip interfaces
- int interfaces = table.readUnsignedShort(idx);
- idx += 2 + interfaces * 2;
-
- // skip fields and methods
- int fields = table.readUnsignedShort(idx);
- idx += 2;
- for (int i = 0; i < fields; i++)
- idx += skipFieldOrMethod(table, idx);
- int methods = table.readUnsignedShort(idx);
- idx += 2;
- for (int i = 0; i < methods; i++)
- idx += skipFieldOrMethod(table, idx);
-
- // look for annotation attrs
- int attrs = table.readUnsignedShort(idx);
- idx += 2;
- int name;
- for (int i = 0; i < attrs; i++) {
- name = table.readUnsignedShort(idx);
- idx += 2;
- if ("RuntimeVisibleAnnotations".equals(table.readString
- (table.get(name))))
- return matchAnnotations(table, idx + 4);
- idx += 4 + table.readInt(idx);
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- /*
- * This ArrayIndexOutOfBoundsException indicates an incorrectly
- * formed .class file. We will eat the exception, log a trace
- * message (if a log exists), and return "false" to indicate there
- * was no match.
- */
- Error cfe = new ClassFormatError(rsrc.getName());
- cfe.initCause(e);
- if (_log != null && _log.isTraceEnabled())
- _log.trace(_loc.get("class-arg", rsrc.getName()), cfe);
}
- return false;
- }
- /**
- * Return whether the given annotations match our candidates.
- */
- private boolean matchAnnotations(ConstantPoolTable table, int idx) {
- int annos = table.readUnsignedShort(idx);
- idx += 2;
-
- int type;
- int props;
- for (int i = 0; i < annos; i++) {
- type = table.readUnsignedShort(idx);
- idx += 2;
- if (matchAnnotation(table.readString(table.get(type))))
- return true;
-
- props = table.readUnsignedShort(idx);
- idx += 2;
- for (int j = 0; j < props; j++) {
- idx += 2; // name
- idx += skipAnnotationPropertyValue(table, idx);
- }
- }
- return false;
- }
+ ClassReader cr = new ClassReader(rsrc.getContent());
+ final MatchAnnotationScanner classVisitor = new MatchAnnotationScanner(Opcodes.ASM9);
+ cr.accept(classVisitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
- /**
- * Return whether the given annotation matches our candidates.
- */
- private boolean matchAnnotation(String name) {
- for (String anno : _annos)
- if (name.equals(anno))
- return true;
- return false;
+ return classVisitor.matches;
}
- /**
- * Skip an annotation property value, returning the number of bytes skipped.
- */
- private static int skipAnnotationPropertyValue(ConstantPoolTable table,
- int idx) {
- int skipped = 0;
- switch (table.readByte(idx + skipped++)) {
- case 'Z': // bool
- case 'B': // byte
- case 'C': // char
- case 'D': // double
- case 'F': // float
- case 'I': // int
- case 'J': // long
- case 'S': // short
- case 's': // string
- case 'c': // class
- skipped += 2;
- break;
- case 'e': // enum ptr
- skipped += 4;
- break;
- case '[': // array
- int size = table.readUnsignedShort(idx + skipped);
- skipped += 2;
- for (int i = 0; i < size; i++)
- skipped +=
- skipAnnotationPropertyValue(table, idx + skipped);
- break;
- case '@': // anno
- skipped += 2; // type
- int props = table.readUnsignedShort(idx + skipped);
- skipped += 2;
- for (int j = 0; j < props; j++) {
- skipped += 2; // name
- skipped +=
- skipAnnotationPropertyValue(table, idx + skipped);
- }
- break;
- }
- return skipped;
- }
- /**
- * Skip the current field or method, returning the number of bytes skipped.
- */
- private static int skipFieldOrMethod(ConstantPoolTable table, int idx) {
- int attrs = table.readUnsignedShort(idx + 6);
- int skipped = 8;
- int len;
- for (int i = 0; i < attrs; i++) {
- len = table.readInt(idx + skipped + 2);
- skipped += 6 + len;
- }
- return skipped;
- }
public Log getLog() {
return _log;
@@ -206,4 +84,20 @@ public class ClassAnnotationMetaDataFilter implements MetaDataFilter {
public void setLog(Log _log) {
this._log = _log;
}
+
+ public class MatchAnnotationScanner extends ClassVisitor {
+ boolean matches = false;
+
+ public MatchAnnotationScanner(int api) {
+ super(api);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ if (visible && _annos.contains(descriptor)) {
+ matches = true;
+ }
+ return super.visitAnnotation(descriptor, visible);
+ }
+ }
}
diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java
index 5c4c7ba35..4b8833c54 100644
--- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java
+++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/meta/ClassArgParser.java
@@ -40,8 +40,10 @@ import org.apache.openjpa.lib.util.ClassUtil;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
+import org.apache.xbean.asm9.ClassReader;
+import org.apache.xbean.asm9.ClassVisitor;
+import org.apache.xbean.asm9.Opcodes;
-import serp.bytecode.lowlevel.ConstantPoolTable;
/**
* Parser used to resolve arguments into java classes.
@@ -253,11 +255,11 @@ public class ClassArgParser {
* Parse the names in the given metadata iterator stream, closing the
* stream on completion.
*/
- private void appendTypeNames(Object source, InputStream in,
- List<String> names) throws IOException {
+ private void appendTypeNames(Object source, InputStream in, List<String> names) throws IOException {
try {
- if (source.toString().endsWith(".class"))
- names.add(getFromClass(in));
+ if (source.toString().endsWith(".class")) {
+ names.add(getNameFromClass(in));
+ }
names.addAll(getFromMetaData(new InputStreamReader(in)));
} finally {
try {
@@ -300,30 +302,31 @@ public class ClassArgParser {
private String getFromClassFile(File file) throws IOException {
FileInputStream fin = null;
try {
- fin = AccessController.doPrivileged(
- J2DoPrivHelper.newFileInputStreamAction(file));
- return getFromClass(fin);
+ fin = AccessController.doPrivileged(J2DoPrivHelper.newFileInputStreamAction(file));
+ return getNameFromClass(fin);
} catch (PrivilegedActionException pae) {
throw (FileNotFoundException) pae.getException();
} finally {
- if (fin != null)
+ if (fin != null) {
try {
fin.close();
- } catch (IOException ioe) {
}
+ catch (IOException ioe) {
+ }
+ }
}
}
/**
* Returns the class name in the given .class bytecode.
*/
- private String getFromClass(InputStream in) throws IOException {
- ConstantPoolTable table = new ConstantPoolTable(in);
- int idx = table.getEndIndex();
- idx += 2; // access flags
- int clsEntry = table.readUnsignedShort(idx);
- int utfEntry = table.readUnsignedShort(table.get(clsEntry));
- return table.readString(table.get(utfEntry)).replace('/', '.');
+ private String getNameFromClass(InputStream in) throws IOException {
+
+ ClassReader cr = new ClassReader(in);
+ final ClassNameScanner classNameScanner = new ClassNameScanner(Opcodes.ASM9);
+ cr.accept(classNameScanner, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+
+ return classNameScanner.className;
}
/**
@@ -620,4 +623,19 @@ public class ClassArgParser {
buf.append((char) ch);
}
}
+
+
+ public class ClassNameScanner extends ClassVisitor {
+ String className = null;
+
+ public ClassNameScanner(int api) {
+ super(api);
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ this.className = name.replace("/", ".");
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+ }
}
diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
index 96eb36610..721ad71eb 100644
--- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
+++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/J2DoPrivHelper.java
@@ -54,12 +54,6 @@ import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
-import serp.bytecode.BCClass;
-import serp.bytecode.BCClassLoader;
-import serp.bytecode.BCField;
-import serp.bytecode.Code;
-import serp.bytecode.FieldInstruction;
-import serp.bytecode.Project;
/**
* Helper class to obtain the Privilege(Exception)Action object to perform
@@ -108,12 +102,6 @@ import serp.bytecode.Project;
* <li>URL.openStream
* <li>URLConnection.getContent
* <li>ZipFile new
- * <li>serp.bytecode.Code new
- * <li>serp.bytecode.BCClassLoader new
- * <li>serp.bytecode.BCClass.write
- * <li>serp.bytecode.BCClass.getFields
- * <li>serp.bytecode.FieldInstruction.getField
- * <li>serp.bytecode.Project.loadClass
* <li>AnnotatedElement.getAnnotations
* <li>AnnotatedElement.getDeclaredAnnotations
* <li>AnnotatedElement.isAnnotationPresent
@@ -1068,22 +1056,6 @@ public abstract class J2DoPrivHelper {
};
}
- /**
- * Return a PrivilegeAction object for new serp.bytecode.Code().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "getClassLoader";'
- *
- * @return serp.bytecode.Code
- */
- public static PrivilegedAction<Code> newCodeAction() {
- return new PrivilegedAction<Code>() {
- @Override
- public Code run() {
- return new Code();
- }
- };
- }
/**
* Return a PrivilegeAction object for new TemporaryClassLoader().
@@ -1121,106 +1093,6 @@ public abstract class J2DoPrivHelper {
};
}
- /**
- * Return a PrivilegeAction object for new BCClassLoader().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "createClassLoader";'
- *
- * @return BCClassLoader
- */
- public static PrivilegedAction<BCClassLoader> newBCClassLoaderAction(
- final Project project, final ClassLoader parent) {
- return new PrivilegedAction<BCClassLoader>() {
- @Override
- public BCClassLoader run() {
- return new BCClassLoader(project, parent);
- }
- };
- }
-
- public static PrivilegedAction<BCClassLoader> newBCClassLoaderAction(
- final Project project) {
- return new PrivilegedAction<BCClassLoader>() {
- @Override
- public BCClassLoader run() {
- return new BCClassLoader(project);
- }
- };
- }
-
- /**
- * Return a PrivilegeAction object for BCClass.getFields().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "getClassLoader";'
- *
- * @return BCField
- */
- public static PrivilegedAction<BCField []> getBCClassFieldsAction(
- final BCClass bcClass, final String fieldName) {
- return new PrivilegedAction<BCField []>() {
- @Override
- public BCField [] run() {
- return bcClass.getFields(fieldName);
- }
- };
- }
-
- /**
- * Return a PrivilegeAction object for FieldInstruction.getField().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "getClassLoader";'
- *
- * @return BCField
- */
- public static PrivilegedAction<BCField> getFieldInstructionFieldAction
- (
- final FieldInstruction instruction) {
- return new PrivilegedAction<BCField>() {
- @Override
- public BCField run() {
- return instruction.getField();
- }
- };
- }
-
- /**
- * Return a PrivilegeAction object for Project.loadClass().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "createClassLoader";'
- *
- * @return BCClass
- */
- public static PrivilegedAction<BCClass> loadProjectClassAction(
- final Project project, final Class<?> clazz) {
- return new PrivilegedAction<BCClass>() {
- @Override
- public BCClass run() {
- return project.loadClass(clazz);
- }
- };
- }
-
- /**
- * Return a PrivilegeAction object for Project.loadClass().
- *
- * Requires security policy:
- * 'permission java.lang.RuntimePermission "getClassLoader";'
- *
- * @return BCClass
- */
- public static PrivilegedAction<BCClass> loadProjectClassAction(
- final Project project, final String clazzName) {
- return new PrivilegedAction<BCClass>() {
- @Override
- public BCClass run() {
- return project.loadClass(clazzName);
- }
- };
- }
/**
* Return a PrivilegeAction object for AnnotatedElement.getAnnotations().
diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/JavaVersions.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/JavaVersions.java
index ae402e5d5..222770d6e 100644
--- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/JavaVersions.java
+++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/JavaVersions.java
@@ -34,7 +34,7 @@ import java.security.AccessController;
public class JavaVersions {
/**
- * Java version; one of 2, 3, 4, 5, 6, or 7.
+ * Java version; one of 2, 3, 4, 5, 6, 7, or later.
*/
public static final int VERSION;
@@ -57,8 +57,9 @@ public class JavaVersions {
VERSION = 7;
else if ("1.8".equals(specVersion))
VERSION = 8;
- else
- VERSION = 9; // maybe someday...
+ else {
+ VERSION = Integer.parseInt(specVersion);
+ }
}
/**
diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java
index 1c3881790..7bd16d182 100644
--- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java
+++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/TemporaryClassLoader.java
@@ -22,7 +22,10 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import serp.bytecode.lowlevel.ConstantPoolTable;
+import org.apache.xbean.asm9.ClassReader;
+import org.apache.xbean.asm9.ClassVisitor;
+import org.apache.xbean.asm9.Opcodes;
+
/**
* ClassLoader implementation that allows classes to be temporarily
@@ -73,10 +76,15 @@ public class TemporaryClassLoader extends ClassLoader {
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)) {
+ ClassReader cr = new ClassReader(classBytes);
+ final AccessScanner accessScanner = new AccessScanner(Opcodes.ASM9);
+ cr.accept(accessScanner, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+
+ if (accessScanner.isAnnotation || accessScanner.isEnum) {
try {
Class<?> frameworkClass = Class.forName(name, resolve,
getClass().getClassLoader());
@@ -98,27 +106,21 @@ public class TemporaryClassLoader extends ClassLoader {
}
}
- /**
- * 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
+ public class AccessScanner extends ClassVisitor {
+ boolean isEnum = false;
+ boolean isAnnotation = false;
+
+ public AccessScanner(int api) {
+ super(api);
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ isEnum = (access & Opcodes.ACC_ENUM) > 0;
+ isAnnotation = (access & Opcodes.ACC_ANNOTATION) > 0;
+
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
}
}
diff --git a/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/StringUtilTest.java b/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/StringUtilTest.java
index 6fd48c54d..5380d44c2 100644
--- a/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/StringUtilTest.java
+++ b/openjpa-lib/src/test/java/org/apache/openjpa/lib/util/StringUtilTest.java
@@ -193,8 +193,6 @@ public class StringUtilTest {
long start = System.nanoTime();
for (int i = 1; i < 10000000; i++) {
StringUtil.split(val, "sd", 0);
- //X val.split("sd");
- //X serp.util.Strings.split(val, "sd", 0);
}
long stop = System.nanoTime();
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
index 67597d454..38dc3cdfb 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/TestEnhancementWithMultiplePUs.java
@@ -51,8 +51,7 @@ public class TestEnhancementWithMultiplePUs
getClass().getClassLoader()));
Project project = new Project();
- String className =
- "org.apache.openjpa.enhance.UnenhancedBootstrapInstance";
+ String className = "org.apache.openjpa.enhance.UnenhancedBootstrapInstance";
BCClass bc = assertNotPC(loader, project, className);
PCEnhancer enhancer = new PCEnhancer(conf, bc, repos, loader);
@@ -62,8 +61,7 @@ public class TestEnhancementWithMultiplePUs
assertTrue(enhancer.getPCBytecode().getClassNode().interfaces.contains(Type.getInternalName(PersistenceCapable.class)));
}
- private BCClass assertNotPC(ClassLoader loader, Project project,
- String className) {
+ private BCClass assertNotPC(ClassLoader loader, Project project, String className) {
BCClass bc = project.loadClass(className, loader);
assertFalse(className + " must not be enhanced already; it was.",
Arrays.asList(bc.getInterfaceNames()).contains(