javassist.CtClassType Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of driver-cql-shaded Show documentation
Show all versions of driver-cql-shaded Show documentation
A Shaded CQL ActivityType driver for http://nosqlbench.io/
/*
* 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 javassist;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javassist.bytecode.AccessFlag;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.AttributeInfo;
import javassist.bytecode.BadBytecode;
import javassist.bytecode.Bytecode;
import javassist.bytecode.ClassFile;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.CodeIterator;
import javassist.bytecode.ConstPool;
import javassist.bytecode.ConstantAttribute;
import javassist.bytecode.Descriptor;
import javassist.bytecode.EnclosingMethodAttribute;
import javassist.bytecode.FieldInfo;
import javassist.bytecode.InnerClassesAttribute;
import javassist.bytecode.MethodInfo;
import javassist.bytecode.ParameterAnnotationsAttribute;
import javassist.bytecode.SignatureAttribute;
import javassist.bytecode.annotation.Annotation;
import javassist.compiler.AccessorMaker;
import javassist.compiler.CompileError;
import javassist.compiler.Javac;
import javassist.expr.ExprEditor;
/**
* Class> types.
*/
class CtClassType extends CtClass {
ClassPool classPool;
boolean wasChanged;
private boolean wasFrozen;
boolean wasPruned;
boolean gcConstPool; // if true, the constant pool entries will be garbage collected.
ClassFile classfile;
byte[] rawClassfile; // backup storage
private Reference memberCache;
private AccessorMaker accessors;
private FieldInitLink fieldInitializers;
private Map hiddenMethods; // must be synchronous
private int uniqueNumberSeed;
private boolean doPruning = ClassPool.doPruning;
private int getCount;
private static final int GET_THRESHOLD = 2; // see compress()
CtClassType(String name, ClassPool cp) {
super(name);
classPool = cp;
wasChanged = wasFrozen = wasPruned = gcConstPool = false;
classfile = null;
rawClassfile = null;
memberCache = null;
accessors = null;
fieldInitializers = null;
hiddenMethods = null;
uniqueNumberSeed = 0;
getCount = 0;
}
CtClassType(InputStream ins, ClassPool cp) throws IOException {
this((String)null, cp);
classfile = new ClassFile(new DataInputStream(ins));
qualifiedName = classfile.getName();
}
CtClassType(ClassFile cf, ClassPool cp) {
this((String)null, cp);
classfile = cf;
qualifiedName = classfile.getName();
}
@Override
protected void extendToString(StringBuffer buffer) {
if (wasChanged)
buffer.append("changed ");
if (wasFrozen)
buffer.append("frozen ");
if (wasPruned)
buffer.append("pruned ");
buffer.append(Modifier.toString(getModifiers()));
buffer.append(" class ");
buffer.append(getName());
try {
CtClass ext = getSuperclass();
if (ext != null) {
String name = ext.getName();
if (!name.equals("java.lang.Object"))
buffer.append(" extends " + ext.getName());
}
}
catch (NotFoundException e) {
buffer.append(" extends ??");
}
try {
CtClass[] intf = getInterfaces();
if (intf.length > 0)
buffer.append(" implements ");
for (int i = 0; i < intf.length; ++i) {
buffer.append(intf[i].getName());
buffer.append(", ");
}
}
catch (NotFoundException e) {
buffer.append(" extends ??");
}
CtMember.Cache memCache = getMembers();
exToString(buffer, " fields=",
memCache.fieldHead(), memCache.lastField());
exToString(buffer, " constructors=",
memCache.consHead(), memCache.lastCons());
exToString(buffer, " methods=",
memCache.methodHead(), memCache.lastMethod());
}
private void exToString(StringBuffer buffer, String msg,
CtMember head, CtMember tail) {
buffer.append(msg);
while (head != tail) {
head = head.next();
buffer.append(head);
buffer.append(", ");
}
}
@Override
public AccessorMaker getAccessorMaker() {
if (accessors == null)
accessors = new AccessorMaker(this);
return accessors;
}
@Override
public ClassFile getClassFile2() {
return getClassFile3(true);
}
public ClassFile getClassFile3(boolean doCompress) {
ClassFile cfile = classfile;
if (cfile != null)
return cfile;
if (doCompress)
classPool.compress();
if (rawClassfile != null) {
try {
ClassFile cf = new ClassFile(new DataInputStream(
new ByteArrayInputStream(rawClassfile)));
rawClassfile = null;
getCount = GET_THRESHOLD;
return setClassFile(cf);
}
catch (IOException e) {
throw new RuntimeException(e.toString(), e);
}
}
InputStream fin = null;
try {
fin = classPool.openClassfile(getName());
if (fin == null)
throw new NotFoundException(getName());
fin = new BufferedInputStream(fin);
ClassFile cf = new ClassFile(new DataInputStream(fin));
if (!cf.getName().equals(qualifiedName))
throw new RuntimeException("cannot find " + qualifiedName + ": "
+ cf.getName() + " found in "
+ qualifiedName.replace('.', '/') + ".class");
return setClassFile(cf);
}
catch (NotFoundException e) {
throw new RuntimeException(e.toString(), e);
}
catch (IOException e) {
throw new RuntimeException(e.toString(), e);
}
finally {
if (fin != null)
try {
fin.close();
}
catch (IOException e) {}
}
}
/* Inherited from CtClass. Called by get() in ClassPool.
*
* @see javassist.CtClass#incGetCounter()
* @see #toBytecode(DataOutputStream)
*/
@Override
final void incGetCounter() { ++getCount; }
/**
* Invoked from ClassPool#compress().
* It releases the class files that have not been recently used
* if they are unmodified.
*/
@Override
void compress() {
if (getCount < GET_THRESHOLD)
if (!isModified() && ClassPool.releaseUnmodifiedClassFile)
removeClassFile();
else if (isFrozen() && !wasPruned)
saveClassFile();
getCount = 0;
}
/**
* Converts a ClassFile object into a byte array
* for saving memory space.
*/
private synchronized void saveClassFile() {
/* getMembers() and removeClassFile() are also synchronized.
*/
if (classfile == null || hasMemberCache() != null)
return;
ByteArrayOutputStream barray = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(barray);
try {
classfile.write(out);
barray.close();
rawClassfile = barray.toByteArray();
classfile = null;
}
catch (IOException e) {}
}
private synchronized void removeClassFile() {
if (classfile != null && !isModified() && hasMemberCache() == null)
classfile = null;
}
/**
* Updates {@code classfile} if it is null.
*/
private synchronized ClassFile setClassFile(ClassFile cf) {
if (classfile == null)
classfile = cf;
return classfile;
}
@Override
public ClassPool getClassPool() { return classPool; }
void setClassPool(ClassPool cp) { classPool = cp; }
@Override
public URL getURL() throws NotFoundException {
URL url = classPool.find(getName());
if (url == null)
throw new NotFoundException(getName());
return url;
}
@Override
public boolean isModified() { return wasChanged; }
@Override
public boolean isFrozen() { return wasFrozen; }
@Override
public void freeze() { wasFrozen = true; }
@Override
void checkModify() throws RuntimeException {
if (isFrozen()) {
String msg = getName() + " class is frozen";
if (wasPruned)
msg += " and pruned";
throw new RuntimeException(msg);
}
wasChanged = true;
}
@Override
public void defrost() {
checkPruned("defrost");
wasFrozen = false;
}
@Override
public boolean subtypeOf(CtClass clazz) throws NotFoundException {
int i;
String cname = clazz.getName();
if (this == clazz || getName().equals(cname))
return true;
ClassFile file = getClassFile2();
String supername = file.getSuperclass();
if (supername != null && supername.equals(cname))
return true;
String[] ifs = file.getInterfaces();
int num = ifs.length;
for (i = 0; i < num; ++i)
if (ifs[i].equals(cname))
return true;
if (supername != null && classPool.get(supername).subtypeOf(clazz))
return true;
for (i = 0; i < num; ++i)
if (classPool.get(ifs[i]).subtypeOf(clazz))
return true;
return false;
}
@Override
public void setName(String name) throws RuntimeException {
String oldname = getName();
if (name.equals(oldname))
return;
// check this in advance although classNameChanged() below does.
classPool.checkNotFrozen(name);
ClassFile cf = getClassFile2();
super.setName(name);
cf.setName(name);
nameReplaced();
classPool.classNameChanged(oldname, this);
}
@Override
public String getGenericSignature() {
SignatureAttribute sa
= (SignatureAttribute)getClassFile2().getAttribute(SignatureAttribute.tag);
return sa == null ? null : sa.getSignature();
}
@Override
public void setGenericSignature(String sig) {
ClassFile cf = getClassFile();
SignatureAttribute sa = new SignatureAttribute(cf.getConstPool(), sig);
cf.addAttribute(sa);
}
@Override
public void replaceClassName(ClassMap classnames)
throws RuntimeException
{
String oldClassName = getName();
String newClassName
= classnames.get(Descriptor.toJvmName(oldClassName));
if (newClassName != null) {
newClassName = Descriptor.toJavaName(newClassName);
// check this in advance although classNameChanged() below does.
classPool.checkNotFrozen(newClassName);
}
super.replaceClassName(classnames);
ClassFile cf = getClassFile2();
cf.renameClass(classnames);
nameReplaced();
if (newClassName != null) {
super.setName(newClassName);
classPool.classNameChanged(oldClassName, this);
}
}
@Override
public void replaceClassName(String oldname, String newname)
throws RuntimeException
{
String thisname = getName();
if (thisname.equals(oldname))
setName(newname);
else {
super.replaceClassName(oldname, newname);
getClassFile2().renameClass(oldname, newname);
nameReplaced();
}
}
@Override
public boolean isInterface() {
return Modifier.isInterface(getModifiers());
}
@Override
public boolean isAnnotation() {
return Modifier.isAnnotation(getModifiers());
}
@Override
public boolean isEnum() {
return Modifier.isEnum(getModifiers());
}
@Override
public int getModifiers() {
ClassFile cf = getClassFile2();
int acc = cf.getAccessFlags();
acc = AccessFlag.clear(acc, AccessFlag.SUPER);
int inner = cf.getInnerAccessFlags();
if (inner != -1) {
if ((inner & AccessFlag.STATIC) != 0)
acc |= AccessFlag.STATIC;
if ((inner & AccessFlag.PUBLIC) != 0)
acc |= AccessFlag.PUBLIC;
else {
acc &= ~AccessFlag.PUBLIC; //clear PUBLIC
if ((inner & AccessFlag.PROTECTED) != 0)
acc |= AccessFlag.PROTECTED;
else if ((inner & AccessFlag.PRIVATE) != 0)
acc |= AccessFlag.PRIVATE;
}
}
return AccessFlag.toModifier(acc);
}
@Override
public CtClass[] getNestedClasses() throws NotFoundException {
ClassFile cf = getClassFile2();
InnerClassesAttribute ica
= (InnerClassesAttribute)cf.getAttribute(InnerClassesAttribute.tag);
if (ica == null)
return new CtClass[0];
String thisName = cf.getName() + "$";
int n = ica.tableLength();
List list = new ArrayList(n);
for (int i = 0; i < n; i++) {
String name = ica.innerClass(i);
if (name != null)
if (name.startsWith(thisName)) {
// if it is an immediate nested class
if (name.lastIndexOf('$') < thisName.length())
list.add(classPool.get(name));
}
}
return list.toArray(new CtClass[list.size()]);
}
@Override
public void setModifiers(int mod) {
checkModify();
updateInnerEntry(mod, getName(), this, true);
ClassFile cf = getClassFile2();
cf.setAccessFlags(AccessFlag.of(mod & ~Modifier.STATIC));
}
private static void updateInnerEntry(int newMod, String name, CtClass clazz, boolean outer) {
ClassFile cf = clazz.getClassFile2();
InnerClassesAttribute ica
= (InnerClassesAttribute)cf.getAttribute(InnerClassesAttribute.tag);
if (ica != null) {
// If the class is a static inner class, its modifier
// does not contain the static bit. Its inner class attribute
// contains the static bit.
int mod = newMod & ~Modifier.STATIC;
int i = ica.find(name);
if (i >= 0) {
int isStatic = ica.accessFlags(i) & AccessFlag.STATIC;
if (isStatic != 0 || !Modifier.isStatic(newMod)) {
clazz.checkModify();
ica.setAccessFlags(i, AccessFlag.of(mod) | isStatic);
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);
}
return;
}
}
}
if (Modifier.isStatic(newMod))
throw new RuntimeException("cannot change " + Descriptor.toJavaName(name)
+ " into a static class");
}
@Override
public boolean hasAnnotation(String annotationName) {
ClassFile cf = getClassFile2();
AnnotationsAttribute ainfo = (AnnotationsAttribute)
cf.getAttribute(AnnotationsAttribute.invisibleTag);
AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
cf.getAttribute(AnnotationsAttribute.visibleTag);
return hasAnnotationType(annotationName, getClassPool(), ainfo, ainfo2);
}
/**
* @deprecated
*/
@Deprecated
static boolean hasAnnotationType(Class> clz, ClassPool cp,
AnnotationsAttribute a1,
AnnotationsAttribute a2)
{
return hasAnnotationType(clz.getName(), cp, a1, a2);
}
static boolean hasAnnotationType(String annotationTypeName, ClassPool cp,
AnnotationsAttribute a1,
AnnotationsAttribute a2)
{
Annotation[] anno1, anno2;
if (a1 == null)
anno1 = null;
else
anno1 = a1.getAnnotations();
if (a2 == null)
anno2 = null;
else
anno2 = a2.getAnnotations();
if (anno1 != null)
for (int i = 0; i < anno1.length; i++)
if (anno1[i].getTypeName().equals(annotationTypeName))
return true;
if (anno2 != null)
for (int i = 0; i < anno2.length; i++)
if (anno2[i].getTypeName().equals(annotationTypeName))
return true;
return false;
}
@Override
public Object getAnnotation(Class> clz) throws ClassNotFoundException {
ClassFile cf = getClassFile2();
AnnotationsAttribute ainfo = (AnnotationsAttribute)
cf.getAttribute(AnnotationsAttribute.invisibleTag);
AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
cf.getAttribute(AnnotationsAttribute.visibleTag);
return getAnnotationType(clz, getClassPool(), ainfo, ainfo2);
}
static Object getAnnotationType(Class> clz, ClassPool cp,
AnnotationsAttribute a1, AnnotationsAttribute a2)
throws ClassNotFoundException
{
Annotation[] anno1, anno2;
if (a1 == null)
anno1 = null;
else
anno1 = a1.getAnnotations();
if (a2 == null)
anno2 = null;
else
anno2 = a2.getAnnotations();
String typeName = clz.getName();
if (anno1 != null)
for (int i = 0; i < anno1.length; i++)
if (anno1[i].getTypeName().equals(typeName))
return toAnnoType(anno1[i], cp);
if (anno2 != null)
for (int i = 0; i < anno2.length; i++)
if (anno2[i].getTypeName().equals(typeName))
return toAnnoType(anno2[i], cp);
return null;
}
@Override
public Object[] getAnnotations() throws ClassNotFoundException {
return getAnnotations(false);
}
@Override
public Object[] getAvailableAnnotations(){
try {
return getAnnotations(true);
}
catch (ClassNotFoundException e) {
throw new RuntimeException("Unexpected exception ", e);
}
}
private Object[] getAnnotations(boolean ignoreNotFound)
throws ClassNotFoundException
{
ClassFile cf = getClassFile2();
AnnotationsAttribute ainfo = (AnnotationsAttribute)
cf.getAttribute(AnnotationsAttribute.invisibleTag);
AnnotationsAttribute ainfo2 = (AnnotationsAttribute)
cf.getAttribute(AnnotationsAttribute.visibleTag);
return toAnnotationType(ignoreNotFound, getClassPool(), ainfo, ainfo2);
}
static Object[] toAnnotationType(boolean ignoreNotFound, ClassPool cp,
AnnotationsAttribute a1, AnnotationsAttribute a2)
throws ClassNotFoundException
{
Annotation[] anno1, anno2;
int size1, size2;
if (a1 == null) {
anno1 = null;
size1 = 0;
}
else {
anno1 = a1.getAnnotations();
size1 = anno1.length;
}
if (a2 == null) {
anno2 = null;
size2 = 0;
}
else {
anno2 = a2.getAnnotations();
size2 = anno2.length;
}
if (!ignoreNotFound){
Object[] result = new Object[size1 + size2];
for (int i = 0; i < size1; i++)
result[i] = toAnnoType(anno1[i], cp);
for (int j = 0; j < size2; j++)
result[j + size1] = toAnnoType(anno2[j], cp);
return result;
}
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy