crashanalysis/crashanalyser/com.nokia.s60tools.crashanalyser/src/com/nokia/s60tools/crashanalyser/containers/Process.java
author Jussi Ryoma <ext-jussi.s.ryoma@nokia.com>
Tue, 24 Aug 2010 14:01:48 +0300
changeset 16 72f198be1c1d
parent 0 5ad7ad99af01
permissions -rw-r--r--
Crash Analyser Carbide Extension 1.4.0

/*
* 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.containers;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.NamedNodeMap;
import java.io.*;
import com.nokia.s60tools.crashanalyser.model.XmlUtils;
import java.util.*;

/**
 * A process class. Contains all process information.
 * This class owns this process' threads and code segments 
 *
 */
public final class Process {
	
	// XML tags
	public static final String TAG_ID = "id";
	public static final String TAG_NAME = "name";
	public static final String TAG_UID1 = "uid1";
	public static final String TAG_UID2 = "uid2";
	public static final String TAG_UID3 = "uid3";
	public static final String TAG_SID = "sid";
	public static final String TAG_LINK = "link";
	public static final String ATTRIBUTE_SEG = "seg";
	public static final String SEGMENT_THREADS = "seg_threads";
	public static final String SEGMENT_CODESEGS = "seg_codesegs";
	
	public static enum StackItems {ALL, SYMBOLS, ACCURATE};
	
	static final String FORMAT = "%-13s: %s";

	// process data
	private final int processId;
	private final String processName;
	private final String processUid1;
	private final String processUid2;
	private final String processUid3;
	private final String processSid;
	private final List<Thread> processThreads;
	private final List<CodeSegment> processCodeSegments;
	
	/**
	 * Constructor 
	 * @param id process id
	 * @param name process name
	 * @param uid1 process UID1
	 * @param uid2 process UID2
	 * @param uid3 process UID3
	 * @param sid process SID
	 * @param threads threads of the process
	 * @param codeSegments code segments of the process
	 */
	private Process(final int id, final String name, final String uid1, final String uid2, final String uid3, final String sid,
					final List<Thread> threads, final List<CodeSegment> codeSegments) {
		processId = id;
		processName = name;
		processUid1 = uid1;
		processUid2 = uid2;
		processUid3 = uid3;
		processSid = sid;
		processThreads = threads;
		processCodeSegments = codeSegments;
	}
	
	public int getId() {
		return processId;
	}
	
	public String getName() {
		return processName;
	}
	
	public List<CodeSegment> getCodeSegments() {
		return processCodeSegments;
	}
	
	/**
	 * Writes process data into given buffer (i.e text file)
	 * @param out buffer to write to
	 * @param stackItems
	 * @param html defines whether html format should be written
	 * @throws IOException
	 */
	public void writeTo(final BufferedWriter out, final StackItems stackItems, final boolean html) throws IOException {
		
		// write basic process data
		writeLine(out,"");
		writeLine(out, "PROCESS:");
		writeLine(out, "--------");
		writeLine(out, "Process Name", processName);
		writeLine(out, "Uid1", processUid1);
		writeLine(out, "Uid2", processUid2);
		writeLine(out, "Uid3", processUid3);
		writeLine(out, "Sid", processSid);
		writeLine(out, "");
		
		// write code segments of the process
		if (processCodeSegments != null && !processCodeSegments.isEmpty()) {
			writeLine(out, "CODE SEGMENTS:");
			writeLine(out, "--------------");
			for (int i = 0; i < processCodeSegments.size(); i++) {
				final CodeSegment codeSegment = processCodeSegments.get(i);
				codeSegment.writeTo(out);
			}
			writeLine(out, "");
		}

		// write threads of the process
		if (processThreads != null && !processThreads.isEmpty()) {
			for (int i = 0; i < processThreads.size(); i++) {
				final Thread thread = processThreads.get(i);
				thread.writeTo(out, stackItems, html);
				writeLine(out, "");
			}
			writeLine(out, "");
		}
	}
	
	void writeLine(final BufferedWriter out, final String line) throws IOException {
		out.write(line);
		out.newLine();
	}

	void writeLine(final BufferedWriter out, final String header, final String value) throws IOException {
		if (!"".equals(value)) {
			out.write(String.format(FORMAT, header, value));
			out.newLine();
		}
	}

	/**
	 * Reads and creates a process from process xml element
	 * @param elementProcess
	 * @param threads
	 * @param codeSegments
	 * @return created process or null
	 */
	public static Process read(final Element elementProcess, 
								final Map<Integer, Thread> threads,
								final Map<Integer, CodeSegment> codeSegments) {
		try {
			if (threads == null || threads.isEmpty())
				return null;
			
			// read process id
			final String processId = XmlUtils.getTextValue(elementProcess, TAG_ID);
			if (processId == null)
				return null;
			
			// convert process id to integer
			final int id = Integer.parseInt(processId);
			
			// read process name
			final String  processName = XmlUtils.getTextValue(elementProcess, TAG_NAME);
			if (processName == null)
				return null;
			
			// read UID1 if exists
			String uid1 = XmlUtils.getTextValue(elementProcess, TAG_UID1);
			if (uid1 == null)
				uid1 = "";
			
			// read UID2 if exists
			String uid2 = XmlUtils.getTextValue(elementProcess, TAG_UID2);
			if (uid2 == null)
				uid2 = "";
	
			// read UID# if exists
			String uid3 = XmlUtils.getTextValue(elementProcess, TAG_UID3);
			if (uid3 == null)
				uid3 = "";
	
			// read SID if exists
			String sid = XmlUtils.getTextValue(elementProcess, TAG_SID);
			if (sid == null)
				sid = "";
			
			// get link nodes for thread and codesegment ids
			final NodeList nl = elementProcess.getElementsByTagName(TAG_LINK);
			if (nl == null || nl.getLength() < 1)
				return null;

			final List<Thread> processThreads = new ArrayList<Thread>();
			final List<CodeSegment> processCodesegments = new ArrayList<CodeSegment>();

			// read threads and code segments
			for (int i = 0; i < nl.getLength(); i++) {
				final Node node = nl.item(i);
				final String nodeValue = XmlUtils.getNodeValue(node);
				final NamedNodeMap attributes = node.getAttributes();
				if (attributes != null && attributes.getLength() > 0) {
					final Node seg = attributes.getNamedItem(ATTRIBUTE_SEG);
					// thread id
					if (SEGMENT_THREADS.equals(XmlUtils.getNodeValue(seg))) {
						final int tId = Integer.parseInt(nodeValue);
						if (threads.containsKey(tId))
							processThreads.add(threads.get(tId));
					// codesegment id
					} else if (SEGMENT_CODESEGS.equals(XmlUtils.getNodeValue(seg))) {
						final int segmentId = Integer.parseInt(nodeValue);
						if (codeSegments.containsKey(segmentId))
							processCodesegments.add(codeSegments.get(segmentId));
					}
				}
			}
			
			if (processThreads.isEmpty())
				return null;
			
			return new Process(id, processName, uid1, uid2, uid3, sid, processThreads, processCodesegments);
			
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * Returns the first thread of this process
	 * @return first thread of this process or null
	 */
	public Thread getFirstThread() {
		Thread thread = null;
		if (processThreads != null && !processThreads.isEmpty())
			thread = processThreads.get(0);
			
		return thread;
	}
	
	/**
	 * Returns the threads of this process
	 * @return threads of this process or null
	 */
	public List<Thread> getThreads() {
		return processThreads;
	}
}