package it.unina.seclab.jafimon;
import it.unina.seclab.jafimon.util.JaFiMonLogger;
import it.unina.seclab.jafimon.util.JavassistCodeBuffer;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Questa classe viene utilizzata dalla classe {@link it.unina.seclab.jafimon.Monitor} per effettuare la
* validazione ed il caricamento del file XML che definisce la <code>Configuration</code>
* attualmente in uso e realizzarne l'instrumentazione di runtime definita.
*
* @author Mauro Iorio
*
*/
public class ConfigurationSAXParser extends DefaultHandler {
private String className;
private String origMethod;
private String newClass;
private String newMethod;
private boolean isBody = false;
protected boolean monitorMode = false; // RFU
protected boolean injectorMode = false; // RFU
private CustomTranslator translator;
private ClassPool thePool;
private CtClass newClazz;
private JavassistCodeBuffer newBody;
private int editType;
private boolean doEditor = false;
private boolean doConverter = false;
//private static final Logger logger = Logger.getRootLogger();
private static final JaFiMonLogger logger = new JaFiMonLogger();
public ConfigurationSAXParser(CustomTranslator xlat, ClassPool pool) {
translator = xlat;
thePool = pool;
}
public void startDocument() throws SAXException {
logger.debug("startDocument");
}
public void endDocument() throws SAXException {
logger.debug("endDocument");
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
logger.debug("startElement: " + qName);
if (qName.equalsIgnoreCase("monitor")) {
monitorMode = true;
injectorMode = false;
}
if (qName.equalsIgnoreCase("injector")) {
monitorMode = false;
injectorMode = true;
}
try {
if (qName.equalsIgnoreCase("class")) {
className = atts.getValue("name");
newClazz = thePool.get(className);
} else if (qName.equalsIgnoreCase("insertAfterMethod")) {
doConverter = true;
origMethod = atts.getValue("origMethod");
newMethod = atts.getValue("afterMethod");
newClass = atts.getValue("afterClass");
translator.newConverterForClass(className).addOperation(CustomConverter.INSERTAFTERMETHOD, className, origMethod, newClass, newMethod);
} else if (qName.equalsIgnoreCase("insertBeforeMethod")) {
doConverter = true;
origMethod = atts.getValue("origMethod");
newMethod = atts.getValue("beforeMethod");
newClass = atts.getValue("beforeClass");
translator.newConverterForClass(className).addOperation(CustomConverter.INSERTBEFOREMETHOD, className, origMethod, newClass, newMethod);
} else if (qName.equalsIgnoreCase("redirectMethodCall")) {
doConverter = true;
origMethod = atts.getValue("origMethod");
newMethod = atts.getValue("substMethod");
newClass = atts.getValue("redirectClass");
translator.newConverterForClass(className).addOperation(CustomConverter.REDIRECTMETHODCALL, className, origMethod, newClass, newMethod);
} else if (qName.equals("replaceFieldRead")) {
doConverter = true;
origMethod = atts.getValue("origField");
newClass = atts.getValue("redirectClass");
newMethod = atts.getValue("redirectMethod");
translator.newConverterForClass(className).addOperation(CustomConverter.REPLACEFIELDREAD, className, origMethod, newClass, newMethod);
} else if (qName.equals("redirectFieldAccess")) {
doConverter = true;
origMethod = atts.getValue("origField");
newClass = atts.getValue("redirectClass");
newMethod = atts.getValue("redirectField");
translator.newConverterForClass(className).addOperation(CustomConverter.REDIRECTFIELDACCESS, className, origMethod, newClass, newMethod);
} else if (qName.equals("replaceFieldWrite")) {
doConverter = true;
origMethod = atts.getValue("origField");
newClass = atts.getValue("redirectClass");
newMethod = atts.getValue("redirectMethod");
translator.newConverterForClass(className).addOperation(CustomConverter.REPLACEFIELDWRITE, className, origMethod, newClass, newMethod);
} else if (qName.equalsIgnoreCase("replacenew")) {
doConverter = true;
newClass = atts.getValue("calledClass");
newMethod = atts.getValue("calledMethod");
translator.newConverterForClass(className).addOperation(CustomConverter.REPLACENEW, className, null, newClass, newMethod);
} else if (qName.equalsIgnoreCase("new_class")) {
newClass = atts.getValue("name");
className = atts.getValue("superclass");
newClazz = thePool.makeClass(newClass);
if (className.equals(""))
className = "java.lang.Object";
newClazz.setSuperclass(thePool.get(className));
} else if (qName.equalsIgnoreCase("new_method")) {
newMethod = atts.getValue("signature");
isBody = true;
newBody = new JavassistCodeBuffer();
newBody.append(newMethod);
} else if (qName.equalsIgnoreCase("new_constructor")) {
newMethod = atts.getValue("signature");
isBody = true;
newBody = new JavassistCodeBuffer();
newBody.append(newMethod);
} else if (qName.equalsIgnoreCase("new_field")) {
newMethod = atts.getValue("signature");
newClazz.addField(CtField.make(newMethod, newClazz));
} else if (qName.equalsIgnoreCase("new_interface")) {
newMethod = atts.getValue("signature");
CtClass intf = thePool.get(newMethod);
newClazz.addInterface(intf);
} else if (qName.equalsIgnoreCase("edit")) {
doEditor = true;
isBody = true;
newBody = new JavassistCodeBuffer();
newMethod = atts.getValue("type");
if (newMethod.equalsIgnoreCase("cast")) {
editType = CustomTranslator.EDITCAST;
} else if (newMethod.equalsIgnoreCase("constructor")) {
editType = CustomTranslator.EDITCONSTRUCTOR;
} else if (newMethod.equalsIgnoreCase("fieldaccess")) {
editType = CustomTranslator.EDITFIELDACCESS;
} else if (newMethod.equalsIgnoreCase("handler")) {
editType = CustomTranslator.EDITHANDLER;
} else if (newMethod.equalsIgnoreCase("instanceof")) {
editType = CustomTranslator.EDITINSTANCEOF;
} else if (newMethod.equalsIgnoreCase("methodcall")) {
editType = CustomTranslator.EDITMETHODCALL;
} else if (newMethod.equalsIgnoreCase("newarray")) {
editType = CustomTranslator.EDITNEWARRAY;
} else if (newMethod.equalsIgnoreCase("newexpr")) {
editType = CustomTranslator.EDITNEWEXPR;
}
/*
JavassistCodeBuffer sb = new JavassistCodeBuffer();
sb.append("{\n");
sb.append("if ( $1.getFieldName().equals('intero') && $1.isWriter() ) {\n");
// sb.append("$1.replace('System.out.println(\\\"Pippo\\\");');\n");
sb.append("$1.replace('$' + '0' + '.intero = ' + $1.getLineNumber() + ';');\n");
// sb.append("System.out.println(\"\tSUBCLASS: new \" + $1.getClassName() + \" \" + $1.getFileName() + \".\" + $1.getLineNumber());\n");
sb.append("}\n");
sb.append("}");
translator.newEditorForClass(className, thePool);
*/
}
} catch(Exception e) {
throw new SAXException(e);
}
}
public void endElement(String namespaceURI, String localName,
String qName) throws SAXException {
logger.debug("endElement: " + qName);
if (qName.equalsIgnoreCase("monitor")) {
monitorMode = false;
}
if (qName.equalsIgnoreCase("injector")) {
injectorMode = false;
}
if (qName.equalsIgnoreCase("new_method")) {
isBody = false;
try {
logger.trace("Body: " + newBody.toString());
newClazz.addMethod(CtNewMethod.make(newBody.toString(), newClazz));
} catch (CannotCompileException e) {
throw new SAXException(e);
}
} else if (qName.equalsIgnoreCase("new_constructor")) {
isBody = false;
try {
logger.trace("Constructor Body: " + newBody.toString());
newClazz.addConstructor(CtNewConstructor.make(newBody.toString(), newClazz));
} catch (CannotCompileException e) {
throw new SAXException(e);
}
} else if (qName.equalsIgnoreCase("edit")) {
isBody = false;
try {
logger.trace("Body: " + newBody.toString());
translator.instrumentEditor(thePool, className, editType, newBody.toString());
} catch (CannotCompileException e) {
throw new SAXException(e);
} catch (NotFoundException e) {
throw new SAXException(e);
}
} else if (qName.equalsIgnoreCase("class")) {
if (doConverter) {
translator.newConverterForClass(className);
doConverter = false;
}
if (doEditor) {
translator.newEditorForClass(className, thePool);
doEditor = false;
}
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (isBody) {
String s = new String(ch,start,length);
newBody.append(s);
}
}
}