Browse Source

REPORT-51412 fix: 移除fine-third的TTL和javaassist

release/10.0
Cloud.Liu 3 years ago
parent
commit
0f7c125ff1
  1. 3
      build.third_step3-jdk11.gradle
  2. 3
      build.third_step3.gradle
  3. 2
      build.third_step8-jdk11.gradle
  4. 2
      build.third_step8.gradle
  5. 6
      fine-hibernate/pom.xml
  6. 6
      fine-javassist/.gitignore
  7. 2
      fine-javassist/README.md
  8. 18
      fine-javassist/pom.xml
  9. 99
      fine-javassist/src/main/java/com/fr/third/javassist/ByteArrayClassPath.java
  10. 120
      fine-javassist/src/main/java/com/fr/third/javassist/CannotCompileException.java
  11. 97
      fine-javassist/src/main/java/com/fr/third/javassist/ClassClassPath.java
  12. 173
      fine-javassist/src/main/java/com/fr/third/javassist/ClassMap.java
  13. 68
      fine-javassist/src/main/java/com/fr/third/javassist/ClassPath.java
  14. 1164
      fine-javassist/src/main/java/com/fr/third/javassist/ClassPool.java
  15. 429
      fine-javassist/src/main/java/com/fr/third/javassist/ClassPoolTail.java
  16. 809
      fine-javassist/src/main/java/com/fr/third/javassist/CodeConverter.java
  17. 113
      fine-javassist/src/main/java/com/fr/third/javassist/CtArray.java
  18. 1215
      fine-javassist/src/main/java/com/fr/third/javassist/CtBehavior.java
  19. 1558
      fine-javassist/src/main/java/com/fr/third/javassist/CtClass.java
  20. 1722
      fine-javassist/src/main/java/com/fr/third/javassist/CtClassType.java
  21. 403
      fine-javassist/src/main/java/com/fr/third/javassist/CtConstructor.java
  22. 1414
      fine-javassist/src/main/java/com/fr/third/javassist/CtField.java
  23. 322
      fine-javassist/src/main/java/com/fr/third/javassist/CtMember.java
  24. 436
      fine-javassist/src/main/java/com/fr/third/javassist/CtMethod.java
  25. 127
      fine-javassist/src/main/java/com/fr/third/javassist/CtNewClass.java
  26. 317
      fine-javassist/src/main/java/com/fr/third/javassist/CtNewConstructor.java
  27. 476
      fine-javassist/src/main/java/com/fr/third/javassist/CtNewMethod.java
  28. 67
      fine-javassist/src/main/java/com/fr/third/javassist/CtNewNestedClass.java
  29. 103
      fine-javassist/src/main/java/com/fr/third/javassist/CtNewWrappedConstructor.java
  30. 199
      fine-javassist/src/main/java/com/fr/third/javassist/CtNewWrappedMethod.java
  31. 112
      fine-javassist/src/main/java/com/fr/third/javassist/CtPrimitiveType.java
  32. 433
      fine-javassist/src/main/java/com/fr/third/javassist/Loader.java
  33. 96
      fine-javassist/src/main/java/com/fr/third/javassist/LoaderClassPath.java
  34. 219
      fine-javassist/src/main/java/com/fr/third/javassist/Modifier.java
  35. 30
      fine-javassist/src/main/java/com/fr/third/javassist/NotFoundException.java
  36. 212
      fine-javassist/src/main/java/com/fr/third/javassist/SerialVersionUID.java
  37. 71
      fine-javassist/src/main/java/com/fr/third/javassist/Translator.java
  38. 179
      fine-javassist/src/main/java/com/fr/third/javassist/URLClassPath.java
  39. 133
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AccessFlag.java
  40. 161
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AnnotationDefaultAttribute.java
  41. 703
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AnnotationsAttribute.java
  42. 289
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AttributeInfo.java
  43. 40
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/BadBytecode.java
  44. 123
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/BootstrapMethodsAttribute.java
  45. 77
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ByteArray.java
  46. 194
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ByteStream.java
  47. 1430
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Bytecode.java
  48. 909
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ClassFile.java
  49. 154
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ClassFilePrinter.java
  50. 782
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ClassFileWriter.java
  51. 267
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/CodeAnalyzer.java
  52. 594
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/CodeAttribute.java
  53. 1599
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/CodeIterator.java
  54. 1991
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ConstPool.java
  55. 73
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ConstantAttribute.java
  56. 56
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/DeprecatedAttribute.java
  57. 872
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Descriptor.java
  58. 31
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/DuplicateMemberException.java
  59. 134
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/EnclosingMethodAttribute.java
  60. 281
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ExceptionTable.java
  61. 174
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ExceptionsAttribute.java
  62. 269
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/FieldInfo.java
  63. 242
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/InnerClassesAttribute.java
  64. 295
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/InstructionPrinter.java
  65. 182
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LineNumberAttribute.java
  66. 334
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LocalVariableAttribute.java
  67. 63
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LocalVariableTypeAttribute.java
  68. 64
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LongVector.java
  69. 551
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/MethodInfo.java
  70. 239
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Mnemonic.java
  71. 449
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Opcode.java
  72. 215
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ParameterAnnotationsAttribute.java
  73. 1170
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/SignatureAttribute.java
  74. 71
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/SourceFileAttribute.java
  75. 575
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/StackMap.java
  76. 1051
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/StackMapTable.java
  77. 56
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/SyntheticAttribute.java
  78. 423
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Analyzer.java
  79. 504
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/ControlFlow.java
  80. 1047
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Executor.java
  81. 289
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Frame.java
  82. 148
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/FramePrinter.java
  83. 57
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/IntQueue.java
  84. 130
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/MultiArrayType.java
  85. 314
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/MultiType.java
  86. 67
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Subroutine.java
  87. 157
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/SubroutineScanner.java
  88. 593
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Type.java
  89. 48
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Util.java
  90. 20
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/package.html
  91. 351
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/Annotation.java
  92. 305
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/AnnotationImpl.java
  93. 97
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/AnnotationMemberValue.java
  94. 356
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/AnnotationsWriter.java
  95. 146
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/ArrayMemberValue.java
  96. 104
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/BooleanMemberValue.java
  97. 104
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/ByteMemberValue.java
  98. 105
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/CharMemberValue.java
  99. 140
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/ClassMemberValue.java
  100. 106
      fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/DoubleMemberValue.java
  101. Some files were not shown because too many files have changed in this diff Show More

3
build.third_step3-jdk11.gradle

@ -31,7 +31,6 @@ sourceSets{
java{
srcDirs=[
"${srcDir}/fine-itext/src/main/java",
"${srcDir}/fine-javassist/src/main/java",
"${srcDir}/fine-jedis/src/main/java",
"${srcDir}/fine-jboss-logging/src/main/java"
]
@ -43,8 +42,6 @@ sourceSets{
def resourceDirs = [
"${srcDir}/fine-itext/src/main/java",
"${srcDir}/fine-itext/src/main/resources",
"${srcDir}/fine-javassist/src/main/java",
"${srcDir}/fine-javassist/src/main/resources",
"${srcDir}/fine-jedis/src/main/java",
"${srcDir}/fine-jedis/src/main/resources",
"${srcDir}/fine-jboss-logging/src/main/java",

3
build.third_step3.gradle

@ -25,7 +25,6 @@ sourceSets{
java{
srcDirs=[
"${srcDir}/fine-itext/src/main/java",
"${srcDir}/fine-javassist/src/main/java",
"${srcDir}/fine-jedis/src/main/java",
"${srcDir}/fine-jboss-logging/src/main/java"
]
@ -84,8 +83,6 @@ task copyFiles(type:Copy,dependsOn:'compileJava'){
println "------------------------------------------------copyfiles"
with dataContent.call("${srcDir}/fine-itext/src/main/java")
with dataContent.call("${srcDir}/fine-itext/src/main/resources")
with dataContent.call("${srcDir}/fine-javassist/src/main/java")
with dataContent.call("${srcDir}/fine-javassist/src/main/resources")
with dataContent.call("${srcDir}/fine-jedis/src/main/java")
with dataContent.call("${srcDir}/fine-jedis/src/main/resources")
with dataContent.call("${srcDir}/fine-jboss-logging/src/main/java")

2
build.third_step8-jdk11.gradle

@ -26,7 +26,6 @@ sourceSets{
java{
srcDirs=[
"${srcDir}/fine-ehcache/src/main/java",
"${srcDir}/fine-transmittable-thread-local/src/main/java"
]
}
}
@ -35,7 +34,6 @@ sourceSets{
def resourceDirs = [
"${srcDir}/fine-ehcache/src/main/java",
"${srcDir}/fine-ehcache/src/main/recources",
"${srcDir}/fine-transmittable-thread-local/src/main/java"
]
sourceSets.main.java.outputDir = file('build/classes/8')

2
build.third_step8.gradle

@ -26,7 +26,6 @@ sourceSets{
java{
srcDirs=[
"${srcDir}/fine-ehcache/src/main/java",
"${srcDir}/fine-transmittable-thread-local/src/main/java"
]
}
}
@ -83,7 +82,6 @@ task copyFiles(type:Copy,dependsOn:'compileJava'){
println "------------------------------------------------copyfiles"
with dataContent.call("${srcDir}/fine-ehcache/src/main/java")
with dataContent.call("${srcDir}/fine-ehcache/src/main/recources")
with dataContent.call("${srcDir}/fine-transmittable-thread-local/src/main/java")
into "${classesDir}"
}
}

6
fine-hibernate/pom.xml

@ -41,9 +41,9 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.fr.third</groupId>
<artifactId>fine-javassist</artifactId>
<version>${revision}</version>
<groupId>com.fr.essential</groupId>
<artifactId>fine-javaassist</artifactId>
<version>${essentialVersion}</version>
</dependency>
<dependency>
<groupId>com.fr.third</groupId>

6
fine-javassist/.gitignore vendored

@ -1,6 +0,0 @@
*.iml
.idea/
.DS_Store
.project
.classpath
*.gradle

2
fine-javassist/README.md

@ -1,2 +0,0 @@
源码地址:https://github.com/jboss-javassist/javassist <br>
版本:3.18

18
fine-javassist/pom.xml

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.fr.third</groupId>
<artifactId>step3</artifactId>
<version>${revision}</version>
<relativePath>../base-third-project/base-third-step3</relativePath>
</parent>
<artifactId>fine-javassist</artifactId>
<version>${revision}</version>
</project>

99
fine-javassist/src/main/java/com/fr/third/javassist/ByteArrayClassPath.java

@ -1,99 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;
/**
* A <code>ByteArrayClassPath</code> contains bytes that is served as
* a class file to a <code>ClassPool</code>. It is useful to convert
* a byte array to a <code>CtClass</code> object.
*
* <p>For example, if you want to convert a byte array <code>b</code>
* into a <code>CtClass</code> object representing the class with a name
* <code>classname</code>, then do as following:
*
* <ul><pre>
* ClassPool cp = ClassPool.getDefault();
* cp.insertClassPath(new ByteArrayClassPath(classname, b));
* CtClass cc = cp.get(classname);
* </pre></ul>
*
* <p>The <code>ClassPool</code> object <code>cp</code> uses the created
* <code>ByteArrayClassPath</code> object as the source of the class file.
*
* <p>A <code>ByteArrayClassPath</code> must be instantiated for every
* class. It contains only a single class file.
*
* @see ClassPath
* @see ClassPool#insertClassPath(ClassPath)
* @see ClassPool#appendClassPath(ClassPath)
* @see ClassPool#makeClass(InputStream)
*/
public class ByteArrayClassPath implements ClassPath {
protected String classname;
protected byte[] classfile;
/*
* Creates a <code>ByteArrayClassPath</code> containing the given
* bytes.
*
* @param name a fully qualified class name
* @param classfile the contents of a class file.
*/
public ByteArrayClassPath(String name, byte[] classfile) {
this.classname = name;
this.classfile = classfile;
}
/**
* Closes this class path.
*/
public void close() {}
public String toString() {
return "byte[]:" + classname;
}
/**
* Opens the class file.
*/
public InputStream openClassfile(String classname) {
if(this.classname.equals(classname))
return new ByteArrayInputStream(classfile);
else
return null;
}
/**
* Obtains the URL.
*/
public URL find(String classname) {
if(this.classname.equals(classname)) {
String cname = classname.replace('.', '/') + ".class";
try {
// return new File(cname).toURL();
return new URL("file:/ByteArrayClassPath/" + cname);
}
catch (MalformedURLException e) {}
}
return null;
}
}

120
fine-javassist/src/main/java/com/fr/third/javassist/CannotCompileException.java

@ -1,120 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.compiler.CompileError;
/**
* Thrown when bytecode transformation has failed.
*/
public class CannotCompileException extends Exception {
private Throwable myCause;
/**
* Gets the cause of this throwable.
* It is for JDK 1.3 compatibility.
*/
public Throwable getCause() {
return (myCause == this ? null : myCause);
}
/**
* Initializes the cause of this throwable.
* It is for JDK 1.3 compatibility.
*/
public synchronized Throwable initCause(Throwable cause) {
myCause = cause;
return this;
}
private String message;
/**
* Gets a long message if it is available.
*/
public String getReason() {
if (message != null)
return message;
else
return this.toString();
}
/**
* Constructs a CannotCompileException with a message.
*
* @param msg the message.
*/
public CannotCompileException(String msg) {
super(msg);
message = msg;
initCause(null);
}
/**
* Constructs a CannotCompileException with an <code>Exception</code>
* representing the cause.
*
* @param e the cause.
*/
public CannotCompileException(Throwable e) {
super("by " + e.toString());
message = null;
initCause(e);
}
/**
* Constructs a CannotCompileException with a detailed message
* and an <code>Exception</code> representing the cause.
*
* @param msg the message.
* @param e the cause.
*/
public CannotCompileException(String msg, Throwable e) {
this(msg);
initCause(e);
}
/**
* Constructs a CannotCompileException with a
* <code>NotFoundException</code>.
*/
public CannotCompileException(NotFoundException e) {
this("cannot find " + e.getMessage(), e);
}
/**
* Constructs a CannotCompileException with an <code>CompileError</code>.
*/
public CannotCompileException(CompileError e) {
this("[source error] " + e.getMessage(), e);
}
/**
* Constructs a CannotCompileException
* with a <code>ClassNotFoundException</code>.
*/
public CannotCompileException(ClassNotFoundException e, String name) {
this("cannot find " + name, e);
}
/**
* Constructs a CannotCompileException with a ClassFormatError.
*/
public CannotCompileException(ClassFormatError e, String name) {
this("invalid class format: " + name, e);
}
}

97
fine-javassist/src/main/java/com/fr/third/javassist/ClassClassPath.java

@ -1,97 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.InputStream;
import java.net.URL;
/**
* A search-path for obtaining a class file
* by <code>getResourceAsStream()</code> in <code>java.lang.Class</code>.
*
* <p>Try adding a <code>ClassClassPath</code> when a program is running
* with a user-defined class loader and any class files are not found with
* the default <code>ClassPool</code>. For example,
*
* <ul><pre>
* ClassPool cp = ClassPool.getDefault();
* cp.insertClassPath(new ClassClassPath(this.getClass()));
* </pre></ul>
*
* This code snippet permanently adds a <code>ClassClassPath</code>
* to the default <code>ClassPool</code>. Note that the default
* <code>ClassPool</code> is a singleton. The added
* <code>ClassClassPath</code> uses a class object representing
* the class including the code snippet above.
*
* @see ClassPool#insertClassPath(ClassPath)
* @see ClassPool#appendClassPath(ClassPath)
* @see LoaderClassPath
*/
public class ClassClassPath implements ClassPath {
private Class thisClass;
/** Creates a search path.
*
* @param c the <code>Class</code> object used to obtain a class
* file. <code>getResourceAsStream()</code> is called on
* this object.
*/
public ClassClassPath(Class c) {
thisClass = c;
}
ClassClassPath() {
/* The value of thisClass was this.getClass() in early versions:
*
* thisClass = this.getClass();
*
* However, this made openClassfile() not search all the system
* class paths if javassist.jar is put in jre/lib/ext/
* (with JDK1.4).
*/
this(java.lang.Object.class);
}
/**
* Obtains a class file by <code>getResourceAsStream()</code>.
*/
public InputStream openClassfile(String classname) {
String jarname = "/" + classname.replace('.', '/') + ".class";
return thisClass.getResourceAsStream(jarname);
}
/**
* Obtains the URL of the specified class file.
*
* @return null if the class file could not be found.
*/
public URL find(String classname) {
String jarname = "/" + classname.replace('.', '/') + ".class";
return thisClass.getResource(jarname);
}
/**
* Does nothing.
*/
public void close() {
}
public String toString() {
return thisClass.getName() + ".class";
}
}

173
fine-javassist/src/main/java/com/fr/third/javassist/ClassMap.java

@ -1,173 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.Descriptor;
/**
* A hash table associating class names with different names.
*
* <p>This hashtable is used for replacing class names in a class
* definition or a method body. Define a subclass of this class
* if a more complex mapping algorithm is needed. For example,
*
* <ul><pre>class MyClassMap extends ClassMap {
* public Object get(Object jvmClassName) {
* String name = toJavaName((String)jvmClassName);
* if (name.startsWith("java."))
* return toJvmName("java2." + name.substring(5));
* else
* return super.get(jvmClassName);
* }
* }</pre></ul>
*
* <p>This subclass maps <code>java.lang.String</code> to
* <code>java2.lang.String</code>. Note that <code>get()</code>
* receives and returns the internal representation of a class name.
* For example, the internal representation of <code>java.lang.String</code>
* is <code>java/lang/String</code>.
*
* <p>Note that this is a map from <code>String</code> to <code>String</code>.
*
* @see #get(Object)
* @see CtClass#replaceClassName(ClassMap)
* @see CtNewMethod#copy(CtMethod,String,CtClass,ClassMap)
*/
public class ClassMap extends java.util.HashMap {
private ClassMap parent;
/**
* Constructs a hash table.
*/
public ClassMap() { parent = null; }
ClassMap(ClassMap map) { parent = map; }
/**
* Maps a class name to another name in this hashtable.
* The names are obtained with calling <code>Class.getName()</code>.
* This method translates the given class names into the
* internal form used in the JVM before putting it in
* the hashtable.
*
* @param oldname the original class name
* @param newname the substituted class name.
*/
public void put(CtClass oldname, CtClass newname) {
put(oldname.getName(), newname.getName());
}
/**
* Maps a class name to another name in this hashtable.
* If the hashtable contains another mapping from the same
* class name, the old mapping is replaced.
* This method translates the given class names into the
* internal form used in the JVM before putting it in
* the hashtable.
*
* <p>If <code>oldname</code> is identical to
* <code>newname</code>, then this method does not
* perform anything; it does not record the mapping from
* <code>oldname</code> to <code>newname</code>. See
* <code>fix</code> method.
*
* @param oldname the original class name.
* @param newname the substituted class name.
* @see #fix(String)
*/
public void put(String oldname, String newname) {
if (oldname == newname)
return;
String oldname2 = toJvmName(oldname);
String s = (String)get(oldname2);
if (s == null || !s.equals(oldname2))
super.put(oldname2, toJvmName(newname));
}
/**
* Is equivalent to <code>put()</code> except that
* the given mapping is not recorded into the hashtable
* if another mapping from <code>oldname</code> is
* already included.
*
* @param oldname the original class name.
* @param newname the substituted class name.
*/
public void putIfNone(String oldname, String newname) {
if (oldname == newname)
return;
String oldname2 = toJvmName(oldname);
String s = (String)get(oldname2);
if (s == null)
super.put(oldname2, toJvmName(newname));
}
protected final void put0(Object oldname, Object newname) {
super.put(oldname, newname);
}
/**
* Returns the class name to wihch the given <code>jvmClassName</code>
* is mapped. A subclass of this class should override this method.
*
* <p>This method receives and returns the internal representation of
* class name used in the JVM.
*
* @see #toJvmName(String)
* @see #toJavaName(String)
*/
public Object get(Object jvmClassName) {
Object found = super.get(jvmClassName);
if (found == null && parent != null)
return parent.get(jvmClassName);
else
return found;
}
/**
* Prevents a mapping from the specified class name to another name.
*/
public void fix(CtClass clazz) {
fix(clazz.getName());
}
/**
* Prevents a mapping from the specified class name to another name.
*/
public void fix(String name) {
String name2 = toJvmName(name);
super.put(name2, name2);
}
/**
* Converts a class name into the internal representation used in
* the JVM.
*/
public static String toJvmName(String classname) {
return Descriptor.toJvmName(classname);
}
/**
* Converts a class name from the internal representation used in
* the JVM to the normal one used in Java.
*/
public static String toJavaName(String classname) {
return Descriptor.toJavaName(classname);
}
}

68
fine-javassist/src/main/java/com/fr/third/javassist/ClassPath.java

@ -1,68 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.InputStream;
import java.net.URL;
/**
* <code>ClassPath</code> is an interface implemented by objects
* representing a class search path.
* <code>ClassPool</code> uses those objects for reading class files.
*
* <p>The users can define a class implementing this interface so that
* a class file is obtained from a non-standard source.
*
* @see ClassPool#insertClassPath(ClassPath)
* @see ClassPool#appendClassPath(ClassPath)
* @see ClassPool#removeClassPath(ClassPath)
*/
public interface ClassPath {
/**
* Opens a class file.
* This method may be called just to examine whether the class file
* exists as well as to read the contents of the file.
*
* <p>This method can return null if the specified class file is not
* found. If null is returned, the next search path is examined.
* However, if an error happens, this method must throw an exception
* so that the search will be terminated.
*
* <p>This method should not modify the contents of the class file.
*
* @param classname a fully-qualified class name
* @return the input stream for reading a class file
* @see Translator
*/
InputStream openClassfile(String classname) throws NotFoundException;
/**
* Returns the uniform resource locator (URL) of the class file
* with the specified name.
*
* @param classname a fully-qualified class name.
* @return null if the specified class file could not be found.
*/
URL find(String classname);
/**
* This method is invoked when the <code>ClassPath</code> object is
* detached from the search path. It will be an empty method in most of
* classes.
*/
void close();
}

1164
fine-javassist/src/main/java/com/fr/third/javassist/ClassPool.java

File diff suppressed because it is too large Load Diff

429
fine-javassist/src/main/java/com/fr/third/javassist/ClassPoolTail.java

@ -1,429 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.*;
import java.util.jar.*;
import java.net.MalformedURLException;
import java.net.URL;
final class ClassPathList {
ClassPathList next;
com.fr.third.javassist.ClassPath path;
ClassPathList(com.fr.third.javassist.ClassPath p, ClassPathList n) {
next = n;
path = p;
}
}
final class DirClassPath implements com.fr.third.javassist.ClassPath {
String directory;
DirClassPath(String dirName) {
directory = dirName;
}
public InputStream openClassfile(String classname) {
try {
char sep = File.separatorChar;
String filename = directory + sep
+ classname.replace('.', sep) + ".class";
return new FileInputStream(filename.toString());
}
catch (FileNotFoundException e) {}
catch (SecurityException e) {}
return null;
}
public URL find(String classname) {
char sep = File.separatorChar;
String filename = directory + sep
+ classname.replace('.', sep) + ".class";
File f = new File(filename);
if (f.exists())
try {
return f.getCanonicalFile().toURI().toURL();
}
catch (MalformedURLException e) {}
catch (IOException e) {}
return null;
}
public void close() {}
public String toString() {
return directory;
}
}
final class JarDirClassPath implements com.fr.third.javassist.ClassPath {
JarClassPath[] jars;
JarDirClassPath(String dirName) throws NotFoundException {
File[] files = new File(dirName).listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
name = name.toLowerCase();
return name.endsWith(".jar") || name.endsWith(".zip");
}
});
if (files != null) {
jars = new JarClassPath[files.length];
for (int i = 0; i < files.length; i++)
jars[i] = new JarClassPath(files[i].getPath());
}
}
public InputStream openClassfile(String classname) throws NotFoundException {
if (jars != null)
for (int i = 0; i < jars.length; i++) {
InputStream is = jars[i].openClassfile(classname);
if (is != null)
return is;
}
return null; // not found
}
public URL find(String classname) {
if (jars != null)
for (int i = 0; i < jars.length; i++) {
URL url = jars[i].find(classname);
if (url != null)
return url;
}
return null; // not found
}
public void close() {
if (jars != null)
for (int i = 0; i < jars.length; i++)
jars[i].close();
}
}
final class JarClassPath implements com.fr.third.javassist.ClassPath {
JarFile jarfile;
String jarfileURL;
JarClassPath(String pathname) throws NotFoundException {
try {
jarfile = new JarFile(pathname);
jarfileURL = new File(pathname).getCanonicalFile()
.toURI().toURL().toString();
return;
}
catch (IOException e) {}
throw new NotFoundException(pathname);
}
public InputStream openClassfile(String classname)
throws NotFoundException
{
try {
String jarname = classname.replace('.', '/') + ".class";
JarEntry je = jarfile.getJarEntry(jarname);
if (je != null)
return jarfile.getInputStream(je);
else
return null; // not found
}
catch (IOException e) {}
throw new NotFoundException("broken jar file?: "
+ jarfile.getName());
}
public URL find(String classname) {
String jarname = classname.replace('.', '/') + ".class";
JarEntry je = jarfile.getJarEntry(jarname);
if (je != null)
try {
return new URL("jar:" + jarfileURL + "!/" + jarname);
}
catch (MalformedURLException e) {}
return null; // not found
}
public void close() {
try {
jarfile.close();
jarfile = null;
}
catch (IOException e) {}
}
public String toString() {
return jarfile == null ? "<null>" : jarfile.toString();
}
}
final class ClassPoolTail {
protected ClassPathList pathList;
public ClassPoolTail() {
pathList = null;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[class path: ");
ClassPathList list = pathList;
while (list != null) {
buf.append(list.path.toString());
buf.append(File.pathSeparatorChar);
list = list.next;
}
buf.append(']');
return buf.toString();
}
public synchronized com.fr.third.javassist.ClassPath insertClassPath(com.fr.third.javassist.ClassPath cp) {
pathList = new ClassPathList(cp, pathList);
return cp;
}
public synchronized com.fr.third.javassist.ClassPath appendClassPath(com.fr.third.javassist.ClassPath cp) {
ClassPathList tail = new ClassPathList(cp, null);
ClassPathList list = pathList;
if (list == null)
pathList = tail;
else {
while (list.next != null)
list = list.next;
list.next = tail;
}
return cp;
}
public synchronized void removeClassPath(com.fr.third.javassist.ClassPath cp) {
ClassPathList list = pathList;
if (list != null)
if (list.path == cp)
pathList = list.next;
else {
while (list.next != null)
if (list.next.path == cp)
list.next = list.next.next;
else
list = list.next;
}
cp.close();
}
public com.fr.third.javassist.ClassPath appendSystemPath() {
return appendClassPath(new ClassClassPath());
}
public com.fr.third.javassist.ClassPath insertClassPath(String pathname)
throws NotFoundException
{
return insertClassPath(makePathObject(pathname));
}
public com.fr.third.javassist.ClassPath appendClassPath(String pathname)
throws NotFoundException
{
return appendClassPath(makePathObject(pathname));
}
private static ClassPath makePathObject(String pathname)
throws NotFoundException
{
String lower = pathname.toLowerCase();
if (lower.endsWith(".jar") || lower.endsWith(".zip"))
return new JarClassPath(pathname);
int len = pathname.length();
if (len > 2 && pathname.charAt(len - 1) == '*'
&& (pathname.charAt(len - 2) == '/'
|| pathname.charAt(len - 2) == File.separatorChar)) {
String dir = pathname.substring(0, len - 2);
return new JarDirClassPath(dir);
}
return new DirClassPath(pathname);
}
/**
* This method does not close the output stream.
*/
void writeClassfile(String classname, OutputStream out)
throws NotFoundException, IOException, CannotCompileException
{
InputStream fin = openClassfile(classname);
if (fin == null)
throw new NotFoundException(classname);
try {
copyStream(fin, out);
}
finally {
fin.close();
}
}
/*
-- faster version --
void checkClassName(String classname) throws NotFoundException {
if (find(classname) == null)
throw new NotFoundException(classname);
}
-- slower version --
void checkClassName(String classname) throws NotFoundException {
InputStream fin = openClassfile(classname);
try {
fin.close();
}
catch (IOException e) {}
}
*/
/**
* Opens the class file for the class specified by
* <code>classname</code>.
*
* @param classname a fully-qualified class name
* @return null if the file has not been found.
* @throws NotFoundException if any error is reported by ClassPath.
*/
InputStream openClassfile(String classname)
throws NotFoundException
{
ClassPathList list = pathList;
InputStream ins = null;
NotFoundException error = null;
while (list != null) {
try {
ins = list.path.openClassfile(classname);
}
catch (NotFoundException e) {
if (error == null)
error = e;
}
if (ins == null)
list = list.next;
else
return ins;
}
if (error != null)
throw error;
else
return null; // not found
}
/**
* Searches the class path to obtain the URL of the class file
* specified by classname. It is also used to determine whether
* the class file exists.
*
* @param classname a fully-qualified class name.
* @return null if the class file could not be found.
*/
public URL find(String classname) {
ClassPathList list = pathList;
URL url = null;
while (list != null) {
url = list.path.find(classname);
if (url == null)
list = list.next;
else
return url;
}
return null;
}
/**
* Reads from an input stream until it reaches the end.
*
* @return the contents of that input stream
*/
public static byte[] readStream(InputStream fin) throws IOException {
byte[][] bufs = new byte[8][];
int bufsize = 4096;
for (int i = 0; i < 8; ++i) {
bufs[i] = new byte[bufsize];
int size = 0;
int len = 0;
do {
len = fin.read(bufs[i], size, bufsize - size);
if (len >= 0)
size += len;
else {
byte[] result = new byte[bufsize - 4096 + size];
int s = 0;
for (int j = 0; j < i; ++j) {
System.arraycopy(bufs[j], 0, result, s, s + 4096);
s = s + s + 4096;
}
System.arraycopy(bufs[i], 0, result, s, size);
return result;
}
} while (size < bufsize);
bufsize *= 2;
}
throw new IOException("too much data");
}
/**
* Reads from an input stream and write to an output stream
* until it reaches the end. This method does not close the
* streams.
*/
public static void copyStream(InputStream fin, OutputStream fout)
throws IOException
{
int bufsize = 4096;
byte[] buf = null;
for (int i = 0; i < 64; ++i) {
if (i < 8) {
bufsize *= 2;
buf = new byte[bufsize];
}
int size = 0;
int len = 0;
do {
len = fin.read(buf, size, bufsize - size);
if (len >= 0)
size += len;
else {
fout.write(buf, 0, size);
return;
}
} while (size < bufsize);
fout.write(buf);
}
throw new IOException("too much data");
}
}

809
fine-javassist/src/main/java/com/fr/third/javassist/CodeConverter.java

@ -1,809 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.CodeAttribute;
import com.fr.third.javassist.convert.TransformCall;
import com.fr.third.javassist.expr.ExprEditor;
/**
* Simple translator of method bodies
* (also see the <code>javassist.expr</code> package).
*
* <p>Instances of this class specifies how to instrument of the
* bytecodes representing a method body. They are passed to
* <code>CtClass.instrument()</code> or
* <code>CtMethod.instrument()</code> as a parameter.
*
* <p>Example:
* <ul><pre>
* ClassPool cp = ClassPool.getDefault();
* CtClass point = cp.get("Point");
* CtClass singleton = cp.get("Singleton");
* CtClass client = cp.get("Client");
* CodeConverter conv = new CodeConverter();
* conv.replaceNew(point, singleton, "makePoint");
* client.instrument(conv);
* </pre></ul>
*
* <p>This program substitutes "<code>Singleton.makePoint()</code>"
* for all occurrences of "<code>new Point()</code>"
* appearing in methods declared in a <code>Client</code> class.
*
* @see CtClass#instrument(CodeConverter)
* @see CtMethod#instrument(CodeConverter)
* @see ExprEditor
*/
public class CodeConverter {
protected com.fr.third.javassist.convert.Transformer transformers = null;
/**
* Modify a method body so that instantiation of the specified class
* is replaced with a call to the specified static method. For example,
* <code>replaceNew(ctPoint, ctSingleton, "createPoint")</code>
* (where <code>ctPoint</code> and <code>ctSingleton</code> are
* compile-time classes for class <code>Point</code> and class
* <code>Singleton</code>, respectively)
* replaces all occurrences of:
*
* <ul><code>new Point(x, y)</code></ul>
*
* in the method body with:
*
* <ul><code>Singleton.createPoint(x, y)</code></ul>
*
* <p>This enables to intercept instantiation of <code>Point</code>
* and change the samentics. For example, the following
* <code>createPoint()</code> implements the singleton pattern:
*
* <ul><pre>public static Point createPoint(int x, int y) {
* if (aPoint == null)
* aPoint = new Point(x, y);
* return aPoint;
* }
* </pre></ul>
*
* <p>The static method call substituted for the original <code>new</code>
* expression must be
* able to receive the same set of parameters as the original
* constructor. If there are multiple constructors with different
* parameter types, then there must be multiple static methods
* with the same name but different parameter types.
*
* <p>The return type of the substituted static method must be
* the exactly same as the type of the instantiated class specified by
* <code>newClass</code>.
*
* @param newClass the instantiated class.
* @param calledClass the class in which the static method is
* declared.
* @param calledMethod the name of the static method.
*/
public void replaceNew(CtClass newClass,
CtClass calledClass, String calledMethod) {
transformers = new com.fr.third.javassist.convert.TransformNew(transformers, newClass.getName(),
calledClass.getName(), calledMethod);
}
/**
* Modify a method body so that instantiation of the class
* specified by <code>oldClass</code>
* is replaced with instantiation of another class <code>newClass</code>.
* For example,
* <code>replaceNew(ctPoint, ctPoint2)</code>
* (where <code>ctPoint</code> and <code>ctPoint2</code> are
* compile-time classes for class <code>Point</code> and class
* <code>Point2</code>, respectively)
* replaces all occurrences of:
*
* <ul><code>new Point(x, y)</code></ul>
*
* in the method body with:
*
* <ul><code>new Point2(x, y)</code></ul>
*
* <p>Note that <code>Point2</code> must be type-compatible with <code>Point</code>.
* It must have the same set of methods, fields, and constructors as the
* replaced class.
*/
public void replaceNew(CtClass oldClass, CtClass newClass) {
transformers = new com.fr.third.javassist.convert.TransformNewClass(transformers, oldClass.getName(),
newClass.getName());
}
/**
* Modify a method body so that field read/write expressions access
* a different field from the original one.
*
* <p>Note that this method changes only the filed name and the class
* declaring the field; the type of the target object does not change.
* Therefore, the substituted field must be declared in the same class
* or a superclass of the original class.
*
* <p>Also, <code>clazz</code> and <code>newClass</code> must specify
* the class directly declaring the field. They must not specify
* a subclass of that class.
*
* @param field the originally accessed field.
* @param newClass the class declaring the substituted field.
* @param newFieldname the name of the substituted field.
*/
public void redirectFieldAccess(CtField field,
CtClass newClass, String newFieldname) {
transformers = new com.fr.third.javassist.convert.TransformFieldAccess(transformers, field,
newClass.getName(),
newFieldname);
}
/**
* Modify a method body so that an expression reading the specified
* field is replaced with a call to the specified <i>static</i> method.
* This static method receives the target object of the original
* read expression as a parameter. It must return a value of
* the same type as the field.
*
* <p>For example, the program below
*
* <ul><pre>Point p = new Point();
* int newX = p.x + 3;</pre></ul>
*
* <p>can be translated into:
*
* <ul><pre>Point p = new Point();
* int newX = Accessor.readX(p) + 3;</pre></ul>
*
* <p>where
*
* <ul><pre>public class Accessor {
* public static int readX(Object target) { ... }
* }</pre></ul>
*
* <p>The type of the parameter of <code>readX()</code> must
* be <code>java.lang.Object</code> independently of the actual
* type of <code>target</code>. The return type must be the same
* as the field type.
*
* @param field the field.
* @param calledClass the class in which the static method is
* declared.
* @param calledMethod the name of the static method.
*/
public void replaceFieldRead(CtField field,
CtClass calledClass, String calledMethod) {
transformers = new com.fr.third.javassist.convert.TransformReadField(transformers, field,
calledClass.getName(),
calledMethod);
}
/**
* Modify a method body so that an expression writing the specified
* field is replaced with a call to the specified static method.
* This static method receives two parameters: the target object of
* the original
* write expression and the assigned value. The return type of the
* static method is <code>void</code>.
*
* <p>For example, the program below
*
* <ul><pre>Point p = new Point();
* p.x = 3;</pre></ul>
*
* <p>can be translated into:
*
* <ul><pre>Point p = new Point();
* Accessor.writeX(3);</pre></ul>
*
* <p>where
*
* <ul><pre>public class Accessor {
* public static void writeX(Object target, int value) { ... }
* }</pre></ul>
*
* <p>The type of the first parameter of <code>writeX()</code> must
* be <code>java.lang.Object</code> independently of the actual
* type of <code>target</code>. The type of the second parameter
* is the same as the field type.
*
* @param field the field.
* @param calledClass the class in which the static method is
* declared.
* @param calledMethod the name of the static method.
*/
public void replaceFieldWrite(CtField field,
CtClass calledClass, String calledMethod) {
transformers = new com.fr.third.javassist.convert.TransformWriteField(transformers, field,
calledClass.getName(),
calledMethod);
}
/**
* Modify a method body, so that ALL accesses to an array are replaced with
* calls to static methods within another class. In the case of reading an
* element from the array, this is replaced with a call to a static method with
* the array and the index as arguments, the return value is the value read from
* the array. If writing to an array, this is replaced with a call to a static
* method with the array, index and new value as parameters, the return value of
* the static method is <code>void</code>.
*
* <p>The <code>calledClass</code> parameter is the class containing the static methods to be used
* for array replacement. The <code>names</code> parameter points to an implementation of
* <code>ArrayAccessReplacementMethodNames</code> which specifies the names of the method to be
* used for access for each type of array. For example reading from an <code>int[]</code> will
* require a different method than if writing to an <code>int[]</code>, and writing to a <code>long[]</code>
* will require a different method than if writing to a <code>byte[]</code>. If the implementation
* of <code>ArrayAccessReplacementMethodNames</code> does not contain the name for access for a
* type of array, that access is not replaced.
*
* <p>A default implementation of <code>ArrayAccessReplacementMethodNames</code> called
* <code>DefaultArrayAccessReplacementMethodNames</code> has been provided and is what is used in the
* following example. This also assumes that <code>'foo.ArrayAdvisor'</code> is the name of the
* <code>CtClass</code> passed in.
*
* <p>If we have the following class:
* <pre>class POJO{
* int[] ints = new int[]{1, 2, 3, 4, 5};
* long[] longs = new int[]{10, 20, 30};
* Object objects = new Object[]{true, false};
* Integer[] integers = new Integer[]{new Integer(10)};
* }
* </pre>
* and this is accessed as:
* <pre>POJO p = new POJO();
*
* //Write to int array
* p.ints[2] = 7;
*
* //Read from int array
* int i = p.ints[2];
*
* //Write to long array
* p.longs[2] = 1000L;
*
* //Read from long array
* long l = p.longs[2];
*
* //Write to Object array
* p.objects[2] = "Hello";
*
* //Read from Object array
* Object o = p.objects[2];
*
* //Write to Integer array
* Integer integer = new Integer(5);
* p.integers[0] = integer;
*
* //Read from Object array
* integer = p.integers[0];
* </pre>
*
* Following instrumentation we will have
* <pre>POJO p = new POJO();
*
* //Write to int array
* ArrayAdvisor.arrayWriteInt(p.ints, 2, 7);
*
* //Read from int array
* int i = ArrayAdvisor.arrayReadInt(p.ints, 2);
*
* //Write to long array
* ArrayAdvisor.arrayWriteLong(p.longs, 2, 1000L);
*
* //Read from long array
* long l = ArrayAdvisor.arrayReadLong(p.longs, 2);
*
* //Write to Object array
* ArrayAdvisor.arrayWriteObject(p.objects, 2, "Hello");
*
* //Read from Object array
* Object o = ArrayAdvisor.arrayReadObject(p.objects, 2);
*
* //Write to Integer array
* Integer integer = new Integer(5);
* ArrayAdvisor.arrayWriteObject(p.integers, 0, integer);
*
* //Read from Object array
* integer = ArrayAdvisor.arrayWriteObject(p.integers, 0);
* </pre>
*
* @see DefaultArrayAccessReplacementMethodNames
*
* @param calledClass the class containing the static methods.
* @param names contains the names of the methods to replace
* the different kinds of array access with.
*/
public void replaceArrayAccess(CtClass calledClass, ArrayAccessReplacementMethodNames names)
throws NotFoundException
{
transformers = new com.fr.third.javassist.convert.TransformAccessArrayField(transformers, calledClass.getName(), names);
}
/**
* Modify method invocations in a method body so that a different
* method will be invoked.
*
* <p>Note that the target object, the parameters, or
* the type of invocation
* (static method call, interface call, or private method call)
* are not modified. Only the method name is changed. The substituted
* method must have the same signature that the original one has.
* If the original method is a static method, the substituted method
* must be static.
*
* @param origMethod original method
* @param substMethod substituted method
*/
public void redirectMethodCall(CtMethod origMethod,
CtMethod substMethod)
throws com.fr.third.javassist.CannotCompileException
{
String d1 = origMethod.getMethodInfo2().getDescriptor();
String d2 = substMethod.getMethodInfo2().getDescriptor();
if (!d1.equals(d2))
throw new com.fr.third.javassist.CannotCompileException("signature mismatch: "
+ substMethod.getLongName());
int mod1 = origMethod.getModifiers();
int mod2 = substMethod.getModifiers();
if (Modifier.isStatic(mod1) != Modifier.isStatic(mod2)
|| (Modifier.isPrivate(mod1) && !Modifier.isPrivate(mod2))
|| origMethod.getDeclaringClass().isInterface()
!= substMethod.getDeclaringClass().isInterface())
throw new com.fr.third.javassist.CannotCompileException("invoke-type mismatch "
+ substMethod.getLongName());
transformers = new com.fr.third.javassist.convert.TransformCall(transformers, origMethod,
substMethod);
}
/**
* Correct invocations to a method that has been renamed.
* If a method is renamed, calls to that method must be also
* modified so that the method with the new name will be called.
*
* <p>The method must be declared in the same class before and
* after it is renamed.
*
* <p>Note that the target object, the parameters, or
* the type of invocation
* (static method call, interface call, or private method call)
* are not modified. Only the method name is changed.
*
* @param oldMethodName the old name of the method.
* @param newMethod the method with the new name.
* @see CtMethod#setName(String)
*/
public void redirectMethodCall(String oldMethodName,
CtMethod newMethod)
throws com.fr.third.javassist.CannotCompileException
{
transformers
= new TransformCall(transformers, oldMethodName, newMethod);
}
/**
* Insert a call to another method before an existing method call.
* That "before" method must be static. The return type must be
* <code>void</code>. As parameters, the before method receives
* the target object and all the parameters to the originally invoked
* method. For example, if the originally invoked method is
* <code>move()</code>:
*
* <ul><pre>class Point {
* Point move(int x, int y) { ... }
* }</pre></ul>
*
* <p>Then the before method must be something like this:
*
* <ul><pre>class Verbose {
* static void print(Point target, int x, int y) { ... }
* }</pre></ul>
*
* <p>The <code>CodeConverter</code> would translate bytecode
* equivalent to:
*
* <ul><pre>Point p2 = p.move(x + y, 0);</pre></ul>
*
* <p>into the bytecode equivalent to:
*
* <ul><pre>int tmp1 = x + y;
* int tmp2 = 0;
* Verbose.print(p, tmp1, tmp2);
* Point p2 = p.move(tmp1, tmp2);</pre></ul>
*
* @param origMethod the method originally invoked.
* @param beforeMethod the method invoked before
* <code>origMethod</code>.
*/
public void insertBeforeMethod(CtMethod origMethod,
CtMethod beforeMethod)
throws com.fr.third.javassist.CannotCompileException
{
try {
transformers = new com.fr.third.javassist.convert.TransformBefore(transformers, origMethod,
beforeMethod);
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
/**
* Inserts a call to another method after an existing method call.
* That "after" method must be static. The return type must be
* <code>void</code>. As parameters, the after method receives
* the target object and all the parameters to the originally invoked
* method. For example, if the originally invoked method is
* <code>move()</code>:
*
* <ul><pre>class Point {
* Point move(int x, int y) { ... }
* }</pre></ul>
*
* <p>Then the after method must be something like this:
*
* <ul><pre>class Verbose {
* static void print(Point target, int x, int y) { ... }
* }</pre></ul>
*
* <p>The <code>CodeConverter</code> would translate bytecode
* equivalent to:
*
* <ul><pre>Point p2 = p.move(x + y, 0);</pre></ul>
*
* <p>into the bytecode equivalent to:
*
* <ul><pre>int tmp1 = x + y;
* int tmp2 = 0;
* Point p2 = p.move(tmp1, tmp2);
* Verbose.print(p, tmp1, tmp2);</pre></ul>
*
* @param origMethod the method originally invoked.
* @param afterMethod the method invoked after
* <code>origMethod</code>.
*/
public void insertAfterMethod(CtMethod origMethod,
CtMethod afterMethod)
throws com.fr.third.javassist.CannotCompileException
{
try {
transformers = new com.fr.third.javassist.convert.TransformAfter(transformers, origMethod,
afterMethod);
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
/**
* Performs code conversion.
*/
protected void doit(CtClass clazz, com.fr.third.javassist.bytecode.MethodInfo minfo, com.fr.third.javassist.bytecode.ConstPool cp)
throws com.fr.third.javassist.CannotCompileException
{
com.fr.third.javassist.convert.Transformer t;
CodeAttribute codeAttr = minfo.getCodeAttribute();
if (codeAttr == null || transformers == null)
return;
for (t = transformers; t != null; t = t.getNext())
t.initialize(cp, clazz, minfo);
com.fr.third.javassist.bytecode.CodeIterator iterator = codeAttr.iterator();
while (iterator.hasNext()) {
try {
int pos = iterator.next();
for (t = transformers; t != null; t = t.getNext())
pos = t.transform(clazz, pos, iterator, cp);
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
int locals = 0;
int stack = 0;
for (t = transformers; t != null; t = t.getNext()) {
int s = t.extraLocals();
if (s > locals)
locals = s;
s = t.extraStack();
if (s > stack)
stack = s;
}
for (t = transformers; t != null; t = t.getNext())
t.clean();
if (locals > 0)
codeAttr.setMaxLocals(codeAttr.getMaxLocals() + locals);
if (stack > 0)
codeAttr.setMaxStack(codeAttr.getMaxStack() + stack);
try {
minfo.rebuildStackMapIf6(clazz.getClassPool(),
clazz.getClassFile2());
}
catch (com.fr.third.javassist.bytecode.BadBytecode b) {
throw new CannotCompileException(b.getMessage(), b);
}
}
/**
* Interface containing the method names to be used
* as array access replacements.
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @version $Revision: 1.16 $
*/
public interface ArrayAccessReplacementMethodNames
{
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)B</code> to replace reading from a byte[].
*/
String byteOrBooleanRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;IB)V</code> to replace writing to a byte[].
*/
String byteOrBooleanWrite();
/**
* @return the name of a static method with the signature
* <code>(Ljava/lang/Object;I)C</code> to replace reading from a char[].
*/
String charRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;IC)V</code> to replace writing to a byte[].
*/
String charWrite();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)D</code> to replace reading from a double[].
*/
String doubleRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;ID)V</code> to replace writing to a double[].
*/
String doubleWrite();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)F</code> to replace reading from a float[].
*/
String floatRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;IF)V</code> to replace writing to a float[].
*/
String floatWrite();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)I</code> to replace reading from a int[].
*/
String intRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;II)V</code> to replace writing to a int[].
*/
String intWrite();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)J</code> to replace reading from a long[].
*/
String longRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;IJ)V</code> to replace writing to a long[].
*/
String longWrite();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)Ljava/lang/Object;</code>
* to replace reading from a Object[] (or any subclass of object).
*/
String objectRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;ILjava/lang/Object;)V</code>
* to replace writing to a Object[] (or any subclass of object).
*/
String objectWrite();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;I)S</code> to replace reading from a short[].
*/
String shortRead();
/**
* Returns the name of a static method with the signature
* <code>(Ljava/lang/Object;IS)V</code> to replace writing to a short[].
*/
String shortWrite();
}
/**
* Default implementation of the <code>ArrayAccessReplacementMethodNames</code>
* interface giving default values for method names to be used for replacing
* accesses to array elements.
*
* @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
* @version $Revision: 1.16 $
*/
public static class DefaultArrayAccessReplacementMethodNames
implements ArrayAccessReplacementMethodNames
{
/**
* Returns "arrayReadByteOrBoolean" as the name of the static method with the signature
* (Ljava/lang/Object;I)B to replace reading from a byte[].
*/
public String byteOrBooleanRead()
{
return "arrayReadByteOrBoolean";
}
/**
* Returns "arrayWriteByteOrBoolean" as the name of the static method with the signature
* (Ljava/lang/Object;IB)V to replace writing to a byte[].
*/
public String byteOrBooleanWrite()
{
return "arrayWriteByteOrBoolean";
}
/**
* Returns "arrayReadChar" as the name of the static method with the signature
* (Ljava/lang/Object;I)C to replace reading from a char[].
*/
public String charRead()
{
return "arrayReadChar";
}
/**
* Returns "arrayWriteChar" as the name of the static method with the signature
* (Ljava/lang/Object;IC)V to replace writing to a byte[].
*/
public String charWrite()
{
return "arrayWriteChar";
}
/**
* Returns "arrayReadDouble" as the name of the static method with the signature
* (Ljava/lang/Object;I)D to replace reading from a double[].
*/
public String doubleRead()
{
return "arrayReadDouble";
}
/**
* Returns "arrayWriteDouble" as the name of the static method with the signature
* (Ljava/lang/Object;ID)V to replace writing to a double[].
*/
public String doubleWrite()
{
return "arrayWriteDouble";
}
/**
* Returns "arrayReadFloat" as the name of the static method with the signature
* (Ljava/lang/Object;I)F to replace reading from a float[].
*/
public String floatRead()
{
return "arrayReadFloat";
}
/**
* Returns "arrayWriteFloat" as the name of the static method with the signature
* (Ljava/lang/Object;IF)V to replace writing to a float[].
*/
public String floatWrite()
{
return "arrayWriteFloat";
}
/**
* Returns "arrayReadInt" as the name of the static method with the signature
* (Ljava/lang/Object;I)I to replace reading from a int[].
*/
public String intRead()
{
return "arrayReadInt";
}
/**
* Returns "arrayWriteInt" as the name of the static method with the signature
* (Ljava/lang/Object;II)V to replace writing to a int[].
*/
public String intWrite()
{
return "arrayWriteInt";
}
/**
* Returns "arrayReadLong" as the name of the static method with the signature
* (Ljava/lang/Object;I)J to replace reading from a long[].
*/
public String longRead()
{
return "arrayReadLong";
}
/**
* Returns "arrayWriteLong" as the name of the static method with the signature
* (Ljava/lang/Object;IJ)V to replace writing to a long[].
*/
public String longWrite()
{
return "arrayWriteLong";
}
/**
* Returns "arrayReadObject" as the name of the static method with the signature
* (Ljava/lang/Object;I)Ljava/lang/Object; to replace reading from a Object[] (or any subclass of object).
*/
public String objectRead()
{
return "arrayReadObject";
}
/**
* Returns "arrayWriteObject" as the name of the static method with the signature
* (Ljava/lang/Object;ILjava/lang/Object;)V to replace writing to a Object[] (or any subclass of object).
*/
public String objectWrite()
{
return "arrayWriteObject";
}
/**
* Returns "arrayReadShort" as the name of the static method with the signature
* (Ljava/lang/Object;I)S to replace reading from a short[].
*/
public String shortRead()
{
return "arrayReadShort";
}
/**
* Returns "arrayWriteShort" as the name of the static method with the signature
* (Ljava/lang/Object;IS)V to replace writing to a short[].
*/
public String shortWrite()
{
return "arrayWriteShort";
}
}
}

113
fine-javassist/src/main/java/com/fr/third/javassist/CtArray.java

@ -1,113 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
/**
* Array types.
*/
final class CtArray extends CtClass {
protected com.fr.third.javassist.ClassPool pool;
// the name of array type ends with "[]".
CtArray(String name, com.fr.third.javassist.ClassPool cp) {
super(name);
pool = cp;
}
public ClassPool getClassPool() {
return pool;
}
public boolean isArray() {
return true;
}
private CtClass[] interfaces = null;
public int getModifiers() {
int mod = Modifier.FINAL;
try {
mod |= getComponentType().getModifiers()
& (Modifier.PROTECTED | Modifier.PUBLIC | Modifier.PRIVATE);
}
catch (NotFoundException e) {}
return mod;
}
public CtClass[] getInterfaces() throws NotFoundException {
if (interfaces == null) {
Class[] intfs = Object[].class.getInterfaces();
// java.lang.Cloneable and java.io.Serializable.
// If the JVM is CLDC, intfs is empty.
interfaces = new CtClass[intfs.length];
for (int i = 0; i < intfs.length; i++)
interfaces[i] = pool.get(intfs[i].getName());
}
return interfaces;
}
public boolean subtypeOf(CtClass clazz) throws NotFoundException {
if (super.subtypeOf(clazz))
return true;
String cname = clazz.getName();
if (cname.equals(javaLangObject))
return true;
CtClass[] intfs = getInterfaces();
for (int i = 0; i < intfs.length; i++)
if (intfs[i].subtypeOf(clazz))
return true;
return clazz.isArray()
&& getComponentType().subtypeOf(clazz.getComponentType());
}
public CtClass getComponentType() throws NotFoundException {
String name = getName();
return pool.get(name.substring(0, name.length() - 2));
}
public CtClass getSuperclass() throws NotFoundException {
return pool.get(javaLangObject);
}
public CtMethod[] getMethods() {
try {
return getSuperclass().getMethods();
}
catch (NotFoundException e) {
return super.getMethods();
}
}
public CtMethod getMethod(String name, String desc)
throws NotFoundException
{
return getSuperclass().getMethod(name, desc);
}
public CtConstructor[] getConstructors() {
try {
return getSuperclass().getConstructors();
}
catch (NotFoundException e) {
return super.getConstructors();
}
}
}

1215
fine-javassist/src/main/java/com/fr/third/javassist/CtBehavior.java

File diff suppressed because it is too large Load Diff

1558
fine-javassist/src/main/java/com/fr/third/javassist/CtClass.java

File diff suppressed because it is too large Load Diff

1722
fine-javassist/src/main/java/com/fr/third/javassist/CtClassType.java

File diff suppressed because it is too large Load Diff

403
fine-javassist/src/main/java/com/fr/third/javassist/CtConstructor.java

@ -1,403 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.CodeAttribute;
import com.fr.third.javassist.compiler.Javac;
import com.fr.third.javassist.compiler.CompileError;
/**
* An instance of CtConstructor represents a constructor.
* It may represent a static constructor
* (class initializer). To distinguish a constructor and a class
* initializer, call <code>isClassInitializer()</code>.
*
* <p>See the super class <code>CtBehavior</code> as well since
* a number of useful methods are in <code>CtBehavior</code>.
*
* @see com.fr.third.javassist.CtClass#getDeclaredConstructors()
* @see com.fr.third.javassist.CtClass#getClassInitializer()
* @see CtNewConstructor
*/
public final class CtConstructor extends CtBehavior {
protected CtConstructor(com.fr.third.javassist.bytecode.MethodInfo minfo, com.fr.third.javassist.CtClass declaring) {
super(declaring, minfo);
}
/**
* Creates a constructor with no constructor body.
* The created constructor
* must be added to a class with <code>CtClass.addConstructor()</code>.
*
* <p>The created constructor does not include a constructor body,
* which must be specified with <code>setBody()</code>.
*
* @param declaring the class to which the created method is added.
* @param parameters a list of the parameter types
*
* @see com.fr.third.javassist.CtClass#addConstructor(CtConstructor)
* @see CtConstructor#setBody(String)
* @see CtConstructor#setBody(CtConstructor, com.fr.third.javassist.ClassMap)
*/
public CtConstructor(com.fr.third.javassist.CtClass[] parameters, com.fr.third.javassist.CtClass declaring) {
this((com.fr.third.javassist.bytecode.MethodInfo)null, declaring);
com.fr.third.javassist.bytecode.ConstPool cp = declaring.getClassFile2().getConstPool();
String desc = com.fr.third.javassist.bytecode.Descriptor.ofConstructor(parameters);
methodInfo = new com.fr.third.javassist.bytecode.MethodInfo(cp, "<init>", desc);
setModifiers(Modifier.PUBLIC);
}
/**
* Creates a copy of a <code>CtConstructor</code> object.
* The created constructor must be
* added to a class with <code>CtClass.addConstructor()</code>.
*
* <p>All occurrences of class names in the created constructor
* are replaced with names specified by
* <code>map</code> if <code>map</code> is not <code>null</code>.
*
* <p>By default, all the occurrences of the names of the class
* declaring <code>src</code> and the superclass are replaced
* with the name of the class and the superclass that
* the created constructor is added to.
* This is done whichever <code>map</code> is null or not.
* To prevent this replacement, call <code>ClassMap.fix()</code>
* or <code>put()</code> to explicitly specify replacement.
*
* <p><b>Note:</b> if the <code>.class</code> notation (for example,
* <code>String.class</code>) is included in an expression, the
* Javac compiler may produce a helper method.
* Since this constructor never
* copies this helper method, the programmers have the responsiblity of
* copying it. Otherwise, use <code>Class.forName()</code> in the
* expression.
*
* @param src the source method.
* @param declaring the class to which the created method is added.
* @param map the hashtable associating original class names
* with substituted names.
* It can be <code>null</code>.
*
* @see com.fr.third.javassist.CtClass#addConstructor(CtConstructor)
* @see com.fr.third.javassist.ClassMap#fix(String)
*/
public CtConstructor(CtConstructor src, com.fr.third.javassist.CtClass declaring, com.fr.third.javassist.ClassMap map)
throws com.fr.third.javassist.CannotCompileException
{
this((com.fr.third.javassist.bytecode.MethodInfo)null, declaring);
copy(src, true, map);
}
/**
* Returns true if this object represents a constructor.
*/
public boolean isConstructor() {
return methodInfo.isConstructor();
}
/**
* Returns true if this object represents a static initializer.
*/
public boolean isClassInitializer() {
return methodInfo.isStaticInitializer();
}
/**
* Returns the constructor name followed by parameter types
* such as <code>javassist.CtConstructor(CtClass[],CtClass)</code>.
*
* @since 3.5
*/
public String getLongName() {
return getDeclaringClass().getName()
+ (isConstructor() ? com.fr.third.javassist.bytecode.Descriptor.toString(getSignature())
: ("." + com.fr.third.javassist.bytecode.MethodInfo.nameClinit + "()"));
}
/**
* Obtains the name of this constructor.
* It is the same as the simple name of the class declaring this
* constructor. If this object represents a class initializer,
* then this method returns <code>"&lt;clinit&gt;"</code>.
*/
public String getName() {
if (methodInfo.isStaticInitializer())
return com.fr.third.javassist.bytecode.MethodInfo.nameClinit;
else
return declaringClass.getSimpleName();
}
/**
* Returns true if the constructor (or static initializer)
* is the default one. This method returns true if the constructor
* takes some arguments but it does not perform anything except
* calling <code>super()</code> (the no-argument constructor of
* the super class).
*/
public boolean isEmpty() {
com.fr.third.javassist.bytecode.CodeAttribute ca = getMethodInfo2().getCodeAttribute();
if (ca == null)
return false; // native or abstract??
// they are not allowed, though.
com.fr.third.javassist.bytecode.ConstPool cp = ca.getConstPool();
com.fr.third.javassist.bytecode.CodeIterator it = ca.iterator();
try {
int pos, desc;
int op0 = it.byteAt(it.next());
return op0 == com.fr.third.javassist.bytecode.Opcode.RETURN // empty static initializer
|| (op0 == com.fr.third.javassist.bytecode.Opcode.ALOAD_0
&& it.byteAt(pos = it.next()) == com.fr.third.javassist.bytecode.Opcode.INVOKESPECIAL
&& (desc = cp.isConstructor(getSuperclassName(),
it.u16bitAt(pos + 1))) != 0
&& "()V".equals(cp.getUtf8Info(desc))
&& it.byteAt(it.next()) == com.fr.third.javassist.bytecode.Opcode.RETURN
&& !it.hasNext());
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {}
return false;
}
private String getSuperclassName() {
com.fr.third.javassist.bytecode.ClassFile cf = declaringClass.getClassFile2();
return cf.getSuperclass();
}
/**
* Returns true if this constructor calls a constructor
* of the super class. This method returns false if it
* calls another constructor of this class by <code>this()</code>.
*/
public boolean callsSuper() throws com.fr.third.javassist.CannotCompileException {
com.fr.third.javassist.bytecode.CodeAttribute codeAttr = methodInfo.getCodeAttribute();
if (codeAttr != null) {
com.fr.third.javassist.bytecode.CodeIterator it = codeAttr.iterator();
try {
int index = it.skipSuperConstructor();
return index >= 0;
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
return false;
}
/**
* Sets a constructor body.
*
* @param src the source code representing the constructor body.
* It must be a single statement or block.
* If it is <code>null</code>, the substituted
* constructor body does nothing except calling
* <code>super()</code>.
*/
public void setBody(String src) throws com.fr.third.javassist.CannotCompileException {
if (src == null)
if (isClassInitializer())
src = ";";
else
src = "super();";
super.setBody(src);
}
/**
* Copies a constructor body from another constructor.
*
* <p>All occurrences of the class names in the copied body
* are replaced with the names specified by
* <code>map</code> if <code>map</code> is not <code>null</code>.
*
* @param src the method that the body is copied from.
* @param map the hashtable associating original class names
* with substituted names.
* It can be <code>null</code>.
*/
public void setBody(CtConstructor src, com.fr.third.javassist.ClassMap map)
throws com.fr.third.javassist.CannotCompileException
{
setBody0(src.declaringClass, src.methodInfo,
declaringClass, methodInfo, map);
}
/**
* Inserts bytecode just after another constructor in the super class
* or this class is called.
* It does not work if this object represents a class initializer.
*
* @param src the source code representing the inserted bytecode.
* It must be a single statement or block.
*/
public void insertBeforeBody(String src) throws com.fr.third.javassist.CannotCompileException {
com.fr.third.javassist.CtClass cc = declaringClass;
cc.checkModify();
if (isClassInitializer())
throw new com.fr.third.javassist.CannotCompileException("class initializer");
com.fr.third.javassist.bytecode.CodeAttribute ca = methodInfo.getCodeAttribute();
com.fr.third.javassist.bytecode.CodeIterator iterator = ca.iterator();
com.fr.third.javassist.bytecode.Bytecode b = new com.fr.third.javassist.bytecode.Bytecode(methodInfo.getConstPool(),
ca.getMaxStack(), ca.getMaxLocals());
b.setStackDepth(ca.getMaxStack());
Javac jv = new Javac(b, cc);
try {
jv.recordParams(getParameterTypes(), false);
jv.compileStmnt(src);
ca.setMaxStack(b.getMaxStack());
ca.setMaxLocals(b.getMaxLocals());
iterator.skipConstructor();
int pos = iterator.insertEx(b.get());
iterator.insert(b.getExceptionTable(), pos);
methodInfo.rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
catch (CompileError e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
/* This method is called by addCatch() in CtBehavior.
* super() and this() must not be in a try statement.
*/
int getStartPosOfBody(com.fr.third.javassist.bytecode.CodeAttribute ca) throws com.fr.third.javassist.CannotCompileException {
com.fr.third.javassist.bytecode.CodeIterator ci = ca.iterator();
try {
ci.skipConstructor();
return ci.next();
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
/**
* Makes a copy of this constructor and converts it into a method.
* The signature of the mehtod is the same as the that of this constructor.
* The return type is <code>void</code>. The resulting method must be
* appended to the class specified by <code>declaring</code>.
* If this constructor is a static initializer, the resulting method takes
* no parameter.
*
* <p>An occurrence of another constructor call <code>this()</code>
* or a super constructor call <code>super()</code> is
* eliminated from the resulting method.
*
* <p>The immediate super class of the class declaring this constructor
* must be also a super class of the class declaring the resulting method.
* If the constructor accesses a field, the class declaring the resulting method
* must also declare a field with the same name and type.
*
* @param name the name of the resulting method.
* @param declaring the class declaring the resulting method.
*/
public CtMethod toMethod(String name, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
return toMethod(name, declaring, null);
}
/**
* Makes a copy of this constructor and converts it into a method.
* The signature of the method is the same as the that of this constructor.
* The return type is <code>void</code>. The resulting method must be
* appended to the class specified by <code>declaring</code>.
* If this constructor is a static initializer, the resulting method takes
* no parameter.
*
* <p>An occurrence of another constructor call <code>this()</code>
* or a super constructor call <code>super()</code> is
* eliminated from the resulting method.
*
* <p>The immediate super class of the class declaring this constructor
* must be also a super class of the class declaring the resulting method
* (this is obviously true if the second parameter <code>declaring</code> is
* the same as the class declaring this constructor).
* If the constructor accesses a field, the class declaring the resulting method
* must also declare a field with the same name and type.
*
* @param name the name of the resulting method.
* @param declaring the class declaring the resulting method.
* It is normally the same as the class declaring this
* constructor.
* @param map the hash table associating original class names
* with substituted names. The original class names will be
* replaced while making a copy.
* <code>map</code> can be <code>null</code>.
*/
public CtMethod toMethod(String name, CtClass declaring, ClassMap map)
throws com.fr.third.javassist.CannotCompileException
{
CtMethod method = new CtMethod(null, declaring);
method.copy(this, false, map);
if (isConstructor()) {
com.fr.third.javassist.bytecode.MethodInfo minfo = method.getMethodInfo2();
com.fr.third.javassist.bytecode.CodeAttribute ca = minfo.getCodeAttribute();
if (ca != null) {
removeConsCall(ca);
try {
methodInfo.rebuildStackMapIf6(declaring.getClassPool(),
declaring.getClassFile2());
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
}
method.setName(name);
return method;
}
private static void removeConsCall(CodeAttribute ca)
throws com.fr.third.javassist.CannotCompileException
{
com.fr.third.javassist.bytecode.CodeIterator iterator = ca.iterator();
try {
int pos = iterator.skipConstructor();
if (pos >= 0) {
int mref = iterator.u16bitAt(pos + 1);
String desc = ca.getConstPool().getMethodrefType(mref);
int num = com.fr.third.javassist.bytecode.Descriptor.numOfParameters(desc) + 1;
if (num > 3)
pos = iterator.insertGapAt(pos, num - 3, false).position;
iterator.writeByte(com.fr.third.javassist.bytecode.Opcode.POP, pos++); // this
iterator.writeByte(com.fr.third.javassist.bytecode.Opcode.NOP, pos);
iterator.writeByte(com.fr.third.javassist.bytecode.Opcode.NOP, pos + 1);
com.fr.third.javassist.bytecode.Descriptor.Iterator it = new com.fr.third.javassist.bytecode.Descriptor.Iterator(desc);
while (true) {
it.next();
if (it.isParameter())
iterator.writeByte(it.is2byte() ? com.fr.third.javassist.bytecode.Opcode.POP2 : com.fr.third.javassist.bytecode.Opcode.POP,
pos++);
else
break;
}
}
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new CannotCompileException(e);
}
}
}

1414
fine-javassist/src/main/java/com/fr/third/javassist/CtField.java

File diff suppressed because it is too large Load Diff

322
fine-javassist/src/main/java/com/fr/third/javassist/CtMember.java

@ -1,322 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.AttributeInfo;
import com.fr.third.javassist.bytecode.SignatureAttribute;
/**
* An instance of <code>CtMember</code> represents a field, a constructor,
* or a method.
*/
public abstract class CtMember {
CtMember next; // for internal use
protected com.fr.third.javassist.CtClass declaringClass;
/* Make a circular link of CtMembers declared in the
* same class so that they are garbage-collected together
* at the same time.
*/
static class Cache extends CtMember {
protected void extendToString(StringBuffer buffer) {}
public boolean hasAnnotation(Class clz) { return false; }
public Object getAnnotation(Class clz)
throws ClassNotFoundException { return null; }
public Object[] getAnnotations()
throws ClassNotFoundException { return null; }
public byte[] getAttribute(String name) { return null; }
public Object[] getAvailableAnnotations() { return null; }
public int getModifiers() { return 0; }
public String getName() { return null; }
public String getSignature() { return null; }
public void setAttribute(String name, byte[] data) {}
public void setModifiers(int mod) {}
public String getGenericSignature() { return null; }
public void setGenericSignature(String sig) {}
private CtMember methodTail;
private CtMember consTail; // constructor tail
private CtMember fieldTail;
Cache(com.fr.third.javassist.CtClassType decl) {
super(decl);
methodTail = this;
consTail = this;
fieldTail = this;
fieldTail.next = this;
}
CtMember methodHead() { return this; }
CtMember lastMethod() { return methodTail; }
CtMember consHead() { return methodTail; } // may include a static initializer
CtMember lastCons() { return consTail; }
CtMember fieldHead() { return consTail; }
CtMember lastField() { return fieldTail; }
void addMethod(CtMember method) {
method.next = methodTail.next;
methodTail.next = method;
if (methodTail == consTail) {
consTail = method;
if (methodTail == fieldTail)
fieldTail = method;
}
methodTail = method;
}
/* Both constructors and a class initializer.
*/
void addConstructor(CtMember cons) {
cons.next = consTail.next;
consTail.next = cons;
if (consTail == fieldTail)
fieldTail = cons;
consTail = cons;
}
void addField(CtMember field) {
field.next = this; // or fieldTail.next
fieldTail.next = field;
fieldTail = field;
}
static int count(CtMember head, CtMember tail) {
int n = 0;
while (head != tail) {
n++;
head = head.next;
}
return n;
}
void remove(CtMember mem) {
CtMember m = this;
CtMember node;
while ((node = m.next) != this) {
if (node == mem) {
m.next = node.next;
if (node == methodTail)
methodTail = m;
if (node == consTail)
consTail = m;
if (node == fieldTail)
fieldTail = m;
break;
}
else
m = m.next;
}
}
}
protected CtMember(com.fr.third.javassist.CtClass clazz) {
declaringClass = clazz;
next = null;
}
final CtMember next() { return next; }
/**
* This method is invoked when setName() or replaceClassName()
* in CtClass is called.
*
* @see CtMethod#nameReplaced()
*/
void nameReplaced() {}
public String toString() {
StringBuffer buffer = new StringBuffer(getClass().getName());
buffer.append("@");
buffer.append(Integer.toHexString(hashCode()));
buffer.append("[");
buffer.append(Modifier.toString(getModifiers()));
extendToString(buffer);
buffer.append("]");
return buffer.toString();
}
/**
* Invoked by {@link #toString()} to add to the buffer and provide the
* complete value. Subclasses should invoke this method, adding a
* space before each token. The modifiers for the member are
* provided first; subclasses should provide additional data such
* as return type, field or method name, etc.
*/
protected abstract void extendToString(StringBuffer buffer);
/**
* Returns the class that declares this member.
*/
public com.fr.third.javassist.CtClass getDeclaringClass() { return declaringClass; }
/**
* Returns true if this member is accessible from the given class.
*/
public boolean visibleFrom(com.fr.third.javassist.CtClass clazz) {
int mod = getModifiers();
if (Modifier.isPublic(mod))
return true;
else if (Modifier.isPrivate(mod))
return clazz == declaringClass;
else { // package or protected
String declName = declaringClass.getPackageName();
String fromName = clazz.getPackageName();
boolean visible;
if (declName == null)
visible = fromName == null;
else
visible = declName.equals(fromName);
if (!visible && Modifier.isProtected(mod))
return clazz.subclassOf(declaringClass);
return visible;
}
}
/**
* Obtains the modifiers of the member.
*
* @return modifiers encoded with
* <code>javassist.Modifier</code>.
* @see Modifier
*/
public abstract int getModifiers();
/**
* Sets the encoded modifiers of the member.
*
* @see Modifier
*/
public abstract void setModifiers(int mod);
/**
* Returns true if the class has the specified annotation class.
*
* @param clz the annotation class.
* @return <code>true</code> if the annotation is found, otherwise <code>false</code>.
* @since 3.11
*/
public abstract boolean hasAnnotation(Class clz);
/**
* Returns the annotation if the class has the specified annotation class.
* For example, if an annotation <code>@Author</code> is associated
* with this member, an <code>Author</code> object is returned.
* The member values can be obtained by calling methods on
* the <code>Author</code> object.
*
* @param clz the annotation class.
* @return the annotation if found, otherwise <code>null</code>.
* @since 3.11
*/
public abstract Object getAnnotation(Class clz) throws ClassNotFoundException;
/**
* Returns the annotations associated with this member.
* For example, if an annotation <code>@Author</code> is associated
* with this member, the returned array contains an <code>Author</code>
* object. The member values can be obtained by calling methods on
* the <code>Author</code> object.
*
* @return an array of annotation-type objects.
* @see com.fr.third.javassist.CtClass#getAnnotations()
*/
public abstract Object[] getAnnotations() throws ClassNotFoundException;
/**
* Returns the annotations associated with this member.
* This method is equivalent to <code>getAnnotations()</code>
* except that, if any annotations are not on the classpath,
* they are not included in the returned array.
*
* @return an array of annotation-type objects.
* @see #getAnnotations()
* @see com.fr.third.javassist.CtClass#getAvailableAnnotations()
* @since 3.3
*/
public abstract Object[] getAvailableAnnotations();
/**
* Obtains the name of the member.
*
* <p>As for constructor names, see <code>getName()</code>
* in <code>CtConstructor</code>.
*
* @see CtConstructor#getName()
*/
public abstract String getName();
/**
* Returns the character string representing the signature of the member.
* If two members have the same signature (parameter types etc.),
* <code>getSignature()</code> returns the same string.
*/
public abstract String getSignature();
/**
* Returns the generic signature of the member.
*
* @see SignatureAttribute#toFieldSignature(String)
* @see SignatureAttribute#toMethodSignature(String)
* @see com.fr.third.javassist.CtClass#getGenericSignature()
* @since 3.17
*/
public abstract String getGenericSignature();
/**
* Sets the generic signature of the member.
*
* @param sig a new generic signature.
* @see SignatureAttribute.ObjectType#encode()
* @see SignatureAttribute.MethodSignature#encode()
* @see CtClass#setGenericSignature(String)
* @since 3.17
*/
public abstract void setGenericSignature(String sig);
/**
* Obtains a user-defined attribute with the given name.
* If that attribute is not found in the class file, this
* method returns null.
*
* <p>Note that an attribute is a data block specified by
* the class file format.
* See {@link AttributeInfo}.
*
* @param name attribute name
*/
public abstract byte[] getAttribute(String name);
/**
* Adds a user-defined attribute. The attribute is saved in the class file.
*
* <p>Note that an attribute is a data block specified by
* the class file format.
* See {@link AttributeInfo}.
*
* @param name attribute name
* @param data attribute value
*/
public abstract void setAttribute(String name, byte[] data);
}

436
fine-javassist/src/main/java/com/fr/third/javassist/CtMethod.java

@ -1,436 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.CodeAttribute;
/**
* An instance of <code>CtMethod</code> represents a method.
*
* <p>See the super class <code>CtBehavior</code> since
* a number of useful methods are in <code>CtBehavior</code>.
* A number of useful factory methods are in <code>CtNewMethod</code>.
*
* @see com.fr.third.javassist.CtClass#getDeclaredMethods()
* @see CtNewMethod
*/
public final class CtMethod extends CtBehavior {
protected String cachedStringRep;
/**
* @see #make(com.fr.third.javassist.bytecode.MethodInfo minfo, com.fr.third.javassist.CtClass declaring)
*/
CtMethod(com.fr.third.javassist.bytecode.MethodInfo minfo, com.fr.third.javassist.CtClass declaring) {
super(declaring, minfo);
cachedStringRep = null;
}
/**
* Creates a public abstract method. The created method must be
* added to a class with <code>CtClass.addMethod()</code>.
*
* @param declaring the class to which the created method is added.
* @param returnType the type of the returned value
* @param mname the method name
* @param parameters a list of the parameter types
*
* @see com.fr.third.javassist.CtClass#addMethod(CtMethod)
*/
public CtMethod(com.fr.third.javassist.CtClass returnType, String mname,
com.fr.third.javassist.CtClass[] parameters, com.fr.third.javassist.CtClass declaring) {
this(null, declaring);
com.fr.third.javassist.bytecode.ConstPool cp = declaring.getClassFile2().getConstPool();
String desc = com.fr.third.javassist.bytecode.Descriptor.ofMethod(returnType, parameters);
methodInfo = new com.fr.third.javassist.bytecode.MethodInfo(cp, mname, desc);
setModifiers(Modifier.PUBLIC | Modifier.ABSTRACT);
}
/**
* Creates a copy of a <code>CtMethod</code> object.
* The created method must be
* added to a class with <code>CtClass.addMethod()</code>.
*
* <p>All occurrences of class names in the created method
* are replaced with names specified by
* <code>map</code> if <code>map</code> is not <code>null</code>.
*
* <p>For example, suppose that a method <code>at()</code> is as
* follows:
*
* <ul><pre>public X at(int i) {
* return (X)super.elementAt(i);
* }</pre></ul>
*
* <p>(<code>X</code> is a class name.) If <code>map</code> substitutes
* <code>String</code> for <code>X</code>, then the created method is:
*
* <ul><pre>public String at(int i) {
* return (String)super.elementAt(i);
* }</pre></ul>
*
* <p>By default, all the occurrences of the names of the class
* declaring <code>at()</code> and the superclass are replaced
* with the name of the class and the superclass that the
* created method is added to.
* This is done whichever <code>map</code> is null or not.
* To prevent this replacement, call <code>ClassMap.fix()</code>
* or <code>put()</code> to explicitly specify replacement.
*
* <p><b>Note:</b> if the <code>.class</code> notation (for example,
* <code>String.class</code>) is included in an expression, the
* Javac compiler may produce a helper method.
* Since this constructor never
* copies this helper method, the programmers have the responsiblity of
* copying it. Otherwise, use <code>Class.forName()</code> in the
* expression.
*
* @param src the source method.
* @param declaring the class to which the created method is added.
* @param map the hashtable associating original class names
* with substituted names.
* It can be <code>null</code>.
*
* @see com.fr.third.javassist.CtClass#addMethod(CtMethod)
* @see com.fr.third.javassist.ClassMap#fix(String)
*/
public CtMethod(CtMethod src, com.fr.third.javassist.CtClass declaring, com.fr.third.javassist.ClassMap map)
throws com.fr.third.javassist.CannotCompileException
{
this(null, declaring);
copy(src, false, map);
}
/**
* Compiles the given source code and creates a method.
* This method simply delegates to <code>make()</code> in
* <code>CtNewMethod</code>. See it for more details.
* <code>CtNewMethod</code> has a number of useful factory methods.
*
* @param src the source text.
* @param declaring the class to which the created method is added.
* @see CtNewMethod#make(String, com.fr.third.javassist.CtClass)
*/
public static CtMethod make(String src, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
return CtNewMethod.make(src, declaring);
}
/**
* Creates a method from a <code>MethodInfo</code> object.
*
* @param declaring the class declaring the method.
* @throws com.fr.third.javassist.CannotCompileException if the the <code>MethodInfo</code>
* object and the declaring class have different
* <code>ConstPool</code> objects
* @since 3.6
*/
public static CtMethod make(com.fr.third.javassist.bytecode.MethodInfo minfo, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
if (declaring.getClassFile2().getConstPool() != minfo.getConstPool())
throw new com.fr.third.javassist.CannotCompileException("bad declaring class");
return new CtMethod(minfo, declaring);
}
/**
* Returns a hash code value for the method.
* If two methods have the same name and signature, then
* the hash codes for the two methods are equal.
*/
public int hashCode() {
return getStringRep().hashCode();
}
/**
* This method is invoked when setName() or replaceClassName()
* in CtClass is called.
*/
void nameReplaced() {
cachedStringRep = null;
}
/* This method is also called by CtClassType.getMethods0().
*/
final String getStringRep() {
if (cachedStringRep == null)
cachedStringRep = methodInfo.getName()
+ com.fr.third.javassist.bytecode.Descriptor.getParamDescriptor(methodInfo.getDescriptor());
return cachedStringRep;
}
/**
* Indicates whether <code>obj</code> has the same name and the
* same signature as this method.
*/
public boolean equals(Object obj) {
return obj != null && obj instanceof CtMethod
&& ((CtMethod)obj).getStringRep().equals(getStringRep());
}
/**
* Returns the method name followed by parameter types
* such as <code>javassist.CtMethod.setBody(String)</code>.
*
* @since 3.5
*/
public String getLongName() {
return getDeclaringClass().getName() + "."
+ getName() + com.fr.third.javassist.bytecode.Descriptor.toString(getSignature());
}
/**
* Obtains the name of this method.
*/
public String getName() {
return methodInfo.getName();
}
/**
* Changes the name of this method.
*/
public void setName(String newname) {
declaringClass.checkModify();
methodInfo.setName(newname);
}
/**
* Obtains the type of the returned value.
*/
public com.fr.third.javassist.CtClass getReturnType() throws NotFoundException {
return getReturnType0();
}
/**
* Returns true if the method body is empty, that is, <code>{}</code>.
* It also returns true if the method is an abstract method.
*/
public boolean isEmpty() {
com.fr.third.javassist.bytecode.CodeAttribute ca = getMethodInfo2().getCodeAttribute();
if (ca == null) // abstract or native
return (getModifiers() & Modifier.ABSTRACT) != 0;
com.fr.third.javassist.bytecode.CodeIterator it = ca.iterator();
try {
return it.hasNext() && it.byteAt(it.next()) == com.fr.third.javassist.bytecode.Opcode.RETURN
&& !it.hasNext();
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {}
return false;
}
/**
* Copies a method body from another method.
* If this method is abstract, the abstract modifier is removed
* after the method body is copied.
*
* <p>All occurrences of the class names in the copied method body
* are replaced with the names specified by
* <code>map</code> if <code>map</code> is not <code>null</code>.
*
* @param src the method that the body is copied from.
* @param map the hashtable associating original class names
* with substituted names.
* It can be <code>null</code>.
*/
public void setBody(CtMethod src, ClassMap map)
throws com.fr.third.javassist.CannotCompileException
{
setBody0(src.declaringClass, src.methodInfo,
declaringClass, methodInfo, map);
}
/**
* Replace a method body with a new method body wrapping the
* given method.
*
* @param mbody the wrapped method
* @param constParam the constant parameter given to
* the wrapped method
* (maybe <code>null</code>).
*
* @see CtNewMethod#wrapped(com.fr.third.javassist.CtClass,String, com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtClass[],CtMethod,CtMethod.ConstParameter, com.fr.third.javassist.CtClass)
*/
public void setWrappedBody(CtMethod mbody, ConstParameter constParam)
throws com.fr.third.javassist.CannotCompileException
{
declaringClass.checkModify();
com.fr.third.javassist.CtClass clazz = getDeclaringClass();
com.fr.third.javassist.CtClass[] params;
com.fr.third.javassist.CtClass retType;
try {
params = getParameterTypes();
retType = getReturnType();
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
com.fr.third.javassist.bytecode.Bytecode code = CtNewWrappedMethod.makeBody(clazz,
clazz.getClassFile2(),
mbody,
params, retType,
constParam);
CodeAttribute cattr = code.toCodeAttribute();
methodInfo.setCodeAttribute(cattr);
methodInfo.setAccessFlags(methodInfo.getAccessFlags()
& ~com.fr.third.javassist.bytecode.AccessFlag.ABSTRACT);
// rebuilding a stack map table is not needed.
}
// inner classes
/**
* Instances of this class represent a constant parameter.
* They are used to specify the parameter given to the methods
* created by <code>CtNewMethod.wrapped()</code>.
*
* @see CtMethod#setWrappedBody(CtMethod,CtMethod.ConstParameter)
* @see CtNewMethod#wrapped(com.fr.third.javassist.CtClass,String, com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtClass[],CtMethod,CtMethod.ConstParameter, com.fr.third.javassist.CtClass)
* @see CtNewConstructor#make(com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtClass[],int,CtMethod,CtMethod.ConstParameter, CtClass)
*/
public static class ConstParameter {
/**
* Makes an integer constant.
*
* @param i the constant value.
*/
public static ConstParameter integer(int i) {
return new IntConstParameter(i);
}
/**
* Makes a long integer constant.
*
* @param i the constant value.
*/
public static ConstParameter integer(long i) {
return new LongConstParameter(i);
}
/**
* Makes an <code>String</code> constant.
*
* @param s the constant value.
*/
public static ConstParameter string(String s) {
return new StringConstParameter(s);
}
ConstParameter() {}
/**
* @return the size of the stack consumption.
*/
int compile(com.fr.third.javassist.bytecode.Bytecode code) throws com.fr.third.javassist.CannotCompileException {
return 0;
}
String descriptor() {
return defaultDescriptor();
}
/**
* @see CtNewWrappedMethod
*/
static String defaultDescriptor() {
return "([Ljava/lang/Object;)Ljava/lang/Object;";
}
/**
* Returns the descriptor for constructors.
*
* @see CtNewWrappedConstructor
*/
String constDescriptor() {
return defaultConstDescriptor();
}
/**
* Returns the default descriptor for constructors.
*/
static String defaultConstDescriptor() {
return "([Ljava/lang/Object;)V";
}
}
static class IntConstParameter extends ConstParameter {
int param;
IntConstParameter(int i) {
param = i;
}
int compile(com.fr.third.javassist.bytecode.Bytecode code) throws com.fr.third.javassist.CannotCompileException {
code.addIconst(param);
return 1;
}
String descriptor() {
return "([Ljava/lang/Object;I)Ljava/lang/Object;";
}
String constDescriptor() {
return "([Ljava/lang/Object;I)V";
}
}
static class LongConstParameter extends ConstParameter {
long param;
LongConstParameter(long l) {
param = l;
}
int compile(com.fr.third.javassist.bytecode.Bytecode code) throws com.fr.third.javassist.CannotCompileException {
code.addLconst(param);
return 2;
}
String descriptor() {
return "([Ljava/lang/Object;J)Ljava/lang/Object;";
}
String constDescriptor() {
return "([Ljava/lang/Object;J)V";
}
}
static class StringConstParameter extends ConstParameter {
String param;
StringConstParameter(String s) {
param = s;
}
int compile(com.fr.third.javassist.bytecode.Bytecode code) throws CannotCompileException {
code.addLdc(param);
return 1;
}
String descriptor() {
return "([Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;";
}
String constDescriptor() {
return "([Ljava/lang/Object;Ljava/lang/String;)V";
}
}
}

127
fine-javassist/src/main/java/com/fr/third/javassist/CtNewClass.java

@ -1,127 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.DataOutputStream;
import java.io.IOException;
import com.fr.third.javassist.bytecode.ClassFile;
class CtNewClass extends com.fr.third.javassist.CtClassType {
/* true if the class is an interface.
*/
protected boolean hasConstructor;
CtNewClass(String name, ClassPool cp,
boolean isInterface, com.fr.third.javassist.CtClass superclass) {
super(name, cp);
wasChanged = true;
String superName;
if (isInterface || superclass == null)
superName = null;
else
superName = superclass.getName();
classfile = new ClassFile(isInterface, name, superName);
if (isInterface && superclass != null)
classfile.setInterfaces(new String[] { superclass.getName() });
setModifiers(Modifier.setPublic(getModifiers()));
hasConstructor = isInterface;
}
protected void extendToString(StringBuffer buffer) {
if (hasConstructor)
buffer.append("hasConstructor ");
super.extendToString(buffer);
}
public void addConstructor(com.fr.third.javassist.CtConstructor c)
throws com.fr.third.javassist.CannotCompileException
{
hasConstructor = true;
super.addConstructor(c);
}
public void toBytecode(DataOutputStream out)
throws com.fr.third.javassist.CannotCompileException, IOException
{
if (!hasConstructor)
try {
inheritAllConstructors();
hasConstructor = true;
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
super.toBytecode(out);
}
/**
* Adds constructors inhrited from the super class.
*
* <p>After this method is called, the class inherits all the
* constructors from the super class. The added constructor
* calls the super's constructor with the same signature.
*/
public void inheritAllConstructors()
throws com.fr.third.javassist.CannotCompileException, NotFoundException
{
com.fr.third.javassist.CtClass superclazz;
com.fr.third.javassist.CtConstructor[] cs;
superclazz = getSuperclass();
cs = superclazz.getDeclaredConstructors();
int n = 0;
for (int i = 0; i < cs.length; ++i) {
com.fr.third.javassist.CtConstructor c = cs[i];
int mod = c.getModifiers();
if (isInheritable(mod, superclazz)) {
CtConstructor cons
= CtNewConstructor.make(c.getParameterTypes(),
c.getExceptionTypes(), this);
cons.setModifiers(mod & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE));
addConstructor(cons);
++n;
}
}
if (n < 1)
throw new CannotCompileException(
"no inheritable constructor in " + superclazz.getName());
}
private boolean isInheritable(int mod, CtClass superclazz) {
if (Modifier.isPrivate(mod))
return false;
if (Modifier.isPackage(mod)) {
String pname = getPackageName();
String pname2 = superclazz.getPackageName();
if (pname == null)
return pname2 == null;
else
return pname.equals(pname2);
}
return true;
}
}

317
fine-javassist/src/main/java/com/fr/third/javassist/CtNewConstructor.java

@ -1,317 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.compiler.Javac;
import com.fr.third.javassist.compiler.CompileError;
import com.fr.third.javassist.CtMethod.ConstParameter;
/**
* A collection of static methods for creating a <code>CtConstructor</code>.
* An instance of this class does not make any sense.
*
* <p>A class initializer (static constructor) cannot be created by the
* methods in this class. Call <code>makeClassInitializer()</code> in
* <code>CtClass</code> and append code snippet to the body of the class
* initializer obtained by <code>makeClassInitializer()</code>.
*
* @see com.fr.third.javassist.CtClass#addConstructor(com.fr.third.javassist.CtConstructor)
* @see com.fr.third.javassist.CtClass#makeClassInitializer()
*/
public class CtNewConstructor {
/**
* Specifies that no parameters are passed to a super-class'
* constructor. That is, the default constructor is invoked.
*/
public static final int PASS_NONE = 0; // call super()
/**
* Specifies that parameters are converted into an array of
* <code>Object</code> and passed to a super-class'
* constructor.
*/
public static final int PASS_ARRAY = 1; // an array of parameters
/**
* Specifies that parameters are passed <i>as is</i>
* to a super-class' constructor. The signature of that
* constructor must be the same as that of the created constructor.
*/
public static final int PASS_PARAMS = 2;
/**
* Compiles the given source code and creates a constructor.
* The source code must include not only the constructor body
* but the whole declaration.
*
* @param src the source text.
* @param declaring the class to which the created constructor is added.
*/
public static com.fr.third.javassist.CtConstructor make(String src, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
Javac compiler = new Javac(declaring);
try {
CtMember obj = compiler.compile(src);
if (obj instanceof com.fr.third.javassist.CtConstructor) {
// a stack map table has been already created.
return (com.fr.third.javassist.CtConstructor)obj;
}
}
catch (CompileError e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
throw new com.fr.third.javassist.CannotCompileException("not a constructor");
}
/**
* Creates a public constructor.
*
* @param parameters a list of the parameter types.
* @param exceptions a list of the exception types.
* @param body the source text of the constructor body.
* It must be a block surrounded by <code>{}</code>.
* If it is <code>null</code>, the substituted
* constructor body does nothing except calling
* <code>super()</code>.
* @param declaring the class to which the created method is added.
*/
public static com.fr.third.javassist.CtConstructor make(com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions,
String body, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
try {
com.fr.third.javassist.CtConstructor cc = new com.fr.third.javassist.CtConstructor(parameters, declaring);
cc.setExceptionTypes(exceptions);
cc.setBody(body);
return cc;
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
/**
* Creates a copy of a constructor.
* This is a convenience method for calling
* {@link com.fr.third.javassist.CtConstructor#CtConstructor(com.fr.third.javassist.CtConstructor, com.fr.third.javassist.CtClass, com.fr.third.javassist.ClassMap) this constructor}.
* See the description of the constructor for particular behavior of the copying.
*
* @param c the copied constructor.
* @param declaring the class to which the created method is added.
* @param map the hash table associating original class names
* with substituted names.
* It can be <code>null</code>.
*
* @see com.fr.third.javassist.CtConstructor#CtConstructor(com.fr.third.javassist.CtConstructor, com.fr.third.javassist.CtClass, com.fr.third.javassist.ClassMap)
*/
public static com.fr.third.javassist.CtConstructor copy(com.fr.third.javassist.CtConstructor c, com.fr.third.javassist.CtClass declaring,
ClassMap map) throws com.fr.third.javassist.CannotCompileException {
return new com.fr.third.javassist.CtConstructor(c, declaring, map);
}
/**
* Creates a default (public) constructor.
*
* <p>The created constructor takes no parameter. It calls
* <code>super()</code>.
*/
public static com.fr.third.javassist.CtConstructor defaultConstructor(com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
com.fr.third.javassist.CtConstructor cons = new com.fr.third.javassist.CtConstructor((com.fr.third.javassist.CtClass[])null, declaring);
ConstPool cp = declaring.getClassFile2().getConstPool();
com.fr.third.javassist.bytecode.Bytecode code = new com.fr.third.javassist.bytecode.Bytecode(cp, 1, 1);
code.addAload(0);
try {
code.addInvokespecial(declaring.getSuperclass(),
"<init>", "()V");
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
code.add(com.fr.third.javassist.bytecode.Bytecode.RETURN);
// no need to construct a stack map table.
cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
return cons;
}
/**
* Creates a public constructor that only calls a constructor
* in the super class. The created constructor receives parameters
* specified by <code>parameters</code> but calls the super's
* constructor without those parameters (that is, it calls the default
* constructor).
*
* <p>The parameters passed to the created constructor should be
* used for field initialization. <code>CtField.Initializer</code>
* objects implicitly insert initialization code in constructor
* bodies.
*
* @param parameters parameter types
* @param exceptions exception types
* @param declaring the class to which the created constructor
* is added.
* @see CtField.Initializer#byParameter(int)
*/
public static com.fr.third.javassist.CtConstructor skeleton(com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
return make(parameters, exceptions, PASS_NONE,
null, null, declaring);
}
/**
* Creates a public constructor that only calls a constructor
* in the super class. The created constructor receives parameters
* specified by <code>parameters</code> and calls the super's
* constructor with those parameters.
*
* @param parameters parameter types
* @param exceptions exception types
* @param declaring the class to which the created constructor
* is added.
*/
public static com.fr.third.javassist.CtConstructor make(com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
return make(parameters, exceptions, PASS_PARAMS,
null, null, declaring);
}
/**
* Creates a public constructor.
*
* <p>If <code>howto</code> is <code>PASS_PARAMS</code>,
* the created constructor calls the super's constructor with the
* same signature. The superclass must contain
* a constructor taking the same set of parameters as the created one.
*
* <p>If <code>howto</code> is <code>PASS_NONE</code>,
* the created constructor calls the super's default constructor.
* The superclass must contain a constructor taking no parameters.
*
* <p>If <code>howto</code> is <code>PASS_ARRAY</code>,
* the created constructor calls the super's constructor
* with the given parameters in the form of an array of
* <code>Object</code>. The signature of the super's constructor
* must be:
*
* <ul><code>constructor(Object[] params, &lt;type&gt; cvalue)
* </code></ul>
*
* <p>Here, <code>cvalue</code> is the constant value specified
* by <code>cparam</code>.
*
* <p>If <code>cparam</code> is <code>null</code>, the signature
* must be:
*
* <ul><code>constructor(Object[] params)</code></ul>
*
* <p>If <code>body</code> is not null, a copy of that method is
* embedded in the body of the created constructor.
* The embedded method is executed after
* the super's constructor is called and the values of fields are
* initialized. Note that <code>body</code> must not
* be a constructor but a method.
*
* <p>Since the embedded method is wrapped
* in parameter-conversion code
* as in <code>CtNewMethod.wrapped()</code>,
* the constructor parameters are
* passed in the form of an array of <code>Object</code>.
* The method specified by <code>body</code> must have the
* signature shown below:
*
* <ul><code>Object method(Object[] params, &lt;type&gt; cvalue)
* </code></ul>
*
* <p>If <code>cparam</code> is <code>null</code>, the signature
* must be:
*
* <ul><code>Object method(Object[] params)</code></ul>
*
* <p>Although the type of the returned value is <code>Object</code>,
* the value must be always <code>null</code>.
*
* <p><i>Example:</i>
*
* <ul><pre>ClassPool pool = ... ;
* CtClass xclass = pool.makeClass("X");
* CtMethod method = pool.getMethod("Sample", "m");
* xclass.setSuperclass(pool.get("Y"));
* CtClass[] argTypes = { CtClass.intType };
* ConstParameter cparam = ConstParameter.string("test");
* CtConstructor c = CtNewConstructor.make(argTypes, null,
* PASS_PARAMS, method, cparam, xclass);
* xclass.addConstructor(c);</pre></ul>
*
* <p>where the class <code>Sample</code> is as follows:
*
* <ul><pre>public class Sample {
* public Object m(Object[] args, String msg) {
* System.out.println(msg);
* return null;
* }
* }</pre></ul>
*
* <p>This program produces the following class:
*
* <ul><pre>public class X extends Y {
* public X(int p0) {
* super(p0);
* String msg = "test";
* Object[] args = new Object[] { p0 };
* // begin of copied body
* System.out.println(msg);
* Object result = null;
* // end
* }
* }</pre></ul>
*
* @param parameters a list of the parameter types
* @param exceptions a list of the exceptions
* @param howto how to pass parameters to the super-class'
* constructor (<code>PASS_NONE</code>,
* <code>PASS_ARRAY</code>,
* or <code>PASS_PARAMS</code>)
* @param body appended body (may be <code>null</code>).
* It must be not a constructor but a method.
* @param cparam constant parameter (may be <code>null</code>.)
* @param declaring the class to which the created constructor
* is added.
*
* @see CtNewMethod#wrapped(com.fr.third.javassist.CtClass,String, com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtMethod, ConstParameter, com.fr.third.javassist.CtClass)
*/
public static CtConstructor make(com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions, int howto,
CtMethod body, ConstParameter cparam,
CtClass declaring)
throws CannotCompileException
{
return CtNewWrappedConstructor.wrapped(parameters, exceptions,
howto, body, cparam, declaring);
}
}

476
fine-javassist/src/main/java/com/fr/third/javassist/CtNewMethod.java

@ -1,476 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.compiler.Javac;
import com.fr.third.javassist.compiler.CompileError;
import com.fr.third.javassist.CtMethod.ConstParameter;
/**
* A collection of static methods for creating a <code>CtMethod</code>.
* An instance of this class does not make any sense.
*
* @see com.fr.third.javassist.CtClass#addMethod(com.fr.third.javassist.CtMethod)
*/
public class CtNewMethod {
/**
* Compiles the given source code and creates a method.
* The source code must include not only the method body
* but the whole declaration, for example,
*
* <ul><pre>"public Object id(Object obj) { return obj; }"</pre></ul>
*
* @param src the source text.
* @param declaring the class to which the created method is added.
*/
public static com.fr.third.javassist.CtMethod make(String src, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
return make(src, declaring, null, null);
}
/**
* Compiles the given source code and creates a method.
* The source code must include not only the method body
* but the whole declaration, for example,
*
* <ul><pre>"public Object id(Object obj) { return obj; }"</pre></ul>
*
* <p>If the source code includes <code>$proceed()</code>, then
* it is compiled into a method call on the specified object.
*
* @param src the source text.
* @param declaring the class to which the created method is added.
* @param delegateObj the source text specifying the object
* that is called on by <code>$proceed()</code>.
* @param delegateMethod the name of the method
* that is called by <code>$proceed()</code>.
*/
public static com.fr.third.javassist.CtMethod make(String src, com.fr.third.javassist.CtClass declaring,
String delegateObj, String delegateMethod)
throws com.fr.third.javassist.CannotCompileException
{
Javac compiler = new Javac(declaring);
try {
if (delegateMethod != null)
compiler.recordProceed(delegateObj, delegateMethod);
CtMember obj = compiler.compile(src);
if (obj instanceof com.fr.third.javassist.CtMethod)
return (com.fr.third.javassist.CtMethod)obj;
}
catch (CompileError e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
throw new com.fr.third.javassist.CannotCompileException("not a method");
}
/**
* Creates a public (non-static) method. The created method cannot
* be changed to a static method later.
*
* @param returnType the type of the returned value.
* @param mname the method name.
* @param parameters a list of the parameter types.
* @param exceptions a list of the exception types.
* @param body the source text of the method body.
* It must be a block surrounded by <code>{}</code>.
* If it is <code>null</code>, the created method
* does nothing except returning zero or null.
* @param declaring the class to which the created method is added.
* @see #make(int, com.fr.third.javassist.CtClass, String, com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtClass[], String, com.fr.third.javassist.CtClass)
*/
public static com.fr.third.javassist.CtMethod make(com.fr.third.javassist.CtClass returnType,
String mname, com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions,
String body, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
return make(Modifier.PUBLIC, returnType, mname, parameters, exceptions,
body, declaring);
}
/**
* Creates a method. <code>modifiers</code> can contain
* <code>Modifier.STATIC</code>.
*
* @param modifiers access modifiers.
* @param returnType the type of the returned value.
* @param mname the method name.
* @param parameters a list of the parameter types.
* @param exceptions a list of the exception types.
* @param body the source text of the method body.
* It must be a block surrounded by <code>{}</code>.
* If it is <code>null</code>, the created method
* does nothing except returning zero or null.
* @param declaring the class to which the created method is added.
*
* @see Modifier
*/
public static com.fr.third.javassist.CtMethod make(int modifiers, com.fr.third.javassist.CtClass returnType,
String mname, com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions,
String body, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
try {
com.fr.third.javassist.CtMethod cm
= new com.fr.third.javassist.CtMethod(returnType, mname, parameters, declaring);
cm.setModifiers(modifiers);
cm.setExceptionTypes(exceptions);
cm.setBody(body);
return cm;
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
/**
* Creates a copy of a method. This method is provided for creating
* a new method based on an existing method.
* This is a convenience method for calling
* {@link com.fr.third.javassist.CtMethod#CtMethod(com.fr.third.javassist.CtMethod, com.fr.third.javassist.CtClass, com.fr.third.javassist.ClassMap) this constructor}.
* See the description of the constructor for particular behavior of the copying.
*
* @param src the source method.
* @param declaring the class to which the created method is added.
* @param map the hash table associating original class names
* with substituted names.
* It can be <code>null</code>.
*
* @see com.fr.third.javassist.CtMethod#CtMethod(com.fr.third.javassist.CtMethod, com.fr.third.javassist.CtClass, com.fr.third.javassist.ClassMap)
*/
public static com.fr.third.javassist.CtMethod copy(com.fr.third.javassist.CtMethod src, com.fr.third.javassist.CtClass declaring,
com.fr.third.javassist.ClassMap map) throws com.fr.third.javassist.CannotCompileException {
return new com.fr.third.javassist.CtMethod(src, declaring, map);
}
/**
* Creates a copy of a method with a new name.
* This method is provided for creating
* a new method based on an existing method.
* This is a convenience method for calling
* {@link com.fr.third.javassist.CtMethod#CtMethod(com.fr.third.javassist.CtMethod, com.fr.third.javassist.CtClass, com.fr.third.javassist.ClassMap) this constructor}.
* See the description of the constructor for particular behavior of the copying.
*
* @param src the source method.
* @param name the name of the created method.
* @param declaring the class to which the created method is added.
* @param map the hash table associating original class names
* with substituted names.
* It can be <code>null</code>.
*
* @see com.fr.third.javassist.CtMethod#CtMethod(com.fr.third.javassist.CtMethod, com.fr.third.javassist.CtClass, com.fr.third.javassist.ClassMap)
*/
public static com.fr.third.javassist.CtMethod copy(com.fr.third.javassist.CtMethod src, String name, com.fr.third.javassist.CtClass declaring,
ClassMap map) throws com.fr.third.javassist.CannotCompileException {
com.fr.third.javassist.CtMethod cm = new com.fr.third.javassist.CtMethod(src, declaring, map);
cm.setName(name);
return cm;
}
/**
* Creates a public abstract method.
*
* @param returnType the type of the returned value
* @param mname the method name
* @param parameters a list of the parameter types
* @param exceptions a list of the exception types
* @param declaring the class to which the created method is added.
*
* @see com.fr.third.javassist.CtMethod#CtMethod(com.fr.third.javassist.CtClass,String, com.fr.third.javassist.CtClass[], com.fr.third.javassist.CtClass)
*/
public static com.fr.third.javassist.CtMethod abstractMethod(com.fr.third.javassist.CtClass returnType,
String mname,
com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass[] exceptions,
com.fr.third.javassist.CtClass declaring)
throws NotFoundException
{
com.fr.third.javassist.CtMethod cm = new com.fr.third.javassist.CtMethod(returnType, mname, parameters, declaring);
cm.setExceptionTypes(exceptions);
return cm;
}
/**
* Creates a public getter method. The getter method returns the value
* of the specified field in the class to which this method is added.
* The created method is initially not static even if the field is
* static. Change the modifiers if the method should be static.
*
* @param methodName the name of the getter
* @param field the field accessed.
*/
public static com.fr.third.javassist.CtMethod getter(String methodName, com.fr.third.javassist.CtField field)
throws com.fr.third.javassist.CannotCompileException
{
com.fr.third.javassist.bytecode.FieldInfo finfo = field.getFieldInfo2();
String fieldType = finfo.getDescriptor();
String desc = "()" + fieldType;
com.fr.third.javassist.bytecode.ConstPool cp = finfo.getConstPool();
com.fr.third.javassist.bytecode.MethodInfo minfo = new com.fr.third.javassist.bytecode.MethodInfo(cp, methodName, desc);
minfo.setAccessFlags(com.fr.third.javassist.bytecode.AccessFlag.PUBLIC);
com.fr.third.javassist.bytecode.Bytecode code = new com.fr.third.javassist.bytecode.Bytecode(cp, 2, 1);
try {
String fieldName = finfo.getName();
if ((finfo.getAccessFlags() & com.fr.third.javassist.bytecode.AccessFlag.STATIC) == 0) {
code.addAload(0);
code.addGetfield(com.fr.third.javassist.bytecode.Bytecode.THIS, fieldName, fieldType);
}
else
code.addGetstatic(com.fr.third.javassist.bytecode.Bytecode.THIS, fieldName, fieldType);
code.addReturn(field.getType());
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
minfo.setCodeAttribute(code.toCodeAttribute());
com.fr.third.javassist.CtClass cc = field.getDeclaringClass();
// a stack map is not needed.
return new com.fr.third.javassist.CtMethod(minfo, cc);
}
/**
* Creates a public setter method. The setter method assigns the
* value of the first parameter to the specified field
* in the class to which this method is added.
* The created method is not static even if the field is
* static. You may not change it to be static
* by <code>setModifiers()</code> in <code>CtBehavior</code>.
*
* @param methodName the name of the setter
* @param field the field accessed.
*/
public static com.fr.third.javassist.CtMethod setter(String methodName, CtField field)
throws com.fr.third.javassist.CannotCompileException
{
com.fr.third.javassist.bytecode.FieldInfo finfo = field.getFieldInfo2();
String fieldType = finfo.getDescriptor();
String desc = "(" + fieldType + ")V";
com.fr.third.javassist.bytecode.ConstPool cp = finfo.getConstPool();
com.fr.third.javassist.bytecode.MethodInfo minfo = new com.fr.third.javassist.bytecode.MethodInfo(cp, methodName, desc);
minfo.setAccessFlags(com.fr.third.javassist.bytecode.AccessFlag.PUBLIC);
com.fr.third.javassist.bytecode.Bytecode code = new com.fr.third.javassist.bytecode.Bytecode(cp, 3, 3);
try {
String fieldName = finfo.getName();
if ((finfo.getAccessFlags() & com.fr.third.javassist.bytecode.AccessFlag.STATIC) == 0) {
code.addAload(0);
code.addLoad(1, field.getType());
code.addPutfield(com.fr.third.javassist.bytecode.Bytecode.THIS, fieldName, fieldType);
}
else {
code.addLoad(1, field.getType());
code.addPutstatic(com.fr.third.javassist.bytecode.Bytecode.THIS, fieldName, fieldType);
}
code.addReturn(null);
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
minfo.setCodeAttribute(code.toCodeAttribute());
com.fr.third.javassist.CtClass cc = field.getDeclaringClass();
// a stack map is not needed.
return new com.fr.third.javassist.CtMethod(minfo, cc);
}
/**
* Creates a method forwarding to a delegate in
* a super class. The created method calls a method specified
* by <code>delegate</code> with all the parameters passed to the
* created method. If the delegate method returns a value,
* the created method returns that value to the caller.
* The delegate method must be declared in a super class.
*
* <p>The following method is an example of the created method.
*
* <ul><pre>int f(int p, int q) {
* return super.f(p, q);
* }</pre></ul>
*
* <p>The name of the created method can be changed by
* <code>setName()</code>.
*
* @param delegate the method that the created method forwards to.
* @param declaring the class to which the created method is
* added.
*/
public static com.fr.third.javassist.CtMethod delegator(com.fr.third.javassist.CtMethod delegate, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
try {
return delegator0(delegate, declaring);
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
private static com.fr.third.javassist.CtMethod delegator0(com.fr.third.javassist.CtMethod delegate, com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException, NotFoundException
{
com.fr.third.javassist.bytecode.MethodInfo deleInfo = delegate.getMethodInfo2();
String methodName = deleInfo.getName();
String desc = deleInfo.getDescriptor();
ConstPool cp = declaring.getClassFile2().getConstPool();
com.fr.third.javassist.bytecode.MethodInfo minfo = new com.fr.third.javassist.bytecode.MethodInfo(cp, methodName, desc);
minfo.setAccessFlags(deleInfo.getAccessFlags());
com.fr.third.javassist.bytecode.ExceptionsAttribute eattr = deleInfo.getExceptionsAttribute();
if (eattr != null)
minfo.setExceptionsAttribute(
(com.fr.third.javassist.bytecode.ExceptionsAttribute)eattr.copy(cp, null));
com.fr.third.javassist.bytecode.Bytecode code = new com.fr.third.javassist.bytecode.Bytecode(cp, 0, 0);
boolean isStatic = Modifier.isStatic(delegate.getModifiers());
com.fr.third.javassist.CtClass deleClass = delegate.getDeclaringClass();
com.fr.third.javassist.CtClass[] params = delegate.getParameterTypes();
int s;
if (isStatic) {
s = code.addLoadParameters(params, 0);
code.addInvokestatic(deleClass, methodName, desc);
}
else {
code.addLoad(0, deleClass);
s = code.addLoadParameters(params, 1);
code.addInvokespecial(deleClass, methodName, desc);
}
code.addReturn(delegate.getReturnType());
code.setMaxLocals(++s);
code.setMaxStack(s < 2 ? 2 : s); // for a 2-word return value
minfo.setCodeAttribute(code.toCodeAttribute());
// a stack map is not needed.
return new com.fr.third.javassist.CtMethod(minfo, declaring);
}
/**
* Creates a wrapped method. The wrapped method receives parameters
* in the form of an array of <code>Object</code>.
*
* <p>The body of the created method is a copy of the body of the method
* specified by <code>body</code>. However, it is wrapped in
* parameter-conversion code.
*
* <p>The method specified by <code>body</code> must have this singature:
*
* <ul><code>Object method(Object[] params, &lt;type&gt; cvalue)
* </code></ul>
*
* <p>The type of the <code>cvalue</code> depends on
* <code>constParam</code>.
* If <code>constParam</code> is <code>null</code>, the signature
* must be:
*
* <ul><code>Object method(Object[] params)</code></ul>
*
* <p>The method body copied from <code>body</code> is wrapped in
* parameter-conversion code, which converts parameters specified by
* <code>parameterTypes</code> into an array of <code>Object</code>.
* The returned value is also converted from the <code>Object</code>
* type to the type specified by <code>returnType</code>. Thus,
* the resulting method body is as follows:
*
* <ul><pre>Object[] params = new Object[] { p0, p1, ... };
* &lt;<i>type</i>&gt; cvalue = &lt;<i>constant-value</i>&gt;;
* <i>... copied method body ...</i>
* Object result = &lt;<i>returned value</i>&gt;
* return (<i>&lt;returnType&gt;</i>)result;
* </pre></ul>
*
* <p>The variables <code>p0</code>, <code>p2</code>, ... represent
* formal parameters of the created method.
* The value of <code>cvalue</code> is specified by
* <code>constParam</code>.
*
* <p>If the type of a parameter or a returned value is a primitive
* type, then the value is converted into a wrapper object such as
* <code>java.lang.Integer</code>. If the type of the returned value
* is <code>void</code>, the returned value is discarded.
*
* <p><i>Example:</i>
*
* <ul><pre>ClassPool pool = ... ;
* CtClass vec = pool.makeClass("intVector");
* vec.setSuperclass(pool.get("java.util.Vector"));
* CtMethod addMethod = pool.getMethod("Sample", "add0");
*
* CtClass[] argTypes = { CtClass.intType };
* CtMethod m = CtNewMethod.wrapped(CtClass.voidType, "add", argTypes,
* null, addMethod, null, vec);
* vec.addMethod(m);</pre></ul>
*
* <p>where the class <code>Sample</code> is as follows:
*
* <ul><pre>public class Sample extends java.util.Vector {
* public Object add0(Object[] args) {
* super.addElement(args[0]);
* return null;
* }
* }</pre></ul>
*
* <p>This program produces a class <code>intVector</code>:
*
* <ul><pre>public class intVector extends java.util.Vector {
* public void add(int p0) {
* Object[] args = new Object[] { p0 };
* // begin of the copied body
* super.addElement(args[0]);
* Object result = null;
* // end
* }
* }</pre></ul>
*
* <p>Note that the type of the parameter to <code>add()</code> depends
* only on the value of <code>argTypes</code> passed to
* <code>CtNewMethod.wrapped()</code>. Thus, it is easy to
* modify this program to produce a
* <code>StringVector</code> class, which is a vector containing
* only <code>String</code> objects, and other vector classes.
*
* @param returnType the type of the returned value.
* @param mname the method name.
* @param parameterTypes a list of the parameter types.
* @param exceptionTypes a list of the exception types.
* @param body the method body
* (must not be a static method).
* @param constParam the constant parameter
* (maybe <code>null</code>).
* @param declaring the class to which the created method is
* added.
*/
public static com.fr.third.javassist.CtMethod wrapped(com.fr.third.javassist.CtClass returnType,
String mname,
com.fr.third.javassist.CtClass[] parameterTypes,
com.fr.third.javassist.CtClass[] exceptionTypes,
CtMethod body, ConstParameter constParam,
CtClass declaring)
throws CannotCompileException
{
return CtNewWrappedMethod.wrapped(returnType, mname, parameterTypes,
exceptionTypes, body, constParam, declaring);
}
}

67
fine-javassist/src/main/java/com/fr/third/javassist/CtNewNestedClass.java

@ -1,67 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.ClassFile;
import com.fr.third.javassist.bytecode.AccessFlag;
import com.fr.third.javassist.bytecode.InnerClassesAttribute;
/**
* A newly created public nested class.
*/
class CtNewNestedClass extends com.fr.third.javassist.CtNewClass {
CtNewNestedClass(String realName, ClassPool cp, boolean isInterface,
com.fr.third.javassist.CtClass superclass) {
super(realName, cp, isInterface, superclass);
}
/**
* This method does not change the STATIC bit. The original value is kept.
*/
public void setModifiers(int mod) {
mod = mod & ~Modifier.STATIC;
super.setModifiers(mod);
updateInnerEntry(mod, getName(), this, true);
}
private static void updateInnerEntry(int mod, String name, com.fr.third.javassist.CtClass clazz, boolean outer) {
ClassFile cf = clazz.getClassFile2();
InnerClassesAttribute ica = (InnerClassesAttribute)cf.getAttribute(
InnerClassesAttribute.tag);
if (ica == null)
return;
int n = ica.tableLength();
for (int i = 0; i < n; i++)
if (name.equals(ica.innerClass(i))) {
int acc = ica.accessFlags(i) & AccessFlag.STATIC;
ica.setAccessFlags(i, mod | acc);
String outName = ica.outerClass(i);
if (outName != null && outer)
try {
CtClass parent = clazz.getClassPool().get(outName);
updateInnerEntry(mod, name, parent, false);
}
catch (NotFoundException e) {
throw new RuntimeException("cannot find the declaring class: "
+ outName);
}
break;
}
}
}

103
fine-javassist/src/main/java/com/fr/third/javassist/CtNewWrappedConstructor.java

@ -1,103 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.ClassFile;
import com.fr.third.javassist.CtMethod.ConstParameter;
class CtNewWrappedConstructor extends CtNewWrappedMethod {
private static final int PASS_NONE = com.fr.third.javassist.CtNewConstructor.PASS_NONE;
// private static final int PASS_ARRAY = CtNewConstructor.PASS_ARRAY;
private static final int PASS_PARAMS = CtNewConstructor.PASS_PARAMS;
public static com.fr.third.javassist.CtConstructor wrapped(com.fr.third.javassist.CtClass[] parameterTypes,
com.fr.third.javassist.CtClass[] exceptionTypes,
int howToCallSuper,
com.fr.third.javassist.CtMethod body,
ConstParameter constParam,
com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
try {
com.fr.third.javassist.CtConstructor cons = new CtConstructor(parameterTypes, declaring);
cons.setExceptionTypes(exceptionTypes);
com.fr.third.javassist.bytecode.Bytecode code = makeBody(declaring, declaring.getClassFile2(),
howToCallSuper, body,
parameterTypes, constParam);
cons.getMethodInfo2().setCodeAttribute(code.toCodeAttribute());
// a stack map table is not needed.
return cons;
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
}
protected static com.fr.third.javassist.bytecode.Bytecode makeBody(com.fr.third.javassist.CtClass declaring, ClassFile classfile,
int howToCallSuper,
CtMethod wrappedBody,
com.fr.third.javassist.CtClass[] parameters,
ConstParameter cparam)
throws CannotCompileException
{
int stacksize, stacksize2;
int superclazz = classfile.getSuperclassId();
com.fr.third.javassist.bytecode.Bytecode code = new com.fr.third.javassist.bytecode.Bytecode(classfile.getConstPool(), 0, 0);
code.setMaxLocals(false, parameters, 0);
code.addAload(0);
if (howToCallSuper == PASS_NONE) {
stacksize = 1;
code.addInvokespecial(superclazz, "<init>", "()V");
}
else if (howToCallSuper == PASS_PARAMS) {
stacksize = code.addLoadParameters(parameters, 1) + 1;
code.addInvokespecial(superclazz, "<init>",
com.fr.third.javassist.bytecode.Descriptor.ofConstructor(parameters));
}
else {
stacksize = compileParameterList(code, parameters, 1);
String desc;
if (cparam == null) {
stacksize2 = 2;
desc = ConstParameter.defaultConstDescriptor();
}
else {
stacksize2 = cparam.compile(code) + 2;
desc = cparam.constDescriptor();
}
if (stacksize < stacksize2)
stacksize = stacksize2;
code.addInvokespecial(superclazz, "<init>", desc);
}
if (wrappedBody == null)
code.add(com.fr.third.javassist.bytecode.Bytecode.RETURN);
else {
stacksize2 = makeBody0(declaring, classfile, wrappedBody,
false, parameters, CtClass.voidType,
cparam, code);
if (stacksize < stacksize2)
stacksize = stacksize2;
}
code.setMaxStack(stacksize);
return code;
}
}

199
fine-javassist/src/main/java/com/fr/third/javassist/CtNewWrappedMethod.java

@ -1,199 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.SyntheticAttribute;
import com.fr.third.javassist.compiler.JvstCodeGen;
import java.util.Hashtable;
import com.fr.third.javassist.CtMethod.ConstParameter;
class CtNewWrappedMethod {
private static final String addedWrappedMethod = "_added_m$";
public static com.fr.third.javassist.CtMethod wrapped(com.fr.third.javassist.CtClass returnType, String mname,
com.fr.third.javassist.CtClass[] parameterTypes,
com.fr.third.javassist.CtClass[] exceptionTypes,
com.fr.third.javassist.CtMethod body, ConstParameter constParam,
com.fr.third.javassist.CtClass declaring)
throws com.fr.third.javassist.CannotCompileException
{
com.fr.third.javassist.CtMethod mt = new com.fr.third.javassist.CtMethod(returnType, mname, parameterTypes,
declaring);
mt.setModifiers(body.getModifiers());
try {
mt.setExceptionTypes(exceptionTypes);
}
catch (NotFoundException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
com.fr.third.javassist.bytecode.Bytecode code = makeBody(declaring, declaring.getClassFile2(), body,
parameterTypes, returnType, constParam);
com.fr.third.javassist.bytecode.MethodInfo minfo = mt.getMethodInfo2();
minfo.setCodeAttribute(code.toCodeAttribute());
// a stack map has been already created.
return mt;
}
static com.fr.third.javassist.bytecode.Bytecode makeBody(com.fr.third.javassist.CtClass clazz, com.fr.third.javassist.bytecode.ClassFile classfile,
com.fr.third.javassist.CtMethod wrappedBody,
com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass returnType,
ConstParameter cparam)
throws com.fr.third.javassist.CannotCompileException
{
boolean isStatic = Modifier.isStatic(wrappedBody.getModifiers());
com.fr.third.javassist.bytecode.Bytecode code = new com.fr.third.javassist.bytecode.Bytecode(classfile.getConstPool(), 0, 0);
int stacksize = makeBody0(clazz, classfile, wrappedBody, isStatic,
parameters, returnType, cparam, code);
code.setMaxStack(stacksize);
code.setMaxLocals(isStatic, parameters, 0);
return code;
}
/* The generated method body does not need a stack map table
* because it does not contain a branch instruction.
*/
protected static int makeBody0(com.fr.third.javassist.CtClass clazz, com.fr.third.javassist.bytecode.ClassFile classfile,
com.fr.third.javassist.CtMethod wrappedBody,
boolean isStatic, com.fr.third.javassist.CtClass[] parameters,
com.fr.third.javassist.CtClass returnType, ConstParameter cparam,
com.fr.third.javassist.bytecode.Bytecode code)
throws com.fr.third.javassist.CannotCompileException
{
if (!(clazz instanceof com.fr.third.javassist.CtClassType))
throw new com.fr.third.javassist.CannotCompileException("bad declaring class"
+ clazz.getName());
if (!isStatic)
code.addAload(0);
int stacksize = compileParameterList(code, parameters,
(isStatic ? 0 : 1));
int stacksize2;
String desc;
if (cparam == null) {
stacksize2 = 0;
desc = ConstParameter.defaultDescriptor();
}
else {
stacksize2 = cparam.compile(code);
desc = cparam.descriptor();
}
checkSignature(wrappedBody, desc);
String bodyname;
try {
bodyname = addBodyMethod((com.fr.third.javassist.CtClassType)clazz, classfile,
wrappedBody);
/* if an exception is thrown below, the method added above
* should be removed. (future work :<)
*/
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
if (isStatic)
code.addInvokestatic(com.fr.third.javassist.bytecode.Bytecode.THIS, bodyname, desc);
else
code.addInvokespecial(com.fr.third.javassist.bytecode.Bytecode.THIS, bodyname, desc);
compileReturn(code, returnType); // consumes 2 stack entries
if (stacksize < stacksize2 + 2)
stacksize = stacksize2 + 2;
return stacksize;
}
private static void checkSignature(com.fr.third.javassist.CtMethod wrappedBody,
String descriptor)
throws com.fr.third.javassist.CannotCompileException
{
if (!descriptor.equals(wrappedBody.getMethodInfo2().getDescriptor()))
throw new com.fr.third.javassist.CannotCompileException(
"wrapped method with a bad signature: "
+ wrappedBody.getDeclaringClass().getName()
+ '.' + wrappedBody.getName());
}
private static String addBodyMethod(com.fr.third.javassist.CtClassType clazz,
com.fr.third.javassist.bytecode.ClassFile classfile,
com.fr.third.javassist.CtMethod src)
throws com.fr.third.javassist.bytecode.BadBytecode, CannotCompileException
{
Hashtable bodies = clazz.getHiddenMethods();
String bodyname = (String)bodies.get(src);
if (bodyname == null) {
do {
bodyname = addedWrappedMethod + clazz.getUniqueNumber();
} while (classfile.getMethod(bodyname) != null);
com.fr.third.javassist.ClassMap map = new ClassMap();
map.put(src.getDeclaringClass().getName(), clazz.getName());
com.fr.third.javassist.bytecode.MethodInfo body = new com.fr.third.javassist.bytecode.MethodInfo(classfile.getConstPool(),
bodyname, src.getMethodInfo2(),
map);
int acc = body.getAccessFlags();
body.setAccessFlags(com.fr.third.javassist.bytecode.AccessFlag.setPrivate(acc));
body.addAttribute(new SyntheticAttribute(classfile.getConstPool()));
// a stack map is copied. rebuilding it is not needed.
classfile.addMethod(body);
bodies.put(src, bodyname);
CtMember.Cache cache = clazz.hasMemberCache();
if (cache != null)
cache.addMethod(new CtMethod(body, clazz));
}
return bodyname;
}
/* compileParameterList() returns the stack size used
* by the produced code.
*
* @param regno the index of the local variable in which
* the first argument is received.
* (0: static method, 1: regular method.)
*/
static int compileParameterList(com.fr.third.javassist.bytecode.Bytecode code,
com.fr.third.javassist.CtClass[] params, int regno) {
return JvstCodeGen.compileParameterList(code, params, regno);
}
/*
* The produced codes cosume 1 or 2 stack entries.
*/
private static void compileReturn(com.fr.third.javassist.bytecode.Bytecode code, com.fr.third.javassist.CtClass type) {
if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType)type;
if (pt != CtClass.voidType) {
String wrapper = pt.getWrapperName();
code.addCheckcast(wrapper);
code.addInvokevirtual(wrapper, pt.getGetMethodName(),
pt.getGetMethodDescriptor());
}
code.addOpcode(pt.getReturnOp());
}
else {
code.addCheckcast(type);
code.addOpcode(com.fr.third.javassist.bytecode.Bytecode.ARETURN);
}
}
}

112
fine-javassist/src/main/java/com/fr/third/javassist/CtPrimitiveType.java

@ -1,112 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
/**
* An instance of <code>CtPrimitiveType</code> represents a primitive type.
* It is obtained from <code>CtClass</code>.
*/
public final class CtPrimitiveType extends CtClass {
private char descriptor;
private String wrapperName;
private String getMethodName;
private String mDescriptor;
private int returnOp;
private int arrayType;
private int dataSize;
CtPrimitiveType(String name, char desc, String wrapper,
String methodName, String mDesc, int opcode, int atype,
int size) {
super(name);
descriptor = desc;
wrapperName = wrapper;
getMethodName = methodName;
mDescriptor = mDesc;
returnOp = opcode;
arrayType = atype;
dataSize = size;
}
/**
* Returns <code>true</code> if this object represents a primitive
* Java type: boolean, byte, char, short, int, long, float, double,
* or void.
*/
public boolean isPrimitive() { return true; }
/**
* Returns the modifiers for this type.
* For decoding, use <code>javassist.Modifier</code>.
*
* @see Modifier
*/
public int getModifiers() {
return Modifier.PUBLIC | Modifier.FINAL;
}
/**
* Returns the descriptor representing this type.
* For example, if the type is int, then the descriptor is I.
*/
public char getDescriptor() { return descriptor; }
/**
* Returns the name of the wrapper class.
* For example, if the type is int, then the wrapper class is
* <code>java.lang.Integer</code>.
*/
public String getWrapperName() { return wrapperName; }
/**
* Returns the name of the method for retrieving the value
* from the wrapper object.
* For example, if the type is int, then the method name is
* <code>intValue</code>.
*/
public String getGetMethodName() { return getMethodName; }
/**
* Returns the descriptor of the method for retrieving the value
* from the wrapper object.
* For example, if the type is int, then the method descriptor is
* <code>()I</code>.
*/
public String getGetMethodDescriptor() { return mDescriptor; }
/**
* Returns the opcode for returning a value of the type.
* For example, if the type is int, then the returned opcode is
* <code>javassit.bytecode.Opcode.IRETURN</code>.
*/
public int getReturnOp() { return returnOp; }
/**
* Returns the array-type code representing the type.
* It is used for the newarray instruction.
* For example, if the type is int, then this method returns
* <code>javassit.bytecode.Opcode.T_INT</code>.
*/
public int getArrayType() { return arrayType; }
/**
* Returns the data size of the primitive type.
* If the type is long or double, this method returns 2.
* Otherwise, it returns 1.
*/
public int getDataSize() { return dataSize; }
}

433
fine-javassist/src/main/java/com/fr/third/javassist/Loader.java

@ -1,433 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.*;
import java.util.Hashtable;
import java.util.Vector;
import java.security.ProtectionDomain;
/**
* The class loader for Javassist.
*
* <p>This is a sample class loader using <code>ClassPool</code>.
* Unlike a regular class loader, this class loader obtains bytecode
* from a <code>ClassPool</code>.
*
* <p>Note that Javassist can be used without this class loader; programmers
* can define their own versions of class loader. They can run
* a program even without any user-defined class loader if that program
* is statically translated with Javassist.
* This class loader is just provided as a utility class.
*
* <p>Suppose that an instance of <code>MyTranslator</code> implementing
* the interface <code>Translator</code> is responsible for modifying
* class files.
* The startup program of an application using <code>MyTranslator</code>
* should be something like this:
*
* <ul><pre>
* import javassist.*;
*
* public class Main {
* public static void main(String[] args) throws Throwable {
* MyTranslator myTrans = new MyTranslator();
* ClassPool cp = ClassPool.getDefault();
* Loader cl = new Loader(cp);
* cl.addTranslator(cp, myTrans);
* cl.run("MyApp", args);
* }
* }
* </pre></ul>
*
* <p>Class <code>MyApp</code> is the main program of the application.
*
* <p>This program should be executed as follows:
*
* <ul><pre>
* % java Main <i>arg1</i> <i>arg2</i>...
* </pre></ul>
*
* <p>It modifies the class <code>MyApp</code> with a <code>MyTranslator</code>
* object before the JVM loads it.
* Then it calls <code>main()</code> in <code>MyApp</code> with arguments
* <i>arg1</i>, <i>arg2</i>, ...
*
* <p>This program execution is equivalent to:
*
* <ul><pre>
* % java MyApp <i>arg1</i> <i>arg2</i>...
* </pre></ul>
*
* <p>except that classes are translated by <code>MyTranslator</code>
* at load time.
*
* <p>If only a particular class must be modified when it is loaded,
* the startup program can be simpler; <code>MyTranslator</code> is
* unnecessary. For example, if only a class <code>test.Rectangle</code>
* is modified, the <code>main()</code> method above will be the following:
*
* <ul><pre>
* ClassPool cp = ClassPool.getDefault();
* Loader cl = new Loader(cp);
* CtClass ct = cp.get("test.Rectangle");
* ct.setSuperclass(cp.get("test.Point"));
* cl.run("MyApp", args);</pre></ul>
*
* <p>This program changes the super class of the <code>test.Rectangle</code>
* class.
*
* <p><b>Note 1:</b>
*
* <p>This class loader does not allow the users to intercept the loading
* of <code>java.*</code> and <code>javax.*</code> classes (and
* <code>sun.*</code>, <code>org.xml.*</code>, ...) unless
* <code>Loader.doDelegation</code> is <code>false</code>. This is because
* the JVM prohibits a user class loader from loading a system class.
* Also see Note 2.
* If this behavior is not appropriate, a subclass of <code>Loader</code>
* must be defined and <code>loadClassByDelegation()</code> must be overridden.
*
* <p><b>Note 2:</b>
*
* <p>If classes are loaded with different class loaders, they belong to
* separate name spaces. If class <code>C</code> is loaded by a class
* loader <code>CL</code>, all classes that the class <code>C</code>
* refers to are also loaded by <code>CL</code>. However, if <code>CL</code>
* delegates the loading of the class <code>C</code> to <code>CL'</code>,
* then those classes that the class <code>C</code> refers to
* are loaded by a parent class loader <code>CL'</code>
* instead of <code>CL</code>.
*
* <p>If an object of class <code>C</code> is assigned
* to a variable of class <code>C</code> belonging to a different name
* space, then a <code>ClassCastException</code> is thrown.
*
* <p>Because of the fact above, this loader delegates only the loading of
* <code>javassist.Loader</code>
* and classes included in package <code>java.*</code> and
* <code>javax.*</code> to the parent class
* loader. Other classes are directly loaded by this loader.
*
* <p>For example, suppose that <code>java.lang.String</code> would be loaded
* by this loader while <code>java.io.File</code> is loaded by the parent
* class loader. If the constructor of <code>java.io.File</code> is called
* with an instance of <code>java.lang.String</code>, then it may throw
* an exception since it accepts an instance of only the
* <code>java.lang.String</code> loaded by the parent class loader.
*
* @see com.fr.third.javassist.ClassPool
* @see Translator
*/
public class Loader extends ClassLoader {
private Hashtable notDefinedHere; // must be atomic.
private Vector notDefinedPackages; // must be atomic.
private com.fr.third.javassist.ClassPool source;
private Translator translator;
private ProtectionDomain domain;
/**
* Specifies the algorithm of class loading.
*
* <p>This class loader uses the parent class loader for
* <code>java.*</code> and <code>javax.*</code> classes.
* If this variable <code>doDelegation</code>
* is <code>false</code>, this class loader does not delegate those
* classes to the parent class loader.
*
* <p>The default value is <code>true</code>.
*/
public boolean doDelegation = true;
/**
* Creates a new class loader.
*/
public Loader() {
this(null);
}
/**
* Creates a new class loader.
*
* @param cp the source of class files.
*/
public Loader(com.fr.third.javassist.ClassPool cp) {
init(cp);
}
/**
* Creates a new class loader
* using the specified parent class loader for delegation.
*
* @param parent the parent class loader.
* @param cp the source of class files.
*/
public Loader(ClassLoader parent, com.fr.third.javassist.ClassPool cp) {
super(parent);
init(cp);
}
private void init(com.fr.third.javassist.ClassPool cp) {
notDefinedHere = new Hashtable();
notDefinedPackages = new Vector();
source = cp;
translator = null;
domain = null;
delegateLoadingOf("javassist.Loader");
}
/**
* Records a class so that the loading of that class is delegated
* to the parent class loader.
*
* <p>If the given class name ends with <code>.</code> (dot), then
* that name is interpreted as a package name. All the classes
* in that package and the sub packages are delegated.
*/
public void delegateLoadingOf(String classname) {
if (classname.endsWith("."))
notDefinedPackages.addElement(classname);
else
notDefinedHere.put(classname, this);
}
/**
* Sets the protection domain for the classes handled by this class
* loader. Without registering an appropriate protection domain,
* the program loaded by this loader will not work with a security
* manager or a signed jar file.
*/
public void setDomain(ProtectionDomain d) {
domain = d;
}
/**
* Sets the soruce <code>ClassPool</code>.
*/
public void setClassPool(com.fr.third.javassist.ClassPool cp) {
source = cp;
}
/**
* Adds a translator, which is called whenever a class is loaded.
*
* @param cp the <code>ClassPool</code> object for obtaining
* a class file.
* @param t a translator.
* @throws NotFoundException if <code>t.start()</code> throws an exception.
* @throws com.fr.third.javassist.CannotCompileException if <code>t.start()</code> throws an exception.
*/
public void addTranslator(ClassPool cp, Translator t)
throws NotFoundException, CannotCompileException {
source = cp;
translator = t;
t.start(cp);
}
/**
* Loads a class with an instance of <code>Loader</code>
* and calls <code>main()</code> of that class.
*
* <p>This method calls <code>run()</code>.
*
* @param args command line parameters.
* <ul>
* <code>args[0]</code> is the class name to be loaded.
* <br><code>args[1..n]</code> are parameters passed
* to the target <code>main()</code>.
* </ul>
*
* @see Loader#run(String[])
*/
public static void main(String[] args) throws Throwable {
Loader cl = new Loader();
cl.run(args);
}
/**
* Loads a class and calls <code>main()</code> in that class.
*
* @param args command line parameters.
* <ul>
* <code>args[0]</code> is the class name to be loaded.
* <br><code>args[1..n]</code> are parameters passed
* to the target <code>main()</code>.
* </ul>
*/
public void run(String[] args) throws Throwable {
int n = args.length - 1;
if (n >= 0) {
String[] args2 = new String[n];
for (int i = 0; i < n; ++i)
args2[i] = args[i + 1];
run(args[0], args2);
}
}
/**
* Loads a class and calls <code>main()</code> in that class.
*
* @param classname the loaded class.
* @param args parameters passed to <code>main()</code>.
*/
public void run(String classname, String[] args) throws Throwable {
Class c = loadClass(classname);
try {
c.getDeclaredMethod("main", new Class[] { String[].class }).invoke(
null,
new Object[] { args });
}
catch (java.lang.reflect.InvocationTargetException e) {
throw e.getTargetException();
}
}
/**
* Requests the class loader to load a class.
*/
protected Class loadClass(String name, boolean resolve)
throws ClassFormatError, ClassNotFoundException {
name = name.intern();
synchronized (name) {
Class c = findLoadedClass(name);
if (c == null)
c = loadClassByDelegation(name);
if (c == null)
c = findClass(name);
if (c == null)
c = delegateToParent(name);
if (resolve)
resolveClass(c);
return c;
}
}
/**
* Finds the specified class using <code>ClassPath</code>.
* If the source throws an exception, this returns null.
*
* <p>This method can be overridden by a subclass of
* <code>Loader</code>. Note that the overridden method must not throw
* an exception when it just fails to find a class file.
*
* @return null if the specified class could not be found.
* @throws ClassNotFoundException if an exception is thrown while
* obtaining a class file.
*/
protected Class findClass(String name) throws ClassNotFoundException {
byte[] classfile;
try {
if (source != null) {
if (translator != null)
translator.onLoad(source, name);
try {
classfile = source.get(name).toBytecode();
}
catch (NotFoundException e) {
return null;
}
}
else {
String jarname = "/" + name.replace('.', '/') + ".class";
InputStream in = this.getClass().getResourceAsStream(jarname);
if (in == null)
return null;
classfile = com.fr.third.javassist.ClassPoolTail.readStream(in);
}
}
catch (Exception e) {
throw new ClassNotFoundException(
"caught an exception while obtaining a class file for "
+ name, e);
}
int i = name.lastIndexOf('.');
if (i != -1) {
String pname = name.substring(0, i);
if (getPackage(pname) == null)
try {
definePackage(
pname, null, null, null, null, null, null, null);
}
catch (IllegalArgumentException e) {
// ignore. maybe the package object for the same
// name has been created just right away.
}
}
if (domain == null)
return defineClass(name, classfile, 0, classfile.length);
else
return defineClass(name, classfile, 0, classfile.length, domain);
}
protected Class loadClassByDelegation(String name)
throws ClassNotFoundException
{
/* The swing components must be loaded by a system
* class loader.
* javax.swing.UIManager loads a (concrete) subclass
* of LookAndFeel by a system class loader and cast
* an instance of the class to LookAndFeel for
* (maybe) a security reason. To avoid failure of
* type conversion, LookAndFeel must not be loaded
* by this class loader.
*/
Class c = null;
if (doDelegation)
if (name.startsWith("java.")
|| name.startsWith("javax.")
|| name.startsWith("sun.")
|| name.startsWith("com.sun.")
|| name.startsWith("org.w3c.")
|| name.startsWith("org.xml.")
|| notDelegated(name))
c = delegateToParent(name);
return c;
}
private boolean notDelegated(String name) {
if (notDefinedHere.get(name) != null)
return true;
int n = notDefinedPackages.size();
for (int i = 0; i < n; ++i)
if (name.startsWith((String)notDefinedPackages.elementAt(i)))
return true;
return false;
}
protected Class delegateToParent(String classname)
throws ClassNotFoundException
{
ClassLoader cl = getParent();
if (cl != null)
return cl.loadClass(classname);
else
return findSystemClass(classname);
}
}

96
fine-javassist/src/main/java/com/fr/third/javassist/LoaderClassPath.java

@ -1,96 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.InputStream;
import java.net.URL;
import java.lang.ref.WeakReference;
/**
* A class search-path representing a class loader.
*
* <p>It is used for obtaining a class file from the given
* class loader by <code>getResourceAsStream()</code>.
* The <code>LoaderClassPath</code> refers to the class loader through
* <code>WeakReference</code>. If the class loader is garbage collected,
* the other search pathes are examined.
*
* <p>The given class loader must have both <code>getResourceAsStream()</code>
* and <code>getResource()</code>.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*
* @see com.fr.third.javassist.ClassPool#insertClassPath(com.fr.third.javassist.ClassPath)
* @see ClassPool#appendClassPath(com.fr.third.javassist.ClassPath)
* @see ClassClassPath
*/
public class LoaderClassPath implements ClassPath {
private WeakReference clref;
/**
* Creates a search path representing a class loader.
*/
public LoaderClassPath(ClassLoader cl) {
clref = new WeakReference(cl);
}
public String toString() {
Object cl = null;
if (clref != null)
cl = clref.get();
return cl == null ? "<null>" : cl.toString();
}
/**
* Obtains a class file from the class loader.
* This method calls <code>getResourceAsStream(String)</code>
* on the class loader.
*/
public InputStream openClassfile(String classname) {
String cname = classname.replace('.', '/') + ".class";
ClassLoader cl = (ClassLoader)clref.get();
if (cl == null)
return null; // not found
else
return cl.getResourceAsStream(cname);
}
/**
* Obtains the URL of the specified class file.
* This method calls <code>getResource(String)</code>
* on the class loader.
*
* @return null if the class file could not be found.
*/
public URL find(String classname) {
String cname = classname.replace('.', '/') + ".class";
ClassLoader cl = (ClassLoader)clref.get();
if (cl == null)
return null; // not found
else
return cl.getResource(cname);
}
/**
* Closes this class path.
*/
public void close() {
clref = null;
}
}

219
fine-javassist/src/main/java/com/fr/third/javassist/Modifier.java

@ -1,219 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import com.fr.third.javassist.bytecode.AccessFlag;
/**
* The Modifier class provides static methods and constants to decode
* class and member access modifiers. The constant values are equivalent
* to the corresponding values in <code>javassist.bytecode.AccessFlag</code>.
*
* <p>All the methods/constants in this class are compatible with
* ones in <code>java.lang.reflect.Modifier</code>.
*
* @see CtClass#getModifiers()
*/
public class Modifier {
public static final int PUBLIC = AccessFlag.PUBLIC;
public static final int PRIVATE = AccessFlag.PRIVATE;
public static final int PROTECTED = AccessFlag.PROTECTED;
public static final int STATIC = AccessFlag.STATIC;
public static final int FINAL = AccessFlag.FINAL;
public static final int SYNCHRONIZED = AccessFlag.SYNCHRONIZED;
public static final int VOLATILE = AccessFlag.VOLATILE;
public static final int VARARGS = AccessFlag.VARARGS;
public static final int TRANSIENT = AccessFlag.TRANSIENT;
public static final int NATIVE = AccessFlag.NATIVE;
public static final int INTERFACE = AccessFlag.INTERFACE;
public static final int ABSTRACT = AccessFlag.ABSTRACT;
public static final int STRICT = AccessFlag.STRICT;
public static final int ANNOTATION = AccessFlag.ANNOTATION;
public static final int ENUM = AccessFlag.ENUM;
/**
* Returns true if the modifiers include the <tt>public</tt>
* modifier.
*/
public static boolean isPublic(int mod) {
return (mod & PUBLIC) != 0;
}
/**
* Returns true if the modifiers include the <tt>private</tt>
* modifier.
*/
public static boolean isPrivate(int mod) {
return (mod & PRIVATE) != 0;
}
/**
* Returns true if the modifiers include the <tt>protected</tt>
* modifier.
*/
public static boolean isProtected(int mod) {
return (mod & PROTECTED) != 0;
}
/**
* Returns true if the modifiers do not include either
* <tt>public</tt>, <tt>protected</tt>, or <tt>private</tt>.
*/
public static boolean isPackage(int mod) {
return (mod & (PUBLIC | PRIVATE | PROTECTED)) == 0;
}
/**
* Returns true if the modifiers include the <tt>static</tt>
* modifier.
*/
public static boolean isStatic(int mod) {
return (mod & STATIC) != 0;
}
/**
* Returns true if the modifiers include the <tt>final</tt>
* modifier.
*/
public static boolean isFinal(int mod) {
return (mod & FINAL) != 0;
}
/**
* Returns true if the modifiers include the <tt>synchronized</tt>
* modifier.
*/
public static boolean isSynchronized(int mod) {
return (mod & SYNCHRONIZED) != 0;
}
/**
* Returns true if the modifiers include the <tt>volatile</tt>
* modifier.
*/
public static boolean isVolatile(int mod) {
return (mod & VOLATILE) != 0;
}
/**
* Returns true if the modifiers include the <tt>transient</tt>
* modifier.
*/
public static boolean isTransient(int mod) {
return (mod & TRANSIENT) != 0;
}
/**
* Returns true if the modifiers include the <tt>native</tt>
* modifier.
*/
public static boolean isNative(int mod) {
return (mod & NATIVE) != 0;
}
/**
* Returns true if the modifiers include the <tt>interface</tt>
* modifier.
*/
public static boolean isInterface(int mod) {
return (mod & INTERFACE) != 0;
}
/**
* Returns true if the modifiers include the <tt>annotation</tt>
* modifier.
*
* @since 3.2
*/
public static boolean isAnnotation(int mod) {
return (mod & ANNOTATION) != 0;
}
/**
* Returns true if the modifiers include the <tt>enum</tt>
* modifier.
*
* @since 3.2
*/
public static boolean isEnum(int mod) {
return (mod & ENUM) != 0;
}
/**
* Returns true if the modifiers include the <tt>abstract</tt>
* modifier.
*/
public static boolean isAbstract(int mod) {
return (mod & ABSTRACT) != 0;
}
/**
* Returns true if the modifiers include the <tt>strictfp</tt>
* modifier.
*/
public static boolean isStrict(int mod) {
return (mod & STRICT) != 0;
}
/**
* Truns the public bit on. The protected and private bits are
* cleared.
*/
public static int setPublic(int mod) {
return (mod & ~(PRIVATE | PROTECTED)) | PUBLIC;
}
/**
* Truns the protected bit on. The protected and public bits are
* cleared.
*/
public static int setProtected(int mod) {
return (mod & ~(PRIVATE | PUBLIC)) | PROTECTED;
}
/**
* Truns the private bit on. The protected and private bits are
* cleared.
*/
public static int setPrivate(int mod) {
return (mod & ~(PROTECTED | PUBLIC)) | PRIVATE;
}
/**
* Clears the public, protected, and private bits.
*/
public static int setPackage(int mod) {
return (mod & ~(PROTECTED | PUBLIC | PRIVATE));
}
/**
* Clears a specified bit in <code>mod</code>.
*/
public static int clear(int mod, int clearBit) {
return mod & ~clearBit;
}
/**
* Return a string describing the access modifier flags in
* the specified modifier.
*
* @param mod modifier flags.
*/
public static String toString(int mod) {
return java.lang.reflect.Modifier.toString(mod);
}
}

30
fine-javassist/src/main/java/com/fr/third/javassist/NotFoundException.java

@ -1,30 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
/**
* Signals that something could not be found.
*/
public class NotFoundException extends Exception {
public NotFoundException(String msg) {
super(msg);
}
public NotFoundException(String msg, Exception e) {
super(msg + " because of " + e.toString());
}
}

212
fine-javassist/src/main/java/com/fr/third/javassist/SerialVersionUID.java

@ -1,212 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.*;
import java.lang.reflect.Modifier;
import com.fr.third.javassist.bytecode.ClassFile;
import java.util.*;
import java.security.*;
/**
* Utility for calculating serialVersionUIDs for Serializable classes.
*
* @author Bob Lee (crazybob@crazybob.org)
* @author modified by Shigeru Chiba
*/
public class SerialVersionUID {
/**
* Adds serialVersionUID if one does not already exist. Call this before
* modifying a class to maintain serialization compatability.
*/
public static void setSerialVersionUID(com.fr.third.javassist.CtClass clazz)
throws com.fr.third.javassist.CannotCompileException, com.fr.third.javassist.NotFoundException
{
// check for pre-existing field.
try {
clazz.getDeclaredField("serialVersionUID");
return;
}
catch (com.fr.third.javassist.NotFoundException e) {}
// check if the class is serializable.
if (!isSerializable(clazz))
return;
// add field with default value.
com.fr.third.javassist.CtField field = new com.fr.third.javassist.CtField(com.fr.third.javassist.CtClass.longType, "serialVersionUID",
clazz);
field.setModifiers(Modifier.PRIVATE | Modifier.STATIC |
Modifier.FINAL);
clazz.addField(field, calculateDefault(clazz) + "L");
}
/**
* Does the class implement Serializable?
*/
private static boolean isSerializable(com.fr.third.javassist.CtClass clazz)
throws NotFoundException
{
ClassPool pool = clazz.getClassPool();
return clazz.subtypeOf(pool.get("java.io.Serializable"));
}
/**
* Calculate default value. See Java Serialization Specification, Stream
* Unique Identifiers.
*/
static long calculateDefault(com.fr.third.javassist.CtClass clazz)
throws com.fr.third.javassist.CannotCompileException
{
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(bout);
ClassFile classFile = clazz.getClassFile();
// class name.
String javaName = javaName(clazz);
out.writeUTF(javaName);
com.fr.third.javassist.CtMethod[] methods = clazz.getDeclaredMethods();
// class modifiers.
int classMods = clazz.getModifiers();
if ((classMods & Modifier.INTERFACE) != 0)
if (methods.length > 0)
classMods = classMods | Modifier.ABSTRACT;
else
classMods = classMods & ~Modifier.ABSTRACT;
out.writeInt(classMods);
// interfaces.
String[] interfaces = classFile.getInterfaces();
for (int i = 0; i < interfaces.length; i++)
interfaces[i] = javaName(interfaces[i]);
Arrays.sort(interfaces);
for (int i = 0; i < interfaces.length; i++)
out.writeUTF(interfaces[i]);
// fields.
com.fr.third.javassist.CtField[] fields = clazz.getDeclaredFields();
Arrays.sort(fields, new Comparator() {
public int compare(Object o1, Object o2) {
com.fr.third.javassist.CtField field1 = (com.fr.third.javassist.CtField)o1;
com.fr.third.javassist.CtField field2 = (com.fr.third.javassist.CtField)o2;
return field1.getName().compareTo(field2.getName());
}
});
for (int i = 0; i < fields.length; i++) {
com.fr.third.javassist.CtField field = (CtField) fields[i];
int mods = field.getModifiers();
if (((mods & Modifier.PRIVATE) == 0) ||
((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) {
out.writeUTF(field.getName());
out.writeInt(mods);
out.writeUTF(field.getFieldInfo2().getDescriptor());
}
}
// static initializer.
if (classFile.getStaticInitializer() != null) {
out.writeUTF("<clinit>");
out.writeInt(Modifier.STATIC);
out.writeUTF("()V");
}
// constructors.
com.fr.third.javassist.CtConstructor[] constructors = clazz.getDeclaredConstructors();
Arrays.sort(constructors, new Comparator() {
public int compare(Object o1, Object o2) {
com.fr.third.javassist.CtConstructor c1 = (com.fr.third.javassist.CtConstructor)o1;
com.fr.third.javassist.CtConstructor c2 = (com.fr.third.javassist.CtConstructor)o2;
return c1.getMethodInfo2().getDescriptor().compareTo(
c2.getMethodInfo2().getDescriptor());
}
});
for (int i = 0; i < constructors.length; i++) {
CtConstructor constructor = constructors[i];
int mods = constructor.getModifiers();
if ((mods & Modifier.PRIVATE) == 0) {
out.writeUTF("<init>");
out.writeInt(mods);
out.writeUTF(constructor.getMethodInfo2()
.getDescriptor().replace('/', '.'));
}
}
// methods.
Arrays.sort(methods, new Comparator() {
public int compare(Object o1, Object o2) {
com.fr.third.javassist.CtMethod m1 = (com.fr.third.javassist.CtMethod)o1;
com.fr.third.javassist.CtMethod m2 = (com.fr.third.javassist.CtMethod)o2;
int value = m1.getName().compareTo(m2.getName());
if (value == 0)
value = m1.getMethodInfo2().getDescriptor()
.compareTo(m2.getMethodInfo2().getDescriptor());
return value;
}
});
for (int i = 0; i < methods.length; i++) {
CtMethod method = methods[i];
int mods = method.getModifiers()
& (Modifier.PUBLIC | Modifier.PRIVATE
| Modifier.PROTECTED | Modifier.STATIC
| Modifier.FINAL | Modifier.SYNCHRONIZED
| Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT);
if ((mods & Modifier.PRIVATE) == 0) {
out.writeUTF(method.getName());
out.writeInt(mods);
out.writeUTF(method.getMethodInfo2()
.getDescriptor().replace('/', '.'));
}
}
// calculate hash.
out.flush();
MessageDigest digest = MessageDigest.getInstance("SHA");
byte[] digested = digest.digest(bout.toByteArray());
long hash = 0;
for (int i = Math.min(digested.length, 8) - 1; i >= 0; i--)
hash = (hash << 8) | (digested[i] & 0xFF);
return hash;
}
catch (IOException e) {
throw new com.fr.third.javassist.CannotCompileException(e);
}
catch (NoSuchAlgorithmException e) {
throw new CannotCompileException(e);
}
}
private static String javaName(CtClass clazz) {
return com.fr.third.javassist.bytecode.Descriptor.toJavaName(com.fr.third.javassist.bytecode.Descriptor.toJvmName(clazz));
}
private static String javaName(String name) {
return com.fr.third.javassist.bytecode.Descriptor.toJavaName(com.fr.third.javassist.bytecode.Descriptor.toJvmName(name));
}
}

71
fine-javassist/src/main/java/com/fr/third/javassist/Translator.java

@ -1,71 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
/**
* An observer of <code>Loader</code>.
* The users can define a class implementing this
* interface and attach an instance of that class to a
* <code>Loader</code> object so that it can translate a class file
* when the class file is loaded into the JVM.
*
* @see com.fr.third.javassist.Loader#addTranslator(com.fr.third.javassist.ClassPool, Translator)
*/
public interface Translator {
/**
* Is invoked by a <code>Loader</code> for initialization
* when the object is attached to the <code>Loader</code> object.
* This method can be used for getting (for caching) some
* <code>CtClass</code> objects that will be accessed
* in <code>onLoad()</code> in <code>Translator</code>.
*
* @param pool the <code>ClassPool</code> that this translator
* should use.
* @see com.fr.third.javassist.Loader
* @throws com.fr.third.javassist.NotFoundException if a <code>CtClass</code> cannot be found.
* @throws com.fr.third.javassist.CannotCompileException if the initialization by this method
* fails.
*/
void start(com.fr.third.javassist.ClassPool pool)
throws com.fr.third.javassist.NotFoundException, com.fr.third.javassist.CannotCompileException;
/**
* Is invoked by a <code>Loader</code> for notifying that
* a class is loaded. The <code>Loader</code> calls
*
* <ul><pre>
* pool.get(classname).toBytecode()</pre></ul>
*
* to read the class file after <code>onLoad()</code> returns.
*
* <p><code>classname</code> may be the name of a class
* that has not been created yet.
* If so, <code>onLoad()</code> must create that class so that
* the <code>Loader</code> can read it after <code>onLoad()</code>
* returns.
*
* @param pool the <code>ClassPool</code> that this translator
* should use.
* @param classname the name of the class being loaded.
* @see Loader
* @throws com.fr.third.javassist.NotFoundException if a <code>CtClass</code> cannot be found.
* @throws com.fr.third.javassist.CannotCompileException if the code transformation
* by this method fails.
*/
void onLoad(ClassPool pool, String classname)
throws NotFoundException, CannotCompileException;
}

179
fine-javassist/src/main/java/com/fr/third/javassist/URLClassPath.java

@ -1,179 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist;
import java.io.*;
import java.net.*;
/**
* A class search-path specified with URL (http).
*
* @see com.fr.third.javassist.ClassPath
* @see com.fr.third.javassist.ClassPool#insertClassPath(com.fr.third.javassist.ClassPath)
* @see ClassPool#appendClassPath(com.fr.third.javassist.ClassPath)
*/
public class URLClassPath implements ClassPath {
protected String hostname;
protected int port;
protected String directory;
protected String packageName;
/**
* Creates a search path specified with URL (http).
*
* <p>This search path is used only if a requested
* class name starts with the name specified by <code>packageName</code>.
* If <code>packageName</code> is "org.javassist." and a requested class is
* "org.javassist.test.Main", then the given URL is used for loading that class.
* The <code>URLClassPath</code> obtains a class file from:
*
* <ul><pre>http://www.javassist.org:80/java/classes/org/javassist/test/Main.class
* </pre></ul>
*
* <p>Here, we assume that <code>host</code> is "www.javassist.org",
* <code>port</code> is 80, and <code>directory</code> is "/java/classes/".
*
* <p>If <code>packageName</code> is <code>null</code>, the URL is used
* for loading any class.
*
* @param host host name
* @param port port number
* @param directory directory name ending with "/".
* It can be "/" (root directory).
* It must start with "/".
* @param packageName package name. It must end with "." (dot).
*/
public URLClassPath(String host, int port,
String directory, String packageName) {
hostname = host;
this.port = port;
this.directory = directory;
this.packageName = packageName;
}
public String toString() {
return hostname + ":" + port + directory;
}
/**
* Opens a class file with http.
*
* @return null if the class file could not be found.
*/
public InputStream openClassfile(String classname) {
try {
URLConnection con = openClassfile0(classname);
if (con != null)
return con.getInputStream();
}
catch (IOException e) {}
return null; // not found
}
private URLConnection openClassfile0(String classname) throws IOException {
if (packageName == null || classname.startsWith(packageName)) {
String jarname
= directory + classname.replace('.', '/') + ".class";
return fetchClass0(hostname, port, jarname);
}
else
return null; // not found
}
/**
* Returns the URL.
*
* @return null if the class file could not be obtained.
*/
public URL find(String classname) {
try {
URLConnection con = openClassfile0(classname);
InputStream is = con.getInputStream();
if (is != null) {
is.close();
return con.getURL();
}
}
catch (IOException e) {}
return null;
}
/**
* Closes this class path.
*/
public void close() {}
/**
* Reads a class file on an http server.
*
* @param host host name
* @param port port number
* @param directory directory name ending with "/".
* It can be "/" (root directory).
* It must start with "/".
* @param classname fully-qualified class name
*/
public static byte[] fetchClass(String host, int port,
String directory, String classname)
throws IOException
{
byte[] b;
URLConnection con = fetchClass0(host, port,
directory + classname.replace('.', '/') + ".class");
int size = con.getContentLength();
InputStream s = con.getInputStream();
try {
if (size <= 0)
b = com.fr.third.javassist.ClassPoolTail.readStream(s);
else {
b = new byte[size];
int len = 0;
do {
int n = s.read(b, len, size - len);
if (n < 0)
throw new IOException("the stream was closed: "
+ classname);
len += n;
} while (len < size);
}
}
finally {
s.close();
}
return b;
}
private static URLConnection fetchClass0(String host, int port,
String filename)
throws IOException
{
URL url;
try {
url = new URL("http", host, port, filename);
}
catch (MalformedURLException e) {
// should never reache here.
throw new IOException("invalid URL?");
}
URLConnection con = url.openConnection();
con.connect();
return con;
}
}

133
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AccessFlag.java

@ -1,133 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
/**
* A support class providing static methods and constants
* for access modifiers such as public, rivate, ...
*/
public class AccessFlag {
public static final int PUBLIC = 0x0001;
public static final int PRIVATE = 0x0002;
public static final int PROTECTED = 0x0004;
public static final int STATIC = 0x0008;
public static final int FINAL = 0x0010;
public static final int SYNCHRONIZED = 0x0020;
public static final int VOLATILE = 0x0040;
public static final int BRIDGE = 0x0040; // for method_info
public static final int TRANSIENT = 0x0080;
public static final int VARARGS = 0x0080; // for method_info
public static final int NATIVE = 0x0100;
public static final int INTERFACE = 0x0200;
public static final int ABSTRACT = 0x0400;
public static final int STRICT = 0x0800;
public static final int SYNTHETIC = 0x1000;
public static final int ANNOTATION = 0x2000;
public static final int ENUM = 0x4000;
public static final int SUPER = 0x0020;
// Note: 0x0020 is assigned to both ACC_SUPER and ACC_SYNCHRONIZED
// although java.lang.reflect.Modifier does not recognize ACC_SUPER.
/**
* Truns the public bit on. The protected and private bits are
* cleared.
*/
public static int setPublic(int accflags) {
return (accflags & ~(PRIVATE | PROTECTED)) | PUBLIC;
}
/**
* Truns the protected bit on. The protected and public bits are
* cleared.
*/
public static int setProtected(int accflags) {
return (accflags & ~(PRIVATE | PUBLIC)) | PROTECTED;
}
/**
* Truns the private bit on. The protected and private bits are
* cleared.
*/
public static int setPrivate(int accflags) {
return (accflags & ~(PROTECTED | PUBLIC)) | PRIVATE;
}
/**
* Clears the public, protected, and private bits.
*/
public static int setPackage(int accflags) {
return (accflags & ~(PROTECTED | PUBLIC | PRIVATE));
}
/**
* Returns true if the access flags include the public bit.
*/
public static boolean isPublic(int accflags) {
return (accflags & PUBLIC) != 0;
}
/**
* Returns true if the access flags include the protected bit.
*/
public static boolean isProtected(int accflags) {
return (accflags & PROTECTED) != 0;
}
/**
* Returns true if the access flags include the private bit.
*/
public static boolean isPrivate(int accflags) {
return (accflags & PRIVATE) != 0;
}
/**
* Returns true if the access flags include neither public, protected,
* or private.
*/
public static boolean isPackage(int accflags) {
return (accflags & (PROTECTED | PUBLIC | PRIVATE)) == 0;
}
/**
* Clears a specified bit in <code>accflags</code>.
*/
public static int clear(int accflags, int clearBit) {
return accflags & ~clearBit;
}
/**
* Converts a javassist.Modifier into
* a javassist.bytecode.AccessFlag.
*
* @param modifier javassist.Modifier
*/
public static int of(int modifier) {
return modifier;
}
/**
* Converts a javassist.bytecode.AccessFlag
* into a javassist.Modifier.
*
* @param accflags javassist.bytecode.Accessflag
*/
public static int toModifier(int accflags) {
return accflags;
}
}

161
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AnnotationDefaultAttribute.java

@ -1,161 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.bytecode.annotation.Annotation;
import com.fr.third.javassist.bytecode.annotation.AnnotationsWriter;
import com.fr.third.javassist.bytecode.annotation.MemberValue;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* A class representing <code>AnnotationDefault_attribute</code>.
*
* <p>For example, if you declare the following annotation type:
*
* <ul><pre>
* &#64;interface Author {
* String name() default "Shakespeare";
* int age() default 99;
* }
* </pre></ul>
*
* <p>The defautl values of <code>name</code> and <code>age</code>
* are stored as annotation default attributes in <code>Author.class</code>.
* The following code snippet obtains the default value of <code>name</code>:
*
* <ul><pre>
* ClassPool pool = ...
* CtClass cc = pool.get("Author");
* CtMethod cm = cc.getDeclaredMethod("age");
* MethodInfo minfo = cm.getMethodInfo();
* AnnotationDefaultAttribute ada
* = (AnnotationDefaultAttribute)
* minfo.getAttribute(AnnotationDefaultAttribute.tag);
* MemberValue value = ada.getDefaultValue()); // default value of age
* </pre></ul>
*
* <p>If the following statement is executed after the code above,
* the default value of age is set to 80:
*
* <ul><pre>
* ada.setDefaultValue(new IntegerMemberValue(minfo.getConstPool(), 80));
* </pre></ul>
*
* @see com.fr.third.javassist.bytecode.AnnotationsAttribute
* @see MemberValue
*/
public class AnnotationDefaultAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of the <code>AnnotationDefault</code> attribute.
*/
public static final String tag = "AnnotationDefault";
/**
* Constructs an <code>AnnotationDefault_attribute</code>.
*
* @param cp constant pool
* @param info the contents of this attribute. It does not
* include <code>attribute_name_index</code> or
* <code>attribute_length</code>.
*/
public AnnotationDefaultAttribute(com.fr.third.javassist.bytecode.ConstPool cp, byte[] info) {
super(cp, tag, info);
}
/**
* Constructs an empty <code>AnnotationDefault_attribute</code>.
* The default value can be set by <code>setDefaultValue()</code>.
*
* @param cp constant pool
* @see #setDefaultValue(MemberValue)
*/
public AnnotationDefaultAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
this(cp, new byte[] { 0, 0 });
}
/**
* @param n the attribute name.
*/
AnnotationDefaultAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Copies this attribute and returns a new copy.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
com.fr.third.javassist.bytecode.AnnotationsAttribute.Copier copier
= new com.fr.third.javassist.bytecode.AnnotationsAttribute.Copier(info, constPool, newCp, classnames);
try {
copier.memberValue(0);
return new AnnotationDefaultAttribute(newCp, copier.close());
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
/**
* Obtains the default value represented by this attribute.
*/
public MemberValue getDefaultValue()
{
try {
return new AnnotationsAttribute.Parser(info, constPool)
.parseMemberValue();
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
/**
* Changes the default value represented by this attribute.
*
* @param value the new value.
* @see Annotation#createMemberValue(ConstPool, CtClass)
*/
public void setDefaultValue(MemberValue value) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
AnnotationsWriter writer = new AnnotationsWriter(output, constPool);
try {
value.write(writer);
writer.close();
}
catch (IOException e) {
throw new RuntimeException(e); // should never reach here.
}
set(output.toByteArray());
}
/**
* Returns a string representation of this object.
*/
public String toString() {
return getDefaultValue().toString();
}
}

703
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AnnotationsAttribute.java

@ -1,703 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.ByteArrayOutputStream;
import com.fr.third.javassist.bytecode.annotation.ClassMemberValue;
/**
* A class representing
* <code>RuntimeVisibleAnnotations_attribute</code> and
* <code>RuntimeInvisibleAnnotations_attribute</code>.
*
* <p>To obtain an AnnotationAttribute object, invoke
* <code>getAttribute(AnnotationsAttribute.visibleTag)</code>
* in <code>ClassFile</code>, <code>MethodInfo</code>,
* or <code>FieldInfo</code>. The obtained attribute is a
* runtime visible annotations attribute.
* If the parameter is
* <code>AnnotationAttribute.invisibleTag</code>, then the obtained
* attribute is a runtime invisible one.
*
* <p>For example,
*
* <ul><pre>
* import javassist.bytecode.annotation.Annotation;
* :
* CtMethod m = ... ;
* MethodInfo minfo = m.getMethodInfo();
* AnnotationsAttribute attr = (AnnotationsAttribute)
* minfo.getAttribute(AnnotationsAttribute.invisibleTag);
* Annotation an = attr.getAnnotation("Author");
* String s = ((StringMemberValue)an.getMemberValue("name")).getValue();
* System.out.println("@Author(name=" + s + ")");
* </pre></ul>
*
* <p>This code snippet retrieves an annotation of the type <code>Author</code>
* from the <code>MethodInfo</code> object specified by <code>minfo</code>.
* Then, it prints the value of <code>name</code> in <code>Author</code>.
*
* <p>If the annotation type <code>Author</code> is annotated by a meta annotation:
*
* <ul><pre>
* &#64;Retention(RetentionPolicy.RUNTIME)
* </pre></ul>
*
* <p>Then <code>Author</code> is visible at runtime. Therefore, the third
* statement of the code snippet above must be changed into:
*
* <ul><pre>
* AnnotationsAttribute attr = (AnnotationsAttribute)
* minfo.getAttribute(AnnotationsAttribute.visibleTag);
* </pre></ul>
*
* <p>The attribute tag must be <code>visibleTag</code> instead of
* <code>invisibleTag</code>.
*
* <p>If the member value of an annotation is not specified, the default value
* is used as that member value. If so, <code>getMemberValue()</code> in
* <code>Annotation</code> returns <code>null</code>
* since the default value is not included in the
* <code>AnnotationsAttribute</code>. It is included in the
* <code>AnnotationDefaultAttribute</code> of the method declared in the
* annotation type.
*
* <p>If you want to record a new AnnotationAttribute object, execute the
* following snippet:
*
* <ul><pre>
* ClassFile cf = ... ;
* ConstPool cp = cf.getConstPool();
* AnnotationsAttribute attr
* = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag);
* Annotation a = new Annotation("Author", cp);
* a.addMemberValue("name", new StringMemberValue("Chiba", cp));
* attr.setAnnotation(a);
* cf.addAttribute(attr);
* cf.setVersionToJava5();
* </pre></ul>
*
* <p>The last statement is necessary if the class file was produced by
* Javassist or JDK 1.4. Otherwise, it is not necessary.
*
* @see AnnotationDefaultAttribute
* @see com.fr.third.javassist.bytecode.annotation.Annotation
*/
public class AnnotationsAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of the <code>RuntimeVisibleAnnotations</code> attribute.
*/
public static final String visibleTag = "RuntimeVisibleAnnotations";
/**
* The name of the <code>RuntimeInvisibleAnnotations</code> attribute.
*/
public static final String invisibleTag = "RuntimeInvisibleAnnotations";
/**
* Constructs a <code>Runtime(In)VisibleAnnotations_attribute</code>.
*
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @param info the contents of this attribute. It does not
* include <code>attribute_name_index</code> or
* <code>attribute_length</code>.
*/
public AnnotationsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String attrname, byte[] info) {
super(cp, attrname, info);
}
/**
* Constructs an empty
* <code>Runtime(In)VisibleAnnotations_attribute</code>.
* A new annotation can be later added to the created attribute
* by <code>setAnnotations()</code>.
*
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @see #setAnnotations(com.fr.third.javassist.bytecode.annotation.Annotation[])
*/
public AnnotationsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String attrname) {
this(cp, attrname, new byte[] { 0, 0 });
}
/**
* @param n the attribute name.
*/
AnnotationsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Returns <code>num_annotations</code>.
*/
public int numAnnotations() {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, 0);
}
/**
* Copies this attribute and returns a new copy.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
Copier copier = new Copier(info, constPool, newCp, classnames);
try {
copier.annotationArray();
return new AnnotationsAttribute(newCp, getName(), copier.close());
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Parses the annotations and returns a data structure representing
* the annotation with the specified type. See also
* <code>getAnnotations()</code> as to the returned data structure.
*
* @param type the annotation type.
* @return null if the specified annotation type is not included.
* @see #getAnnotations()
*/
public com.fr.third.javassist.bytecode.annotation.Annotation getAnnotation(String type) {
com.fr.third.javassist.bytecode.annotation.Annotation[] annotations = getAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].getTypeName().equals(type))
return annotations[i];
}
return null;
}
/**
* Adds an annotation. If there is an annotation with the same type,
* it is removed before the new annotation is added.
*
* @param annotation the added annotation.
*/
public void addAnnotation(com.fr.third.javassist.bytecode.annotation.Annotation annotation) {
String type = annotation.getTypeName();
com.fr.third.javassist.bytecode.annotation.Annotation[] annotations = getAnnotations();
for (int i = 0; i < annotations.length; i++) {
if (annotations[i].getTypeName().equals(type)) {
annotations[i] = annotation;
setAnnotations(annotations);
return;
}
}
com.fr.third.javassist.bytecode.annotation.Annotation[] newlist = new com.fr.third.javassist.bytecode.annotation.Annotation[annotations.length + 1];
System.arraycopy(annotations, 0, newlist, 0, annotations.length);
newlist[annotations.length] = annotation;
setAnnotations(newlist);
}
/**
* Parses the annotations and returns a data structure representing
* that parsed annotations. Note that changes of the node values of the
* returned tree are not reflected on the annotations represented by
* this object unless the tree is copied back to this object by
* <code>setAnnotations()</code>.
*
* @see #setAnnotations(com.fr.third.javassist.bytecode.annotation.Annotation[])
*/
public com.fr.third.javassist.bytecode.annotation.Annotation[] getAnnotations() {
try {
return new Parser(info, constPool).parseAnnotations();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Changes the annotations represented by this object according to
* the given array of <code>Annotation</code> objects.
*
* @param annotations the data structure representing the
* new annotations.
*/
public void setAnnotations(com.fr.third.javassist.bytecode.annotation.Annotation[] annotations) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
com.fr.third.javassist.bytecode.annotation.AnnotationsWriter writer = new com.fr.third.javassist.bytecode.annotation.AnnotationsWriter(output, constPool);
try {
int n = annotations.length;
writer.numAnnotations(n);
for (int i = 0; i < n; ++i)
annotations[i].write(writer);
writer.close();
}
catch (IOException e) {
throw new RuntimeException(e); // should never reach here.
}
set(output.toByteArray());
}
/**
* Changes the annotations. A call to this method is equivalent to:
* <ul><pre>setAnnotations(new Annotation[] { annotation })</pre></ul>
*
* @param annotation the data structure representing
* the new annotation.
*/
public void setAnnotation(com.fr.third.javassist.bytecode.annotation.Annotation annotation) {
setAnnotations(new com.fr.third.javassist.bytecode.annotation.Annotation[] { annotation });
}
/**
* @param oldname a JVM class name.
* @param newname a JVM class name.
*/
void renameClass(String oldname, String newname) {
HashMap map = new HashMap();
map.put(oldname, newname);
renameClass(map);
}
void renameClass(Map classnames) {
Renamer renamer = new Renamer(info, getConstPool(), classnames);
try {
renamer.annotationArray();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
void getRefClasses(Map classnames) { renameClass(classnames); }
/**
* Returns a string representation of this object.
*/
public String toString() {
com.fr.third.javassist.bytecode.annotation.Annotation[] a = getAnnotations();
StringBuilder sbuf = new StringBuilder();
int i = 0;
while (i < a.length) {
sbuf.append(a[i++].toString());
if (i != a.length)
sbuf.append(", ");
}
return sbuf.toString();
}
static class Walker {
byte[] info;
Walker(byte[] attrInfo) {
info = attrInfo;
}
final void parameters() throws Exception {
int numParam = info[0] & 0xff;
parameters(numParam, 1);
}
void parameters(int numParam, int pos) throws Exception {
for (int i = 0; i < numParam; ++i)
pos = annotationArray(pos);
}
final void annotationArray() throws Exception {
annotationArray(0);
}
final int annotationArray(int pos) throws Exception {
int num = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos);
return annotationArray(pos + 2, num);
}
int annotationArray(int pos, int num) throws Exception {
for (int i = 0; i < num; ++i)
pos = annotation(pos);
return pos;
}
final int annotation(int pos) throws Exception {
int type = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos);
int numPairs = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 2);
return annotation(pos + 4, type, numPairs);
}
int annotation(int pos, int type, int numPairs) throws Exception {
for (int j = 0; j < numPairs; ++j)
pos = memberValuePair(pos);
return pos;
}
final int memberValuePair(int pos) throws Exception {
int nameIndex = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos);
return memberValuePair(pos + 2, nameIndex);
}
int memberValuePair(int pos, int nameIndex) throws Exception {
return memberValue(pos);
}
final int memberValue(int pos) throws Exception {
int tag = info[pos] & 0xff;
if (tag == 'e') {
int typeNameIndex = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 1);
int constNameIndex = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 3);
enumMemberValue(pos, typeNameIndex, constNameIndex);
return pos + 5;
}
else if (tag == 'c') {
int index = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 1);
classMemberValue(pos, index);
return pos + 3;
}
else if (tag == '@')
return annotationMemberValue(pos + 1);
else if (tag == '[') {
int num = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 1);
return arrayMemberValue(pos + 3, num);
}
else { // primitive types or String.
int index = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 1);
constValueMember(tag, index);
return pos + 3;
}
}
void constValueMember(int tag, int index) throws Exception {}
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
throws Exception {
}
void classMemberValue(int pos, int index) throws Exception {}
int annotationMemberValue(int pos) throws Exception {
return annotation(pos);
}
int arrayMemberValue(int pos, int num) throws Exception {
for (int i = 0; i < num; ++i) {
pos = memberValue(pos);
}
return pos;
}
}
static class Renamer extends Walker {
com.fr.third.javassist.bytecode.ConstPool cpool;
Map classnames;
/**
* Constructs a renamer. It renames some class names
* into the new names specified by <code>map</code>.
*
* @param info the annotations attribute.
* @param cp the constant pool.
* @param map pairs of replaced and substituted class names.
* It can be null.
*/
Renamer(byte[] info, com.fr.third.javassist.bytecode.ConstPool cp, Map map) {
super(info);
cpool = cp;
classnames = map;
}
int annotation(int pos, int type, int numPairs) throws Exception {
renameType(pos - 4, type);
return super.annotation(pos, type, numPairs);
}
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
throws Exception
{
renameType(pos + 1, typeNameIndex);
super.enumMemberValue(pos, typeNameIndex, constNameIndex);
}
void classMemberValue(int pos, int index) throws Exception {
renameType(pos + 1, index);
super.classMemberValue(pos, index);
}
private void renameType(int pos, int index) {
String name = cpool.getUtf8Info(index);
String newName = com.fr.third.javassist.bytecode.Descriptor.rename(name, classnames);
if (!name.equals(newName)) {
int index2 = cpool.addUtf8Info(newName);
ByteArray.write16bit(index2, info, pos);
}
}
}
static class Copier extends Walker {
ByteArrayOutputStream output;
com.fr.third.javassist.bytecode.annotation.AnnotationsWriter writer;
com.fr.third.javassist.bytecode.ConstPool srcPool, destPool;
Map classnames;
/**
* Constructs a copier. This copier renames some class names
* into the new names specified by <code>map</code> when it copies
* an annotation attribute.
*
* @param info the source attribute.
* @param src the constant pool of the source class.
* @param dest the constant pool of the destination class.
* @param map pairs of replaced and substituted class names.
* It can be null.
*/
Copier(byte[] info, com.fr.third.javassist.bytecode.ConstPool src, com.fr.third.javassist.bytecode.ConstPool dest, Map map) {
super(info);
output = new ByteArrayOutputStream();
writer = new com.fr.third.javassist.bytecode.annotation.AnnotationsWriter(output, dest);
srcPool = src;
destPool = dest;
classnames = map;
}
byte[] close() throws IOException {
writer.close();
return output.toByteArray();
}
void parameters(int numParam, int pos) throws Exception {
writer.numParameters(numParam);
super.parameters(numParam, pos);
}
int annotationArray(int pos, int num) throws Exception {
writer.numAnnotations(num);
return super.annotationArray(pos, num);
}
int annotation(int pos, int type, int numPairs) throws Exception {
writer.annotation(copyType(type), numPairs);
return super.annotation(pos, type, numPairs);
}
int memberValuePair(int pos, int nameIndex) throws Exception {
writer.memberValuePair(copy(nameIndex));
return super.memberValuePair(pos, nameIndex);
}
void constValueMember(int tag, int index) throws Exception {
writer.constValueIndex(tag, copy(index));
super.constValueMember(tag, index);
}
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
throws Exception
{
writer.enumConstValue(copyType(typeNameIndex), copy(constNameIndex));
super.enumMemberValue(pos, typeNameIndex, constNameIndex);
}
void classMemberValue(int pos, int index) throws Exception {
writer.classInfoIndex(copyType(index));
super.classMemberValue(pos, index);
}
int annotationMemberValue(int pos) throws Exception {
writer.annotationValue();
return super.annotationMemberValue(pos);
}
int arrayMemberValue(int pos, int num) throws Exception {
writer.arrayValue(num);
return super.arrayMemberValue(pos, num);
}
/**
* Copies a constant pool entry into the destination constant pool
* and returns the index of the copied entry.
*
* @param srcIndex the index of the copied entry into the source
* constant pool.
* @return the index of the copied item into the destination
* constant pool.
*/
int copy(int srcIndex) {
return srcPool.copy(srcIndex, destPool, classnames);
}
/**
* Copies a constant pool entry into the destination constant pool
* and returns the index of the copied entry. That entry must be
* a Utf8Info representing a class name in the L<class name>; form.
*
* @param srcIndex the index of the copied entry into the source
* constant pool.
* @return the index of the copied item into the destination
* constant pool.
*/
int copyType(int srcIndex) {
String name = srcPool.getUtf8Info(srcIndex);
String newName = Descriptor.rename(name, classnames);
return destPool.addUtf8Info(newName);
}
}
static class Parser extends Walker {
com.fr.third.javassist.bytecode.ConstPool pool;
com.fr.third.javassist.bytecode.annotation.Annotation[][] allParams; // all parameters
com.fr.third.javassist.bytecode.annotation.Annotation[] allAnno; // all annotations
com.fr.third.javassist.bytecode.annotation.Annotation currentAnno; // current annotation
com.fr.third.javassist.bytecode.annotation.MemberValue currentMember; // current member
/**
* Constructs a parser. This parser constructs a parse tree of
* the annotations.
*
* @param info the attribute.
* @param src the constant pool.
*/
Parser(byte[] info, com.fr.third.javassist.bytecode.ConstPool cp) {
super(info);
pool = cp;
}
com.fr.third.javassist.bytecode.annotation.Annotation[][] parseParameters() throws Exception {
parameters();
return allParams;
}
com.fr.third.javassist.bytecode.annotation.Annotation[] parseAnnotations() throws Exception {
annotationArray();
return allAnno;
}
com.fr.third.javassist.bytecode.annotation.MemberValue parseMemberValue() throws Exception {
memberValue(0);
return currentMember;
}
void parameters(int numParam, int pos) throws Exception {
com.fr.third.javassist.bytecode.annotation.Annotation[][] params = new com.fr.third.javassist.bytecode.annotation.Annotation[numParam][];
for (int i = 0; i < numParam; ++i) {
pos = annotationArray(pos);
params[i] = allAnno;
}
allParams = params;
}
int annotationArray(int pos, int num) throws Exception {
com.fr.third.javassist.bytecode.annotation.Annotation[] array = new com.fr.third.javassist.bytecode.annotation.Annotation[num];
for (int i = 0; i < num; ++i) {
pos = annotation(pos);
array[i] = currentAnno;
}
allAnno = array;
return pos;
}
int annotation(int pos, int type, int numPairs) throws Exception {
currentAnno = new com.fr.third.javassist.bytecode.annotation.Annotation(type, pool);
return super.annotation(pos, type, numPairs);
}
int memberValuePair(int pos, int nameIndex) throws Exception {
pos = super.memberValuePair(pos, nameIndex);
currentAnno.addMemberValue(nameIndex, currentMember);
return pos;
}
void constValueMember(int tag, int index) throws Exception {
com.fr.third.javassist.bytecode.annotation.MemberValue m;
ConstPool cp = pool;
switch (tag) {
case 'B' :
m = new com.fr.third.javassist.bytecode.annotation.ByteMemberValue(index, cp);
break;
case 'C' :
m = new com.fr.third.javassist.bytecode.annotation.CharMemberValue(index, cp);
break;
case 'D' :
m = new com.fr.third.javassist.bytecode.annotation.DoubleMemberValue(index, cp);
break;
case 'F' :
m = new com.fr.third.javassist.bytecode.annotation.FloatMemberValue(index, cp);
break;
case 'I' :
m = new com.fr.third.javassist.bytecode.annotation.IntegerMemberValue(index, cp);
break;
case 'J' :
m = new com.fr.third.javassist.bytecode.annotation.LongMemberValue(index, cp);
break;
case 'S' :
m = new com.fr.third.javassist.bytecode.annotation.ShortMemberValue(index, cp);
break;
case 'Z' :
m = new com.fr.third.javassist.bytecode.annotation.BooleanMemberValue(index, cp);
break;
case 's' :
m = new com.fr.third.javassist.bytecode.annotation.StringMemberValue(index, cp);
break;
default :
throw new RuntimeException("unknown tag:" + tag);
}
currentMember = m;
super.constValueMember(tag, index);
}
void enumMemberValue(int pos, int typeNameIndex, int constNameIndex)
throws Exception
{
currentMember = new com.fr.third.javassist.bytecode.annotation.EnumMemberValue(typeNameIndex,
constNameIndex, pool);
super.enumMemberValue(pos, typeNameIndex, constNameIndex);
}
void classMemberValue(int pos, int index) throws Exception {
currentMember = new ClassMemberValue(index, pool);
super.classMemberValue(pos, index);
}
int annotationMemberValue(int pos) throws Exception {
com.fr.third.javassist.bytecode.annotation.Annotation anno = currentAnno;
pos = super.annotationMemberValue(pos);
currentMember = new com.fr.third.javassist.bytecode.annotation.AnnotationMemberValue(currentAnno, pool);
currentAnno = anno;
return pos;
}
int arrayMemberValue(int pos, int num) throws Exception {
com.fr.third.javassist.bytecode.annotation.ArrayMemberValue amv = new com.fr.third.javassist.bytecode.annotation.ArrayMemberValue(pool);
com.fr.third.javassist.bytecode.annotation.MemberValue[] elements = new com.fr.third.javassist.bytecode.annotation.MemberValue[num];
for (int i = 0; i < num; ++i) {
pos = memberValue(pos);
elements[i] = currentMember;
}
amv.setValue(elements);
currentMember = amv;
return pos;
}
}
}

289
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/AttributeInfo.java

@ -1,289 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.List;
import java.util.Iterator;
// Note: if you define a new subclass of AttributeInfo, then
// update AttributeInfo.read(), .copy(), and (maybe) write().
/**
* <code>attribute_info</code> structure.
*/
public class AttributeInfo {
protected com.fr.third.javassist.bytecode.ConstPool constPool;
int name;
byte[] info;
protected AttributeInfo(com.fr.third.javassist.bytecode.ConstPool cp, int attrname, byte[] attrinfo) {
constPool = cp;
name = attrname;
info = attrinfo;
}
protected AttributeInfo(com.fr.third.javassist.bytecode.ConstPool cp, String attrname) {
this(cp, attrname, (byte[])null);
}
/**
* Constructs an <code>attribute_info</code> structure.
*
* @param cp constant pool table
* @param attrname attribute name
* @param attrinfo <code>info</code> field
* of <code>attribute_info</code> structure.
*/
public AttributeInfo(com.fr.third.javassist.bytecode.ConstPool cp, String attrname, byte[] attrinfo) {
this(cp, cp.addUtf8Info(attrname), attrinfo);
}
protected AttributeInfo(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
constPool = cp;
name = n;
int len = in.readInt();
info = new byte[len];
if (len > 0)
in.readFully(info);
}
static AttributeInfo read(com.fr.third.javassist.bytecode.ConstPool cp, DataInputStream in)
throws IOException
{
int name = in.readUnsignedShort();
String nameStr = cp.getUtf8Info(name);
if (nameStr.charAt(0) < 'L') {
if (nameStr.equals(AnnotationDefaultAttribute.tag))
return new AnnotationDefaultAttribute(cp, name, in);
else if (nameStr.equals(BootstrapMethodsAttribute.tag))
return new BootstrapMethodsAttribute(cp, name, in);
else if (nameStr.equals(CodeAttribute.tag))
return new CodeAttribute(cp, name, in);
else if (nameStr.equals(ConstantAttribute.tag))
return new ConstantAttribute(cp, name, in);
else if (nameStr.equals(DeprecatedAttribute.tag))
return new DeprecatedAttribute(cp, name, in);
else if (nameStr.equals(EnclosingMethodAttribute.tag))
return new EnclosingMethodAttribute(cp, name, in);
else if (nameStr.equals(ExceptionsAttribute.tag))
return new ExceptionsAttribute(cp, name, in);
else if (nameStr.equals(InnerClassesAttribute.tag))
return new InnerClassesAttribute(cp, name, in);
}
else {
/* Note that the names of Annotations attributes begin with 'R'.
*/
if (nameStr.equals(LineNumberAttribute.tag))
return new LineNumberAttribute(cp, name, in);
else if (nameStr.equals(LocalVariableAttribute.tag))
return new LocalVariableAttribute(cp, name, in);
else if (nameStr.equals(LocalVariableTypeAttribute.tag))
return new LocalVariableTypeAttribute(cp, name, in);
else if (nameStr.equals(AnnotationsAttribute.visibleTag)
|| nameStr.equals(AnnotationsAttribute.invisibleTag)) {
// RuntimeVisibleAnnotations or RuntimeInvisibleAnnotations
return new AnnotationsAttribute(cp, name, in);
}
else if (nameStr.equals(ParameterAnnotationsAttribute.visibleTag)
|| nameStr.equals(ParameterAnnotationsAttribute.invisibleTag))
return new ParameterAnnotationsAttribute(cp, name, in);
else if (nameStr.equals(SignatureAttribute.tag))
return new SignatureAttribute(cp, name, in);
else if (nameStr.equals(SourceFileAttribute.tag))
return new SourceFileAttribute(cp, name, in);
else if (nameStr.equals(SyntheticAttribute.tag))
return new SyntheticAttribute(cp, name, in);
else if (nameStr.equals(com.fr.third.javassist.bytecode.StackMap.tag))
return new StackMap(cp, name, in);
else if (nameStr.equals(StackMapTable.tag))
return new StackMapTable(cp, name, in);
}
return new AttributeInfo(cp, name, in);
}
/**
* Returns an attribute name.
*/
public String getName() {
return constPool.getUtf8Info(name);
}
/**
* Returns a constant pool table.
*/
public com.fr.third.javassist.bytecode.ConstPool getConstPool() { return constPool; }
/**
* Returns the length of this <code>attribute_info</code>
* structure.
* The returned value is <code>attribute_length + 6</code>.
*/
public int length() {
return info.length + 6;
}
/**
* Returns the <code>info</code> field
* of this <code>attribute_info</code> structure.
*
* <p>This method is not available if the object is an instance
* of <code>CodeAttribute</code>.
*/
public byte[] get() { return info; }
/**
* Sets the <code>info</code> field
* of this <code>attribute_info</code> structure.
*
* <p>This method is not available if the object is an instance
* of <code>CodeAttribute</code>.
*/
public void set(byte[] newinfo) { info = newinfo; }
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
int s = info.length;
byte[] srcInfo = info;
byte[] newInfo = new byte[s];
for (int i = 0; i < s; ++i)
newInfo[i] = srcInfo[i];
return new AttributeInfo(newCp, getName(), newInfo);
}
void write(DataOutputStream out) throws IOException {
out.writeShort(name);
out.writeInt(info.length);
if (info.length > 0)
out.write(info);
}
static int getLength(ArrayList list) {
int size = 0;
int n = list.size();
for (int i = 0; i < n; ++i) {
AttributeInfo attr = (AttributeInfo)list.get(i);
size += attr.length();
}
return size;
}
static AttributeInfo lookup(ArrayList list, String name) {
if (list == null)
return null;
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
AttributeInfo ai = (AttributeInfo)iterator.next();
if (ai.getName().equals(name))
return ai;
}
return null; // no such attribute
}
static synchronized void remove(ArrayList list, String name) {
if (list == null)
return;
ListIterator iterator = list.listIterator();
while (iterator.hasNext()) {
AttributeInfo ai = (AttributeInfo)iterator.next();
if (ai.getName().equals(name))
iterator.remove();
}
}
static void writeAll(ArrayList list, DataOutputStream out)
throws IOException
{
if (list == null)
return;
int n = list.size();
for (int i = 0; i < n; ++i) {
AttributeInfo attr = (AttributeInfo)list.get(i);
attr.write(out);
}
}
static ArrayList copyAll(ArrayList list, ConstPool cp) {
if (list == null)
return null;
ArrayList newList = new ArrayList();
int n = list.size();
for (int i = 0; i < n; ++i) {
AttributeInfo attr = (AttributeInfo)list.get(i);
newList.add(attr.copy(cp, null));
}
return newList;
}
/* The following two methods are used to implement
* ClassFile.renameClass().
* Only CodeAttribute, LocalVariableAttribute,
* AnnotationsAttribute, and SignatureAttribute
* override these methods.
*/
void renameClass(String oldname, String newname) {}
void renameClass(Map classnames) {}
static void renameClass(List attributes, String oldname, String newname) {
Iterator iterator = attributes.iterator();
while (iterator.hasNext()) {
AttributeInfo ai = (AttributeInfo)iterator.next();
ai.renameClass(oldname, newname);
}
}
static void renameClass(List attributes, Map classnames) {
Iterator iterator = attributes.iterator();
while (iterator.hasNext()) {
AttributeInfo ai = (AttributeInfo)iterator.next();
ai.renameClass(classnames);
}
}
void getRefClasses(Map classnames) {}
static void getRefClasses(List attributes, Map classnames) {
Iterator iterator = attributes.iterator();
while (iterator.hasNext()) {
AttributeInfo ai = (AttributeInfo)iterator.next();
ai.getRefClasses(classnames);
}
}
}

40
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/BadBytecode.java

@ -1,40 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
/**
* Signals that a bad bytecode sequence has been found.
*/
public class BadBytecode extends Exception {
public BadBytecode(int opcode) {
super("bytecode " + opcode);
}
public BadBytecode(String msg) {
super(msg);
}
public BadBytecode(String msg, Throwable cause) {
super(msg, cause);
}
public BadBytecode(MethodInfo minfo, Throwable cause) {
super(minfo.toString() + " in "
+ minfo.getConstPool().getClassName()
+ ": " + cause.getMessage(), cause);
}
}

123
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/BootstrapMethodsAttribute.java

@ -1,123 +0,0 @@
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
public class BootstrapMethodsAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"BootstrapMethods"</code>.
*/
public static final String tag = "BootstrapMethods";
/**
* An element of <code>bootstrap_methods</code>.
*/
public static class BootstrapMethod {
/**
* Constructs an element of <code>bootstrap_methods</code>.
*
* @param method <code>bootstrap_method_ref</code>.
* @param args <code>bootstrap_arguments</code>.
*/
public BootstrapMethod(int method, int[] args) {
methodRef = method;
arguments = args;
}
/**
* <code>bootstrap_method_ref</code>.
* The value at this index must be a <code>CONSTANT_MethodHandle_info</code>.
*/
public int methodRef;
/**
* <code>bootstrap_arguments</code>.
*/
public int[] arguments;
}
BootstrapMethodsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a BootstrapMethods attribute.
*
* @param cp a constant pool table.
* @param methods the contents.
*/
public BootstrapMethodsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, BootstrapMethod[] methods) {
super(cp, tag);
int size = 2;
for (int i = 0; i < methods.length; i++)
size += 4 + methods[i].arguments.length * 2;
byte[] data = new byte[size];
com.fr.third.javassist.bytecode.ByteArray.write16bit(methods.length, data, 0); // num_bootstrap_methods
int pos = 2;
for (int i = 0; i < methods.length; i++) {
com.fr.third.javassist.bytecode.ByteArray.write16bit(methods[i].methodRef, data, pos);
com.fr.third.javassist.bytecode.ByteArray.write16bit(methods[i].arguments.length, data, pos + 2);
int[] args = methods[i].arguments;
pos += 4;
for (int k = 0; k < args.length; k++) {
com.fr.third.javassist.bytecode.ByteArray.write16bit(args[k], data, pos);
pos += 2;
}
}
set(data);
}
/**
* Obtains <code>bootstrap_methods</code> in this attribute.
*
* @return an array of <code>BootstrapMethod</code>. Since it
* is a fresh copy, modifying the returned array does not
* affect the original contents of this attribute.
*/
public BootstrapMethod[] getMethods() {
byte[] data = this.get();
int num = com.fr.third.javassist.bytecode.ByteArray.readU16bit(data, 0);
BootstrapMethod[] methods = new BootstrapMethod[num];
int pos = 2;
for (int i = 0; i < num; i++) {
int ref = com.fr.third.javassist.bytecode.ByteArray.readU16bit(data, pos);
int len = com.fr.third.javassist.bytecode.ByteArray.readU16bit(data, pos + 2);
int[] args = new int[len];
pos += 4;
for (int k = 0; k < len; k++) {
args[k] = ByteArray.readU16bit(data, pos);
pos += 2;
}
methods[i] = new BootstrapMethod(ref, args);
}
return methods;
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
BootstrapMethod[] methods = getMethods();
ConstPool thisCp = getConstPool();
for (int i = 0; i < methods.length; i++) {
BootstrapMethod m = methods[i];
m.methodRef = thisCp.copy(m.methodRef, newCp, classnames);
for (int k = 0; k < m.arguments.length; k++)
m.arguments[k] = thisCp.copy(m.arguments[k], newCp, classnames);
}
return new BootstrapMethodsAttribute(newCp, methods);
}
}

77
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ByteArray.java

@ -1,77 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
/**
* A collection of static methods for reading and writing a byte array.
*/
public class ByteArray {
/**
* Reads an unsigned 16bit integer at the index.
*/
public static int readU16bit(byte[] code, int index) {
return ((code[index] & 0xff) << 8) | (code[index + 1] & 0xff);
}
/**
* Reads a signed 16bit integer at the index.
*/
public static int readS16bit(byte[] code, int index) {
return (code[index] << 8) | (code[index + 1] & 0xff);
}
/**
* Writes a 16bit integer at the index.
*/
public static void write16bit(int value, byte[] code, int index) {
code[index] = (byte)(value >>> 8);
code[index + 1] = (byte)value;
}
/**
* Reads a 32bit integer at the index.
*/
public static int read32bit(byte[] code, int index) {
return (code[index] << 24) | ((code[index + 1] & 0xff) << 16)
| ((code[index + 2] & 0xff) << 8) | (code[index + 3] & 0xff);
}
/**
* Writes a 32bit integer at the index.
*/
public static void write32bit(int value, byte[] code, int index) {
code[index] = (byte)(value >>> 24);
code[index + 1] = (byte)(value >>> 16);
code[index + 2] = (byte)(value >>> 8);
code[index + 3] = (byte)value;
}
/**
* Copies a 32bit integer.
*
* @param src the source byte array.
* @param isrc the index into the source byte array.
* @param dest the destination byte array.
* @param idest the index into the destination byte array.
*/
static void copy32bit(byte[] src, int isrc, byte[] dest, int idest) {
dest[idest] = src[isrc];
dest[idest + 1] = src[isrc + 1];
dest[idest + 2] = src[isrc + 2];
dest[idest + 3] = src[isrc + 3];
}
}

194
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ByteStream.java

@ -1,194 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.OutputStream;
import java.io.IOException;
final class ByteStream extends OutputStream {
private byte[] buf;
private int count;
public ByteStream() { this(32); }
public ByteStream(int size) {
buf = new byte[size];
count = 0;
}
public int getPos() { return count; }
public int size() { return count; }
public void writeBlank(int len) {
enlarge(len);
count += len;
}
public void write(byte[] data) {
write(data, 0, data.length);
}
public void write(byte[] data, int off, int len) {
enlarge(len);
System.arraycopy(data, off, buf, count, len);
count += len;
}
public void write(int b) {
enlarge(1);
int oldCount = count;
buf[oldCount] = (byte)b;
count = oldCount + 1;
}
public void writeShort(int s) {
enlarge(2);
int oldCount = count;
buf[oldCount] = (byte)(s >>> 8);
buf[oldCount + 1] = (byte)s;
count = oldCount + 2;
}
public void writeInt(int i) {
enlarge(4);
int oldCount = count;
buf[oldCount] = (byte)(i >>> 24);
buf[oldCount + 1] = (byte)(i >>> 16);
buf[oldCount + 2] = (byte)(i >>> 8);
buf[oldCount + 3] = (byte)i;
count = oldCount + 4;
}
public void writeLong(long i) {
enlarge(8);
int oldCount = count;
buf[oldCount] = (byte)(i >>> 56);
buf[oldCount + 1] = (byte)(i >>> 48);
buf[oldCount + 2] = (byte)(i >>> 40);
buf[oldCount + 3] = (byte)(i >>> 32);
buf[oldCount + 4] = (byte)(i >>> 24);
buf[oldCount + 5] = (byte)(i >>> 16);
buf[oldCount + 6] = (byte)(i >>> 8);
buf[oldCount + 7] = (byte)i;
count = oldCount + 8;
}
public void writeFloat(float v) {
writeInt(Float.floatToIntBits(v));
}
public void writeDouble(double v) {
writeLong(Double.doubleToLongBits(v));
}
public void writeUTF(String s) {
int sLen = s.length();
int pos = count;
enlarge(sLen + 2);
byte[] buffer = buf;
buffer[pos++] = (byte)(sLen >>> 8);
buffer[pos++] = (byte)sLen;
for (int i = 0; i < sLen; ++i) {
char c = s.charAt(i);
if (0x01 <= c && c <= 0x7f)
buffer[pos++] = (byte)c;
else {
writeUTF2(s, sLen, i);
return;
}
}
count = pos;
}
private void writeUTF2(String s, int sLen, int offset) {
int size = sLen;
for (int i = offset; i < sLen; i++) {
int c = s.charAt(i);
if (c > 0x7ff)
size += 2; // 3 bytes code
else if (c == 0 || c > 0x7f)
++size; // 2 bytes code
}
if (size > 65535)
throw new RuntimeException(
"encoded string too long: " + sLen + size + " bytes");
enlarge(size + 2);
int pos = count;
byte[] buffer = buf;
buffer[pos] = (byte)(size >>> 8);
buffer[pos + 1] = (byte)size;
pos += 2 + offset;
for (int j = offset; j < sLen; ++j) {
int c = s.charAt(j);
if (0x01 <= c && c <= 0x7f)
buffer[pos++] = (byte) c;
else if (c > 0x07ff) {
buffer[pos] = (byte)(0xe0 | ((c >> 12) & 0x0f));
buffer[pos + 1] = (byte)(0x80 | ((c >> 6) & 0x3f));
buffer[pos + 2] = (byte)(0x80 | (c & 0x3f));
pos += 3;
}
else {
buffer[pos] = (byte)(0xc0 | ((c >> 6) & 0x1f));
buffer[pos + 1] = (byte)(0x80 | (c & 0x3f));
pos += 2;
}
}
count = pos;
}
public void write(int pos, int value) {
buf[pos] = (byte)value;
}
public void writeShort(int pos, int value) {
buf[pos] = (byte)(value >>> 8);
buf[pos + 1] = (byte)value;
}
public void writeInt(int pos, int value) {
buf[pos] = (byte)(value >>> 24);
buf[pos + 1] = (byte)(value >>> 16);
buf[pos + 2] = (byte)(value >>> 8);
buf[pos + 3] = (byte)value;
}
public byte[] toByteArray() {
byte[] buf2 = new byte[count];
System.arraycopy(buf, 0, buf2, 0, count);
return buf2;
}
public void writeTo(OutputStream out) throws IOException {
out.write(buf, 0, count);
}
public void enlarge(int delta) {
int newCount = count + delta;
if (newCount > buf.length) {
int newLen = buf.length << 1;
byte[] newBuf = new byte[newLen > newCount ? newLen : newCount];
System.arraycopy(buf, 0, newBuf, 0, count);
buf = newBuf;
}
}
}

1430
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Bytecode.java

File diff suppressed because it is too large Load Diff

909
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ClassFile.java

@ -1,909 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import com.fr.third.javassist.CannotCompileException;
import com.fr.third.javassist.CtClass;
/**
* <code>ClassFile</code> represents a Java <code>.class</code> file, which
* consists of a constant pool, methods, fields, and attributes.
*
* @see CtClass#getClassFile()
*/
public final class ClassFile {
int major, minor; // version number
ConstPool constPool;
int thisClass;
int accessFlags;
int superClass;
int[] interfaces;
ArrayList fields;
ArrayList methods;
ArrayList attributes;
String thisclassname; // not JVM-internal name
String[] cachedInterfaces;
String cachedSuperclass;
/**
* The major version number of class files
* for JDK 1.1.
*/
public static final int JAVA_1 = 45;
/**
* The major version number of class files
* for JDK 1.2.
*/
public static final int JAVA_2 = 46;
/**
* The major version number of class files
* for JDK 1.3.
*/
public static final int JAVA_3 = 47;
/**
* The major version number of class files
* for JDK 1.4.
*/
public static final int JAVA_4 = 48;
/**
* The major version number of class files
* for JDK 1.5.
*/
public static final int JAVA_5 = 49;
/**
* The major version number of class files
* for JDK 1.6.
*/
public static final int JAVA_6 = 50;
/**
* The major version number of class files
* for JDK 1.7.
*/
public static final int JAVA_7 = 51;
/**
* The major version number of class files
* for JDK 1.8.
*/
public static final int JAVA_8 = 52;
/**
* The major version number of class files created
* from scratch. The default value is 47 (JDK 1.3).
* It is 49 (JDK 1.5)
* if the JVM supports <code>java.lang.StringBuilder</code>.
* It is 50 (JDK 1.6)
* if the JVM supports <code>java.util.zip.DeflaterInputStream</code>.
* It is 51 (JDK 1.7)
* if the JVM supports <code>java.lang.invoke.CallSite</code>.
*/
public static int MAJOR_VERSION = JAVA_3;
static {
try {
Class.forName("java.lang.StringBuilder");
MAJOR_VERSION = JAVA_5;
Class.forName("java.util.zip.DeflaterInputStream");
MAJOR_VERSION = JAVA_6;
Class.forName("java.lang.invoke.CallSite");
MAJOR_VERSION = JAVA_7;
}
catch (Throwable t) {}
}
/**
* Constructs a class file from a byte stream.
*/
public ClassFile(DataInputStream in) throws IOException {
read(in);
}
/**
* Constructs a class file including no members.
*
* @param isInterface
* true if this is an interface. false if this is a class.
* @param classname
* a fully-qualified class name
* @param superclass
* a fully-qualified super class name
*/
public ClassFile(boolean isInterface, String classname, String superclass) {
major = MAJOR_VERSION;
minor = 0; // JDK 1.3 or later
constPool = new ConstPool(classname);
thisClass = constPool.getThisClassInfo();
if (isInterface)
accessFlags = AccessFlag.INTERFACE | AccessFlag.ABSTRACT;
else
accessFlags = AccessFlag.SUPER;
initSuperclass(superclass);
interfaces = null;
fields = new ArrayList();
methods = new ArrayList();
thisclassname = classname;
attributes = new ArrayList();
attributes.add(new SourceFileAttribute(constPool,
getSourcefileName(thisclassname)));
}
private void initSuperclass(String superclass) {
if (superclass != null) {
this.superClass = constPool.addClassInfo(superclass);
cachedSuperclass = superclass;
}
else {
this.superClass = constPool.addClassInfo("java.lang.Object");
cachedSuperclass = "java.lang.Object";
}
}
private static String getSourcefileName(String qname) {
int index = qname.lastIndexOf('.');
if (index >= 0)
qname = qname.substring(index + 1);
return qname + ".java";
}
/**
* Eliminates dead constant pool items. If a method or a field is removed,
* the constant pool items used by that method/field become dead items. This
* method recreates a constant pool.
*/
public void compact() {
ConstPool cp = compact0();
ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
minfo.compact(cp);
}
list = fields;
n = list.size();
for (int i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
finfo.compact(cp);
}
attributes = AttributeInfo.copyAll(attributes, cp);
constPool = cp;
}
private ConstPool compact0() {
ConstPool cp = new ConstPool(thisclassname);
thisClass = cp.getThisClassInfo();
String sc = getSuperclass();
if (sc != null)
superClass = cp.addClassInfo(getSuperclass());
if (interfaces != null) {
int n = interfaces.length;
for (int i = 0; i < n; ++i)
interfaces[i]
= cp.addClassInfo(constPool.getClassInfo(interfaces[i]));
}
return cp;
}
/**
* Discards all attributes, associated with both the class file and the
* members such as a code attribute and exceptions attribute. The unused
* constant pool entries are also discarded (a new packed constant pool is
* constructed).
*/
public void prune() {
ConstPool cp = compact0();
ArrayList newAttributes = new ArrayList();
AttributeInfo invisibleAnnotations
= getAttribute(AnnotationsAttribute.invisibleTag);
if (invisibleAnnotations != null) {
invisibleAnnotations = invisibleAnnotations.copy(cp, null);
newAttributes.add(invisibleAnnotations);
}
AttributeInfo visibleAnnotations
= getAttribute(AnnotationsAttribute.visibleTag);
if (visibleAnnotations != null) {
visibleAnnotations = visibleAnnotations.copy(cp, null);
newAttributes.add(visibleAnnotations);
}
AttributeInfo signature
= getAttribute(SignatureAttribute.tag);
if (signature != null) {
signature = signature.copy(cp, null);
newAttributes.add(signature);
}
ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
minfo.prune(cp);
}
list = fields;
n = list.size();
for (int i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
finfo.prune(cp);
}
attributes = newAttributes;
constPool = cp;
}
/**
* Returns a constant pool table.
*/
public ConstPool getConstPool() {
return constPool;
}
/**
* Returns true if this is an interface.
*/
public boolean isInterface() {
return (accessFlags & AccessFlag.INTERFACE) != 0;
}
/**
* Returns true if this is a final class or interface.
*/
public boolean isFinal() {
return (accessFlags & AccessFlag.FINAL) != 0;
}
/**
* Returns true if this is an abstract class or an interface.
*/
public boolean isAbstract() {
return (accessFlags & AccessFlag.ABSTRACT) != 0;
}
/**
* Returns access flags.
*
* @see AccessFlag
*/
public int getAccessFlags() {
return accessFlags;
}
/**
* Changes access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc) {
if ((acc & AccessFlag.INTERFACE) == 0)
acc |= AccessFlag.SUPER;
accessFlags = acc;
}
/**
* Returns access and property flags of this nested class.
* This method returns -1 if the class is not a nested class.
*
* <p>The returned value is obtained from <code>inner_class_access_flags</code>
* of the entry representing this nested class itself
* in <code>InnerClasses_attribute</code>>.
*/
public int getInnerAccessFlags() {
InnerClassesAttribute ica
= (InnerClassesAttribute)getAttribute(InnerClassesAttribute.tag);
if (ica == null)
return -1;
String name = getName();
int n = ica.tableLength();
for (int i = 0; i < n; ++i)
if (name.equals(ica.innerClass(i)))
return ica.accessFlags(i);
return -1;
}
/**
* Returns the class name.
*/
public String getName() {
return thisclassname;
}
/**
* Sets the class name. This method substitutes the new name for all
* occurrences of the old class name in the class file.
*/
public void setName(String name) {
renameClass(thisclassname, name);
}
/**
* Returns the super class name.
*/
public String getSuperclass() {
if (cachedSuperclass == null)
cachedSuperclass = constPool.getClassInfo(superClass);
return cachedSuperclass;
}
/**
* Returns the index of the constant pool entry representing the super
* class.
*/
public int getSuperclassId() {
return superClass;
}
/**
* Sets the super class.
*
* <p>
* The new super class should inherit from the old super class.
* This method modifies constructors so that they call constructors declared
* in the new super class.
*/
public void setSuperclass(String superclass) throws CannotCompileException {
if (superclass == null)
superclass = "java.lang.Object";
try {
this.superClass = constPool.addClassInfo(superclass);
ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
minfo.setSuperclass(superclass);
}
}
catch (BadBytecode e) {
throw new CannotCompileException(e);
}
cachedSuperclass = superclass;
}
/**
* Replaces all occurrences of a class name in the class file.
*
* <p>
* If class X is substituted for class Y in the class file, X and Y must
* have the same signature. If Y provides a method m(), X must provide it
* even if X inherits m() from the super class. If this fact is not
* guaranteed, the bytecode verifier may cause an error.
*
* @param oldname
* the replaced class name
* @param newname
* the substituted class name
*/
public final void renameClass(String oldname, String newname) {
ArrayList list;
int n;
if (oldname.equals(newname))
return;
if (oldname.equals(thisclassname))
thisclassname = newname;
oldname = Descriptor.toJvmName(oldname);
newname = Descriptor.toJvmName(newname);
constPool.renameClass(oldname, newname);
AttributeInfo.renameClass(attributes, oldname, newname);
list = methods;
n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
String desc = minfo.getDescriptor();
minfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
AttributeInfo.renameClass(minfo.getAttributes(), oldname, newname);
}
list = fields;
n = list.size();
for (int i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
String desc = finfo.getDescriptor();
finfo.setDescriptor(Descriptor.rename(desc, oldname, newname));
AttributeInfo.renameClass(finfo.getAttributes(), oldname, newname);
}
}
/**
* Replaces all occurrences of several class names in the class file.
*
* @param classnames
* specifies which class name is replaced with which new name.
* Class names must be described with the JVM-internal
* representation like <code>java/lang/Object</code>.
* @see #renameClass(String,String)
*/
public final void renameClass(Map classnames) {
String jvmNewThisName = (String)classnames.get(Descriptor
.toJvmName(thisclassname));
if (jvmNewThisName != null)
thisclassname = Descriptor.toJavaName(jvmNewThisName);
constPool.renameClass(classnames);
AttributeInfo.renameClass(attributes, classnames);
ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
String desc = minfo.getDescriptor();
minfo.setDescriptor(Descriptor.rename(desc, classnames));
AttributeInfo.renameClass(minfo.getAttributes(), classnames);
}
list = fields;
n = list.size();
for (int i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
String desc = finfo.getDescriptor();
finfo.setDescriptor(Descriptor.rename(desc, classnames));
AttributeInfo.renameClass(finfo.getAttributes(), classnames);
}
}
/**
* Internal-use only.
* <code>CtClass.getRefClasses()</code> calls this method.
*/
public final void getRefClasses(Map classnames) {
constPool.renameClass(classnames);
AttributeInfo.getRefClasses(attributes, classnames);
ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
String desc = minfo.getDescriptor();
Descriptor.rename(desc, classnames);
AttributeInfo.getRefClasses(minfo.getAttributes(), classnames);
}
list = fields;
n = list.size();
for (int i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
String desc = finfo.getDescriptor();
Descriptor.rename(desc, classnames);
AttributeInfo.getRefClasses(finfo.getAttributes(), classnames);
}
}
/**
* Returns the names of the interfaces implemented by the class.
* The returned array is read only.
*/
public String[] getInterfaces() {
if (cachedInterfaces != null)
return cachedInterfaces;
String[] rtn = null;
if (interfaces == null)
rtn = new String[0];
else {
int n = interfaces.length;
String[] list = new String[n];
for (int i = 0; i < n; ++i)
list[i] = constPool.getClassInfo(interfaces[i]);
rtn = list;
}
cachedInterfaces = rtn;
return rtn;
}
/**
* Sets the interfaces.
*
* @param nameList
* the names of the interfaces.
*/
public void setInterfaces(String[] nameList) {
cachedInterfaces = null;
if (nameList != null) {
int n = nameList.length;
interfaces = new int[n];
for (int i = 0; i < n; ++i)
interfaces[i] = constPool.addClassInfo(nameList[i]);
}
}
/**
* Appends an interface to the interfaces implemented by the class.
*/
public void addInterface(String name) {
cachedInterfaces = null;
int info = constPool.addClassInfo(name);
if (interfaces == null) {
interfaces = new int[1];
interfaces[0] = info;
}
else {
int n = interfaces.length;
int[] newarray = new int[n + 1];
System.arraycopy(interfaces, 0, newarray, 0, n);
newarray[n] = info;
interfaces = newarray;
}
}
/**
* Returns all the fields declared in the class.
*
* @return a list of <code>FieldInfo</code>.
* @see FieldInfo
*/
public List getFields() {
return fields;
}
/**
* Appends a field to the class.
*
* @throws DuplicateMemberException when the field is already included.
*/
public void addField(FieldInfo finfo) throws DuplicateMemberException {
testExistingField(finfo.getName(), finfo.getDescriptor());
fields.add(finfo);
}
/**
* Just appends a field to the class.
* It does not check field duplication.
* Use this method only when minimizing performance overheads
* is seriously required.
*
* @since 3.13
*/
public final void addField2(FieldInfo finfo) {
fields.add(finfo);
}
private void testExistingField(String name, String descriptor)
throws DuplicateMemberException {
ListIterator it = fields.listIterator(0);
while (it.hasNext()) {
FieldInfo minfo = (FieldInfo)it.next();
if (minfo.getName().equals(name))
throw new DuplicateMemberException("duplicate field: " + name);
}
}
/**
* Returns all the methods declared in the class.
*
* @return a list of <code>MethodInfo</code>.
* @see MethodInfo
*/
public List getMethods() {
return methods;
}
/**
* Returns the method with the specified name. If there are multiple methods
* with that name, this method returns one of them.
*
* @return null if no such method is found.
*/
public MethodInfo getMethod(String name) {
ArrayList list = methods;
int n = list.size();
for (int i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
if (minfo.getName().equals(name))
return minfo;
}
return null;
}
/**
* Returns a static initializer (class initializer), or null if it does not
* exist.
*/
public MethodInfo getStaticInitializer() {
return getMethod(MethodInfo.nameClinit);
}
/**
* Appends a method to the class.
* If there is a bridge method with the same name and signature,
* then the bridge method is removed before a new method is added.
*
* @throws DuplicateMemberException when the method is already included.
*/
public void addMethod(MethodInfo minfo) throws DuplicateMemberException {
testExistingMethod(minfo);
methods.add(minfo);
}
/**
* Just appends a method to the class.
* It does not check method duplication or remove a bridge method.
* Use this method only when minimizing performance overheads
* is seriously required.
*
* @since 3.13
*/
public final void addMethod2(MethodInfo minfo) {
methods.add(minfo);
}
private void testExistingMethod(MethodInfo newMinfo)
throws DuplicateMemberException
{
String name = newMinfo.getName();
String descriptor = newMinfo.getDescriptor();
ListIterator it = methods.listIterator(0);
while (it.hasNext())
if (isDuplicated(newMinfo, name, descriptor, (MethodInfo)it.next(), it))
throw new DuplicateMemberException("duplicate method: " + name
+ " in " + this.getName());
}
private static boolean isDuplicated(MethodInfo newMethod, String newName,
String newDesc, MethodInfo minfo,
ListIterator it)
{
if (!minfo.getName().equals(newName))
return false;
String desc = minfo.getDescriptor();
if (!Descriptor.eqParamTypes(desc, newDesc))
return false;
if (desc.equals(newDesc)) {
if (notBridgeMethod(minfo))
return true;
else {
// if the bridge method with the same signature
// already exists, replace it.
it.remove();
return false;
}
}
else
return false;
// return notBridgeMethod(minfo) && notBridgeMethod(newMethod);
}
/* For a bridge method, see Sec. 15.12.4.5 of JLS 3rd Ed.
*/
private static boolean notBridgeMethod(MethodInfo minfo) {
return (minfo.getAccessFlags() & AccessFlag.BRIDGE) == 0;
}
/**
* Returns all the attributes. The returned <code>List</code> object
* is shared with this object. If you add a new attribute to the list,
* the attribute is also added to the classs file represented by this
* object. If you remove an attribute from the list, it is also removed
* from the class file.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes() {
return attributes;
}
/**
* Returns the attribute with the specified name. If there are multiple
* attributes with that name, this method returns either of them. It
* returns null if the specified attributed is not found.
*
* @param name attribute name
* @see #getAttributes()
*/
public AttributeInfo getAttribute(String name) {
ArrayList list = attributes;
int n = list.size();
for (int i = 0; i < n; ++i) {
AttributeInfo ai = (AttributeInfo)list.get(i);
if (ai.getName().equals(name))
return ai;
}
return null;
}
/**
* Appends an attribute. If there is already an attribute with the same
* name, the new one substitutes for it.
*
* @see #getAttributes()
*/
public void addAttribute(AttributeInfo info) {
AttributeInfo.remove(attributes, info.getName());
attributes.add(info);
}
/**
* Returns the source file containing this class.
*
* @return null if this information is not available.
*/
public String getSourceFile() {
SourceFileAttribute sf
= (SourceFileAttribute)getAttribute(SourceFileAttribute.tag);
if (sf == null)
return null;
else
return sf.getFileName();
}
private void read(DataInputStream in) throws IOException {
int i, n;
int magic = in.readInt();
if (magic != 0xCAFEBABE)
throw new IOException("bad magic number: " + Integer.toHexString(magic));
minor = in.readUnsignedShort();
major = in.readUnsignedShort();
constPool = new ConstPool(in);
accessFlags = in.readUnsignedShort();
thisClass = in.readUnsignedShort();
constPool.setThisClassInfo(thisClass);
superClass = in.readUnsignedShort();
n = in.readUnsignedShort();
if (n == 0)
interfaces = null;
else {
interfaces = new int[n];
for (i = 0; i < n; ++i)
interfaces[i] = in.readUnsignedShort();
}
ConstPool cp = constPool;
n = in.readUnsignedShort();
fields = new ArrayList();
for (i = 0; i < n; ++i)
addField2(new FieldInfo(cp, in));
n = in.readUnsignedShort();
methods = new ArrayList();
for (i = 0; i < n; ++i)
addMethod2(new MethodInfo(cp, in));
attributes = new ArrayList();
n = in.readUnsignedShort();
for (i = 0; i < n; ++i)
addAttribute(AttributeInfo.read(cp, in));
thisclassname = constPool.getClassInfo(thisClass);
}
/**
* Writes a class file represented by this object into an output stream.
*/
public void write(DataOutputStream out) throws IOException {
int i, n;
out.writeInt(0xCAFEBABE); // magic
out.writeShort(minor); // minor version
out.writeShort(major); // major version
constPool.write(out); // constant pool
out.writeShort(accessFlags);
out.writeShort(thisClass);
out.writeShort(superClass);
if (interfaces == null)
n = 0;
else
n = interfaces.length;
out.writeShort(n);
for (i = 0; i < n; ++i)
out.writeShort(interfaces[i]);
ArrayList list = fields;
n = list.size();
out.writeShort(n);
for (i = 0; i < n; ++i) {
FieldInfo finfo = (FieldInfo)list.get(i);
finfo.write(out);
}
list = methods;
n = list.size();
out.writeShort(n);
for (i = 0; i < n; ++i) {
MethodInfo minfo = (MethodInfo)list.get(i);
minfo.write(out);
}
out.writeShort(attributes.size());
AttributeInfo.writeAll(attributes, out);
}
/**
* Get the Major version.
*
* @return the major version
*/
public int getMajorVersion() {
return major;
}
/**
* Set the major version.
*
* @param major
* the major version
*/
public void setMajorVersion(int major) {
this.major = major;
}
/**
* Get the minor version.
*
* @return the minor version
*/
public int getMinorVersion() {
return minor;
}
/**
* Set the minor version.
*
* @param minor
* the minor version
*/
public void setMinorVersion(int minor) {
this.minor = minor;
}
/**
* Sets the major and minor version to Java 5.
*
* If the major version is older than 49, Java 5
* extensions such as annotations are ignored
* by the JVM.
*/
public void setVersionToJava5() {
this.major = 49;
this.minor = 0;
}
}

154
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ClassFilePrinter.java

@ -1,154 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.PrintWriter;
import com.fr.third.javassist.Modifier;
import java.util.List;
/**
* A utility class for priting the contents of a class file.
* It prints a constant pool table, fields, and methods in a
* human readable representation.
*/
public class ClassFilePrinter {
/**
* Prints the contents of a class file to the standard output stream.
*/
public static void print(com.fr.third.javassist.bytecode.ClassFile cf) {
print(cf, new PrintWriter(System.out, true));
}
/**
* Prints the contents of a class file.
*/
public static void print(ClassFile cf, PrintWriter out) {
List list;
int n;
/* 0x0020 (SYNCHRONIZED) means ACC_SUPER if the modifiers
* are of a class.
*/
int mod
= com.fr.third.javassist.bytecode.AccessFlag.toModifier(cf.getAccessFlags()
& ~com.fr.third.javassist.bytecode.AccessFlag.SYNCHRONIZED);
out.println("major: " + cf.major + ", minor: " + cf.minor
+ " modifiers: " + Integer.toHexString(cf.getAccessFlags()));
out.println(Modifier.toString(mod) + " class "
+ cf.getName() + " extends " + cf.getSuperclass());
String[] infs = cf.getInterfaces();
if (infs != null && infs.length > 0) {
out.print(" implements ");
out.print(infs[0]);
for (int i = 1; i < infs.length; ++i)
out.print(", " + infs[i]);
out.println();
}
out.println();
list = cf.getFields();
n = list.size();
for (int i = 0; i < n; ++i) {
com.fr.third.javassist.bytecode.FieldInfo finfo = (FieldInfo)list.get(i);
int acc = finfo.getAccessFlags();
out.println(Modifier.toString(com.fr.third.javassist.bytecode.AccessFlag.toModifier(acc))
+ " " + finfo.getName() + "\t"
+ finfo.getDescriptor());
printAttributes(finfo.getAttributes(), out, 'f');
}
out.println();
list = cf.getMethods();
n = list.size();
for (int i = 0; i < n; ++i) {
com.fr.third.javassist.bytecode.MethodInfo minfo = (MethodInfo)list.get(i);
int acc = minfo.getAccessFlags();
out.println(Modifier.toString(AccessFlag.toModifier(acc))
+ " " + minfo.getName() + "\t"
+ minfo.getDescriptor());
printAttributes(minfo.getAttributes(), out, 'm');
out.println();
}
out.println();
printAttributes(cf.getAttributes(), out, 'c');
}
static void printAttributes(List list, PrintWriter out, char kind) {
if (list == null)
return;
int n = list.size();
for (int i = 0; i < n; ++i) {
com.fr.third.javassist.bytecode.AttributeInfo ai = (AttributeInfo)list.get(i);
if (ai instanceof com.fr.third.javassist.bytecode.CodeAttribute) {
com.fr.third.javassist.bytecode.CodeAttribute ca = (CodeAttribute)ai;
out.println("attribute: " + ai.getName() + ": "
+ ai.getClass().getName());
out.println("max stack " + ca.getMaxStack()
+ ", max locals " + ca.getMaxLocals()
+ ", " + ca.getExceptionTable().size()
+ " catch blocks");
out.println("<code attribute begin>");
printAttributes(ca.getAttributes(), out, kind);
out.println("<code attribute end>");
}
else if (ai instanceof AnnotationsAttribute) {
out.println("annnotation: " + ai.toString());
}
else if (ai instanceof ParameterAnnotationsAttribute) {
out.println("parameter annnotations: " + ai.toString());
}
else if (ai instanceof com.fr.third.javassist.bytecode.StackMapTable) {
out.println("<stack map table begin>");
com.fr.third.javassist.bytecode.StackMapTable.Printer.print((StackMapTable)ai, out);
out.println("<stack map table end>");
}
else if (ai instanceof com.fr.third.javassist.bytecode.StackMap) {
out.println("<stack map begin>");
((StackMap)ai).print(out);
out.println("<stack map end>");
}
else if (ai instanceof SignatureAttribute) {
SignatureAttribute sa = (SignatureAttribute)ai;
String sig = sa.getSignature();
out.println("signature: " + sig);
try {
String s;
if (kind == 'c')
s = SignatureAttribute.toClassSignature(sig).toString();
else if (kind == 'm')
s = SignatureAttribute.toMethodSignature(sig).toString();
else
s = SignatureAttribute.toFieldSignature(sig).toString();
out.println(" " + s);
}
catch (BadBytecode e) {
out.println(" syntax error");
}
}
else
out.println("attribute: " + ai.getName()
+ " (" + ai.get().length + " byte): "
+ ai.getClass().getName());
}
}
}

782
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ClassFileWriter.java

@ -1,782 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
/**
* A quick class-file writer. This is useful when a generated
* class file is simple and the code generation should be fast.
*
* <p>Example:
*
* <blockquote><pre>
* ClassFileWriter cfw = new ClassFileWriter(ClassFile.JAVA_4, 0);
* ConstPoolWriter cpw = cfw.getConstPool();
*
* FieldWriter fw = cfw.getFieldWriter();
* fw.add(AccessFlag.PUBLIC, "value", "I", null);
* fw.add(AccessFlag.PUBLIC, "value2", "J", null);
*
* int thisClass = cpw.addClassInfo("sample/Test");
* int superClass = cpw.addClassInfo("java/lang/Object");
*
* MethodWriter mw = cfw.getMethodWriter();
*
* mw.begin(AccessFlag.PUBLIC, MethodInfo.nameInit, "()V", null, null);
* mw.add(Opcode.ALOAD_0);
* mw.add(Opcode.INVOKESPECIAL);
* int signature = cpw.addNameAndTypeInfo(MethodInfo.nameInit, "()V");
* mw.add16(cpw.addMethodrefInfo(superClass, signature));
* mw.add(Opcode.RETURN);
* mw.codeEnd(1, 1);
* mw.end(null, null);
*
* mw.begin(AccessFlag.PUBLIC, "one", "()I", null, null);
* mw.add(Opcode.ICONST_1);
* mw.add(Opcode.IRETURN);
* mw.codeEnd(1, 1);
* mw.end(null, null);
*
* byte[] classfile = cfw.end(AccessFlag.PUBLIC, thisClass, superClass,
* null, null);
* </pre></blockquote>
*
* <p>The code above generates the following class:
*
* <blockquote><pre>
* package sample;
* public class Test {
* public int value;
* public long value2;
* public Test() { super(); }
* public one() { return 1; }
* }
* </pre></blockquote>
*
* @since 3.13
*/
public class ClassFileWriter {
private com.fr.third.javassist.bytecode.ByteStream output;
private ConstPoolWriter constPool;
private FieldWriter fields;
private MethodWriter methods;
int thisClass, superClass;
/**
* Constructs a class file writer.
*
* @param major the major version ({@link com.fr.third.javassist.bytecode.ClassFile#JAVA_4}, {@link ClassFile#JAVA_5}, ...).
* @param minor the minor version (0 for JDK 1.3 and later).
*/
public ClassFileWriter(int major, int minor) {
output = new com.fr.third.javassist.bytecode.ByteStream(512);
output.writeInt(0xCAFEBABE); // magic
output.writeShort(minor);
output.writeShort(major);
constPool = new ConstPoolWriter(output);
fields = new FieldWriter(constPool);
methods = new MethodWriter(constPool);
}
/**
* Returns a constant pool.
*/
public ConstPoolWriter getConstPool() { return constPool; }
/**
* Returns a filed writer.
*/
public FieldWriter getFieldWriter() { return fields; }
/**
* Returns a method writer.
*/
public MethodWriter getMethodWriter() { return methods; }
/**
* Ends writing and returns the contents of the class file.
*
* @param accessFlags access flags.
* @param thisClass this class. an index indicating its <code>CONSTANT_Class_info</code>.
* @param superClass super class. an index indicating its <code>CONSTANT_Class_info</code>.
* @param interfaces implemented interfaces.
* index numbers indicating their <code>ClassInfo</code>.
* It may be null.
* @param aw attributes of the class file. May be null.
*
* @see com.fr.third.javassist.bytecode.AccessFlag
*/
public byte[] end(int accessFlags, int thisClass, int superClass,
int[] interfaces, AttributeWriter aw) {
constPool.end();
output.writeShort(accessFlags);
output.writeShort(thisClass);
output.writeShort(superClass);
if (interfaces == null)
output.writeShort(0);
else {
int n = interfaces.length;
output.writeShort(n);
for (int i = 0; i < n; i++)
output.writeShort(interfaces[i]);
}
output.enlarge(fields.dataSize() + methods.dataSize() + 6);
try {
output.writeShort(fields.size());
fields.write(output);
output.writeShort(methods.size());
methods.write(output);
}
catch (IOException e) {}
writeAttribute(output, aw, 0);
return output.toByteArray();
}
/**
* Ends writing and writes the contents of the class file into the
* given output stream.
*
* @param accessFlags access flags.
* @param thisClass this class. an index indicating its <code>CONSTANT_Class_info</code>.
* @param superClass super class. an index indicating its <code>CONSTANT_Class_info</code>.
* @param interfaces implemented interfaces.
* index numbers indicating their <code>CONSTATNT_Class_info</code>.
* It may be null.
* @param aw attributes of the class file. May be null.
*
* @see com.fr.third.javassist.bytecode.AccessFlag
*/
public void end(DataOutputStream out,
int accessFlags, int thisClass, int superClass,
int[] interfaces, AttributeWriter aw)
throws IOException
{
constPool.end();
output.writeTo(out);
out.writeShort(accessFlags);
out.writeShort(thisClass);
out.writeShort(superClass);
if (interfaces == null)
out.writeShort(0);
else {
int n = interfaces.length;
out.writeShort(n);
for (int i = 0; i < n; i++)
out.writeShort(interfaces[i]);
}
out.writeShort(fields.size());
fields.write(out);
out.writeShort(methods.size());
methods.write(out);
if (aw == null)
out.writeShort(0);
else {
out.writeShort(aw.size());
aw.write(out);
}
}
/**
* This writes attributes.
*
* <p>For example, the following object writes a synthetic attribute:
*
* <pre>
* ConstPoolWriter cpw = ...;
* final int tag = cpw.addUtf8Info("Synthetic");
* AttributeWriter aw = new AttributeWriter() {
* public int size() {
* return 1;
* }
* public void write(DataOutputStream out) throws java.io.IOException {
* out.writeShort(tag);
* out.writeInt(0);
* }
* };
* </pre>
*/
public static interface AttributeWriter {
/**
* Returns the number of attributes that this writer will
* write.
*/
public int size();
/**
* Writes all the contents of the attributes. The binary representation
* of the contents is an array of <code>attribute_info</code>.
*/
public void write(DataOutputStream out) throws IOException;
}
static void writeAttribute(com.fr.third.javassist.bytecode.ByteStream bs, AttributeWriter aw, int attrCount) {
if (aw == null) {
bs.writeShort(attrCount);
return;
}
bs.writeShort(aw.size() + attrCount);
DataOutputStream dos = new DataOutputStream(bs);
try {
aw.write(dos);
dos.flush();
}
catch (IOException e) {}
}
/**
* Field.
*/
public static final class FieldWriter {
protected com.fr.third.javassist.bytecode.ByteStream output;
protected ConstPoolWriter constPool;
private int fieldCount;
FieldWriter(ConstPoolWriter cp) {
output = new com.fr.third.javassist.bytecode.ByteStream(128);
constPool = cp;
fieldCount = 0;
}
/**
* Adds a new field.
*
* @param accessFlags access flags.
* @param name the field name.
* @param descriptor the field type.
* @param aw the attributes of the field. may be null.
* @see com.fr.third.javassist.bytecode.AccessFlag
*/
public void add(int accessFlags, String name, String descriptor, AttributeWriter aw) {
int nameIndex = constPool.addUtf8Info(name);
int descIndex = constPool.addUtf8Info(descriptor);
add(accessFlags, nameIndex, descIndex, aw);
}
/**
* Adds a new field.
*
* @param accessFlags access flags.
* @param name the field name. an index indicating its <code>CONSTANT_Utf8_info</code>.
* @param descriptor the field type. an index indicating its <code>CONSTANT_Utf8_info</code>.
* @param aw the attributes of the field. may be null.
* @see com.fr.third.javassist.bytecode.AccessFlag
*/
public void add(int accessFlags, int name, int descriptor, AttributeWriter aw) {
++fieldCount;
output.writeShort(accessFlags);
output.writeShort(name);
output.writeShort(descriptor);
writeAttribute(output, aw, 0);
}
int size() { return fieldCount; }
int dataSize() { return output.size(); }
/**
* Writes the added fields.
*/
void write(OutputStream out) throws IOException {
output.writeTo(out);
}
}
/**
* Method.
*/
public static final class MethodWriter {
protected com.fr.third.javassist.bytecode.ByteStream output;
protected ConstPoolWriter constPool;
private int methodCount;
protected int codeIndex;
protected int throwsIndex;
protected int stackIndex;
private int startPos;
private boolean isAbstract;
private int catchPos;
private int catchCount;
MethodWriter(ConstPoolWriter cp) {
output = new com.fr.third.javassist.bytecode.ByteStream(256);
constPool = cp;
methodCount = 0;
codeIndex = 0;
throwsIndex = 0;
stackIndex = 0;
}
/**
* Starts Adding a new method.
*
* @param accessFlags access flags.
* @param name the method name.
* @param descriptor the method signature.
* @param exceptions throws clause. It may be null.
* The class names must be the JVM-internal
* representations like <code>java/lang/Exception</code>.
* @param aw attributes to the <code>Method_info</code>.
*/
public void begin(int accessFlags, String name, String descriptor,
String[] exceptions, AttributeWriter aw) {
int nameIndex = constPool.addUtf8Info(name);
int descIndex = constPool.addUtf8Info(descriptor);
int[] intfs;
if (exceptions == null)
intfs = null;
else
intfs = constPool.addClassInfo(exceptions);
begin(accessFlags, nameIndex, descIndex, intfs, aw);
}
/**
* Starts adding a new method.
*
* @param accessFlags access flags.
* @param name the method name. an index indicating its <code>CONSTANT_Utf8_info</code>.
* @param descriptor the field type. an index indicating its <code>CONSTANT_Utf8_info</code>.
* @param exceptions throws clause. indexes indicating <code>CONSTANT_Class_info</code>s.
* It may be null.
* @param aw attributes to the <code>Method_info</code>.
*/
public void begin(int accessFlags, int name, int descriptor, int[] exceptions, AttributeWriter aw) {
++methodCount;
output.writeShort(accessFlags);
output.writeShort(name);
output.writeShort(descriptor);
isAbstract = (accessFlags & AccessFlag.ABSTRACT) != 0;
int attrCount = isAbstract ? 0 : 1;
if (exceptions != null)
++attrCount;
writeAttribute(output, aw, attrCount);
if (exceptions != null)
writeThrows(exceptions);
if (!isAbstract) {
if (codeIndex == 0)
codeIndex = constPool.addUtf8Info(CodeAttribute.tag);
startPos = output.getPos();
output.writeShort(codeIndex);
output.writeBlank(12); // attribute_length, maxStack, maxLocals, code_lenth
}
catchPos = -1;
catchCount = 0;
}
private void writeThrows(int[] exceptions) {
if (throwsIndex == 0)
throwsIndex = constPool.addUtf8Info(ExceptionsAttribute.tag);
output.writeShort(throwsIndex);
output.writeInt(exceptions.length * 2 + 2);
output.writeShort(exceptions.length);
for (int i = 0; i < exceptions.length; i++)
output.writeShort(exceptions[i]);
}
/**
* Appends an 8bit value of bytecode.
*
* @see com.fr.third.javassist.bytecode.Opcode
*/
public void add(int b) {
output.write(b);
}
/**
* Appends a 16bit value of bytecode.
*/
public void add16(int b) {
output.writeShort(b);
}
/**
* Appends a 32bit value of bytecode.
*/
public void add32(int b) {
output.writeInt(b);
}
/**
* Appends a invokevirtual, inovkespecial, or invokestatic bytecode.
*
* @see Opcode
*/
public void addInvoke(int opcode, String targetClass, String methodName,
String descriptor) {
int target = constPool.addClassInfo(targetClass);
int nt = constPool.addNameAndTypeInfo(methodName, descriptor);
int method = constPool.addMethodrefInfo(target, nt);
add(opcode);
add16(method);
}
/**
* Ends appending bytecode.
*/
public void codeEnd(int maxStack, int maxLocals) {
if (!isAbstract) {
output.writeShort(startPos + 6, maxStack);
output.writeShort(startPos + 8, maxLocals);
output.writeInt(startPos + 10, output.getPos() - startPos - 14); // code_length
catchPos = output.getPos();
catchCount = 0;
output.writeShort(0); // number of catch clauses
}
}
/**
* Appends an <code>exception_table</code> entry to the
* <code>Code_attribute</code>. This method is available
* only after the <code>codeEnd</code> method is called.
*
* @param catchType an index indicating a <code>CONSTANT_Class_info</code>.
*/
public void addCatch(int startPc, int endPc, int handlerPc, int catchType) {
++catchCount;
output.writeShort(startPc);
output.writeShort(endPc);
output.writeShort(handlerPc);
output.writeShort(catchType);
}
/**
* Ends adding a new method. The <code>add</code> method must be
* called before the <code>end</code> method is called.
*
* @param smap a stack map table. may be null.
* @param aw attributes to the <code>Code_attribute</code>.
* may be null.
*/
public void end(com.fr.third.javassist.bytecode.StackMapTable.Writer smap, AttributeWriter aw) {
if (isAbstract)
return;
// exception_table_length
output.writeShort(catchPos, catchCount);
int attrCount = smap == null ? 0 : 1;
writeAttribute(output, aw, attrCount);
if (smap != null) {
if (stackIndex == 0)
stackIndex = constPool.addUtf8Info(StackMapTable.tag);
output.writeShort(stackIndex);
byte[] data = smap.toByteArray();
output.writeInt(data.length);
output.write(data);
}
// Code attribute_length
output.writeInt(startPos + 2, output.getPos() - startPos - 6);
}
int size() { return methodCount; }
int dataSize() { return output.size(); }
/**
* Writes the added methods.
*/
void write(OutputStream out) throws IOException {
output.writeTo(out);
}
}
/**
* Constant Pool.
*/
public static final class ConstPoolWriter {
com.fr.third.javassist.bytecode.ByteStream output;
protected int startPos;
protected int num;
ConstPoolWriter(com.fr.third.javassist.bytecode.ByteStream out) {
output = out;
startPos = out.getPos();
num = 1;
output.writeShort(1); // number of entries
}
/**
* Makes <code>CONSTANT_Class_info</code> objects for each class name.
*
* @return an array of indexes indicating <code>CONSTANT_Class_info</code>s.
*/
public int[] addClassInfo(String[] classNames) {
int n = classNames.length;
int[] result = new int[n];
for (int i = 0; i < n; i++)
result[i] = addClassInfo(classNames[i]);
return result;
}
/**
* Adds a new <code>CONSTANT_Class_info</code> structure.
*
* <p>This also adds a <code>CONSTANT_Utf8_info</code> structure
* for storing the class name.
*
* @param jvmname the JVM-internal representation of a class name.
* e.g. <code>java/lang/Object</code>.
* @return the index of the added entry.
*/
public int addClassInfo(String jvmname) {
int utf8 = addUtf8Info(jvmname);
output.write(com.fr.third.javassist.bytecode.ClassInfo.tag);
output.writeShort(utf8);
return num++;
}
/**
* Adds a new <code>CONSTANT_Class_info</code> structure.
*
* @param name <code>name_index</code>
* @return the index of the added entry.
*/
public int addClassInfo(int name) {
output.write(com.fr.third.javassist.bytecode.ClassInfo.tag);
output.writeShort(name);
return num++;
}
/**
* Adds a new <code>CONSTANT_NameAndType_info</code> structure.
*
* @param name <code>name_index</code>
* @param type <code>descriptor_index</code>
* @return the index of the added entry.
*/
public int addNameAndTypeInfo(String name, String type) {
return addNameAndTypeInfo(addUtf8Info(name), addUtf8Info(type));
}
/**
* Adds a new <code>CONSTANT_NameAndType_info</code> structure.
*
* @param name <code>name_index</code>
* @param type <code>descriptor_index</code>
* @return the index of the added entry.
*/
public int addNameAndTypeInfo(int name, int type) {
output.write(com.fr.third.javassist.bytecode.NameAndTypeInfo.tag);
output.writeShort(name);
output.writeShort(type);
return num++;
}
/**
* Adds a new <code>CONSTANT_Fieldref_info</code> structure.
*
* @param classInfo <code>class_index</code>
* @param nameAndTypeInfo <code>name_and_type_index</code>.
* @return the index of the added entry.
*/
public int addFieldrefInfo(int classInfo, int nameAndTypeInfo) {
output.write(com.fr.third.javassist.bytecode.FieldrefInfo.tag);
output.writeShort(classInfo);
output.writeShort(nameAndTypeInfo);
return num++;
}
/**
* Adds a new <code>CONSTANT_Methodref_info</code> structure.
*
* @param classInfo <code>class_index</code>
* @param nameAndTypeInfo <code>name_and_type_index</code>.
* @return the index of the added entry.
*/
public int addMethodrefInfo(int classInfo, int nameAndTypeInfo) {
output.write(com.fr.third.javassist.bytecode.MethodrefInfo.tag);
output.writeShort(classInfo);
output.writeShort(nameAndTypeInfo);
return num++;
}
/**
* Adds a new <code>CONSTANT_InterfaceMethodref_info</code>
* structure.
*
* @param classInfo <code>class_index</code>
* @param nameAndTypeInfo <code>name_and_type_index</code>.
* @return the index of the added entry.
*/
public int addInterfaceMethodrefInfo(int classInfo,
int nameAndTypeInfo) {
output.write(com.fr.third.javassist.bytecode.InterfaceMethodrefInfo.tag);
output.writeShort(classInfo);
output.writeShort(nameAndTypeInfo);
return num++;
}
/**
* Adds a new <code>CONSTANT_MethodHandle_info</code>
* structure.
*
* @param kind <code>reference_kind</code>
* such as {@link ConstPool#REF_invokeStatic <code>REF_invokeStatic</code>}.
* @param index <code>reference_index</code>.
* @return the index of the added entry.
*
* @since 3.17.1
*/
public int addMethodHandleInfo(int kind, int index) {
output.write(com.fr.third.javassist.bytecode.MethodHandleInfo.tag);
output.write(kind);
output.writeShort(index);
return num++;
}
/**
* Adds a new <code>CONSTANT_MethodType_info</code>
* structure.
*
* @param desc <code>descriptor_index</code>.
* @return the index of the added entry.
*
* @since 3.17.1
*/
public int addMethodTypeInfo(int desc) {
output.write(com.fr.third.javassist.bytecode.MethodTypeInfo.tag);
output.writeShort(desc);
return num++;
}
/**
* Adds a new <code>CONSTANT_InvokeDynamic_info</code>
* structure.
*
* @param bootstrap <code>bootstrap_method_attr_index</code>.
* @param nameAndTypeInfo <code>name_and_type_index</code>.
* @return the index of the added entry.
*
* @since 3.17.1
*/
public int addInvokeDynamicInfo(int bootstrap,
int nameAndTypeInfo) {
output.write(com.fr.third.javassist.bytecode.InvokeDynamicInfo.tag);
output.writeShort(bootstrap);
output.writeShort(nameAndTypeInfo);
return num++;
}
/**
* Adds a new <code>CONSTANT_String_info</code>
* structure.
*
* <p>This also adds a new <code>CONSTANT_Utf8_info</code>
* structure.
*
* @return the index of the added entry.
*/
public int addStringInfo(String str) {
int utf8 = addUtf8Info(str);
output.write(com.fr.third.javassist.bytecode.StringInfo.tag);
output.writeShort(utf8);
return num++;
}
/**
* Adds a new <code>CONSTANT_Integer_info</code>
* structure.
*
* @return the index of the added entry.
*/
public int addIntegerInfo(int i) {
output.write(com.fr.third.javassist.bytecode.IntegerInfo.tag);
output.writeInt(i);
return num++;
}
/**
* Adds a new <code>CONSTANT_Float_info</code>
* structure.
*
* @return the index of the added entry.
*/
public int addFloatInfo(float f) {
output.write(com.fr.third.javassist.bytecode.FloatInfo.tag);
output.writeFloat(f);
return num++;
}
/**
* Adds a new <code>CONSTANT_Long_info</code>
* structure.
*
* @return the index of the added entry.
*/
public int addLongInfo(long l) {
output.write(com.fr.third.javassist.bytecode.LongInfo.tag);
output.writeLong(l);
int n = num;
num += 2;
return n;
}
/**
* Adds a new <code>CONSTANT_Double_info</code>
* structure.
*
* @return the index of the added entry.
*/
public int addDoubleInfo(double d) {
output.write(com.fr.third.javassist.bytecode.DoubleInfo.tag);
output.writeDouble(d);
int n = num;
num += 2;
return n;
}
/**
* Adds a new <code>CONSTANT_Utf8_info</code>
* structure.
*
* @return the index of the added entry.
*/
public int addUtf8Info(String utf8) {
output.write(com.fr.third.javassist.bytecode.Utf8Info.tag);
output.writeUTF(utf8);
return num++;
}
/**
* Writes the contents of this class pool.
*/
void end() {
output.writeShort(startPos, num);
}
}
}

267
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/CodeAnalyzer.java

@ -1,267 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
/**
* Utility for computing <code>max_stack</code>.
*/
class CodeAnalyzer implements Opcode {
private ConstPool constPool;
private CodeAttribute codeAttr;
public CodeAnalyzer(CodeAttribute ca) {
codeAttr = ca;
constPool = ca.getConstPool();
}
public int computeMaxStack()
throws com.fr.third.javassist.bytecode.BadBytecode
{
/* d = stack[i]
* d == 0: not visited
* d > 0: the depth is d - 1 after executing the bytecode at i.
* d < 0: not visited. the initial depth (before execution) is 1 - d.
*/
CodeIterator ci = codeAttr.iterator();
int length = ci.getCodeLength();
int[] stack = new int[length];
constPool = codeAttr.getConstPool();
initStack(stack, codeAttr);
boolean repeat;
do {
repeat = false;
for (int i = 0; i < length; ++i)
if (stack[i] < 0) {
repeat = true;
visitBytecode(ci, stack, i);
}
} while (repeat);
int maxStack = 1;
for (int i = 0; i < length; ++i)
if (stack[i] > maxStack)
maxStack = stack[i];
return maxStack - 1; // the base is 1.
}
private void initStack(int[] stack, CodeAttribute ca) {
stack[0] = -1;
ExceptionTable et = ca.getExceptionTable();
if (et != null) {
int size = et.size();
for (int i = 0; i < size; ++i)
stack[et.handlerPc(i)] = -2; // an exception is on stack
}
}
private void visitBytecode(CodeIterator ci, int[] stack, int index)
throws com.fr.third.javassist.bytecode.BadBytecode
{
int codeLength = stack.length;
ci.move(index);
int stackDepth = -stack[index];
int[] jsrDepth = new int[1];
jsrDepth[0] = -1;
while (ci.hasNext()) {
index = ci.next();
stack[index] = stackDepth;
int op = ci.byteAt(index);
stackDepth = visitInst(op, ci, index, stackDepth);
if (stackDepth < 1)
throw new com.fr.third.javassist.bytecode.BadBytecode("stack underflow at " + index);
if (processBranch(op, ci, index, codeLength, stack, stackDepth, jsrDepth))
break;
if (isEnd(op)) // return, ireturn, athrow, ...
break;
if (op == JSR || op == JSR_W)
--stackDepth;
}
}
private boolean processBranch(int opcode, CodeIterator ci, int index,
int codeLength, int[] stack, int stackDepth, int[] jsrDepth)
throws com.fr.third.javassist.bytecode.BadBytecode
{
if ((IFEQ <= opcode && opcode <= IF_ACMPNE)
|| opcode == IFNULL || opcode == IFNONNULL) {
int target = index + ci.s16bitAt(index + 1);
checkTarget(index, target, codeLength, stack, stackDepth);
}
else {
int target, index2;
switch (opcode) {
case GOTO :
target = index + ci.s16bitAt(index + 1);
checkTarget(index, target, codeLength, stack, stackDepth);
return true;
case GOTO_W :
target = index + ci.s32bitAt(index + 1);
checkTarget(index, target, codeLength, stack, stackDepth);
return true;
case JSR :
case JSR_W :
if (opcode == JSR)
target = index + ci.s16bitAt(index + 1);
else
target = index + ci.s32bitAt(index + 1);
checkTarget(index, target, codeLength, stack, stackDepth);
/*
* It is unknown which RET comes back to this JSR.
* So we assume that if the stack depth at one JSR instruction
* is N, then it is also N at other JSRs and N - 1 at all RET
* instructions. Note that STACK_GROW[JSR] is 1 since it pushes
* a return address on the operand stack.
*/
if (jsrDepth[0] < 0) {
jsrDepth[0] = stackDepth;
return false;
}
else if (stackDepth == jsrDepth[0])
return false;
else
throw new com.fr.third.javassist.bytecode.BadBytecode(
"sorry, cannot compute this data flow due to JSR: "
+ stackDepth + "," + jsrDepth[0]);
case RET :
if (jsrDepth[0] < 0) {
jsrDepth[0] = stackDepth + 1;
return false;
}
else if (stackDepth + 1 == jsrDepth[0])
return true;
else
throw new com.fr.third.javassist.bytecode.BadBytecode(
"sorry, cannot compute this data flow due to RET: "
+ stackDepth + "," + jsrDepth[0]);
case LOOKUPSWITCH :
case TABLESWITCH :
index2 = (index & ~3) + 4;
target = index + ci.s32bitAt(index2);
checkTarget(index, target, codeLength, stack, stackDepth);
if (opcode == LOOKUPSWITCH) {
int npairs = ci.s32bitAt(index2 + 4);
index2 += 12;
for (int i = 0; i < npairs; ++i) {
target = index + ci.s32bitAt(index2);
checkTarget(index, target, codeLength,
stack, stackDepth);
index2 += 8;
}
}
else {
int low = ci.s32bitAt(index2 + 4);
int high = ci.s32bitAt(index2 + 8);
int n = high - low + 1;
index2 += 12;
for (int i = 0; i < n; ++i) {
target = index + ci.s32bitAt(index2);
checkTarget(index, target, codeLength,
stack, stackDepth);
index2 += 4;
}
}
return true; // always branch.
}
}
return false; // may not branch.
}
private void checkTarget(int opIndex, int target, int codeLength,
int[] stack, int stackDepth)
throws com.fr.third.javassist.bytecode.BadBytecode
{
if (target < 0 || codeLength <= target)
throw new com.fr.third.javassist.bytecode.BadBytecode("bad branch offset at " + opIndex);
int d = stack[target];
if (d == 0)
stack[target] = -stackDepth;
else if (d != stackDepth && d != -stackDepth)
throw new com.fr.third.javassist.bytecode.BadBytecode("verification error (" + stackDepth +
"," + d + ") at " + opIndex);
}
private static boolean isEnd(int opcode) {
return (IRETURN <= opcode && opcode <= RETURN) || opcode == ATHROW;
}
/**
* Visits an instruction.
*/
private int visitInst(int op, CodeIterator ci, int index, int stack)
throws BadBytecode
{
String desc;
switch (op) {
case GETFIELD :
stack += getFieldSize(ci, index) - 1;
break;
case PUTFIELD :
stack -= getFieldSize(ci, index) + 1;
break;
case GETSTATIC :
stack += getFieldSize(ci, index);
break;
case PUTSTATIC :
stack -= getFieldSize(ci, index);
break;
case INVOKEVIRTUAL :
case INVOKESPECIAL :
desc = constPool.getMethodrefType(ci.u16bitAt(index + 1));
stack += com.fr.third.javassist.bytecode.Descriptor.dataSize(desc) - 1;
break;
case INVOKESTATIC :
desc = constPool.getMethodrefType(ci.u16bitAt(index + 1));
stack += com.fr.third.javassist.bytecode.Descriptor.dataSize(desc);
break;
case INVOKEINTERFACE :
desc = constPool.getInterfaceMethodrefType(
ci.u16bitAt(index + 1));
stack += com.fr.third.javassist.bytecode.Descriptor.dataSize(desc) - 1;
break;
case INVOKEDYNAMIC :
desc = constPool.getInvokeDynamicType(ci.u16bitAt(index + 1));
stack += com.fr.third.javassist.bytecode.Descriptor.dataSize(desc); // assume CosntPool#REF_invokeStatic
break;
case ATHROW :
stack = 1; // the stack becomes empty (1 means no values).
break;
case MULTIANEWARRAY :
stack += 1 - ci.byteAt(index + 3);
break;
case WIDE :
op = ci.byteAt(index + 1);
// don't break here.
default :
stack += STACK_GROW[op];
}
return stack;
}
private int getFieldSize(CodeIterator ci, int index) {
String desc = constPool.getFieldrefType(ci.u16bitAt(index + 1));
return Descriptor.dataSize(desc);
}
}

594
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/CodeAttribute.java

@ -1,594 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
/**
* <code>Code_attribute</code>.
*
* <p>To browse the <code>code</code> field of
* a <code>Code_attribute</code> structure,
* use <code>CodeIterator</code>.
*
* @see com.fr.third.javassist.bytecode.CodeIterator
* @see #iterator()
*/
public class CodeAttribute extends com.fr.third.javassist.bytecode.AttributeInfo implements Opcode {
/**
* The name of this attribute <code>"Code"</code>.
*/
public static final String tag = "Code";
// code[] is stored in AttributeInfo.info.
private int maxStack;
private int maxLocals;
private ExceptionTable exceptions;
private ArrayList attributes;
/**
* Constructs a <code>Code_attribute</code>.
*
* @param cp constant pool table
* @param stack <code>max_stack</code>
* @param locals <code>max_locals</code>
* @param code <code>code[]</code>
* @param etable <code>exception_table[]</code>
*/
public CodeAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int stack, int locals, byte[] code,
ExceptionTable etable)
{
super(cp, tag);
maxStack = stack;
maxLocals = locals;
info = code;
exceptions = etable;
attributes = new ArrayList();
}
/**
* Constructs a copy of <code>Code_attribute</code>.
* Specified class names are replaced during the copy.
*
* @param cp constant pool table.
* @param src source Code attribute.
* @param classnames pairs of replaced and substituted
* class names.
*/
private CodeAttribute(com.fr.third.javassist.bytecode.ConstPool cp, CodeAttribute src, Map classnames)
throws com.fr.third.javassist.bytecode.BadBytecode
{
super(cp, tag);
maxStack = src.getMaxStack();
maxLocals = src.getMaxLocals();
exceptions = src.getExceptionTable().copy(cp, classnames);
attributes = new ArrayList();
List src_attr = src.getAttributes();
int num = src_attr.size();
for (int i = 0; i < num; ++i) {
com.fr.third.javassist.bytecode.AttributeInfo ai = (com.fr.third.javassist.bytecode.AttributeInfo)src_attr.get(i);
attributes.add(ai.copy(cp, classnames));
}
info = src.copyCode(cp, classnames, exceptions, this);
}
CodeAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int name_id, DataInputStream in)
throws IOException
{
super(cp, name_id, (byte[])null);
int attr_len = in.readInt();
maxStack = in.readUnsignedShort();
maxLocals = in.readUnsignedShort();
int code_len = in.readInt();
info = new byte[code_len];
in.readFully(info);
exceptions = new ExceptionTable(cp, in);
attributes = new ArrayList();
int num = in.readUnsignedShort();
for (int i = 0; i < num; ++i)
attributes.add(com.fr.third.javassist.bytecode.AttributeInfo.read(cp, in));
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
* @exception RuntimeCopyException if a <code>BadBytecode</code>
* exception is thrown, it is
* converted into
* <code>RuntimeCopyException</code>.
*
* @return <code>CodeAttribute</code> object.
*/
public com.fr.third.javassist.bytecode.AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames)
throws RuntimeCopyException
{
try {
return new CodeAttribute(newCp, this, classnames);
}
catch (com.fr.third.javassist.bytecode.BadBytecode e) {
throw new RuntimeCopyException("bad bytecode. fatal?");
}
}
/**
* An exception that may be thrown by <code>copy()</code>
* in <code>CodeAttribute</code>.
*/
public static class RuntimeCopyException extends RuntimeException {
/**
* Constructs an exception.
*/
public RuntimeCopyException(String s) {
super(s);
}
}
/**
* Returns the length of this <code>attribute_info</code>
* structure.
* The returned value is <code>attribute_length + 6</code>.
*/
public int length() {
return 18 + info.length + exceptions.size() * 8
+ com.fr.third.javassist.bytecode.AttributeInfo.getLength(attributes);
}
void write(DataOutputStream out) throws IOException {
out.writeShort(name); // attribute_name_index
out.writeInt(length() - 6); // attribute_length
out.writeShort(maxStack); // max_stack
out.writeShort(maxLocals); // max_locals
out.writeInt(info.length); // code_length
out.write(info); // code
exceptions.write(out);
out.writeShort(attributes.size()); // attributes_count
com.fr.third.javassist.bytecode.AttributeInfo.writeAll(attributes, out); // attributes
}
/**
* This method is not available.
*
* @throws java.lang.UnsupportedOperationException always thrown.
*/
public byte[] get() {
throw new UnsupportedOperationException("CodeAttribute.get()");
}
/**
* This method is not available.
*
* @throws java.lang.UnsupportedOperationException always thrown.
*/
public void set(byte[] newinfo) {
throw new UnsupportedOperationException("CodeAttribute.set()");
}
void renameClass(String oldname, String newname) {
com.fr.third.javassist.bytecode.AttributeInfo.renameClass(attributes, oldname, newname);
}
void renameClass(Map classnames) {
com.fr.third.javassist.bytecode.AttributeInfo.renameClass(attributes, classnames);
}
void getRefClasses(Map classnames) {
com.fr.third.javassist.bytecode.AttributeInfo.getRefClasses(attributes, classnames);
}
/**
* Returns the name of the class declaring the method including
* this code attribute.
*/
public String getDeclaringClass() {
com.fr.third.javassist.bytecode.ConstPool cp = getConstPool();
return cp.getClassName();
}
/**
* Returns <code>max_stack</code>.
*/
public int getMaxStack() {
return maxStack;
}
/**
* Sets <code>max_stack</code>.
*/
public void setMaxStack(int value) {
maxStack = value;
}
/**
* Computes the maximum stack size and sets <code>max_stack</code>
* to the computed size.
*
* @throws com.fr.third.javassist.bytecode.BadBytecode if this method fails in computing.
* @return the newly computed value of <code>max_stack</code>
*/
public int computeMaxStack() throws com.fr.third.javassist.bytecode.BadBytecode {
maxStack = new com.fr.third.javassist.bytecode.CodeAnalyzer(this).computeMaxStack();
return maxStack;
}
/**
* Returns <code>max_locals</code>.
*/
public int getMaxLocals() {
return maxLocals;
}
/**
* Sets <code>max_locals</code>.
*/
public void setMaxLocals(int value) {
maxLocals = value;
}
/**
* Returns <code>code_length</code>.
*/
public int getCodeLength() {
return info.length;
}
/**
* Returns <code>code[]</code>.
*/
public byte[] getCode() {
return info;
}
/**
* Sets <code>code[]</code>.
*/
void setCode(byte[] newinfo) { super.set(newinfo); }
/**
* Makes a new iterator for reading this code attribute.
*/
public com.fr.third.javassist.bytecode.CodeIterator iterator() {
return new com.fr.third.javassist.bytecode.CodeIterator(this);
}
/**
* Returns <code>exception_table[]</code>.
*/
public ExceptionTable getExceptionTable() { return exceptions; }
/**
* Returns <code>attributes[]</code>.
* It returns a list of <code>AttributeInfo</code>.
* A new element can be added to the returned list
* and an existing element can be removed from the list.
*
* @see com.fr.third.javassist.bytecode.AttributeInfo
*/
public List getAttributes() { return attributes; }
/**
* Returns the attribute with the specified name.
* If it is not found, this method returns null.
*
* @param name attribute name
* @return an <code>AttributeInfo</code> object or null.
*/
public com.fr.third.javassist.bytecode.AttributeInfo getAttribute(String name) {
return com.fr.third.javassist.bytecode.AttributeInfo.lookup(attributes, name);
}
/**
* Adds a stack map table. If another copy of stack map table
* is already contained, the old one is removed.
*
* @param smt the stack map table added to this code attribute.
* If it is null, a new stack map is not added.
* Only the old stack map is removed.
*/
public void setAttribute(StackMapTable smt) {
com.fr.third.javassist.bytecode.AttributeInfo.remove(attributes, StackMapTable.tag);
if (smt != null)
attributes.add(smt);
}
/**
* Adds a stack map table for J2ME (CLDC). If another copy of stack map table
* is already contained, the old one is removed.
*
* @param sm the stack map table added to this code attribute.
* If it is null, a new stack map is not added.
* Only the old stack map is removed.
* @since 3.12
*/
public void setAttribute(com.fr.third.javassist.bytecode.StackMap sm) {
AttributeInfo.remove(attributes, com.fr.third.javassist.bytecode.StackMap.tag);
if (sm != null)
attributes.add(sm);
}
/**
* Copies code.
*/
private byte[] copyCode(com.fr.third.javassist.bytecode.ConstPool destCp, Map classnames,
ExceptionTable etable, CodeAttribute destCa)
throws com.fr.third.javassist.bytecode.BadBytecode
{
int len = getCodeLength();
byte[] newCode = new byte[len];
destCa.info = newCode;
LdcEntry ldc = copyCode(this.info, 0, len, this.getConstPool(),
newCode, destCp, classnames);
return LdcEntry.doit(newCode, ldc, etable, destCa);
}
private static LdcEntry copyCode(byte[] code, int beginPos, int endPos,
com.fr.third.javassist.bytecode.ConstPool srcCp, byte[] newcode,
com.fr.third.javassist.bytecode.ConstPool destCp, Map classnameMap)
throws com.fr.third.javassist.bytecode.BadBytecode
{
int i2, index;
LdcEntry ldcEntry = null;
for (int i = beginPos; i < endPos; i = i2) {
i2 = com.fr.third.javassist.bytecode.CodeIterator.nextOpcode(code, i);
byte c = code[i];
newcode[i] = c;
switch (c & 0xff) {
case LDC_W :
case LDC2_W :
case GETSTATIC :
case PUTSTATIC :
case GETFIELD :
case PUTFIELD :
case INVOKEVIRTUAL :
case INVOKESPECIAL :
case INVOKESTATIC :
case NEW :
case ANEWARRAY :
case CHECKCAST :
case INSTANCEOF :
copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
classnameMap);
break;
case LDC :
index = code[i + 1] & 0xff;
index = srcCp.copy(index, destCp, classnameMap);
if (index < 0x100)
newcode[i + 1] = (byte)index;
else {
newcode[i] = NOP;
newcode[i + 1] = NOP;
LdcEntry ldc = new LdcEntry();
ldc.where = i;
ldc.index = index;
ldc.next = ldcEntry;
ldcEntry = ldc;
}
break;
case INVOKEINTERFACE :
copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
classnameMap);
newcode[i + 3] = code[i + 3];
newcode[i + 4] = code[i + 4];
break;
case INVOKEDYNAMIC :
copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
classnameMap);
newcode[i + 3] = 0;
newcode[i + 4] = 0;
break;
case MULTIANEWARRAY :
copyConstPoolInfo(i + 1, code, srcCp, newcode, destCp,
classnameMap);
newcode[i + 3] = code[i + 3];
break;
default :
while (++i < i2)
newcode[i] = code[i];
break;
}
}
return ldcEntry;
}
private static void copyConstPoolInfo(int i, byte[] code, com.fr.third.javassist.bytecode.ConstPool srcCp,
byte[] newcode, ConstPool destCp,
Map classnameMap) {
int index = ((code[i] & 0xff) << 8) | (code[i + 1] & 0xff);
index = srcCp.copy(index, destCp, classnameMap);
newcode[i] = (byte)(index >> 8);
newcode[i + 1] = (byte)index;
}
static class LdcEntry {
LdcEntry next;
int where;
int index;
static byte[] doit(byte[] code, LdcEntry ldc, ExceptionTable etable,
CodeAttribute ca)
throws com.fr.third.javassist.bytecode.BadBytecode
{
if (ldc != null)
code = com.fr.third.javassist.bytecode.CodeIterator.changeLdcToLdcW(code, etable, ca, ldc);
/* The original code was the following:
while (ldc != null) {
int where = ldc.where;
code = CodeIterator.insertGapCore0(code, where, 1, false, etable, ca);
code[where] = (byte)Opcode.LDC_W;
ByteArray.write16bit(ldc.index, code, where + 1);
ldc = ldc.next;
}
But this code does not support a large method > 32KB.
*/
return code;
}
}
/**
* Changes the index numbers of the local variables
* to append a new parameter.
* This method does not update <code>LocalVariableAttribute</code>,
* <code>LocalVariableTypeAttribute</code>,
* <code>StackMapTable</code>, or <code>StackMap</code>.
* These attributes must be explicitly updated.
*
* @param where the index of the new parameter.
* @param size the type size of the new parameter (1 or 2).
*
* @see LocalVariableAttribute#shiftIndex(int, int)
* @see LocalVariableTypeAttribute#shiftIndex(int, int)
* @see StackMapTable#insertLocal(int, int, int)
* @see StackMap#insertLocal(int, int, int)
*/
public void insertLocalVar(int where, int size) throws com.fr.third.javassist.bytecode.BadBytecode {
com.fr.third.javassist.bytecode.CodeIterator ci = iterator();
while (ci.hasNext())
shiftIndex(ci, where, size);
setMaxLocals(getMaxLocals() + size);
}
/**
* @param lessThan If the index of the local variable is
* less than this value, it does not change.
* Otherwise, the index is increased.
* @param delta the indexes of the local variables are
* increased by this value.
*/
private static void shiftIndex(com.fr.third.javassist.bytecode.CodeIterator ci, int lessThan, int delta) throws com.fr.third.javassist.bytecode.BadBytecode {
int index = ci.next();
int opcode = ci.byteAt(index);
if (opcode < ILOAD)
return;
else if (opcode < IASTORE) {
if (opcode < ILOAD_0) {
// iload, lload, fload, dload, aload
shiftIndex8(ci, index, opcode, lessThan, delta);
}
else if (opcode < IALOAD) {
// iload_0, ..., aload_3
shiftIndex0(ci, index, opcode, lessThan, delta, ILOAD_0, ILOAD);
}
else if (opcode < ISTORE)
return;
else if (opcode < ISTORE_0) {
// istore, lstore, ...
shiftIndex8(ci, index, opcode, lessThan, delta);
}
else {
// istore_0, ..., astore_3
shiftIndex0(ci, index, opcode, lessThan, delta, ISTORE_0, ISTORE);
}
}
else if (opcode == IINC) {
int var = ci.byteAt(index + 1);
if (var < lessThan)
return;
var += delta;
if (var < 0x100)
ci.writeByte(var, index + 1);
else {
int plus = (byte)ci.byteAt(index + 2);
int pos = ci.insertExGap(3);
ci.writeByte(WIDE, pos - 3);
ci.writeByte(IINC, pos - 2);
ci.write16bit(var, pos - 1);
ci.write16bit(plus, pos + 1);
}
}
else if (opcode == RET)
shiftIndex8(ci, index, opcode, lessThan, delta);
else if (opcode == WIDE) {
int var = ci.u16bitAt(index + 2);
if (var < lessThan)
return;
var += delta;
ci.write16bit(var, index + 2);
}
}
private static void shiftIndex8(com.fr.third.javassist.bytecode.CodeIterator ci, int index, int opcode,
int lessThan, int delta)
throws com.fr.third.javassist.bytecode.BadBytecode
{
int var = ci.byteAt(index + 1);
if (var < lessThan)
return;
var += delta;
if (var < 0x100)
ci.writeByte(var, index + 1);
else {
int pos = ci.insertExGap(2);
ci.writeByte(WIDE, pos - 2);
ci.writeByte(opcode, pos - 1);
ci.write16bit(var, pos);
}
}
private static void shiftIndex0(CodeIterator ci, int index, int opcode,
int lessThan, int delta,
int opcode_i_0, int opcode_i)
throws BadBytecode
{
int var = (opcode - opcode_i_0) % 4;
if (var < lessThan)
return;
var += delta;
if (var < 4)
ci.writeByte(opcode + delta, index);
else {
opcode = (opcode - opcode_i_0) / 4 + opcode_i;
if (var < 0x100) {
int pos = ci.insertExGap(1);
ci.writeByte(opcode, pos - 1);
ci.writeByte(var, pos);
}
else {
int pos = ci.insertExGap(3);
ci.writeByte(WIDE, pos - 1);
ci.writeByte(opcode, pos);
ci.write16bit(var, pos + 1);
}
}
}
}

1599
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/CodeIterator.java

File diff suppressed because it is too large Load Diff

1991
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ConstPool.java

File diff suppressed because it is too large Load Diff

73
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ConstantAttribute.java

@ -1,73 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.util.Map;
import java.io.IOException;
/**
* <code>ConstantValue_attribute</code>.
*/
public class ConstantAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"ConstantValue"</code>.
*/
public static final String tag = "ConstantValue";
ConstantAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a ConstantValue attribute.
*
* @param cp a constant pool table.
* @param index <code>constantvalue_index</code>
* of <code>ConstantValue_attribute</code>.
*/
public ConstantAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int index) {
super(cp, tag);
byte[] bvalue = new byte[2];
bvalue[0] = (byte)(index >>> 8);
bvalue[1] = (byte)index;
set(bvalue);
}
/**
* Returns <code>constantvalue_index</code>.
*/
public int getConstantValue() {
return ByteArray.readU16bit(get(), 0);
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
int index = getConstPool().copy(getConstantValue(), newCp,
classnames);
return new ConstantAttribute(newCp, index);
}
}

56
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/DeprecatedAttribute.java

@ -1,56 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>Deprecated_attribute</code>.
*/
public class DeprecatedAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"Deprecated"</code>.
*/
public static final String tag = "Deprecated";
DeprecatedAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a Deprecated attribute.
*
* @param cp a constant pool table.
*/
public DeprecatedAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
super(cp, tag, new byte[0]);
}
/**
* Makes a copy.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames should be null.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
return new DeprecatedAttribute(newCp);
}
}

872
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Descriptor.java

@ -1,872 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.CtPrimitiveType;
import com.fr.third.javassist.NotFoundException;
import java.util.Map;
/**
* A support class for dealing with descriptors.
*
* <p>See chapter 4.3 in "The Java Virtual Machine Specification (2nd ed.)"
*/
public class Descriptor {
/**
* Converts a class name into the internal representation used in
* the JVM.
*
* <p>Note that <code>toJvmName(toJvmName(s))</code> is equivalent
* to <code>toJvmName(s)</code>.
*/
public static String toJvmName(String classname) {
return classname.replace('.', '/');
}
/**
* Converts a class name from the internal representation used in
* the JVM to the normal one used in Java.
* This method does not deal with an array type name such as
* "[Ljava/lang/Object;" and "[I;". For such names, use
* <code>toClassName()</code>.
*
* @see #toClassName(String)
*/
public static String toJavaName(String classname) {
return classname.replace('/', '.');
}
/**
* Returns the internal representation of the class name in the
* JVM.
*/
public static String toJvmName(CtClass clazz) {
if (clazz.isArray())
return of(clazz);
else
return toJvmName(clazz.getName());
}
/**
* Converts to a Java class name from a descriptor.
*
* @param descriptor type descriptor.
*/
public static String toClassName(String descriptor) {
int arrayDim = 0;
int i = 0;
char c = descriptor.charAt(0);
while (c == '[') {
++arrayDim;
c = descriptor.charAt(++i);
}
String name;
if (c == 'L') {
int i2 = descriptor.indexOf(';', i++);
name = descriptor.substring(i, i2).replace('/', '.');
i = i2;
}
else if (c == 'V')
name = "void";
else if (c == 'I')
name = "int";
else if (c == 'B')
name = "byte";
else if (c == 'J')
name = "long";
else if (c == 'D')
name = "double";
else if (c == 'F')
name = "float";
else if (c == 'C')
name = "char";
else if (c == 'S')
name = "short";
else if (c == 'Z')
name = "boolean";
else
throw new RuntimeException("bad descriptor: " + descriptor);
if (i + 1 != descriptor.length())
throw new RuntimeException("multiple descriptors?: " + descriptor);
if (arrayDim == 0)
return name;
else {
StringBuffer sbuf = new StringBuffer(name);
do {
sbuf.append("[]");
} while (--arrayDim > 0);
return sbuf.toString();
}
}
/**
* Converts to a descriptor from a Java class name
*/
public static String of(String classname) {
if (classname.equals("void"))
return "V";
else if (classname.equals("int"))
return "I";
else if (classname.equals("byte"))
return "B";
else if (classname.equals("long"))
return "J";
else if (classname.equals("double"))
return "D";
else if (classname.equals("float"))
return "F";
else if (classname.equals("char"))
return "C";
else if (classname.equals("short"))
return "S";
else if (classname.equals("boolean"))
return "Z";
else
return "L" + toJvmName(classname) + ";";
}
/**
* Substitutes a class name
* in the given descriptor string.
*
* @param desc descriptor string
* @param oldname replaced JVM class name
* @param newname substituted JVM class name
*
* @see Descriptor#toJvmName(String)
*/
public static String rename(String desc, String oldname, String newname) {
if (desc.indexOf(oldname) < 0)
return desc;
StringBuffer newdesc = new StringBuffer();
int head = 0;
int i = 0;
for (;;) {
int j = desc.indexOf('L', i);
if (j < 0)
break;
else if (desc.startsWith(oldname, j + 1)
&& desc.charAt(j + oldname.length() + 1) == ';') {
newdesc.append(desc.substring(head, j));
newdesc.append('L');
newdesc.append(newname);
newdesc.append(';');
head = i = j + oldname.length() + 2;
}
else {
i = desc.indexOf(';', j) + 1;
if (i < 1)
break; // ';' was not found.
}
}
if (head == 0)
return desc;
else {
int len = desc.length();
if (head < len)
newdesc.append(desc.substring(head, len));
return newdesc.toString();
}
}
/**
* Substitutes class names in the given descriptor string
* according to the given <code>map</code>.
*
* @param map a map between replaced and substituted
* JVM class names.
* @see Descriptor#toJvmName(String)
*/
public static String rename(String desc, Map map) {
if (map == null)
return desc;
StringBuffer newdesc = new StringBuffer();
int head = 0;
int i = 0;
for (;;) {
int j = desc.indexOf('L', i);
if (j < 0)
break;
int k = desc.indexOf(';', j);
if (k < 0)
break;
i = k + 1;
String name = desc.substring(j + 1, k);
String name2 = (String)map.get(name);
if (name2 != null) {
newdesc.append(desc.substring(head, j));
newdesc.append('L');
newdesc.append(name2);
newdesc.append(';');
head = i;
}
}
if (head == 0)
return desc;
else {
int len = desc.length();
if (head < len)
newdesc.append(desc.substring(head, len));
return newdesc.toString();
}
}
/**
* Returns the descriptor representing the given type.
*/
public static String of(CtClass type) {
StringBuffer sbuf = new StringBuffer();
toDescriptor(sbuf, type);
return sbuf.toString();
}
private static void toDescriptor(StringBuffer desc, CtClass type) {
if (type.isArray()) {
desc.append('[');
try {
toDescriptor(desc, type.getComponentType());
}
catch (NotFoundException e) {
desc.append('L');
String name = type.getName();
desc.append(toJvmName(name.substring(0, name.length() - 2)));
desc.append(';');
}
}
else if (type.isPrimitive()) {
CtPrimitiveType pt = (CtPrimitiveType)type;
desc.append(pt.getDescriptor());
}
else { // class type
desc.append('L');
desc.append(type.getName().replace('.', '/'));
desc.append(';');
}
}
/**
* Returns the descriptor representing a constructor receiving
* the given parameter types.
*
* @param paramTypes parameter types
*/
public static String ofConstructor(CtClass[] paramTypes) {
return ofMethod(CtClass.voidType, paramTypes);
}
/**
* Returns the descriptor representing a method that receives
* the given parameter types and returns the given type.
*
* @param returnType return type
* @param paramTypes parameter types
*/
public static String ofMethod(CtClass returnType, CtClass[] paramTypes) {
StringBuffer desc = new StringBuffer();
desc.append('(');
if (paramTypes != null) {
int n = paramTypes.length;
for (int i = 0; i < n; ++i)
toDescriptor(desc, paramTypes[i]);
}
desc.append(')');
if (returnType != null)
toDescriptor(desc, returnType);
return desc.toString();
}
/**
* Returns the descriptor representing a list of parameter types.
* For example, if the given parameter types are two <code>int</code>,
* then this method returns <code>"(II)"</code>.
*
* @param paramTypes parameter types
*/
public static String ofParameters(CtClass[] paramTypes) {
return ofMethod(null, paramTypes);
}
/**
* Appends a parameter type to the parameter list represented
* by the given descriptor.
*
* <p><code>classname</code> must not be an array type.
*
* @param classname parameter type (not primitive type)
* @param desc descriptor
*/
public static String appendParameter(String classname, String desc) {
int i = desc.indexOf(')');
if (i < 0)
return desc;
else {
StringBuffer newdesc = new StringBuffer();
newdesc.append(desc.substring(0, i));
newdesc.append('L');
newdesc.append(classname.replace('.', '/'));
newdesc.append(';');
newdesc.append(desc.substring(i));
return newdesc.toString();
}
}
/**
* Inserts a parameter type at the beginning of the parameter
* list represented
* by the given descriptor.
*
* <p><code>classname</code> must not be an array type.
*
* @param classname parameter type (not primitive type)
* @param desc descriptor
*/
public static String insertParameter(String classname, String desc) {
if (desc.charAt(0) != '(')
return desc;
else
return "(L" + classname.replace('.', '/') + ';'
+ desc.substring(1);
}
/**
* Appends a parameter type to the parameter list represented
* by the given descriptor. The appended parameter becomes
* the last parameter.
*
* @param type the type of the appended parameter.
* @param descriptor the original descriptor.
*/
public static String appendParameter(CtClass type, String descriptor) {
int i = descriptor.indexOf(')');
if (i < 0)
return descriptor;
else {
StringBuffer newdesc = new StringBuffer();
newdesc.append(descriptor.substring(0, i));
toDescriptor(newdesc, type);
newdesc.append(descriptor.substring(i));
return newdesc.toString();
}
}
/**
* Inserts a parameter type at the beginning of the parameter
* list represented
* by the given descriptor.
*
* @param type the type of the inserted parameter.
* @param descriptor the descriptor of the method.
*/
public static String insertParameter(CtClass type,
String descriptor) {
if (descriptor.charAt(0) != '(')
return descriptor;
else
return "(" + of(type) + descriptor.substring(1);
}
/**
* Changes the return type included in the given descriptor.
*
* <p><code>classname</code> must not be an array type.
*
* @param classname return type
* @param desc descriptor
*/
public static String changeReturnType(String classname, String desc) {
int i = desc.indexOf(')');
if (i < 0)
return desc;
else {
StringBuffer newdesc = new StringBuffer();
newdesc.append(desc.substring(0, i + 1));
newdesc.append('L');
newdesc.append(classname.replace('.', '/'));
newdesc.append(';');
return newdesc.toString();
}
}
/**
* Returns the <code>CtClass</code> objects representing the parameter
* types specified by the given descriptor.
*
* @param desc descriptor
* @param cp the class pool used for obtaining
* a <code>CtClass</code> object.
*/
public static CtClass[] getParameterTypes(String desc, ClassPool cp)
throws NotFoundException
{
if (desc.charAt(0) != '(')
return null;
else {
int num = numOfParameters(desc);
CtClass[] args = new CtClass[num];
int n = 0;
int i = 1;
do {
i = toCtClass(cp, desc, i, args, n++);
} while (i > 0);
return args;
}
}
/**
* Returns true if the list of the parameter types of desc1 is equal to
* that of desc2.
* For example, "(II)V" and "(II)I" are equal.
*/
public static boolean eqParamTypes(String desc1, String desc2) {
if (desc1.charAt(0) != '(')
return false;
for (int i = 0; true; ++i) {
char c = desc1.charAt(i);
if (c != desc2.charAt(i))
return false;
if (c == ')')
return true;
}
}
/**
* Returns the signature of the given descriptor. The signature does
* not include the return type. For example, the signature of "(I)V"
* is "(I)".
*/
public static String getParamDescriptor(String decl) {
return decl.substring(0, decl.indexOf(')') + 1);
}
/**
* Returns the <code>CtClass</code> object representing the return
* type specified by the given descriptor.
*
* @param desc descriptor
* @param cp the class pool used for obtaining
* a <code>CtClass</code> object.
*/
public static CtClass getReturnType(String desc, ClassPool cp)
throws NotFoundException
{
int i = desc.indexOf(')');
if (i < 0)
return null;
else {
CtClass[] type = new CtClass[1];
toCtClass(cp, desc, i + 1, type, 0);
return type[0];
}
}
/**
* Returns the number of the prameters included in the given
* descriptor.
*
* @param desc descriptor
*/
public static int numOfParameters(String desc) {
int n = 0;
int i = 1;
for (;;) {
char c = desc.charAt(i);
if (c == ')')
break;
while (c == '[')
c = desc.charAt(++i);
if (c == 'L') {
i = desc.indexOf(';', i) + 1;
if (i <= 0)
throw new IndexOutOfBoundsException("bad descriptor");
}
else
++i;
++n;
}
return n;
}
/**
* Returns a <code>CtClass</code> object representing the type
* specified by the given descriptor.
*
* <p>This method works even if the package-class separator is
* not <code>/</code> but <code>.</code> (period). For example,
* it accepts <code>Ljava.lang.Object;</code>
* as well as <code>Ljava/lang/Object;</code>.
*
* @param desc descriptor.
* @param cp the class pool used for obtaining
* a <code>CtClass</code> object.
*/
public static CtClass toCtClass(String desc, ClassPool cp)
throws NotFoundException
{
CtClass[] clazz = new CtClass[1];
int res = toCtClass(cp, desc, 0, clazz, 0);
if (res >= 0)
return clazz[0];
else {
// maybe, you forgot to surround the class name with
// L and ;. It violates the protocol, but I'm tolerant...
return cp.get(desc.replace('/', '.'));
}
}
private static int toCtClass(ClassPool cp, String desc, int i,
CtClass[] args, int n)
throws NotFoundException
{
int i2;
String name;
int arrayDim = 0;
char c = desc.charAt(i);
while (c == '[') {
++arrayDim;
c = desc.charAt(++i);
}
if (c == 'L') {
i2 = desc.indexOf(';', ++i);
name = desc.substring(i, i2++).replace('/', '.');
}
else {
CtClass type = toPrimitiveClass(c);
if (type == null)
return -1; // error
i2 = i + 1;
if (arrayDim == 0) {
args[n] = type;
return i2; // neither an array type or a class type
}
else
name = type.getName();
}
if (arrayDim > 0) {
StringBuffer sbuf = new StringBuffer(name);
while (arrayDim-- > 0)
sbuf.append("[]");
name = sbuf.toString();
}
args[n] = cp.get(name);
return i2;
}
static CtClass toPrimitiveClass(char c) {
CtClass type = null;
switch (c) {
case 'Z' :
type = CtClass.booleanType;
break;
case 'C' :
type = CtClass.charType;
break;
case 'B' :
type = CtClass.byteType;
break;
case 'S' :
type = CtClass.shortType;
break;
case 'I' :
type = CtClass.intType;
break;
case 'J' :
type = CtClass.longType;
break;
case 'F' :
type = CtClass.floatType;
break;
case 'D' :
type = CtClass.doubleType;
break;
case 'V' :
type = CtClass.voidType;
break;
}
return type;
}
/**
* Computes the dimension of the array represented by the given
* descriptor. For example, if the descriptor is <code>"[[I"</code>,
* then this method returns 2.
*
* @param desc the descriptor.
* @return 0 if the descriptor does not represent an array type.
*/
public static int arrayDimension(String desc) {
int dim = 0;
while (desc.charAt(dim) == '[')
++dim;
return dim;
}
/**
* Returns the descriptor of the type of the array component.
* For example, if the given descriptor is
* <code>"[[Ljava/lang/String;"</code> and the given dimension is 2,
* then this method returns <code>"Ljava/lang/String;"</code>.
*
* @param desc the descriptor.
* @param dim the array dimension.
*/
public static String toArrayComponent(String desc, int dim) {
return desc.substring(dim);
}
/**
* Computes the data size specified by the given descriptor.
* For example, if the descriptor is "D", this method returns 2.
*
* <p>If the descriptor represents a method type, this method returns
* (the size of the returned value) - (the sum of the data sizes
* of all the parameters). For example, if the descriptor is
* <code>"(I)D"</code>, then this method returns 1 (= 2 - 1).
*
* @param desc descriptor
*/
public static int dataSize(String desc) {
return dataSize(desc, true);
}
/**
* Computes the data size of parameters.
* If one of the parameters is double type, the size of that parameter
* is 2 words. For example, if the given descriptor is
* <code>"(IJ)D"</code>, then this method returns 3. The size of the
* return type is not computed.
*
* @param desc a method descriptor.
*/
public static int paramSize(String desc) {
return -dataSize(desc, false);
}
private static int dataSize(String desc, boolean withRet) {
int n = 0;
char c = desc.charAt(0);
if (c == '(') {
int i = 1;
for (;;) {
c = desc.charAt(i);
if (c == ')') {
c = desc.charAt(i + 1);
break;
}
boolean array = false;
while (c == '[') {
array = true;
c = desc.charAt(++i);
}
if (c == 'L') {
i = desc.indexOf(';', i) + 1;
if (i <= 0)
throw new IndexOutOfBoundsException("bad descriptor");
}
else
++i;
if (!array && (c == 'J' || c == 'D'))
n -= 2;
else
--n;
}
}
if (withRet)
if (c == 'J' || c == 'D')
n += 2;
else if (c != 'V')
++n;
return n;
}
/**
* Returns a human-readable representation of the
* given descriptor. For example, <code>Ljava/lang/Object;</code>
* is converted into <code>java.lang.Object</code>.
* <code>(I[I)V</code> is converted into <code>(int, int[])</code>
* (the return type is ignored).
*/
public static String toString(String desc) {
return PrettyPrinter.toString(desc);
}
static class PrettyPrinter {
static String toString(String desc) {
StringBuffer sbuf = new StringBuffer();
if (desc.charAt(0) == '(') {
int pos = 1;
sbuf.append('(');
while (desc.charAt(pos) != ')') {
if (pos > 1)
sbuf.append(',');
pos = readType(sbuf, pos, desc);
}
sbuf.append(')');
}
else
readType(sbuf, 0, desc);
return sbuf.toString();
}
static int readType(StringBuffer sbuf, int pos, String desc) {
char c = desc.charAt(pos);
int arrayDim = 0;
while (c == '[') {
arrayDim++;
c = desc.charAt(++pos);
}
if (c == 'L')
while (true) {
c = desc.charAt(++pos);
if (c == ';')
break;
if (c == '/')
c = '.';
sbuf.append(c);
}
else {
CtClass t = toPrimitiveClass(c);
sbuf.append(t.getName());
}
while (arrayDim-- > 0)
sbuf.append("[]");
return pos + 1;
}
}
/**
* An Iterator over a descriptor.
*/
public static class Iterator {
private String desc;
private int index, curPos;
private boolean param;
/**
* Constructs an iterator.
*
* @param s descriptor.
*/
public Iterator(String s) {
desc = s;
index = curPos = 0;
param = false;
}
/**
* Returns true if the iteration has more elements.
*/
public boolean hasNext() {
return index < desc.length();
}
/**
* Returns true if the current element is a parameter type.
*/
public boolean isParameter() { return param; }
/**
* Returns the first character of the current element.
*/
public char currentChar() { return desc.charAt(curPos); }
/**
* Returns true if the current element is double or long type.
*/
public boolean is2byte() {
char c = currentChar();
return c == 'D' || c == 'J';
}
/**
* Returns the position of the next type character.
* That type character becomes a new current element.
*/
public int next() {
int nextPos = index;
char c = desc.charAt(nextPos);
if (c == '(') {
++index;
c = desc.charAt(++nextPos);
param = true;
}
if (c == ')') {
++index;
c = desc.charAt(++nextPos);
param = false;
}
while (c == '[')
c = desc.charAt(++nextPos);
if (c == 'L') {
nextPos = desc.indexOf(';', nextPos) + 1;
if (nextPos <= 0)
throw new IndexOutOfBoundsException("bad descriptor");
}
else
++nextPos;
curPos = index;
index = nextPos;
return curPos;
}
}
}

31
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/DuplicateMemberException.java

@ -1,31 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import com.fr.third.javassist.CannotCompileException;
/**
* An exception thrown when adding a duplicate member is requested.
*
* @see com.fr.third.javassist.bytecode.ClassFile#addMethod(MethodInfo)
* @see ClassFile#addField(FieldInfo)
*/
public class DuplicateMemberException extends CannotCompileException {
public DuplicateMemberException(String msg) {
super(msg);
}
}

134
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/EnclosingMethodAttribute.java

@ -1,134 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>EnclosingMethod_attribute</code>.
*/
public class EnclosingMethodAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"EnclosingMethod"</code>.
*/
public static final String tag = "EnclosingMethod";
EnclosingMethodAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs an EnclosingMethod attribute.
*
* @param cp a constant pool table.
* @param className the name of the innermost enclosing class.
* @param methodName the name of the enclosing method.
* @param methodDesc the descriptor of the enclosing method.
*/
public EnclosingMethodAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String className,
String methodName, String methodDesc) {
super(cp, tag);
int ci = cp.addClassInfo(className);
int ni = cp.addNameAndTypeInfo(methodName, methodDesc);
byte[] bvalue = new byte[4];
bvalue[0] = (byte)(ci >>> 8);
bvalue[1] = (byte)ci;
bvalue[2] = (byte)(ni >>> 8);
bvalue[3] = (byte)ni;
set(bvalue);
}
/**
* Constructs an EnclosingMethod attribute.
* The value of <code>method_index</code> is set to 0.
*
* @param cp a constant pool table.
* @param className the name of the innermost enclosing class.
*/
public EnclosingMethodAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String className) {
super(cp, tag);
int ci = cp.addClassInfo(className);
int ni = 0;
byte[] bvalue = new byte[4];
bvalue[0] = (byte)(ci >>> 8);
bvalue[1] = (byte)ci;
bvalue[2] = (byte)(ni >>> 8);
bvalue[3] = (byte)ni;
set(bvalue);
}
/**
* Returns the value of <code>class_index</code>.
*/
public int classIndex() {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(get(), 0);
}
/**
* Returns the value of <code>method_index</code>.
*/
public int methodIndex() {
return ByteArray.readU16bit(get(), 2);
}
/**
* Returns the name of the class specified by <code>class_index</code>.
*/
public String className() {
return getConstPool().getClassInfo(classIndex());
}
/**
* Returns the method name specified by <code>method_index</code>.
*/
public String methodName() {
com.fr.third.javassist.bytecode.ConstPool cp = getConstPool();
int mi = methodIndex();
int ni = cp.getNameAndTypeName(mi);
return cp.getUtf8Info(ni);
}
/**
* Returns the method descriptor specified by <code>method_index</code>.
*/
public String methodDescriptor() {
com.fr.third.javassist.bytecode.ConstPool cp = getConstPool();
int mi = methodIndex();
int ti = cp.getNameAndTypeDescriptor(mi);
return cp.getUtf8Info(ti);
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
if (methodIndex() == 0)
return new EnclosingMethodAttribute(newCp, className());
else
return new EnclosingMethodAttribute(newCp, className(),
methodName(), methodDescriptor());
}
}

281
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ExceptionTable.java

@ -1,281 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
class ExceptionTableEntry {
int startPc;
int endPc;
int handlerPc;
int catchType;
ExceptionTableEntry(int start, int end, int handle, int type) {
startPc = start;
endPc = end;
handlerPc = handle;
catchType = type;
}
}
/**
* <code>exception_table[]</code> of <code>Code_attribute</code>.
*/
public class ExceptionTable implements Cloneable {
private com.fr.third.javassist.bytecode.ConstPool constPool;
private ArrayList entries;
/**
* Constructs an <code>exception_table[]</code>.
*
* @param cp constant pool table.
*/
public ExceptionTable(com.fr.third.javassist.bytecode.ConstPool cp) {
constPool = cp;
entries = new ArrayList();
}
ExceptionTable(com.fr.third.javassist.bytecode.ConstPool cp, DataInputStream in) throws IOException {
constPool = cp;
int length = in.readUnsignedShort();
ArrayList list = new ArrayList(length);
for (int i = 0; i < length; ++i) {
int start = in.readUnsignedShort();
int end = in.readUnsignedShort();
int handle = in.readUnsignedShort();
int type = in.readUnsignedShort();
list.add(new ExceptionTableEntry(start, end, handle, type));
}
entries = list;
}
/**
* Creates and returns a copy of this object.
* The constant pool object is shared between this object
* and the cloned object.
*/
public Object clone() throws CloneNotSupportedException {
ExceptionTable r = (ExceptionTable)super.clone();
r.entries = new ArrayList(entries);
return r;
}
/**
* Returns <code>exception_table_length</code>, which is the number
* of entries in the <code>exception_table[]</code>.
*/
public int size() {
return entries.size();
}
/**
* Returns <code>startPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
*/
public int startPc(int nth) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
return e.startPc;
}
/**
* Sets <code>startPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
* @param value new value.
*/
public void setStartPc(int nth, int value) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
e.startPc = value;
}
/**
* Returns <code>endPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
*/
public int endPc(int nth) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
return e.endPc;
}
/**
* Sets <code>endPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
* @param value new value.
*/
public void setEndPc(int nth, int value) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
e.endPc = value;
}
/**
* Returns <code>handlerPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
*/
public int handlerPc(int nth) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
return e.handlerPc;
}
/**
* Sets <code>handlerPc</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
* @param value new value.
*/
public void setHandlerPc(int nth, int value) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
e.handlerPc = value;
}
/**
* Returns <code>catchType</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
* @return an index into the <code>constant_pool</code> table,
* or zero if this exception handler is for all exceptions.
*/
public int catchType(int nth) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
return e.catchType;
}
/**
* Sets <code>catchType</code> of the <i>n</i>-th entry.
*
* @param nth the <i>n</i>-th (&gt;= 0).
* @param value new value.
*/
public void setCatchType(int nth, int value) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(nth);
e.catchType = value;
}
/**
* Copies the given exception table at the specified position
* in the table.
*
* @param index index (&gt;= 0) at which the entry is to be inserted.
* @param offset the offset added to the code position.
*/
public void add(int index, ExceptionTable table, int offset) {
int len = table.size();
while (--len >= 0) {
ExceptionTableEntry e
= (ExceptionTableEntry)table.entries.get(len);
add(index, e.startPc + offset, e.endPc + offset,
e.handlerPc + offset, e.catchType);
}
}
/**
* Adds a new entry at the specified position in the table.
*
* @param index index (&gt;= 0) at which the entry is to be inserted.
* @param start <code>startPc</code>
* @param end <code>endPc</code>
* @param handler <code>handlerPc</code>
* @param type <code>catchType</code>
*/
public void add(int index, int start, int end, int handler, int type) {
if (start < end)
entries.add(index,
new ExceptionTableEntry(start, end, handler, type));
}
/**
* Appends a new entry at the end of the table.
*
* @param start <code>startPc</code>
* @param end <code>endPc</code>
* @param handler <code>handlerPc</code>
* @param type <code>catchType</code>
*/
public void add(int start, int end, int handler, int type) {
if (start < end)
entries.add(new ExceptionTableEntry(start, end, handler, type));
}
/**
* Removes the entry at the specified position in the table.
*
* @param index the index of the removed entry.
*/
public void remove(int index) {
entries.remove(index);
}
/**
* Makes a copy of this <code>exception_table[]</code>.
* Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public ExceptionTable copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
ExceptionTable et = new ExceptionTable(newCp);
ConstPool srcCp = constPool;
int len = size();
for (int i = 0; i < len; ++i) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i);
int type = srcCp.copy(e.catchType, newCp, classnames);
et.add(e.startPc, e.endPc, e.handlerPc, type);
}
return et;
}
void shiftPc(int where, int gapLength, boolean exclusive) {
int len = size();
for (int i = 0; i < len; ++i) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i);
e.startPc = shiftPc(e.startPc, where, gapLength, exclusive);
e.endPc = shiftPc(e.endPc, where, gapLength, exclusive);
e.handlerPc = shiftPc(e.handlerPc, where, gapLength, exclusive);
}
}
private static int shiftPc(int pc, int where, int gapLength,
boolean exclusive) {
if (pc > where || (exclusive && pc == where))
pc += gapLength;
return pc;
}
void write(DataOutputStream out) throws IOException {
int len = size();
out.writeShort(len); // exception_table_length
for (int i = 0; i < len; ++i) {
ExceptionTableEntry e = (ExceptionTableEntry)entries.get(i);
out.writeShort(e.startPc);
out.writeShort(e.endPc);
out.writeShort(e.handlerPc);
out.writeShort(e.catchType);
}
}
}

174
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ExceptionsAttribute.java

@ -1,174 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>Exceptions_attribute</code>.
*/
public class ExceptionsAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"Exceptions"</code>.
*/
public static final String tag = "Exceptions";
ExceptionsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a copy of an exceptions attribute.
*
* @param cp constant pool table.
* @param src source attribute.
*/
private ExceptionsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, ExceptionsAttribute src,
Map classnames) {
super(cp, tag);
copyFrom(src, classnames);
}
/**
* Constructs a new exceptions attribute.
*
* @param cp constant pool table.
*/
public ExceptionsAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
super(cp, tag);
byte[] data = new byte[2];
data[0] = data[1] = 0; // empty
this.info = data;
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names. It can be <code>null</code>.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
return new ExceptionsAttribute(newCp, this, classnames);
}
/**
* Copies the contents from a source attribute.
* Specified class names are replaced during the copy.
*
* @param srcAttr source Exceptions attribute
* @param classnames pairs of replaced and substituted
* class names.
*/
private void copyFrom(ExceptionsAttribute srcAttr, Map classnames) {
com.fr.third.javassist.bytecode.ConstPool srcCp = srcAttr.constPool;
ConstPool destCp = this.constPool;
byte[] src = srcAttr.info;
int num = src.length;
byte[] dest = new byte[num];
dest[0] = src[0];
dest[1] = src[1]; // the number of elements.
for (int i = 2; i < num; i += 2) {
int index = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, i);
com.fr.third.javassist.bytecode.ByteArray.write16bit(srcCp.copy(index, destCp, classnames),
dest, i);
}
this.info = dest;
}
/**
* Returns <code>exception_index_table[]</code>.
*/
public int[] getExceptionIndexes() {
byte[] blist = info;
int n = blist.length;
if (n <= 2)
return null;
int[] elist = new int[n / 2 - 1];
int k = 0;
for (int j = 2; j < n; j += 2)
elist[k++] = ((blist[j] & 0xff) << 8) | (blist[j + 1] & 0xff);
return elist;
}
/**
* Returns the names of exceptions that the method may throw.
*/
public String[] getExceptions() {
byte[] blist = info;
int n = blist.length;
if (n <= 2)
return null;
String[] elist = new String[n / 2 - 1];
int k = 0;
for (int j = 2; j < n; j += 2) {
int index = ((blist[j] & 0xff) << 8) | (blist[j + 1] & 0xff);
elist[k++] = constPool.getClassInfo(index);
}
return elist;
}
/**
* Sets <code>exception_index_table[]</code>.
*/
public void setExceptionIndexes(int[] elist) {
int n = elist.length;
byte[] blist = new byte[n * 2 + 2];
com.fr.third.javassist.bytecode.ByteArray.write16bit(n, blist, 0);
for (int i = 0; i < n; ++i)
com.fr.third.javassist.bytecode.ByteArray.write16bit(elist[i], blist, i * 2 + 2);
info = blist;
}
/**
* Sets the names of exceptions that the method may throw.
*/
public void setExceptions(String[] elist) {
int n = elist.length;
byte[] blist = new byte[n * 2 + 2];
com.fr.third.javassist.bytecode.ByteArray.write16bit(n, blist, 0);
for (int i = 0; i < n; ++i)
ByteArray.write16bit(constPool.addClassInfo(elist[i]),
blist, i * 2 + 2);
info = blist;
}
/**
* Returns <code>number_of_exceptions</code>.
*/
public int tableLength() { return info.length / 2 - 1; }
/**
* Returns the value of <code>exception_index_table[nth]</code>.
*/
public int getException(int nth) {
int index = nth * 2 + 2; // nth >= 0
return ((info[index] & 0xff) << 8) | (info[index + 1] & 0xff);
}
}

269
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/FieldInfo.java

@ -1,269 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import com.fr.third.javassist.CtField;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
/**
* <code>field_info</code> structure.
*
* @see CtField#getFieldInfo()
*/
public final class FieldInfo {
com.fr.third.javassist.bytecode.ConstPool constPool;
int accessFlags;
int name;
String cachedName;
String cachedType;
int descriptor;
ArrayList attribute; // may be null.
private FieldInfo(com.fr.third.javassist.bytecode.ConstPool cp) {
constPool = cp;
accessFlags = 0;
attribute = null;
}
/**
* Constructs a <code>field_info</code> structure.
*
* @param cp a constant pool table
* @param fieldName field name
* @param desc field descriptor
*
* @see Descriptor
*/
public FieldInfo(com.fr.third.javassist.bytecode.ConstPool cp, String fieldName, String desc) {
this(cp);
name = cp.addUtf8Info(fieldName);
cachedName = fieldName;
descriptor = cp.addUtf8Info(desc);
}
FieldInfo(com.fr.third.javassist.bytecode.ConstPool cp, DataInputStream in) throws IOException {
this(cp);
read(in);
}
/**
* Returns a string representation of the object.
*/
public String toString() {
return getName() + " " + getDescriptor();
}
/**
* Copies all constant pool items to a given new constant pool
* and replaces the original items with the new ones.
* This is used for garbage collecting the items of removed fields
* and methods.
*
* @param cp the destination
*/
void compact(com.fr.third.javassist.bytecode.ConstPool cp) {
name = cp.addUtf8Info(getName());
descriptor = cp.addUtf8Info(getDescriptor());
attribute = AttributeInfo.copyAll(attribute, cp);
constPool = cp;
}
void prune(com.fr.third.javassist.bytecode.ConstPool cp) {
ArrayList newAttributes = new ArrayList();
AttributeInfo invisibleAnnotations
= getAttribute(AnnotationsAttribute.invisibleTag);
if (invisibleAnnotations != null) {
invisibleAnnotations = invisibleAnnotations.copy(cp, null);
newAttributes.add(invisibleAnnotations);
}
AttributeInfo visibleAnnotations
= getAttribute(AnnotationsAttribute.visibleTag);
if (visibleAnnotations != null) {
visibleAnnotations = visibleAnnotations.copy(cp, null);
newAttributes.add(visibleAnnotations);
}
AttributeInfo signature
= getAttribute(SignatureAttribute.tag);
if (signature != null) {
signature = signature.copy(cp, null);
newAttributes.add(signature);
}
int index = getConstantValue();
if (index != 0) {
index = constPool.copy(index, cp, null);
newAttributes.add(new ConstantAttribute(cp, index));
}
attribute = newAttributes;
name = cp.addUtf8Info(getName());
descriptor = cp.addUtf8Info(getDescriptor());
constPool = cp;
}
/**
* Returns the constant pool table used
* by this <code>field_info</code>.
*/
public ConstPool getConstPool() {
return constPool;
}
/**
* Returns the field name.
*/
public String getName() {
if (cachedName == null)
cachedName = constPool.getUtf8Info(name);
return cachedName;
}
/**
* Sets the field name.
*/
public void setName(String newName) {
name = constPool.addUtf8Info(newName);
cachedName = newName;
}
/**
* Returns the access flags.
*
* @see AccessFlag
*/
public int getAccessFlags() {
return accessFlags;
}
/**
* Sets the access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc) {
accessFlags = acc;
}
/**
* Returns the field descriptor.
*
* @see Descriptor
*/
public String getDescriptor() {
return constPool.getUtf8Info(descriptor);
}
/**
* Sets the field descriptor.
*
* @see Descriptor
*/
public void setDescriptor(String desc) {
if (!desc.equals(getDescriptor()))
descriptor = constPool.addUtf8Info(desc);
}
/**
* Finds a ConstantValue attribute and returns the index into
* the <code>constant_pool</code> table.
*
* @return 0 if a ConstantValue attribute is not found.
*/
public int getConstantValue() {
if ((accessFlags & AccessFlag.STATIC) == 0)
return 0;
ConstantAttribute attr
= (ConstantAttribute)getAttribute(ConstantAttribute.tag);
if (attr == null)
return 0;
else
return attr.getConstantValue();
}
/**
* Returns all the attributes. The returned <code>List</code> object
* is shared with this object. If you add a new attribute to the list,
* the attribute is also added to the field represented by this
* object. If you remove an attribute from the list, it is also removed
* from the field.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes() {
if (attribute == null)
attribute = new ArrayList();
return attribute;
}
/**
* Returns the attribute with the specified name.
* It returns null if the specified attribute is not found.
*
* @param name attribute name
* @see #getAttributes()
*/
public AttributeInfo getAttribute(String name) {
return AttributeInfo.lookup(attribute, name);
}
/**
* Appends an attribute. If there is already an attribute with
* the same name, the new one substitutes for it.
*
* @see #getAttributes()
*/
public void addAttribute(AttributeInfo info) {
if (attribute == null)
attribute = new ArrayList();
AttributeInfo.remove(attribute, info.getName());
attribute.add(info);
}
private void read(DataInputStream in) throws IOException {
accessFlags = in.readUnsignedShort();
name = in.readUnsignedShort();
descriptor = in.readUnsignedShort();
int n = in.readUnsignedShort();
attribute = new ArrayList();
for (int i = 0; i < n; ++i)
attribute.add(AttributeInfo.read(constPool, in));
}
void write(DataOutputStream out) throws IOException {
out.writeShort(accessFlags);
out.writeShort(name);
out.writeShort(descriptor);
if (attribute == null)
out.writeShort(0);
else {
out.writeShort(attribute.size());
AttributeInfo.writeAll(attribute, out);
}
}
}

242
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/InnerClassesAttribute.java

@ -1,242 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.util.Map;
import java.io.IOException;
/**
* <code>InnerClasses_attribute</code>.
*/
public class InnerClassesAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"InnerClasses"</code>.
*/
public static final String tag = "InnerClasses";
InnerClassesAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
private InnerClassesAttribute(com.fr.third.javassist.bytecode.ConstPool cp, byte[] info) {
super(cp, tag, info);
}
/**
* Constructs an empty InnerClasses attribute.
*
* @see #append(String, String, String, int)
*/
public InnerClassesAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
super(cp, tag, new byte[2]);
com.fr.third.javassist.bytecode.ByteArray.write16bit(0, get(), 0);
}
/**
* Returns <code>number_of_classes</code>.
*/
public int tableLength() { return com.fr.third.javassist.bytecode.ByteArray.readU16bit(get(), 0); }
/**
* Returns <code>classes[nth].inner_class_info_index</code>.
*/
public int innerClassIndex(int nth) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(get(), nth * 8 + 2);
}
/**
* Returns the class name indicated
* by <code>classes[nth].inner_class_info_index</code>.
*
* @return null or the class name.
*/
public String innerClass(int nth) {
int i = innerClassIndex(nth);
if (i == 0)
return null;
else
return constPool.getClassInfo(i);
}
/**
* Sets <code>classes[nth].inner_class_info_index</code> to
* the given index.
*/
public void setInnerClassIndex(int nth, int index) {
com.fr.third.javassist.bytecode.ByteArray.write16bit(index, get(), nth * 8 + 2);
}
/**
* Returns <code>classes[nth].outer_class_info_index</code>.
*/
public int outerClassIndex(int nth) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(get(), nth * 8 + 4);
}
/**
* Returns the class name indicated
* by <code>classes[nth].outer_class_info_index</code>.
*
* @return null or the class name.
*/
public String outerClass(int nth) {
int i = outerClassIndex(nth);
if (i == 0)
return null;
else
return constPool.getClassInfo(i);
}
/**
* Sets <code>classes[nth].outer_class_info_index</code> to
* the given index.
*/
public void setOuterClassIndex(int nth, int index) {
com.fr.third.javassist.bytecode.ByteArray.write16bit(index, get(), nth * 8 + 4);
}
/**
* Returns <code>classes[nth].inner_name_index</code>.
*/
public int innerNameIndex(int nth) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(get(), nth * 8 + 6);
}
/**
* Returns the simple class name indicated
* by <code>classes[nth].inner_name_index</code>.
*
* @return null or the class name.
*/
public String innerName(int nth) {
int i = innerNameIndex(nth);
if (i == 0)
return null;
else
return constPool.getUtf8Info(i);
}
/**
* Sets <code>classes[nth].inner_name_index</code> to
* the given index.
*/
public void setInnerNameIndex(int nth, int index) {
com.fr.third.javassist.bytecode.ByteArray.write16bit(index, get(), nth * 8 + 6);
}
/**
* Returns <code>classes[nth].inner_class_access_flags</code>.
*/
public int accessFlags(int nth) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(get(), nth * 8 + 8);
}
/**
* Sets <code>classes[nth].inner_class_access_flags</code> to
* the given index.
*/
public void setAccessFlags(int nth, int flags) {
com.fr.third.javassist.bytecode.ByteArray.write16bit(flags, get(), nth * 8 + 8);
}
/**
* Appends a new entry.
*
* @param inner <code>inner_class_info_index</code>
* @param outer <code>outer_class_info_index</code>
* @param name <code>inner_name_index</code>
* @param flags <code>inner_class_access_flags</code>
*/
public void append(String inner, String outer, String name, int flags) {
int i = constPool.addClassInfo(inner);
int o = constPool.addClassInfo(outer);
int n = constPool.addUtf8Info(name);
append(i, o, n, flags);
}
/**
* Appends a new entry.
*
* @param inner <code>inner_class_info_index</code>
* @param outer <code>outer_class_info_index</code>
* @param name <code>inner_name_index</code>
* @param flags <code>inner_class_access_flags</code>
*/
public void append(int inner, int outer, int name, int flags) {
byte[] data = get();
int len = data.length;
byte[] newData = new byte[len + 8];
for (int i = 2; i < len; ++i)
newData[i] = data[i];
int n = com.fr.third.javassist.bytecode.ByteArray.readU16bit(data, 0);
com.fr.third.javassist.bytecode.ByteArray.write16bit(n + 1, newData, 0);
com.fr.third.javassist.bytecode.ByteArray.write16bit(inner, newData, len);
com.fr.third.javassist.bytecode.ByteArray.write16bit(outer, newData, len + 2);
com.fr.third.javassist.bytecode.ByteArray.write16bit(name, newData, len + 4);
com.fr.third.javassist.bytecode.ByteArray.write16bit(flags, newData, len + 6);
set(newData);
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
byte[] src = get();
byte[] dest = new byte[src.length];
ConstPool cp = getConstPool();
InnerClassesAttribute attr = new InnerClassesAttribute(newCp, dest);
int n = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, 0);
com.fr.third.javassist.bytecode.ByteArray.write16bit(n, dest, 0);
int j = 2;
for (int i = 0; i < n; ++i) {
int innerClass = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j);
int outerClass = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 2);
int innerName = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 4);
int innerAccess = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 6);
if (innerClass != 0)
innerClass = cp.copy(innerClass, newCp, classnames);
com.fr.third.javassist.bytecode.ByteArray.write16bit(innerClass, dest, j);
if (outerClass != 0)
outerClass = cp.copy(outerClass, newCp, classnames);
com.fr.third.javassist.bytecode.ByteArray.write16bit(outerClass, dest, j + 2);
if (innerName != 0)
innerName = cp.copy(innerName, newCp, classnames);
com.fr.third.javassist.bytecode.ByteArray.write16bit(innerName, dest, j + 4);
ByteArray.write16bit(innerAccess, dest, j + 6);
j += 8;
}
return attr;
}
}

295
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/InstructionPrinter.java

@ -1,295 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.PrintStream;
import com.fr.third.javassist.CtMethod;
/**
* Simple utility class for printing the bytecode instructions of a method.
*
* @author Jason T. Greene
*/
public class InstructionPrinter implements Opcode {
private final static String opcodes[] = Mnemonic.OPCODE;
private final PrintStream stream;
/**
* Constructs a <code>InstructionPrinter</code> object.
*/
public InstructionPrinter(PrintStream stream) {
this.stream = stream;
}
/**
* Prints the bytecode instructions of a given method.
*/
public static void print(CtMethod method, PrintStream stream) {
(new InstructionPrinter(stream)).print(method);
}
/**
* Prints the bytecode instructions of a given method.
*/
public void print(CtMethod method) {
MethodInfo info = method.getMethodInfo2();
com.fr.third.javassist.bytecode.ConstPool pool = info.getConstPool();
CodeAttribute code = info.getCodeAttribute();
if (code == null)
return;
com.fr.third.javassist.bytecode.CodeIterator iterator = code.iterator();
while (iterator.hasNext()) {
int pos;
try {
pos = iterator.next();
} catch (BadBytecode e) {
throw new RuntimeException(e);
}
stream.println(pos + ": " + instructionString(iterator, pos, pool));
}
}
/**
* Gets a string representation of the bytecode instruction at the specified
* position.
*/
public static String instructionString(com.fr.third.javassist.bytecode.CodeIterator iter, int pos, com.fr.third.javassist.bytecode.ConstPool pool) {
int opcode = iter.byteAt(pos);
if (opcode > opcodes.length || opcode < 0)
throw new IllegalArgumentException("Invalid opcode, opcode: " + opcode + " pos: "+ pos);
String opstring = opcodes[opcode];
switch (opcode) {
case BIPUSH:
return opstring + " " + iter.byteAt(pos + 1);
case SIPUSH:
return opstring + " " + iter.s16bitAt(pos + 1);
case LDC:
return opstring + " " + ldc(pool, iter.byteAt(pos + 1));
case LDC_W :
case LDC2_W :
return opstring + " " + ldc(pool, iter.u16bitAt(pos + 1));
case ILOAD:
case LLOAD:
case FLOAD:
case DLOAD:
case ALOAD:
case ISTORE:
case LSTORE:
case FSTORE:
case DSTORE:
case ASTORE:
return opstring + " " + iter.byteAt(pos + 1);
case IFEQ:
case IFGE:
case IFGT:
case IFLE:
case IFLT:
case IFNE:
case IFNONNULL:
case IFNULL:
case IF_ACMPEQ:
case IF_ACMPNE:
case IF_ICMPEQ:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ICMPLT:
case IF_ICMPNE:
return opstring + " " + (iter.s16bitAt(pos + 1) + pos);
case IINC:
return opstring + " " + iter.byteAt(pos + 1);
case GOTO:
case JSR:
return opstring + " " + (iter.s16bitAt(pos + 1) + pos);
case RET:
return opstring + " " + iter.byteAt(pos + 1);
case TABLESWITCH:
return tableSwitch(iter, pos);
case LOOKUPSWITCH:
return lookupSwitch(iter, pos);
case GETSTATIC:
case PUTSTATIC:
case GETFIELD:
case PUTFIELD:
return opstring + " " + fieldInfo(pool, iter.u16bitAt(pos + 1));
case INVOKEVIRTUAL:
case INVOKESPECIAL:
case INVOKESTATIC:
return opstring + " " + methodInfo(pool, iter.u16bitAt(pos + 1));
case INVOKEINTERFACE:
return opstring + " " + interfaceMethodInfo(pool, iter.u16bitAt(pos + 1));
case INVOKEDYNAMIC:
return opstring + " " + iter.u16bitAt(pos + 1);
case NEW:
return opstring + " " + classInfo(pool, iter.u16bitAt(pos + 1));
case NEWARRAY:
return opstring + " " + arrayInfo(iter.byteAt(pos + 1));
case ANEWARRAY:
case CHECKCAST:
return opstring + " " + classInfo(pool, iter.u16bitAt(pos + 1));
case WIDE:
return wide(iter, pos);
case MULTIANEWARRAY:
return opstring + " " + classInfo(pool, iter.u16bitAt(pos + 1));
case GOTO_W:
case JSR_W:
return opstring + " " + (iter.s32bitAt(pos + 1)+ pos);
default:
return opstring;
}
}
private static String wide(com.fr.third.javassist.bytecode.CodeIterator iter, int pos) {
int opcode = iter.byteAt(pos + 1);
int index = iter.u16bitAt(pos + 2);
switch (opcode) {
case ILOAD:
case LLOAD:
case FLOAD:
case DLOAD:
case ALOAD:
case ISTORE:
case LSTORE:
case FSTORE:
case DSTORE:
case ASTORE:
case IINC:
case RET:
return opcodes[opcode] + " " + index;
default:
throw new RuntimeException("Invalid WIDE operand");
}
}
private static String arrayInfo(int type) {
switch (type) {
case T_BOOLEAN:
return "boolean";
case T_CHAR:
return "char";
case T_BYTE:
return "byte";
case T_SHORT:
return "short";
case T_INT:
return "int";
case T_LONG:
return "long";
case T_FLOAT:
return "float";
case T_DOUBLE:
return "double";
default:
throw new RuntimeException("Invalid array type");
}
}
private static String classInfo(com.fr.third.javassist.bytecode.ConstPool pool, int index) {
return "#" + index + " = Class " + pool.getClassInfo(index);
}
private static String interfaceMethodInfo(com.fr.third.javassist.bytecode.ConstPool pool, int index) {
return "#" + index + " = Method "
+ pool.getInterfaceMethodrefClassName(index) + "."
+ pool.getInterfaceMethodrefName(index) + "("
+ pool.getInterfaceMethodrefType(index) + ")";
}
private static String methodInfo(com.fr.third.javassist.bytecode.ConstPool pool, int index) {
return "#" + index + " = Method "
+ pool.getMethodrefClassName(index) + "."
+ pool.getMethodrefName(index) + "("
+ pool.getMethodrefType(index) + ")";
}
private static String fieldInfo(com.fr.third.javassist.bytecode.ConstPool pool, int index) {
return "#" + index + " = Field "
+ pool.getFieldrefClassName(index) + "."
+ pool.getFieldrefName(index) + "("
+ pool.getFieldrefType(index) + ")";
}
private static String lookupSwitch(com.fr.third.javassist.bytecode.CodeIterator iter, int pos) {
StringBuffer buffer = new StringBuffer("lookupswitch {\n");
int index = (pos & ~3) + 4;
// default
buffer.append("\t\tdefault: ").append(pos + iter.s32bitAt(index)).append("\n");
int npairs = iter.s32bitAt(index += 4);
int end = npairs * 8 + (index += 4);
for (; index < end; index += 8) {
int match = iter.s32bitAt(index);
int target = iter.s32bitAt(index + 4) + pos;
buffer.append("\t\t").append(match).append(": ").append(target).append("\n");
}
buffer.setCharAt(buffer.length() - 1, '}');
return buffer.toString();
}
private static String tableSwitch(CodeIterator iter, int pos) {
StringBuffer buffer = new StringBuffer("tableswitch {\n");
int index = (pos & ~3) + 4;
// default
buffer.append("\t\tdefault: ").append(pos + iter.s32bitAt(index)).append("\n");
int low = iter.s32bitAt(index += 4);
int high = iter.s32bitAt(index += 4);
int end = (high - low + 1) * 4 + (index += 4);
// Offset table
for (int key = low; index < end; index += 4, key++) {
int target = iter.s32bitAt(index) + pos;
buffer.append("\t\t").append(key).append(": ").append(target).append("\n");
}
buffer.setCharAt(buffer.length() - 1, '}');
return buffer.toString();
}
private static String ldc(com.fr.third.javassist.bytecode.ConstPool pool, int index) {
int tag = pool.getTag(index);
switch (tag) {
case com.fr.third.javassist.bytecode.ConstPool.CONST_String:
return "#" + index + " = \"" + pool.getStringInfo(index) + "\"";
case com.fr.third.javassist.bytecode.ConstPool.CONST_Integer:
return "#" + index + " = int " + pool.getIntegerInfo(index);
case com.fr.third.javassist.bytecode.ConstPool.CONST_Float:
return "#" + index + " = float " + pool.getFloatInfo(index);
case com.fr.third.javassist.bytecode.ConstPool.CONST_Long:
return "#" + index + " = long " + pool.getLongInfo(index);
case com.fr.third.javassist.bytecode.ConstPool.CONST_Double:
return "#" + index + " = int " + pool.getDoubleInfo(index);
case ConstPool.CONST_Class:
return classInfo(pool, index);
default:
throw new RuntimeException("bad LDC: " + tag);
}
}
}

182
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LineNumberAttribute.java

@ -1,182 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>LineNumberTable_attribute</code>.
*/
public class LineNumberAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"LineNumberTable"</code>.
*/
public static final String tag = "LineNumberTable";
LineNumberAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
private LineNumberAttribute(com.fr.third.javassist.bytecode.ConstPool cp, byte[] i) {
super(cp, tag, i);
}
/**
* Returns <code>line_number_table_length</code>.
* This represents the number of entries in the table.
*/
public int tableLength() {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, 0);
}
/**
* Returns <code>line_number_table[i].start_pc</code>.
* This represents the index into the code array at which the code
* for a new line in the original source file begins.
*
* @param i the i-th entry.
*/
public int startPc(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 4 + 2);
}
/**
* Returns <code>line_number_table[i].line_number</code>.
* This represents the corresponding line number in the original
* source file.
*
* @param i the i-th entry.
*/
public int lineNumber(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 4 + 4);
}
/**
* Returns the line number corresponding to the specified bytecode.
*
* @param pc the index into the code array.
*/
public int toLineNumber(int pc) {
int n = tableLength();
int i = 0;
for (; i < n; ++i)
if (pc < startPc(i))
if (i == 0)
return lineNumber(0);
else
break;
return lineNumber(i - 1);
}
/**
* Returns the index into the code array at which the code for
* the specified line begins.
*
* @param line the line number.
* @return -1 if the specified line is not found.
*/
public int toStartPc(int line) {
int n = tableLength();
for (int i = 0; i < n; ++i)
if (line == lineNumber(i))
return startPc(i);
return -1;
}
/**
* Used as a return type of <code>toNearPc()</code>.
*/
static public class Pc {
/**
* The index into the code array.
*/
public int index;
/**
* The line number.
*/
public int line;
}
/**
* Returns the index into the code array at which the code for
* the specified line (or the nearest line after the specified one)
* begins.
*
* @param line the line number.
* @return a pair of the index and the line number of the
* bytecode at that index.
*/
public Pc toNearPc(int line) {
int n = tableLength();
int nearPc = 0;
int distance = 0;
if (n > 0) {
distance = lineNumber(0) - line;
nearPc = startPc(0);
}
for (int i = 1; i < n; ++i) {
int d = lineNumber(i) - line;
if ((d < 0 && d > distance)
|| (d >= 0 && (d < distance || distance < 0))) {
distance = d;
nearPc = startPc(i);
}
}
Pc res = new Pc();
res.index = nearPc;
res.line = line + distance;
return res;
}
/**
* Makes a copy.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames should be null.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
byte[] src = info;
int num = src.length;
byte[] dest = new byte[num];
for (int i = 0; i < num; ++i)
dest[i] = src[i];
LineNumberAttribute attr = new LineNumberAttribute(newCp, dest);
return attr;
}
/**
* Adjusts start_pc if bytecode is inserted in a method body.
*/
void shiftPc(int where, int gapLength, boolean exclusive) {
int n = tableLength();
for (int i = 0; i < n; ++i) {
int pos = i * 4 + 2;
int pc = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos);
if (pc > where || (exclusive && pc == where))
ByteArray.write16bit(pc + gapLength, info, pos);
}
}
}

334
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LocalVariableAttribute.java

@ -1,334 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>LocalVariableTable_attribute</code>.
*/
public class LocalVariableAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"LocalVariableTable"</code>.
*/
public static final String tag = "LocalVariableTable";
/**
* The name of the attribute <code>"LocalVariableTypeTable"</code>.
*/
public static final String typeTag = "LocalVariableTypeTable";
/**
* Constructs an empty LocalVariableTable.
*/
public LocalVariableAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
super(cp, tag, new byte[2]);
com.fr.third.javassist.bytecode.ByteArray.write16bit(0, info, 0);
}
/**
* Constructs an empty LocalVariableTable.
*
* @param name the attribute name.
* <code>LocalVariableAttribute.tag</code> or
* <code>LocalVariableAttribute.typeTag</code>.
* @see #tag
* @see #typeTag
* @since 3.1
* @deprecated
*/
public LocalVariableAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String name) {
super(cp, name, new byte[2]);
com.fr.third.javassist.bytecode.ByteArray.write16bit(0, info, 0);
}
LocalVariableAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
LocalVariableAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String name, byte[] i) {
super(cp, name, i);
}
/**
* Appends a new entry to <code>local_variable_table</code>.
*
* @param startPc <code>start_pc</code>
* @param length <code>length</code>
* @param nameIndex <code>name_index</code>
* @param descriptorIndex <code>descriptor_index</code>
* @param index <code>index</code>
*/
public void addEntry(int startPc, int length, int nameIndex,
int descriptorIndex, int index) {
int size = info.length;
byte[] newInfo = new byte[size + 10];
com.fr.third.javassist.bytecode.ByteArray.write16bit(tableLength() + 1, newInfo, 0);
for (int i = 2; i < size; ++i)
newInfo[i] = info[i];
com.fr.third.javassist.bytecode.ByteArray.write16bit(startPc, newInfo, size);
com.fr.third.javassist.bytecode.ByteArray.write16bit(length, newInfo, size + 2);
com.fr.third.javassist.bytecode.ByteArray.write16bit(nameIndex, newInfo, size + 4);
com.fr.third.javassist.bytecode.ByteArray.write16bit(descriptorIndex, newInfo, size + 6);
com.fr.third.javassist.bytecode.ByteArray.write16bit(index, newInfo, size + 8);
info = newInfo;
}
void renameClass(String oldname, String newname) {
com.fr.third.javassist.bytecode.ConstPool cp = getConstPool();
int n = tableLength();
for (int i = 0; i < n; ++i) {
int pos = i * 10 + 2;
int index = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 6);
if (index != 0) {
String desc = cp.getUtf8Info(index);
desc = renameEntry(desc, oldname, newname);
com.fr.third.javassist.bytecode.ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
}
}
}
String renameEntry(String desc, String oldname, String newname) {
return com.fr.third.javassist.bytecode.Descriptor.rename(desc, oldname, newname);
}
void renameClass(Map classnames) {
com.fr.third.javassist.bytecode.ConstPool cp = getConstPool();
int n = tableLength();
for (int i = 0; i < n; ++i) {
int pos = i * 10 + 2;
int index = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 6);
if (index != 0) {
String desc = cp.getUtf8Info(index);
desc = renameEntry(desc, classnames);
com.fr.third.javassist.bytecode.ByteArray.write16bit(cp.addUtf8Info(desc), info, pos + 6);
}
}
}
String renameEntry(String desc, Map classnames) {
return com.fr.third.javassist.bytecode.Descriptor.rename(desc, classnames);
}
/**
* For each <code>local_variable_table[i].index</code>,
* this method increases <code>index</code> by <code>delta</code>.
*
* @param lessThan the index does not change if it
* is less than this value.
*/
public void shiftIndex(int lessThan, int delta) {
int size = info.length;
for (int i = 2; i < size; i += 10){
int org = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i + 8);
if (org >= lessThan)
com.fr.third.javassist.bytecode.ByteArray.write16bit(org + delta, info, i + 8);
}
}
/**
* Returns <code>local_variable_table_length</code>.
* This represents the number of entries in the table.
*/
public int tableLength() {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, 0);
}
/**
* Returns <code>local_variable_table[i].start_pc</code>.
* This represents the index into the code array from which the local
* variable is effective.
*
* @param i the i-th entry.
*/
public int startPc(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 10 + 2);
}
/**
* Returns <code>local_variable_table[i].length</code>.
* This represents the length of the code region in which the local
* variable is effective.
*
* @param i the i-th entry.
*/
public int codeLength(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 10 + 4);
}
/**
* Adjusts start_pc and length if bytecode is inserted in a method body.
*/
void shiftPc(int where, int gapLength, boolean exclusive) {
int n = tableLength();
for (int i = 0; i < n; ++i) {
int pos = i * 10 + 2;
int pc = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos);
int len = com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, pos + 2);
/* if pc == 0, then the local variable is a method parameter.
*/
if (pc > where || (exclusive && pc == where && pc != 0))
com.fr.third.javassist.bytecode.ByteArray.write16bit(pc + gapLength, info, pos);
else if (pc + len > where || (exclusive && pc + len == where))
com.fr.third.javassist.bytecode.ByteArray.write16bit(len + gapLength, info, pos + 2);
}
}
/**
* Returns the value of <code>local_variable_table[i].name_index</code>.
* This represents the name of the local variable.
*
* @param i the i-th entry.
*/
public int nameIndex(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 10 + 6);
}
/**
* Returns the name of the local variable
* specified by <code>local_variable_table[i].name_index</code>.
*
* @param i the i-th entry.
*/
public String variableName(int i) {
return getConstPool().getUtf8Info(nameIndex(i));
}
/**
* Returns the value of
* <code>local_variable_table[i].descriptor_index</code>.
* This represents the type descriptor of the local variable.
* <p>
* If this attribute represents a LocalVariableTypeTable attribute,
* this method returns the value of
* <code>local_variable_type_table[i].signature_index</code>.
* It represents the type of the local variable.
*
* @param i the i-th entry.
*/
public int descriptorIndex(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 10 + 8);
}
/**
* This method is equivalent to <code>descriptorIndex()</code>.
* If this attribute represents a LocalVariableTypeTable attribute,
* this method should be used instead of <code>descriptorIndex()</code>
* since the method name is more appropriate.
*
* @param i the i-th entry.
* @see #descriptorIndex(int)
* @see com.fr.third.javassist.bytecode.SignatureAttribute#toFieldSignature(String)
*/
public int signatureIndex(int i) {
return descriptorIndex(i);
}
/**
* Returns the type descriptor of the local variable
* specified by <code>local_variable_table[i].descriptor_index</code>.
* <p>
* If this attribute represents a LocalVariableTypeTable attribute,
* this method returns the type signature of the local variable
* specified by <code>local_variable_type_table[i].signature_index</code>.
*
* @param i the i-th entry.
*/
public String descriptor(int i) {
return getConstPool().getUtf8Info(descriptorIndex(i));
}
/**
* This method is equivalent to <code>descriptor()</code>.
* If this attribute represents a LocalVariableTypeTable attribute,
* this method should be used instead of <code>descriptor()</code>
* since the method name is more appropriate.
*
* <p>To parse the string, call <code>toFieldSignature(String)</code>
* in <code>SignatureAttribute</code>.
*
* @param i the i-th entry.
* @see #descriptor(int)
* @see SignatureAttribute#toFieldSignature(String)
*/
public String signature(int i) {
return descriptor(i);
}
/**
* Returns <code>local_variable_table[i].index</code>.
* This represents the index of the local variable.
*
* @param i the i-th entry.
*/
public int index(int i) {
return com.fr.third.javassist.bytecode.ByteArray.readU16bit(info, i * 10 + 10);
}
/**
* Makes a copy.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames should be null.
*/
public AttributeInfo copy(com.fr.third.javassist.bytecode.ConstPool newCp, Map classnames) {
byte[] src = get();
byte[] dest = new byte[src.length];
com.fr.third.javassist.bytecode.ConstPool cp = getConstPool();
LocalVariableAttribute attr = makeThisAttr(newCp, dest);
int n = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, 0);
com.fr.third.javassist.bytecode.ByteArray.write16bit(n, dest, 0);
int j = 2;
for (int i = 0; i < n; ++i) {
int start = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j);
int len = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 2);
int name = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 4);
int type = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 6);
int index = com.fr.third.javassist.bytecode.ByteArray.readU16bit(src, j + 8);
com.fr.third.javassist.bytecode.ByteArray.write16bit(start, dest, j);
com.fr.third.javassist.bytecode.ByteArray.write16bit(len, dest, j + 2);
if (name != 0)
name = cp.copy(name, newCp, null);
com.fr.third.javassist.bytecode.ByteArray.write16bit(name, dest, j + 4);
if (type != 0) {
String sig = cp.getUtf8Info(type);
sig = Descriptor.rename(sig, classnames);
type = newCp.addUtf8Info(sig);
}
com.fr.third.javassist.bytecode.ByteArray.write16bit(type, dest, j + 6);
ByteArray.write16bit(index, dest, j + 8);
j += 10;
}
return attr;
}
// LocalVariableTypeAttribute overrides this method.
LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
return new LocalVariableAttribute(cp, tag, dest);
}
}

63
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LocalVariableTypeAttribute.java

@ -1,63 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>LocalVariableTypeTable_attribute</code>.
*
* @since 3.11
*/
public class LocalVariableTypeAttribute extends com.fr.third.javassist.bytecode.LocalVariableAttribute {
/**
* The name of the attribute <code>"LocalVariableTypeTable"</code>.
*/
public static final String tag = com.fr.third.javassist.bytecode.LocalVariableAttribute.typeTag;
/**
* Constructs an empty LocalVariableTypeTable.
*/
public LocalVariableTypeAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
super(cp, tag, new byte[2]);
ByteArray.write16bit(0, info, 0);
}
LocalVariableTypeAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
private LocalVariableTypeAttribute(com.fr.third.javassist.bytecode.ConstPool cp, byte[] dest) {
super(cp, tag, dest);
}
String renameEntry(String desc, String oldname, String newname) {
return com.fr.third.javassist.bytecode.SignatureAttribute.renameClass(desc, oldname, newname);
}
String renameEntry(String desc, Map classnames) {
return SignatureAttribute.renameClass(desc, classnames);
}
LocalVariableAttribute makeThisAttr(ConstPool cp, byte[] dest) {
return new LocalVariableTypeAttribute(cp, dest);
}
}

64
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/LongVector.java

@ -1,64 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
final class LongVector {
static final int ASIZE = 128;
static final int ABITS = 7; // ASIZE = 2^ABITS
static final int VSIZE = 8;
private com.fr.third.javassist.bytecode.ConstInfo[][] objects;
private int elements;
public LongVector() {
objects = new com.fr.third.javassist.bytecode.ConstInfo[VSIZE][];
elements = 0;
}
public LongVector(int initialSize) {
int vsize = ((initialSize >> ABITS) & ~(VSIZE - 1)) + VSIZE;
objects = new com.fr.third.javassist.bytecode.ConstInfo[vsize][];
elements = 0;
}
public int size() { return elements; }
public int capacity() { return objects.length * ASIZE; }
public com.fr.third.javassist.bytecode.ConstInfo elementAt(int i) {
if (i < 0 || elements <= i)
return null;
return objects[i >> ABITS][i & (ASIZE - 1)];
}
public void addElement(com.fr.third.javassist.bytecode.ConstInfo value) {
int nth = elements >> ABITS;
int offset = elements & (ASIZE - 1);
int len = objects.length;
if (nth >= len) {
com.fr.third.javassist.bytecode.ConstInfo[][] newObj = new com.fr.third.javassist.bytecode.ConstInfo[len + VSIZE][];
System.arraycopy(objects, 0, newObj, 0, len);
objects = newObj;
}
if (objects[nth] == null)
objects[nth] = new com.fr.third.javassist.bytecode.ConstInfo[ASIZE];
objects[nth][offset] = value;
elements++;
}
}

551
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/MethodInfo.java

@ -1,551 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtConstructor;
import com.fr.third.javassist.CtMethod;
import com.fr.third.javassist.bytecode.stackmap.MapMaker;
/**
* <code>method_info</code> structure.
*
* <p>The bytecode sequence of the method is represented
* by a <code>CodeAttribute</code> object.
*
* @see #getCodeAttribute()
* @see CodeAttribute
* @see CtMethod#getMethodInfo()
* @see CtConstructor#getMethodInfo()
*/
public class MethodInfo {
com.fr.third.javassist.bytecode.ConstPool constPool;
int accessFlags;
int name;
String cachedName;
int descriptor;
ArrayList attribute; // may be null
/**
* If this value is true, Javassist maintains a <code>StackMap</code> attribute
* generated by the <code>preverify</code> tool of J2ME (CLDC). The initial
* value of this field is <code>false</code>.
*/
public static boolean doPreverify = false;
/**
* The name of constructors: <code>&lt;init&gt</code>.
*/
public static final String nameInit = "<init>";
/**
* The name of class initializer (static initializer):
* <code>&lt;clinit&gt</code>.
*/
public static final String nameClinit = "<clinit>";
private MethodInfo(com.fr.third.javassist.bytecode.ConstPool cp) {
constPool = cp;
attribute = null;
}
/**
* Constructs a <code>method_info</code> structure. The initial value of
* <code>access_flags</code> is zero.
*
* @param cp
* a constant pool table
* @param methodname
* method name
* @param desc
* method descriptor
* @see com.fr.third.javassist.bytecode.Descriptor
*/
public MethodInfo(com.fr.third.javassist.bytecode.ConstPool cp, String methodname, String desc) {
this(cp);
accessFlags = 0;
name = cp.addUtf8Info(methodname);
cachedName = methodname;
descriptor = constPool.addUtf8Info(desc);
}
MethodInfo(com.fr.third.javassist.bytecode.ConstPool cp, DataInputStream in) throws IOException {
this(cp);
read(in);
}
/**
* Constructs a copy of <code>method_info</code> structure. Class names
* appearing in the source <code>method_info</code> are renamed according
* to <code>classnameMap</code>.
*
* <p>
* Note: only <code>Code</code> and <code>Exceptions</code> attributes
* are copied from the source. The other attributes are ignored.
*
* @param cp
* a constant pool table
* @param methodname
* a method name
* @param src
* a source <code>method_info</code>
* @param classnameMap
* specifies pairs of replaced and substituted name.
* @see com.fr.third.javassist.bytecode.Descriptor
*/
public MethodInfo(com.fr.third.javassist.bytecode.ConstPool cp, String methodname, MethodInfo src,
Map classnameMap) throws BadBytecode {
this(cp);
read(src, methodname, classnameMap);
}
/**
* Returns a string representation of the object.
*/
public String toString() {
return getName() + " " + getDescriptor();
}
/**
* Copies all constant pool items to a given new constant pool
* and replaces the original items with the new ones.
* This is used for garbage collecting the items of removed fields
* and methods.
*
* @param cp the destination
*/
void compact(com.fr.third.javassist.bytecode.ConstPool cp) {
name = cp.addUtf8Info(getName());
descriptor = cp.addUtf8Info(getDescriptor());
attribute = AttributeInfo.copyAll(attribute, cp);
constPool = cp;
}
void prune(com.fr.third.javassist.bytecode.ConstPool cp) {
ArrayList newAttributes = new ArrayList();
AttributeInfo invisibleAnnotations
= getAttribute(AnnotationsAttribute.invisibleTag);
if (invisibleAnnotations != null) {
invisibleAnnotations = invisibleAnnotations.copy(cp, null);
newAttributes.add(invisibleAnnotations);
}
AttributeInfo visibleAnnotations
= getAttribute(AnnotationsAttribute.visibleTag);
if (visibleAnnotations != null) {
visibleAnnotations = visibleAnnotations.copy(cp, null);
newAttributes.add(visibleAnnotations);
}
AttributeInfo parameterInvisibleAnnotations
= getAttribute(ParameterAnnotationsAttribute.invisibleTag);
if (parameterInvisibleAnnotations != null) {
parameterInvisibleAnnotations = parameterInvisibleAnnotations.copy(cp, null);
newAttributes.add(parameterInvisibleAnnotations);
}
AttributeInfo parameterVisibleAnnotations
= getAttribute(ParameterAnnotationsAttribute.visibleTag);
if (parameterVisibleAnnotations != null) {
parameterVisibleAnnotations = parameterVisibleAnnotations.copy(cp, null);
newAttributes.add(parameterVisibleAnnotations);
}
AnnotationDefaultAttribute defaultAttribute
= (AnnotationDefaultAttribute) getAttribute(AnnotationDefaultAttribute.tag);
if (defaultAttribute != null)
newAttributes.add(defaultAttribute);
ExceptionsAttribute ea = getExceptionsAttribute();
if (ea != null)
newAttributes.add(ea);
AttributeInfo signature
= getAttribute(SignatureAttribute.tag);
if (signature != null) {
signature = signature.copy(cp, null);
newAttributes.add(signature);
}
attribute = newAttributes;
name = cp.addUtf8Info(getName());
descriptor = cp.addUtf8Info(getDescriptor());
constPool = cp;
}
/**
* Returns a method name.
*/
public String getName() {
if (cachedName == null)
cachedName = constPool.getUtf8Info(name);
return cachedName;
}
/**
* Sets a method name.
*/
public void setName(String newName) {
name = constPool.addUtf8Info(newName);
cachedName = newName;
}
/**
* Returns true if this is not a constructor or a class initializer (static
* initializer).
*/
public boolean isMethod() {
String n = getName();
return !n.equals(nameInit) && !n.equals(nameClinit);
}
/**
* Returns a constant pool table used by this method.
*/
public com.fr.third.javassist.bytecode.ConstPool getConstPool() {
return constPool;
}
/**
* Returns true if this is a constructor.
*/
public boolean isConstructor() {
return getName().equals(nameInit);
}
/**
* Returns true if this is a class initializer (static initializer).
*/
public boolean isStaticInitializer() {
return getName().equals(nameClinit);
}
/**
* Returns access flags.
*
* @see com.fr.third.javassist.bytecode.AccessFlag
*/
public int getAccessFlags() {
return accessFlags;
}
/**
* Sets access flags.
*
* @see AccessFlag
*/
public void setAccessFlags(int acc) {
accessFlags = acc;
}
/**
* Returns a method descriptor.
*
* @see com.fr.third.javassist.bytecode.Descriptor
*/
public String getDescriptor() {
return constPool.getUtf8Info(descriptor);
}
/**
* Sets a method descriptor.
*
* @see com.fr.third.javassist.bytecode.Descriptor
*/
public void setDescriptor(String desc) {
if (!desc.equals(getDescriptor()))
descriptor = constPool.addUtf8Info(desc);
}
/**
* Returns all the attributes. The returned <code>List</code> object
* is shared with this object. If you add a new attribute to the list,
* the attribute is also added to the method represented by this
* object. If you remove an attribute from the list, it is also removed
* from the method.
*
* @return a list of <code>AttributeInfo</code> objects.
* @see AttributeInfo
*/
public List getAttributes() {
if (attribute == null)
attribute = new ArrayList();
return attribute;
}
/**
* Returns the attribute with the specified name. If it is not found, this
* method returns null.
*
* @param name attribute name
* @return an <code>AttributeInfo</code> object or null.
* @see #getAttributes()
*/
public AttributeInfo getAttribute(String name) {
return AttributeInfo.lookup(attribute, name);
}
/**
* Appends an attribute. If there is already an attribute with the same
* name, the new one substitutes for it.
*
* @see #getAttributes()
*/
public void addAttribute(AttributeInfo info) {
if (attribute == null)
attribute = new ArrayList();
AttributeInfo.remove(attribute, info.getName());
attribute.add(info);
}
/**
* Returns an Exceptions attribute.
*
* @return an Exceptions attribute or null if it is not specified.
*/
public ExceptionsAttribute getExceptionsAttribute() {
AttributeInfo info = AttributeInfo.lookup(attribute,
ExceptionsAttribute.tag);
return (ExceptionsAttribute)info;
}
/**
* Returns a Code attribute.
*
* @return a Code attribute or null if it is not specified.
*/
public CodeAttribute getCodeAttribute() {
AttributeInfo info = AttributeInfo.lookup(attribute, CodeAttribute.tag);
return (CodeAttribute)info;
}
/**
* Removes an Exception attribute.
*/
public void removeExceptionsAttribute() {
AttributeInfo.remove(attribute, ExceptionsAttribute.tag);
}
/**
* Adds an Exception attribute.
*
* <p>
* The added attribute must share the same constant pool table as this
* <code>method_info</code> structure.
*/
public void setExceptionsAttribute(ExceptionsAttribute cattr) {
removeExceptionsAttribute();
if (attribute == null)
attribute = new ArrayList();
attribute.add(cattr);
}
/**
* Removes a Code attribute.
*/
public void removeCodeAttribute() {
AttributeInfo.remove(attribute, CodeAttribute.tag);
}
/**
* Adds a Code attribute.
*
* <p>
* The added attribute must share the same constant pool table as this
* <code>method_info</code> structure.
*/
public void setCodeAttribute(CodeAttribute cattr) {
removeCodeAttribute();
if (attribute == null)
attribute = new ArrayList();
attribute.add(cattr);
}
/**
* Rebuilds a stack map table if the class file is for Java 6
* or later. Java 5 or older Java VMs do not recognize a stack
* map table. If <code>doPreverify</code> is true, this method
* also rebuilds a stack map for J2ME (CLDC).
*
* @param pool used for making type hierarchy.
* @param cf rebuild if this class file is for Java 6 or later.
* @see #rebuildStackMap(ClassPool)
* @see #rebuildStackMapForME(ClassPool)
* @see #doPreverify
* @since 3.6
*/
public void rebuildStackMapIf6(ClassPool pool, com.fr.third.javassist.bytecode.ClassFile cf)
throws BadBytecode
{
if (cf.getMajorVersion() >= ClassFile.JAVA_6)
rebuildStackMap(pool);
if (doPreverify)
rebuildStackMapForME(pool);
}
/**
* Rebuilds a stack map table. If no stack map table is included,
* a new one is created. If this <code>MethodInfo</code> does not
* include a code attribute, nothing happens.
*
* @param pool used for making type hierarchy.
* @see StackMapTable
* @since 3.6
*/
public void rebuildStackMap(ClassPool pool) throws BadBytecode {
CodeAttribute ca = getCodeAttribute();
if (ca != null) {
StackMapTable smt = MapMaker.make(pool, this);
ca.setAttribute(smt);
}
}
/**
* Rebuilds a stack map table for J2ME (CLDC). If no stack map table is included,
* a new one is created. If this <code>MethodInfo</code> does not
* include a code attribute, nothing happens.
*
* @param pool used for making type hierarchy.
* @see com.fr.third.javassist.bytecode.StackMap
* @since 3.12
*/
public void rebuildStackMapForME(ClassPool pool) throws BadBytecode {
CodeAttribute ca = getCodeAttribute();
if (ca != null) {
StackMap sm = MapMaker.make2(pool, this);
ca.setAttribute(sm);
}
}
/**
* Returns the line number of the source line corresponding to the specified
* bytecode contained in this method.
*
* @param pos
* the position of the bytecode (&gt;= 0). an index into the code
* array.
* @return -1 if this information is not available.
*/
public int getLineNumber(int pos) {
CodeAttribute ca = getCodeAttribute();
if (ca == null)
return -1;
LineNumberAttribute ainfo = (LineNumberAttribute)ca
.getAttribute(LineNumberAttribute.tag);
if (ainfo == null)
return -1;
return ainfo.toLineNumber(pos);
}
/**
* Changes a super constructor called by this constructor.
*
* <p>
* This method modifies a call to <code>super()</code>, which should be
* at the head of a constructor body, so that a constructor in a different
* super class is called. This method does not change actual parameters.
* Hence the new super class must have a constructor with the same signature
* as the original one.
*
* <p>
* This method should be called when the super class of the class declaring
* this method is changed.
*
* <p>
* This method does not perform anything unless this <code>MethodInfo</code>
* represents a constructor.
*
* @param superclass
* the new super class
*/
public void setSuperclass(String superclass) throws BadBytecode {
if (!isConstructor())
return;
CodeAttribute ca = getCodeAttribute();
byte[] code = ca.getCode();
CodeIterator iterator = ca.iterator();
int pos = iterator.skipSuperConstructor();
if (pos >= 0) { // not this()
com.fr.third.javassist.bytecode.ConstPool cp = constPool;
int mref = com.fr.third.javassist.bytecode.ByteArray.readU16bit(code, pos + 1);
int nt = cp.getMethodrefNameAndType(mref);
int sc = cp.addClassInfo(superclass);
int mref2 = cp.addMethodrefInfo(sc, nt);
ByteArray.write16bit(mref2, code, pos + 1);
}
}
private void read(MethodInfo src, String methodname, Map classnames)
throws BadBytecode {
com.fr.third.javassist.bytecode.ConstPool destCp = constPool;
accessFlags = src.accessFlags;
name = destCp.addUtf8Info(methodname);
cachedName = methodname;
ConstPool srcCp = src.constPool;
String desc = srcCp.getUtf8Info(src.descriptor);
String desc2 = Descriptor.rename(desc, classnames);
descriptor = destCp.addUtf8Info(desc2);
attribute = new ArrayList();
ExceptionsAttribute eattr = src.getExceptionsAttribute();
if (eattr != null)
attribute.add(eattr.copy(destCp, classnames));
CodeAttribute cattr = src.getCodeAttribute();
if (cattr != null)
attribute.add(cattr.copy(destCp, classnames));
}
private void read(DataInputStream in) throws IOException {
accessFlags = in.readUnsignedShort();
name = in.readUnsignedShort();
descriptor = in.readUnsignedShort();
int n = in.readUnsignedShort();
attribute = new ArrayList();
for (int i = 0; i < n; ++i)
attribute.add(AttributeInfo.read(constPool, in));
}
void write(DataOutputStream out) throws IOException {
out.writeShort(accessFlags);
out.writeShort(name);
out.writeShort(descriptor);
if (attribute == null)
out.writeShort(0);
else {
out.writeShort(attribute.size());
AttributeInfo.writeAll(attribute, out);
}
}
}

239
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Mnemonic.java

@ -1,239 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
/**
* JVM Instruction Names.
*
* <p>This interface has been separated from javassist.bytecode.Opcode
* because typical bytecode translators do not use mnemonics. If this
* interface were merged with Opcode, extra memory would be unnecessary
* consumed.
*
* @see Opcode
*/
public interface Mnemonic {
/**
* The instruction names (mnemonics) sorted by the opcode.
* The length of this array is 202 (jsr_w=201).
*/
String[] OPCODE = {
"nop", /* 0*/
"aconst_null", /* 1*/
"iconst_m1", /* 2*/
"iconst_0", /* 3*/
"iconst_1", /* 4*/
"iconst_2", /* 5*/
"iconst_3", /* 6*/
"iconst_4", /* 7*/
"iconst_5", /* 8*/
"lconst_0", /* 9*/
"lconst_1", /* 10*/
"fconst_0", /* 11*/
"fconst_1", /* 12*/
"fconst_2", /* 13*/
"dconst_0", /* 14*/
"dconst_1", /* 15*/
"bipush", /* 16*/
"sipush", /* 17*/
"ldc", /* 18*/
"ldc_w", /* 19*/
"ldc2_w", /* 20*/
"iload", /* 21*/
"lload", /* 22*/
"fload", /* 23*/
"dload", /* 24*/
"aload", /* 25*/
"iload_0", /* 26*/
"iload_1", /* 27*/
"iload_2", /* 28*/
"iload_3", /* 29*/
"lload_0", /* 30*/
"lload_1", /* 31*/
"lload_2", /* 32*/
"lload_3", /* 33*/
"fload_0", /* 34*/
"fload_1", /* 35*/
"fload_2", /* 36*/
"fload_3", /* 37*/
"dload_0", /* 38*/
"dload_1", /* 39*/
"dload_2", /* 40*/
"dload_3", /* 41*/
"aload_0", /* 42*/
"aload_1", /* 43*/
"aload_2", /* 44*/
"aload_3", /* 45*/
"iaload", /* 46*/
"laload", /* 47*/
"faload", /* 48*/
"daload", /* 49*/
"aaload", /* 50*/
"baload", /* 51*/
"caload", /* 52*/
"saload", /* 53*/
"istore", /* 54*/
"lstore", /* 55*/
"fstore", /* 56*/
"dstore", /* 57*/
"astore", /* 58*/
"istore_0", /* 59*/
"istore_1", /* 60*/
"istore_2", /* 61*/
"istore_3", /* 62*/
"lstore_0", /* 63*/
"lstore_1", /* 64*/
"lstore_2", /* 65*/
"lstore_3", /* 66*/
"fstore_0", /* 67*/
"fstore_1", /* 68*/
"fstore_2", /* 69*/
"fstore_3", /* 70*/
"dstore_0", /* 71*/
"dstore_1", /* 72*/
"dstore_2", /* 73*/
"dstore_3", /* 74*/
"astore_0", /* 75*/
"astore_1", /* 76*/
"astore_2", /* 77*/
"astore_3", /* 78*/
"iastore", /* 79*/
"lastore", /* 80*/
"fastore", /* 81*/
"dastore", /* 82*/
"aastore", /* 83*/
"bastore", /* 84*/
"castore", /* 85*/
"sastore", /* 86*/
"pop", /* 87*/
"pop2", /* 88*/
"dup", /* 89*/
"dup_x1", /* 90*/
"dup_x2", /* 91*/
"dup2", /* 92*/
"dup2_x1", /* 93*/
"dup2_x2", /* 94*/
"swap", /* 95*/
"iadd", /* 96*/
"ladd", /* 97*/
"fadd", /* 98*/
"dadd", /* 99*/
"isub", /* 100*/
"lsub", /* 101*/
"fsub", /* 102*/
"dsub", /* 103*/
"imul", /* 104*/
"lmul", /* 105*/
"fmul", /* 106*/
"dmul", /* 107*/
"idiv", /* 108*/
"ldiv", /* 109*/
"fdiv", /* 110*/
"ddiv", /* 111*/
"irem", /* 112*/
"lrem", /* 113*/
"frem", /* 114*/
"drem", /* 115*/
"ineg", /* 116*/
"lneg", /* 117*/
"fneg", /* 118*/
"dneg", /* 119*/
"ishl", /* 120*/
"lshl", /* 121*/
"ishr", /* 122*/
"lshr", /* 123*/
"iushr", /* 124*/
"lushr", /* 125*/
"iand", /* 126*/
"land", /* 127*/
"ior", /* 128*/
"lor", /* 129*/
"ixor", /* 130*/
"lxor", /* 131*/
"iinc", /* 132*/
"i2l", /* 133*/
"i2f", /* 134*/
"i2d", /* 135*/
"l2i", /* 136*/
"l2f", /* 137*/
"l2d", /* 138*/
"f2i", /* 139*/
"f2l", /* 140*/
"f2d", /* 141*/
"d2i", /* 142*/
"d2l", /* 143*/
"d2f", /* 144*/
"i2b", /* 145*/
"i2c", /* 146*/
"i2s", /* 147*/
"lcmp", /* 148*/
"fcmpl", /* 149*/
"fcmpg", /* 150*/
"dcmpl", /* 151*/
"dcmpg", /* 152*/
"ifeq", /* 153*/
"ifne", /* 154*/
"iflt", /* 155*/
"ifge", /* 156*/
"ifgt", /* 157*/
"ifle", /* 158*/
"if_icmpeq", /* 159*/
"if_icmpne", /* 160*/
"if_icmplt", /* 161*/
"if_icmpge", /* 162*/
"if_icmpgt", /* 163*/
"if_icmple", /* 164*/
"if_acmpeq", /* 165*/
"if_acmpne", /* 166*/
"goto", /* 167*/
"jsr", /* 168*/
"ret", /* 169*/
"tableswitch", /* 170*/
"lookupswitch", /* 171*/
"ireturn", /* 172*/
"lreturn", /* 173*/
"freturn", /* 174*/
"dreturn", /* 175*/
"areturn", /* 176*/
"return", /* 177*/
"getstatic", /* 178*/
"putstatic", /* 179*/
"getfield", /* 180*/
"putfield", /* 181*/
"invokevirtual", /* 182*/
"invokespecial", /* 183*/
"invokestatic", /* 184*/
"invokeinterface", /* 185*/
"invokedynamic", /* 186 */
"new", /* 187*/
"newarray", /* 188*/
"anewarray", /* 189*/
"arraylength", /* 190*/
"athrow", /* 191*/
"checkcast", /* 192*/
"instanceof", /* 193*/
"monitorenter", /* 194*/
"monitorexit", /* 195*/
"wide", /* 196*/
"multianewarray", /* 197*/
"ifnull", /* 198*/
"ifnonnull", /* 199*/
"goto_w", /* 200*/
"jsr_w" /* 201*/
};
}

449
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/Opcode.java

@ -1,449 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
/**
* JVM Instruction Set.
*
* <p>This interface defines opcodes and
* array types for the NEWARRAY instruction.
*
* @see Mnemonic
*/
public interface Opcode {
/* Opcodes */
int AALOAD = 50;
int AASTORE = 83;
int ACONST_NULL = 1;
int ALOAD = 25;
int ALOAD_0 = 42;
int ALOAD_1 = 43;
int ALOAD_2 = 44;
int ALOAD_3 = 45;
int ANEWARRAY = 189;
int ARETURN = 176;
int ARRAYLENGTH = 190;
int ASTORE = 58;
int ASTORE_0 = 75;
int ASTORE_1 = 76;
int ASTORE_2 = 77;
int ASTORE_3 = 78;
int ATHROW = 191;
int BALOAD = 51;
int BASTORE = 84;
int BIPUSH = 16;
int CALOAD = 52;
int CASTORE = 85;
int CHECKCAST = 192;
int D2F = 144;
int D2I = 142;
int D2L = 143;
int DADD = 99;
int DALOAD = 49;
int DASTORE = 82;
int DCMPG = 152;
int DCMPL = 151;
int DCONST_0 = 14;
int DCONST_1 = 15;
int DDIV = 111;
int DLOAD = 24;
int DLOAD_0 = 38;
int DLOAD_1 = 39;
int DLOAD_2 = 40;
int DLOAD_3 = 41;
int DMUL = 107;
int DNEG = 119;
int DREM = 115;
int DRETURN = 175;
int DSTORE = 57;
int DSTORE_0 = 71;
int DSTORE_1 = 72;
int DSTORE_2 = 73;
int DSTORE_3 = 74;
int DSUB = 103;
int DUP = 89;
int DUP2 = 92;
int DUP2_X1 = 93;
int DUP2_X2 = 94;
int DUP_X1 = 90;
int DUP_X2 = 91;
int F2D = 141;
int F2I = 139;
int F2L = 140;
int FADD = 98;
int FALOAD = 48;
int FASTORE = 81;
int FCMPG = 150;
int FCMPL = 149;
int FCONST_0 = 11;
int FCONST_1 = 12;
int FCONST_2 = 13;
int FDIV = 110;
int FLOAD = 23;
int FLOAD_0 = 34;
int FLOAD_1 = 35;
int FLOAD_2 = 36;
int FLOAD_3 = 37;
int FMUL = 106;
int FNEG = 118;
int FREM = 114;
int FRETURN = 174;
int FSTORE = 56;
int FSTORE_0 = 67;
int FSTORE_1 = 68;
int FSTORE_2 = 69;
int FSTORE_3 = 70;
int FSUB = 102;
int GETFIELD = 180;
int GETSTATIC = 178;
int GOTO = 167;
int GOTO_W = 200;
int I2B = 145;
int I2C = 146;
int I2D = 135;
int I2F = 134;
int I2L = 133;
int I2S = 147;
int IADD = 96;
int IALOAD = 46;
int IAND = 126;
int IASTORE = 79;
int ICONST_0 = 3;
int ICONST_1 = 4;
int ICONST_2 = 5;
int ICONST_3 = 6;
int ICONST_4 = 7;
int ICONST_5 = 8;
int ICONST_M1 = 2;
int IDIV = 108;
int IFEQ = 153;
int IFGE = 156;
int IFGT = 157;
int IFLE = 158;
int IFLT = 155;
int IFNE = 154;
int IFNONNULL = 199;
int IFNULL = 198;
int IF_ACMPEQ = 165;
int IF_ACMPNE = 166;
int IF_ICMPEQ = 159;
int IF_ICMPGE = 162;
int IF_ICMPGT = 163;
int IF_ICMPLE = 164;
int IF_ICMPLT = 161;
int IF_ICMPNE = 160;
int IINC = 132;
int ILOAD = 21;
int ILOAD_0 = 26;
int ILOAD_1 = 27;
int ILOAD_2 = 28;
int ILOAD_3 = 29;
int IMUL = 104;
int INEG = 116;
int INSTANCEOF = 193;
int INVOKEDYNAMIC = 186;
int INVOKEINTERFACE = 185;
int INVOKESPECIAL = 183;
int INVOKESTATIC = 184;
int INVOKEVIRTUAL = 182;
int IOR = 128;
int IREM = 112;
int IRETURN = 172;
int ISHL = 120;
int ISHR = 122;
int ISTORE = 54;
int ISTORE_0 = 59;
int ISTORE_1 = 60;
int ISTORE_2 = 61;
int ISTORE_3 = 62;
int ISUB = 100;
int IUSHR = 124;
int IXOR = 130;
int JSR = 168;
int JSR_W = 201;
int L2D = 138;
int L2F = 137;
int L2I = 136;
int LADD = 97;
int LALOAD = 47;
int LAND = 127;
int LASTORE = 80;
int LCMP = 148;
int LCONST_0 = 9;
int LCONST_1 = 10;
int LDC = 18;
int LDC2_W = 20;
int LDC_W = 19;
int LDIV = 109;
int LLOAD = 22;
int LLOAD_0 = 30;
int LLOAD_1 = 31;
int LLOAD_2 = 32;
int LLOAD_3 = 33;
int LMUL = 105;
int LNEG = 117;
int LOOKUPSWITCH = 171;
int LOR = 129;
int LREM = 113;
int LRETURN = 173;
int LSHL = 121;
int LSHR = 123;
int LSTORE = 55;
int LSTORE_0 = 63;
int LSTORE_1 = 64;
int LSTORE_2 = 65;
int LSTORE_3 = 66;
int LSUB = 101;
int LUSHR = 125;
int LXOR = 131;
int MONITORENTER = 194;
int MONITOREXIT = 195;
int MULTIANEWARRAY = 197;
int NEW = 187;
int NEWARRAY = 188;
int NOP = 0;
int POP = 87;
int POP2 = 88;
int PUTFIELD = 181;
int PUTSTATIC = 179;
int RET = 169;
int RETURN = 177;
int SALOAD = 53;
int SASTORE = 86;
int SIPUSH = 17;
int SWAP = 95;
int TABLESWITCH = 170;
int WIDE = 196;
/* array-type code for the newarray instruction */
int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
/* how many values are pushed on the operand stack. */
int[] STACK_GROW = {
0, // nop, 0
1, // aconst_null, 1
1, // iconst_m1, 2
1, // iconst_0, 3
1, // iconst_1, 4
1, // iconst_2, 5
1, // iconst_3, 6
1, // iconst_4, 7
1, // iconst_5, 8
2, // lconst_0, 9
2, // lconst_1, 10
1, // fconst_0, 11
1, // fconst_1, 12
1, // fconst_2, 13
2, // dconst_0, 14
2, // dconst_1, 15
1, // bipush, 16
1, // sipush, 17
1, // ldc, 18
1, // ldc_w, 19
2, // ldc2_w, 20
1, // iload, 21
2, // lload, 22
1, // fload, 23
2, // dload, 24
1, // aload, 25
1, // iload_0, 26
1, // iload_1, 27
1, // iload_2, 28
1, // iload_3, 29
2, // lload_0, 30
2, // lload_1, 31
2, // lload_2, 32
2, // lload_3, 33
1, // fload_0, 34
1, // fload_1, 35
1, // fload_2, 36
1, // fload_3, 37
2, // dload_0, 38
2, // dload_1, 39
2, // dload_2, 40
2, // dload_3, 41
1, // aload_0, 42
1, // aload_1, 43
1, // aload_2, 44
1, // aload_3, 45
-1, // iaload, 46
0, // laload, 47
-1, // faload, 48
0, // daload, 49
-1, // aaload, 50
-1, // baload, 51
-1, // caload, 52
-1, // saload, 53
-1, // istore, 54
-2, // lstore, 55
-1, // fstore, 56
-2, // dstore, 57
-1, // astore, 58
-1, // istore_0, 59
-1, // istore_1, 60
-1, // istore_2, 61
-1, // istore_3, 62
-2, // lstore_0, 63
-2, // lstore_1, 64
-2, // lstore_2, 65
-2, // lstore_3, 66
-1, // fstore_0, 67
-1, // fstore_1, 68
-1, // fstore_2, 69
-1, // fstore_3, 70
-2, // dstore_0, 71
-2, // dstore_1, 72
-2, // dstore_2, 73
-2, // dstore_3, 74
-1, // astore_0, 75
-1, // astore_1, 76
-1, // astore_2, 77
-1, // astore_3, 78
-3, // iastore, 79
-4, // lastore, 80
-3, // fastore, 81
-4, // dastore, 82
-3, // aastore, 83
-3, // bastore, 84
-3, // castore, 85
-3, // sastore, 86
-1, // pop, 87
-2, // pop2, 88
1, // dup, 89
1, // dup_x1, 90
1, // dup_x2, 91
2, // dup2, 92
2, // dup2_x1, 93
2, // dup2_x2, 94
0, // swap, 95
-1, // iadd, 96
-2, // ladd, 97
-1, // fadd, 98
-2, // dadd, 99
-1, // isub, 100
-2, // lsub, 101
-1, // fsub, 102
-2, // dsub, 103
-1, // imul, 104
-2, // lmul, 105
-1, // fmul, 106
-2, // dmul, 107
-1, // idiv, 108
-2, // ldiv, 109
-1, // fdiv, 110
-2, // ddiv, 111
-1, // irem, 112
-2, // lrem, 113
-1, // frem, 114
-2, // drem, 115
0, // ineg, 116
0, // lneg, 117
0, // fneg, 118
0, // dneg, 119
-1, // ishl, 120
-1, // lshl, 121
-1, // ishr, 122
-1, // lshr, 123
-1, // iushr, 124
-1, // lushr, 125
-1, // iand, 126
-2, // land, 127
-1, // ior, 128
-2, // lor, 129
-1, // ixor, 130
-2, // lxor, 131
0, // iinc, 132
1, // i2l, 133
0, // i2f, 134
1, // i2d, 135
-1, // l2i, 136
-1, // l2f, 137
0, // l2d, 138
0, // f2i, 139
1, // f2l, 140
1, // f2d, 141
-1, // d2i, 142
0, // d2l, 143
-1, // d2f, 144
0, // i2b, 145
0, // i2c, 146
0, // i2s, 147
-3, // lcmp, 148
-1, // fcmpl, 149
-1, // fcmpg, 150
-3, // dcmpl, 151
-3, // dcmpg, 152
-1, // ifeq, 153
-1, // ifne, 154
-1, // iflt, 155
-1, // ifge, 156
-1, // ifgt, 157
-1, // ifle, 158
-2, // if_icmpeq, 159
-2, // if_icmpne, 160
-2, // if_icmplt, 161
-2, // if_icmpge, 162
-2, // if_icmpgt, 163
-2, // if_icmple, 164
-2, // if_acmpeq, 165
-2, // if_acmpne, 166
0, // goto, 167
1, // jsr, 168
0, // ret, 169
-1, // tableswitch, 170
-1, // lookupswitch, 171
-1, // ireturn, 172
-2, // lreturn, 173
-1, // freturn, 174
-2, // dreturn, 175
-1, // areturn, 176
0, // return, 177
0, // getstatic, 178 depends on the type
0, // putstatic, 179 depends on the type
0, // getfield, 180 depends on the type
0, // putfield, 181 depends on the type
0, // invokevirtual, 182 depends on the type
0, // invokespecial, 183 depends on the type
0, // invokestatic, 184 depends on the type
0, // invokeinterface, 185 depends on the type
0, // invokedynaimc, 186 depends on the type
1, // new, 187
0, // newarray, 188
0, // anewarray, 189
0, // arraylength, 190
-1, // athrow, 191 stack is cleared
0, // checkcast, 192
0, // instanceof, 193
-1, // monitorenter, 194
-1, // monitorexit, 195
0, // wide, 196 depends on the following opcode
0, // multianewarray, 197 depends on the dimensions
-1, // ifnull, 198
-1, // ifnonnull, 199
0, // goto_w, 200
1 // jsr_w, 201
};
}

215
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/ParameterAnnotationsAttribute.java

@ -1,215 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.util.HashMap;
import java.util.Map;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.ByteArrayOutputStream;
import com.fr.third.javassist.bytecode.annotation.Annotation;
import com.fr.third.javassist.bytecode.AnnotationsAttribute.Copier;
import com.fr.third.javassist.bytecode.AnnotationsAttribute.Parser;
import com.fr.third.javassist.bytecode.AnnotationsAttribute.Renamer;
/**
* A class representing <code>RuntimeVisibleAnnotations_attribute</code> and
* <code>RuntimeInvisibleAnnotations_attribute</code>.
*
* <p>To obtain an ParameterAnnotationAttribute object, invoke
* <code>getAttribute(ParameterAnnotationsAttribute.invisibleTag)</code>
* in <code>MethodInfo</code>.
* The obtained attribute is a
* runtime invisible annotations attribute.
* If the parameter is
* <code>ParameterAnnotationAttribute.visibleTag</code>, then the obtained
* attribute is a runtime visible one.
*/
public class ParameterAnnotationsAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of the <code>RuntimeVisibleParameterAnnotations</code>
* attribute.
*/
public static final String visibleTag
= "RuntimeVisibleParameterAnnotations";
/**
* The name of the <code>RuntimeInvisibleParameterAnnotations</code>
* attribute.
*/
public static final String invisibleTag
= "RuntimeInvisibleParameterAnnotations";
/**
* Constructs
* a <code>Runtime(In)VisibleParameterAnnotations_attribute</code>.
*
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @param info the contents of this attribute. It does not
* include <code>attribute_name_index</code> or
* <code>attribute_length</code>.
*/
public ParameterAnnotationsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String attrname,
byte[] info) {
super(cp, attrname, info);
}
/**
* Constructs an empty
* <code>Runtime(In)VisibleParameterAnnotations_attribute</code>.
* A new annotation can be later added to the created attribute
* by <code>setAnnotations()</code>.
*
* @param cp constant pool
* @param attrname attribute name (<code>visibleTag</code> or
* <code>invisibleTag</code>).
* @see #setAnnotations(com.fr.third.javassist.bytecode.annotation.Annotation[][])
*/
public ParameterAnnotationsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String attrname) {
this(cp, attrname, new byte[] { 0 });
}
/**
* @param n the attribute name.
*/
ParameterAnnotationsAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Returns <code>num_parameters</code>.
*/
public int numParameters() {
return info[0] & 0xff;
}
/**
* Copies this attribute and returns a new copy.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
Copier copier = new Copier(info, constPool, newCp, classnames);
try {
copier.parameters();
return new ParameterAnnotationsAttribute(newCp, getName(),
copier.close());
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
/**
* Parses the annotations and returns a data structure representing
* that parsed annotations. Note that changes of the node values of the
* returned tree are not reflected on the annotations represented by
* this object unless the tree is copied back to this object by
* <code>setAnnotations()</code>.
*
* @return Each element of the returned array represents an array of
* annotations that are associated with each method parameter.
*
* @see #setAnnotations(com.fr.third.javassist.bytecode.annotation.Annotation[][])
*/
public com.fr.third.javassist.bytecode.annotation.Annotation[][] getAnnotations() {
try {
return new Parser(info, constPool).parseParameters();
}
catch (Exception e) {
throw new RuntimeException(e.toString());
}
}
/**
* Changes the annotations represented by this object according to
* the given array of <code>Annotation</code> objects.
*
* @param params the data structure representing the
* new annotations. Every element of this array
* is an array of <code>Annotation</code> and
* it represens annotations of each method parameter.
*/
public void setAnnotations(com.fr.third.javassist.bytecode.annotation.Annotation[][] params) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
com.fr.third.javassist.bytecode.annotation.AnnotationsWriter writer = new com.fr.third.javassist.bytecode.annotation.AnnotationsWriter(output, constPool);
try {
int n = params.length;
writer.numParameters(n);
for (int i = 0; i < n; ++i) {
com.fr.third.javassist.bytecode.annotation.Annotation[] anno = params[i];
writer.numAnnotations(anno.length);
for (int j = 0; j < anno.length; ++j)
anno[j].write(writer);
}
writer.close();
}
catch (IOException e) {
throw new RuntimeException(e); // should never reach here.
}
set(output.toByteArray());
}
/**
* @param oldname a JVM class name.
* @param newname a JVM class name.
*/
void renameClass(String oldname, String newname) {
HashMap map = new HashMap();
map.put(oldname, newname);
renameClass(map);
}
void renameClass(Map classnames) {
Renamer renamer = new Renamer(info, getConstPool(), classnames);
try {
renamer.parameters();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
void getRefClasses(Map classnames) { renameClass(classnames); }
/**
* Returns a string representation of this object.
*/
public String toString() {
com.fr.third.javassist.bytecode.annotation.Annotation[][] aa = getAnnotations();
StringBuilder sbuf = new StringBuilder();
int k = 0;
while (k < aa.length) {
Annotation[] a = aa[k++];
int i = 0;
while (i < a.length) {
sbuf.append(a[i++].toString());
if (i != a.length)
sbuf.append(" ");
}
if (k != aa.length)
sbuf.append(", ");
}
return sbuf.toString();
}
}

1170
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/SignatureAttribute.java

File diff suppressed because it is too large Load Diff

71
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/SourceFileAttribute.java

@ -1,71 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>SourceFile_attribute</code>.
*/
public class SourceFileAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"SourceFile"</code>.
*/
public static final String tag = "SourceFile";
SourceFileAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a SourceFile attribute.
*
* @param cp a constant pool table.
* @param filename the name of the source file.
*/
public SourceFileAttribute(com.fr.third.javassist.bytecode.ConstPool cp, String filename) {
super(cp, tag);
int index = cp.addUtf8Info(filename);
byte[] bvalue = new byte[2];
bvalue[0] = (byte)(index >>> 8);
bvalue[1] = (byte)index;
set(bvalue);
}
/**
* Returns the file name indicated by <code>sourcefile_index</code>.
*/
public String getFileName() {
return getConstPool().getUtf8Info(ByteArray.readU16bit(get(), 0));
}
/**
* Makes a copy. Class names are replaced according to the
* given <code>Map</code> object.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames pairs of replaced and substituted
* class names.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
return new SourceFileAttribute(newCp, getFileName());
}
}

575
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/StackMap.java

@ -1,575 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
import com.fr.third.javassist.CannotCompileException;
import com.fr.third.javassist.CtBehavior;
import com.fr.third.javassist.CtClass;
/**
* Another <code>stack_map</code> attribute defined in CLDC 1.1 for J2ME.
*
* <p>This is an entry in the attributes table of a Code attribute.
* It was introduced by J2ME CLDC 1.1 (JSR 139) for pre-verification.
*
* <p>According to the CLDC specification, the sizes of some fields are not 16bit
* but 32bit if the code size is more than 64K or the number of the local variables
* is more than 64K. However, for the J2ME CLDC technology, they are always 16bit.
* The implementation of the StackMap class assumes they are 16bit.
*
* @see MethodInfo#doPreverify
* @see StackMapTable
* @since 3.12
*/
public class StackMap extends AttributeInfo {
/**
* The name of this attribute <code>"StackMap"</code>.
*/
public static final String tag = "StackMap";
/**
* Constructs a <code>stack_map</code> attribute.
*/
StackMap(ConstPool cp, byte[] newInfo) {
super(cp, tag, newInfo);
}
StackMap(ConstPool cp, int name_id, DataInputStream in)
throws IOException
{
super(cp, name_id, in);
}
/**
* Returns <code>number_of_entries</code>.
*/
public int numOfEntries() {
return ByteArray.readU16bit(info, 0);
}
/**
* <code>Top_variable_info.tag</code>.
*/
public static final int TOP = 0;
/**
* <code>Integer_variable_info.tag</code>.
*/
public static final int INTEGER = 1;
/**
* <code>Float_variable_info.tag</code>.
*/
public static final int FLOAT = 2;
/**
* <code>Double_variable_info.tag</code>.
*/
public static final int DOUBLE = 3;
/**
* <code>Long_variable_info.tag</code>.
*/
public static final int LONG = 4;
/**
* <code>Null_variable_info.tag</code>.
*/
public static final int NULL = 5;
/**
* <code>UninitializedThis_variable_info.tag</code>.
*/
public static final int THIS = 6;
/**
* <code>Object_variable_info.tag</code>.
*/
public static final int OBJECT = 7;
/**
* <code>Uninitialized_variable_info.tag</code>.
*/
public static final int UNINIT = 8;
/**
* Makes a copy.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
Copier copier = new Copier(this, newCp, classnames);
copier.visit();
return copier.getStackMap();
}
/**
* A code walker for a StackMap attribute.
*/
public static class Walker {
byte[] info;
/**
* Constructs a walker.
*/
public Walker(StackMap sm) {
info = sm.get();
}
/**
* Visits each entry of the stack map frames.
*/
public void visit() {
int num = ByteArray.readU16bit(info, 0);
int pos = 2;
for (int i = 0; i < num; i++) {
int offset = ByteArray.readU16bit(info, pos);
int numLoc = ByteArray.readU16bit(info, pos + 2);
pos = locals(pos + 4, offset, numLoc);
int numStack = ByteArray.readU16bit(info, pos);
pos = stack(pos + 2, offset, numStack);
}
}
/**
* Invoked when <code>locals</code> of <code>stack_map_frame</code>
* is visited.
*/
public int locals(int pos, int offset, int num) {
return typeInfoArray(pos, offset, num, true);
}
/**
* Invoked when <code>stack</code> of <code>stack_map_frame</code>
* is visited.
*/
public int stack(int pos, int offset, int num) {
return typeInfoArray(pos, offset, num, false);
}
/**
* Invoked when an array of <code>verification_type_info</code> is
* visited.
*
* @param num the number of elements.
* @param isLocals true if this array is for <code>locals</code>.
* false if it is for <code>stack</code>.
*/
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) {
for (int k = 0; k < num; k++)
pos = typeInfoArray2(k, pos);
return pos;
}
int typeInfoArray2(int k, int pos) {
byte tag = info[pos];
if (tag == OBJECT) {
int clazz = ByteArray.readU16bit(info, pos + 1);
objectVariable(pos, clazz);
pos += 3;
}
else if (tag == UNINIT) {
int offsetOfNew = ByteArray.readU16bit(info, pos + 1);
uninitialized(pos, offsetOfNew);
pos += 3;
}
else {
typeInfo(pos, tag);
pos++;
}
return pos;
}
/**
* Invoked when an element of <code>verification_type_info</code>
* (except <code>Object_variable_info</code> and
* <code>Uninitialized_variable_info</code>) is visited.
*/
public void typeInfo(int pos, byte tag) {}
/**
* Invoked when an element of type <code>Object_variable_info</code>
* is visited.
*/
public void objectVariable(int pos, int clazz) {}
/**
* Invoked when an element of type <code>Uninitialized_variable_info</code>
* is visited.
*/
public void uninitialized(int pos, int offset) {}
}
static class Copier extends Walker {
byte[] dest;
ConstPool srcCp, destCp;
Map classnames;
Copier(StackMap map, ConstPool newCp, Map classnames) {
super(map);
srcCp = map.getConstPool();
dest = new byte[info.length];
destCp = newCp;
this.classnames = classnames;
}
public void visit() {
int num = ByteArray.readU16bit(info, 0);
ByteArray.write16bit(num, dest, 0);
super.visit();
}
public int locals(int pos, int offset, int num) {
ByteArray.write16bit(offset, dest, pos - 4);
return super.locals(pos, offset, num);
}
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) {
ByteArray.write16bit(num, dest, pos - 2);
return super.typeInfoArray(pos, offset, num, isLocals);
}
public void typeInfo(int pos, byte tag) {
dest[pos] = tag;
}
public void objectVariable(int pos, int clazz) {
dest[pos] = OBJECT;
int newClazz = srcCp.copy(clazz, destCp, classnames);
ByteArray.write16bit(newClazz, dest, pos + 1);
}
public void uninitialized(int pos, int offset) {
dest[pos] = UNINIT;
ByteArray.write16bit(offset, dest, pos + 1);
}
public StackMap getStackMap() {
return new StackMap(destCp, dest);
}
}
/**
* Updates this stack map table when a new local variable is inserted
* for a new parameter.
*
* @param index the index of the added local variable.
* @param tag the type tag of that local variable.
* It is available by <code>StackMapTable.typeTagOf(char)</code>.
* @param classInfo the index of the <code>CONSTANT_Class_info</code> structure
* in a constant pool table. This should be zero unless the tag
* is <code>ITEM_Object</code>.
*
* @see CtBehavior#addParameter(CtClass)
* @see StackMapTable#typeTagOf(char)
* @see ConstPool
*/
public void insertLocal(int index, int tag, int classInfo)
throws BadBytecode
{
byte[] data = new InsertLocal(this, index, tag, classInfo).doit();
this.set(data);
}
static class SimpleCopy extends Walker {
Writer writer;
SimpleCopy(StackMap map) {
super(map);
writer = new Writer();
}
byte[] doit() {
visit();
return writer.toByteArray();
}
public void visit() {
int num = ByteArray.readU16bit(info, 0);
writer.write16bit(num);
super.visit();
}
public int locals(int pos, int offset, int num) {
writer.write16bit(offset);
return super.locals(pos, offset, num);
}
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) {
writer.write16bit(num);
return super.typeInfoArray(pos, offset, num, isLocals);
}
public void typeInfo(int pos, byte tag) {
writer.writeVerifyTypeInfo(tag, 0);
}
public void objectVariable(int pos, int clazz) {
writer.writeVerifyTypeInfo(OBJECT, clazz);
}
public void uninitialized(int pos, int offset) {
writer.writeVerifyTypeInfo(UNINIT, offset);
}
}
static class InsertLocal extends SimpleCopy {
private int varIndex;
private int varTag, varData;
InsertLocal(StackMap map, int varIndex, int varTag, int varData) {
super(map);
this.varIndex = varIndex;
this.varTag = varTag;
this.varData = varData;
}
public int typeInfoArray(int pos, int offset, int num, boolean isLocals) {
if (!isLocals || num < varIndex)
return super.typeInfoArray(pos, offset, num, isLocals);
writer.write16bit(num + 1);
for (int k = 0; k < num; k++) {
if (k == varIndex)
writeVarTypeInfo();
pos = typeInfoArray2(k, pos);
}
if (num == varIndex)
writeVarTypeInfo();
return pos;
}
private void writeVarTypeInfo() {
if (varTag == OBJECT)
writer.writeVerifyTypeInfo(OBJECT, varData);
else if (varTag == UNINIT)
writer.writeVerifyTypeInfo(UNINIT, varData);
else
writer.writeVerifyTypeInfo(varTag, 0);
}
}
void shiftPc(int where, int gapSize, boolean exclusive)
throws BadBytecode
{
new Shifter(this, where, gapSize, exclusive).visit();
}
static class Shifter extends Walker {
private int where, gap;
private boolean exclusive;
public Shifter(StackMap smt, int where, int gap, boolean exclusive) {
super(smt);
this.where = where;
this.gap = gap;
this.exclusive = exclusive;
}
public int locals(int pos, int offset, int num) {
if (exclusive ? where <= offset : where < offset)
ByteArray.write16bit(offset + gap, info, pos - 4);
return super.locals(pos, offset, num);
}
public void uninitialized(int pos, int offset) {
if (where <= offset)
ByteArray.write16bit(offset + gap, info, pos + 1);
}
}
/**
* @see CodeIterator.Switcher#adjustOffsets(int, int)
*/
void shiftForSwitch(int where, int gapSize) throws BadBytecode {
new SwitchShifter(this, where, gapSize).visit();
}
static class SwitchShifter extends Walker {
private int where, gap;
public SwitchShifter(StackMap smt, int where, int gap) {
super(smt);
this.where = where;
this.gap = gap;
}
public int locals(int pos, int offset, int num) {
if (where == pos + offset)
ByteArray.write16bit(offset - gap, info, pos - 4);
else if (where == pos)
ByteArray.write16bit(offset + gap, info, pos - 4);
return super.locals(pos, offset, num);
}
}
/**
* Undocumented method. Do not use; internal-use only.
*
* <p>This method is for javassist.convert.TransformNew.
* It is called to update the stack map when
* the NEW opcode (and the following DUP) is removed.
*
* @param where the position of the removed NEW opcode.
*/
public void removeNew(int where) throws CannotCompileException {
byte[] data = new NewRemover(this, where).doit();
this.set(data);
}
static class NewRemover extends SimpleCopy {
int posOfNew;
NewRemover(StackMap map, int where) {
super(map);
posOfNew = where;
}
public int stack(int pos, int offset, int num) {
return stackTypeInfoArray(pos, offset, num);
}
private int stackTypeInfoArray(int pos, int offset, int num) {
int p = pos;
int count = 0;
for (int k = 0; k < num; k++) {
byte tag = info[p];
if (tag == OBJECT)
p += 3;
else if (tag == UNINIT) {
int offsetOfNew = ByteArray.readU16bit(info, p + 1);
if (offsetOfNew == posOfNew)
count++;
p += 3;
}
else
p++;
}
writer.write16bit(num - count);
for (int k = 0; k < num; k++) {
byte tag = info[pos];
if (tag == OBJECT) {
int clazz = ByteArray.readU16bit(info, pos + 1);
objectVariable(pos, clazz);
pos += 3;
}
else if (tag == UNINIT) {
int offsetOfNew = ByteArray.readU16bit(info, pos + 1);
if (offsetOfNew != posOfNew)
uninitialized(pos, offsetOfNew);
pos += 3;
}
else {
typeInfo(pos, tag);
pos++;
}
}
return pos;
}
}
/**
* Prints this stack map.
*/
public void print(java.io.PrintWriter out) {
new Printer(this, out).print();
}
static class Printer extends Walker {
private java.io.PrintWriter writer;
public Printer(StackMap map, java.io.PrintWriter out) {
super(map);
writer = out;
}
public void print() {
int num = ByteArray.readU16bit(info, 0);
writer.println(num + " entries");
visit();
}
public int locals(int pos, int offset, int num) {
writer.println(" * offset " + offset);
return super.locals(pos, offset, num);
}
}
/**
* Internal use only.
*/
public static class Writer {
// see javassist.bytecode.stackmap.MapMaker
private ByteArrayOutputStream output;
/**
* Constructs a writer.
*/
public Writer() {
output = new ByteArrayOutputStream();
}
/**
* Converts the written data into a byte array.
*/
public byte[] toByteArray() {
return output.toByteArray();
}
/**
* Converts to a <code>StackMap</code> attribute.
*/
public StackMap toStackMap(ConstPool cp) {
return new StackMap(cp, output.toByteArray());
}
/**
* Writes a <code>union verification_type_info</code> value.
*
* @param data <code>cpool_index</code> or <code>offset</code>.
*/
public void writeVerifyTypeInfo(int tag, int data) {
output.write(tag);
if (tag == StackMap.OBJECT || tag == StackMap.UNINIT)
write16bit(data);
}
/**
* Writes a 16bit value.
*/
public void write16bit(int value) {
output.write((value >>> 8) & 0xff);
output.write(value & 0xff);
}
}
}

1051
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/StackMapTable.java

File diff suppressed because it is too large Load Diff

56
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/SyntheticAttribute.java

@ -1,56 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.Map;
/**
* <code>Synthetic_attribute</code>.
*/
public class SyntheticAttribute extends com.fr.third.javassist.bytecode.AttributeInfo {
/**
* The name of this attribute <code>"Synthetic"</code>.
*/
public static final String tag = "Synthetic";
SyntheticAttribute(com.fr.third.javassist.bytecode.ConstPool cp, int n, DataInputStream in)
throws IOException
{
super(cp, n, in);
}
/**
* Constructs a Synthetic attribute.
*
* @param cp a constant pool table.
*/
public SyntheticAttribute(com.fr.third.javassist.bytecode.ConstPool cp) {
super(cp, tag, new byte[0]);
}
/**
* Makes a copy.
*
* @param newCp the constant pool table used by the new copy.
* @param classnames should be null.
*/
public AttributeInfo copy(ConstPool newCp, Map classnames) {
return new SyntheticAttribute(newCp);
}
}

423
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Analyzer.java

@ -1,423 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.Iterator;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.CtMethod;
import com.fr.third.javassist.NotFoundException;
import com.fr.third.javassist.bytecode.AccessFlag;
import com.fr.third.javassist.bytecode.BadBytecode;
import com.fr.third.javassist.bytecode.CodeAttribute;
import com.fr.third.javassist.bytecode.CodeIterator;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.bytecode.Descriptor;
import com.fr.third.javassist.bytecode.ExceptionTable;
import com.fr.third.javassist.bytecode.MethodInfo;
import com.fr.third.javassist.bytecode.Opcode;
/**
* A data-flow analyzer that determines the type state of the stack and local
* variable table at every reachable instruction in a method. During analysis,
* bytecode verification is performed in a similar manner to that described
* in the JVM specification.
*
* <p>Example:</p>
*
* <pre>
* // Method to analyze
* public Object doSomething(int x) {
* Number n;
* if (x < 5) {
* n = new Double(0);
* } else {
* n = new Long(0);
* }
*
* return n;
* }
*
* // Which compiles to:
* // 0: iload_1
* // 1: iconst_5
* // 2: if_icmpge 17
* // 5: new #18; //class java/lang/Double
* // 8: dup
* // 9: dconst_0
* // 10: invokespecial #44; //Method java/lang/Double."<init>":(D)V
* // 13: astore_2
* // 14: goto 26
* // 17: new #16; //class java/lang/Long
* // 20: dup
* // 21: lconst_1
* // 22: invokespecial #47; //Method java/lang/Long."<init>":(J)V
* // 25: astore_2
* // 26: aload_2
* // 27: areturn
*
* public void analyzeIt(CtClass clazz, MethodInfo method) {
* Analyzer analyzer = new Analyzer();
* Frame[] frames = analyzer.analyze(clazz, method);
* frames[0].getLocal(0).getCtClass(); // returns clazz;
* frames[0].getLocal(1).getCtClass(); // returns java.lang.String
* frames[1].peek(); // returns Type.INTEGER
* frames[27].peek().getCtClass(); // returns java.lang.Number
* }
* </pre>
*
* @see FramePrinter
* @author Jason T. Greene
*/
public class Analyzer implements Opcode {
private final SubroutineScanner scanner = new SubroutineScanner();
private CtClass clazz;
private ExceptionInfo[] exceptions;
private com.fr.third.javassist.bytecode.analysis.Frame[] frames;
private Subroutine[] subroutines;
private static class ExceptionInfo {
private int end;
private int handler;
private int start;
private com.fr.third.javassist.bytecode.analysis.Type type;
private ExceptionInfo(int start, int end, int handler, com.fr.third.javassist.bytecode.analysis.Type type) {
this.start = start;
this.end = end;
this.handler = handler;
this.type = type;
}
}
/**
* Performs data-flow analysis on a method and returns an array, indexed by
* instruction position, containing the starting frame state of all reachable
* instructions. Non-reachable code, and illegal code offsets are represented
* as a null in the frame state array. This can be used to detect dead code.
*
* If the method does not contain code (it is either native or abstract), null
* is returned.
*
* @param clazz the declaring class of the method
* @param method the method to analyze
* @return an array, indexed by instruction position, of the starting frame state,
* or null if this method doesn't have code
* @throws BadBytecode if the bytecode does not comply with the JVM specification
*/
public com.fr.third.javassist.bytecode.analysis.Frame[] analyze(CtClass clazz, MethodInfo method) throws BadBytecode {
this.clazz = clazz;
CodeAttribute codeAttribute = method.getCodeAttribute();
// Native or Abstract
if (codeAttribute == null)
return null;
int maxLocals = codeAttribute.getMaxLocals();
int maxStack = codeAttribute.getMaxStack();
int codeLength = codeAttribute.getCodeLength();
CodeIterator iter = codeAttribute.iterator();
IntQueue queue = new IntQueue();
exceptions = buildExceptionInfo(method);
subroutines = scanner.scan(method);
Executor executor = new Executor(clazz.getClassPool(), method.getConstPool());
frames = new com.fr.third.javassist.bytecode.analysis.Frame[codeLength];
frames[iter.lookAhead()] = firstFrame(method, maxLocals, maxStack);
queue.add(iter.next());
while (!queue.isEmpty()) {
analyzeNextEntry(method, iter, queue, executor);
}
return frames;
}
/**
* Performs data-flow analysis on a method and returns an array, indexed by
* instruction position, containing the starting frame state of all reachable
* instructions. Non-reachable code, and illegal code offsets are represented
* as a null in the frame state array. This can be used to detect dead code.
*
* If the method does not contain code (it is either native or abstract), null
* is returned.
*
* @param method the method to analyze
* @return an array, indexed by instruction position, of the starting frame state,
* or null if this method doesn't have code
* @throws BadBytecode if the bytecode does not comply with the JVM specification
*/
public com.fr.third.javassist.bytecode.analysis.Frame[] analyze(CtMethod method) throws BadBytecode {
return analyze(method.getDeclaringClass(), method.getMethodInfo2());
}
private void analyzeNextEntry(MethodInfo method, CodeIterator iter,
IntQueue queue, Executor executor) throws BadBytecode {
int pos = queue.take();
iter.move(pos);
iter.next();
com.fr.third.javassist.bytecode.analysis.Frame frame = frames[pos].copy();
Subroutine subroutine = subroutines[pos];
try {
executor.execute(method, pos, iter, frame, subroutine);
} catch (RuntimeException e) {
throw new BadBytecode(e.getMessage() + "[pos = " + pos + "]", e);
}
int opcode = iter.byteAt(pos);
if (opcode == TABLESWITCH) {
mergeTableSwitch(queue, pos, iter, frame);
} else if (opcode == LOOKUPSWITCH) {
mergeLookupSwitch(queue, pos, iter, frame);
} else if (opcode == RET) {
mergeRet(queue, iter, pos, frame, subroutine);
} else if (com.fr.third.javassist.bytecode.analysis.Util.isJumpInstruction(opcode)) {
int target = com.fr.third.javassist.bytecode.analysis.Util.getJumpTarget(pos, iter);
if (com.fr.third.javassist.bytecode.analysis.Util.isJsr(opcode)) {
// Merge the state before the jsr into the next instruction
mergeJsr(queue, frames[pos], subroutines[target], pos, lookAhead(iter, pos));
} else if (! com.fr.third.javassist.bytecode.analysis.Util.isGoto(opcode)) {
merge(queue, frame, lookAhead(iter, pos));
}
merge(queue, frame, target);
} else if (opcode != ATHROW && ! Util.isReturn(opcode)) {
// Can advance to next instruction
merge(queue, frame, lookAhead(iter, pos));
}
// Merge all exceptions that are reachable from this instruction.
// The redundancy is intentional, since the state must be based
// on the current instruction frame.
mergeExceptionHandlers(queue, method, pos, frame);
}
private ExceptionInfo[] buildExceptionInfo(MethodInfo method) {
ConstPool constPool = method.getConstPool();
ClassPool classes = clazz.getClassPool();
ExceptionTable table = method.getCodeAttribute().getExceptionTable();
ExceptionInfo[] exceptions = new ExceptionInfo[table.size()];
for (int i = 0; i < table.size(); i++) {
int index = table.catchType(i);
com.fr.third.javassist.bytecode.analysis.Type type;
try {
type = index == 0 ? com.fr.third.javassist.bytecode.analysis.Type.THROWABLE : com.fr.third.javassist.bytecode.analysis.Type.get(classes.get(constPool.getClassInfo(index)));
} catch (NotFoundException e) {
throw new IllegalStateException(e.getMessage());
}
exceptions[i] = new ExceptionInfo(table.startPc(i), table.endPc(i), table.handlerPc(i), type);
}
return exceptions;
}
private com.fr.third.javassist.bytecode.analysis.Frame firstFrame(MethodInfo method, int maxLocals, int maxStack) {
int pos = 0;
com.fr.third.javassist.bytecode.analysis.Frame first = new com.fr.third.javassist.bytecode.analysis.Frame(maxLocals, maxStack);
if ((method.getAccessFlags() & AccessFlag.STATIC) == 0) {
first.setLocal(pos++, com.fr.third.javassist.bytecode.analysis.Type.get(clazz));
}
CtClass[] parameters;
try {
parameters = Descriptor.getParameterTypes(method.getDescriptor(), clazz.getClassPool());
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
for (int i = 0; i < parameters.length; i++) {
com.fr.third.javassist.bytecode.analysis.Type type = zeroExtend(com.fr.third.javassist.bytecode.analysis.Type.get(parameters[i]));
first.setLocal(pos++, type);
if (type.getSize() == 2)
first.setLocal(pos++, com.fr.third.javassist.bytecode.analysis.Type.TOP);
}
return first;
}
private int getNext(CodeIterator iter, int of, int restore) throws BadBytecode {
iter.move(of);
iter.next();
int next = iter.lookAhead();
iter.move(restore);
iter.next();
return next;
}
private int lookAhead(CodeIterator iter, int pos) throws BadBytecode {
if (! iter.hasNext())
throw new BadBytecode("Execution falls off end! [pos = " + pos + "]");
return iter.lookAhead();
}
private void merge(IntQueue queue, com.fr.third.javassist.bytecode.analysis.Frame frame, int target) {
com.fr.third.javassist.bytecode.analysis.Frame old = frames[target];
boolean changed;
if (old == null) {
frames[target] = frame.copy();
changed = true;
} else {
changed = old.merge(frame);
}
if (changed) {
queue.add(target);
}
}
private void mergeExceptionHandlers(IntQueue queue, MethodInfo method, int pos, com.fr.third.javassist.bytecode.analysis.Frame frame) {
for (int i = 0; i < exceptions.length; i++) {
ExceptionInfo exception = exceptions[i];
// Start is inclusive, while end is exclusive!
if (pos >= exception.start && pos < exception.end) {
com.fr.third.javassist.bytecode.analysis.Frame newFrame = frame.copy();
newFrame.clearStack();
newFrame.push(exception.type);
merge(queue, newFrame, exception.handler);
}
}
}
private void mergeJsr(IntQueue queue, com.fr.third.javassist.bytecode.analysis.Frame frame, Subroutine sub, int pos, int next) throws BadBytecode {
if (sub == null)
throw new BadBytecode("No subroutine at jsr target! [pos = " + pos + "]");
com.fr.third.javassist.bytecode.analysis.Frame old = frames[next];
boolean changed = false;
if (old == null) {
old = frames[next] = frame.copy();
changed = true;
} else {
for (int i = 0; i < frame.localsLength(); i++) {
// Skip everything accessed by a subroutine, mergeRet must handle this
if (!sub.isAccessed(i)) {
com.fr.third.javassist.bytecode.analysis.Type oldType = old.getLocal(i);
com.fr.third.javassist.bytecode.analysis.Type newType = frame.getLocal(i);
if (oldType == null) {
old.setLocal(i, newType);
changed = true;
continue;
}
newType = oldType.merge(newType);
// Always set the type, in case a multi-type switched to a standard type.
old.setLocal(i, newType);
if (!newType.equals(oldType) || newType.popChanged())
changed = true;
}
}
}
if (! old.isJsrMerged()) {
old.setJsrMerged(true);
changed = true;
}
if (changed && old.isRetMerged())
queue.add(next);
}
private void mergeLookupSwitch(IntQueue queue, int pos, CodeIterator iter, com.fr.third.javassist.bytecode.analysis.Frame frame) throws BadBytecode {
int index = (pos & ~3) + 4;
// default
merge(queue, frame, pos + iter.s32bitAt(index));
int npairs = iter.s32bitAt(index += 4);
int end = npairs * 8 + (index += 4);
// skip "match"
for (index += 4; index < end; index += 8) {
int target = iter.s32bitAt(index) + pos;
merge(queue, frame, target);
}
}
private void mergeRet(IntQueue queue, CodeIterator iter, int pos, com.fr.third.javassist.bytecode.analysis.Frame frame, Subroutine subroutine) throws BadBytecode {
if (subroutine == null)
throw new BadBytecode("Ret on no subroutine! [pos = " + pos + "]");
Iterator callerIter = subroutine.callers().iterator();
while (callerIter.hasNext()) {
int caller = ((Integer) callerIter.next()).intValue();
int returnLoc = getNext(iter, caller, pos);
boolean changed = false;
com.fr.third.javassist.bytecode.analysis.Frame old = frames[returnLoc];
if (old == null) {
old = frames[returnLoc] = frame.copyStack();
changed = true;
} else {
changed = old.mergeStack(frame);
}
for (Iterator i = subroutine.accessed().iterator(); i.hasNext(); ) {
int index = ((Integer)i.next()).intValue();
com.fr.third.javassist.bytecode.analysis.Type oldType = old.getLocal(index);
com.fr.third.javassist.bytecode.analysis.Type newType = frame.getLocal(index);
if (oldType != newType) {
old.setLocal(index, newType);
changed = true;
}
}
if (! old.isRetMerged()) {
old.setRetMerged(true);
changed = true;
}
if (changed && old.isJsrMerged())
queue.add(returnLoc);
}
}
private void mergeTableSwitch(IntQueue queue, int pos, CodeIterator iter, Frame frame) throws BadBytecode {
// Skip 4 byte alignment padding
int index = (pos & ~3) + 4;
// default
merge(queue, frame, pos + iter.s32bitAt(index));
int low = iter.s32bitAt(index += 4);
int high = iter.s32bitAt(index += 4);
int end = (high - low + 1) * 4 + (index += 4);
// Offset table
for (; index < end; index += 4) {
int target = iter.s32bitAt(index) + pos;
merge(queue, frame, target);
}
}
private com.fr.third.javassist.bytecode.analysis.Type zeroExtend(com.fr.third.javassist.bytecode.analysis.Type type) {
if (type == com.fr.third.javassist.bytecode.analysis.Type.SHORT || type == com.fr.third.javassist.bytecode.analysis.Type.BYTE || type == com.fr.third.javassist.bytecode.analysis.Type.CHAR || type == com.fr.third.javassist.bytecode.analysis.Type.BOOLEAN)
return Type.INTEGER;
return type;
}
}

504
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/ControlFlow.java

@ -1,504 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.ArrayList;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.CtMethod;
import com.fr.third.javassist.bytecode.BadBytecode;
import com.fr.third.javassist.bytecode.MethodInfo;
import com.fr.third.javassist.bytecode.stackmap.BasicBlock;
/**
* Represents the control flow graph of a given method.
*
* <p>To obtain the control flow graph, do the following:</p>
*
* <pre>CtMethod m = ...
* ControlFlow cf = new ControlFlow(m);
* Block[] blocks = cf.basicBlocks();
* </pre>
*
* <p><code>blocks</code> is an array of basic blocks in
* that method body.</p>
*
* @see CtMethod
* @see Block
* @see com.fr.third.javassist.bytecode.analysis.Frame
* @see com.fr.third.javassist.bytecode.analysis.Analyzer
* @author Shigeru Chiba
* @since 3.16
*/
public class ControlFlow {
private CtClass clazz;
private MethodInfo methodInfo;
private Block[] basicBlocks;
private com.fr.third.javassist.bytecode.analysis.Frame[] frames;
/**
* Constructs a control-flow analyzer for the given method.
*/
public ControlFlow(CtMethod method) throws BadBytecode {
this(method.getDeclaringClass(), method.getMethodInfo2());
}
/**
* Constructs a control-flow analyzer.
*/
public ControlFlow(CtClass ctclazz, MethodInfo minfo) throws BadBytecode {
clazz = ctclazz;
methodInfo = minfo;
frames = null;
basicBlocks = (Block[])new BasicBlock.Maker() {
protected BasicBlock makeBlock(int pos) {
return new Block(pos, methodInfo);
}
protected BasicBlock[] makeArray(int size) {
return new Block[size];
}
}.make(minfo);
int size = basicBlocks.length;
int[] counters = new int[size];
for (int i = 0; i < size; i++) {
Block b = basicBlocks[i];
b.index = i;
b.entrances = new Block[b.incomings()];
counters[i] = 0;
}
for (int i = 0; i < size; i++) {
Block b = basicBlocks[i];
for (int k = 0; k < b.exits(); k++) {
Block e = b.exit(k);
e.entrances[counters[e.index]++] = b;
}
ControlFlow.Catcher[] catchers = b.catchers();
for (int k = 0; k < catchers.length; k++) {
Block catchBlock = catchers[k].node;
catchBlock.entrances[counters[catchBlock.index]++] = b;
}
}
}
/**
* Returns all the basic blocks in the method body.
*/
public Block[] basicBlocks() {
return basicBlocks;
}
/**
* Returns the types of the local variables and stack frame entries
* available at the given position. If the byte at the position is
* not the first byte of an instruction, then this method returns
* null.
*
* @param pos the position.
*/
public Frame frameAt(int pos) throws BadBytecode {
if (frames == null)
frames = new Analyzer().analyze(clazz, methodInfo);
return frames[pos];
}
/**
* Constructs a dominator tree. This method returns an array of
* the tree nodes. The first element of the array is the root
* of the tree.
*
* <p> The order of the elements is the same as that
* of the elements in the <code>Block</code> array returned
* by the <code>basicBlocks</code>
* method. If a <code>Block</code> object is at the i-th position
* in the <code>Block</code> array, then
* the <code>Node</code> object referring to that
* <code>Block</code> object is at the i-th position in the
* array returned by this method.
* For every array element <code>node</code>, its index in the
* array is equivalent to <code>node.block().index()</code>.
*
* @return an array of the tree nodes, or null if the method is abstract.
* @see Node#block()
* @see Block#index()
*/
public Node[] dominatorTree() {
int size = basicBlocks.length;
if (size == 0)
return null;
Node[] nodes = new Node[size];
boolean[] visited = new boolean[size];
int[] distance = new int[size];
for (int i = 0; i < size; i++) {
nodes[i] = new Node(basicBlocks[i]);
visited[i] = false;
}
Access access = new Access(nodes) {
BasicBlock[] exits(Node n) { return n.block.getExit(); }
BasicBlock[] entrances(Node n) { return n.block.entrances; }
};
nodes[0].makeDepth1stTree(null, visited, 0, distance, access);
do {
for (int i = 0; i < size; i++)
visited[i] = false;
} while (nodes[0].makeDominatorTree(visited, distance, access));
Node.setChildren(nodes);
return nodes;
}
/**
* Constructs a post dominator tree. This method returns an array of
* the tree nodes. Note that the tree has multiple roots.
* The parent of the root nodes is null.
*
* <p> The order of the elements is the same as that
* of the elements in the <code>Block</code> array returned
* by the <code>basicBlocks</code>
* method. If a <code>Block</code> object is at the i-th position
* in the <code>Block</code> array, then
* the <code>Node</code> object referring to that
* <code>Block</code> object is at the i-th position in the
* array returned by this method.
* For every array element <code>node</code>, its index in the
* array is equivalent to <code>node.block().index()</code>.
*
* @return an array of the tree nodes, or null if the method is abstract.
* @see Node#block()
* @see Block#index()
*/
public Node[] postDominatorTree() {
int size = basicBlocks.length;
if (size == 0)
return null;
Node[] nodes = new Node[size];
boolean[] visited = new boolean[size];
int[] distance = new int[size];
for (int i = 0; i < size; i++) {
nodes[i] = new Node(basicBlocks[i]);
visited[i] = false;
}
Access access = new Access(nodes) {
BasicBlock[] exits(Node n) { return n.block.entrances; }
BasicBlock[] entrances(Node n) { return n.block.getExit(); }
};
int counter = 0;
for (int i = 0; i < size; i++)
if (nodes[i].block.exits() == 0)
counter = nodes[i].makeDepth1stTree(null, visited, counter, distance, access);
boolean changed;
do {
for (int i = 0; i < size; i++)
visited[i] = false;
changed = false;
for (int i = 0; i < size; i++)
if (nodes[i].block.exits() == 0)
if (nodes[i].makeDominatorTree(visited, distance, access))
changed = true;
} while (changed);
Node.setChildren(nodes);
return nodes;
}
/**
* Basic block.
* It is a sequence of contiguous instructions that do not contain
* jump/branch instructions except the last one.
* Since Java6 or later does not allow <code>JSR</code>,
* we deal with <code>JSR</code> as a non-branch instruction.
*/
public static class Block extends BasicBlock {
/**
* A field that can be freely used for storing extra data.
* A client program of this control-flow analyzer can append
* an additional attribute to a <code>Block</code> object.
* The Javassist library never accesses this field.
*/
public Object clientData = null;
int index;
MethodInfo method;
Block[] entrances;
Block(int pos, MethodInfo minfo) {
super(pos);
method = minfo;
}
protected void toString2(StringBuffer sbuf) {
super.toString2(sbuf);
sbuf.append(", incoming{");
for (int i = 0; i < entrances.length; i++)
sbuf.append(entrances[i].position).append(", ");
sbuf.append("}");
}
BasicBlock[] getExit() { return exit; }
/**
* Returns the position of this block in the array of
* basic blocks that the <code>basicBlocks</code> method
* returns.
*
* @see #basicBlocks()
*/
public int index() { return index; }
/**
* Returns the position of the first instruction
* in this block.
*/
public int position() { return position; }
/**
* Returns the length of this block.
*/
public int length() { return length; }
/**
* Returns the number of the control paths entering this block.
*/
public int incomings() { return incoming; }
/**
* Returns the block that the control may jump into this block from.
*/
public Block incoming(int n) {
return entrances[n];
}
/**
* Return the number of the blocks that may be executed
* after this block.
*/
public int exits() { return exit == null ? 0 : exit.length; }
/**
* Returns the n-th block that may be executed after this
* block.
*
* @param n an index in the array of exit blocks.
*/
public Block exit(int n) { return (Block)exit[n]; }
/**
* Returns catch clauses that will catch an exception thrown
* in this block.
*/
public Catcher[] catchers() {
ArrayList catchers = new ArrayList();
BasicBlock.Catch c = toCatch;
while (c != null) {
catchers.add(new Catcher(c));
c = c.next;
}
return (Catcher[])catchers.toArray(new Catcher[catchers.size()]);
}
}
static abstract class Access {
Node[] all;
Access(Node[] nodes) { all = nodes; }
Node node(BasicBlock b) { return all[((Block)b).index]; }
abstract BasicBlock[] exits(Node n);
abstract BasicBlock[] entrances(Node n);
}
/**
* A node of (post) dominator trees.
*/
public static class Node {
private Block block;
private Node parent;
private Node[] children;
Node(Block b) {
block = b;
parent = null;
}
/**
* Returns a <code>String</code> representation.
*/
public String toString() {
StringBuffer sbuf = new StringBuffer();
sbuf.append("Node[pos=").append(block().position());
sbuf.append(", parent=");
sbuf.append(parent == null ? "*" : Integer.toString(parent.block().position()));
sbuf.append(", children{");
for (int i = 0; i < children.length; i++)
sbuf.append(children[i].block().position()).append(", ");
sbuf.append("}]");
return sbuf.toString();
}
/**
* Returns the basic block indicated by this node.
*/
public Block block() { return block; }
/**
* Returns the parent of this node.
*/
public Node parent() { return parent; }
/**
* Returns the number of the children of this node.
*/
public int children() { return children.length; }
/**
* Returns the n-th child of this node.
*
* @param n an index in the array of children.
*/
public Node child(int n) { return children[n]; }
/*
* After executing this method, distance[] represents the post order of the tree nodes.
* It also represents distances from the root; a bigger number represents a shorter
* distance. parent is set to its parent in the depth first spanning tree.
*/
int makeDepth1stTree(Node caller, boolean[] visited, int counter, int[] distance, Access access) {
int index = block.index;
if (visited[index])
return counter;
visited[index] = true;
parent = caller;
BasicBlock[] exits = access.exits(this);
if (exits != null)
for (int i = 0; i < exits.length; i++) {
Node n = access.node(exits[i]);
counter = n.makeDepth1stTree(this, visited, counter, distance, access);
}
distance[index] = counter++;
return counter;
}
boolean makeDominatorTree(boolean[] visited, int[] distance, Access access) {
int index = block.index;
if (visited[index])
return false;
visited[index] = true;
boolean changed = false;
BasicBlock[] exits = access.exits(this);
if (exits != null)
for (int i = 0; i < exits.length; i++) {
Node n = access.node(exits[i]);
if (n.makeDominatorTree(visited, distance, access))
changed = true;
}
BasicBlock[] entrances = access.entrances(this);
if (entrances != null)
for (int i = 0; i < entrances.length; i++) {
if (parent != null) {
Node n = getAncestor(parent, access.node(entrances[i]), distance);
if (n != parent) {
parent = n;
changed = true;
}
}
}
return changed;
}
private static Node getAncestor(Node n1, Node n2, int[] distance) {
while (n1 != n2) {
if (distance[n1.block.index] < distance[n2.block.index])
n1 = n1.parent;
else
n2 = n2.parent;
if (n1 == null || n2 == null)
return null;
}
return n1;
}
private static void setChildren(Node[] all) {
int size = all.length;
int[] nchildren = new int[size];
for (int i = 0; i < size; i++)
nchildren[i] = 0;
for (int i = 0; i < size; i++) {
Node p = all[i].parent;
if (p != null)
nchildren[p.block.index]++;
}
for (int i = 0; i < size; i++)
all[i].children = new Node[nchildren[i]];
for (int i = 0; i < size; i++)
nchildren[i] = 0;
for (int i = 0; i < size; i++) {
Node n = all[i];
Node p = n.parent;
if (p != null)
p.children[nchildren[p.block.index]++] = n;
}
}
}
/**
* Represents a catch clause.
*/
public static class Catcher {
private Block node;
private int typeIndex;
Catcher(BasicBlock.Catch c) {
node = (Block)c.body;
typeIndex = c.typeIndex;
}
/**
* Returns the first block of the catch clause.
*/
public Block block() { return node; }
/**
* Returns the name of the exception type that
* this catch clause catches.
*/
public String type() {
if (typeIndex == 0)
return "java.lang.Throwable";
else
return node.method.getConstPool().getClassInfo(typeIndex);
}
}
}

1047
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Executor.java

File diff suppressed because it is too large Load Diff

289
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Frame.java

@ -1,289 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
/**
* Represents the stack frame and local variable table at a particular point in time.
*
* @author Jason T. Greene
*/
public class Frame {
private com.fr.third.javassist.bytecode.analysis.Type[] locals;
private com.fr.third.javassist.bytecode.analysis.Type[] stack;
private int top;
private boolean jsrMerged;
private boolean retMerged;
/**
* Create a new frame with the specified local variable table size, and max stack size
*
* @param locals the number of local variable table entries
* @param stack the maximum stack size
*/
public Frame(int locals, int stack) {
this.locals = new com.fr.third.javassist.bytecode.analysis.Type[locals];
this.stack = new com.fr.third.javassist.bytecode.analysis.Type[stack];
}
/**
* Returns the local varaible table entry at index.
*
* @param index the position in the table
* @return the type if one exists, or null if the position is empty
*/
public com.fr.third.javassist.bytecode.analysis.Type getLocal(int index) {
return locals[index];
}
/**
* Sets the local variable table entry at index to a type.
*
* @param index the position in the table
* @param type the type to set at the position
*/
public void setLocal(int index, com.fr.third.javassist.bytecode.analysis.Type type) {
locals[index] = type;
}
/**
* Returns the type on the stack at the specified index.
*
* @param index the position on the stack
* @return the type of the stack position
*/
public com.fr.third.javassist.bytecode.analysis.Type getStack(int index) {
return stack[index];
}
/**
* Sets the type of the stack position
*
* @param index the position on the stack
* @param type the type to set
*/
public void setStack(int index, com.fr.third.javassist.bytecode.analysis.Type type) {
stack[index] = type;
}
/**
* Empties the stack
*/
public void clearStack() {
top = 0;
}
/**
* Gets the index of the type sitting at the top of the stack.
* This is not to be confused with a length operation which
* would return the number of elements, not the position of
* the last element.
*
* @return the position of the element at the top of the stack
*/
public int getTopIndex() {
return top - 1;
}
/**
* Returns the number of local variable table entries, specified
* at construction.
*
* @return the number of local variable table entries
*/
public int localsLength() {
return locals.length;
}
/**
* Gets the top of the stack without altering it
*
* @return the top of the stack
*/
public com.fr.third.javassist.bytecode.analysis.Type peek() {
if (top < 1)
throw new IndexOutOfBoundsException("Stack is empty");
return stack[top - 1];
}
/**
* Alters the stack to contain one less element and return it.
*
* @return the element popped from the stack
*/
public com.fr.third.javassist.bytecode.analysis.Type pop() {
if (top < 1)
throw new IndexOutOfBoundsException("Stack is empty");
return stack[--top];
}
/**
* Alters the stack by placing the passed type on the top
*
* @param type the type to add to the top
*/
public void push(com.fr.third.javassist.bytecode.analysis.Type type) {
stack[top++] = type;
}
/**
* Makes a shallow copy of this frame, i.e. the type instances will
* remain the same.
*
* @return the shallow copy
*/
public Frame copy() {
Frame frame = new Frame(locals.length, stack.length);
System.arraycopy(locals, 0, frame.locals, 0, locals.length);
System.arraycopy(stack, 0, frame.stack, 0, stack.length);
frame.top = top;
return frame;
}
/**
* Makes a shallow copy of the stack portion of this frame. The local
* variable table size will be copied, but its contents will be empty.
*
* @return the shallow copy of the stack
*/
public Frame copyStack() {
Frame frame = new Frame(locals.length, stack.length);
System.arraycopy(stack, 0, frame.stack, 0, stack.length);
frame.top = top;
return frame;
}
/**
* Merges all types on the stack of this frame instance with that of the specified frame.
* The local variable table is left untouched.
*
* @param frame the frame to merge the stack from
* @return true if any changes where made
*/
public boolean mergeStack(Frame frame) {
boolean changed = false;
if (top != frame.top)
throw new RuntimeException("Operand stacks could not be merged, they are different sizes!");
for (int i = 0; i < top; i++) {
if (stack[i] != null) {
com.fr.third.javassist.bytecode.analysis.Type prev = stack[i];
com.fr.third.javassist.bytecode.analysis.Type merged = prev.merge(frame.stack[i]);
if (merged == com.fr.third.javassist.bytecode.analysis.Type.BOGUS)
throw new RuntimeException("Operand stacks could not be merged due to differing primitive types: pos = " + i);
stack[i] = merged;
// always replace the instance in case a multi-interface type changes to a normal Type
if ((! merged.equals(prev)) || merged.popChanged()) {
changed = true;
}
}
}
return changed;
}
/**
* Merges all types on the stack and local variable table of this frame with that of the specified
* type.
*
* @param frame the frame to merge with
* @return true if any changes to this frame where made by this merge
*/
public boolean merge(Frame frame) {
boolean changed = false;
// Local variable table
for (int i = 0; i < locals.length; i++) {
if (locals[i] != null) {
com.fr.third.javassist.bytecode.analysis.Type prev = locals[i];
Type merged = prev.merge(frame.locals[i]);
// always replace the instance in case a multi-interface type changes to a normal Type
locals[i] = merged;
if (! merged.equals(prev) || merged.popChanged()) {
changed = true;
}
} else if (frame.locals[i] != null) {
locals[i] = frame.locals[i];
changed = true;
}
}
changed |= mergeStack(frame);
return changed;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("locals = [");
for (int i = 0; i < locals.length; i++) {
buffer.append(locals[i] == null ? "empty" : locals[i].toString());
if (i < locals.length - 1)
buffer.append(", ");
}
buffer.append("] stack = [");
for (int i = 0; i < top; i++) {
buffer.append(stack[i]);
if (i < top - 1)
buffer.append(", ");
}
buffer.append("]");
return buffer.toString();
}
/**
* Whether or not state from the source JSR instruction has been merged
*
* @return true if JSR state has been merged
*/
boolean isJsrMerged() {
return jsrMerged;
}
/**
* Sets whether of not the state from the source JSR instruction has been merged
*
* @param jsrMerged true if merged, otherwise false
*/
void setJsrMerged(boolean jsrMerged) {
this.jsrMerged = jsrMerged;
}
/**
* Whether or not state from the RET instruction, of the subroutine that was jumped
* to has been merged.
*
* @return true if RET state has been merged
*/
boolean isRetMerged() {
return retMerged;
}
/**
* Sets whether or not state from the RET instruction, of the subroutine that was jumped
* to has been merged.
*
* @param retMerged true if RET state has been merged
*/
void setRetMerged(boolean retMerged) {
this.retMerged = retMerged;
}
}

148
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/FramePrinter.java

@ -1,148 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.io.PrintStream;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.CtMethod;
import com.fr.third.javassist.Modifier;
import com.fr.third.javassist.NotFoundException;
import com.fr.third.javassist.bytecode.BadBytecode;
import com.fr.third.javassist.bytecode.CodeAttribute;
import com.fr.third.javassist.bytecode.CodeIterator;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.bytecode.Descriptor;
import com.fr.third.javassist.bytecode.InstructionPrinter;
import com.fr.third.javassist.bytecode.MethodInfo;
/**
* A utility class for printing a merged view of the frame state and the
* instructions of a method.
*
* @author Jason T. Greene
*/
public final class FramePrinter {
private final PrintStream stream;
/**
* Constructs a bytecode printer.
*/
public FramePrinter(PrintStream stream) {
this.stream = stream;
}
/**
* Prints all the methods declared in the given class.
*/
public static void print(CtClass clazz, PrintStream stream) {
(new FramePrinter(stream)).print(clazz);
}
/**
* Prints all the methods declared in the given class.
*/
public void print(CtClass clazz) {
CtMethod[] methods = clazz.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
print(methods[i]);
}
}
private String getMethodString(CtMethod method) {
try {
return Modifier.toString(method.getModifiers()) + " "
+ method.getReturnType().getName() + " " + method.getName()
+ Descriptor.toString(method.getSignature()) + ";";
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
}
/**
* Prints the instructions and the frame states of the given method.
*/
public void print(CtMethod method) {
stream.println("\n" + getMethodString(method));
MethodInfo info = method.getMethodInfo2();
ConstPool pool = info.getConstPool();
CodeAttribute code = info.getCodeAttribute();
if (code == null)
return;
com.fr.third.javassist.bytecode.analysis.Frame[] frames;
try {
frames = (new Analyzer()).analyze(method.getDeclaringClass(), info);
} catch (BadBytecode e) {
throw new RuntimeException(e);
}
int spacing = String.valueOf(code.getCodeLength()).length();
CodeIterator iterator = code.iterator();
while (iterator.hasNext()) {
int pos;
try {
pos = iterator.next();
} catch (BadBytecode e) {
throw new RuntimeException(e);
}
stream.println(pos + ": " + InstructionPrinter.instructionString(iterator, pos, pool));
addSpacing(spacing + 3);
com.fr.third.javassist.bytecode.analysis.Frame frame = frames[pos];
if (frame == null) {
stream.println("--DEAD CODE--");
continue;
}
printStack(frame);
addSpacing(spacing + 3);
printLocals(frame);
}
}
private void printStack(com.fr.third.javassist.bytecode.analysis.Frame frame) {
stream.print("stack [");
int top = frame.getTopIndex();
for (int i = 0; i <= top; i++) {
if (i > 0)
stream.print(", ");
com.fr.third.javassist.bytecode.analysis.Type type = frame.getStack(i);
stream.print(type);
}
stream.println("]");
}
private void printLocals(Frame frame) {
stream.print("locals [");
int length = frame.localsLength();
for (int i = 0; i < length; i++) {
if (i > 0)
stream.print(", ");
Type type = frame.getLocal(i);
stream.print(type == null ? "empty" : type.toString());
}
stream.println("]");
}
private void addSpacing(int count) {
while (count-- > 0)
stream.print(' ');
}
}

57
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/IntQueue.java

@ -1,57 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.NoSuchElementException;
class IntQueue {
private static class Entry {
private IntQueue.Entry next;
private int value;
private Entry(int value) {
this.value = value;
}
}
private IntQueue.Entry head;
private IntQueue.Entry tail;
void add(int value) {
IntQueue.Entry entry = new Entry(value);
if (tail != null)
tail.next = entry;
tail = entry;
if (head == null)
head = entry;
}
boolean isEmpty() {
return head == null;
}
int take() {
if (head == null)
throw new NoSuchElementException();
int value = head.value;
head = head.next;
if (head == null)
tail = null;
return value;
}
}

130
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/MultiArrayType.java

@ -1,130 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.NotFoundException;
/**
* Represents an array of {@link com.fr.third.javassist.bytecode.analysis.MultiType} instances.
*
* @author Jason T. Greene
*/
public class MultiArrayType extends com.fr.third.javassist.bytecode.analysis.Type {
private com.fr.third.javassist.bytecode.analysis.MultiType component;
private int dims;
public MultiArrayType(MultiType component, int dims) {
super(null);
this.component = component;
this.dims = dims;
}
public CtClass getCtClass() {
CtClass clazz = component.getCtClass();
if (clazz == null)
return null;
ClassPool pool = clazz.getClassPool();
if (pool == null)
pool = ClassPool.getDefault();
String name = arrayName(clazz.getName(), dims);
try {
return pool.get(name);
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
}
boolean popChanged() {
return component.popChanged();
}
public int getDimensions() {
return dims;
}
public com.fr.third.javassist.bytecode.analysis.Type getComponent() {
return dims == 1 ? (com.fr.third.javassist.bytecode.analysis.Type)component : new MultiArrayType(component, dims - 1);
}
public int getSize() {
return 1;
}
public boolean isArray() {
return true;
}
public boolean isAssignableFrom(com.fr.third.javassist.bytecode.analysis.Type type) {
throw new UnsupportedOperationException("Not implemented");
}
public boolean isReference() {
return true;
}
public boolean isAssignableTo(com.fr.third.javassist.bytecode.analysis.Type type) {
if (eq(type.getCtClass(), com.fr.third.javassist.bytecode.analysis.Type.OBJECT.getCtClass()))
return true;
if (eq(type.getCtClass(), com.fr.third.javassist.bytecode.analysis.Type.CLONEABLE.getCtClass()))
return true;
if (eq(type.getCtClass(), com.fr.third.javassist.bytecode.analysis.Type.SERIALIZABLE.getCtClass()))
return true;
if (! type.isArray())
return false;
com.fr.third.javassist.bytecode.analysis.Type typeRoot = getRootComponent(type);
int typeDims = type.getDimensions();
if (typeDims > dims)
return false;
if (typeDims < dims) {
if (eq(typeRoot.getCtClass(), com.fr.third.javassist.bytecode.analysis.Type.OBJECT.getCtClass()))
return true;
if (eq(typeRoot.getCtClass(), com.fr.third.javassist.bytecode.analysis.Type.CLONEABLE.getCtClass()))
return true;
if (eq(typeRoot.getCtClass(), Type.SERIALIZABLE.getCtClass()))
return true;
return false;
}
return component.isAssignableTo(typeRoot);
}
public boolean equals(Object o) {
if (! (o instanceof MultiArrayType))
return false;
MultiArrayType multi = (MultiArrayType)o;
return component.equals(multi.component) && dims == multi.dims;
}
public String toString() {
// follows the same detailed formating scheme as component
return arrayName(component.toString(), dims);
}
}

314
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/MultiType.java

@ -1,314 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.fr.third.javassist.CtClass;
/**
* MultiType represents an unresolved type. Whenever two <literal>Type</literal>
* instances are merged, if they share more than one super type (either an
* interface or a superclass), then a <literal>MultiType</literal> is used to
* represent the possible super types. The goal of a <literal>MultiType</literal>
* is to reduce the set of possible types down to a single resolved type. This
* is done by eliminating non-assignable types from the typeset when the
* <literal>MultiType</literal> is passed as an argument to
* {@link com.fr.third.javassist.bytecode.analysis.Type#isAssignableFrom(com.fr.third.javassist.bytecode.analysis.Type)}, as well as removing non-intersecting
* types during a merge.
*
* Note: Currently the <litera>MultiType</literal> instance is reused as much
* as possible so that updates are visible from all frames. In addition, all
* <literal>MultiType</literal> merge paths are also updated. This is somewhat
* hackish, but it appears to handle most scenarios.
*
* @author Jason T. Greene
*/
/* TODO - A better, but more involved, approach would be to track the instruction
* offset that resulted in the creation of this type, and
* whenever the typeset changes, to force a merge on that position. This
* would require creating a new MultiType instance every time the typeset
* changes, and somehow communicating assignment changes to the Analyzer
*/
public class MultiType extends com.fr.third.javassist.bytecode.analysis.Type {
private Map interfaces;
private com.fr.third.javassist.bytecode.analysis.Type resolved;
private com.fr.third.javassist.bytecode.analysis.Type potentialClass;
private MultiType mergeSource;
private boolean changed = false;
public MultiType(Map interfaces) {
this(interfaces, null);
}
public MultiType(Map interfaces, com.fr.third.javassist.bytecode.analysis.Type potentialClass) {
super(null);
this.interfaces = interfaces;
this.potentialClass = potentialClass;
}
/**
* Gets the class that corresponds with this type. If this information
* is not yet known, java.lang.Object will be returned.
*/
public CtClass getCtClass() {
if (resolved != null)
return resolved.getCtClass();
return com.fr.third.javassist.bytecode.analysis.Type.OBJECT.getCtClass();
}
/**
* Always returns null since this type is never used for an array.
*/
public com.fr.third.javassist.bytecode.analysis.Type getComponent() {
return null;
}
/**
* Always returns 1, since this type is a reference.
*/
public int getSize() {
return 1;
}
/**
* Always reutnrs false since this type is never used for an array
*/
public boolean isArray() {
return false;
}
/**
* Returns true if the internal state has changed.
*/
boolean popChanged() {
boolean changed = this.changed;
this.changed = false;
return changed;
}
public boolean isAssignableFrom(com.fr.third.javassist.bytecode.analysis.Type type) {
throw new UnsupportedOperationException("Not implemented");
}
public boolean isAssignableTo(com.fr.third.javassist.bytecode.analysis.Type type) {
if (resolved != null)
return type.isAssignableFrom(resolved);
if (com.fr.third.javassist.bytecode.analysis.Type.OBJECT.equals(type))
return true;
if (potentialClass != null && !type.isAssignableFrom(potentialClass))
potentialClass = null;
Map map = mergeMultiAndSingle(this, type);
if (map.size() == 1 && potentialClass == null) {
// Update previous merge paths to the same resolved type
resolved = com.fr.third.javassist.bytecode.analysis.Type.get((CtClass)map.values().iterator().next());
propogateResolved();
return true;
}
// Keep all previous merge paths up to date
if (map.size() >= 1) {
interfaces = map;
propogateState();
return true;
}
if (potentialClass != null) {
resolved = potentialClass;
propogateResolved();
return true;
}
return false;
}
private void propogateState() {
MultiType source = mergeSource;
while (source != null) {
source.interfaces = interfaces;
source.potentialClass = potentialClass;
source = source.mergeSource;
}
}
private void propogateResolved() {
MultiType source = mergeSource;
while (source != null) {
source.resolved = resolved;
source = source.mergeSource;
}
}
/**
* Always returns true, since this type is always a reference.
*
* @return true
*/
public boolean isReference() {
return true;
}
private Map getAllMultiInterfaces(MultiType type) {
Map map = new HashMap();
Iterator iter = type.interfaces.values().iterator();
while (iter.hasNext()) {
CtClass intf = (CtClass)iter.next();
map.put(intf.getName(), intf);
getAllInterfaces(intf, map);
}
return map;
}
private Map mergeMultiInterfaces(MultiType type1, MultiType type2) {
Map map1 = getAllMultiInterfaces(type1);
Map map2 = getAllMultiInterfaces(type2);
return findCommonInterfaces(map1, map2);
}
private Map mergeMultiAndSingle(MultiType multi, com.fr.third.javassist.bytecode.analysis.Type single) {
Map map1 = getAllMultiInterfaces(multi);
Map map2 = getAllInterfaces(single.getCtClass(), null);
return findCommonInterfaces(map1, map2);
}
private boolean inMergeSource(MultiType source) {
while (source != null) {
if (source == this)
return true;
source = source.mergeSource;
}
return false;
}
public com.fr.third.javassist.bytecode.analysis.Type merge(com.fr.third.javassist.bytecode.analysis.Type type) {
if (this == type)
return this;
if (type == UNINIT)
return this;
if (type == BOGUS)
return BOGUS;
if (type == null)
return this;
if (resolved != null)
return resolved.merge(type);
if (potentialClass != null) {
com.fr.third.javassist.bytecode.analysis.Type mergePotential = potentialClass.merge(type);
if (! mergePotential.equals(potentialClass) || mergePotential.popChanged()) {
potentialClass = com.fr.third.javassist.bytecode.analysis.Type.OBJECT.equals(mergePotential) ? null : mergePotential;
changed = true;
}
}
Map merged;
if (type instanceof MultiType) {
MultiType multi = (MultiType)type;
if (multi.resolved != null) {
merged = mergeMultiAndSingle(this, multi.resolved);
} else {
merged = mergeMultiInterfaces(multi, this);
if (! inMergeSource(multi))
mergeSource = multi;
}
} else {
merged = mergeMultiAndSingle(this, type);
}
// Keep all previous merge paths up to date
if (merged.size() > 1 || (merged.size() == 1 && potentialClass != null)) {
// Check for changes
if (merged.size() != interfaces.size()) {
changed = true;
} else if (changed == false){
Iterator iter = merged.keySet().iterator();
while (iter.hasNext())
if (! interfaces.containsKey(iter.next()))
changed = true;
}
interfaces = merged;
propogateState();
return this;
}
if (merged.size() == 1) {
resolved = Type.get((CtClass) merged.values().iterator().next());
} else if (potentialClass != null){
resolved = potentialClass;
} else {
resolved = OBJECT;
}
propogateResolved();
return resolved;
}
public boolean equals(Object o) {
if (! (o instanceof MultiType))
return false;
MultiType multi = (MultiType) o;
if (resolved != null)
return resolved.equals(multi.resolved);
else if (multi.resolved != null)
return false;
return interfaces.keySet().equals(multi.interfaces.keySet());
}
public String toString() {
if (resolved != null)
return resolved.toString();
StringBuffer buffer = new StringBuffer("{");
Iterator iter = interfaces.keySet().iterator();
while (iter.hasNext()) {
buffer.append(iter.next());
buffer.append(", ");
}
buffer.setLength(buffer.length() - 2);
if (potentialClass != null)
buffer.append(", *").append(potentialClass.toString());
buffer.append("}");
return buffer.toString();
}
}

67
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Subroutine.java

@ -1,67 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Represents a nested method subroutine (marked by JSR and RET).
*
* @author Jason T. Greene
*/
public class Subroutine {
//private Set callers = new HashSet();
private List callers = new ArrayList();
private Set access = new HashSet();
private int start;
public Subroutine(int start, int caller) {
this.start = start;
callers.add(new Integer(caller));
}
public void addCaller(int caller) {
callers.add(new Integer(caller));
}
public int start() {
return start;
}
public void access(int index) {
access.add(new Integer(index));
}
public boolean isAccessed(int index) {
return access.contains(new Integer(index));
}
public Collection accessed() {
return access;
}
public Collection callers() {
return callers;
}
public String toString() {
return "start = " + start + " callers = " + callers.toString();
}
}

157
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/SubroutineScanner.java

@ -1,157 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.fr.third.javassist.bytecode.BadBytecode;
import com.fr.third.javassist.bytecode.CodeAttribute;
import com.fr.third.javassist.bytecode.CodeIterator;
import com.fr.third.javassist.bytecode.ExceptionTable;
import com.fr.third.javassist.bytecode.MethodInfo;
import com.fr.third.javassist.bytecode.Opcode;
/**
* Discovers the subroutines in a method, and tracks all callers.
*
* @author Jason T. Greene
*/
public class SubroutineScanner implements Opcode {
private com.fr.third.javassist.bytecode.analysis.Subroutine[] subroutines;
Map subTable = new HashMap();
Set done = new HashSet();
public com.fr.third.javassist.bytecode.analysis.Subroutine[] scan(MethodInfo method) throws BadBytecode {
CodeAttribute code = method.getCodeAttribute();
CodeIterator iter = code.iterator();
subroutines = new com.fr.third.javassist.bytecode.analysis.Subroutine[code.getCodeLength()];
subTable.clear();
done.clear();
scan(0, iter, null);
ExceptionTable exceptions = code.getExceptionTable();
for (int i = 0; i < exceptions.size(); i++) {
int handler = exceptions.handlerPc(i);
// If an exception is thrown in subroutine, the handler
// is part of the same subroutine.
scan(handler, iter, subroutines[exceptions.startPc(i)]);
}
return subroutines;
}
private void scan(int pos, CodeIterator iter, com.fr.third.javassist.bytecode.analysis.Subroutine sub) throws BadBytecode {
// Skip already processed blocks
if (done.contains(new Integer(pos)))
return;
done.add(new Integer(pos));
int old = iter.lookAhead();
iter.move(pos);
boolean next;
do {
pos = iter.next();
next = scanOp(pos, iter, sub) && iter.hasNext();
} while (next);
iter.move(old);
}
private boolean scanOp(int pos, CodeIterator iter, com.fr.third.javassist.bytecode.analysis.Subroutine sub) throws BadBytecode {
subroutines[pos] = sub;
int opcode = iter.byteAt(pos);
if (opcode == TABLESWITCH) {
scanTableSwitch(pos, iter, sub);
return false;
}
if (opcode == LOOKUPSWITCH) {
scanLookupSwitch(pos, iter, sub);
return false;
}
// All forms of return and throw end current code flow
if (com.fr.third.javassist.bytecode.analysis.Util.isReturn(opcode) || opcode == RET || opcode == ATHROW)
return false;
if (com.fr.third.javassist.bytecode.analysis.Util.isJumpInstruction(opcode)) {
int target = com.fr.third.javassist.bytecode.analysis.Util.getJumpTarget(pos, iter);
if (opcode == JSR || opcode == JSR_W) {
com.fr.third.javassist.bytecode.analysis.Subroutine s = (com.fr.third.javassist.bytecode.analysis.Subroutine) subTable.get(new Integer(target));
if (s == null) {
s = new com.fr.third.javassist.bytecode.analysis.Subroutine(target, pos);
subTable.put(new Integer(target), s);
scan(target, iter, s);
} else {
s.addCaller(pos);
}
} else {
scan(target, iter, sub);
// GOTO ends current code flow
if (Util.isGoto(opcode))
return false;
}
}
return true;
}
private void scanLookupSwitch(int pos, CodeIterator iter, com.fr.third.javassist.bytecode.analysis.Subroutine sub) throws BadBytecode {
int index = (pos & ~3) + 4;
// default
scan(pos + iter.s32bitAt(index), iter, sub);
int npairs = iter.s32bitAt(index += 4);
int end = npairs * 8 + (index += 4);
// skip "match"
for (index += 4; index < end; index += 8) {
int target = iter.s32bitAt(index) + pos;
scan(target, iter, sub);
}
}
private void scanTableSwitch(int pos, CodeIterator iter, Subroutine sub) throws BadBytecode {
// Skip 4 byte alignment padding
int index = (pos & ~3) + 4;
// default
scan(pos + iter.s32bitAt(index), iter, sub);
int low = iter.s32bitAt(index += 4);
int high = iter.s32bitAt(index += 4);
int end = (high - low + 1) * 4 + (index += 4);
// Offset table
for (; index < end; index += 4) {
int target = iter.s32bitAt(index) + pos;
scan(target, iter, sub);
}
}
}

593
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Type.java

@ -1,593 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.NotFoundException;
/**
* Represents a JVM type in data-flow analysis. This abstraction is necessary since
* a JVM type not only includes all normal Java types, but also a few special types
* that are used by the JVM internally. See the static field types on this class for
* more info on these special types.
*
* All primitive and special types reuse the same instance, so identity comparison can
* be used when examining them. Normal java types must use {@link #equals(Object)} to
* compare type instances.
*
* In most cases, applications which consume this API, only need to call {@link #getCtClass()}
* to obtain the needed type information.
*
* @author Jason T. Greene
*/
public class Type {
private final CtClass clazz;
private final boolean special;
private static final Map prims = new IdentityHashMap();
/** Represents the double primitive type */
public static final Type DOUBLE = new Type(CtClass.doubleType);
/** Represents the boolean primitive type */
public static final Type BOOLEAN = new Type(CtClass.booleanType);
/** Represents the long primitive type */
public static final Type LONG = new Type(CtClass.longType);
/** Represents the char primitive type */
public static final Type CHAR = new Type(CtClass.charType);
/** Represents the byte primitive type */
public static final Type BYTE = new Type(CtClass.byteType);
/** Represents the short primitive type */
public static final Type SHORT = new Type(CtClass.shortType);
/** Represents the integer primitive type */
public static final Type INTEGER = new Type(CtClass.intType);
/** Represents the float primitive type */
public static final Type FLOAT = new Type(CtClass.floatType);
/** Represents the void primitive type */
public static final Type VOID = new Type(CtClass.voidType);
/**
* Represents an unknown, or null type. This occurs when aconst_null is used.
* It is important not to treat this type as java.lang.Object, since a null can
* be assigned to any reference type. The analyzer will replace these with
* an actual known type if it can be determined by a merged path with known type
* information. If this type is encountered on a frame then it is guaranteed to
* be null, and the type information is simply not available. Any attempts to
* infer the type, without further information from the compiler would be a guess.
*/
public static final Type UNINIT = new Type(null);
/**
* Represents an internal JVM return address, which is used by the RET
* instruction to return to a JSR that invoked the subroutine.
*/
public static final Type RETURN_ADDRESS = new Type(null, true);
/** A placeholder used by the analyzer for the second word position of a double-word type */
public static final Type TOP = new Type(null, true);
/**
* Represents a non-accessible value. Code cannot access the value this type
* represents. It occurs when bytecode reuses a local variable table
* position with non-mergable types. An example would be compiled code which
* uses the same position for a primitive type in one branch, and a reference type
* in another branch.
*/
public static final Type BOGUS = new Type(null, true);
/** Represents the java.lang.Object reference type */
public static final Type OBJECT = lookupType("java.lang.Object");
/** Represents the java.io.Serializable reference type */
public static final Type SERIALIZABLE = lookupType("java.io.Serializable");
/** Represents the java.lang.Coneable reference type */
public static final Type CLONEABLE = lookupType("java.lang.Cloneable");
/** Represents the java.lang.Throwable reference type */
public static final Type THROWABLE = lookupType("java.lang.Throwable");
static {
prims.put(CtClass.doubleType, DOUBLE);
prims.put(CtClass.longType, LONG);
prims.put(CtClass.charType, CHAR);
prims.put(CtClass.shortType, SHORT);
prims.put(CtClass.intType, INTEGER);
prims.put(CtClass.floatType, FLOAT);
prims.put(CtClass.byteType, BYTE);
prims.put(CtClass.booleanType, BOOLEAN);
prims.put(CtClass.voidType, VOID);
}
/**
* Obtain the Type for a given class. If the class is a primitive,
* the the unique type instance for the primitive will be returned.
* Otherwise a new Type instance representing the class is returned.
*
* @param clazz The java class
* @return a type instance for this class
*/
public static Type get(CtClass clazz) {
Type type = (Type)prims.get(clazz);
return type != null ? type : new Type(clazz);
}
private static Type lookupType(String name) {
try {
return new Type(ClassPool.getDefault().get(name));
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
}
Type(CtClass clazz) {
this(clazz, false);
}
private Type(CtClass clazz, boolean special) {
this.clazz = clazz;
this.special = special;
}
// Used to indicate a merge internally triggered a change
boolean popChanged() {
return false;
}
/**
* Gets the word size of this type. Double-word types, such as long and double
* will occupy two positions on the local variable table or stack.
*
* @return the number of words needed to hold this type
*/
public int getSize() {
return clazz == CtClass.doubleType || clazz == CtClass.longType || this == TOP ? 2 : 1;
}
/**
* Returns the class this type represents. If the type is special, null will be returned.
*
* @return the class for this type, or null if special
*/
public CtClass getCtClass() {
return clazz;
}
/**
* Returns whether or not this type is a normal java reference, i.e. it is or extends java.lang.Object.
*
* @return true if a java reference, false if a primitive or special
*/
public boolean isReference() {
return !special && (clazz == null || !clazz.isPrimitive());
}
/**
* Returns whether or not the type is special. A special type is one that is either used
* for internal tracking, or is only used internally by the JVM.
*
* @return true if special, false if not
*/
public boolean isSpecial() {
return special;
}
/**
* Returns whether or not this type is an array.
*
* @return true if an array, false if not
*/
public boolean isArray() {
return clazz != null && clazz.isArray();
}
/**
* Returns the number of dimensions of this array. If the type is not an
* array zero is returned.
*
* @return zero if not an array, otherwise the number of array dimensions.
*/
public int getDimensions() {
if (!isArray()) return 0;
String name = clazz.getName();
int pos = name.length() - 1;
int count = 0;
while (name.charAt(pos) == ']' ) {
pos -= 2;
count++;
}
return count;
}
/**
* Returns the array component if this type is an array. If the type
* is not an array null is returned.
*
* @return the array component if an array, otherwise null
*/
public Type getComponent() {
if (this.clazz == null || !this.clazz.isArray())
return null;
CtClass component;
try {
component = this.clazz.getComponentType();
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
Type type = (Type)prims.get(component);
return (type != null) ? type : new Type(component);
}
/**
* Determines whether this type is assignable, to the passed type.
* A type is assignable to another if it is either the same type, or
* a sub-type.
*
* @param type the type to test assignability to
* @return true if this is assignable to type, otherwise false
*/
public boolean isAssignableFrom(Type type) {
if (this == type)
return true;
if ((type == UNINIT && isReference()) || this == UNINIT && type.isReference())
return true;
if (type instanceof MultiType)
return ((MultiType)type).isAssignableTo(this);
if (type instanceof MultiArrayType)
return ((MultiArrayType)type).isAssignableTo(this);
// Primitives and Special types must be identical
if (clazz == null || clazz.isPrimitive())
return false;
try {
return type.clazz.subtypeOf(clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Finds the common base type, or interface which both this and the specified
* type can be assigned. If there is more than one possible answer, then a {@link MultiType},
* or a {@link MultiArrayType} is returned. Multi-types have special rules,
* and successive merges and assignment tests on them will alter their internal state,
* as well as other multi-types they have been merged with. This method is used by
* the data-flow analyzer to merge the type state from multiple branches.
*
* @param type the type to merge with
* @return the merged type
*/
public Type merge(Type type) {
if (type == this)
return this;
if (type == null)
return this;
if (type == Type.UNINIT)
return this;
if (this == Type.UNINIT)
return type;
// Unequal primitives and special types can not be merged
if (! type.isReference() || ! this.isReference())
return BOGUS;
// Centralize merging of multi-interface types
if (type instanceof MultiType)
return type.merge(this);
if (type.isArray() && this.isArray())
return mergeArray(type);
try {
return mergeClasses(type);
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
}
Type getRootComponent(Type type) {
while (type.isArray())
type = type.getComponent();
return type;
}
private Type createArray(Type rootComponent, int dims) {
if (rootComponent instanceof MultiType)
return new MultiArrayType((MultiType) rootComponent, dims);
String name = arrayName(rootComponent.clazz.getName(), dims);
Type type;
try {
type = Type.get(getClassPool(rootComponent).get(name));
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
return type;
}
String arrayName(String component, int dims) {
// Using char[] since we have no StringBuilder in JDK4, and StringBuffer is slow.
// Although, this is more efficient even if we did have one.
int i = component.length();
int size = i + dims * 2;
char[] string = new char[size];
component.getChars(0, i, string, 0);
while (i < size) {
string[i++] = '[';
string[i++] = ']';
}
component = new String(string);
return component;
}
private ClassPool getClassPool(Type rootComponent) {
ClassPool pool = rootComponent.clazz.getClassPool();
return pool != null ? pool : ClassPool.getDefault();
}
private Type mergeArray(Type type) {
Type typeRoot = getRootComponent(type);
Type thisRoot = getRootComponent(this);
int typeDims = type.getDimensions();
int thisDims = this.getDimensions();
// Array commponents can be merged when the dimensions are equal
if (typeDims == thisDims) {
Type mergedComponent = thisRoot.merge(typeRoot);
// If the components can not be merged (a primitive component mixed with a different type)
// then Object is the common type.
if (mergedComponent == Type.BOGUS)
return Type.OBJECT;
return createArray(mergedComponent, thisDims);
}
Type targetRoot;
int targetDims;
if (typeDims < thisDims) {
targetRoot = typeRoot;
targetDims = typeDims;
} else {
targetRoot = thisRoot;
targetDims = thisDims;
}
// Special case, arrays are cloneable and serializable, so prefer them when dimensions differ
if (eq(CLONEABLE.clazz, targetRoot.clazz) || eq(SERIALIZABLE.clazz, targetRoot.clazz))
return createArray(targetRoot, targetDims);
return createArray(OBJECT, targetDims);
}
private static CtClass findCommonSuperClass(CtClass one, CtClass two) throws NotFoundException {
CtClass deep = one;
CtClass shallow = two;
CtClass backupShallow = shallow;
CtClass backupDeep = deep;
// Phase 1 - Find the deepest hierarchy, set deep and shallow correctly
for (;;) {
// In case we get lucky, and find a match early
if (eq(deep, shallow) && deep.getSuperclass() != null)
return deep;
CtClass deepSuper = deep.getSuperclass();
CtClass shallowSuper = shallow.getSuperclass();
if (shallowSuper == null) {
// right, now reset shallow
shallow = backupShallow;
break;
}
if (deepSuper == null) {
// wrong, swap them, since deep is now useless, its our tmp before we swap it
deep = backupDeep;
backupDeep = backupShallow;
backupShallow = deep;
deep = shallow;
shallow = backupShallow;
break;
}
deep = deepSuper;
shallow = shallowSuper;
}
// Phase 2 - Move deepBackup up by (deep end - deep)
for (;;) {
deep = deep.getSuperclass();
if (deep == null)
break;
backupDeep = backupDeep.getSuperclass();
}
deep = backupDeep;
// Phase 3 - The hierarchy positions are now aligned
// The common super class is easy to find now
while (!eq(deep, shallow)) {
deep = deep.getSuperclass();
shallow = shallow.getSuperclass();
}
return deep;
}
private Type mergeClasses(Type type) throws NotFoundException {
CtClass superClass = findCommonSuperClass(this.clazz, type.clazz);
// If its Object, then try and find a common interface(s)
if (superClass.getSuperclass() == null) {
Map interfaces = findCommonInterfaces(type);
if (interfaces.size() == 1)
return new Type((CtClass) interfaces.values().iterator().next());
if (interfaces.size() > 1)
return new MultiType(interfaces);
// Only Object is in common
return new Type(superClass);
}
// Check for a common interface that is not on the found supertype
Map commonDeclared = findExclusiveDeclaredInterfaces(type, superClass);
if (commonDeclared.size() > 0) {
return new MultiType(commonDeclared, new Type(superClass));
}
return new Type(superClass);
}
private Map findCommonInterfaces(Type type) {
Map typeMap = getAllInterfaces(type.clazz, null);
Map thisMap = getAllInterfaces(this.clazz, null);
return findCommonInterfaces(typeMap, thisMap);
}
private Map findExclusiveDeclaredInterfaces(Type type, CtClass exclude) {
Map typeMap = getDeclaredInterfaces(type.clazz, null);
Map thisMap = getDeclaredInterfaces(this.clazz, null);
Map excludeMap = getAllInterfaces(exclude, null);
Iterator i = excludeMap.keySet().iterator();
while (i.hasNext()) {
Object intf = i.next();
typeMap.remove(intf);
thisMap.remove(intf);
}
return findCommonInterfaces(typeMap, thisMap);
}
Map findCommonInterfaces(Map typeMap, Map alterMap) {
Iterator i = alterMap.keySet().iterator();
while (i.hasNext()) {
if (! typeMap.containsKey(i.next()))
i.remove();
}
// Reduce to subinterfaces
// This does not need to be recursive since we make a copy,
// and that copy contains all super types for the whole hierarchy
i = new ArrayList(alterMap.values()).iterator();
while (i.hasNext()) {
CtClass intf = (CtClass) i.next();
CtClass[] interfaces;
try {
interfaces = intf.getInterfaces();
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
for (int c = 0; c < interfaces.length; c++)
alterMap.remove(interfaces[c].getName());
}
return alterMap;
}
Map getAllInterfaces(CtClass clazz, Map map) {
if (map == null)
map = new HashMap();
if (clazz.isInterface())
map.put(clazz.getName(), clazz);
do {
try {
CtClass[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
CtClass intf = interfaces[i];
map.put(intf.getName(), intf);
getAllInterfaces(intf, map);
}
clazz = clazz.getSuperclass();
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
} while (clazz != null);
return map;
}
Map getDeclaredInterfaces(CtClass clazz, Map map) {
if (map == null)
map = new HashMap();
if (clazz.isInterface())
map.put(clazz.getName(), clazz);
CtClass[] interfaces;
try {
interfaces = clazz.getInterfaces();
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
for (int i = 0; i < interfaces.length; i++) {
CtClass intf = interfaces[i];
map.put(intf.getName(), intf);
getDeclaredInterfaces(intf, map);
}
return map;
}
public boolean equals(Object o) {
if (! (o instanceof Type))
return false;
return o.getClass() == getClass() && eq(clazz, ((Type)o).clazz);
}
static boolean eq(CtClass one, CtClass two) {
return one == two || (one != null && two != null && one.getName().equals(two.getName()));
}
public String toString() {
if (this == BOGUS)
return "BOGUS";
if (this == UNINIT)
return "UNINIT";
if (this == RETURN_ADDRESS)
return "RETURN ADDRESS";
if (this == TOP)
return "TOP";
return clazz == null ? "null" : clazz.getName();
}
}

48
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/Util.java

@ -1,48 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.analysis;
import com.fr.third.javassist.bytecode.CodeIterator;
import com.fr.third.javassist.bytecode.Opcode;
/**
* A set of common utility methods.
*
* @author Jason T. Greene
*/
public class Util implements Opcode {
public static int getJumpTarget(int pos, CodeIterator iter) {
int opcode = iter.byteAt(pos);
pos += (opcode == JSR_W || opcode == GOTO_W) ? iter.s32bitAt(pos + 1) : iter.s16bitAt(pos + 1);
return pos;
}
public static boolean isJumpInstruction(int opcode) {
return (opcode >= IFEQ && opcode <= JSR) || opcode == IFNULL || opcode == IFNONNULL || opcode == JSR_W || opcode == GOTO_W;
}
public static boolean isGoto(int opcode) {
return opcode == GOTO || opcode == GOTO_W;
}
public static boolean isJsr(int opcode) {
return opcode == JSR || opcode == JSR_W;
}
public static boolean isReturn(int opcode) {
return (opcode >= IRETURN && opcode <= RETURN);
}
}

20
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/analysis/package.html

@ -1,20 +0,0 @@
<html>
<body>
Bytecode Analysis API.
<p>This package provides an API for performing data-flow analysis on a method's bytecode.
This allows the user to determine the type state of the stack and local variable table
at the start of every instruction. In addition this API can be used to validate
bytecode, find dead bytecode, and identify unnecessary checkcasts.
Look at <code>ControlFlow</code> class first for details.
<p>The users of this package must know the specifications of
class file and Java bytecode. For more details, read this book:
<ul>Tim Lindholm and Frank Yellin,
"The Java Virtual Machine Specification 2nd Ed.",
Addison-Wesley, 1999.
</ul>
</body>
</html>

351
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/Annotation.java

@ -1,351 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.bytecode.AnnotationDefaultAttribute;
import com.fr.third.javassist.bytecode.AnnotationsAttribute;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.bytecode.Descriptor;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.CtMethod;
import com.fr.third.javassist.NotFoundException;
import com.fr.third.javassist.bytecode.ParameterAnnotationsAttribute;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.Iterator;
/**
* The <code>annotation</code> structure.
*
* <p>An instance of this class is returned by
* <code>getAnnotations()</code> in <code>AnnotationsAttribute</code>
* or in <code>ParameterAnnotationsAttribute</code>.
*
* @see AnnotationsAttribute#getAnnotations()
* @see ParameterAnnotationsAttribute#getAnnotations()
* @see MemberValue
* @see MemberValueVisitor
* @see AnnotationsWriter
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
* @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
*/
public class Annotation {
static class Pair {
int name;
MemberValue value;
}
ConstPool pool;
int typeIndex;
LinkedHashMap members; // this sould be LinkedHashMap
// but it is not supported by JDK 1.3.
/**
* Constructs an annotation including no members. A member can be
* later added to the created annotation by <code>addMemberValue()</code>.
*
* @param type the index into the constant pool table.
* the entry at that index must be the
* <code>CONSTANT_Utf8_Info</code> structure
* repreenting the name of the annotation interface type.
* @param cp the constant pool table.
*
* @see #addMemberValue(String, MemberValue)
*/
public Annotation(int type, ConstPool cp) {
pool = cp;
typeIndex = type;
members = null;
}
/**
* Constructs an annotation including no members. A member can be
* later added to the created annotation by <code>addMemberValue()</code>.
*
* @param typeName the name of the annotation interface type.
* @param cp the constant pool table.
*
* @see #addMemberValue(String, MemberValue)
*/
public Annotation(String typeName, ConstPool cp) {
this(cp.addUtf8Info(Descriptor.of(typeName)), cp);
}
/**
* Constructs an annotation that can be accessed through the interface
* represented by <code>clazz</code>. The values of the members are
* not specified.
*
* @param cp the constant pool table.
* @param clazz the interface.
* @throws NotFoundException when the clazz is not found
*/
public Annotation(ConstPool cp, CtClass clazz)
throws NotFoundException
{
// todo Enums are not supported right now.
this(cp.addUtf8Info(Descriptor.of(clazz.getName())), cp);
if (!clazz.isInterface())
throw new RuntimeException(
"Only interfaces are allowed for Annotation creation.");
CtMethod methods[] = clazz.getDeclaredMethods();
if (methods.length > 0) {
members = new LinkedHashMap();
}
for (int i = 0; i < methods.length; i++) {
CtClass returnType = methods[i].getReturnType();
addMemberValue(methods[i].getName(),
createMemberValue(cp, returnType));
}
}
/**
* Makes an instance of <code>MemberValue</code>.
*
* @param cp the constant pool table.
* @param type the type of the member.
* @return the member value
* @throws NotFoundException when the type is not found
*/
public static MemberValue createMemberValue(ConstPool cp, CtClass type)
throws NotFoundException
{
if (type == CtClass.booleanType)
return new BooleanMemberValue(cp);
else if (type == CtClass.byteType)
return new ByteMemberValue(cp);
else if (type == CtClass.charType)
return new CharMemberValue(cp);
else if (type == CtClass.shortType)
return new ShortMemberValue(cp);
else if (type == CtClass.intType)
return new IntegerMemberValue(cp);
else if (type == CtClass.longType)
return new LongMemberValue(cp);
else if (type == CtClass.floatType)
return new FloatMemberValue(cp);
else if (type == CtClass.doubleType)
return new DoubleMemberValue(cp);
else if (type.getName().equals("java.lang.Class"))
return new ClassMemberValue(cp);
else if (type.getName().equals("java.lang.String"))
return new StringMemberValue(cp);
else if (type.isArray()) {
CtClass arrayType = type.getComponentType();
MemberValue member = createMemberValue(cp, arrayType);
return new ArrayMemberValue(member, cp);
}
else if (type.isInterface()) {
Annotation info = new Annotation(cp, type);
return new AnnotationMemberValue(info, cp);
}
else {
// treat as enum. I know this is not typed,
// but JBoss has an Annotation Compiler for JDK 1.4
// and I want it to work with that. - Bill Burke
EnumMemberValue emv = new EnumMemberValue(cp);
emv.setType(type.getName());
return emv;
}
}
/**
* Adds a new member.
*
* @param nameIndex the index into the constant pool table.
* The entry at that index must be
* a <code>CONSTANT_Utf8_info</code> structure.
* structure representing the member name.
* @param value the member value.
*/
public void addMemberValue(int nameIndex, MemberValue value) {
Pair p = new Pair();
p.name = nameIndex;
p.value = value;
addMemberValue(p);
}
/**
* Adds a new member.
*
* @param name the member name.
* @param value the member value.
*/
public void addMemberValue(String name, MemberValue value) {
Pair p = new Pair();
p.name = pool.addUtf8Info(name);
p.value = value;
if (members == null)
members = new LinkedHashMap();
members.put(name, p);
}
private void addMemberValue(Pair pair) {
String name = pool.getUtf8Info(pair.name);
if (members == null)
members = new LinkedHashMap();
members.put(name, pair);
}
/**
* Returns a string representation of the annotation.
*/
public String toString() {
StringBuffer buf = new StringBuffer("@");
buf.append(getTypeName());
if (members != null) {
buf.append("(");
Iterator mit = members.keySet().iterator();
while (mit.hasNext()) {
String name = (String)mit.next();
buf.append(name).append("=").append(getMemberValue(name));
if (mit.hasNext())
buf.append(", ");
}
buf.append(")");
}
return buf.toString();
}
/**
* Obtains the name of the annotation type.
*
* @return the type name
*/
public String getTypeName() {
return Descriptor.toClassName(pool.getUtf8Info(typeIndex));
}
/**
* Obtains all the member names.
*
* @return null if no members are defined.
*/
public Set getMemberNames() {
if (members == null)
return null;
else
return members.keySet();
}
/**
* Obtains the member value with the given name.
*
* <p>If this annotation does not have a value for the
* specified member,
* this method returns null. It does not return a
* <code>MemberValue</code> with the default value.
* The default value can be obtained from the annotation type.
*
* @param name the member name
* @return null if the member cannot be found or if the value is
* the default value.
*
* @see AnnotationDefaultAttribute
*/
public MemberValue getMemberValue(String name) {
if (members == null)
return null;
else {
Pair p = (Pair)members.get(name);
if (p == null)
return null;
else
return p.value;
}
}
/**
* Constructs an annotation-type object representing this annotation.
* For example, if this annotation represents <code>@Author</code>,
* this method returns an <code>Author</code> object.
*
* @param cl class loader for loading an annotation type.
* @param cp class pool for obtaining class files.
* @return the annotation
* @throws ClassNotFoundException if the class cannot found.
* @throws NoSuchClassError if the class linkage fails.
*/
public Object toAnnotationType(ClassLoader cl, ClassPool cp)
throws ClassNotFoundException, NoSuchClassError
{
return AnnotationImpl.make(cl,
MemberValue.loadClass(cl, getTypeName()),
cp, this);
}
/**
* Writes this annotation.
*
* @param writer the output.
* @throws IOException for an error during the write
*/
public void write(AnnotationsWriter writer) throws IOException {
String typeName = pool.getUtf8Info(typeIndex);
if (members == null) {
writer.annotation(typeName, 0);
return;
}
writer.annotation(typeName, members.size());
Iterator it = members.values().iterator();
while (it.hasNext()) {
Pair pair = (Pair)it.next();
writer.memberValuePair(pair.name);
pair.value.write(writer);
}
}
/**
* Returns true if the given object represents the same annotation
* as this object. The equality test checks the member values.
*/
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null || obj instanceof Annotation == false)
return false;
Annotation other = (Annotation) obj;
if (getTypeName().equals(other.getTypeName()) == false)
return false;
LinkedHashMap otherMembers = other.members;
if (members == otherMembers)
return true;
else if (members == null)
return otherMembers == null;
else
if (otherMembers == null)
return false;
else
return members.equals(otherMembers);
}
}

305
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/AnnotationImpl.java

@ -1,305 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.CtClass;
import com.fr.third.javassist.NotFoundException;
import com.fr.third.javassist.bytecode.AnnotationDefaultAttribute;
import com.fr.third.javassist.bytecode.ClassFile;
import com.fr.third.javassist.bytecode.MethodInfo;
/**
* Internal-use only. This is a helper class internally used for implementing
* <code>toAnnotationType()</code> in <code>Annotation</code>.
*
* @author Shigeru Chiba
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
*/
public class AnnotationImpl implements InvocationHandler {
private static final String JDK_ANNOTATION_CLASS_NAME = "java.lang.annotation.Annotation";
private static Method JDK_ANNOTATION_TYPE_METHOD = null;
private com.fr.third.javassist.bytecode.annotation.Annotation annotation;
private ClassPool pool;
private ClassLoader classLoader;
private transient Class annotationType;
private transient int cachedHashCode = Integer.MIN_VALUE;
static {
// Try to resolve the JDK annotation type method
try {
Class clazz = Class.forName(JDK_ANNOTATION_CLASS_NAME);
JDK_ANNOTATION_TYPE_METHOD = clazz.getMethod("annotationType", (Class[])null);
}
catch (Exception ignored) {
// Probably not JDK5+
}
}
/**
* Constructs an annotation object.
*
* @param cl class loader for obtaining annotation types.
* @param clazz the annotation type.
* @param cp class pool for containing an annotation
* type (or null).
* @param anon the annotation.
* @return the annotation
*/
public static Object make(ClassLoader cl, Class clazz, ClassPool cp,
com.fr.third.javassist.bytecode.annotation.Annotation anon) {
AnnotationImpl handler = new AnnotationImpl(anon, cp, cl);
return Proxy.newProxyInstance(cl, new Class[] { clazz }, handler);
}
private AnnotationImpl(com.fr.third.javassist.bytecode.annotation.Annotation a, ClassPool cp, ClassLoader loader) {
annotation = a;
pool = cp;
classLoader = loader;
}
/**
* Obtains the name of the annotation type.
*
* @return the type name
*/
public String getTypeName() {
return annotation.getTypeName();
}
/**
* Get the annotation type
*
* @return the annotation class
* @throws NoClassDefFoundError when the class could not loaded
*/
private Class getAnnotationType() {
if (annotationType == null) {
String typeName = annotation.getTypeName();
try {
annotationType = classLoader.loadClass(typeName);
}
catch (ClassNotFoundException e) {
NoClassDefFoundError error = new NoClassDefFoundError("Error loading annotation class: " + typeName);
error.setStackTrace(e.getStackTrace());
throw error;
}
}
return annotationType;
}
/**
* Obtains the internal data structure representing the annotation.
*
* @return the annotation
*/
public Annotation getAnnotation() {
return annotation;
}
/**
* Executes a method invocation on a proxy instance.
* The implementations of <code>toString()</code>, <code>equals()</code>,
* and <code>hashCode()</code> are directly supplied by the
* <code>AnnotationImpl</code>. The <code>annotationType()</code> method
* is also available on the proxy instance.
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
String name = method.getName();
if (Object.class == method.getDeclaringClass()) {
if ("equals".equals(name)) {
Object obj = args[0];
return new Boolean(checkEquals(obj));
}
else if ("toString".equals(name))
return annotation.toString();
else if ("hashCode".equals(name))
return new Integer(hashCode());
}
else if ("annotationType".equals(name)
&& method.getParameterTypes().length == 0)
return getAnnotationType();
com.fr.third.javassist.bytecode.annotation.MemberValue mv = annotation.getMemberValue(name);
if (mv == null)
return getDefault(name, method);
else
return mv.getValue(classLoader, pool, method);
}
private Object getDefault(String name, Method method)
throws ClassNotFoundException, RuntimeException
{
String classname = annotation.getTypeName();
if (pool != null) {
try {
CtClass cc = pool.get(classname);
ClassFile cf = cc.getClassFile2();
MethodInfo minfo = cf.getMethod(name);
if (minfo != null) {
AnnotationDefaultAttribute ainfo
= (AnnotationDefaultAttribute)
minfo.getAttribute(AnnotationDefaultAttribute.tag);
if (ainfo != null) {
com.fr.third.javassist.bytecode.annotation.MemberValue mv = ainfo.getDefaultValue();
return mv.getValue(classLoader, pool, method);
}
}
}
catch (NotFoundException e) {
throw new RuntimeException("cannot find a class file: "
+ classname);
}
}
throw new RuntimeException("no default value: " + classname + "."
+ name + "()");
}
/**
* Returns a hash code value for this object.
*/
public int hashCode() {
if (cachedHashCode == Integer.MIN_VALUE) {
int hashCode = 0;
// Load the annotation class
getAnnotationType();
Method[] methods = annotationType.getDeclaredMethods();
for (int i = 0; i < methods.length; ++ i) {
String name = methods[i].getName();
int valueHashCode = 0;
// Get the value
com.fr.third.javassist.bytecode.annotation.MemberValue mv = annotation.getMemberValue(name);
Object value = null;
try {
if (mv != null)
value = mv.getValue(classLoader, pool, methods[i]);
if (value == null)
value = getDefault(name, methods[i]);
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException("Error retrieving value " + name + " for annotation " + annotation.getTypeName(), e);
}
// Calculate the hash code
if (value != null) {
if (value.getClass().isArray())
valueHashCode = arrayHashCode(value);
else
valueHashCode = value.hashCode();
}
hashCode += 127 * name.hashCode() ^ valueHashCode;
}
cachedHashCode = hashCode;
}
return cachedHashCode;
}
/**
* Check that another annotation equals ourselves.
*
* @param obj the other annotation
* @return the true when equals false otherwise
* @throws Exception for any problem
*/
private boolean checkEquals(Object obj) throws Exception {
if (obj == null)
return false;
// Optimization when the other is one of ourselves
if (obj instanceof Proxy) {
InvocationHandler ih = Proxy.getInvocationHandler(obj);
if (ih instanceof AnnotationImpl) {
AnnotationImpl other = (AnnotationImpl) ih;
return annotation.equals(other.annotation);
}
}
Class otherAnnotationType = (Class) JDK_ANNOTATION_TYPE_METHOD.invoke(obj, (Object[])null);
if (getAnnotationType().equals(otherAnnotationType) == false)
return false;
Method[] methods = annotationType.getDeclaredMethods();
for (int i = 0; i < methods.length; ++ i) {
String name = methods[i].getName();
// Get the value
MemberValue mv = annotation.getMemberValue(name);
Object value = null;
Object otherValue = null;
try {
if (mv != null)
value = mv.getValue(classLoader, pool, methods[i]);
if (value == null)
value = getDefault(name, methods[i]);
otherValue = methods[i].invoke(obj, (Object[])null);
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException("Error retrieving value " + name + " for annotation " + annotation.getTypeName(), e);
}
if (value == null && otherValue != null)
return false;
if (value != null && value.equals(otherValue) == false)
return false;
}
return true;
}
/**
* Calculates the hashCode of an array using the same
* algorithm as java.util.Arrays.hashCode()
*
* @param object the object
* @return the hashCode
*/
private static int arrayHashCode(Object object)
{
if (object == null)
return 0;
int result = 1;
Object[] array = (Object[]) object;
for (int i = 0; i < array.length; ++i) {
int elementHashCode = 0;
if (array[i] != null)
elementHashCode = array[i].hashCode();
result = 31 * result + elementHashCode;
}
return result;
}
}

97
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/AnnotationMemberValue.java

@ -1,97 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.ConstPool;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Nested annotation.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
public class AnnotationMemberValue extends MemberValue {
com.fr.third.javassist.bytecode.annotation.Annotation value;
/**
* Constructs an annotation member. The initial value is not specified.
*/
public AnnotationMemberValue(ConstPool cp) {
this(null, cp);
}
/**
* Constructs an annotation member. The initial value is specified by
* the first parameter.
*/
public AnnotationMemberValue(com.fr.third.javassist.bytecode.annotation.Annotation a, ConstPool cp) {
super('@', cp);
value = a;
}
Object getValue(ClassLoader cl, ClassPool cp, Method m)
throws ClassNotFoundException
{
return AnnotationImpl.make(cl, getType(cl), cp, value);
}
Class getType(ClassLoader cl) throws ClassNotFoundException {
if (value == null)
throw new ClassNotFoundException("no type specified");
else
return loadClass(cl, value.getTypeName());
}
/**
* Obtains the value.
*/
public com.fr.third.javassist.bytecode.annotation.Annotation getValue() {
return value;
}
/**
* Sets the value of this member.
*/
public void setValue(Annotation newValue) {
value = newValue;
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
return value.toString();
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
writer.annotationValue();
value.write(writer);
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitAnnotationMemberValue(this);
}
}

356
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/AnnotationsWriter.java

@ -1,356 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import java.io.*;
import com.fr.third.javassist.bytecode.AnnotationsAttribute;
import com.fr.third.javassist.bytecode.ByteArray;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.bytecode.ParameterAnnotationsAttribute;
/**
* A convenience class for constructing a
* <code>..Annotations_attribute</code>.
* See the source code of the <code>AnnotationsAttribute.Copier</code> class.
*
* <p>The following code snippet is an example of use of this class:
*
* <ul><pre>
* ConstPool pool = ...;
* output = new ByteArrayOutputStream();
* writer = new AnnotationsWriter(output, pool);
*
* writer.numAnnotations(1);
* writer.annotation("Author", 2);
* writer.memberValuePair("name");
* writer.constValueIndex("chiba");
* writer.memberValuePair("address");
* writer.constValueIndex("tokyo");
*
* writer.close();
* byte[] attribute_info = output.toByteArray();
* AnnotationsAttribute anno
* = new AnnotationsAttribute(pool, AnnotationsAttribute.visibleTag,
* attribute_info);
* </pre></ul>
*
* <p>The code snippet above generates the annotation attribute
* corresponding to this annotation:
*
* <ul><pre>
* &nbsp;@Author(name = "chiba", address = "tokyo")
* </pre></ul>
*
* @see AnnotationsAttribute
* @see ParameterAnnotationsAttribute
*/
public class AnnotationsWriter {
private OutputStream output;
private ConstPool pool;
/**
* Constructs with the given output stream.
*
* @param os the output stream.
* @param cp the constant pool.
*/
public AnnotationsWriter(OutputStream os, ConstPool cp) {
output = os;
pool = cp;
}
/**
* Obtains the constant pool given to the constructor.
*/
public ConstPool getConstPool() {
return pool;
}
/**
* Closes the output stream.
*
*/
public void close() throws IOException {
output.close();
}
/**
* Writes <code>num_parameters</code> in
* <code>Runtime(In)VisibleParameterAnnotations_attribute</code>.
* This method must be followed by <code>num</code> calls to
* <code>numAnnotations()</code>.
*/
public void numParameters(int num) throws IOException {
output.write(num);
}
/**
* Writes <code>num_annotations</code> in
* <code>Runtime(In)VisibleAnnotations_attribute</code>.
* This method must be followed by <code>num</code> calls to
* <code>annotation()</code>.
*/
public void numAnnotations(int num) throws IOException {
write16bit(num);
}
/**
* Writes <code>annotation</code>.
* This method must be followed by <code>numMemberValuePairs</code>
* calls to <code>memberValuePair()</code>.
*
* @param type the annotation interface name.
* @param numMemberValuePairs <code>num_member_value_pairs</code>
* in <code>annotation</code>.
*/
public void annotation(String type, int numMemberValuePairs)
throws IOException
{
annotation(pool.addUtf8Info(type), numMemberValuePairs);
}
/**
* Writes <code>annotation</code>.
* This method must be followed by <code>numMemberValuePairs</code>
* calls to <code>memberValuePair()</code>.
*
* @param typeIndex <code>type_index</code> in <code>annotation</code>.
* @param numMemberValuePairs <code>num_member_value_pairs</code>
* in <code>annotation</code>.
*/
public void annotation(int typeIndex, int numMemberValuePairs)
throws IOException
{
write16bit(typeIndex);
write16bit(numMemberValuePairs);
}
/**
* Writes an element of a <code>member_value_pairs</code> array
* in <code>annotation</code>.
* This method must be followed by a
* call to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
* etc.
*
* @param memberName the name of the annotation type member.
*/
public void memberValuePair(String memberName) throws IOException {
memberValuePair(pool.addUtf8Info(memberName));
}
/**
* Writes an element of a <code>member_value_pairs</code> array
* in <code>annotation</code>.
* This method must be followed by a
* call to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
* etc.
*
* @param memberNameIndex <code>member_name_index</code>
* in <code>member_value_pairs</code> array.
*/
public void memberValuePair(int memberNameIndex) throws IOException {
write16bit(memberNameIndex);
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(boolean value) throws IOException {
constValueIndex('Z', pool.addIntegerInfo(value ? 1 : 0));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(byte value) throws IOException {
constValueIndex('B', pool.addIntegerInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(char value) throws IOException {
constValueIndex('C', pool.addIntegerInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(short value) throws IOException {
constValueIndex('S', pool.addIntegerInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(int value) throws IOException {
constValueIndex('I', pool.addIntegerInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(long value) throws IOException {
constValueIndex('J', pool.addLongInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(float value) throws IOException {
constValueIndex('F', pool.addFloatInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(double value) throws IOException {
constValueIndex('D', pool.addDoubleInfo(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param value the constant value.
*/
public void constValueIndex(String value) throws IOException {
constValueIndex('s', pool.addUtf8Info(value));
}
/**
* Writes <code>tag</code> and <code>const_value_index</code>
* in <code>member_value</code>.
*
* @param tag <code>tag</code> in <code>member_value</code>.
* @param index <code>const_value_index</code>
* in <code>member_value</code>.
*/
public void constValueIndex(int tag, int index)
throws IOException
{
output.write(tag);
write16bit(index);
}
/**
* Writes <code>tag</code> and <code>enum_const_value</code>
* in <code>member_value</code>.
*
* @param typeName the type name of the enum constant.
* @param constName the simple name of the enum constant.
*/
public void enumConstValue(String typeName, String constName)
throws IOException
{
enumConstValue(pool.addUtf8Info(typeName),
pool.addUtf8Info(constName));
}
/**
* Writes <code>tag</code> and <code>enum_const_value</code>
* in <code>member_value</code>.
*
* @param typeNameIndex <code>type_name_index</code>
* in <code>member_value</code>.
* @param constNameIndex <code>const_name_index</code>
* in <code>member_value</code>.
*/
public void enumConstValue(int typeNameIndex, int constNameIndex)
throws IOException
{
output.write('e');
write16bit(typeNameIndex);
write16bit(constNameIndex);
}
/**
* Writes <code>tag</code> and <code>class_info_index</code>
* in <code>member_value</code>.
*
* @param name the class name.
*/
public void classInfoIndex(String name) throws IOException {
classInfoIndex(pool.addUtf8Info(name));
}
/**
* Writes <code>tag</code> and <code>class_info_index</code>
* in <code>member_value</code>.
*
* @param index <code>class_info_index</code>
*/
public void classInfoIndex(int index) throws IOException {
output.write('c');
write16bit(index);
}
/**
* Writes <code>tag</code> and <code>annotation_value</code>
* in <code>member_value</code>.
* This method must be followed by a call to <code>annotation()</code>.
*/
public void annotationValue() throws IOException {
output.write('@');
}
/**
* Writes <code>tag</code> and <code>array_value</code>
* in <code>member_value</code>.
* This method must be followed by <code>numValues</code> calls
* to <code>constValueIndex()</code>, <code>enumConstValue()</code>,
* etc.
*
* @param numValues <code>num_values</code>
* in <code>array_value</code>.
*/
public void arrayValue(int numValues) throws IOException {
output.write('[');
write16bit(numValues);
}
private void write16bit(int value) throws IOException {
byte[] buf = new byte[2];
ByteArray.write16bit(value, buf, 0);
output.write(buf);
}
}

146
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/ArrayMemberValue.java

@ -1,146 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.ConstPool;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
/**
* Array member.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
public class ArrayMemberValue extends com.fr.third.javassist.bytecode.annotation.MemberValue {
com.fr.third.javassist.bytecode.annotation.MemberValue type;
com.fr.third.javassist.bytecode.annotation.MemberValue[] values;
/**
* Constructs an array. The initial value or type are not specified.
*/
public ArrayMemberValue(ConstPool cp) {
super('[', cp);
type = null;
values = null;
}
/**
* Constructs an array. The initial value is not specified.
*
* @param t the type of the array elements.
*/
public ArrayMemberValue(com.fr.third.javassist.bytecode.annotation.MemberValue t, ConstPool cp) {
super('[', cp);
type = t;
values = null;
}
Object getValue(ClassLoader cl, ClassPool cp, Method method)
throws ClassNotFoundException
{
if (values == null)
throw new ClassNotFoundException(
"no array elements found: " + method.getName());
int size = values.length;
Class clazz;
if (type == null) {
clazz = method.getReturnType().getComponentType();
if (clazz == null || size > 0)
throw new ClassNotFoundException("broken array type: "
+ method.getName());
}
else
clazz = type.getType(cl);
Object a = Array.newInstance(clazz, size);
for (int i = 0; i < size; i++)
Array.set(a, i, values[i].getValue(cl, cp, method));
return a;
}
Class getType(ClassLoader cl) throws ClassNotFoundException {
if (type == null)
throw new ClassNotFoundException("no array type specified");
Object a = Array.newInstance(type.getType(cl), 0);
return a.getClass();
}
/**
* Obtains the type of the elements.
*
* @return null if the type is not specified.
*/
public com.fr.third.javassist.bytecode.annotation.MemberValue getType() {
return type;
}
/**
* Obtains the elements of the array.
*/
public com.fr.third.javassist.bytecode.annotation.MemberValue[] getValue() {
return values;
}
/**
* Sets the elements of the array.
*/
public void setValue(MemberValue[] elements) {
values = elements;
if (elements != null && elements.length > 0)
type = elements[0];
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
StringBuffer buf = new StringBuffer("{");
if (values != null) {
for (int i = 0; i < values.length; i++) {
buf.append(values[i].toString());
if (i + 1 < values.length)
buf.append(", ");
}
}
buf.append("}");
return buf.toString();
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
int num = values.length;
writer.arrayValue(num);
for (int i = 0; i < num; ++i)
values[i].write(writer);
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitArrayMemberValue(this);
}
}

104
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/BooleanMemberValue.java

@ -1,104 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.ConstPool;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Boolean constant value.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
public class BooleanMemberValue extends MemberValue {
int valueIndex;
/**
* Constructs a boolean constant value. The initial value is specified
* by the constant pool entry at the given index.
*
* @param index the index of a CONSTANT_Integer_info structure.
*/
public BooleanMemberValue(int index, ConstPool cp) {
super('Z', cp);
this.valueIndex = index;
}
/**
* Constructs a boolean constant value.
*
* @param b the initial value.
*/
public BooleanMemberValue(boolean b, ConstPool cp) {
super('Z', cp);
setValue(b);
}
/**
* Constructs a boolean constant value. The initial value is false.
*/
public BooleanMemberValue(ConstPool cp) {
super('Z', cp);
setValue(false);
}
Object getValue(ClassLoader cl, ClassPool cp, Method m) {
return new Boolean(getValue());
}
Class getType(ClassLoader cl) {
return boolean.class;
}
/**
* Obtains the value of the member.
*/
public boolean getValue() {
return cp.getIntegerInfo(valueIndex) != 0;
}
/**
* Sets the value of the member.
*/
public void setValue(boolean newValue) {
valueIndex = cp.addIntegerInfo(newValue ? 1 : 0);
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
return getValue() ? "true" : "false";
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitBooleanMemberValue(this);
}
}

104
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/ByteMemberValue.java

@ -1,104 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.ConstPool;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Byte constant value.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
public class ByteMemberValue extends MemberValue {
int valueIndex;
/**
* Constructs a byte constant value. The initial value is specified
* by the constant pool entry at the given index.
*
* @param index the index of a CONSTANT_Integer_info structure.
*/
public ByteMemberValue(int index, ConstPool cp) {
super('B', cp);
this.valueIndex = index;
}
/**
* Constructs a byte constant value.
*
* @param b the initial value.
*/
public ByteMemberValue(byte b, ConstPool cp) {
super('B', cp);
setValue(b);
}
/**
* Constructs a byte constant value. The initial value is 0.
*/
public ByteMemberValue(ConstPool cp) {
super('B', cp);
setValue((byte)0);
}
Object getValue(ClassLoader cl, ClassPool cp, Method m) {
return new Byte(getValue());
}
Class getType(ClassLoader cl) {
return byte.class;
}
/**
* Obtains the value of the member.
*/
public byte getValue() {
return (byte)cp.getIntegerInfo(valueIndex);
}
/**
* Sets the value of the member.
*/
public void setValue(byte newValue) {
valueIndex = cp.addIntegerInfo(newValue);
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
return Byte.toString(getValue());
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitByteMemberValue(this);
}
}

105
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/CharMemberValue.java

@ -1,105 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.ConstPool;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Char constant value.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
public class CharMemberValue extends MemberValue {
int valueIndex;
/**
* Constructs a char constant value. The initial value is specified
* by the constant pool entry at the given index.
*
* @param index the index of a CONSTANT_Integer_info structure.
*/
public CharMemberValue(int index, ConstPool cp) {
super('C', cp);
this.valueIndex = index;
}
/**
* Constructs a char constant value.
*
* @param c the initial value.
*/
public CharMemberValue(char c, ConstPool cp) {
super('C', cp);
setValue(c);
}
/**
* Constructs a char constant value. The initial value is '\0'.
*/
public CharMemberValue(ConstPool cp) {
super('C', cp);
setValue('\0');
}
Object getValue(ClassLoader cl, ClassPool cp, Method m) {
return new Character(getValue());
}
Class getType(ClassLoader cl) {
return char.class;
}
/**
* Obtains the value of the member.
*/
public char getValue() {
return (char)cp.getIntegerInfo(valueIndex);
}
/**
* Sets the value of the member.
*/
public void setValue(char newValue) {
valueIndex = cp.addIntegerInfo(newValue);
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
return Character.toString(getValue());
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitCharMemberValue(this);
}
}

140
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/ClassMemberValue.java

@ -1,140 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.BadBytecode;
import com.fr.third.javassist.bytecode.ConstPool;
import com.fr.third.javassist.bytecode.Descriptor;
import com.fr.third.javassist.bytecode.SignatureAttribute;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Class value.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
*/
public class ClassMemberValue extends MemberValue {
int valueIndex;
/**
* Constructs a class value. The initial value is specified
* by the constant pool entry at the given index.
*
* @param index the index of a CONSTANT_Utf8_info structure.
*/
public ClassMemberValue(int index, ConstPool cp) {
super('c', cp);
this.valueIndex = index;
}
/**
* Constructs a class value.
*
* @param className the initial value.
*/
public ClassMemberValue(String className, ConstPool cp) {
super('c', cp);
setValue(className);
}
/**
* Constructs a class value.
* The initial value is java.lang.Class.
*/
public ClassMemberValue(ConstPool cp) {
super('c', cp);
setValue("java.lang.Class");
}
Object getValue(ClassLoader cl, ClassPool cp, Method m)
throws ClassNotFoundException {
final String classname = getValue();
if (classname.equals("void"))
return void.class;
else if (classname.equals("int"))
return int.class;
else if (classname.equals("byte"))
return byte.class;
else if (classname.equals("long"))
return long.class;
else if (classname.equals("double"))
return double.class;
else if (classname.equals("float"))
return float.class;
else if (classname.equals("char"))
return char.class;
else if (classname.equals("short"))
return short.class;
else if (classname.equals("boolean"))
return boolean.class;
else
return loadClass(cl, classname);
}
Class getType(ClassLoader cl) throws ClassNotFoundException {
return loadClass(cl, "java.lang.Class");
}
/**
* Obtains the value of the member.
*
* @return fully-qualified class name.
*/
public String getValue() {
String v = cp.getUtf8Info(valueIndex);
try {
return SignatureAttribute.toTypeSignature(v).jvmTypeName();
} catch (BadBytecode e) {
throw new RuntimeException(e);
}
}
/**
* Sets the value of the member.
*
* @param newClassName fully-qualified class name.
*/
public void setValue(String newClassName) {
String setTo = Descriptor.of(newClassName);
valueIndex = cp.addUtf8Info(setTo);
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
return getValue().replace('$', '.') + ".class";
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
writer.classInfoIndex(cp.getUtf8Info(valueIndex));
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitClassMemberValue(this);
}
}

106
fine-javassist/src/main/java/com/fr/third/javassist/bytecode/annotation/DoubleMemberValue.java

@ -1,106 +0,0 @@
/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 2004 Bill Burke. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package com.fr.third.javassist.bytecode.annotation;
import com.fr.third.javassist.ClassPool;
import com.fr.third.javassist.bytecode.ConstPool;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Double floating-point number constant value.
*
* @author <a href="mailto:bill@jboss.org">Bill Burke</a>
* @author Shigeru Chiba
* @version $Revision: 1.7 $
*/
public class DoubleMemberValue extends MemberValue {
int valueIndex;
/**
* Constructs a double constant value. The initial value is specified
* by the constant pool entry at the given index.
*
* @param index the index of a CONSTANT_Double_info structure.
*/
public DoubleMemberValue(int index, ConstPool cp) {
super('D', cp);
this.valueIndex = index;
}
/**
* Constructs a double constant value.
*
* @param d the initial value.
*/
public DoubleMemberValue(double d, ConstPool cp) {
super('D', cp);
setValue(d);
}
/**
* Constructs a double constant value. The initial value is 0.0.
*/
public DoubleMemberValue(ConstPool cp) {
super('D', cp);
setValue(0.0);
}
Object getValue(ClassLoader cl, ClassPool cp, Method m) {
return new Double(getValue());
}
Class getType(ClassLoader cl) {
return double.class;
}
/**
* Obtains the value of the member.
*/
public double getValue() {
return cp.getDoubleInfo(valueIndex);
}
/**
* Sets the value of the member.
*/
public void setValue(double newValue) {
valueIndex = cp.addDoubleInfo(newValue);
}
/**
* Obtains the string representation of this object.
*/
public String toString() {
return Double.toString(getValue());
}
/**
* Writes the value.
*/
public void write(AnnotationsWriter writer) throws IOException {
writer.constValueIndex(getValue());
}
/**
* Accepts a visitor.
*/
public void accept(MemberValueVisitor visitor) {
visitor.visitDoubleMemberValue(this);
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save