|
1 /* |
|
2 * Copyright (c) 2009 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 * The class CXmlFileDocument is part of CrashAnalyser XmlFilePlugin plugin. |
|
16 * Container and output implementation for data in XML File format. |
|
17 * XML format is an intermediate file used in the MobileCrash server |
|
18 * CXmlFileSink creates an instance of this class and uses it to output |
|
19 * crash data to file in XML format. |
|
20 * |
|
21 */ |
|
22 |
|
23 using System; |
|
24 using System.Collections.Generic; |
|
25 using System.Text; |
|
26 using System.Xml; |
|
27 |
|
28 using CrashItemLib.Crash.Base; |
|
29 using CrashItemLib.Crash.Processes; |
|
30 using CrashItemLib.Crash.Container; |
|
31 using System.IO; |
|
32 using CrashItemLib.Sink; |
|
33 |
|
34 namespace XmlFilePlugin.PluginImplementations.FileFormat |
|
35 { |
|
36 internal class CXmlFileDocument |
|
37 { |
|
38 #region Constructors |
|
39 public CXmlFileDocument() |
|
40 |
|
41 { |
|
42 } |
|
43 |
|
44 #endregion |
|
45 |
|
46 /** Creates a new datablock and inputs data from container to the datablock */ |
|
47 public void ReadDataFromContainer(CISinkSerializationParameters aParams) |
|
48 { |
|
49 CIContainer container = aParams.Container; |
|
50 |
|
51 //Create a datablock for this container's contents |
|
52 CXmlDataBlock datablock = new CXmlDataBlock(); |
|
53 |
|
54 //Read all interesting data from container to the datablock |
|
55 datablock.AddHeader(container); |
|
56 datablock.AddSWInfos(container); |
|
57 datablock.AddThreadAndExitInfo(container); |
|
58 datablock.AddPanicedProcess(container); |
|
59 datablock.AddRegisterLists(container); |
|
60 datablock.AddStacks(container); |
|
61 datablock.AddCodeSegments(container); |
|
62 datablock.AddMemoryInfo(container); |
|
63 datablock.AddHWInfo(container); |
|
64 datablock.AddTelephony(container); |
|
65 datablock.AddEnvInfo(container); |
|
66 datablock.AddReportParameters(container); |
|
67 datablock.AddMessages(container); |
|
68 datablock.AddCrashHash(container); |
|
69 |
|
70 string archivedFileName = (String)aParams.OperationData1; |
|
71 datablock.AddFileNames(container, archivedFileName); |
|
72 datablock.AddEventlog(container); |
|
73 |
|
74 datablock.AddOstTraces(container); |
|
75 |
|
76 //If all went well, we will add datablock to stored datablocks |
|
77 iDatablocks.Add(datablock); |
|
78 } |
|
79 |
|
80 public void WriteToXmlStream(XmlWriter aOutput) |
|
81 { |
|
82 System.Diagnostics.Debug.Assert(aOutput != null); |
|
83 |
|
84 WriteHeader(aOutput); |
|
85 |
|
86 if (iDatablocks.Count > 0) |
|
87 { |
|
88 WriteReport(aOutput); |
|
89 } |
|
90 |
|
91 WriteFooter(aOutput); |
|
92 } |
|
93 |
|
94 /** |
|
95 * Writes as plain text. |
|
96 */ |
|
97 public void WriteToPlainTextStream(StreamWriter aOutput) |
|
98 { |
|
99 PlainTextOutput.Write(aOutput, iDatablocks); |
|
100 } |
|
101 |
|
102 private void WriteReport(XmlWriter aOutput) |
|
103 { |
|
104 CXmlDataBlock datablock = iDatablocks[0]; |
|
105 |
|
106 aOutput.WriteStartElement(XmlConsts.Kxml_report); |
|
107 |
|
108 WriteDevice(aOutput, datablock); |
|
109 WriteReportDetails(aOutput, datablock); |
|
110 |
|
111 aOutput.WriteEndElement(); |
|
112 } |
|
113 |
|
114 |
|
115 private static void WriteDevice(XmlWriter aOutput, CXmlDataBlock datablock) |
|
116 { |
|
117 // Device |
|
118 aOutput.WriteStartElement(XmlConsts.Kxml_device); |
|
119 |
|
120 if (datablock.Platform().Equals(XmlConsts.Kxml_sos)) |
|
121 { |
|
122 aOutput.WriteAttributeString(XmlConsts.Kxml_platform, XmlConsts.Kxml_s60); |
|
123 } |
|
124 else |
|
125 { |
|
126 aOutput.WriteAttributeString(XmlConsts.Kxml_platform, datablock.Platform()); |
|
127 } |
|
128 |
|
129 aOutput.WriteAttributeString(XmlConsts.Kxml_code, datablock.ProductType()); |
|
130 aOutput.WriteAttributeString(XmlConsts.Kxml_version, datablock.SWVersion()); |
|
131 |
|
132 if (datablock.RomId() != null) |
|
133 { |
|
134 aOutput.WriteAttributeString(XmlConsts.Kxml_romid, datablock.RomId().ToString()); |
|
135 } |
|
136 |
|
137 // variant is not written. |
|
138 |
|
139 if (datablock.Imei() != string.Empty) |
|
140 { |
|
141 aOutput.WriteAttributeString(XmlConsts.Kxml_imei, datablock.Imei()); |
|
142 } |
|
143 |
|
144 // Write additional device details here if exist. |
|
145 |
|
146 aOutput.WriteEndElement(); |
|
147 } |
|
148 |
|
149 private static void WriteHeader(XmlWriter aOutput) |
|
150 { |
|
151 aOutput.WriteStartDocument(); |
|
152 aOutput.WriteDocType(XmlConsts.Kxml_report, null, XmlConsts.Kxml_doctype, null); |
|
153 } |
|
154 |
|
155 private static void WriteFooter(XmlWriter aOutput) |
|
156 { |
|
157 aOutput.WriteEndDocument(); |
|
158 } |
|
159 |
|
160 private static void WriteReportDetails(XmlWriter aOutput, CXmlDataBlock datablock) |
|
161 { |
|
162 // Device report details |
|
163 aOutput.WriteStartElement(XmlConsts.Kxml_report_details); |
|
164 aOutput.WriteAttributeString(XmlConsts.Kxml_timestamp, datablock.TimeStampText()); |
|
165 |
|
166 string crashtypestr = "Not found"; |
|
167 if(datablock.FileType() == XmlConsts.MobileCrashFileType.ETypeBasicCrash) |
|
168 { |
|
169 crashtypestr = XmlConsts.Kxml_type_crash; |
|
170 } |
|
171 else if (datablock.FileType() == XmlConsts.MobileCrashFileType.ETypeAliveMessage) |
|
172 { |
|
173 crashtypestr = XmlConsts.Kxml_type_alivemsg; |
|
174 } |
|
175 else if (datablock.FileType() == XmlConsts.MobileCrashFileType.ETypeCrashAPIReport) |
|
176 { |
|
177 crashtypestr = XmlConsts.Kxml_type_report; |
|
178 } |
|
179 else if (datablock.FileType() == XmlConsts.MobileCrashFileType.ETypeRegistrationMessage) |
|
180 { |
|
181 crashtypestr = XmlConsts.Kxml_type_regmsg; |
|
182 } |
|
183 |
|
184 aOutput.WriteAttributeString(XmlConsts.Kxml_type, crashtypestr); |
|
185 |
|
186 aOutput.WriteAttributeString(XmlConsts.Kxml_file_name, datablock.BinFilename()); |
|
187 |
|
188 if (crashtypestr.Equals(XmlConsts.Kxml_type_report)) |
|
189 { |
|
190 aOutput.WriteAttributeString(XmlConsts.Kxml_report_category, datablock.ReportCategory()); |
|
191 } |
|
192 |
|
193 if (crashtypestr.Equals(XmlConsts.Kxml_type_report)) |
|
194 { |
|
195 aOutput.WriteAttributeString(XmlConsts.Kxml_report_type, datablock.ReportType()); |
|
196 } |
|
197 |
|
198 if (datablock.CrashedModuleName() != string.Empty) |
|
199 { |
|
200 aOutput.WriteAttributeString(XmlConsts.Kxml_crashed_module, datablock.CrashedModuleName()); |
|
201 } |
|
202 |
|
203 if (datablock.Hash() != string.Empty) |
|
204 { |
|
205 aOutput.WriteAttributeString(XmlConsts.Kxml_defect_hash, datablock.Hash()); |
|
206 } |
|
207 |
|
208 // Child elements for report details |
|
209 if (datablock.CodeSegs().Count > 0) |
|
210 { |
|
211 aOutput.WriteStartElement(XmlConsts.Kxml_loaded_dlls); |
|
212 } |
|
213 foreach (CXmlCodeSegItem codeseg in datablock.CodeSegs()) |
|
214 { |
|
215 aOutput.WriteStartElement(XmlConsts.Kxml_loaded_dll); |
|
216 aOutput.WriteAttributeString(XmlConsts.Kxml_name, codeseg.Name); |
|
217 aOutput.WriteAttributeString(XmlConsts.Kxml_start_address, codeseg.Start.ToString()); |
|
218 aOutput.WriteAttributeString(XmlConsts.Kxml_end_address, codeseg.End.ToString()); |
|
219 aOutput.WriteEndElement(); // loaded dll |
|
220 } |
|
221 |
|
222 if (datablock.CodeSegs().Count > 0) |
|
223 { |
|
224 aOutput.WriteEndElement(); // loaded dlls |
|
225 } |
|
226 |
|
227 // Traces |
|
228 if(datablock.RegStorage().BasicRegs().Registers.Count > 0 || |
|
229 datablock.CallStacks().Count > 0 || |
|
230 datablock.OstTraces().Count > 0 || |
|
231 datablock.Eventlog().Count > 0 || |
|
232 datablock.RegStorage().OtherRegLists().Count > 0) |
|
233 { |
|
234 aOutput.WriteStartElement(XmlConsts.Kxml_traces); |
|
235 } |
|
236 |
|
237 WriteDetail(aOutput, XmlConsts.Kxml_register, datablock.RegStorage().BasicRegs().ToString()); |
|
238 |
|
239 // Extra registers |
|
240 System.Text.StringBuilder extraRegisters = new System.Text.StringBuilder(); |
|
241 foreach (CXmlRegisterStorage.CCrashInfoRegisterList registerList in datablock.RegStorage().OtherRegLists()) |
|
242 { |
|
243 extraRegisters.AppendLine(registerList.ToPrettyString()); |
|
244 } |
|
245 WriteDetail(aOutput, XmlConsts.Kxml_register_extra, extraRegisters.ToString()); |
|
246 |
|
247 // Call stack |
|
248 foreach (XmlFilePlugin.FileFormat.CXmlCallStack stack in datablock.CallStacks()) |
|
249 { |
|
250 WriteDetail(aOutput, XmlConsts.Kxml_call_stack_text, stack.ToString()); |
|
251 } |
|
252 |
|
253 // OST traces |
|
254 System.Text.StringBuilder ostTraces = new System.Text.StringBuilder(); |
|
255 foreach (string line in datablock.OstTraces()) |
|
256 { |
|
257 ostTraces.AppendLine(line); |
|
258 } |
|
259 WriteDetail(aOutput, XmlConsts.Kxml_trace_data, ostTraces.ToString()); |
|
260 |
|
261 // Event log |
|
262 System.Text.StringBuilder eventLog = new System.Text.StringBuilder(); |
|
263 foreach (string line in datablock.Eventlog()) |
|
264 { |
|
265 eventLog.AppendLine(line); |
|
266 } |
|
267 WriteDetail(aOutput, XmlConsts.Kxml_eventlog, eventLog.ToString()); |
|
268 |
|
269 if (datablock.RegStorage().BasicRegs().Registers.Count > 0 || |
|
270 datablock.CallStacks().Count > 0 || |
|
271 datablock.OstTraces().Count > 0 || |
|
272 datablock.Eventlog().Count > 0 || |
|
273 datablock.RegStorage().OtherRegLists().Count > 0) |
|
274 { |
|
275 aOutput.WriteEndElement(); // traces |
|
276 } |
|
277 WriteDictionaryValues(aOutput, datablock); |
|
278 WriteUniqueValues(aOutput, datablock); |
|
279 |
|
280 aOutput.WriteEndElement(); // report details |
|
281 } |
|
282 |
|
283 |
|
284 private static void WriteDictionaryValues(XmlWriter aOutput, CXmlDataBlock datablock) |
|
285 { |
|
286 // Dictionary values |
|
287 aOutput.WriteStartElement(XmlConsts.Kxml_dictionary_values); |
|
288 |
|
289 WriteDetail(aOutput, XmlConsts.Kxml_panic_id, datablock.PanicId()); |
|
290 WriteDetail(aOutput, XmlConsts.Kxml_panic_category, datablock.PanicCategory()); |
|
291 WriteDetail(aOutput, XmlConsts.Kxml_panic_description, datablock.PanicDescription()); |
|
292 WriteDetail(aOutput, XmlConsts.Kxml_language, datablock.Language()); |
|
293 |
|
294 if (!datablock.Process().Equals(XmlConsts.Kxml_unknown_process)) |
|
295 { |
|
296 WriteDetail(aOutput, XmlConsts.Kxml_panicked_process, datablock.Process()); |
|
297 } |
|
298 |
|
299 WriteDetail(aOutput, XmlConsts.Kxml_network_country_code, datablock.NetworkCountry()); |
|
300 WriteDetail(aOutput, XmlConsts.Kxml_network_identity, datablock.NetworkIdentity()); |
|
301 WriteDetail(aOutput, XmlConsts.Kxml_s60version, datablock.S60Version()); |
|
302 WriteDetail(aOutput, XmlConsts.Kxml_product_code, datablock.ProductCode()); |
|
303 WriteDetail(aOutput, XmlConsts.Kxml_variant_version, datablock.VariantVersion()); |
|
304 |
|
305 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
306 aOutput.WriteAttributeString(XmlConsts.Kxml_name, XmlConsts.Kxml_file_type); |
|
307 if (datablock.ReportType() != string.Empty) |
|
308 { |
|
309 aOutput.WriteAttributeString(XmlConsts.Kxml_value, "1"); |
|
310 } |
|
311 else |
|
312 { |
|
313 aOutput.WriteAttributeString(XmlConsts.Kxml_value, "0"); |
|
314 } |
|
315 aOutput.WriteEndElement(); |
|
316 |
|
317 // Production mode |
|
318 if (datablock.ProductionMode() != -1) |
|
319 { |
|
320 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
321 aOutput.WriteAttributeString(XmlConsts.Kxml_name, XmlConsts.Kxml_production_mode); |
|
322 if (datablock.ProductionMode() == 1) |
|
323 { |
|
324 aOutput.WriteAttributeString(XmlConsts.Kxml_value, XmlConsts.Kxml_production_mode_value); |
|
325 } |
|
326 else |
|
327 { |
|
328 aOutput.WriteAttributeString(XmlConsts.Kxml_value, XmlConsts.Kxml_rnd_mode_value); |
|
329 } |
|
330 aOutput.WriteEndElement(); |
|
331 } |
|
332 |
|
333 // Crash source |
|
334 if (datablock.CrashSource() != -1) |
|
335 { |
|
336 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
337 aOutput.WriteAttributeString(XmlConsts.Kxml_name, XmlConsts.Kxml_crash_source); |
|
338 if (datablock.CrashSource() == 1) |
|
339 { |
|
340 aOutput.WriteAttributeString(XmlConsts.Kxml_value, XmlConsts.Kxml_crash_source_user); |
|
341 } |
|
342 else |
|
343 { |
|
344 aOutput.WriteAttributeString(XmlConsts.Kxml_value, XmlConsts.Kxml_crash_source_kernel); |
|
345 } |
|
346 aOutput.WriteEndElement(); |
|
347 } |
|
348 |
|
349 WriteSymbolFileNames(aOutput, datablock); |
|
350 |
|
351 |
|
352 aOutput.WriteEndElement(); // dictionary values |
|
353 } |
|
354 |
|
355 |
|
356 private static void WriteUniqueValues(XmlWriter aOutput, CXmlDataBlock datablock) |
|
357 { |
|
358 // Unique values |
|
359 aOutput.WriteStartElement(XmlConsts.Kxml_unique_values); |
|
360 |
|
361 // Hw version is not added because it doesn't exist. |
|
362 |
|
363 WriteDetail(aOutput, XmlConsts.Kxml_available_memory, datablock.FreeMemory()); |
|
364 |
|
365 if (datablock.RegStorage() != null && datablock.RegStorage().ProgramCounter() != null) |
|
366 { |
|
367 WriteDetail(aOutput, XmlConsts.Kxml_program_counter, datablock.RegStorage().ProgramCounter().Value); |
|
368 WriteDetail(aOutput, XmlConsts.Kxml_program_counter_symbol, datablock.RegStorage().ProgramCounter().Symbol); |
|
369 } |
|
370 |
|
371 WriteDetail(aOutput, XmlConsts.Kxml_misc_info, datablock.GetMiscInfo()); |
|
372 |
|
373 // Reporter not written. |
|
374 // Resetreason not written. |
|
375 |
|
376 WriteDetail(aOutput, XmlConsts.Kxml_uptime, datablock.Uptime()); |
|
377 WriteDetail(aOutput, XmlConsts.Kxml_siminfo, datablock.Imsi()); |
|
378 WriteDetail(aOutput, XmlConsts.Kxml_locinfo, datablock.LocInfo()); |
|
379 WriteDetail(aOutput, XmlConsts.Kxml_cellid, datablock.NetworkCell()); |
|
380 WriteDetail(aOutput, XmlConsts.Kxml_psninfo, datablock.SerialNumber()); |
|
381 WriteDetail(aOutput, XmlConsts.Kxml_uid, datablock.UID()); |
|
382 WriteDetail(aOutput, XmlConsts.Kxml_testset, datablock.TestSet()); |
|
383 WriteDetail(aOutput, XmlConsts.Kxml_diskinfo, datablock.DiskInfo()); |
|
384 WriteDetail(aOutput, XmlConsts.Kxml_phone_number, datablock.PhoneNumber()); |
|
385 |
|
386 WriteDetail(aOutput, XmlConsts.Kxml_report_ok, datablock.ReportOK()); |
|
387 WriteDetail(aOutput, XmlConsts.Kxml_report_fail, datablock.ReportFail()); |
|
388 WriteDetail(aOutput, XmlConsts.Kxml_report_param_name1, datablock.ReportParamName1()); |
|
389 WriteDetail(aOutput, XmlConsts.Kxml_report_param_value1, datablock.ReportParamValue1()); |
|
390 WriteDetail(aOutput, XmlConsts.Kxml_report_param_name2, datablock.ReportParamName2()); |
|
391 WriteDetail(aOutput, XmlConsts.Kxml_report_param_value2, datablock.ReportParamValue2()); |
|
392 WriteDetail(aOutput, XmlConsts.Kxml_report_param_name3, datablock.ReportParamName3()); |
|
393 WriteDetail(aOutput, XmlConsts.Kxml_report_param_value3, datablock.ReportParamValue3()); |
|
394 WriteDetail(aOutput, XmlConsts.Kxml_report_comments, datablock.ReportComments()); |
|
395 |
|
396 aOutput.WriteEndElement(); // unique values |
|
397 } |
|
398 |
|
399 |
|
400 private static void WriteSymbolFileNames(XmlWriter aOutput, CXmlDataBlock datablock) |
|
401 { |
|
402 List<string> symbolFiles = datablock.SymbolFiles(); |
|
403 |
|
404 string symbolfilenames = string.Empty; |
|
405 foreach (string fileName in symbolFiles) |
|
406 { |
|
407 if (symbolfilenames != string.Empty) |
|
408 { |
|
409 symbolfilenames = symbolfilenames + ", "; |
|
410 } |
|
411 symbolfilenames = symbolfilenames + Path.GetFileName(fileName); |
|
412 } |
|
413 |
|
414 WriteDetail(aOutput, XmlConsts.Kxml_symbol_file_name, symbolfilenames); |
|
415 } |
|
416 |
|
417 private static void WriteDetail(XmlWriter aOutput, string name, ulong? value) |
|
418 { |
|
419 if (value != null) |
|
420 { |
|
421 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
422 aOutput.WriteAttributeString(XmlConsts.Kxml_name, name); |
|
423 aOutput.WriteAttributeString(XmlConsts.Kxml_value, value.ToString()); |
|
424 aOutput.WriteEndElement(); |
|
425 } |
|
426 } |
|
427 |
|
428 private static void WriteDetail(XmlWriter aOutput, string name, double? value) |
|
429 { |
|
430 if (value != null) |
|
431 { |
|
432 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
433 aOutput.WriteAttributeString(XmlConsts.Kxml_name, name); |
|
434 aOutput.WriteAttributeString(XmlConsts.Kxml_value, value.ToString()); |
|
435 aOutput.WriteEndElement(); |
|
436 } |
|
437 } |
|
438 |
|
439 private static void WriteDetail(XmlWriter aOutput, string name, string value) |
|
440 { |
|
441 if (value != string.Empty) |
|
442 { |
|
443 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
444 aOutput.WriteAttributeString(XmlConsts.Kxml_name, name); |
|
445 aOutput.WriteAttributeString(XmlConsts.Kxml_value, value); |
|
446 aOutput.WriteEndElement(); |
|
447 } |
|
448 } |
|
449 |
|
450 private static void WriteDetail(XmlWriter aOutput, string name, int? value) |
|
451 { |
|
452 if (value != null) |
|
453 { |
|
454 aOutput.WriteStartElement(XmlConsts.Kxml_detail); |
|
455 aOutput.WriteAttributeString(XmlConsts.Kxml_name, name); |
|
456 aOutput.WriteAttributeString(XmlConsts.Kxml_value, value.ToString()); |
|
457 aOutput.WriteEndElement(); |
|
458 } |
|
459 } |
|
460 |
|
461 #region Data members |
|
462 private List<CXmlDataBlock> iDatablocks = new List<CXmlDataBlock>(); |
|
463 #endregion |
|
464 } |
|
465 } |