|
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 java.io.*; |
|
21 import com.nokia.s60tools.crashanalyser.files.*; |
|
22 import com.nokia.s60tools.crashanalyser.interfaces.IDecodingObserver; |
|
23 import com.nokia.s60tools.crashanalyser.plugin.*; |
|
24 import com.nokia.s60tools.crashanalyser.corecomponents.interfaces.CommandLineManager; |
|
25 import com.nokia.s60tools.crashanalyser.data.*; |
|
26 import java.util.ArrayList; |
|
27 import java.util.List; |
|
28 import org.eclipse.core.runtime.*; |
|
29 import org.eclipse.core.runtime.jobs.Job; |
|
30 |
|
31 /** |
|
32 * This class handles the actual decoding Crash files process. Data entered by |
|
33 * user in Wizard pages are passed to this class and this class then handles it |
|
34 * properly. |
|
35 * |
|
36 */ |
|
37 public class DecoderEngine extends Job { |
|
38 protected static final String TOOLS_FOLDER = "tools"; |
|
39 protected static final String WORK_FOLDER = "work"; |
|
40 protected static final String TEMPORARY_FOLDER = "temp"; |
|
41 protected static final String CRASH_FILES_FOLDER = "CrashFiles"; |
|
42 protected static final String MAP_FILES_ZIP_FOLDER = "MapFilesZip"; |
|
43 protected static final String SELGE_EVENT_INI = "selge_event.ini"; |
|
44 protected static final String ERROR_FILE_EXTENSION = "error"; |
|
45 protected static final int MAX_FILE_COUNT = 500; |
|
46 |
|
47 public static enum PathTypes { |
|
48 CRASH, SYMBOL |
|
49 } |
|
50 |
|
51 private List<CrashFileBundle> crashFiles = null; |
|
52 private IDecodingObserver decodingObserver = null; |
|
53 private DecodingData decodingData = null; |
|
54 |
|
55 /** |
|
56 * Constructor |
|
57 */ |
|
58 public DecoderEngine() { |
|
59 super("Handling Crash Files (Note! This might take several minutes)"); |
|
60 } |
|
61 |
|
62 /** |
|
63 * Returns path where selge_event.ini |
|
64 * |
|
65 * @return path where selge_event.ini is located |
|
66 */ |
|
67 public static String getSelgeEventIniFile() { |
|
68 return FileOperations.addSlashToEnd(CrashAnalyserPlugin |
|
69 .getPluginInstallPath()) |
|
70 + FileOperations.addSlashToEnd(TOOLS_FOLDER) + SELGE_EVENT_INI; |
|
71 } |
|
72 |
|
73 /** |
|
74 * Checks whether given file is a known crash file |
|
75 * |
|
76 * @param file |
|
77 * crash file |
|
78 * @return true if file seems to be a known crash file, false if not |
|
79 */ |
|
80 public static boolean isFileValidCrashFile(String file) { |
|
81 return isFileValidCrashFile(new File(file)); |
|
82 } |
|
83 |
|
84 /** |
|
85 * Checks whether given file is a known crash file |
|
86 * |
|
87 * @param file |
|
88 * crash file |
|
89 * @return true if file seems to be a known crash file, false if not |
|
90 */ |
|
91 public static boolean isFileValidCrashFile(File file) { |
|
92 try { |
|
93 // file must be a file and it must exist |
|
94 if (file.isFile() && file.exists()) { |
|
95 String fileName = file.getName(); |
|
96 // file extension must match known extension types |
|
97 if (fileName |
|
98 .endsWith(CrashAnalyserFile.MOBILECRASH_FILE_EXTENSION) |
|
99 || fileName |
|
100 .endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION) |
|
101 || fileName |
|
102 .endsWith(CrashAnalyserFile.D_EXC_FILE_EXTENSION) |
|
103 || fileName |
|
104 .endsWith(CrashAnalyserFile.ELF_CORE_DUMP_FILE_EXTENSION)) |
|
105 return true; |
|
106 } |
|
107 } catch (Exception e) { |
|
108 e.printStackTrace(); |
|
109 } |
|
110 return false; |
|
111 } |
|
112 |
|
113 /** |
|
114 * Checks if given path contains any Crash files. |
|
115 * |
|
116 * @param path |
|
117 * from where Crash files should be found |
|
118 * @return true if given path contains Crash files, false if not |
|
119 */ |
|
120 protected boolean isCrashPathValid(String path) { |
|
121 try { |
|
122 File file = new File(path); |
|
123 if (!file.isDirectory()) |
|
124 return false; |
|
125 |
|
126 // We are looking for files *.bin, or *.txt or *.crashxml |
|
127 FilenameFilter filter = new FilenameFilter() { |
|
128 public boolean accept(File dir, String name) { |
|
129 return (name |
|
130 .endsWith(CrashAnalyserFile.MOBILECRASH_FILE_EXTENSION) |
|
131 || name |
|
132 .endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION) |
|
133 || name |
|
134 .endsWith(CrashAnalyserFile.D_EXC_FILE_EXTENSION) |
|
135 || name |
|
136 .endsWith(CrashAnalyserFile.ELF_CORE_DUMP_FILE_EXTENSION)); |
|
137 } |
|
138 }; |
|
139 File[] files = file.listFiles(filter); |
|
140 if (files != null && files.length > 0) |
|
141 return true; |
|
142 |
|
143 return false; |
|
144 } catch (Exception e) { |
|
145 return false; |
|
146 } |
|
147 } |
|
148 |
|
149 /** |
|
150 * Returns an empty working folder under workspace. |
|
151 * |
|
152 * @param clean |
|
153 * defines whether the folder should be cleared |
|
154 * @return E.g. |
|
155 * C:\My_Workspace\.metadata\.plugins\com.nokia.s60tools.crashanalyser |
|
156 * \work\ |
|
157 */ |
|
158 public static String getWorkingFolder(boolean clean) { |
|
159 String workingFolder = FileOperations |
|
160 .addSlashToEnd(getPluginWorkingLocation()); |
|
161 workingFolder += FileOperations.addSlashToEnd(WORK_FOLDER); |
|
162 // creates the folder. if the folder already exists, deletes its content |
|
163 FileOperations.createFolder(workingFolder, clean); |
|
164 return workingFolder; |
|
165 } |
|
166 |
|
167 /** |
|
168 * Creates a new folder for crash file. E.g. |
|
169 * C:\My_Workspace\.metadata\.plugins |
|
170 * \com.nokia.s60tools.crashanalyser\CrashFiles\5\ |
|
171 * |
|
172 * @return created folder, or null if failed |
|
173 */ |
|
174 public static String getNewCrashFolder() { |
|
175 String crashFilesFolder = FileOperations |
|
176 .addSlashToEnd(getCrashFilesFolder()); |
|
177 for (int i = 1; i < MAX_FILE_COUNT; i++) { |
|
178 File freeFolder = new File(crashFilesFolder + Integer.toString(i)); |
|
179 if (!freeFolder.exists()) { |
|
180 FileOperations.createFolder(freeFolder.getAbsolutePath()); |
|
181 return freeFolder.getAbsolutePath(); |
|
182 } |
|
183 } |
|
184 |
|
185 return null; |
|
186 } |
|
187 |
|
188 /** |
|
189 * Creates a new folder for temporary crash files. This folder is used for |
|
190 * crash files which are read from device. |
|
191 * |
|
192 * @param clean |
|
193 * defines whether the folder should be cleared |
|
194 * @return E.g. |
|
195 * C:\My_Workspace\.metadata\.plugins\com.nokia.s60tools.crashanalyser |
|
196 * \temp |
|
197 */ |
|
198 public static String getTemporaryCrashFileFolder(boolean clean) { |
|
199 String tempFolder = FileOperations |
|
200 .addSlashToEnd(getPluginWorkingLocation()); |
|
201 tempFolder += TEMPORARY_FOLDER; |
|
202 // creates the folder. if the folder already exists, deletes its content |
|
203 FileOperations.createFolder(tempFolder, clean); |
|
204 return tempFolder; |
|
205 } |
|
206 |
|
207 /** |
|
208 * Checks whether given path is valid (i.e. contains correct files etc) |
|
209 * |
|
210 * @param path |
|
211 * path to be checked |
|
212 * @param pathType |
|
213 * defines "how" the path is validated |
|
214 * @return true if path is valid, false if not |
|
215 */ |
|
216 public boolean isPathValid(String path, PathTypes pathType) { |
|
217 |
|
218 boolean retVal = false; |
|
219 |
|
220 if (PathTypes.CRASH.equals(pathType)) |
|
221 retVal = isCrashPathValid(path); |
|
222 |
|
223 return retVal; |
|
224 } |
|
225 |
|
226 /** |
|
227 * Decoder Engine owns crash files which are being handled by Crash Analyser |
|
228 * wizard. This will get all files which are currently being handled. |
|
229 * |
|
230 * @return list of crash files. |
|
231 */ |
|
232 public List<CrashFileBundle> getCrashFiles() { |
|
233 return crashFiles; |
|
234 } |
|
235 |
|
236 /** |
|
237 * This method is used to set crash files which are to be decoded. This |
|
238 * method is used when user has selected files to be re-decoded. |
|
239 * |
|
240 * @param files |
|
241 * files to be decoded |
|
242 */ |
|
243 public void setCrashFiles(List<CrashFileBundle> files) { |
|
244 crashFiles = files; |
|
245 } |
|
246 |
|
247 /** |
|
248 * This method executes CrashAnalyser.exe for summary information for given |
|
249 * file or folder. |
|
250 * |
|
251 * @param fileOrFolder |
|
252 * a file or a folder |
|
253 * @param errorLibrary |
|
254 * Error Library |
|
255 * @param progress |
|
256 * progress monitor |
|
257 * @return true if any files were found for summary info, false if not |
|
258 */ |
|
259 public boolean processSummaryInfoForFiles(String fileOrFolder, |
|
260 ErrorLibrary errorLibrary, IProgressMonitor progress) { |
|
261 if (crashFiles != null) |
|
262 crashFiles.clear(); |
|
263 String workingFolder = DecoderEngine.getWorkingFolder(true); |
|
264 if (!"".equals(fileOrFolder)) { |
|
265 |
|
266 String originatingDirectory = fileOrFolder; |
|
267 |
|
268 File f = new File(fileOrFolder); |
|
269 // if only one .crashxml file is selected, no need to run command |
|
270 // line |
|
271 if (f.isFile() |
|
272 && fileOrFolder |
|
273 .endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION)) { |
|
274 FileOperations.copyFile(f, workingFolder, true); |
|
275 originatingDirectory = FileOperations.getFolder(fileOrFolder); |
|
276 // one binary file is selected, run CrashAnalyser.exe for |
|
277 // summary data |
|
278 } else if (f.isFile()) { |
|
279 CommandLineManager.executeSummary(workingFolder, fileOrFolder, |
|
280 CrashAnalyserFile.SUMMARY_FILE_EXTENSION, progress); |
|
281 originatingDirectory = FileOperations.getFolder(fileOrFolder); |
|
282 // directory was given |
|
283 } else { |
|
284 // copy .crashxml files to working folder. |
|
285 // copySummaryFilesToWorkingDirectory will return true if folder |
|
286 // contained only .crashxml files -> so if false is returned, it |
|
287 // means that we need to run CrashAnalyser.exe for other files |
|
288 // in the directory. |
|
289 if (!copyCrashFilesToWorkingDirectory(fileOrFolder, |
|
290 workingFolder)) |
|
291 CommandLineManager.executeSummary(workingFolder, |
|
292 fileOrFolder, |
|
293 CrashAnalyserFile.SUMMARY_FILE_EXTENSION, progress); |
|
294 } |
|
295 readSummaryFiles(workingFolder, originatingDirectory, errorLibrary); |
|
296 } |
|
297 |
|
298 if (crashFiles.isEmpty()) |
|
299 return false; |
|
300 |
|
301 return true; |
|
302 } |
|
303 |
|
304 /** |
|
305 * copies all crashfiles (.crashxml) from given folder to given workfolder. |
|
306 * |
|
307 * @param fromFolder |
|
308 * folder where crash files are copied from |
|
309 * @param workingFolder |
|
310 * folder where crash files are copied to |
|
311 * @return true if fromFolder contained only crash files (.crashxml), false |
|
312 * if folder contained other files also |
|
313 */ |
|
314 boolean copyCrashFilesToWorkingDirectory(String fromFolder, |
|
315 String workingFolder) { |
|
316 boolean retval = true; |
|
317 File from = new File(fromFolder); |
|
318 // given from folder needs to be an existing directory |
|
319 if (from.isDirectory() && from.exists()) { |
|
320 String[] files = from.list(); // get all files |
|
321 // if files were found |
|
322 if (files != null && files.length > 0) { |
|
323 // go through all files in fromFolder |
|
324 for (int i = 0; i < files.length; i++) { |
|
325 String file = files[i]; |
|
326 // files is .crashxml |
|
327 if (file.endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION)) { |
|
328 FileOperations.copyFile(new File(FileOperations |
|
329 .addSlashToEnd(fromFolder) |
|
330 + file), workingFolder, true); |
|
331 // file was not .crashxml |
|
332 } else { |
|
333 retval = false; |
|
334 } |
|
335 } |
|
336 } |
|
337 } |
|
338 |
|
339 return retval; |
|
340 } |
|
341 |
|
342 /** |
|
343 * Reads all summary and crash files (.xml & .crashxml) from given |
|
344 * directory. Creates a CrashFileBundle for all found files and adds them to |
|
345 * this.crashFiles |
|
346 * |
|
347 * @param summaryFileDirectory |
|
348 * directory where files are to be read from |
|
349 * @param originatingDirectory |
|
350 * directory from where the original files are being imported |
|
351 * @param errorLibrary |
|
352 * Error Library |
|
353 */ |
|
354 void readSummaryFiles(String summaryFileDirectory, |
|
355 String originatingDirectory, ErrorLibrary errorLibrary) { |
|
356 File file = new File(summaryFileDirectory); |
|
357 crashFiles = new ArrayList<CrashFileBundle>(); |
|
358 |
|
359 // read all files from the directory |
|
360 if (file.isDirectory()) { |
|
361 |
|
362 // accept summary and output files (.xml & .crashxml) |
|
363 FilenameFilter filter = new FilenameFilter() { |
|
364 public boolean accept(File dir, String name) { |
|
365 return (name |
|
366 .endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION) || name |
|
367 .endsWith("." |
|
368 + CrashAnalyserFile.SUMMARY_FILE_EXTENSION)); |
|
369 } |
|
370 }; |
|
371 |
|
372 File[] files = file.listFiles(filter); |
|
373 |
|
374 // go through all found files |
|
375 for (int i = 0; i < files.length; i++) { |
|
376 File crashFile = files[i]; |
|
377 |
|
378 // file is output.crashxml type |
|
379 if (crashFile.getName().endsWith( |
|
380 CrashAnalyserFile.OUTPUT_FILE_EXTENSION)) { |
|
381 CrashFile crashxml = CrashFile |
|
382 .read(crashFile, errorLibrary); |
|
383 if (crashxml != null) |
|
384 crashFiles.add(new CrashFileBundle(crashxml, |
|
385 originatingDirectory)); |
|
386 // file is summary file |
|
387 } else { |
|
388 SummaryFile summaryXml = SummaryFile.read(crashFile, |
|
389 errorLibrary); |
|
390 if (summaryXml != null) |
|
391 crashFiles.add(new CrashFileBundle(summaryXml, |
|
392 originatingDirectory)); |
|
393 } |
|
394 } |
|
395 } |
|
396 } |
|
397 |
|
398 /** |
|
399 * Used for passing decoding parameters |
|
400 * |
|
401 * @param data |
|
402 * decoding parameters |
|
403 */ |
|
404 public void setDecodingData(DecodingData data) { |
|
405 decodingData = data; |
|
406 } |
|
407 |
|
408 /** |
|
409 * Returns a path where Crash Analyser plugin can do various tasks (located |
|
410 * under workspace). |
|
411 * |
|
412 * @return E.g. |
|
413 * C:\My_Workspace\.metadata\.plugins\com.nokia.s60tools.crashanalyser |
|
414 * \ |
|
415 */ |
|
416 protected static String getPluginWorkingLocation() { |
|
417 IPath location = Platform.getStateLocation(CrashAnalyserPlugin |
|
418 .getDefault().getBundle()); |
|
419 return location.toOSString(); |
|
420 } |
|
421 |
|
422 /** |
|
423 * Returns the folder under which crash file folders are located |
|
424 * |
|
425 * @return E.g. |
|
426 * C:\My_Workspace\.metadata\.plugins\com.nokia.s60tools.crashanalyser |
|
427 * \CrashFiles |
|
428 */ |
|
429 public static String getCrashFilesFolder() { |
|
430 String crashFilesFolder = FileOperations |
|
431 .addSlashToEnd(getPluginWorkingLocation()) |
|
432 + CRASH_FILES_FOLDER; |
|
433 FileOperations.createFolder(crashFilesFolder); |
|
434 return crashFilesFolder; |
|
435 } |
|
436 |
|
437 /** |
|
438 * Start the decoding process |
|
439 * |
|
440 * @param observer |
|
441 * observer for the decoding process |
|
442 */ |
|
443 public void decode(IDecodingObserver observer) { |
|
444 decodingObserver = observer; |
|
445 setPriority(Job.SHORT); |
|
446 setUser(true); |
|
447 schedule(); |
|
448 } |
|
449 |
|
450 /** |
|
451 * Runs CrashAnalyser.exe for full analysis for (user) selected files. This |
|
452 * also handles already decoded files (.crashxml) so that they are not given |
|
453 * to CrashAnalyser.exe. Outcome of this method is that all decoded files |
|
454 * are under given workingFolder. |
|
455 * |
|
456 * @param workingFolder |
|
457 * where files are to be decoded |
|
458 * @param monitor |
|
459 * for progress bar |
|
460 */ |
|
461 void importCrashFiles(String workingFolder, IProgressMonitor monitor) { |
|
462 if (crashFiles != null) { |
|
463 List<String> filesToBeDecoded = new ArrayList<String>(); |
|
464 // go through all crash files |
|
465 for (int i = 0; i < crashFiles.size(); i++) { |
|
466 CrashFileBundle crashFile = crashFiles.get(i); |
|
467 |
|
468 // we are importing already decoded file (.crashxml) |
|
469 if (crashFile.isFullyDecoded()) { |
|
470 CrashFile f = crashFile.getCrashFile(); |
|
471 // this index was not chosen by user to be imported, delete |
|
472 // this .crash from working folder |
|
473 if (f != null && !decodingData.crashFileIndexes.contains(i)) { |
|
474 FileOperations.deleteFile(f.getFilePath()); |
|
475 } |
|
476 // we are decoding a crash file |
|
477 } else { |
|
478 // this index was not chosen by user to be imported, skip |
|
479 // this crash file |
|
480 if (!decodingData.crashFileIndexes.contains(i)) |
|
481 continue; |
|
482 |
|
483 SummaryFile f = crashFile.getSummaryFile(); |
|
484 filesToBeDecoded.add(f.getSourceFilePath()); |
|
485 } |
|
486 } |
|
487 |
|
488 if (!filesToBeDecoded.isEmpty()) { |
|
489 String mapFilesFolder = decodingData.mapFilesFolder; |
|
490 |
|
491 // if MapFiles.zip is provided |
|
492 if (mapFilesFolder != null && "".equals(mapFilesFolder) |
|
493 && decodingData.mapFilesZip != null |
|
494 && !"".equals(decodingData.mapFilesZip)) { |
|
495 String zipFolder = FileOperations |
|
496 .addSlashToEnd(workingFolder) |
|
497 + FileOperations |
|
498 .addSlashToEnd(MAP_FILES_ZIP_FOLDER); |
|
499 FileOperations.createFolder(zipFolder, true); |
|
500 FileOperations.unZipFiles( |
|
501 new File(decodingData.mapFilesZip), zipFolder); |
|
502 mapFilesFolder = zipFolder; |
|
503 } |
|
504 |
|
505 CommandLineManager.executeFullAnalysis(workingFolder, |
|
506 filesToBeDecoded.toArray(new String[filesToBeDecoded |
|
507 .size()]), decodingData.symbolFiles, |
|
508 mapFilesFolder, decodingData.imageFiles, |
|
509 CrashAnalyserFile.OUTPUT_FILE_EXTENSION, |
|
510 ERROR_FILE_EXTENSION, getSelgeEventIniFile(), monitor); |
|
511 } |
|
512 } |
|
513 } |
|
514 |
|
515 /** |
|
516 * Searches the crash file bundle for the given crashFile |
|
517 * |
|
518 * @param crashFile |
|
519 * .xml or .crashxml file |
|
520 * @return CrashFileBundle for given file if found, null if not found |
|
521 */ |
|
522 CrashFileBundle getCrashFileBundle(File crashFile) { |
|
523 if (crashFiles != null) { |
|
524 for (int i = 0; i < crashFiles.size(); i++) { |
|
525 CrashFileBundle cfb = crashFiles.get(i); |
|
526 String fileName = ""; |
|
527 SummaryFile sf = cfb.getSummaryFile(); |
|
528 if (sf != null) { |
|
529 fileName = FileOperations.getFileNameWithoutExtension(sf |
|
530 .getFileName()); |
|
531 } |
|
532 CrashFile cf = cfb.getCrashFile(); |
|
533 if (cf != null) { |
|
534 fileName = FileOperations.getFileNameWithoutExtension(cf |
|
535 .getFileName()); |
|
536 } |
|
537 |
|
538 if ("".equals(fileName)) { |
|
539 UndecodedFile uf = cfb.getUndecodedFile(); |
|
540 if (uf != null |
|
541 && uf |
|
542 .getFileName() |
|
543 .equals( |
|
544 FileOperations |
|
545 .getFileNameWithoutExtension(crashFile |
|
546 .getName()))) |
|
547 return cfb; |
|
548 } |
|
549 |
|
550 if (FileOperations.getFileNameWithoutExtension( |
|
551 crashFile.getName()).equalsIgnoreCase(fileName)) |
|
552 return cfb; |
|
553 } |
|
554 } |
|
555 return null; |
|
556 } |
|
557 |
|
558 /** |
|
559 * Moves decoded crash files from working folder to their own folders under |
|
560 * CrashFiles folder |
|
561 * |
|
562 * @param workingFolder |
|
563 * from where decoded files are moved from |
|
564 */ |
|
565 CrashAnalyserFile moveDecodedFiles(String workingFolder) { |
|
566 CrashAnalyserFile cafile = null; |
|
567 File folder = new File(workingFolder); |
|
568 |
|
569 // accept output files (.crashxml) |
|
570 FilenameFilter filter = new FilenameFilter() { |
|
571 public boolean accept(File dir, String name) { |
|
572 return (name.endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION)); |
|
573 } |
|
574 }; |
|
575 |
|
576 File[] files = folder.listFiles(filter); |
|
577 |
|
578 // go through all found files |
|
579 for (int i = 0; i < files.length; i++) { |
|
580 try { |
|
581 File crashFile = files[i]; |
|
582 |
|
583 String crashFolder = getNewCrashFolder(); |
|
584 |
|
585 // copy crash file (.crashxml) to crash folder |
|
586 FileOperations.copyFile(crashFile, crashFolder, true); |
|
587 |
|
588 // try to copy the original binary file also to crash folder |
|
589 // (only mobilecrash, not D_EXC) |
|
590 String binaryFile = SummaryFile.getSourceFilePath(crashFile |
|
591 .getAbsolutePath()); |
|
592 if (!"".equals(binaryFile) |
|
593 && binaryFile |
|
594 .toLowerCase() |
|
595 .endsWith( |
|
596 "." |
|
597 + CrashAnalyserFile.MOBILECRASH_FILE_EXTENSION)) { |
|
598 FileOperations.copyFile(new File(binaryFile), crashFolder, |
|
599 true); |
|
600 } |
|
601 |
|
602 // if only one file was decoded, pass this file eventually to |
|
603 // MainView so that this file can be opened up after decoding. |
|
604 if (files.length == 1) { |
|
605 cafile = CrashFile.read(crashFolder, |
|
606 decodingData.errorLibrary); |
|
607 } |
|
608 |
|
609 // html and/or text page needs to be generated |
|
610 if ((decodingData.html || decodingData.text) |
|
611 && decodingData.htmlTextOutputFolder != null) { |
|
612 CrashFile crashxml = CrashFile.read(crashFile, |
|
613 decodingData.errorLibrary); |
|
614 if (crashxml != null) { |
|
615 // create html/text file to the original folder where |
|
616 // file came from |
|
617 if ("".equals(decodingData.htmlTextOutputFolder)) { |
|
618 CrashFileBundle cfb = getCrashFileBundle(crashFile); |
|
619 if (cfb != null) { |
|
620 if (decodingData.html) |
|
621 crashxml.writeTo(cfb |
|
622 .getOriginatingDirectory(), true); |
|
623 if (decodingData.text) |
|
624 crashxml.writeTo(cfb |
|
625 .getOriginatingDirectory(), false); |
|
626 } |
|
627 |
|
628 // create html/text file to user defined location |
|
629 } else { |
|
630 if (decodingData.html) |
|
631 crashxml |
|
632 .writeTo( |
|
633 decodingData.htmlTextOutputFolder, |
|
634 true); |
|
635 if (decodingData.text) |
|
636 crashxml.writeTo( |
|
637 decodingData.htmlTextOutputFolder, |
|
638 false); |
|
639 } |
|
640 } |
|
641 } |
|
642 } catch (Exception e) { |
|
643 e.printStackTrace(); |
|
644 } |
|
645 } |
|
646 return cafile; |
|
647 } |
|
648 |
|
649 /** |
|
650 * Runs CrashAnalyser.exe for full analysis for provided files. This handles |
|
651 * only binary files. Outcome of this method is that all decoded files are |
|
652 * under given workingFolder. |
|
653 * |
|
654 * @param workingFolder |
|
655 * where files are to be decoded |
|
656 * @param monitor |
|
657 */ |
|
658 void reDecodeCrashFiles(String workingFolder, IProgressMonitor monitor) { |
|
659 if (crashFiles != null) { |
|
660 List<String> filesToBeDecoded = new ArrayList<String>(); |
|
661 // collect all binary file paths |
|
662 for (int i = 0; i < crashFiles.size(); i++) { |
|
663 CrashFileBundle crashFile = crashFiles.get(i); |
|
664 UndecodedFile udf = crashFile.getUndecodedFile(); |
|
665 filesToBeDecoded.add(udf.getFilePath()); |
|
666 } |
|
667 |
|
668 if (!filesToBeDecoded.isEmpty()) { |
|
669 String mapFilesFolder = decodingData.mapFilesFolder; |
|
670 |
|
671 // if MapFiles.zip is provided |
|
672 if (mapFilesFolder != null && "".equals(mapFilesFolder) |
|
673 && decodingData.mapFilesZip != null |
|
674 && !"".equals(decodingData.mapFilesZip)) { |
|
675 String zipFolder = FileOperations |
|
676 .addSlashToEnd(workingFolder) |
|
677 + FileOperations |
|
678 .addSlashToEnd(MAP_FILES_ZIP_FOLDER); |
|
679 FileOperations.createFolder(zipFolder, true); |
|
680 FileOperations.unZipFiles( |
|
681 new File(decodingData.mapFilesZip), zipFolder); |
|
682 mapFilesFolder = zipFolder; |
|
683 } |
|
684 CommandLineManager.executeFullAnalysis(workingFolder, |
|
685 filesToBeDecoded.toArray(new String[filesToBeDecoded |
|
686 .size()]), decodingData.symbolFiles, |
|
687 mapFilesFolder, decodingData.imageFiles, |
|
688 CrashAnalyserFile.OUTPUT_FILE_EXTENSION, |
|
689 ERROR_FILE_EXTENSION, getSelgeEventIniFile(), monitor); |
|
690 } |
|
691 } |
|
692 } |
|
693 |
|
694 /** |
|
695 * Moves re-decoded crash files from working folder to their own folders |
|
696 * under CrashFiles folder |
|
697 * |
|
698 * @param workingFolder |
|
699 * from where decoded files are moved from |
|
700 */ |
|
701 CrashFile moveReDecodedFiles(String workingFolder) { |
|
702 CrashFile cafile = null; |
|
703 File folder = new File(workingFolder); |
|
704 |
|
705 // accept output files (.crashxml) |
|
706 FilenameFilter filter = new FilenameFilter() { |
|
707 public boolean accept(File dir, String name) { |
|
708 return (name.endsWith(CrashAnalyserFile.OUTPUT_FILE_EXTENSION)); |
|
709 } |
|
710 }; |
|
711 |
|
712 File[] files = folder.listFiles(filter); |
|
713 |
|
714 // go through all found files |
|
715 for (int i = 0; i < files.length; i++) { |
|
716 try { |
|
717 File crashFile = files[i]; |
|
718 |
|
719 CrashFileBundle cfb = getCrashFileBundle(crashFile); |
|
720 if (cfb == null) |
|
721 continue; |
|
722 |
|
723 String crashFolder = FileOperations.addSlashToEnd(cfb |
|
724 .getOriginatingDirectory()); |
|
725 File fCrashFolder = new File(crashFolder); |
|
726 |
|
727 // folder should exist |
|
728 if (!fCrashFolder.exists()) |
|
729 continue; |
|
730 |
|
731 // copy crash file (.crashxml) to crash folder |
|
732 if (FileOperations.copyFile(crashFile, crashFolder, true)) { |
|
733 String[] crashFolderFiles = fCrashFolder.list(); |
|
734 |
|
735 // if only one file was decoded, pass this file eventually |
|
736 // to MainView so that this file can be opened up after decoding. |
|
737 if (files.length == 1) { |
|
738 cafile = CrashFile.read(crashFolder, |
|
739 decodingData.errorLibrary); |
|
740 } |
|
741 |
|
742 // remove .html and .xml files from crash folder if they |
|
743 // exist |
|
744 if (crashFolderFiles != null && crashFolderFiles.length > 0) { |
|
745 for (int j = 0; j < crashFolderFiles.length; j++) { |
|
746 String crashFolderFile = crashFolderFiles[j]; |
|
747 if (crashFolderFile.toLowerCase().endsWith( |
|
748 CrashFileBundle.EXTENSION_HTML) |
|
749 || crashFolderFile |
|
750 .toLowerCase() |
|
751 .endsWith( |
|
752 "." |
|
753 + CrashAnalyserFile.SUMMARY_FILE_EXTENSION)) |
|
754 FileOperations.deleteFile(crashFolder |
|
755 + crashFolderFile); |
|
756 } |
|
757 } |
|
758 } |
|
759 |
|
760 } catch (Exception e) { |
|
761 e.printStackTrace(); |
|
762 } |
|
763 } |
|
764 |
|
765 return cafile; |
|
766 } |
|
767 |
|
768 String getToolsPath() { |
|
769 String toolsPath = CrashAnalyserPlugin.getPluginInstallPath(); |
|
770 if (!toolsPath.endsWith(File.separator)) |
|
771 toolsPath += File.separator; |
|
772 toolsPath += TOOLS_FOLDER + File.separator; |
|
773 return toolsPath; |
|
774 } |
|
775 |
|
776 @Override |
|
777 protected IStatus run(IProgressMonitor monitor) { |
|
778 String workingFolder = ""; |
|
779 CrashAnalyserFile caFile = null; |
|
780 try { |
|
781 // we are importing files |
|
782 if (decodingData.importingFiles) { |
|
783 workingFolder = getWorkingFolder(false); |
|
784 importCrashFiles(workingFolder, monitor); |
|
785 caFile = moveDecodedFiles(workingFolder); |
|
786 // we are re-decoding selected crash files |
|
787 } else { |
|
788 workingFolder = getWorkingFolder(true); |
|
789 reDecodeCrashFiles(workingFolder, monitor); |
|
790 caFile = moveReDecodedFiles(workingFolder); |
|
791 } |
|
792 } catch (Exception e) { |
|
793 FileOperations.deleteFolder(workingFolder); |
|
794 decodingObserver.decodingFinished(e.getMessage(), caFile); |
|
795 return Status.OK_STATUS; |
|
796 } |
|
797 |
|
798 FileOperations.deleteFolder(workingFolder); |
|
799 decodingObserver.decodingFinished("", caFile); |
|
800 return Status.OK_STATUS; |
|
801 } |
|
802 } |