3789983e89
Reviewed-by: darcy, ihse
168 lines
5.6 KiB
Java
168 lines
5.6 KiB
Java
/*
|
|
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
package selectionresolution;
|
|
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import jdk.internal.org.objectweb.asm.ClassWriter;
|
|
import jdk.internal.org.objectweb.asm.Opcodes;
|
|
|
|
public abstract class ClassConstruct {
|
|
private final ClassWriter cw;
|
|
private final String name;
|
|
private final boolean isInterface;
|
|
private final int index;
|
|
|
|
/**
|
|
* Base constructor for building a Class or Interface
|
|
* @param name Name of Class/Interface, including package name
|
|
* @param extending Name of extending Class if any
|
|
* @param access Access for Class/Interface
|
|
* @param classFileVersion Class file version
|
|
* @param interfaces Interface implemented
|
|
*/
|
|
public ClassConstruct(String name,
|
|
String extending,
|
|
int access,
|
|
int classFileVersion,
|
|
int index,
|
|
String... interfaces) {
|
|
this.name = name;
|
|
isInterface = (access & Opcodes.ACC_INTERFACE) == Opcodes.ACC_INTERFACE;
|
|
cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
cw.visit(classFileVersion, access, name, null, extending, interfaces == null ? new String[] { } : interfaces);
|
|
this.index = index;
|
|
}
|
|
|
|
/**
|
|
* Get full Class/Interface name including package name, as it
|
|
* should appear in a classfile.
|
|
*
|
|
* @return The full Class/Interface name including package name
|
|
*/
|
|
public String getName() {
|
|
return name;
|
|
}
|
|
|
|
/**
|
|
* Get the name of the class, including package as it would appear
|
|
* in Java source.
|
|
*
|
|
* @return The name of the class as it would appear in Java source.
|
|
*/
|
|
public String getDottedName() {
|
|
return name.replace("/", ".");
|
|
}
|
|
|
|
public String getPackageName() {
|
|
final int idx = name.lastIndexOf('/');
|
|
if (idx != -1) {
|
|
return name.substring(0, name.indexOf('/'));
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public String getClassName() {
|
|
final int idx = name.lastIndexOf('/');
|
|
if (idx != -1) {
|
|
return name.substring(name.indexOf('/'));
|
|
} else {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a method, no code associated with it yet
|
|
* @param name Name of method
|
|
* @param descriptor Descriptor for method
|
|
* @param access Access for the method
|
|
* @return Method object that can be used for constructing a method body
|
|
*/
|
|
public Method addMethod(String name,
|
|
String descriptor,
|
|
int access) {
|
|
return addMethod(name, descriptor, access, null);
|
|
}
|
|
|
|
/**
|
|
* Add a method, no code associated with it yet
|
|
* @param name Name of method
|
|
* @param descriptor Descriptor for method
|
|
* @param access Access for the method
|
|
* @param execMode The execution mode for the method.
|
|
* @return Method object that can be used for constructing a method body
|
|
*/
|
|
public Method addMethod(String name,
|
|
String descriptor,
|
|
int access,
|
|
ClassBuilder.ExecutionMode execMode) {
|
|
return new Method(this, cw, name, descriptor, access, execMode);
|
|
}
|
|
|
|
/**
|
|
* Adds a m()LTestObject; method which returns null unless the method is abstract
|
|
* @param access Access for the method
|
|
*/
|
|
public void addTestMethod(int access) {
|
|
Method m = new Method(this, cw, Method.defaultMethodName, Method.defaultMethodDescriptor, access, null);
|
|
if ((access & Opcodes.ACC_ABSTRACT) != Opcodes.ACC_ABSTRACT) {
|
|
m.makeDefaultMethod();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Construct the class to a byte[]
|
|
* @return byte[] with class file
|
|
*/
|
|
public byte[] generateBytes() {
|
|
cw.visitEnd();
|
|
return cw.toByteArray();
|
|
}
|
|
|
|
/**
|
|
* Write out a class to a file in the specified directory.
|
|
*
|
|
* @param dir Directory to which to write out the file.
|
|
*/
|
|
public void writeClass(final File dir) throws Exception {
|
|
final String pkgname = getPackageName();
|
|
final File pkgdir = pkgname != null ? new File(dir, getPackageName()) : dir;
|
|
pkgdir.mkdirs();
|
|
final File out = new File(pkgdir, getClassName() + ".class");
|
|
out.createNewFile();
|
|
try (final FileOutputStream fos = new FileOutputStream(out)) {
|
|
fos.write(generateBytes());
|
|
}
|
|
}
|
|
|
|
public boolean isInterface() {
|
|
return isInterface;
|
|
}
|
|
|
|
public Integer getIndex() {
|
|
return index;
|
|
}
|
|
}
|