package org.aspectj.weaver.bcel;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.aspectj.apache.bcel.classfile.JavaClass;
import org.aspectj.util.FileUtil;
import org.aspectj.weaver.IUnwovenClassFile;
public class UnwovenClassFile implements IUnwovenClassFile {
protected String filename;
protected char[] charfilename;
protected byte[] bytes;
protected List<ChildClass> writtenChildClasses = Collections.emptyList();
protected String className = null;
protected boolean isModule = false;
public UnwovenClassFile(String filename, byte[] bytes) {
this.filename = filename;
this.isModule = filename.toLowerCase().endsWith("module-info.java");
this.bytes = bytes;
}
public UnwovenClassFile(String filename, String classname, byte[] bytes) {
this.filename = filename;
this.isModule = filename.toLowerCase().endsWith("module-info.class");
this.className = classname;
this.bytes = bytes;
}
public boolean shouldBeWoven() {
return !isModule;
}
public String getFilename() {
return filename;
}
public String makeInnerFileName(String innerName) {
String prefix = filename.substring(0, filename.length() - 6);
return prefix + "$" + innerName + ".class";
}
public byte[] getBytes() {
return bytes;
}
public JavaClass getJavaClass() {
if (getBytes() == null) {
System.out.println("no bytes for: " + getFilename());
Thread.dumpStack();
}
return Utility.makeJavaClass(filename, getBytes());
}
public void writeUnchangedBytes() throws IOException {
writeWovenBytes(getBytes(), Collections.<ChildClass>emptyList());
}
public void writeWovenBytes(byte[] bytes, List<ChildClass> childClasses) throws IOException {
writeChildClasses(childClasses);
BufferedOutputStream os = FileUtil.makeOutputStream(new File(filename));
os.write(bytes);
os.close();
}
private void writeChildClasses(List<ChildClass> childClasses) throws IOException {
deleteAllChildClasses();
childClasses.removeAll(writtenChildClasses);
for (ChildClass childClass : childClasses) {
writeChildClassFile(childClass.name, childClass.bytes);
}
writtenChildClasses = childClasses;
}
private void writeChildClassFile(String innerName, byte[] bytes) throws IOException {
BufferedOutputStream os = FileUtil.makeOutputStream(new File(makeInnerFileName(innerName)));
os.write(bytes);
os.close();
}
protected void deleteAllChildClasses() {
for (ChildClass childClass : writtenChildClasses) {
deleteChildClassFile(childClass.name);
}
}
protected void deleteChildClassFile(String innerName) {
File childClassFile = new File(makeInnerFileName(innerName));
childClassFile.delete();
}
static boolean unchanged(byte[] b1, byte[] b2) {
int len = b1.length;
if (b2.length != len)
return false;
for (int i = 0; i < len; i++) {
if (b1[i] != b2[i])
return false;
}
return true;
}
public char[] getClassNameAsChars() {
if (charfilename == null) {
charfilename = getClassName().replace('.', '/').toCharArray();
}
return charfilename;
}
public String getClassName() {
if (className == null)
className = getJavaClass().getClassName();
return className;
}
@Override
public String toString() {
return "UnwovenClassFile(" + filename + ", " + getClassName() + ")";
}
public static class ChildClass {
public final String name;
public final byte[] bytes;
ChildClass(String name, byte[] bytes) {
this.name = name;
this.bytes = bytes;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ChildClass))
return false;
ChildClass o = (ChildClass) other;
return o.name.equals(name) && unchanged(o.bytes, bytes);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return "(ChildClass " + name + ")";
}
}
public void setClassNameAsChars(char[] classNameAsChars) {
this.charfilename = classNameAsChars;
}
}