com.sun.jdo.api.persistence.enhancer.classfile.ClassFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-embedded-all Show documentation
Show all versions of payara-embedded-all Show documentation
Payara-Embedded-All Distribution of the Payara Project
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.jdo.api.persistence.enhancer.classfile;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;
import java.io.DataOutputStream;
/**
* ClassFile models the structure of a class as represented within
* a class file.
*/
final public class ClassFile implements VMConstants {
/* Class file constants */
public static final int magic = 0xcafebabe;
//@olsen: added more flexible version checking.
public static final short[][] jdkMajorMinorVersions = new short[][]{
new short[]{45, 3}, // jdk 1.1
new short[]{46, 0}, // jdk 1.2
new short[]{47, 0}, // jdk 1.3
new short[]{48, 0}, // jdk 1.4
new short[]{49, 0}, // jdk 1.5
new short[]{50, 0} // jdk 1.6
};
public static final List jdkVersions =
convertMajorMinorVersions(jdkMajorMinorVersions);
public static final String supportedVersions = printSupportedVersions();
private int majorVersion = 0;
private int minorVersion = 0;
/* The constant pool for the class file */
private ConstantPool constantPool = new ConstantPool();
/* access flag bit mask - see VMConstants */
private int accessFlags = 0;
/* The name of the class */
private ConstClass thisClassName;
/* The name of the super class */
private ConstClass superClassName;
/* A list of the interfaces which the class implements
* The contents are ConstClass objects
*/
private Vector classInterfaces = new Vector();
/* A list of the fields which the class contains
* The contents are ClassField objects
*/
private Vector classFields = new Vector();
/* A list of the methods which the class defines
* The contents are ClassMethod objects
*/
private Vector classMethods = new Vector();
/* A list of the attributes associated with the class */
private AttributeVector classAttributes = new AttributeVector();
/* public accessors */
/**
* Return the constant pool for the class file
*/
public ConstantPool pool() {
return constantPool;
}
/**
* Return the access flags for the class - see VMConstants
*/
public int access() {
return accessFlags;
}
/**
* Is the class final?
*/
final public boolean isFinal() {
return (accessFlags & ACCFinal) != 0;
}
/**
* Is the class an interface?
*/
final public boolean isInterface() {
return (accessFlags & ACCInterface) != 0;
}
/**
* Is the class public?
*/
final public boolean isPublic() {
return (accessFlags & ACCPublic) != 0;
}
/**
* Is the class abstract?
*/
final public boolean isAbstract() {
return (accessFlags & ACCAbstract) != 0;
}
/**
* Set the access flags for the class - see VMConstants
*/
public void setAccessFlags (int flags) {
accessFlags = flags;
}
/**
* Return the name of the class
*/
public ConstClass className() {
return thisClassName;
}
/**
* Return the name of the super class
*/
public ConstClass superName() {
return superClassName;
}
/**
* Return the name of the super class as a string
*/
public String superNameString() {
return (superClassName == null) ? null : superClassName.asString();
}
/**
* Set the name of the super class
*/
public void setSuperName(ConstClass superCl) {
superClassName = superCl;
}
/**
* Return the list of the interfaces which the class implements
* The contents are ConstClass objects
*/
public Vector interfaces() {
return classInterfaces;
}
/**
* Add an interface to the list of the interfaces which the class implements
*/
public void addInterface (ConstClass iface) {
classInterfaces.addElement(iface);
}
/**
* Return the list of the fields which the class contains
* The contents are ClassField objects
*/
public Vector fields() {
return classFields;
}
/**
* Add a field to the list of the fields which the class contains
*/
public void addField (ClassField field) {
classFields.addElement(field);
}
/**
* Add a field to the list of the fields which the class contains,
* at the index'th position.
*/
public void addField(ClassField field, int index) {
classFields.insertElementAt(field, index);
}
/**
* Return the list of the methods which the class defines
* The contents are ClassMethod objects
*/
public Vector methods() {
return classMethods;
}
/**
* Look for a method with the specified name and type signature
*/
public ClassMethod findMethod(String methodName, String methodSig) {
for (Enumeration e = methods().elements(); e.hasMoreElements();) {
ClassMethod method = (ClassMethod) e.nextElement();
if (method.name().asString().equals(methodName) &&
method.signature().asString().equals(methodSig))
return method;
}
return null;
}
/**
* Add a method to the list of the methods which the class defines
*/
public void addMethod(ClassMethod method) {
classMethods.addElement(method);
}
/**
* Look for a field with the specified name
*/
public ClassField findField(String fieldName) {
for (Enumeration e = fields().elements(); e.hasMoreElements();) {
ClassField field = (ClassField) e.nextElement();
if (field.name().asString().equals(fieldName))
return field;
}
return null;
}
/**
* Return the list of the attributes associated with the class
*/
public AttributeVector attributes() {
return classAttributes;
}
/**
* Construct a ClassFile from an input stream
*/
public ClassFile(DataInputStream data) throws ClassFormatError {
try {
int thisMagic = data.readInt();
if (thisMagic != magic)
throw new ClassFormatError("Bad magic value for input");//NOI18N
short thisMinorVersion = data.readShort();
short thisMajorVersion = data.readShort();
//@olsen: changed checking only target 1.1 and 1.2 to more
//general check for a list of versions.
if (isSupportedVersion(thisMajorVersion, thisMinorVersion)) {
minorVersion = thisMinorVersion;
majorVersion = thisMajorVersion;
} else {
throw new ClassFormatError("Bad version number: {" + //NOI18N
thisMajorVersion + "," + //NOI18N
thisMinorVersion +
"} expected one of: " + //NOI18N
supportedVersions);
}
readConstants(data);
accessFlags = data.readUnsignedShort();
thisClassName = (ConstClass)
constantPool.constantAt(data.readUnsignedShort());
superClassName = (ConstClass)
constantPool.constantAt(data.readUnsignedShort());
readInterfaces(data);
readFields(data);
readMethods(data);
classAttributes = AttributeVector.readAttributes(data, constantPool);
} catch (IOException e) {
ClassFormatError cfe = new ClassFormatError("IOException during reading");//NOI18N
cfe.initCause(e);
throw cfe;
}
//@olsen: added println() for debugging
//System.out.println("ClassFile(): new class = " + thisClassName.asString());
}
/**
* Construct a bare bones class, ready for additions
*/
public ClassFile(String cname, String supername) {
thisClassName = constantPool.addClass(cname);
superClassName = constantPool.addClass(supername);
//@olsen: added println() for debugging
//System.out.println("ClassFile(): new bare class file = " + thisClassName);
}
/**
* Write the Class file to the data output stream
*/
public
void write (DataOutputStream buff) throws IOException {
buff.writeInt(magic);
buff.writeShort(minorVersion);
buff.writeShort(majorVersion);
constantPool.write(buff);
buff.writeShort(accessFlags);
buff.writeShort(thisClassName.getIndex());
//@lars: superclass may be null (java.lang.Object); VMSpec 2nd ed., section 4.1
buff.writeShort(superClassName == null ? 0 : superClassName.getIndex());
// buff.writeShort(superClassName.getIndex());
writeInterfaces(buff);
writeFields(buff);
writeMethods(buff);
classAttributes.write(buff);
}
/**
* Returns a byte array representation of this class.
*/
public byte[] getBytes() throws java.io.IOException {
/* Write the class bytes to a file, for debugging. */
String writeClassToDirectory =
System.getProperty("filter.writeClassToDirectory");
if (writeClassToDirectory != null) {
String filename = writeClassToDirectory + java.io.File.separator +
thisClassName.asString() + ".class";//NOI18N
System.err.println("Writing class to file " + filename);
DataOutputStream stream = new DataOutputStream(
new java.io.FileOutputStream(filename));
write(stream);
stream.close();
}
/* Get the class bytes and return them. */
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
write(new DataOutputStream(byteStream));
return byteStream.toByteArray();
}
/* package local methods */
public void print (PrintStream out) {
constantPool.print(out);
out.println();
out.println("majorVersion = " + Integer.toString(majorVersion));//NOI18N
out.println("minorVersion = " + Integer.toString(minorVersion));//NOI18N
out.println("accessFlags = " + Integer.toString(accessFlags));//NOI18N
out.println("className = " + thisClassName.asString());//NOI18N
out.println("superClassName = " + superClassName.asString());//NOI18N
out.print("Interfaces =");//NOI18N
for (int i=0; i 0) {
int interfaceIndex = data.readUnsignedShort();
ConstClass ci = null;
if (interfaceIndex != 0)
ci = (ConstClass) constantPool.constantAt(interfaceIndex);
classInterfaces.addElement(ci);
}
}
private void writeInterfaces(DataOutputStream data) throws IOException {
data.writeShort(classInterfaces.size());
for (int i=0; i 0) {
classFields.addElement (ClassField.read(data, constantPool));
}
}
private void writeFields (DataOutputStream data) throws IOException {
data.writeShort(classFields.size());
for (int i=0; i 0) {
classMethods.addElement (ClassMethod.read(data, constantPool));
}
}
private void writeMethods (DataOutputStream data) throws IOException {
data.writeShort(classMethods.size());
for (int i=0; i o2 */
abstract int compare(int o1Index, int o2Index);
/* Swap the elements at index o1Index and o2Index */
abstract void swap(int o1Index, int o2Index);
void sortArray() {
sortArray(0, size()-1);
}
private void sortArray(int start, int end) {
if (end > start) {
swap(start, (start+end)/2);
int last = start;
for (int i = start+1; i<=end; i++) {
if (compare(i, start) < 0)
swap (++last, i);
}
swap(start, last);
sortArray(start, last-1);
sortArray(last+1, end);
}
}
}
class InterfaceArraySorter extends ArraySorter {
private ConstClass theArray[];
InterfaceArraySorter(ConstClass[] interfaces) {
theArray = interfaces;
}
/* return the size of the array being sorted */
int size() { return theArray.length; }
/* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
int compare(int o1Index, int o2Index) {
return theArray[o1Index].asString().compareTo(
theArray[o2Index].asString());
}
/* Swap the elements at index o1Index and o2Index */
void swap(int o1Index, int o2Index) {
ConstClass tmp = theArray[o1Index];
theArray[o1Index] = theArray[o2Index];
theArray[o2Index] = tmp;
}
}
class FieldArraySorter extends ArraySorter {
private ClassField theArray[];
FieldArraySorter(ClassField[] fields) {
theArray = fields;
}
/* return the size of the array being sorted */
int size() { return theArray.length; }
/* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
int compare(int o1Index, int o2Index) {
return theArray[o1Index].name().asString().compareTo(
theArray[o2Index].name().asString());
}
/* Swap the elements at index o1Index and o2Index */
void swap(int o1Index, int o2Index) {
ClassField tmp = theArray[o1Index];
theArray[o1Index] = theArray[o2Index];
theArray[o2Index] = tmp;
}
}
class MethodArraySorter extends ArraySorter {
private ClassMethod theArray[];
MethodArraySorter(ClassMethod[] methods) {
theArray = methods;
}
/* return the size of the array being sorted */
int size() { return theArray.length; }
/* return -1 if o1 < o2, 0 if o1 == o2, 1 if o1 > o2 */
int compare(int o1Index, int o2Index) {
int cmp = theArray[o1Index].name().asString().compareTo(
theArray[o2Index].name().asString());
if (cmp == 0) {
cmp = theArray[o1Index].signature().asString().compareTo(
theArray[o2Index].signature().asString());
}
return cmp;
}
/* Swap the elements at index o1Index and o2Index */
void swap(int o1Index, int o2Index) {
ClassMethod tmp = theArray[o1Index];
theArray[o1Index] = theArray[o2Index];
theArray[o2Index] = tmp;
}
}