crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/model/TraceListener.java
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:06:45 +0200
changeset 0 5ad7ad99af01
child 4 615035072f7e
permissions -rw-r--r--
Initial version of CrashAnalyser under EPL

/*
* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/

package com.nokia.s60tools.crashanalyser.model;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.widgets.Display;
import com.nokia.s60tools.crashanalyser.data.*;
import com.nokia.s60tools.crashanalyser.interfaces.IErrorLibraryObserver;
import com.nokia.s60tools.crashanalyser.files.*;
import com.nokia.s60tools.crashanalyser.export.*;
import com.nokia.s60tools.crashanalyser.plugin.*;

/**
 * This class listens MobileCrash files via TraceViewer 
 *
 */
public class TraceListener implements ITraceDataProcessor, 
										IErrorLibraryObserver  {
	private final static String MOBILE_CRASH_STARTTAG = "<MB_CR_START>"; //$NON-NLS-1$
	private final static String MOBILE_CRASH_LINE_TAG = "<MB_CD>"; //$NON-NLS-1$
	private final static String MOBILE_CRASH_STOPTAG = "<MB_CR_STOP>"; //$NON-NLS-1$
	private final static String MOBILECRASH_START = "MobileCrash_"; //$NON-NLS-1$
	final String EXTENSION_TRACE_PROVIDER = "traceprovider"; //$NON-NLS-1$


	boolean listening = false;
	boolean mobileCrashStarted = false;
	BufferedWriter mcFile = null;
	String dumpFolder = ""; //$NON-NLS-1$
	File dumpFile;
	ErrorLibrary errorLibrary = null;
	boolean decode = false;
	private static ITraceProvider traceProvider = null;
	
	/**
	 * Constructor
	 */
	public TraceListener() {
		readTraceProvider();
	}
	
	/**
	 * Starts trace listening asynchronously
	 */
	public void errorLibraryReady() {
		Runnable refreshRunnable = new Runnable(){
			public void run(){
				startListening();
			}
		};
		
		Display.getDefault().asyncExec(refreshRunnable);        		
	}
	
	/**
	 * Activates MobileCrash file listening
	 */
	public void startListening() {
		if (errorLibrary == null) {
			errorLibrary = ErrorLibrary.getInstance(this);
			return;
		}
		
		if (listening || traceProvider == null)
			return;

		if (traceProvider.start(this))
			listening = true;
	}
	
	/**
	 * Sets whether we should decode imported files or just import them as undecoded state.
	 * @param decodeFiles 
	 */
	public void setDecode(boolean decodeFiles) {
		decode = decodeFiles;
	}
	
	/**
	 * De-activates MobileCrash file listening
	 */
	public void stopListening() {
		if (!listening)
			return;
		
		if (traceProvider != null)
			traceProvider.stop();
		listening = false;
	}

	/**
	 * All lines in trace data will be passed to this method. This method
	 * pics up MobileCrash file content from trace data.
	 * @param line trace data line
	 */
	public void processDataLine(String line) {
		int idx = line.indexOf(MOBILE_CRASH_STARTTAG);
		
		try {
			// Line contained <MC_CR_START>
			if (idx > -1) { 
				mobileCrashStarted = true;
				dumpFolder = FileOperations.addSlashToEnd(DecoderEngine.getNewCrashFolder());
				
				Calendar cal = Calendar.getInstance();
			    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS"); //$NON-NLS-1$
			    dumpFile = new File(dumpFolder +
			    					MOBILECRASH_START + 
			    					sdf.format(cal.getTime()) + 
			    					"." + 
			    					CrashAnalyserFile.TRACE_EXTENSION);		
				
			    // create a file for this mobilecrash
			    mcFile = new BufferedWriter(new FileWriter(dumpFile));
			    mcFile.write(line);
				mcFile.newLine();
				
			// Line did not contain <MC_CR_START>, but <MB_CR_START> has been found previously (i.e we are reading a file) 
			} else if (mobileCrashStarted){ 
				
				idx = line.indexOf(MOBILE_CRASH_LINE_TAG);
				// Line contained <MB_CD>, add data to file
				if (idx > -1) { 
					mcFile.write(line);
					mcFile.newLine();
				// Line did not contain <MB_CD>
				} else { 
					idx = line.indexOf(MOBILE_CRASH_STOPTAG);
					// Line contained <MC_CR_STOP>, we can finish reading this mobile crash file
					if (idx > -1) {
						mcFile.write(line);
						mcFile.newLine();
						mcFile.close();
						mcFile = null;
						mobileCrashStarted = false;
						
						// give this mobilecrash file for further processing
						MobileCrashImporter tc = new MobileCrashImporter();
						tc.importFrom(dumpFolder, dumpFile.getName(), errorLibrary, decode);
					}
				}
			}
		} catch (Exception e) {
			if (mcFile != null) {
				try {mcFile.close();}catch (Exception E) {E.printStackTrace();}
			}
			mcFile = null;
			mobileCrashStarted = false;
			e.printStackTrace();
		}
	}
	
	/**
	 * Returns whether we have found trace provider plugins.
	 * @return true if trace providers were found, false if not
	 */
	public static boolean traceProviderAvailable() {
		if (traceProvider == null)
			return false;
		return true;
	}
	
	/**
	 * Tries to find plugins which are Trace Providers. Selected the first found
	 * Trace provider plugin.
	 */
	void readTraceProvider() {
		try {
			IExtensionRegistry er = Platform.getExtensionRegistry();
			IExtensionPoint ep = 
				er.getExtensionPoint(CrashAnalyserPlugin.PLUGIN_ID, EXTENSION_TRACE_PROVIDER);
			IExtension[] extensions = ep.getExtensions();
			
			// if plug-ins were found.
			if (extensions != null && extensions.length > 0) {
				
				// read all found trace providers
				for (int i = 0; i < extensions.length; i++) {
					IConfigurationElement[] ce = extensions[i].getConfigurationElements();
					if (ce != null && ce.length > 0) {
						try {
							ITraceProvider provider = (ITraceProvider)ce[0].createExecutableExtension("class");
							// we support only one trace provider
							if (provider != null) {
								traceProvider = provider;
								break;
							}
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}