|
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.model; |
|
19 |
|
20 import com.nokia.s60tools.crashanalyser.files.*; |
|
21 import com.nokia.s60tools.crashanalyser.data.*; |
|
22 import java.io.*; |
|
23 |
|
24 /** |
|
25 * CrashFileBundle class bundles up one folder under Crash Analyser plugin's folder. I.e. one |
|
26 * CrashFileBundle is one row in MainView. A bundle can contain an undecoded MobileCrash file, |
|
27 * decoded .crashxml file, partially decoded .crashxml file or an emulator panic xml file. Or a |
|
28 * combination of these. |
|
29 * |
|
30 * All of the files listed above are found e.g. from |
|
31 * c:\my_carbide_workspace\.metadata\.plugins\com.nokia.s60tools.crashanalyser\CrashFiles\[bundle_folder]. |
|
32 * One bundle contains all files under one [bundle_folder]. |
|
33 * |
|
34 * Bundle can also be an empty bundle, so that 'No crash files found' row can be shown in MainView. |
|
35 * |
|
36 * Bundle can also be a waiting bundle, so that 'Loading files. Please wait' row can be shown in MainView. |
|
37 * |
|
38 */ |
|
39 public class CrashFileBundle { |
|
40 |
|
41 public static final int INDEX_TIME = 0; |
|
42 public static final int INDEX_THREAD = 1; |
|
43 public static final int INDEX_PANIC_CATEGORY = 2; |
|
44 public static final int INDEX_PANIC_CODE = 3; |
|
45 public static final int INDEX_FILE_NAME = 4; |
|
46 public static final String EXTENSION_HTML = ".htm"; |
|
47 |
|
48 /** |
|
49 * A binary crash file |
|
50 */ |
|
51 UndecodedFile undecodedFile = null; |
|
52 |
|
53 /** |
|
54 * Fully decoded crash file |
|
55 */ |
|
56 CrashFile crashxmlFile = null; |
|
57 |
|
58 /** |
|
59 * Partially decoded crash file |
|
60 */ |
|
61 SummaryFile summaryFile = null; |
|
62 |
|
63 /** |
|
64 * A xml file which contains information about one emulator panic |
|
65 */ |
|
66 PanicFile emulatorPanicFile = null; |
|
67 |
|
68 /** |
|
69 * Bundle name for an empty or waiting bundle |
|
70 */ |
|
71 String bundleName = ""; |
|
72 |
|
73 /** |
|
74 * Folder where all bundle's files can be found from |
|
75 */ |
|
76 String bundleFolder = ""; |
|
77 |
|
78 /** |
|
79 * If true, bundle is an empty or waiting bundle |
|
80 */ |
|
81 boolean emptyFile = false; |
|
82 |
|
83 /** |
|
84 * Directory from where files in this bundle originally came from. |
|
85 * This data is not always present. |
|
86 */ |
|
87 String originatingDirectory = ""; |
|
88 |
|
89 /** |
|
90 * Used for creating an empty or waiting bundle |
|
91 * @param empty If true, an empty bundle is created. If false, a waiting bundle is created. |
|
92 */ |
|
93 public CrashFileBundle(boolean empty) { |
|
94 if (empty) |
|
95 bundleName = "No Crash Files Found."; |
|
96 else |
|
97 bundleName = "Loading files. Please wait."; |
|
98 emptyFile = true; |
|
99 } |
|
100 |
|
101 /** |
|
102 * Creates a bundle from folder |
|
103 * @param folder Bundle folder. Bundle's file will be read from here. |
|
104 * @param library ErrorLibrary instance |
|
105 */ |
|
106 public CrashFileBundle(String folder, ErrorLibrary library) { |
|
107 bundleFolder = FileOperations.addSlashToEnd(folder); |
|
108 undecodedFile = UndecodedFile.read(bundleFolder); |
|
109 crashxmlFile = CrashFile.read(bundleFolder, library); |
|
110 emulatorPanicFile = PanicFile.read(bundleFolder, library); |
|
111 summaryFile = SummaryFile.read(bundleFolder, library); |
|
112 originatingDirectory = folder; |
|
113 } |
|
114 |
|
115 /** |
|
116 * Initialise bundle with already read Crash file |
|
117 * @param file crash file |
|
118 */ |
|
119 public CrashFileBundle(CrashFile file, String originalDirectory) { |
|
120 crashxmlFile = file; |
|
121 originatingDirectory = originalDirectory; |
|
122 } |
|
123 |
|
124 /** |
|
125 * Initialise bundle with already read Summary file |
|
126 * @param file summary file |
|
127 */ |
|
128 public CrashFileBundle(SummaryFile file, String originalDirectory) { |
|
129 summaryFile = file; |
|
130 originatingDirectory = originalDirectory; |
|
131 } |
|
132 |
|
133 protected CrashFileBundle(String folder) { |
|
134 bundleFolder = FileOperations.addSlashToEnd(folder); |
|
135 } |
|
136 |
|
137 /** |
|
138 * Creates a dummy bundle, which can be used e.g. for comparison reasons. |
|
139 * A dummy bundle can be compared to another bundle. |
|
140 * @param folder bundle folder |
|
141 * @return crash file bundle |
|
142 */ |
|
143 public static CrashFileBundle createDummyBundle(String folder) { |
|
144 return new CrashFileBundle(folder); |
|
145 } |
|
146 |
|
147 /** |
|
148 * MainView can use this to get description for each column in the grid |
|
149 * @param index index of the column |
|
150 * @return value for asked column |
|
151 */ |
|
152 public String getText(int index) { |
|
153 String retval = ""; |
|
154 switch (index) { |
|
155 case INDEX_TIME: |
|
156 retval = getTime(); |
|
157 break; |
|
158 |
|
159 case INDEX_THREAD: |
|
160 retval = getThreadName(); |
|
161 break; |
|
162 |
|
163 case INDEX_PANIC_CATEGORY: |
|
164 retval = getPanicCategory(); |
|
165 break; |
|
166 |
|
167 case INDEX_PANIC_CODE: |
|
168 retval = getPanicCode(); |
|
169 break; |
|
170 |
|
171 case INDEX_FILE_NAME: |
|
172 retval = getFileName(); |
|
173 break; |
|
174 |
|
175 default: |
|
176 break; |
|
177 } |
|
178 |
|
179 return retval; |
|
180 } |
|
181 |
|
182 /** |
|
183 * Returns the file name for this bundle. File name depends on what types |
|
184 * of files this bundle contains (or if this bundle is an empty or waiting bundle). |
|
185 * |
|
186 * @return the file name for this bundle. |
|
187 */ |
|
188 public String getFileName() { |
|
189 if (emptyFile) |
|
190 return bundleName; |
|
191 |
|
192 String retval = ""; |
|
193 if (undecodedFile != null) { |
|
194 retval = undecodedFile.getFileName(); |
|
195 } else if (crashxmlFile != null) { |
|
196 retval = crashxmlFile.getFileName(); |
|
197 } else if (summaryFile != null) { |
|
198 retval = summaryFile.getFileName(); |
|
199 } else if (emulatorPanicFile != null) { |
|
200 retval = "Emulator Panic"; |
|
201 } |
|
202 return retval; |
|
203 } |
|
204 |
|
205 /** |
|
206 * Returns the name of .crashxml or .xml file is they exists |
|
207 * @return the name of .crashxml or .xml file is they exists |
|
208 */ |
|
209 public String getAnalyzeFileName() { |
|
210 String retval = ""; |
|
211 if (crashxmlFile != null) { |
|
212 retval = crashxmlFile.getFileName(); |
|
213 } else if (summaryFile != null) { |
|
214 retval = summaryFile.getFileName(); |
|
215 } |
|
216 return retval; |
|
217 } |
|
218 |
|
219 /** |
|
220 * Returns the panic code of this bundle. Panic code is available |
|
221 * only if bundle contains decoded files or emulator panic. |
|
222 * |
|
223 * @return panic code or empty |
|
224 */ |
|
225 public String getPanicCode() { |
|
226 if (emptyFile) |
|
227 return ""; |
|
228 |
|
229 String retval = ""; |
|
230 if (crashxmlFile != null) { |
|
231 retval = crashxmlFile.getPanicCode(); |
|
232 } else if (summaryFile != null) { |
|
233 retval = summaryFile.getPanicCode(); |
|
234 } else if (emulatorPanicFile != null) { |
|
235 retval = emulatorPanicFile.getPanicCode(); |
|
236 } |
|
237 |
|
238 return retval; |
|
239 } |
|
240 |
|
241 /** |
|
242 * Returns the panic category of this bundle. Panic category is available |
|
243 * only if bundle contains decoded files or emulator panic. |
|
244 * |
|
245 * @return panic category or empty |
|
246 */ |
|
247 public String getPanicCategory() { |
|
248 if (emptyFile) |
|
249 return ""; |
|
250 |
|
251 String retval = ""; |
|
252 if (crashxmlFile != null) { |
|
253 retval = crashxmlFile.getPanicCategory(); |
|
254 } else if (summaryFile != null) { |
|
255 retval = summaryFile.getPanicCategory(); |
|
256 } else if (emulatorPanicFile != null) { |
|
257 retval = emulatorPanicFile.getPanicCategory(); |
|
258 } else if (undecodedFile != null) { |
|
259 retval = "Unknown"; |
|
260 } |
|
261 |
|
262 return retval; |
|
263 } |
|
264 |
|
265 /** |
|
266 * Returns the name of the paniced thread. Thread name is available |
|
267 * only if bundle contains decoded files or emulator panic. |
|
268 * |
|
269 * @return paniced thread name or empty |
|
270 */ |
|
271 public String getThreadName() { |
|
272 if (emptyFile) |
|
273 return ""; |
|
274 |
|
275 String retval = ""; |
|
276 if (crashxmlFile != null) { |
|
277 retval = crashxmlFile.getThreadName(); |
|
278 } else if (summaryFile != null) { |
|
279 retval = summaryFile.getThreadName(); |
|
280 } else if (emulatorPanicFile != null) { |
|
281 retval = emulatorPanicFile.getThreadName(); |
|
282 } else if (undecodedFile != null) { |
|
283 retval = "Unknown"; |
|
284 } |
|
285 |
|
286 return retval; |
|
287 } |
|
288 |
|
289 /** |
|
290 * Returns the time of a crash. Crash time is not always available |
|
291 * (even in decoded crash files). If crash time is not available, |
|
292 * the creation time of the crash file is returned. |
|
293 * |
|
294 * @return crash time |
|
295 */ |
|
296 public String getTime() { |
|
297 if (emptyFile) |
|
298 return ""; |
|
299 |
|
300 String retval = ""; |
|
301 if (crashxmlFile != null) { |
|
302 retval = crashxmlFile.getTime(); |
|
303 // crashxml does not always contain time |
|
304 if ("".equals(retval)) { |
|
305 // try to read time: when undecoded file was created |
|
306 if (undecodedFile != null) { |
|
307 retval = undecodedFile.getTime(); |
|
308 // there was no undecoded file, read time: when crashxml file was created |
|
309 } else { |
|
310 retval = crashxmlFile.getCreated(); |
|
311 } |
|
312 } |
|
313 } |
|
314 else if (summaryFile != null) { |
|
315 retval = summaryFile.getTime(); |
|
316 // summary does not always contain time |
|
317 if ("".equals(retval)) { |
|
318 // try to read time: when undecoded file was created |
|
319 if (undecodedFile != null) { |
|
320 retval = undecodedFile.getCreated(); |
|
321 // there was no undecoded file, read time: when summary.xml file was created |
|
322 } else { |
|
323 retval = summaryFile.getCreated(); |
|
324 } |
|
325 } |
|
326 } else if (undecodedFile != null) { |
|
327 retval = undecodedFile.getCreated(); |
|
328 } else if (emulatorPanicFile != null) { |
|
329 retval = emulatorPanicFile.getTime(); |
|
330 if ("".equals(retval)) |
|
331 retval = emulatorPanicFile.getCreated(); |
|
332 } |
|
333 |
|
334 return retval; |
|
335 } |
|
336 |
|
337 /** |
|
338 * Returns the crash files ROM ID if available. |
|
339 * @return ROM ID or empty |
|
340 */ |
|
341 public String getRomId() { |
|
342 if (isEmpty()) |
|
343 return ""; |
|
344 |
|
345 if (crashxmlFile != null) { |
|
346 return crashxmlFile.getRomId(); |
|
347 } else if (summaryFile != null) { |
|
348 return summaryFile.getRomId(); |
|
349 } else { |
|
350 return ""; |
|
351 } |
|
352 } |
|
353 |
|
354 /** |
|
355 * Returns whether this is an empty or waiting bundle. |
|
356 * @return true if bundle is empty or waiting, false if not. |
|
357 */ |
|
358 public boolean isEmpty() { |
|
359 return emptyFile; |
|
360 } |
|
361 |
|
362 /** |
|
363 * Returns whether this bundle contains an emulator panic |
|
364 * @return true if this bundle contains an emulator panic, false if not |
|
365 */ |
|
366 public boolean isEmulatorPanic() { |
|
367 if (emulatorPanicFile != null) |
|
368 return true; |
|
369 |
|
370 return false; |
|
371 } |
|
372 |
|
373 /** |
|
374 * Returns whether this bundle contains a fully decoded crash file (.crashxml) |
|
375 * @return true if this bundle contains a fully decoded crash file, false if not |
|
376 */ |
|
377 public boolean isFullyDecoded() { |
|
378 if (crashxmlFile != null) |
|
379 return true; |
|
380 |
|
381 return false; |
|
382 } |
|
383 |
|
384 /** |
|
385 * Returns whether this bundle contains a partially decoded crash file (.xml) |
|
386 * @return true if this bundle contains a partially decoded crash file, false if not |
|
387 */ |
|
388 public boolean isPartiallyDecoded() { |
|
389 if (summaryFile != null) |
|
390 return true; |
|
391 |
|
392 return false; |
|
393 } |
|
394 |
|
395 /** |
|
396 * Returns whether this bundle contains any files. |
|
397 * @return true if bundle contains files, false if not |
|
398 */ |
|
399 public boolean hasFiles() { |
|
400 if (crashxmlFile != null || summaryFile != null || |
|
401 emulatorPanicFile != null || undecodedFile != null) |
|
402 return true; |
|
403 |
|
404 return false; |
|
405 } |
|
406 |
|
407 /** |
|
408 * Returns whether this bundle contains xml files (.crashxml or .xml). |
|
409 * @return true if bundle contains files, false if not |
|
410 */ |
|
411 public boolean hasXml() { |
|
412 if (crashxmlFile != null || summaryFile != null) |
|
413 return true; |
|
414 |
|
415 return false; |
|
416 } |
|
417 |
|
418 /** |
|
419 * Returns undecoded crash file if exists |
|
420 * @return undecoded crash file or null |
|
421 */ |
|
422 public UndecodedFile getUndecodedFile() { |
|
423 return undecodedFile; |
|
424 } |
|
425 |
|
426 /** |
|
427 * Returns fully decoded crash file if exists |
|
428 * @return fully decoded crash file or null |
|
429 */ |
|
430 public CrashFile getCrashFile() { |
|
431 return crashxmlFile; |
|
432 } |
|
433 |
|
434 /** |
|
435 * Returns partially decoded crash file if exists |
|
436 * @return partially decoded crash file or null |
|
437 */ |
|
438 public SummaryFile getSummaryFile() { |
|
439 return summaryFile; |
|
440 } |
|
441 |
|
442 /** |
|
443 * Returns the directory from where the files in this bundle |
|
444 * originally came from. This information is not always available. |
|
445 * @return directory from where the files in this bundle originally came from. |
|
446 */ |
|
447 public String getOriginatingDirectory() { |
|
448 return originatingDirectory; |
|
449 } |
|
450 |
|
451 /** |
|
452 * Returns the location for .xml or .crashxml of this bundle. |
|
453 * @return the location for .xml or .crashxml of this bundle. |
|
454 */ |
|
455 public String getXmlFilePath() { |
|
456 String retval = ""; |
|
457 |
|
458 if (crashxmlFile != null) { |
|
459 retval = FileOperations.addSlashToEnd(bundleFolder) + crashxmlFile.getFileName(); |
|
460 } else if (summaryFile != null) { |
|
461 retval = FileOperations.addSlashToEnd(bundleFolder) + summaryFile.getFileName(); |
|
462 } |
|
463 |
|
464 return retval; |
|
465 } |
|
466 |
|
467 /** |
|
468 * Deletes this bundle. I.e deletes all files under this |
|
469 * bundle's folder and finally deletes the bundle folder |
|
470 */ |
|
471 public void delete() { |
|
472 try { |
|
473 if (!"".equals(bundleFolder)) { |
|
474 FileOperations.deleteFolder(bundleFolder); |
|
475 } |
|
476 } catch (Exception e) { |
|
477 e.printStackTrace(); |
|
478 } |
|
479 } |
|
480 |
|
481 /** |
|
482 * Tests whether this bundle still exists in the drive. |
|
483 * If bundle is empty or waiting, true is always returned. |
|
484 * |
|
485 * @return true if bundle exists, false if not. |
|
486 */ |
|
487 public boolean exists() { |
|
488 if (isEmpty()) |
|
489 return true; |
|
490 |
|
491 try { |
|
492 File f = new File(bundleFolder); |
|
493 if (f.isDirectory() && f.exists()) |
|
494 return true; |
|
495 } catch (Exception e) { |
|
496 return false; |
|
497 } |
|
498 |
|
499 return false; |
|
500 } |
|
501 |
|
502 /** |
|
503 * Returns a description for this bundle. The description depends on which |
|
504 * files this bundle contains. |
|
505 * |
|
506 * @param full defines whether a full description or short description should be returned. |
|
507 * @return file description |
|
508 */ |
|
509 public String getDescription(boolean full) { |
|
510 if (isEmpty()) |
|
511 return ""; |
|
512 |
|
513 if (crashxmlFile != null) { |
|
514 if (full) |
|
515 return crashxmlFile.getDescription(); |
|
516 else |
|
517 return crashxmlFile.getShortDescription(); |
|
518 } else if (summaryFile != null) { |
|
519 if (full) |
|
520 return summaryFile.getDescription(); |
|
521 else |
|
522 return summaryFile.getShortDescription(); |
|
523 } else if (emulatorPanicFile != null) { |
|
524 return emulatorPanicFile.getDescription(); |
|
525 } else { |
|
526 return ""; |
|
527 } |
|
528 } |
|
529 |
|
530 /** |
|
531 * Returns this bundle's folder |
|
532 * @return bundle's folder or empty |
|
533 */ |
|
534 protected String getBundleFolder() { |
|
535 return bundleFolder; |
|
536 } |
|
537 |
|
538 /** |
|
539 * Returns html file if this bundle is a .crashxml or .xml file. |
|
540 * @param create defines whether the html file should be generated if it doesn't exist, or not |
|
541 * @return html file if success, null if not |
|
542 */ |
|
543 public File getHtmlFile(boolean create) { |
|
544 File htmlFile = null; |
|
545 |
|
546 // we have .crashxml file |
|
547 if (crashxmlFile != null) { |
|
548 String crashxml = FileOperations.addSlashToEnd(bundleFolder) + |
|
549 crashxmlFile.getFileName() + |
|
550 EXTENSION_HTML; |
|
551 htmlFile = new File(crashxml); |
|
552 // if html file doesn't exists, create it |
|
553 if (!htmlFile.exists() && create) { |
|
554 crashxmlFile.writeTo(htmlFile); |
|
555 htmlFile = new File(crashxml); |
|
556 // creation of html failed |
|
557 if (!htmlFile.exists()) |
|
558 htmlFile = null; |
|
559 } |
|
560 // we have .xml file |
|
561 } else if (summaryFile != null) { |
|
562 String crashxml = FileOperations.addSlashToEnd(bundleFolder) + |
|
563 summaryFile.getFileName() + |
|
564 EXTENSION_HTML; |
|
565 // if html file doesn't exists, create it |
|
566 htmlFile = new File(crashxml); |
|
567 if (!htmlFile.exists() && create) { |
|
568 summaryFile.writeTo(htmlFile); |
|
569 htmlFile = new File(crashxml); |
|
570 // creation of html failed |
|
571 if (!htmlFile.exists()) |
|
572 htmlFile = null; |
|
573 } |
|
574 } |
|
575 |
|
576 return htmlFile; |
|
577 } |
|
578 |
|
579 /** |
|
580 * Saves .crashxml or .xml as given html file. This is done only if this |
|
581 * bundle contains .crashxml or .xml files |
|
582 * @param destinationFile html file for save as |
|
583 * @return true if success, false if not |
|
584 */ |
|
585 public boolean saveAsHtml(File destinationFile) { |
|
586 File htmlFile = getHtmlFile(true); |
|
587 if (htmlFile != null) |
|
588 return FileOperations.copyFile(htmlFile, destinationFile, true); |
|
589 return false; |
|
590 } |
|
591 |
|
592 /** |
|
593 * Checks if bundles are equal. Two bundles are equal if |
|
594 * their bundleFolder is the same. |
|
595 */ |
|
596 public boolean equals(Object other) { |
|
597 if (this == other) |
|
598 return true; |
|
599 |
|
600 if (!(other instanceof CrashFileBundle)) |
|
601 return false; |
|
602 |
|
603 CrashFileBundle othr = (CrashFileBundle)other; |
|
604 if (bundleFolder.compareToIgnoreCase(othr.getBundleFolder()) == 0) |
|
605 return true; |
|
606 return false; |
|
607 } |
|
608 |
|
609 public int hashCode() { |
|
610 return 0; |
|
611 } |
|
612 } |