21 import java.io.*; |
21 import java.io.*; |
22 import javax.xml.parsers.*; |
22 import javax.xml.parsers.*; |
23 import org.eclipse.jface.resource.ImageDescriptor; |
23 import org.eclipse.jface.resource.ImageDescriptor; |
24 import org.eclipse.ui.*; |
24 import org.eclipse.ui.*; |
25 import org.w3c.dom.*; |
25 import org.w3c.dom.*; |
|
26 |
|
27 import com.nokia.s60tools.crashanalyser.containers.OstTrace; |
26 import com.nokia.s60tools.crashanalyser.containers.RegisterDetails; |
28 import com.nokia.s60tools.crashanalyser.containers.RegisterDetails; |
27 import com.nokia.s60tools.crashanalyser.containers.CodeSegment; |
29 import com.nokia.s60tools.crashanalyser.containers.CodeSegment; |
28 import com.nokia.s60tools.crashanalyser.containers.Message; |
30 import com.nokia.s60tools.crashanalyser.containers.Message; |
29 import com.nokia.s60tools.crashanalyser.containers.EventLog; |
31 import com.nokia.s60tools.crashanalyser.containers.EventLog; |
30 import com.nokia.s60tools.crashanalyser.containers.Process; |
32 import com.nokia.s60tools.crashanalyser.containers.Process; |
42 * A summary file is a crash file which has not been fully decoded. |
44 * A summary file is a crash file which has not been fully decoded. |
43 * A summary file has been decoded without symbol information and it therefore |
45 * A summary file has been decoded without symbol information and it therefore |
44 * does not contain stack information. A summary file is a base class for CrashFile. |
46 * does not contain stack information. A summary file is a base class for CrashFile. |
45 * |
47 * |
46 */ |
48 */ |
47 public class SummaryFile extends CrashAnalyserFile implements IEditorInput { |
49 public class SummaryFile extends CrashAnalyserFile implements IEditorInput, Cloneable { |
|
50 |
|
51 public enum ContentType {CRASH, REGMSG, REPORT}; |
48 |
52 |
49 // XML tags |
53 // XML tags |
50 public static final String TAG_SYMBOL_SET = "symbol_set"; |
54 public static final String TAG_SYMBOL_SET = "symbol_set"; |
51 public static final String TAG_SYMBOL = "symbol"; |
55 public static final String TAG_SYMBOL = "symbol"; |
52 public static final String TAG_SOURCE = "source"; |
56 public static final String TAG_SOURCE = "source"; |
57 public static final String TAG_ID = "id"; |
61 public static final String TAG_ID = "id"; |
58 public static final String TAG_STACK_ENTRY = "stack_entry"; |
62 public static final String TAG_STACK_ENTRY = "stack_entry"; |
59 public static final String TAG_CODESEG = "codeseg"; |
63 public static final String TAG_CODESEG = "codeseg"; |
60 public static final String TAG_REGISTER_SET = "register_set"; |
64 public static final String TAG_REGISTER_SET = "register_set"; |
61 public static final String TAG_SEG_EVENT_LOG = "seg_event_log"; |
65 public static final String TAG_SEG_EVENT_LOG = "seg_event_log"; |
|
66 public static final String TAG_SEG_TRACES = "seg_traces"; |
62 public static final String TAG_MESSAGE = "message"; |
67 public static final String TAG_MESSAGE = "message"; |
63 public static final String TAG_VI_ENTRY = "vi_entry"; |
68 public static final String TAG_VI_ENTRY = "vi_entry"; |
64 public static final String TAG_SOURCE_INFO = "source_info"; |
69 public static final String TAG_SOURCE_INFO = "source_info"; |
65 public static final String TAG_TYPE = "type"; |
70 public static final String TAG_TYPE = "type"; |
66 public static final String TAG_SEGMENT = "segment"; |
71 public static final String TAG_SEGMENT = "segment"; |
72 protected Map<Integer, Message> messages = null; |
77 protected Map<Integer, Message> messages = null; |
73 protected Map<Integer, Stack> stacks = null; |
78 protected Map<Integer, Stack> stacks = null; |
74 protected Map<Integer, RegisterSet> registerSets = null; |
79 protected Map<Integer, RegisterSet> registerSets = null; |
75 protected List<RegisterDetails> registerDetails = null; |
80 protected List<RegisterDetails> registerDetails = null; |
76 protected EventLog eventLog = null; |
81 protected EventLog eventLog = null; |
|
82 protected OstTrace ostTrace = null; |
77 protected Summary crashSummary = null; |
83 protected Summary crashSummary = null; |
78 protected String sourceFileType = ""; |
84 protected String sourceFileType = ""; |
79 protected String sourceFileName = ""; |
85 protected String sourceFileName = ""; |
80 protected String sourceFilePath = ""; |
86 protected String sourceFilePath = ""; |
81 |
87 |
|
88 |
82 /** |
89 /** |
83 * Constructor |
90 * Constructor |
84 * @param filePath file path to this crash file |
91 * @param filePath file path to this crash file |
85 * @param library error library |
92 * @param library error library |
86 */ |
93 */ |
87 protected SummaryFile(String filePath, ErrorLibrary library) { |
94 protected SummaryFile(String filePath, ErrorLibrary library) { |
88 super(filePath, library); |
95 super(filePath, library); |
89 } |
96 } |
90 |
97 |
91 /** |
98 /** |
|
99 * Constructor |
|
100 * @param filePath file path to this crash file |
|
101 * @param library error library |
|
102 */ |
|
103 protected SummaryFile(String filePath, ErrorLibrary library, Thread thread) { |
|
104 super(filePath, library); |
|
105 threadInfo = thread; |
|
106 } |
|
107 |
|
108 public Object clone() { |
|
109 SummaryFile newSummaryFile = null; |
|
110 try { |
|
111 // Just shallow copy (i.e. no need to read information from file) |
|
112 newSummaryFile = (SummaryFile) super.clone(); |
|
113 } catch (CloneNotSupportedException ex) { |
|
114 // ignore |
|
115 } |
|
116 return newSummaryFile; |
|
117 } |
|
118 |
|
119 |
|
120 |
|
121 /** |
92 * Returns the file type of this crash file. |
122 * Returns the file type of this crash file. |
93 * @return "Decoded File" |
123 * @return "Decoded File" |
94 */ |
124 */ |
95 public String getFileType() { |
125 public String getFileType() { |
96 return "Partially Decoded File"; |
126 return "Partially Decoded File"; |
104 return sourceFileName; |
134 return sourceFileName; |
105 } |
135 } |
106 |
136 |
107 public String getSourceFilePath() { |
137 public String getSourceFilePath() { |
108 return sourceFilePath; |
138 return sourceFilePath; |
|
139 } |
|
140 |
|
141 |
|
142 public void setThread(Thread thread) { |
|
143 threadInfo = thread; |
|
144 panicCategory = threadInfo.getExitCategory(); |
|
145 panicCode = threadInfo.getExitReason(); |
|
146 threadName = threadInfo.getFullName(); |
109 } |
147 } |
110 |
148 |
111 public List<Stack> getStandAloneStacks() { |
149 public List<Stack> getStandAloneStacks() { |
112 if (stacks != null && !stacks.isEmpty()) { |
150 if (stacks != null && !stacks.isEmpty()) { |
113 return new ArrayList<Stack>(stacks.values()); |
151 return new ArrayList<Stack>(stacks.values()); |
139 } |
177 } |
140 return false; |
178 return false; |
141 } |
179 } |
142 |
180 |
143 /** |
181 /** |
|
182 * Returns the content type of the file. |
|
183 * @return Returns crash/registration/report. If not found returns crash. |
|
184 */ |
|
185 public ContentType getContentType() { |
|
186 List<Message> msgs = getMessages(); |
|
187 if (msgs != null && !msgs.isEmpty()) { |
|
188 for (int i = 0; i < msgs.size(); i++) { |
|
189 if (Message.MessageTypes.MESSAGE.equals(msgs.get(i).getMessageType()) && |
|
190 msgs.get(i).getTitle().equals("MobileCrash content type")) { |
|
191 if(msgs.get(i).getMessage().equals("registration")) |
|
192 return ContentType.REGMSG; |
|
193 else if (msgs.get(i).getMessage().equals("report")) |
|
194 return ContentType.REPORT; |
|
195 } |
|
196 } |
|
197 } |
|
198 // Returns crash by default. |
|
199 return ContentType.CRASH; |
|
200 } |
|
201 |
|
202 /** |
144 * Returns all messages |
203 * Returns all messages |
145 * @return all messages |
204 * @return all messages |
146 */ |
205 */ |
147 public List<Message> getMessages() { |
206 public List<Message> getMessages() { |
148 List<Message> msgs = new ArrayList<Message>(); |
207 List<Message> msgs = new ArrayList<Message>(); |
182 file.doRead(); |
241 file.doRead(); |
183 return file; |
242 return file; |
184 } |
243 } |
185 |
244 |
186 /** |
245 /** |
|
246 * Reads crash file |
|
247 * @param folder where xml file is |
|
248 * @param library error library |
|
249 * @param thread thread |
|
250 * @return read crash file or null |
|
251 */ |
|
252 public static SummaryFile read(String folder, ErrorLibrary library, Thread thread) { |
|
253 String summaryFile = findFile(folder,"xml"); |
|
254 |
|
255 // summary file doesn't exist |
|
256 if (summaryFile == null) |
|
257 return null; |
|
258 |
|
259 SummaryFile file = new SummaryFile(summaryFile, library, thread); |
|
260 file.doRead(); |
|
261 return file; |
|
262 } |
|
263 |
|
264 /** |
187 * Writes crash file into text or html file |
265 * Writes crash file into text or html file |
188 * @param filePathWithoutFileName file path where file is to be written to |
266 * @param filePathWithoutFileName file path where file is to be written to |
189 * @param html if false a .txt file is created. if true a .html file is created |
267 * @param html if false a .txt file is created. if true a .html file is created |
190 */ |
268 */ |
191 public void writeTo(String filePathWithoutFileName, boolean html) { |
269 public void writeTo(String filePathWithoutFileName, boolean html) { |
241 writeLine(out, "Stack Pointer", thread.getStackPointer()); |
319 writeLine(out, "Stack Pointer", thread.getStackPointer()); |
242 writeLine(out, "Link Register", thread.getLinkRegister()); |
320 writeLine(out, "Link Register", thread.getLinkRegister()); |
243 writeLine(out, "Program Counter", thread.getProgramCounter()); |
321 writeLine(out, "Program Counter", thread.getProgramCounter()); |
244 panicDescription = thread.getPanicDescription(); |
322 panicDescription = thread.getPanicDescription(); |
245 } |
323 } |
|
324 } else if (threadInfo != null) { |
|
325 Process threadProcess = getProcessByThread(threadInfo.getId()); |
|
326 |
|
327 if (threadProcess != null) |
|
328 writeLine(out, "Process", threadProcess.getName()); |
|
329 |
|
330 writeLine(out, "Thread", threadInfo.getFullName()); |
|
331 writeLine(out, "Stack Pointer", threadInfo.getStackPointer()); |
|
332 writeLine(out, "Link Register", threadInfo.getLinkRegister()); |
|
333 writeLine(out, "Program Counter", threadInfo.getProgramCounter()); |
|
334 panicDescription = threadInfo.getPanicDescription(); |
246 } |
335 } |
247 |
336 |
248 // write crash summary to file |
337 // write crash summary to file |
249 if (crashSummary != null) { |
338 if (crashSummary != null) { |
250 crashSummary.writeTo(out); |
339 crashSummary.writeTo(out); |
273 |
362 |
274 // write event log to file |
363 // write event log to file |
275 if (eventLog != null) |
364 if (eventLog != null) |
276 eventLog.writeTo(out); |
365 eventLog.writeTo(out); |
277 |
366 |
|
367 // write OST trace to file |
|
368 if (ostTrace != null) |
|
369 ostTrace.writeTo(out); |
|
370 |
278 // write process data to file |
371 // write process data to file |
279 if (process != null) { |
372 if (process != null) { |
280 process.writeTo(out, Process.StackItems.ALL, html); |
373 process.writeTo(out, Process.StackItems.ALL, html); |
281 out.newLine(); |
374 out.newLine(); |
282 } |
375 } |
450 nl = docEle.getElementsByTagName(TAG_SEG_EVENT_LOG); |
543 nl = docEle.getElementsByTagName(TAG_SEG_EVENT_LOG); |
451 if (nl != null && nl.getLength() > 0) { |
544 if (nl != null && nl.getLength() > 0) { |
452 eventLog = EventLog.read((Element)nl.item(0)); |
545 eventLog = EventLog.read((Element)nl.item(0)); |
453 } |
546 } |
454 |
547 |
|
548 // read OST traces |
|
549 nl = docEle.getElementsByTagName(TAG_SEG_TRACES); |
|
550 if (nl != null && nl.getLength() > 0) { |
|
551 ostTrace = OstTrace.read((Element)nl.item(0)); |
|
552 } |
|
553 |
455 // read messages from xml |
554 // read messages from xml |
456 nl = docEle.getElementsByTagName(TAG_MESSAGE); |
555 nl = docEle.getElementsByTagName(TAG_MESSAGE); |
457 if (nl != null && nl.getLength() > 0) { |
556 if (nl != null && nl.getLength() > 0) { |
458 for (int i = 0; i < nl.getLength(); i++) { |
557 for (int i = 0; i < nl.getLength(); i++) { |
459 Element el = (Element)nl.item(i); |
558 Element el = (Element)nl.item(i); |
590 if (!"".equals(crashSummary.getCrashDate()) && !"".equals(crashSummary.getCrashTime())) |
689 if (!"".equals(crashSummary.getCrashDate()) && !"".equals(crashSummary.getCrashTime())) |
591 time = crashSummary.getCrashDate() + " " + crashSummary.getCrashTime(); |
690 time = crashSummary.getCrashDate() + " " + crashSummary.getCrashTime(); |
592 |
691 |
593 // set panic data |
692 // set panic data |
594 Process process = getCrashedProcess(); |
693 Process process = getCrashedProcess(); |
|
694 processCount = getProcessCount(); |
595 if (process != null) { |
695 if (process != null) { |
596 Thread firstThread = process.getFirstThread(); |
696 Thread firstThread = process.getFirstThread(); |
597 if (firstThread != null) { |
697 if (firstThread != null) { |
598 panicCategory = firstThread.getExitCategory(); |
698 panicCategory = firstThread.getExitCategory(); |
599 panicCode = firstThread.getExitReason(); |
699 panicCode = firstThread.getExitReason(); |
600 threadName = firstThread.getFullName(); |
700 threadName = firstThread.getFullName(); |
601 } |
701 } |
|
702 } else if (threadInfo != null) { |
|
703 panicCategory = threadInfo.getExitCategory(); |
|
704 panicCode = threadInfo.getExitReason(); |
|
705 threadName = threadInfo.getFullName(); |
602 } |
706 } |
603 |
707 |
604 formatDescription(); |
708 formatDescription(); |
605 }catch(Exception e) { |
709 }catch(Exception e) { |
606 e.printStackTrace(); |
710 e.printStackTrace(); |
608 } |
712 } |
609 |
713 |
610 /** |
714 /** |
611 * Formats a description for this crash. |
715 * Formats a description for this crash. |
612 */ |
716 */ |
613 void formatDescription() { |
717 public void formatDescription() { |
614 Thread thread = null; |
718 Thread thread = null; |
615 |
719 |
|
720 if (threadInfo != null) { |
|
721 thread = threadInfo; |
|
722 } |
616 // get the first thread of the first process |
723 // get the first thread of the first process |
617 if (processes != null && !processes.isEmpty()) { |
724 else if (processes != null && !processes.isEmpty()) { |
618 Process[] processesArray = processes.values().toArray(new Process[processes.values().size()]); |
725 thread = getCrashedThread(); |
619 Process process = processesArray[0]; |
726 } |
620 thread = process.getFirstThread(); |
727 |
621 } |
728 if (thread != null) { |
622 |
729 description = HtmlFormatter.formatCrashFileDescription(crashSummary, getMessages(), thread); |
623 description = HtmlFormatter.formatCrashFileDescription(crashSummary, getMessages(), thread); |
730 shortDescription = HtmlFormatter.formatCrashFileDescription(crashSummary, null, thread); |
624 shortDescription = HtmlFormatter.formatCrashFileDescription(crashSummary, null, thread); |
731 } |
625 } |
732 } |
626 |
733 |
627 public Summary getSummary() { |
734 public Summary getSummary() { |
628 return crashSummary; |
735 return crashSummary; |
629 } |
736 } |
632 * Get crashed process |
739 * Get crashed process |
633 * |
740 * |
634 * @return first process or null |
741 * @return first process or null |
635 */ |
742 */ |
636 public Process getCrashedProcess() { |
743 public Process getCrashedProcess() { |
|
744 if (threadInfo != null) { |
|
745 return null; |
|
746 } |
|
747 |
637 Process crashedProcess = null; |
748 Process crashedProcess = null; |
638 if (processes != null && !processes.isEmpty()) { |
749 if (processes != null && !processes.isEmpty()) { |
639 Process[] processesArray = processes.values().toArray(new Process[processes.values().size()]); |
750 Process[] processesArray = processes.values().toArray(new Process[processes.values().size()]); |
640 for (Process process : processesArray) { |
751 for (Process process : processesArray) { |
641 for (Thread thread : process.getThreads()) { |
752 for (Thread thread : process.getThreads()) { |
648 } |
759 } |
649 } |
760 } |
650 return crashedProcess; |
761 return crashedProcess; |
651 } |
762 } |
652 |
763 |
|
764 /** |
|
765 * Get crashed process |
|
766 * |
|
767 * @return first crashed thread |
|
768 */ |
|
769 public Thread getCrashedThread() { |
|
770 if (threadInfo != null) { |
|
771 return null; |
|
772 } |
|
773 |
|
774 Thread crashedThread = null; |
|
775 if (processes != null && !processes.isEmpty()) { |
|
776 Process[] processesArray = processes.values().toArray(new Process[processes.values().size()]); |
|
777 for (Process process : processesArray) { |
|
778 for (Thread thread : process.getThreads()) { |
|
779 String exitType = thread.getExitType(); |
|
780 if (exitType.equalsIgnoreCase("Panic") || exitType.equalsIgnoreCase("Exception")) { |
|
781 crashedThread = thread; |
|
782 break; |
|
783 } |
|
784 } |
|
785 } |
|
786 } |
|
787 return crashedThread; |
|
788 } |
|
789 |
|
790 /** |
|
791 * Get process by thread id |
|
792 * |
|
793 * @return Found process or null |
|
794 */ |
|
795 public Process getProcessByThread(int threadId) { |
|
796 |
|
797 Process threadProcess = null; |
|
798 if (processes != null && !processes.isEmpty()) { |
|
799 Process[] processesArray = processes.values().toArray(new Process[processes.values().size()]); |
|
800 for (Process process : processesArray) { |
|
801 for (Thread thread : process.getThreads()) { |
|
802 //String exitType = thread.getExitType(); |
|
803 if (thread.getId() == threadId) { |
|
804 threadProcess = process; |
|
805 break; |
|
806 } |
|
807 } |
|
808 } |
|
809 } |
|
810 return threadProcess; |
|
811 } |
|
812 |
|
813 /** |
|
814 * Get process count |
|
815 * |
|
816 * @return the number of processes or -1 if not available |
|
817 */ |
|
818 public int getProcessCount() |
|
819 { |
|
820 if (processes == null) { |
|
821 processCount = -1; |
|
822 } |
|
823 else { |
|
824 processCount = processes.size(); |
|
825 } |
|
826 return processCount; |
|
827 } |
|
828 |
|
829 /** |
|
830 * Get process count |
|
831 * |
|
832 * @return the number of threads or -1 if not available |
|
833 */ |
|
834 public int getTotalThreadCount() |
|
835 { |
|
836 totalThreadCount = 0; |
|
837 if (processes == null) { |
|
838 return -1; |
|
839 } |
|
840 for(Process process : processes.values()) { |
|
841 totalThreadCount += process.getThreads().size(); |
|
842 } |
|
843 return totalThreadCount; |
|
844 } |
|
845 |
|
846 /** |
|
847 * Returns all threads |
|
848 * |
|
849 * @return all threads in all processes |
|
850 */ |
|
851 public List<Thread> getThreads() { |
|
852 List<Thread> allThreads = new ArrayList<Thread>(); |
|
853 for(Process process : processes.values()) { |
|
854 allThreads.addAll(process.getThreads()); |
|
855 } |
|
856 return allThreads; |
|
857 } |
|
858 |
653 public EventLog getEventLog() { |
859 public EventLog getEventLog() { |
654 return eventLog; |
860 return eventLog; |
655 } |
861 } |
656 |
862 |
|
863 public OstTrace getOstTrace() { |
|
864 return ostTrace; |
|
865 } |
|
866 |
657 public List<RegisterDetails> getRegisterDetails() { |
867 public List<RegisterDetails> getRegisterDetails() { |
658 return registerDetails; |
868 return registerDetails; |
659 } |
869 } |
660 |
870 |
661 public boolean exists() { |
871 public boolean exists() { |