package gov.nasa.jpf.report;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import gov.nasa.jpf.Config;
import gov.nasa.jpf.Error;
import gov.nasa.jpf.JPF;
import gov.nasa.jpf.util.RepositoryEntry;
import gov.nasa.jpf.vm.ChoiceGenerator;
import gov.nasa.jpf.vm.ElementInfo;
import gov.nasa.jpf.vm.Path;
import gov.nasa.jpf.vm.StackFrame;
import gov.nasa.jpf.vm.Step;
import gov.nasa.jpf.vm.ThreadInfo;
import gov.nasa.jpf.vm.Transition;
import gov.nasa.jpf.vm.VM;
public class XMLPublisher extends Publisher {
public XMLPublisher(Config conf, Reporter reporter) {
super(conf, reporter);
}
public String getName() {
return "xml";
}
protected void openChannel(){
if (out == null) {
String fname = getReportFileName("report.xml.file") + ".xml";
try {
out = new PrintWriter(fname);
} catch (FileNotFoundException fnfx) {
// log here
}
}
}
protected void closeChannel() {
if (out != null){
out.close();
out = null;
}
}
protected void publishProlog() {
out.println("<?xml version=\"1.0\" ?>");
out.println("<jpfreport>");
}
public void publishTopicStart(String topic) {
out.println(" <" + topic + ">");
}
public void publishTopicEnd(String topic) {
out.println(" </" + topic + ">");
}
protected void publishEpilog() {
out.println("</jpfreport>");
}
protected void publishJPF() {
out.println(" <jpf-version>" + JPF.VERSION + "</jpf-version>");
}
protected void publishJPFConfig() {
TreeMap<Object,Object> map = conf.asOrderedMap();
Set<Map.Entry<Object,Object>> eSet = map.entrySet();
out.println(" <jpf-properties>");
for (Object src : conf.getSources()){
out.println(" <source value=\"" + conf.getSourceName(src) + "\"/>");
}
for (Map.Entry<Object,Object> e : eSet) {
out.println(" <entry key=\"" + e.getKey() + "\" value=\"" + e.getValue() + "\"/>");
}
out.println(" </jpf-properties>");
}
protected void publishPlatform() {
out.println(" <platform>");
out.println(" <hostname>" + reporter.getHostName() + "</hostname>");
out.println(" <arch>" + reporter.getArch() + "</arch>");
out.println(" <os>" + reporter.getOS() + "</os>");
out.println(" <java>" + reporter.getJava() + "</java>");
out.println(" </platform>");
}
protected void publishUser() {
out.println(" <user>" + reporter.getUser() + "</user>");
}
protected void publishDTG() {
out.println(" <started>" + reporter.getStartDate() + "</started>");
}
protected void publishSuT() {
out.println(" <sut>");
String mainCls = reporter.getSuT();
if (mainCls != null) {
String mainPath = reporter.getSuT();
if (mainPath != null) {
out.println(" <source>" + mainPath + "</source>");
RepositoryEntry rep = RepositoryEntry.getRepositoryEntry(mainPath);
if (rep != null) {
out.println(" <repository>" + rep.getRepository() + "</repository>");
out.println(" <revision>" + rep.getRevision() + "</revision>");
}
} else {
out.println(" <binary>" + mainCls + ".class" + "</binary>");
}
} else {
// no app specified
}
out.println(" </sut>");
}
protected void publishResult() {
List<Error> errors = reporter.getErrors();
out.print(" <result findings=\"");
if (errors.isEmpty()){
out.println("none\"/>");
} else {
out.println("errors\">");
int i=0;
for (Error e : errors) {
out.print(" <error id=\"");
out.print(i++);
out.println("\">");
out.print(" <property>");
out.print(e.getProperty().getClass().getName());
out.println("</property>");
out.print(" <details>");
out.print(e.getDetails());
out.println(" </details>");
out.println(" </error>");
}
out.println(" </result>");
}
}
// not sure how much effort we want to put into readability here
protected void publishTrace() {
Path path = reporter.getPath();
int i=0;
if (path.size() == 0) {
return; // nothing to publish
}
out.println(" <trace>");
for (Transition t : path) {
ChoiceGenerator<?> cg = t.getChoiceGenerator();
out.println(" <transition id=\"" + i++ + "\" thread=\"" + t.getThreadIndex() + "\">");
out.println(" <cg class=\""+cg.getClass().getName() + "\" choice=\"" +
cg.getProcessedNumberOfChoices() + "\"/>");
for (Step s : t) {
out.print(" <insn src=\"" + s.getLocationString() + "\">");
String insn = s.getInstruction().toString();
if (insn.indexOf('<') >= 0) { // <init> and <clinit> clash with XML
insn = insn.replaceAll("<", "<");
insn = insn.replaceAll(">", ">");
}
out.print(insn);
out.println("</insn>");
}
out.println(" </transition>");
}
out.println(" </trace>");
}
protected void publishOutput() {
Path path = reporter.getPath();
if (path.size() == 0) {
return; // nothing to publish
}
if (path.hasOutput()) {
out.println(" <output>");
for (Transition t : path) {
String s = t.getOutput();
if (s != null){
out.print(s);
}
}
out.println(" </output>");
}
}
protected void publishSnapshot() {
VM vm = reporter.getVM();
out.println(" <live-threads>");
for (ThreadInfo ti : vm.getLiveThreads()) {
out.println(" <thread id=\"" + ti.getId() + "\" name=\"" + ti.getName()
+ "\" status=\"" + ti.getStateName() + "\">");
// owned locks
for (ElementInfo e : ti.getLockedObjects()) {
out.println(" <lock-owned object=\"" + e + "\"/>");
}
// requested locks
ElementInfo ei = ti.getLockObject();
if (ei != null) {
out.println(" <lock-request object=\"" + ei + "\"/>");
}
// stack frames
for (StackFrame frame : ti){
if (!frame.isDirectCallFrame()){
out.println(" <frame>" + frame.getStackTraceInfo() + "</frame>");
}
}
out.println(" </thread>");
}
out.println(" </live-threads>");
}
protected void publishStatistics() {
Statistics stat = reporter.getStatistics();
out.println(" <statistics>");
out.println(" <elapsed-time>" + formatHMS(reporter.getElapsedTime()) + "</elapsed-time>");
out.println(" <new-states>" + stat.newStates + "</new-states>");
out.println(" <visited-states>" + stat.visitedStates + "</visited-states>");
out.println(" <backtracked-states>" + stat.backtracked + "</backtracked-states>");
out.println(" <end-states>" + stat.endStates + "</end-states>");
out.println(" <max-memory unit=\"MB\">" + (stat.maxUsed >>20) + "</max-memory>");
out.println(" </statistics>");
}
}