mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
replace also a class with annotation
This commit is contained in:
parent
442b582dfc
commit
d103f97c04
@ -34,8 +34,6 @@ import de.inetsoftware.classparser.Attributes.AttributeInfo;
|
||||
*/
|
||||
public class ClassFile {
|
||||
|
||||
private final DataInputStream input;
|
||||
|
||||
private final int minorVersion;
|
||||
|
||||
private final int majorVersion;
|
||||
@ -71,7 +69,7 @@ public class ClassFile {
|
||||
* if this input stream reaches the end before reading the class file.
|
||||
*/
|
||||
public ClassFile( InputStream stream ) throws IOException {
|
||||
this.input = new DataInputStream( stream );
|
||||
DataInputStream input = new DataInputStream( stream );
|
||||
int magic = input.readInt();
|
||||
if( magic != 0xCAFEBABE ) {
|
||||
throw new IOException( "Invalid class magic: " + Integer.toHexString( magic ) );
|
||||
@ -87,8 +85,8 @@ public class ClassFile {
|
||||
for( int i = 0; i < interfaces.length; i++ ) {
|
||||
interfaces[i] = (ConstantClass)constantPool.get( input.readUnsignedShort() );
|
||||
}
|
||||
fields = readFields();
|
||||
methods = readMethods();
|
||||
fields = readFields( input );
|
||||
methods = readMethods( input );
|
||||
attributes = new Attributes( input, constantPool );
|
||||
|
||||
stream.close();
|
||||
@ -117,6 +115,45 @@ public class ClassFile {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a replaced instance.
|
||||
*
|
||||
* @param className
|
||||
* the class name that should be replaced
|
||||
* @param classFile
|
||||
* the replacing class file data
|
||||
*/
|
||||
public ClassFile( String className, ClassFile classFile ) {
|
||||
minorVersion = classFile.minorVersion;
|
||||
majorVersion = classFile.majorVersion;
|
||||
|
||||
constantPool = classFile.constantPool;
|
||||
accessFlags = classFile.accessFlags;
|
||||
thisClass = new ConstantClass( className );
|
||||
superClass = classFile.superClass;
|
||||
interfaces = classFile.interfaces;
|
||||
fields = classFile.fields;
|
||||
methods = classFile.methods;
|
||||
attributes = classFile.attributes;
|
||||
|
||||
// patch constant pool
|
||||
String origClassName = classFile.thisClass.getName();
|
||||
for( int i = 0; i < constantPool.size(); i++ ) {
|
||||
Object obj = constantPool.get( i );
|
||||
if( obj instanceof ConstantClass ) {
|
||||
if( ((ConstantClass)obj).getName().equals( origClassName ) ) {
|
||||
constantPool.set( i, thisClass );
|
||||
}
|
||||
} else if( obj instanceof ConstantFieldRef ) {
|
||||
ConstantFieldRef ref = (ConstantFieldRef)obj;
|
||||
if( ref.getClassName().equals( origClassName ) ) {
|
||||
ConstantNameAndType nameAndType = new ConstantNameAndType( ref.getName(), ref.getType() );
|
||||
constantPool.set( i, new ConstantFieldRef( thisClass, nameAndType ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of SourceFile if available.
|
||||
*
|
||||
@ -216,7 +253,7 @@ public class ClassFile {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
private FieldInfo[] readFields() throws IOException {
|
||||
private FieldInfo[] readFields( DataInputStream input ) throws IOException {
|
||||
FieldInfo[] fields = new FieldInfo[input.readUnsignedShort()];
|
||||
for( int i = 0; i < fields.length; i++ ) {
|
||||
fields[i] = new FieldInfo( input, constantPool );
|
||||
@ -224,7 +261,7 @@ public class ClassFile {
|
||||
return fields;
|
||||
}
|
||||
|
||||
private MethodInfo[] readMethods() throws IOException {
|
||||
private MethodInfo[] readMethods( DataInputStream input ) throws IOException {
|
||||
MethodInfo[] methods = new MethodInfo[input.readUnsignedShort()];
|
||||
for( int i = 0; i < methods.length; i++ ) {
|
||||
methods[i] = new MethodInfo( input, constantPool, this );
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2011 - 2019 Volker Berlin (i-net software)
|
||||
Copyright 2011 - 2020 Volker Berlin (i-net software)
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -147,4 +147,25 @@ public class ConstantPool {
|
||||
public Object get( int index ) {
|
||||
return constantPool[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in the constant pool.
|
||||
*
|
||||
* @param index
|
||||
* the index
|
||||
* @param value
|
||||
* the new value
|
||||
*/
|
||||
void set( int index, Object value ) {
|
||||
constantPool[index] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of entries in the pool.
|
||||
*
|
||||
* @return the count
|
||||
*/
|
||||
int size() {
|
||||
return constantPool.length;
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.module;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ -31,7 +32,9 @@ import de.inetsoftware.classparser.WeakValueCache;
|
||||
*/
|
||||
public class ClassFileLoader {
|
||||
|
||||
private final WeakValueCache<String, ClassFile> CACHE = new WeakValueCache<>();
|
||||
private final HashMap<String, ClassFile> replace = new HashMap<>();
|
||||
|
||||
private final WeakValueCache<String, ClassFile> weakCache = new WeakValueCache<>();
|
||||
|
||||
private final ClassLoader loader;
|
||||
|
||||
@ -56,16 +59,32 @@ public class ClassFileLoader {
|
||||
*/
|
||||
@Nullable
|
||||
public ClassFile get( String className ) throws IOException {
|
||||
ClassFile classFile = CACHE.get( className );
|
||||
ClassFile classFile = replace.get( className );
|
||||
if( classFile != null ) {
|
||||
return classFile;
|
||||
}
|
||||
classFile = weakCache.get( className );
|
||||
if( classFile != null ) {
|
||||
return classFile;
|
||||
}
|
||||
InputStream stream = loader.getResourceAsStream( className + ".class" );
|
||||
if( stream != null ) {
|
||||
classFile = new ClassFile( stream );
|
||||
CACHE.put( className, classFile );
|
||||
weakCache.put( className, classFile );
|
||||
}
|
||||
return classFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the class in the cache with the given instance.
|
||||
*
|
||||
* @param className
|
||||
* the name of the class to replace
|
||||
* @param classFile
|
||||
* the replasing ClassFile
|
||||
*/
|
||||
public void replace( String className, ClassFile classFile ) {
|
||||
classFile = new ClassFile( className, classFile );
|
||||
replace.put( className, classFile );
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2017 - 2019 Volker Berlin (i-net software)
|
||||
* Copyright 2017 - 2020 Volker Berlin (i-net software)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -158,8 +158,19 @@ public class ModuleGenerator {
|
||||
* the class file
|
||||
* @throws WasmException
|
||||
* if some Java code can't converted
|
||||
* @throws IOException
|
||||
* if any I/O error occur
|
||||
*/
|
||||
public void prepare( ClassFile classFile ) {
|
||||
public void prepare( ClassFile classFile ) throws IOException {
|
||||
// check if this class replace another class
|
||||
Map<String,Object> annotationValues;
|
||||
if( (annotationValues = classFile.getAnnotation( JWebAssembly.REPLACE_ANNOTATION )) != null ) {
|
||||
String signatureName = (String)annotationValues.get( "value" );
|
||||
if( signatureName != null ) {
|
||||
classFileLoader.replace( signatureName, classFile );
|
||||
}
|
||||
}
|
||||
|
||||
iterateMethods( classFile, m -> prepareMethod( m ) );
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user