crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/model/DecoderEngine.java
changeset 0 5ad7ad99af01
child 4 615035072f7e
equal deleted inserted replaced
-1:000000000000 0:5ad7ad99af01
       
     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 }