1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
/*
* Copyright (c) 2021 Oracle, IBM Corporation, and/or their 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
package org.eclipse.persistence.internal.libraries.asm;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* EclipseLink specific {@link ClassVisitor} that generates a corresponding ClassFile structure
* for currently running Java VM.
*/
public class EclipseLinkASMClassWriter extends ClassWriter {
private static final Logger LOG = Logger.getLogger(EclipseLinkASMClassWriter.class.getName());
private static final int version = getLatestOPCodeVersion();
public EclipseLinkASMClassWriter() {
this(ClassWriter.COMPUTE_FRAMES);
}
public EclipseLinkASMClassWriter(final int flags) {
super(flags);
}
/**
* Visits the header of the class with {@code version} set
* equal to currently running Java SE version.
*
* @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if
* the class is deprecated {@link Opcodes#ACC_DEPRECATED} or a record {@link
* Opcodes#ACC_RECORD}.
* @param name the internal name of the class (see {@link Type#getInternalName()}).
* @param signature the signature of this class. May be {@literal null} if the class is not a
* generic one, and does not extend or implement generic classes or interfaces.
* @param superName the internal of name of the super class (see {@link Type#getInternalName()}).
* For interfaces, the super class is {@link Object}. May be {@literal null}, but only for the
* {@link Object} class.
* @param interfaces the internal names of the class's interfaces (see {@link
* Type#getInternalName()}). May be {@literal null}.
* @see #visit(int, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
*/
public final void visit(final int access, final String name,
final String signature, final String superName, final String[] interfaces) {
visit(version, access, name, signature, superName, interfaces);
}
private static int getLatestOPCodeVersion() {
final LinkedHashMap<String, Integer> versionMap = new LinkedHashMap<String, Integer>();
versionMap.put("1.7", Opcodes.V1_7);
versionMap.put("1.8", Opcodes.V1_8);
versionMap.put("9", Opcodes.V9);
versionMap.put("10", Opcodes.V10);
versionMap.put("11", Opcodes.V11);
versionMap.put("12", Opcodes.V12);
versionMap.put("13", Opcodes.V13);
versionMap.put("14", Opcodes.V14);
versionMap.put("15", Opcodes.V15);
versionMap.put("16", Opcodes.V16);
versionMap.put("17", Opcodes.V17);
final List<String> versions = new ArrayList<String>(versionMap.keySet());
final String oldest = versions.get(0);
final String latest = versions.get(versions.size() - 1);
// let's default to oldest supported Java SE version
String v = oldest;
if (System.getSecurityManager() == null) {
v = System.getProperty("java.specification.version");
} else {
try {
v = AccessController.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty("java.specification.version");
}
});
} catch (Throwable t) {
// ie SecurityException
LOG.log(Level.WARNING, "Cannot read 'java.specification.version' property.", t);
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "Generating bytecode for Java SE ''{0}''.", v);
}
}
}
Integer version = versionMap.get(v);
if (version == null) {
// current JDK is either too new
if (latest.compareTo(v) < 0) {
LOG.log(Level.WARNING, "Java SE ''{0}'' is not fully supported yet. Report this error to the EclipseLink open source project.", v);
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "Generating bytecode for Java SE ''{0}''.", latest);
}
version = versionMap.get(latest);
} else {
// or too old
String key = oldest;
LOG.log(Level.WARNING, "Java SE ''{0}'' is too old.", v);
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "Generating bytecode for Java SE ''{0}''.", key);
}
version = versionMap.get(key);
}
}
return version;
}
}
|