Skip to content
Commits on Source (22)
......@@ -266,11 +266,6 @@ class HtmlDecorator {
// Java8:
// <pre>static class <span class="typeNameLabel">ClassA.InnerAspect</span>
classStartIndex = fileContents.toString().indexOf("class <span class=\"typeNameLabel\">");
if (classStartIndex == -1) {
// Java7: 464604
// <pre>public class <span class="strong">Azpect</span>
classStartIndex = fileContents.toString().indexOf("class <span class=\"strong\">");
}
int classEndIndex = fileContents.toString().indexOf("</span>", classStartIndex);
if (classEndIndex != -1) {
// Convert it to "aspect <span class="typeNameLabel">ClassA.InnerAspect</span>"
......
......@@ -80,6 +80,8 @@ public interface Constants {
public final static short MINOR_1_7 = 0;
public final static short MAJOR_1_8 = 52;
public final static short MINOR_1_8 = 0;
public final static short MAJOR_1_9 = 53;
public final static short MINOR_1_9 = 0;
// Defaults
public final static short MAJOR = MAJOR_1_1;
public final static short MINOR = MINOR_1_1;
......@@ -106,12 +108,17 @@ public interface Constants {
public final static short ACC_ABSTRACT = 0x0400;
public final static short ACC_STRICT = 0x0800;
public final static short ACC_SYNTHETIC = 0x1000;
public final static short ACC_ANNOTATION = 0x2000;
public final static short ACC_ENUM = 0x4000;
public final static int ACC_MODULE = 0x8000;
public final static short ACC_BRIDGE = 0x0040;
public final static short ACC_VARARGS = 0x0080;
// module related
public final static int MODULE_ACC_PUBLIC = 0x0020;
public final static int MODULE_ACC_SYNTHETIC = 0x1000;
public final static int MODULE_ACC_MANDATED = 0x8000;
// Applies to classes compiled by new compilers only
public final static short ACC_SUPER = 0x0020;
......
......@@ -95,7 +95,7 @@ public final class BootstrapMethods extends Attribute {
BootstrapMethods(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException {
this(name_index, length, (BootstrapMethod[])null, constant_pool);
data = new byte[length];
file.readFully(data);
file.read(data);
isInPackedState = true;
}
......
......@@ -162,4 +162,6 @@ public interface ClassVisitor {
public void visitLocalVariableTypeTable(LocalVariableTypeTable obj);
public void visitMethodParameters(MethodParameters methodParameters);
public void visitModule(Module m);
}
......@@ -104,7 +104,7 @@ public final class LineNumberTable extends Attribute {
LineNumberTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException {
this(name_index, length, (LineNumber[]) null, constant_pool);
data = new byte[length];
file.readFully(data);
file.read(data);
isInPackedState = true;
// assert(bytesRead==length)
}
......
......@@ -109,7 +109,7 @@ public class LocalVariableTable extends Attribute {
LocalVariableTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool) throws IOException {
super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool);
data = new byte[length];
file.readFully(data);
file.read(data);
isInPackedState = true;
// assert(bytesRead==length)
}
......
......@@ -38,7 +38,7 @@ public class MethodParameters extends Attribute {
public MethodParameters(int index, int length, DataInputStream dis, ConstantPool cpool) throws IOException {
super(Constants.ATTR_METHOD_PARAMETERS,index,length,cpool);
data = new byte[length];
dis.readFully(data,0,length);
dis.read(data,0,length);
isInPackedState = true;
}
......
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache BCEL" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache BCEL", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.aspectj.apache.bcel.classfile;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Module.Export;
/**
* This class is derived from <em>Attribute</em> and represents the module
* information captured in a class file.
* http://cr.openjdk.java.net/~mr/jigsaw/spec/lang-vm.html
*
* @author Andy Clement
*/
public final class Module extends Attribute {
private static final String[] NO_MODULE_NAMES = {};
private byte[] moduleInfo;
private int ptr;
private boolean unpacked = false;
private Require[] requires;
private Export[] exports;
private Uses[] uses;
private Provide[] provides;
/**
* Build a Module attribute from a previously Unknown attribute.
*/
public Module(Unknown unknown) {
super(unknown.getTag(), unknown.getNameIndex(), unknown.getLength(), unknown.getConstantPool());
moduleInfo = unknown.getBytes();
}
public class Require {
private final int moduleNameIndex;
private final int requiresFlags;
public Require(int moduleNameIndex, int requiresFlags) {
this.moduleNameIndex = moduleNameIndex;
this.requiresFlags = requiresFlags;
}
public String getModuleName() {
return cpool.getConstantUtf8(moduleNameIndex).getStringValue();
}
public int getRequiresFlags() {
return requiresFlags;
}
public String getRequiresFlagsAsString() {
StringBuilder s = new StringBuilder();
if ((requiresFlags & Constants.MODULE_ACC_PUBLIC)!=0) {
s.append("public ");
}
if ((requiresFlags & Constants.MODULE_ACC_SYNTHETIC)!=0) {
s.append("synthetic ");
}
if ((requiresFlags & Constants.MODULE_ACC_MANDATED)!=0) {
s.append("mandated ");
}
return s.toString();
}
public String toString() {
return "requires "+getRequiresFlagsAsString()+getModuleName();
}
}
public class Export {
private final int exportedPackageNameIndex;
private final int[] toModuleNameIndices;
public Export(int exportedPackageNameIndex, int[] toModuleNameIndices) {
this.exportedPackageNameIndex = exportedPackageNameIndex;
this.toModuleNameIndices = toModuleNameIndices;
}
public String getExportedPackage() {
return cpool.getConstantUtf8(exportedPackageNameIndex).getStringValue();
}
public String[] getToModuleNames() {
if (toModuleNameIndices==null) {
return NO_MODULE_NAMES;
}
String[] toModuleNames = new String[toModuleNameIndices.length];
for (int i=0;i<toModuleNameIndices.length;i++) {
toModuleNames[i] = cpool.getConstantUtf8(toModuleNameIndices[i]).getStringValue();
}
return toModuleNames;
}
public String toString() {
StringBuilder s =new StringBuilder();
s.append("exports ").append(getExportedPackage().replace('/', '.'));
String[] toModules = getToModuleNames();
if (toModules.length!=0) {
s.append(" to ");
for (int i=0;i<toModules.length;i++) {
if (i>0) {
s.append(", ");
}
s.append(toModules[i]);
}
}
return s.toString().trim();
}
}
public class Provide {
private final int providedTypeIndex;
private final int withTypeIndex;
public Provide(int providedTypeIndex, int withTypeIndex) {
this.providedTypeIndex = providedTypeIndex;
this.withTypeIndex = withTypeIndex;
}
public String getProvidedType() {
return cpool.getConstantString_CONSTANTClass(providedTypeIndex);
}
public int getProvidedTypeIndex() {
return providedTypeIndex;
}
public String getWithType() {
return cpool.getConstantString_CONSTANTClass(withTypeIndex);
}
public int getWithTypeIndex() {
return withTypeIndex;
}
public String toString() {
StringBuilder s =new StringBuilder();
s.append("provides ").append(getProvidedType().replace('/', '.'));
s.append(" with ").append(getWithType().replace('/','.'));
return s.toString();
}
}
public class Uses {
private final int typeNameIndex;
public Uses(int typeNameIndex) {
this.typeNameIndex = typeNameIndex;
}
public String getTypeName() {
return cpool.getConstantString_CONSTANTClass(typeNameIndex);
}
public int getTypeNameIndex() {
return typeNameIndex;
}
public String toString() {
StringBuilder s =new StringBuilder();
s.append("uses ").append(getTypeName().replace('/', '.'));
return s.toString().trim();
}
}
private final int readInt() {
return ((moduleInfo[ptr++] & 0xFF) << 24) + ((moduleInfo[ptr++] & 0xFF) << 16)
+ ((moduleInfo[ptr++] & 0xFF) << 8) + (moduleInfo[ptr++] & 0xFF);
}
private final int readUnsignedShort() {
return ((moduleInfo[ptr++] & 0xff) << 8) + (moduleInfo[ptr++] & 0xff);
}
private final int readUnsignedShort(int offset) {
return ((moduleInfo[offset++] & 0xff) << 8) + (moduleInfo[offset] & 0xff);
}
private void ensureUnpacked() {
if (!unpacked) {
ptr = 0;
int count = readUnsignedShort();
requires = new Require[count];
for (int i = 0; i < count; i++) {
requires[i] = new Require(readUnsignedShort(), readUnsignedShort());
}
count = readUnsignedShort();
exports = new Export[count];
for (int i = 0; i < count; i++) {
int index = readUnsignedShort();
int toCount = readUnsignedShort();
int[] to = new int[toCount];
for (int j = 0; j < toCount; j++) {
to[j] = readUnsignedShort();
}
exports[i] = new Export(index, to);
}
count = readUnsignedShort();
uses = new Uses[count];
for (int i = 0; i < count; i++) {
uses[i] = new Uses(readUnsignedShort());
}
count = readUnsignedShort();
provides = new Provide[count];
for (int i = 0; i < count; i++) {
provides[i] = new Provide(readUnsignedShort(), readUnsignedShort());
}
unpacked = true;
}
}
@Override
public final void dump(DataOutputStream file) throws IOException {
super.dump(file);
if (!unpacked) {
file.write(moduleInfo);
} else {
file.writeShort(requires.length);
for (int i = 0; i < requires.length; i++) {
file.writeShort(requires[i].moduleNameIndex);
file.writeShort(requires[i].requiresFlags);
}
file.writeShort(exports.length);
for (Export export : exports) {
file.writeShort(export.exportedPackageNameIndex);
int[] toIndices = export.toModuleNameIndices;
file.writeShort(toIndices.length);
for (int index : toIndices) {
file.writeShort(index);
}
}
file.writeShort(uses.length);
for (Uses use : uses) {
file.writeShort(use.getTypeNameIndex());
}
file.writeShort(provides.length);
for (Provide provide : provides) {
file.writeShort(provide.providedTypeIndex);
file.writeShort(provide.withTypeIndex);
}
}
}
public String toStringRequires() {
StringBuilder s = new StringBuilder();
s.append('#').append(requires.length);
if (requires.length > 0) {
for (Require require : requires) {
s.append(' ');
s.append(require.moduleNameIndex).append(':').append(require.requiresFlags);
}
}
return s.toString();
}
public String toStringExports() {
StringBuilder s = new StringBuilder();
s.append('#').append(exports.length);
if (exports.length > 0) {
for (Export export : exports) {
s.append(' ');
s.append(export.exportedPackageNameIndex).append(":[");
int[] toIndices = export.toModuleNameIndices;
for (int i = 0; i < toIndices.length; i++) {
if (i > 0)
s.append(',');
s.append(toIndices[i]);
}
s.append("]");
}
}
return s.toString();
}
public String toStringUses() {
StringBuilder s = new StringBuilder();
s.append('#').append(uses.length);
if (uses.length > 0) {
for (Uses use : uses) {
s.append(' ');
s.append(use.getTypeName());
}
}
return s.toString();
}
public String toStringProvides() {
StringBuilder s = new StringBuilder();
s.append('#').append(provides.length);
if (provides.length > 0) {
for (Provide provide : provides) {
s.append(' ');
s.append(provide.providedTypeIndex).append(':').append(provide.withTypeIndex);
}
}
return s.toString();
}
@Override
public final String toString() {
StringBuilder s = new StringBuilder();
ensureUnpacked();
s.append("Module(");
if (requires.length != 0) {
s.append("requires=");
s.append(toStringRequires());
s.append(" ");
}
if (exports.length != 0) {
s.append("exports=");
s.append(toStringExports());
s.append(" ");
}
if (uses.length != 0) {
s.append("uses=");
s.append(toStringUses());
s.append(" ");
}
if (provides.length != 0) {
s.append("provides=");
s.append(toStringProvides());
s.append(" ");
}
return s.toString().trim()+")";
}
/**
* @return deep copy of this attribute //
*/
// @Override
// public Attribute copy(ConstantPool constant_pool) {
// return (Module) clone();
// }
@Override
public void accept(ClassVisitor v) {
v.visitModule(this);
}
public Require[] getRequires() {
ensureUnpacked();
return requires;
}
public String[] getRequiredModuleNames() {
ensureUnpacked();
String[] results = new String[requires.length];
for (int i=0;i<requires.length;i++) {
results[i] = cpool.getConstantUtf8(requires[i].moduleNameIndex).getStringValue();
}
return results;
}
public byte[] getBytes() {
return moduleInfo;
}
public Export[] getExports() {
ensureUnpacked();
return exports;
}
public Uses[] getUses() {
ensureUnpacked();
return uses;
}
public Provide[] getProvides() {
ensureUnpacked();
return provides;
}
}
......@@ -63,7 +63,7 @@ import org.aspectj.apache.bcel.Constants;
/**
* This class represents a stack map attribute used for preverification of Java classes for the <a href="http://java.sun.com/j2me/">
* Java 2 Micro Edition</a> (J2ME). This attribute is used by the <a href="http://java.sun.com/products/cldc/">KVM</a> and contained
* within the Code attribute of a method. See CLDC specification 5.3.1.2
* within the Code attribute of a method. See CLDC specification §5.3.1.2
*
* @version $Id: StackMap.java,v 1.6 2009/09/15 19:40:12 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
......
......@@ -61,7 +61,7 @@ import java.io.IOException;
/**
* This class represents a stack map entry recording the types of
* local variables and the the of stack items at a given byte code offset.
* See CLDC specification 5.3.1.2
* See CLDC specification §5.3.1.2
*
* @version $Id: StackMapEntry.java,v 1.5 2008/05/28 23:53:02 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
......
......@@ -56,7 +56,7 @@ public abstract class RuntimeAnnos extends Attribute {
protected void readAnnotations(DataInputStream dis, ConstantPool cpool) throws IOException {
annotation_data = new byte[length];
dis.readFully(annotation_data, 0, length);
dis.read(annotation_data, 0, length);
}
protected void writeAnnotations(DataOutputStream dos) throws IOException {
......@@ -71,17 +71,12 @@ public abstract class RuntimeAnnos extends Attribute {
}
}
private void inflate() {
try {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data));
int numberOfAnnotations = dis.readUnsignedShort();
if (numberOfAnnotations > 0) {
List<AnnotationGen> inflatedAnnotations = new ArrayList<AnnotationGen>();
for (int i = 0; i < numberOfAnnotations; i++) {
inflatedAnnotations.add(AnnotationGen.read(dis, getConstantPool(), visible));
}
annotations = inflatedAnnotations;
annotations.add(AnnotationGen.read(dis, getConstantPool(), visible));
}
dis.close();
inflated = true;
......
......@@ -80,28 +80,20 @@ public abstract class RuntimeParamAnnos extends Attribute {
protected void readParameterAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException {
annotation_data = new byte[length];
dis.readFully(annotation_data,0,length);
dis.read(annotation_data,0,length);
}
private void inflate() {
try {
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(annotation_data));
int numParameters = dis.readUnsignedByte();
if (numParameters > 0) {
List<AnnotationGen[]> inflatedParameterAnnotations = new ArrayList<AnnotationGen[]>();
for (int i=0; i<numParameters; i++) {
int numAnnotations = dis.readUnsignedShort();
if (numAnnotations == 0 ) {
inflatedParameterAnnotations.add(AnnotationGen.NO_ANNOTATIONS);
} else {
AnnotationGen[] annotations = new AnnotationGen[numAnnotations];
for (int j=0; j<numAnnotations; j++) {
annotations[j] = AnnotationGen.read(dis,getConstantPool(),visible);
}
inflatedParameterAnnotations.add(annotations);
}
}
parameterAnnotations = inflatedParameterAnnotations;
parameterAnnotations.add(annotations);
}
inflated = true;
} catch (IOException ioe) {
......
......@@ -34,7 +34,7 @@ public abstract class RuntimeTypeAnnos extends Attribute {
protected void readTypeAnnotations(DataInputStream dis,ConstantPool cpool) throws IOException {
annotation_data = new byte[length];
dis.readFully(annotation_data,0,length);
dis.read(annotation_data,0,length);
}
public final void dump(DataOutputStream dos) throws IOException {
......
......@@ -66,7 +66,6 @@ import org.aspectj.apache.bcel.classfile.ConstantInteger;
import org.aspectj.apache.bcel.classfile.ConstantLong;
import org.aspectj.apache.bcel.classfile.ConstantObject;
import org.aspectj.apache.bcel.classfile.ConstantPool;
import org.aspectj.apache.bcel.classfile.ConstantString;
import org.aspectj.apache.bcel.classfile.ConstantValue;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.classfile.Utility;
......@@ -127,6 +126,7 @@ public class FieldGen extends FieldGenOrMethodGen {
}
}
// TODO setting the constant value is a mess...
public void setValue(int index) {
ConstantPool cp = this.cp;
Constant c = cp.getConstant(index);
......@@ -138,8 +138,6 @@ public class FieldGen extends FieldGenOrMethodGen {
value = ((ConstantDouble) c).getValue();
} else if (c instanceof ConstantLong) {
value = ((ConstantLong) c).getValue();
} else if (c instanceof ConstantString) {
value = ((ConstantString)c).getString(cp);
} else {
value = ((ConstantObject) c).getConstantValue(cp);
}
......
......@@ -146,7 +146,7 @@ public class ObjectType extends ReferenceType {
}
/**
* Java Virtual Machine Specification edition 2, 5.4.4 Access Control
* Java Virtual Machine Specification edition 2, § 5.4.4 Access Control
*/
public boolean accessibleTo(ObjectType accessor) {
JavaClass jc = Repository.lookupClass(classname);
......
......@@ -137,7 +137,7 @@ public abstract class ReferenceType extends Type {
*/
if (this instanceof ObjectType && ((ObjectType) this).referencesInterface()) {
/*
* If T is a class type, then T must be Object (2.4.7).
* If T is a class type, then T must be Object (§2.4.7).
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesClass()) {
if (T.equals(Type.OBJECT)) {
......@@ -146,7 +146,7 @@ public abstract class ReferenceType extends Type {
}
/*
* If T is an interface type, then T must be the same interface as this or a superinterface of this (2.13.2).
* If T is an interface type, then T must be the same interface as this or a superinterface of this (§2.13.2).
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesInterface()) {
if (this.equals(T)) {
......@@ -163,7 +163,7 @@ public abstract class ReferenceType extends Type {
*/
if (this instanceof ArrayType) {
/*
* If T is a class type, then T must be Object (2.4.7).
* If T is a class type, then T must be Object (§2.4.7).
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesClass()) {
if (T.equals(Type.OBJECT)) {
......@@ -176,7 +176,7 @@ public abstract class ReferenceType extends Type {
*/
if (T instanceof ArrayType) {
/*
* TC and SC are the same primitive type (2.4.1).
* TC and SC are the same primitive type (§2.4.1).
*/
Type sc = ((ArrayType) this).getElementType();
Type tc = ((ArrayType) this).getElementType();
......@@ -186,7 +186,7 @@ public abstract class ReferenceType extends Type {
}
/*
* TC and SC are reference types (2.4.6), and type SC is assignable to TC by these runtime rules.
* TC and SC are reference types (§2.4.6), and type SC is assignable to TC by these runtime rules.
*/
if (tc instanceof ReferenceType && sc instanceof ReferenceType
&& ((ReferenceType) sc).isAssignmentCompatibleWith(tc)) {
......@@ -194,7 +194,7 @@ public abstract class ReferenceType extends Type {
}
}
/* If T is an interface type, T must be one of the interfaces implemented by arrays (2.15). */
/* If T is an interface type, T must be one of the interfaces implemented by arrays (§2.15). */
// TODO: Check if this is still valid or find a way to dynamically find out which
// interfaces arrays implement. However, as of the JVM specification edition 2, there
// are at least two different pages where assignment compatibility is defined and
......@@ -218,7 +218,7 @@ public abstract class ReferenceType extends Type {
* t is an ArrayType, then Type.OBJECT is returned; unless their dimensions match. Then an ArrayType of the same number of
* dimensions is returned, with its basic type being the first common super class of the basic types of "this" and t. If "this"
* or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. If not all of the two classes' superclasses
* cannot be found, "null" is returned. See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
* cannot be found, "null" is returned. See the JVM specification edition 2, "§4.9.2 The Bytecode Verifier".
*/
public ReferenceType getFirstCommonSuperclass(ReferenceType t) {
if (this.equals(Type.NULL)) {
......@@ -300,7 +300,7 @@ public abstract class ReferenceType extends Type {
// * t is an ArrayType, then Type.OBJECT is returned. If "this" or t is a ReferenceType referencing an interface, then
// Type.OBJECT
// * is returned. If not all of the two classes' superclasses cannot be found, "null" is returned. See the JVM specification
// * edition 2, "4.9.2 The Bytecode Verifier".
// * edition 2, "§4.9.2 The Bytecode Verifier".
// *
// * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has slightly changed semantics.
// */
......
......@@ -59,7 +59,7 @@ import org.aspectj.apache.bcel.generic.InstructionHandle;
/**
* Returnaddress, the type JSR or JSR_W instructions push upon the stack.
*
* see vmspec2 3.3.3
* see vmspec2 §3.3.3
* @version $Id: ReturnaddressType.java,v 1.3 2008/05/28 23:52:56 aclement Exp $
* @author <A HREF="http://www.inf.fu-berlin.de/~ehaase">Enver Haase</A>
*/
......
......@@ -56,7 +56,16 @@ package org.aspectj.apache.bcel.util;
import java.util.*;
import java.util.zip.*;
import java.io.*;
import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
/**
* Responsible for loading (class) files from the CLASSPATH. Inspired by
......@@ -77,6 +86,7 @@ public class ClassPath implements Serializable {
}
return SYSTEM_CLASS_PATH;
}
/**
* Search for classes in given path.
*/
......@@ -85,10 +95,8 @@ public class ClassPath implements Serializable {
ArrayList<PathEntry> vec = new ArrayList<PathEntry>();
for(StringTokenizer tok=new StringTokenizer(class_path,
System.getProperty("path.separator"));
tok.hasMoreTokens();)
{
for (StringTokenizer tok = new StringTokenizer(class_path, System.getProperty("path.separator")); tok
.hasMoreTokens();) {
String path = tok.nextToken();
if (!path.equals("")) {
......@@ -98,9 +106,12 @@ public class ClassPath implements Serializable {
if (file.exists()) {
if (file.isDirectory())
vec.add(new Dir(path));
else
else if (file.getName().endsWith(".jimage")) {
vec.add(new JImage(file));
} else {
vec.add(new Zip(new ZipFile(file)));
}
}
} catch (IOException e) {
System.err.println("CLASSPATH component " + file + ": " + e);
}
......@@ -113,13 +124,15 @@ public class ClassPath implements Serializable {
/**
* Search for classes in CLASSPATH.
*
* @deprecated Use SYSTEM_CLASS_PATH constant
*/
public ClassPath() {
this(getClassPath());
}
/** @return used class path string
/**
* @return used class path string
*/
public String toString() {
return class_path;
......@@ -151,7 +164,8 @@ public class ClassPath implements Serializable {
}
}
/** Checks for class path components in the following properties:
/**
* Checks for class path components in the following properties:
* "java.class.path", "sun.boot.class.path", "java.ext.dirs"
*
* @return class path as used by default by BCEL
......@@ -196,7 +210,8 @@ public class ClassPath implements Serializable {
}
/**
* @param name fully qualified class name, e.g. java.lang.String
* @param name
* fully qualified class name, e.g. java.lang.String
* @return input stream for class
*/
public InputStream getInputStream(String name) throws IOException {
......@@ -206,8 +221,10 @@ public class ClassPath implements Serializable {
/**
* Return stream for class or resource on CLASSPATH.
*
* @param name fully qualified file name, e.g. java/lang/String
* @param suffix file name ends with suff, e.g. .java
* @param name
* fully qualified file name, e.g. java/lang/String
* @param suffix
* file name ends with suff, e.g. .java
* @return input stream for file on class path
*/
public InputStream getInputStream(String name, String suffix) throws IOException {
......@@ -215,7 +232,8 @@ public class ClassPath implements Serializable {
try {
is = getClass().getClassLoader().getResourceAsStream(name + suffix);
} catch(Exception e) { }
} catch (Exception e) {
}
if (is != null)
return is;
......@@ -224,8 +242,10 @@ public class ClassPath implements Serializable {
}
/**
* @param name fully qualified file name, e.g. java/lang/String
* @param suffix file name ends with suff, e.g. .java
* @param name
* fully qualified file name, e.g. java/lang/String
* @param suffix
* file name ends with suff, e.g. .java
* @return class file for the java class
*/
public ClassFile getClassFile(String name, String suffix) throws IOException {
......@@ -240,7 +260,8 @@ public class ClassPath implements Serializable {
}
/**
* @param name fully qualified class name, e.g. java.lang.String
* @param name
* fully qualified class name, e.g. java.lang.String
* @return input stream for class
*/
public ClassFile getClassFile(String name) throws IOException {
......@@ -248,8 +269,10 @@ public class ClassPath implements Serializable {
}
/**
* @param name fully qualified file name, e.g. java/lang/String
* @param suffix file name ends with suffix, e.g. .java
* @param name
* fully qualified file name, e.g. java/lang/String
* @param suffix
* file name ends with suffix, e.g. .java
* @return byte array for file on class path
*/
public byte[] getBytes(String name, String suffix) throws IOException {
......@@ -261,7 +284,8 @@ public class ClassPath implements Serializable {
DataInputStream dis = new DataInputStream(is);
byte[] bytes = new byte[is.available()];
dis.readFully(bytes);
dis.close(); is.close();
dis.close();
is.close();
return bytes;
}
......@@ -274,7 +298,8 @@ public class ClassPath implements Serializable {
}
/**
* @param name name of file to search for, e.g. java/lang/String.java
* @param name
* name of file to search for, e.g. java/lang/String.java
* @return full (canonical) path for file
*/
public String getPath(String name) throws IOException {
......@@ -290,8 +315,10 @@ public class ClassPath implements Serializable {
}
/**
* @param name name of file to search for, e.g. java/lang/String
* @param suffix file name suffix, e.g. .java
* @param name
* name of file to search for, e.g. java/lang/String
* @param suffix
* file name suffix, e.g. .java
* @return full (canonical) path for file, if it exists
*/
public String getPath(String name, String suffix) throws IOException {
......@@ -302,27 +329,33 @@ public class ClassPath implements Serializable {
abstract ClassFile getClassFile(String name, String suffix) throws IOException;
}
/** Contains information about file/ZIP entry of the Java class.
/**
* Contains information about file/ZIP entry of the Java class.
*/
public interface ClassFile {
/** @return input stream for class file.
/**
* @return input stream for class file.
*/
public abstract InputStream getInputStream() throws IOException;
/** @return canonical path to class file.
/**
* @return canonical path to class file.
*/
public abstract String getPath();
/** @return base path of found class, i.e. class is contained relative
* to that path, which may either denote a directory, or zip file
/**
* @return base path of found class, i.e. class is contained relative to
* that path, which may either denote a directory, or zip file
*/
public abstract String getBase();
/** @return modification time of class file.
/**
* @return modification time of class file.
*/
public abstract long getTime();
/** @return size of class file.
/**
* @return size of class file.
*/
public abstract long getSize();
}
......@@ -330,43 +363,175 @@ public class ClassPath implements Serializable {
private static class Dir extends PathEntry {
private String dir;
Dir(String d) { dir = d; }
Dir(String d) {
dir = d;
}
ClassFile getClassFile(String name, String suffix) throws IOException {
final File file = new File(dir + File.separatorChar +
name.replace('.', File.separatorChar) + suffix);
final File file = new File(dir + File.separatorChar + name.replace('.', File.separatorChar) + suffix);
return file.exists() ? new ClassFile() {
public InputStream getInputStream() throws IOException { return new FileInputStream(file); }
public InputStream getInputStream() throws IOException {
return new FileInputStream(file);
}
public String getPath() { try {
public String getPath() {
try {
return file.getCanonicalPath();
} catch(IOException e) { return null; }
} catch (IOException e) {
return null;
}
}
public long getTime() { return file.lastModified(); }
public long getSize() { return file.length(); }
public String getBase() { return dir; }
public long getTime() {
return file.lastModified();
}
public long getSize() {
return file.length();
}
public String getBase() {
return dir;
}
} : null;
}
public String toString() { return dir; }
public String toString() {
return dir;
}
}
private static class JImage extends PathEntry {
private java.nio.file.FileSystem fs;
private static URI JRT_URI = URI.create("jrt:/"); //$NON-NLS-1$
private static String MODULES_PATH = "modules"; //$NON-NLS-1$
private static String JAVA_BASE_PATH = "java.base"; //$NON-NLS-1$
JImage(File jimage) {
// TODO bizarre that you use getFileSystem with just the jrt:/ and not the path !! What happens
// if there are two?
fs = FileSystems.getFileSystem(JRT_URI);//.create(jimage.getAbsolutePath()));
}
private static class ByteBasedClassFile implements ClassFile {
private byte[] bytes;
private ByteArrayInputStream bais;
private String path;
private String base;
private long time;
private long size;
public ByteBasedClassFile(byte[] bytes, String path, String base, long time, long size) {
this.bytes = bytes;
this.path = path;
this.base = base;
this.time = time;
this.size = size;
}
public InputStream getInputStream() throws IOException {
// TODO too costly to keep these in inflated form in memory?
this.bais = new ByteArrayInputStream(bytes);
return this.bais;
}
public String getPath() {
return this.path;
}
public String getBase() {
return this.base;
}
public long getTime() {
return this.time;
}
public long getSize() {
return this.size;
}
}
ClassFile getClassFile(String name, String suffix) throws IOException {
// Class files are in here under names like this:
// /modules/java.base/java/lang/Object.class (jdk9 b74)
// so within a modules top level qualifier and then the java.base module
String fileName = name + suffix;
try {
Path p = fs.getPath(MODULES_PATH,JAVA_BASE_PATH,fileName);
byte[] bs = Files.readAllBytes(p);
BasicFileAttributeView bfav = Files.getFileAttributeView(p, BasicFileAttributeView.class);
BasicFileAttributes bfas = bfav.readAttributes();
long time = bfas.lastModifiedTime().toMillis();
long size = bfas.size();
return new ByteBasedClassFile(bs, "jimage",fileName,time,size);
} catch (NoSuchFileException nsfe) {
// try other modules!
Iterable<java.nio.file.Path> roots = fs.getRootDirectories();
roots = fs.getRootDirectories();
for (java.nio.file.Path path : roots) {
DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(path);
try {
for (java.nio.file.Path module: stream) {
// module will be something like /packages or /modules
for (java.nio.file.Path submodule: Files.newDirectoryStream(module)) {
// submodule will be /modules/java.base or somesuch
try {
Path p = fs.getPath(submodule.toString(), fileName);
byte[] bs = Files.readAllBytes(p);
BasicFileAttributeView bfav = Files.getFileAttributeView(p, BasicFileAttributeView.class);
BasicFileAttributes bfas = bfav.readAttributes();
long time = bfas.lastModifiedTime().toMillis();
long size = bfas.size();
return new ByteBasedClassFile(bs, "jimage", fileName,time,size);
} catch (NoSuchFileException nsfe2) {
}
}
}
} finally {
stream.close();
}
}
return null;
}
}
}
private static class Zip extends PathEntry {
private ZipFile zip;
Zip(ZipFile z) { zip = z; }
Zip(ZipFile z) {
zip = z;
}
ClassFile getClassFile(String name, String suffix) throws IOException {
final ZipEntry entry = zip.getEntry(name.replace('.', '/') + suffix);
return (entry != null) ? new ClassFile() {
public InputStream getInputStream() throws IOException { return zip.getInputStream(entry); }
public String getPath() { return entry.toString(); }
public long getTime() { return entry.getTime(); }
public long getSize() { return entry.getSize(); }
public InputStream getInputStream() throws IOException {
return zip.getInputStream(entry);
}
public String getPath() {
return entry.toString();
}
public long getTime() {
return entry.getTime();
}
public long getSize() {
return entry.getSize();
}
public String getBase() {
return zip.getName();
}
......@@ -374,5 +539,3 @@ public class ClassPath implements Serializable {
}
}
}
......@@ -92,6 +92,7 @@ import org.aspectj.apache.bcel.classfile.LocalVariableTable;
import org.aspectj.apache.bcel.classfile.LocalVariableTypeTable;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.MethodParameters;
import org.aspectj.apache.bcel.classfile.Module;
import org.aspectj.apache.bcel.classfile.Signature;
import org.aspectj.apache.bcel.classfile.SourceFile;
import org.aspectj.apache.bcel.classfile.StackMap;
......@@ -107,10 +108,9 @@ import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisParamAnnos;
import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisTypeAnnos;
/**
* Traverses a JavaClass with another Visitor object 'piggy-backed'
* that is applied to all components of a JavaClass object. I.e. this
* class supplies the traversal strategy, other classes can make use
* of it.
* Traverses a JavaClass with another Visitor object 'piggy-backed' that is
* applied to all components of a JavaClass object. I.e. this class supplies the
* traversal strategy, other classes can make use of it.
*
* @version $Id: DescendingVisitor.java,v 1.4 2009/09/15 19:40:22 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
......@@ -120,14 +120,16 @@ public class DescendingVisitor implements ClassVisitor {
private ClassVisitor visitor;
private Stack<Object> stack = new Stack<Object>();
/** @return container of current entitity, i.e., predecessor during traversal
/**
* @return container of current entitity, i.e., predecessor during traversal
*/
public Object predecessor() {
return predecessor(0);
}
/**
* @param level nesting level, i.e., 0 returns the direct predecessor
* @param level
* nesting level, i.e., 0 returns the direct predecessor
* @return container of current entitity, i.e., predecessor during traversal
*/
public Object predecessor(int level) {
......@@ -139,15 +141,18 @@ public class DescendingVisitor implements ClassVisitor {
return stack.elementAt(size - (level + 2)); // size - 1 == current
}
/** @return current object
/**
* @return current object
*/
public Object current() {
return stack.peek();
}
/**
* @param clazz Class to traverse
* @param visitor visitor object to apply to all components
* @param clazz
* Class to traverse
* @param visitor
* visitor object to apply to all components
*/
public DescendingVisitor(JavaClass clazz, ClassVisitor visitor) {
this.clazz = clazz;
......@@ -157,7 +162,9 @@ public class DescendingVisitor implements ClassVisitor {
/**
* Start traversal.
*/
public void visit() { clazz.accept(this); }
public void visit() {
clazz.accept(this);
}
public void visitJavaClass(JavaClass clazz) {
stack.push(clazz);
......@@ -478,4 +485,10 @@ public class DescendingVisitor implements ClassVisitor {
attribute.accept(visitor);
stack.pop();
}
public void visitModule(Module attribute) {
stack.push(attribute);
attribute.accept(visitor);
stack.pop();
}
}
......@@ -87,6 +87,7 @@ import org.aspectj.apache.bcel.classfile.LocalVariableTable;
import org.aspectj.apache.bcel.classfile.LocalVariableTypeTable;
import org.aspectj.apache.bcel.classfile.Method;
import org.aspectj.apache.bcel.classfile.MethodParameters;
import org.aspectj.apache.bcel.classfile.Module;
import org.aspectj.apache.bcel.classfile.Signature;
import org.aspectj.apache.bcel.classfile.SourceFile;
import org.aspectj.apache.bcel.classfile.StackMap;
......@@ -150,6 +151,7 @@ public class EmptyClassVisitor implements ClassVisitor {
public void visitUnknown(Unknown obj) {}
public void visitStackMap(StackMap obj) {}
public void visitStackMapEntry(StackMapEntry obj) {}
public void visitModule(Module obj) {}
// J5SUPPORT:
public void visitEnclosingMethod(EnclosingMethod obj) {}
......