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 <strub...@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(