Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / report / XMLPublisher.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18
19 package gov.nasa.jpf.report;
20
21 import gov.nasa.jpf.Config;
22 import gov.nasa.jpf.Error;
23 import gov.nasa.jpf.JPF;
24 import gov.nasa.jpf.util.RepositoryEntry;
25 import gov.nasa.jpf.vm.ChoiceGenerator;
26 import gov.nasa.jpf.vm.ElementInfo;
27 import gov.nasa.jpf.vm.VM;
28 import gov.nasa.jpf.vm.Path;
29 import gov.nasa.jpf.vm.StackFrame;
30 import gov.nasa.jpf.vm.Step;
31 import gov.nasa.jpf.vm.ThreadInfo;
32 import gov.nasa.jpf.vm.Transition;
33
34 import java.io.FileNotFoundException;
35 import java.io.PrintWriter;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.TreeMap;
40
41 public class XMLPublisher extends Publisher {
42
43   public XMLPublisher(Config conf, Reporter reporter) {
44     super(conf, reporter);
45   }
46
47   @Override
48   public String getName() {
49     return "xml";
50   }
51   
52   @Override
53   protected void openChannel(){
54     if (out == null) {
55       String fname = getReportFileName("report.xml.file") + ".xml";
56       try {
57         out = new PrintWriter(fname);
58       } catch (FileNotFoundException fnfx) {
59         // log here
60       }
61     }
62   }
63
64   @Override
65   protected void closeChannel() {
66     if (out != null){
67       out.close();
68       out = null;
69     }
70   }
71   
72   
73   @Override
74   protected void publishProlog() {
75     out.println("<?xml version=\"1.0\" ?>");
76     out.println("<jpfreport>");
77   }
78   
79   @Override
80   public void publishTopicStart(String topic) {
81     out.println("  <" + topic + ">");
82   }
83   
84   @Override
85   public void publishTopicEnd(String topic) {
86     out.println("  </" + topic + ">");
87   }  
88   
89   @Override
90   protected void publishEpilog() {
91     out.println("</jpfreport>");
92   }
93   
94   @Override
95   protected void publishJPF() {
96     out.println("  <jpf-version>" + JPF.VERSION + "</jpf-version>");
97   }
98
99   @Override
100   protected void publishJPFConfig() {
101     TreeMap<Object,Object> map = conf.asOrderedMap();
102     Set<Map.Entry<Object,Object>> eSet = map.entrySet();
103
104     out.println("  <jpf-properties>");
105
106     for (Object src : conf.getSources()){
107       out.println("    <source value=\"" + conf.getSourceName(src) + "\"/>");
108     }    
109     
110     for (Map.Entry<Object,Object> e : eSet) {
111       out.println("    <entry key=\"" + e.getKey() + "\" value=\"" + e.getValue() + "\"/>");
112     }      
113     out.println("  </jpf-properties>");
114     
115   }
116
117   @Override
118   protected void publishPlatform() {
119     out.println("  <platform>");
120     out.println("    <hostname>" + reporter.getHostName() + "</hostname>");
121     out.println("    <arch>" + reporter.getArch() + "</arch>");
122     out.println("    <os>" + reporter.getOS() + "</os>");
123     out.println("    <java>" + reporter.getJava() + "</java>");    
124     out.println("  </platform>");
125   }
126
127   @Override
128   protected void publishUser() {
129     out.println("  <user>" + reporter.getUser() + "</user>");
130   }
131
132   @Override
133   protected void publishDTG() {
134     out.println("  <started>" + reporter.getStartDate() + "</started>");
135   }
136   
137   @Override
138   protected void publishSuT() {
139     out.println("  <sut>");
140     String mainCls = reporter.getSuT();
141     if (mainCls != null) {
142       String mainPath = reporter.getSuT();
143       if (mainPath != null) {
144         out.println("    <source>" + mainPath + "</source>");
145
146         RepositoryEntry rep = RepositoryEntry.getRepositoryEntry(mainPath);
147         if (rep != null) {
148           out.println("    <repository>" + rep.getRepository() + "</repository>");
149           out.println("    <revision>" + rep.getRevision() + "</revision>");
150         }
151       } else {
152         out.println("    <binary>" + mainCls + ".class" + "</binary>");
153       }
154     } else {
155       // no app specified
156     }
157     out.println("  </sut>");
158   }
159
160   @Override
161   protected void publishResult() {
162     List<Error> errors = reporter.getErrors();
163     
164     out.print("  <result findings=\"");
165     if (errors.isEmpty()){
166       out.println("none\"/>");
167     } else {
168       out.println("errors\">");
169       int i=0;
170       for (Error e : errors) {
171         out.print("    <error id=\"");
172         out.print(i++);
173         out.println("\">");
174         out.print("      <property>");
175         out.print(e.getProperty().getClass().getName());
176         out.println("</property>");
177         out.print("      <details>");
178         out.print(e.getDetails());
179         out.println("      </details>");
180         out.println("    </error>");
181       }
182       out.println("  </result>");
183     }
184   }
185
186   // not sure how much effort we want to put into readability here
187   @Override
188   protected void publishTrace() {
189     Path path = reporter.getPath();
190     int i=0;
191
192     if (path.size() == 0) {
193       return; // nothing to publish
194     }
195     
196     out.println("  <trace>");
197     for (Transition t : path) {
198       ChoiceGenerator<?> cg = t.getChoiceGenerator();
199       out.println("    <transition id=\"" + i++ + "\" thread=\"" + t.getThreadIndex() + "\">");
200       out.println("      <cg class=\""+cg.getClass().getName() + "\" choice=\"" +
201                   cg.getProcessedNumberOfChoices() + "\"/>");
202       for (Step s : t) {
203         out.print("      <insn src=\"" + s.getLocationString() + "\">");
204         String insn = s.getInstruction().toString();
205         if (insn.indexOf('<') >= 0) { // <init> and <clinit> clash with XML
206           insn = insn.replaceAll("<", "&lt;");
207           insn = insn.replaceAll(">", "&gt;");
208         }
209         out.print(insn);
210         out.println("</insn>");
211       }
212       out.println("    </transition>");      
213     }
214     out.println("  </trace>");
215   }
216
217   @Override
218   protected void publishOutput() {
219     Path path = reporter.getPath();
220
221     if (path.size() == 0) {
222       return; // nothing to publish
223     }
224         
225     if (path.hasOutput()) {
226       out.println("  <output>");
227       for (Transition t : path) {
228         String s = t.getOutput();
229         if (s != null){
230           out.print(s);
231         }
232       }
233       out.println("  </output>");
234     }
235   }
236   
237   @Override
238   protected void publishSnapshot() {
239     VM vm = reporter.getVM();
240     
241     out.println("  <live-threads>");
242     for (ThreadInfo ti : vm.getLiveThreads()) {
243       out.println("    <thread id=\"" + ti.getId() + "\" name=\"" + ti.getName()
244                   + "\" status=\"" + ti.getStateName() + "\">");
245       // owned locks
246       for (ElementInfo e : ti.getLockedObjects()) {
247         out.println("      <lock-owned object=\"" + e + "\"/>");
248       }
249       // requested locks
250       ElementInfo ei = ti.getLockObject();
251       if (ei != null) {
252         out.println("      <lock-request object=\"" + ei + "\"/>");
253       }
254       // stack frames
255       for (StackFrame frame : ti){
256         if (!frame.isDirectCallFrame()){
257           out.println("      <frame>" + frame.getStackTraceInfo() + "</frame>");
258         }
259       }
260       out.println("    </thread>");
261     }
262     out.println("  </live-threads>");
263   }
264
265   @Override
266   protected void publishStatistics() {
267     Statistics stat = reporter.getStatistics();
268     out.println("  <statistics>");
269     out.println("    <elapsed-time>" + formatHMS(reporter.getElapsedTime()) + "</elapsed-time>");
270     out.println("    <new-states>" + stat.newStates + "</new-states>");
271     out.println("    <visited-states>" + stat.visitedStates + "</visited-states>");
272     out.println("    <backtracked-states>" + stat.backtracked + "</backtracked-states>");
273     out.println("    <end-states>" + stat.endStates + "</end-states>");
274     out.println("    <max-memory unit=\"MB\">" + (stat.maxUsed >>20) + "</max-memory>");
275     out.println("  </statistics>");
276   }
277
278 }