|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.s60tools.crashanalyser.containers; |
|
19 |
|
20 import org.w3c.dom.Element; |
|
21 import org.w3c.dom.Node; |
|
22 import org.w3c.dom.NodeList; |
|
23 import org.w3c.dom.NamedNodeMap; |
|
24 import java.io.*; |
|
25 import com.nokia.s60tools.crashanalyser.model.XmlUtils; |
|
26 import java.util.*; |
|
27 |
|
28 /** |
|
29 * A process class. Contains all process information. |
|
30 * This class owns this process' threads and code segments |
|
31 * |
|
32 */ |
|
33 public final class Process { |
|
34 |
|
35 // XML tags |
|
36 public static final String TAG_ID = "id"; |
|
37 public static final String TAG_NAME = "name"; |
|
38 public static final String TAG_UID1 = "uid1"; |
|
39 public static final String TAG_UID2 = "uid2"; |
|
40 public static final String TAG_UID3 = "uid3"; |
|
41 public static final String TAG_SID = "sid"; |
|
42 public static final String TAG_LINK = "link"; |
|
43 public static final String ATTRIBUTE_SEG = "seg"; |
|
44 public static final String SEGMENT_THREADS = "seg_threads"; |
|
45 public static final String SEGMENT_CODESEGS = "seg_codesegs"; |
|
46 |
|
47 public static enum StackItems {ALL, SYMBOLS, ACCURATE}; |
|
48 |
|
49 static final String FORMAT = "%-13s: %s"; |
|
50 |
|
51 // process data |
|
52 private final int processId; |
|
53 private final String processName; |
|
54 private final String processUid1; |
|
55 private final String processUid2; |
|
56 private final String processUid3; |
|
57 private final String processSid; |
|
58 private final List<Thread> processThreads; |
|
59 private final List<CodeSegment> processCodeSegments; |
|
60 |
|
61 /** |
|
62 * Constructor |
|
63 * @param id process id |
|
64 * @param name process name |
|
65 * @param uid1 process UID1 |
|
66 * @param uid2 process UID2 |
|
67 * @param uid3 process UID3 |
|
68 * @param sid process SID |
|
69 * @param threads threads of the process |
|
70 * @param codeSegments code segments of the process |
|
71 */ |
|
72 private Process(int id, String name, String uid1, String uid2, String uid3, String sid, |
|
73 List<Thread> threads, List<CodeSegment> codeSegments) { |
|
74 processId = id; |
|
75 processName = name; |
|
76 processUid1 = uid1; |
|
77 processUid2 = uid2; |
|
78 processUid3 = uid3; |
|
79 processSid = sid; |
|
80 processThreads = threads; |
|
81 processCodeSegments = codeSegments; |
|
82 } |
|
83 |
|
84 public int getId() { |
|
85 return processId; |
|
86 } |
|
87 |
|
88 public String getName() { |
|
89 return processName; |
|
90 } |
|
91 |
|
92 public List<CodeSegment> getCodeSegments() { |
|
93 return processCodeSegments; |
|
94 } |
|
95 |
|
96 /** |
|
97 * Writes process data into given buffer (i.e text file) |
|
98 * @param out buffer to write to |
|
99 * @param stackItems |
|
100 * @param html defines whether html format should be written |
|
101 * @throws IOException |
|
102 */ |
|
103 public void writeTo(BufferedWriter out, StackItems stackItems, boolean html) throws IOException { |
|
104 |
|
105 // write basic process data |
|
106 writeLine(out,""); |
|
107 writeLine(out, "PROCESS:"); |
|
108 writeLine(out, "--------"); |
|
109 writeLine(out, "Process Name", processName); |
|
110 writeLine(out, "Uid1", processUid1); |
|
111 writeLine(out, "Uid2", processUid2); |
|
112 writeLine(out, "Uid3", processUid3); |
|
113 writeLine(out, "Sid", processSid); |
|
114 writeLine(out, ""); |
|
115 |
|
116 // write code segments of the process |
|
117 if (processCodeSegments != null && !processCodeSegments.isEmpty()) { |
|
118 writeLine(out, "CODE SEGMENTS:"); |
|
119 writeLine(out, "--------------"); |
|
120 for (int i = 0; i < processCodeSegments.size(); i++) { |
|
121 CodeSegment codeSegment = processCodeSegments.get(i); |
|
122 codeSegment.writeTo(out); |
|
123 } |
|
124 writeLine(out, ""); |
|
125 } |
|
126 |
|
127 // write threads of the process |
|
128 if (processThreads != null && !processThreads.isEmpty()) { |
|
129 for (int i = 0; i < processThreads.size(); i++) { |
|
130 Thread thread = processThreads.get(i); |
|
131 thread.writeTo(out, stackItems, html); |
|
132 writeLine(out, ""); |
|
133 } |
|
134 writeLine(out, ""); |
|
135 } |
|
136 } |
|
137 |
|
138 void writeLine(BufferedWriter out, String line) throws IOException { |
|
139 out.write(line); |
|
140 out.newLine(); |
|
141 } |
|
142 |
|
143 void writeLine(BufferedWriter out, String header, String value) throws IOException { |
|
144 if (!"".equals(value)) { |
|
145 out.write(String.format(FORMAT, header, value)); |
|
146 out.newLine(); |
|
147 } |
|
148 } |
|
149 |
|
150 /** |
|
151 * Reads and creates a process from process xml element |
|
152 * @param elementProcess |
|
153 * @param threads |
|
154 * @param codeSegments |
|
155 * @return created process or null |
|
156 */ |
|
157 public static Process read(Element elementProcess, |
|
158 Map<Integer, Thread> threads, |
|
159 Map<Integer, CodeSegment> codeSegments) { |
|
160 try { |
|
161 if (threads == null || threads.isEmpty()) |
|
162 return null; |
|
163 |
|
164 // read process id |
|
165 String processId = XmlUtils.getTextValue(elementProcess, TAG_ID); |
|
166 if (processId == null) |
|
167 return null; |
|
168 |
|
169 // convert process id to integer |
|
170 int id = Integer.parseInt(processId); |
|
171 |
|
172 // read process name |
|
173 String processName = XmlUtils.getTextValue(elementProcess, TAG_NAME); |
|
174 if (processName == null) |
|
175 return null; |
|
176 |
|
177 // read UID1 if exists |
|
178 String uid1 = XmlUtils.getTextValue(elementProcess, TAG_UID1); |
|
179 if (uid1 == null) |
|
180 uid1 = ""; |
|
181 |
|
182 // read UID2 if exists |
|
183 String uid2 = XmlUtils.getTextValue(elementProcess, TAG_UID2); |
|
184 if (uid2 == null) |
|
185 uid2 = ""; |
|
186 |
|
187 // read UID# if exists |
|
188 String uid3 = XmlUtils.getTextValue(elementProcess, TAG_UID3); |
|
189 if (uid3 == null) |
|
190 uid3 = ""; |
|
191 |
|
192 // read SID if exists |
|
193 String sid = XmlUtils.getTextValue(elementProcess, TAG_SID); |
|
194 if (sid == null) |
|
195 sid = ""; |
|
196 |
|
197 // get link nodes for thread and codesegment ids |
|
198 NodeList nl = elementProcess.getElementsByTagName(TAG_LINK); |
|
199 if (nl == null || nl.getLength() < 1) |
|
200 return null; |
|
201 |
|
202 List<Thread> processThreads = new ArrayList<Thread>(); |
|
203 List<CodeSegment> processCodesegments = new ArrayList<CodeSegment>(); |
|
204 |
|
205 // read threads and code segments |
|
206 for (int i = 0; i < nl.getLength(); i++) { |
|
207 Node node = nl.item(i); |
|
208 String nodeValue = XmlUtils.getNodeValue(node); |
|
209 NamedNodeMap attributes = node.getAttributes(); |
|
210 if (attributes != null && attributes.getLength() > 0) { |
|
211 Node seg = attributes.getNamedItem(ATTRIBUTE_SEG); |
|
212 // thread id |
|
213 if (SEGMENT_THREADS.equals(XmlUtils.getNodeValue(seg))) { |
|
214 int tId = Integer.parseInt(nodeValue); |
|
215 if (threads.containsKey(tId)) |
|
216 processThreads.add(threads.get(tId)); |
|
217 // codesegment id |
|
218 } else if (SEGMENT_CODESEGS.equals(XmlUtils.getNodeValue(seg))) { |
|
219 int segmentId = Integer.parseInt(nodeValue); |
|
220 if (codeSegments.containsKey(segmentId)) |
|
221 processCodesegments.add(codeSegments.get(segmentId)); |
|
222 } |
|
223 } |
|
224 } |
|
225 |
|
226 if (processThreads.isEmpty()) |
|
227 return null; |
|
228 |
|
229 return new Process(id, processName, uid1, uid2, uid3, sid, processThreads, processCodesegments); |
|
230 |
|
231 } catch (Exception e) { |
|
232 return null; |
|
233 } |
|
234 } |
|
235 |
|
236 /** |
|
237 * Returns the first thread of this process |
|
238 * @return first thread of this process or null |
|
239 */ |
|
240 public Thread getFirstThread() { |
|
241 Thread thread = null; |
|
242 if (processThreads != null && !processThreads.isEmpty()) |
|
243 thread = processThreads.get(0); |
|
244 |
|
245 return thread; |
|
246 } |
|
247 |
|
248 /** |
|
249 * Returns the threads of this process |
|
250 * @return threads of this process or null |
|
251 */ |
|
252 public List<Thread> getThreads() { |
|
253 return processThreads; |
|
254 } |
|
255 } |