File: ClassConstruct.java

package info (click to toggle)
openjdk-17 17.0.17%2B10-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 764,928 kB
  • sloc: java: 5,319,061; xml: 1,291,711; cpp: 1,202,358; ansic: 428,746; asm: 404,978; objc: 20,861; sh: 14,754; javascript: 10,743; python: 6,402; makefile: 2,404; perl: 357; awk: 351; sed: 172; jsp: 24; csh: 3
file content (167 lines) | stat: -rw-r--r-- 5,703 bytes parent folder | download | duplicates (17)
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * 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;
    }
}