/*
* Copyright, Aspect Security, Inc.
*
* This file is part of JavaSnoop.
*
* JavaSnoop is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JavaSnoop 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 JavaSnoop. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aspect.snoop.util;
import com.aspect.snoop.Condition;
import com.aspect.snoop.FunctionHook;
import com.aspect.snoop.SnoopSession;
import com.aspect.snoop.agent.SnoopAgent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import nu.xom.Attribute;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Elements;
import nu.xom.ParsingException;
public class SessionPersistenceUtil {
public static void saveSession(SnoopSession session) throws FileNotFoundException, IOException {
if ( session.alreadyBeenSaved() ) {
saveSession(session, session.getSnoopSessionFilename());
}
}
public static void saveSession(SnoopSession session, String filename) throws FileNotFoundException, IOException {
Element sessionRoot = new Element("session");
Document doc = new Document(sessionRoot);
sessionRoot.addAttribute( new Attribute ("mainClass", session.getMainClass()) );
sessionRoot.addAttribute( new Attribute ("javaArgs", session.getJavaArguments()) );
sessionRoot.addAttribute( new Attribute ("progArgs", session.getArguments()) );
sessionRoot.addAttribute( new Attribute ("classpath", session.getClasspathString()) );
sessionRoot.addAttribute( new Attribute ("workingDir", session.getWorkingDir()) );
// Add a <hooks> node
Element hooksRoot = new Element("hooks");
// Add all the children <hook> elements
for(FunctionHook hook : session.getFunctionHooks() ) {
Element hookRoot = new Element("hook");
hookRoot.addAttribute ( new Attribute("enabled", Boolean.toString(hook.isEnabled()) ));
hookRoot.addAttribute ( new Attribute("class", hook.getClazz().getName()) );
hookRoot.addAttribute ( new Attribute("method", hook.getMethodName() ));
hookRoot.addAttribute ( new Attribute("shouldInherit", Boolean.toString(hook.isAppliedToSubtypes())));
String allParamTypes = StringUtil.join(hook.getParameterTypes(), ",");
hookRoot.addAttribute ( new Attribute("params", allParamTypes ) );
hookRoot.addAttribute ( new Attribute("returnType", hook.getReturnType().getName()));
hookRoot.addAttribute ( new Attribute("shouldTamperParameters", Boolean.toString(hook.shouldTamperParameters())));
hookRoot.addAttribute ( new Attribute("shouldTamperReturnValue", Boolean.toString(hook.shouldTamperReturnValue())));
hookRoot.addAttribute ( new Attribute("shouldRunScript", Boolean.toString(hook.shouldRunScript())));
hookRoot.addAttribute ( new Attribute("startScript", hook.getStartScript()) );
hookRoot.addAttribute ( new Attribute("endScript", hook.getEndScript()) );
hookRoot.addAttribute ( new Attribute("shouldPause", Boolean.toString(hook.shouldPause())) );
hookRoot.addAttribute( new Attribute("shouldPrintParameters", Boolean.toString(hook.shouldPrintParameters())) );
hookRoot.addAttribute( new Attribute("shouldPrintStackTrace", Boolean.toString(hook.shouldPrintStackTrace())) );
hookRoot.addAttribute( new Attribute("outputToConsole", Boolean.toString(hook.isOutputToConsole())) );
hookRoot.addAttribute( new Attribute("outputToFile", Boolean.toString(hook.isOutputToFile())) );
hookRoot.addAttribute( new Attribute("outputFile", hook.getOutputFile()));
hookRoot.addAttribute( new Attribute("interceptCondition", hook.getMode().name() ) );
// Add a <conditions> node
Element conditionsRoot = new Element("conditions");
for(Condition c : hook.getConditions() ) {
Element condition = new Element("condition");
condition.addAttribute( new Attribute ("enabled", Boolean.toString(c.isEnabled()) ) );
condition.addAttribute( new Attribute ("parameter", String.valueOf(c.getParameter()) ) );
condition.addAttribute( new Attribute ("operator", c.getOperator().name()));
condition.addAttribute( new Attribute ("operand", c.getOperand()));
conditionsRoot.appendChild(condition);
}
hookRoot.appendChild(conditionsRoot);
hooksRoot.appendChild(hookRoot);
}
sessionRoot.appendChild(hooksRoot);
Element output = new Element("output");
output.appendChild(session.getOutput());
sessionRoot.appendChild(output);
/*
* Now that we're done, we write out to the filename in the
* method parameter.
*/
FileOutputStream fos = new FileOutputStream(new File(filename));
fos.write(doc.toXML().getBytes());
session.setSnoopSessionFilename(filename);
session.markAsSaved();
}
public static SnoopSession loadSession(String filename) throws FileNotFoundException, IOException {
return loadSession(new File(filename));
}
public static SnoopSession loadSession(File file) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream(file);
SnoopSession session = loadSession(fis);
session.markAsSaved();
session.setSnoopSessionFilename(file.getAbsolutePath());
return session;
}
public static SnoopSession loadSession(Reader reader) throws IOException {
try {
Builder parser = new Builder();
Document doc = parser.build(reader);
return loadSession(doc);
} catch (ParsingException ex) {
Logger.getLogger(SessionPersistenceUtil.class.getName()).log(Level.SEVERE, null, ex);
throw new IOException(ex);
}
}
public static SnoopSession loadSession(InputStream is) throws IOException {
try {
Builder parser = new Builder();
Document doc = parser.build(is);
return loadSession(doc);
} catch (ParsingException ex) {
Logger.getLogger(SessionPersistenceUtil.class.getName()).log(Level.SEVERE, null, ex);
throw new IOException(ex);
}
}
private static SnoopSession loadSession(Document doc) throws IOException {
Element root = doc.getRootElement();
SnoopSession session = new SnoopSession();
session.setMainClass(root.getAttributeValue("mainClass"));
session.setJavaArguments(root.getAttributeValue("javaArgs"));
session.setArguments(root.getAttributeValue("progArgs"));
session.setClasspathString(root.getAttributeValue("classpath"));
session.setWorkingDir(root.getAttributeValue("workingDir"));
List<FunctionHook> hooks = new ArrayList<FunctionHook>();
Element hooksRoot = root.getFirstChildElement("hooks");
for ( int i=0; i< hooksRoot.getChildElements("hook").size(); i++ ) {
Element hookRoot = hooksRoot.getChildElements("hook").get(i);
boolean enabled = "true".equals(hookRoot.getAttributeValue("enabled"));
String clazz = hookRoot.getAttributeValue("class");
boolean applyToSubTypes = "true".equals(hookRoot.getAttributeValue("shouldInherit"));
String method = hookRoot.getAttributeValue("method");
String params = hookRoot.getAttributeValue("params");
String returnType = hookRoot.getAttributeValue("returnType");
String interceptCondition = hookRoot.getAttributeValue("interceptCondition");
FunctionHook.Mode mode = FunctionHook.Mode.valueOf(interceptCondition);
boolean shouldTamperParameters = "true".equals(hookRoot.getAttributeValue("shouldTamperParameters"));
boolean shouldTamperReturnValue = "true".equals(hookRoot.getAttributeValue("shouldTamperReturnValue"));
boolean shouldRunScript = "true".equals(hookRoot.getAttributeValue("shouldRunScript"));
boolean shouldPause = "true".equals(hookRoot.getAttributeValue("shouldPause"));
String startScript = hookRoot.getAttributeValue("startScript");
String endScript = hookRoot.getAttributeValue("endScript");
boolean printParameters = "true".equals(hookRoot.getAttributeValue("shouldPrintParameters"));
boolean printStackTrace = "true".equals(hookRoot.getAttributeValue("shouldPrintStackTrace"));
boolean isOutputToFile = "true".equals(hookRoot.getAttributeValue("outputToFile"));
boolean isOutputToConsole = "true".equals(hookRoot.getAttributeValue("outputToConsole"));
String outputFile = hookRoot.getAttributeValue("outputFile");
List<Condition> conditions = new ArrayList<Condition>();
Element conditionRoot = hookRoot.getFirstChildElement("conditions");
Elements conditionElements = conditionRoot.getChildElements("condition");
for (int j=0; j < conditionElements.size(); j++ ) {
Element e = conditionElements.get(j);
boolean conditionEnabled = "true".equals(e.getAttributeValue("enabled"));
String operand = e.getAttributeValue("operand");
int parameter = Integer.parseInt(e.getAttributeValue("parameter"));
String operatorString = e.getAttributeValue("operator");
Condition.Operator test = Condition.Operator.valueOf(operatorString);
Condition c = new Condition(
conditionEnabled, test, parameter, operand
);
conditions.add(c);
}
try {
Class realClass = SnoopAgent.getAgentManager().getFromAllClasses(clazz);
Class realReturnClass = getClazzFor(returnType);
Class[] realParams = null;
if ( params.trim().length() == 0 ) {
realParams = new Class[]{};
} else {
String[] sParamType = params.split(",");
realParams = new Class[sParamType.length];
for(int j=0;j<realParams.length;j++) {
realParams[j] = getClazzFor(sParamType[j]);
}
}
FunctionHook hook = new FunctionHook(
shouldTamperParameters,
shouldTamperReturnValue,
shouldRunScript,
startScript,
endScript,
shouldPause,
enabled,
realClass,
method,
realParams,
realReturnClass,
applyToSubTypes,
mode,
printParameters,
printStackTrace,
isOutputToConsole,
isOutputToFile,
outputFile,
conditions);
hooks.add(hook);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
session.setFunctionHooks(hooks);
session.setOutput( root.getChildElements("output").get(0).getValue() );
return session;
}
private static Class getClazzFor(String type) throws ClassNotFoundException {
if ( "boolean".equals(type) ) {
return boolean.class;
} else if ( "byte".equals(type) ) {
return byte.class;
} else if ( "char".equals(type) ) {
return char.class;
} else if ( "short".equals(type) ) {
return short.class;
} else if ( "int".equals(type) ) {
return int.class;
} else if ( "long".equals(type) ) {
return long.class;
} else if ( "double".equals(type) ) {
return double.class;
} else if ( "float".equals(type) ) {
return float.class;
} else if ( "void".equals(type) ) {
return void.class;
}
return SnoopAgent.getAgentManager().getFromAllClasses(type);
}
}