/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package com.db4o.instrumentation.core;
import java.util.*;
import EDU.purdue.cs.bloat.cfg.*;
import EDU.purdue.cs.bloat.context.*;
import EDU.purdue.cs.bloat.editor.*;
import EDU.purdue.cs.bloat.reflect.*;
import com.db4o.instrumentation.bloat.*;
import com.db4o.instrumentation.util.*;
/**
* @exclude
*/
public class BloatLoaderContext {
private EditorContext context;
private final BloatReferenceProvider references;
public BloatLoaderContext(ClassInfoLoader loader) {
this(new CachingBloatContext(loader,new LinkedList(),false));
}
public BloatLoaderContext(EditorContext context) {
this.context=context;
this.references = new BloatReferenceProvider();
}
public BloatReferenceProvider references() {
return references;
}
public FlowGraph flowGraph(String className, String methodName) throws ClassNotFoundException {
return flowGraph(className, methodName, null);
}
public FlowGraph flowGraph(String className, String methodName,Type[] argTypes) throws ClassNotFoundException {
ClassEditor classEdit = classEditor(className);
return flowGraph(classEdit, methodName, argTypes);
}
public FlowGraph flowGraph(ClassEditor classEdit, String methodName,Type[] argTypes) throws ClassNotFoundException {
MethodEditor method = method(classEdit, methodName, argTypes);
return method == null ? null : new FlowGraph(method);
}
public MethodEditor method(ClassEditor classEdit, String methodName,Type[] argTypes) throws ClassNotFoundException {
ClassEditor clazz = classEdit;
while(clazz != null) {
MethodInfo[] methods = clazz.methods();
for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) {
MethodEditor methodEdit = context.editMethod(methods[methodIdx]);
if (methodEdit.name().equals(methodName)&&signatureMatchesTypes(argTypes, methodEdit)) {
return methodEdit;
}
}
clazz = classEditor(clazz.superclass());
}
return null;
}
public FieldEditor field(ClassEditor classEdit, String fieldName,Type fieldType) throws ClassNotFoundException {
ClassEditor clazz = classEdit;
while(clazz != null) {
FieldInfo[] fields = clazz.fields();
for (int fieldIdx = 0; fieldIdx < fields.length; fieldIdx++) {
FieldInfo fieldInfo=fields[fieldIdx];
FieldEditor fieldEdit = context.editField(fieldInfo);
if (fieldEdit.name().equals(fieldName)&&fieldType.equals(fieldEdit.type())) {
return fieldEdit;
}
}
clazz = classEditor(clazz.superclass());
}
return null;
}
public ClassEditor classEditor(Type type) throws ClassNotFoundException {
return type == null ? null : classEditor(BloatUtil.normalizeClassName(type));
}
private boolean signatureMatchesTypes(Type[] argTypes,
MethodEditor methodEdit) {
if(argTypes==null) {
return true;
}
Type[] sigTypes=methodEdit.paramTypes();
int sigOffset=(methodEdit.isStatic()||methodEdit.isConstructor() ? 0 : 1);
if(argTypes.length!=(sigTypes.length-sigOffset)) {
return false;
}
for (int idx = 0; idx < argTypes.length; idx++) {
if(!argTypes[idx].className().equals(sigTypes[idx+sigOffset].className())) {
return false;
}
}
return true;
}
public ClassEditor classEditor(String className) throws ClassNotFoundException {
return context.editClass(className);
}
public ClassEditor classEditor(int modifiers, String className, Type superClass, Type[] interfaces) {
return context.newClass(modifiers, className, superClass, interfaces);
}
public Type superType(Type type) throws ClassNotFoundException {
return context.editClass(type).superclass();
}
public void commit() {
try {
context.commit();
}
catch(ConcurrentModificationException exc) {
exc.printStackTrace();
throw exc;
}
}
}