WALA/com.ibm.wala.core/src/com/ibm/wala/ipa/summaries/BypassSyntheticClassLoader....

217 lines
6.1 KiB
Java

/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.ipa.summaries;
import java.io.IOException;
import java.io.Reader;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.Language;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ssa.SSAInstructionFactory;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.config.SetOfClasses;
import com.ibm.wala.util.strings.Atom;
/**
* This class represents class loaders that introduce classes that do not exist
* in the actual application being analyzed. They may be abstract summaries of
* unanalyzed library code, wrappers that encode J2EE specialized behavior or
* other invented classes.
*
* The intention is that there be (at most) one such classloader in a given
* class hierarchy, and that it be referenced using the "Synthetic" classloader
* reference. Furthermore, it is required that this synthetic loader be a child
* loader of the Primordial, Extension and Application loaders.
*
* This special classloader has some interactions with the hierarchy for, while
* the classes it loads are normal-seeming IClass objects, unlike the other
* loaders, its set of classes is not fixed, causing special cases in code that
* caches hierarchy data. Also note that this causes the getNumberfClasses and
* iterateAllClasses methods to behave differently for those of other
* classloaders.
*
* Code that wants to introduce synthetic classes uses the registerClass method,
* giving it an Atom which is the class name, and an IClass which is the class
* to load. Since the synthetic loader musat be a child of the others, it would
* be very bad to use an existing name for a new synthetic class.
*
* Class lookup works just as for any other classloader.
*
* @author Julian Dolby (dolby@us.ibm.com)
*
*/
public class BypassSyntheticClassLoader implements IClassLoader {
private final ClassLoaderReference me;
private final IClassLoader parent;
private final IClassHierarchy cha;
private final HashMap<TypeName, IClass> syntheticClasses = HashMapFactory.make();
/**
* Don't change my signature! ClassLoaderFactoryImpl calls me by reflection! yuck.
*
* @param me the name of this class loader
* @param parent its parent
* @param exclusions classes to ignore
* @param cha governing class hierarchy
*/
public BypassSyntheticClassLoader(ClassLoaderReference me, IClassLoader parent, SetOfClasses exclusions, IClassHierarchy cha) {
if (cha == null) {
throw new IllegalArgumentException("null cha");
}
this.me = me;
this.cha = cha;
this.parent = parent;
}
@Override
public String toString() {
return me.getName().toString();
}
@Override
public IClass lookupClass(TypeName className) {
IClass pc = parent.lookupClass(className);
if (pc == null) {
IClass c = syntheticClasses.get(className);
return c;
} else {
return pc;
}
}
/**
* Register the existence of a new synthetic class
*/
public void registerClass(TypeName className, IClass theClass) {
cha.addClass(theClass);
syntheticClasses.put(className, theClass);
}
/**
* Return the ClassLoaderReference for this class loader.
*/
@Override
public ClassLoaderReference getReference() {
return me;
}
/**
* @return an Iterator of all classes loaded by this loader
*/
@Override
public Iterator<IClass> iterateAllClasses() {
return syntheticClasses.values().iterator();
}
/**
* @return the number of classes in scope to be loaded by this loader
*/
@Override
public int getNumberOfClasses() {
return syntheticClasses.size();
}
/**
* @return the unique name that identifies this class loader.
*/
@Override
public Atom getName() {
return me.getName();
}
/**
* @return the unique name that identifies the programming language
* from which this class loader loads code.
*/
@Override
public Language getLanguage() {
return Language.JAVA;
}
/*
* @see com.ibm.wala.classLoader.IClassLoader#getNumberOfMethods()
*/
@Override
public int getNumberOfMethods() {
// TODO Auto-generated method stub
return 0;
}
/*
* @see com.ibm.wala.classLoader.IClassLoader#getSourceFileName(com.ibm.wala.classLoader.IClass)
*/
@Override
public String getSourceFileName(IClass klass) {
return null;
}
/**
* @see com.ibm.wala.classLoader.IClassLoader#getParent()
*/
@Override
public IClassLoader getParent() {
return parent;
}
@Override
public void init(List<Module> modules) throws IOException {
}
/*
* @see com.ibm.wala.classLoader.IClassLoader#removeAll(java.util.Collection)
*/
@Override
public void removeAll(Collection<IClass> toRemove) {
if (toRemove == null) {
throw new IllegalArgumentException("toRemove is null");
}
for (Iterator<IClass> it = toRemove.iterator(); it.hasNext();) {
IClass klass = it.next();
syntheticClasses.remove(klass.getName());
}
}
@Override
public Reader getSource(IClass klass) {
return null;
}
@Override
public SSAInstructionFactory getInstructionFactory() {
return getLanguage().instructionFactory();
}
@Override
public Reader getSource(IMethod method, int offset) {
return null;
}
@Override
public String getSourceFileName(IMethod method, int offset) {
return null;
}
}