tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/TraceCompiler.java
changeset 56 aa2539c91954
parent 41 838cdffd57ce
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     1 /*
       
     2  * Copyright (c) 2010 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  * TraceCompiler command-line main class
       
    17  *
       
    18  */
       
    19 package com.nokia.tracecompiler;
       
    20 
       
    21 import java.io.BufferedReader;
       
    22 import java.io.File;
       
    23 import java.io.IOException;
       
    24 import java.io.InputStreamReader;
       
    25 import java.net.URL;
       
    26 import java.util.ArrayList;
       
    27 import java.util.Arrays;
       
    28 import java.util.List;
       
    29 
       
    30 import com.nokia.tracecompiler.document.FileDocumentMonitor;
       
    31 import com.nokia.tracecompiler.document.StringDocumentFactory;
       
    32 import com.nokia.tracecompiler.engine.TraceCompilerEngineEvents;
       
    33 import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
       
    34 import com.nokia.tracecompiler.engine.TraceCompilerEngineInterface;
       
    35 import com.nokia.tracecompiler.engine.TraceLocationList;
       
    36 import com.nokia.tracecompiler.engine.project.ProjectEngine;
       
    37 import com.nokia.tracecompiler.engine.utils.TraceUtils;
       
    38 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    39 import com.nokia.tracecompiler.model.TraceModel;
       
    40 import com.nokia.tracecompiler.plugin.TraceCompilerPlugin;
       
    41 import com.nokia.tracecompiler.project.GroupNames;
       
    42 import com.nokia.tracecompiler.source.SourceConstants;
       
    43 import com.nokia.tracecompiler.source.SymbianConstants;
       
    44 import com.nokia.tracecompiler.utils.DocumentFactory;
       
    45 import com.nokia.tracecompiler.utils.TraceCompilerVersion;
       
    46 
       
    47 /**
       
    48  * TraceCompiler command-line main class
       
    49  * 
       
    50  */
       
    51 public class TraceCompiler {
       
    52 	
       
    53 	private static String LINE_SEPARATOR =  System.getProperty("line.separator"); //$NON-NLS-1$
       
    54 
       
    55 	/**
       
    56 	 * Index of third character
       
    57 	 */
       
    58 	private static final int INDEX_OF_THIRD_CHARACTER = 2;
       
    59 
       
    60 	/**
       
    61 	 * Index of first character
       
    62 	 */
       
    63 	private static final int INDEX_OF_FIRST_CHARACTER = 0;
       
    64 
       
    65 	/**
       
    66 	 * Version option
       
    67 	 */
       
    68 	private static final String VERSION_OPTION = "--version"; //$NON-NLS-1$
       
    69 	private static final String LEGACY_VERSION_OPTION = "-version"; //$NON-NLS-1$
       
    70 	private static final String VERSION_OPTION_SF = "-v"; //$NON-NLS-1$
       
    71 	/**
       
    72 	 * Version option instruction text
       
    73 	 */
       
    74 	private static final String VERSION_OPTION_INSTRUCTION_TEXT = "print TraceCompiler version"; //$NON-NLS-1$
       
    75 
       
    76 	
       
    77 	/**
       
    78 	 * help option
       
    79 	 */
       
    80 	private static final String HELP_OPTION = "--help"; //$NON-NLS-1$
       
    81 	private static final String HELP_OPTION_SF = "-h"; //$NON-NLS-1$
       
    82 	private static final String HELP_OPTION_INSTRUCTION_TEXT = "print help"; //$NON-NLS-1$
       
    83 	
       
    84 	/**
       
    85 	 * Verbose option
       
    86 	 */
       
    87 	private static final String VERBOSE_OPTION = "--verbose"; //$NON-NLS-1$
       
    88 	private static final String VERBOSE_OPTION_SF = "-vb"; //$NON-NLS-1$
       
    89 	/**
       
    90 	 * Verbose option instruction text
       
    91 	 */
       
    92 	private static final String VERBOSE_OPTION_INSTRUCTION_TEXT = "print info messages."; //$NON-NLS-1$
       
    93 
       
    94 	/**
       
    95 	 * keep going option
       
    96 	 */
       
    97 	private static final String STOP_ON_ERROR_OPTION = "--stopOnError"; //$NON-NLS-1$
       
    98 	private static final String STOP_ON_ERROR_OPTION_SF = "-soe"; //$NON-NLS-1$
       
    99 	/**
       
   100 	 * keep going option instruction text
       
   101 	 */
       
   102 	private static final String STOP_ON_ERROR_OPTION_INSTRUCTION_TEXT = "On error, stop at the end of the compilation unit."; //$NON-NLS-1$
       
   103 
       
   104 	
       
   105 
       
   106 	/**
       
   107 	 * Version text
       
   108 	 */
       
   109 	private static final String VERSION_TEXT = "TraceCompiler version "; //$NON-NLS-1$
       
   110 
       
   111 	/**
       
   112 	 * Option instruction text
       
   113 	 */
       
   114 	private static final String OPTION_INSTRUCTION_TEXT = "Options:"; //$NON-NLS-1$
       
   115 
       
   116 	
       
   117 	private static final String USAGE = "Usage: " + LINE_SEPARATOR + //$NON-NLS-1$
       
   118 										"tracecompiler [options] Component_UID [Component_name MMP_path source_file...]" + LINE_SEPARATOR + //$NON-NLS-1$
       
   119 										"\t" + OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR + //$NON-NLS-1$
       
   120 										"\t" + HELP_OPTION_SF  + ", " + HELP_OPTION + ", " + HELP_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR +   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   121 										"\t" + VERSION_OPTION_SF + ", " + VERSION_OPTION + ", " + LEGACY_VERSION_OPTION + "\t" +  VERSION_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR +   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
       
   122 										"\t" + VERBOSE_OPTION_SF + ", " + VERBOSE_OPTION + "\t\t" + VERBOSE_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR +  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
       
   123 										"\t" + STOP_ON_ERROR_OPTION_SF + ", " + STOP_ON_ERROR_OPTION + "\t" + STOP_ON_ERROR_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR;  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
       
   124 
       
   125 
       
   126 
       
   127 	/**
       
   128 	 * End of source files tag
       
   129 	 */
       
   130 	private static final String ENDOFSOURCEFILES = "*ENDOFSOURCEFILES*"; //$NON-NLS-1$
       
   131 	
       
   132 
       
   133 	/**
       
   134 	 * Offset to UID
       
   135 	 */
       
   136 	private static final int COMPONENT_UID_ARG = 0;
       
   137 
       
   138 	/**
       
   139 	 * Offset to component name
       
   140 	 */
       
   141 	private static final int COMPONENT_NAME_ARG = 1;
       
   142 
       
   143 	/**
       
   144 	 * Offset to MMP path
       
   145 	 */
       
   146 	private static final int COMPONENT_MMP_PATH_ARG = 2; // CodForChk_Dis_Magic
       
   147 
       
   148 	/**
       
   149 	 * Offset to source files
       
   150 	 */
       
   151 	private static final int SOURCE_FILE_START_OFFSET = 3; // CodForChk_Dis_Magic
       
   152 
       
   153 	/**
       
   154 	 * Number of arguments
       
   155 	 */
       
   156 	private static final int MANDATORY_ARGUMENT_COUNT = 1;
       
   157 
       
   158 	/**
       
   159 	 * MMP file extension
       
   160 	 */
       
   161 	private static final String MMP = ".mmp"; //$NON-NLS-1$
       
   162 
       
   163 	/**
       
   164 	 * Underscore character
       
   165 	 */
       
   166 	private static final String UNDERSCORE = "_"; //$NON-NLS-1$
       
   167 
       
   168 	/**
       
   169 	 * Name of the trace folder that include component name
       
   170 	 */
       
   171 	private String traceFolderName;
       
   172 
       
   173 	/**
       
   174 	 * Decode plugins path
       
   175 	 */
       
   176 	private String DECODE_PLUGINS_PATH = "com/nokia/tracecompiler/decodeplugins"; //$NON-NLS-1$
       
   177 
       
   178 	/**
       
   179 	 * Decode plugin name tag
       
   180 	 */
       
   181 	private String DECODE_PLUGIN_NAME_TAG = "<DECODE_PLUGIN_NAME>"; //$NON-NLS-1$
       
   182 
       
   183 	/**
       
   184 	 * Decode plugin class name tag
       
   185 	 */
       
   186 	private String DECODE_PLUGIN_CLASS_NAME_TAG = "<DECODE_PLUGIN_CLASS_NAME>"; //$NON-NLS-1$
       
   187 
       
   188 	/**
       
   189 	 * Decode plugin engine class name template
       
   190 	 */
       
   191 	private String ENGINE_CLASS_NAME_TEMPLATE = DECODE_PLUGIN_NAME_TAG
       
   192 			+ "Engine"; //$NON-NLS-1$
       
   193 
       
   194 	/**
       
   195 	 * Decode plugin engine file name template
       
   196 	 */
       
   197 	private String ENGINE_FILE_NAME_TEMPLATE = DECODE_PLUGIN_CLASS_NAME_TAG
       
   198 			+ ".class"; //$NON-NLS-1$
       
   199 
       
   200 	/**
       
   201 	 * Decode plugins class template
       
   202 	 */
       
   203 	private String CLASS_TEMPLATE = "com.nokia.tracecompiler.decodeplugins." + DECODE_PLUGIN_NAME_TAG + "." + DECODE_PLUGIN_CLASS_NAME_TAG; //$NON-NLS-1$ //$NON-NLS-2$	
       
   204 
       
   205 	/**
       
   206 	 * Main function
       
   207 	 * 
       
   208 	 * @param args
       
   209 	 *            the command line arguments
       
   210 	 */
       
   211 	public static void main(String[] args) {
       
   212 		ArrayList<String> list = new ArrayList<String>(Arrays.asList(args));
       
   213 		long startTime = System.currentTimeMillis();
       
   214 		//create a new session of TraceCompiler
       
   215 		TraceCompiler console = new TraceCompiler();
       
   216 		
       
   217 		try {
       
   218 			console.parseCommandLine(list);
       
   219 		} catch (Exception e) { //should cover IOException and TraceCompilerIllegalArgumentsException
       
   220 			//There is no point to continue if there are problems with the arguments.
       
   221 			TraceCompilerLogger.printError(e.getMessage());
       
   222 			printUsage();
       
   223 			System.exit(1);
       
   224 		}
       
   225 		
       
   226 		boolean error = false;
       
   227 		try {
       
   228 			if(list.size() != 0) {
       
   229 				console.createPlugins();
       
   230 				console.start();
       
   231 				console.buildTraceFiles();
       
   232 				
       
   233 			}
       
   234 		} catch (Exception e) {
       
   235 			if (e instanceof TraceCompilerRootException) {
       
   236 				TraceCompilerLogger.printError(e.getMessage()); 
       
   237 			} //else the error should have been reported earlier
       
   238 			error = true;
       
   239 		} finally {
       
   240 			try {
       
   241 				if (!error) { //check if errors have been logged by EventEngine
       
   242 					TraceCompilerEngineEvents events = TraceCompilerEngineGlobals.getEvents();
       
   243 					if (events != null && events.hasErrorHappened()) {
       
   244 						error = true;
       
   245 					}
       
   246 				}
       
   247 				console.shutdown();
       
   248 			} catch (TraceCompilerException e) {
       
   249 				error = true;
       
   250 			}
       
   251 		}
       
   252 
       
   253 		if (console.componentName != null) {
       
   254 			TraceCompilerLogger.printMessage(console.componentName + " took " //$NON-NLS-1$
       
   255 					+ (System.currentTimeMillis() - startTime) + " ms"); //$NON-NLS-1$
       
   256 		}
       
   257 		if (error) {
       
   258 			System.exit(1);
       
   259 		} else {
       
   260 			System.exit(0);
       
   261 		}	
       
   262 	}
       
   263 
       
   264 	/**
       
   265 	 * With Eclipse, the plug-ins are loaded by Eclipse framework. Here they
       
   266 	 * must be manually created and started
       
   267 	 */
       
   268 	private ArrayList<TraceCompilerPlugin> plugIns = new ArrayList<TraceCompilerPlugin>();
       
   269 
       
   270 	/**
       
   271 	 * Model listener
       
   272 	 */
       
   273 	private TraceCompilerModelListener modelListener;
       
   274 
       
   275 	/**
       
   276 	 * Name of the component
       
   277 	 */
       
   278 	private String componentName;
       
   279 
       
   280 	/**
       
   281 	 * UID of the component
       
   282 	 */
       
   283 	private long componentUID;
       
   284 
       
   285 	/**
       
   286 	 * Component path
       
   287 	 */
       
   288 	private String componentPath;
       
   289 
       
   290 	/**
       
   291 	 * MMP file path
       
   292 	 */
       
   293 	private File mmpPath;
       
   294 
       
   295 	/**
       
   296 	 * Constructor
       
   297 	 */
       
   298 	TraceCompiler() {
       
   299 
       
   300 		// Creates listeners and preferences
       
   301 		modelListener = new TraceCompilerModelListener();
       
   302 	}
       
   303 
       
   304 	/**
       
   305 	 * Creates the plug-ins to be registered with TraceCompiler
       
   306 	 * @throws TraceCompilerRootException if fail to create a valid plugins
       
   307 	 */
       
   308 	private void createPlugins() throws TraceCompilerRootException {
       
   309 		
       
   310 		// Get location of the TraceCompiler
       
   311 		URL path = getClass().getProtectionDomain().getCodeSource()
       
   312 				.getLocation();
       
   313 		String decodePluginsPath = path.getPath();
       
   314 
       
   315 		// If first character is forward slash and it is located before drive
       
   316 		// letter remove it
       
   317 		if (decodePluginsPath.charAt(INDEX_OF_FIRST_CHARACTER) == SourceConstants.FORWARD_SLASH_CHAR
       
   318 				&& decodePluginsPath.charAt(INDEX_OF_THIRD_CHARACTER) == SourceConstants.COLON_CHAR) {
       
   319 			decodePluginsPath = decodePluginsPath.substring(1);
       
   320 		}
       
   321 		
       
   322 		// Concatenate decode plugins path
       
   323 		decodePluginsPath = decodePluginsPath.concat(DECODE_PLUGINS_PATH);
       
   324 		
       
   325 		// Replace slashes with correct separator character
       
   326 		decodePluginsPath = decodePluginsPath.replace(
       
   327 				SourceConstants.FORWARD_SLASH_CHAR, File.separatorChar);
       
   328 		decodePluginsPath = decodePluginsPath.replace(
       
   329 				SourceConstants.BACKSLASH_CHAR, File.separatorChar);
       
   330 		File decodePluginsDir = new File(decodePluginsPath);
       
   331 		String[] decodePlugins = decodePluginsDir.list();
       
   332 		if (decodePlugins != null) {
       
   333 			for (int i = 0; i < decodePlugins.length; i++) {
       
   334 
       
   335 				// Get decode plugin name
       
   336 				String decodePluginName = decodePlugins[i];
       
   337 
       
   338 				// Get decode plugin path
       
   339 				String decodePluginPath = decodePluginsPath
       
   340 						+ File.separatorChar + decodePluginName;
       
   341 
       
   342 				// Decode plugin must be in own directory
       
   343 				Boolean isDirectory = (new File(decodePluginPath))
       
   344 						.isDirectory();
       
   345 				if (isDirectory) {
       
   346 
       
   347 					// Construct decode plugin engine class name
       
   348 					String engineClassName = ENGINE_CLASS_NAME_TEMPLATE
       
   349 							.replaceFirst(DECODE_PLUGIN_NAME_TAG,
       
   350 									decodePluginName.substring(0, 1)
       
   351 											.toUpperCase()
       
   352 											+ decodePluginName.substring(1));
       
   353 
       
   354 					// Construct decode plugin engine file name
       
   355 					String engineFileName = ENGINE_FILE_NAME_TEMPLATE
       
   356 							.replaceFirst(DECODE_PLUGIN_CLASS_NAME_TAG,
       
   357 									engineClassName);
       
   358 					String engineFileFullName = decodePluginPath
       
   359 							+ File.separatorChar + engineFileName;
       
   360 
       
   361 					// Check does engine file exist
       
   362 					Boolean exists = (new File(engineFileFullName)).exists();
       
   363 					if (exists) {
       
   364 						String engineClassFullName = CLASS_TEMPLATE
       
   365 								.replaceFirst(DECODE_PLUGIN_NAME_TAG,
       
   366 										decodePluginName).replaceFirst(
       
   367 										DECODE_PLUGIN_CLASS_NAME_TAG,
       
   368 										engineClassName);
       
   369 						try {
       
   370 							Class<?> engineClass = Class
       
   371 									.forName(engineClassFullName);
       
   372 							TraceCompilerPlugin engine = (TraceCompilerPlugin) engineClass
       
   373 									.newInstance();
       
   374 							plugIns.add(engine);
       
   375 							TraceCompilerLogger.printInfo("Decode plugin " + engineClassFullName + " added"); //$NON-NLS-1$ //$NON-NLS-2$
       
   376 						} catch (Exception e) {
       
   377 							String msg = "Decode plugin " + engineClassFullName + " adding failed"; //$NON-NLS-1$ //$NON-NLS-2$
       
   378 							throw new TraceCompilerRootException(msg, e); 
       
   379 						}
       
   380 					} else {
       
   381 						String msg = "Decode plugin file " + engineFileFullName + " does not exist"; //$NON-NLS-1$ //$NON-NLS-2$
       
   382 						throw new TraceCompilerRootException(msg, null);
       
   383 					}
       
   384 				}
       
   385 			}
       
   386 		}
       
   387 	}
       
   388 
       
   389 	/**
       
   390 	 * Parses the command line
       
   391 	 * 
       
   392 	 * @param args
       
   393 	 *            the arguments
       
   394 	 * @throws TraceCompilerRootException if arguments are invalid
       
   395 	 * @throws IOException 
       
   396 	 */
       
   397 	private void parseCommandLine(ArrayList<String> list) throws TraceCompilerIllegalArgumentsException, IOException {
       
   398 		TraceCompilerLogger.printInfo("Building traces..."); //$NON-NLS-1$
       
   399 		if (list.size() == 0) {
       
   400 			printUsage();
       
   401 			System.exit(0);
       
   402 		}
       
   403 		List<String> switches = new ArrayList<String>();
       
   404 
       
   405 		// version, verbose, keepgoing if available could be anywhere, so process them and remove them from the list
       
   406 		for (String element : list) {
       
   407 			if (element.equalsIgnoreCase(HELP_OPTION) || element.equalsIgnoreCase(HELP_OPTION_SF)) {
       
   408 				printUsage();
       
   409 				System.exit(0);
       
   410 			}
       
   411 			if (element.equalsIgnoreCase(VERBOSE_OPTION) || element.equalsIgnoreCase(VERBOSE_OPTION_SF)) {
       
   412 				TraceCompilerGlobals.setVerbose(true);
       
   413 				switches.add(element);
       
   414 			}
       
   415 			if (element.equalsIgnoreCase(LEGACY_VERSION_OPTION) || element.equalsIgnoreCase(VERSION_OPTION) || element.equalsIgnoreCase(VERSION_OPTION_SF)) {
       
   416 				TraceCompilerLogger.printMessage(VERSION_TEXT + TraceCompilerVersion.getVersion());
       
   417 				System.exit(0);
       
   418 			}
       
   419 			if (element.equalsIgnoreCase(STOP_ON_ERROR_OPTION) || element.equalsIgnoreCase(STOP_ON_ERROR_OPTION_SF)) {
       
   420 				TraceCompilerGlobals.setKeepGoing(false);
       
   421 				switches.add(element);
       
   422 			}
       
   423 		}
       
   424 		
       
   425 		//remove switches from the list
       
   426 		for (String string : switches) {
       
   427 			list.remove(string);
       
   428 		}
       
   429 		
       
   430 		switches = null;
       
   431 		
       
   432 		if (list.size() < MANDATORY_ARGUMENT_COUNT) {
       
   433 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.invalidTraceCompilerArgumetsExceptionText"), null); //$NON-NLS-1$
       
   434 		}
       
   435 		
       
   436 		
       
   437 		//the rest of elements must be in the order COMPONENT_UID, COMPONENT_NAME, COMPONENT_MMP_PATH, source...
       
   438 		//COMPONENT_UID must be on the command line, the rest can either be on the command line or stdin
       
   439 
       
   440 		try {
       
   441 			componentUID = Long.parseLong(list.get(COMPONENT_UID_ARG),
       
   442 					TraceCompilerConstants.HEX_RADIX);
       
   443 			TraceCompilerLogger.printInfo("Component UID: 0x" + Long.toHexString(componentUID)); //$NON-NLS-1$
       
   444 
       
   445 		} catch (NumberFormatException e) {
       
   446 			String msg = Messages.getString("TraceCompiler.componentUidIsNotValidExceptionText") + componentUID; //$NON-NLS-1$
       
   447 			throw new TraceCompilerIllegalArgumentsException(msg, null);
       
   448 		}
       
   449 		if (componentUID > 0) {
       
   450 
       
   451 			// Arguments are given as a parameter
       
   452 			if (list.size() > MANDATORY_ARGUMENT_COUNT + 1) {
       
   453 				parseParameters(list);
       
   454 
       
   455 				// Otherwise, read arguments from STDIN
       
   456 			} else {
       
   457 				readFromStdin();
       
   458 			}
       
   459 		} else {
       
   460 			String msg = Messages.getString("TraceCompiler.componentUidIsNotValidExceptionText") + componentUID; //$NON-NLS-1$
       
   461 			throw new TraceCompilerIllegalArgumentsException(msg, null);
       
   462 		}
       
   463 	}
       
   464 
       
   465 
       
   466 	private static void printUsage() {
       
   467 		TraceCompilerLogger.printMessage(VERSION_TEXT + TraceCompilerVersion.getVersion());
       
   468 		TraceCompilerLogger.printMessage(USAGE);
       
   469 	}
       
   470 
       
   471 	/**
       
   472 	 * Parses parameters
       
   473 	 * 
       
   474 	 * @param args
       
   475 	 *            the parameters
       
   476 	 * @throws TraceCompilerRootException if arguments are not valid
       
   477 	 */
       
   478 	private void parseParameters(List<String> args) throws TraceCompilerIllegalArgumentsException {
       
   479 		//index is safe, already checked by the caller
       
   480 		componentName = args.get(COMPONENT_NAME_ARG);
       
   481 		traceFolderName = 	TraceCompilerConstants.TRACES_DIRECTORY + UNDERSCORE
       
   482 							+ componentName;
       
   483 		
       
   484 		mmpPath = new File(args.get(COMPONENT_MMP_PATH_ARG));
       
   485 
       
   486 		if (isMmpValid()) {
       
   487 
       
   488 			// Move the files from args array to source file list
       
   489 				ArrayList<String> sources = new ArrayList<String>();
       
   490 				for (int i = 0; i < args.size() - SOURCE_FILE_START_OFFSET; i++) {
       
   491 					sources.add(args.get(SOURCE_FILE_START_OFFSET + i));
       
   492 				}
       
   493 
       
   494 				registerFiles(sources);
       
   495 		} else {
       
   496 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.invalidMmpExceptionText") + mmpPath, null); //$NON-NLS-1$
       
   497 		}
       
   498 		
       
   499 	}
       
   500 
       
   501 	/**
       
   502 	 * Read information from STDIN
       
   503 	 * @throws IOException if fails to read the input
       
   504 	 * @throws TraceCompilerRootException if the list of files is empty
       
   505 	 */
       
   506 	private void readFromStdin() throws IOException, TraceCompilerIllegalArgumentsException {
       
   507 		ArrayList<String> files = new ArrayList<String>();
       
   508 
       
   509 		// Create reader
       
   510 		BufferedReader stdin = new BufferedReader(
       
   511 				new InputStreamReader(System.in));
       
   512 		
       
   513 			int numberOfReceivedLines = 1;
       
   514 
       
   515 			String line = stdin.readLine();
       
   516 						
       
   517 			while (line != null) {
       
   518 
       
   519 				// End of source files received
       
   520 				if (line.equals(ENDOFSOURCEFILES)) {
       
   521 					break;
       
   522 				}
       
   523 
       
   524 				// Component name
       
   525 				if (numberOfReceivedLines == COMPONENT_NAME_ARG) {
       
   526 					componentName = line;
       
   527 					traceFolderName = TraceCompilerConstants.TRACES_DIRECTORY
       
   528 							+ UNDERSCORE + componentName;
       
   529 
       
   530 					// MMP path
       
   531 				} else if (numberOfReceivedLines == COMPONENT_MMP_PATH_ARG) {
       
   532 					mmpPath = new File(line);
       
   533 					if (!isMmpValid()) {
       
   534 						stdin.close();
       
   535 						throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.invalidMmpExceptionText") + mmpPath, null); //$NON-NLS-1$
       
   536 					}
       
   537 
       
   538 					// Source files
       
   539 				} else {
       
   540 					// Add to the files list
       
   541 					File file = new File(line);
       
   542 					files.add(file.getAbsolutePath());
       
   543 				}
       
   544 
       
   545 				numberOfReceivedLines++;
       
   546 
       
   547 				// Read new line from STDIN
       
   548 				line = stdin.readLine();				
       
   549 			}
       
   550 		stdin.close();
       
   551 		registerFiles(files);
       
   552 	}
       
   553 
       
   554 	/**
       
   555 	 * Registers files to document monitor.
       
   556 	 * 
       
   557 	 * @param sources
       
   558 	 *            sources
       
   559 	 * @throws TraceCompilerRootException 
       
   560 	 */
       
   561 	private void registerFiles(ArrayList<String> sources) throws TraceCompilerIllegalArgumentsException {
       
   562 
       
   563 		if (sources.size() == 0) {
       
   564 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.noSourceFilesExceptionText"), null); //$NON-NLS-1$
       
   565 		}
       
   566 		File parent = mmpPath.getParentFile();
       
   567 		boolean found = false;
       
   568 
       
   569 		componentPath = parent.getAbsolutePath();
       
   570 
       
   571 		ProjectEngine.traceFolderName = TraceCompilerConstants.TRACES_DIRECTORY;
       
   572 
       
   573 		// Find location of "traces" or "traces_<component name>" -folder. If
       
   574 		// "traces" or "traces_<component name>" -folder does not
       
   575 		// exist, "traces" -folder will be add to same level than "group" or
       
   576 		// "mmpfiles" -folder. If "group" or "mmpfiles" -folder does not exist
       
   577 		// then "traces" -folder will be added to same level than source file.
       
   578 		while (!found && parent != null) {
       
   579 			File[] children = parent.listFiles();
       
   580 			if (children != null) {
       
   581 				for (int i = 0; i < children.length; i++) {
       
   582 					File child = children[i];
       
   583 					String childName = child.getName();
       
   584 					if (child.isDirectory() && isProjectRoot(childName)) {
       
   585 						componentPath = parent.getAbsolutePath();
       
   586 						found = true;
       
   587 
       
   588 						// Check that does subdirectory that name is
       
   589 						// "traces_<component name>" exist in this directory. If
       
   590 						// it exist use that as traces directory name.
       
   591 						for (i = 0; i < children.length; i++) {
       
   592 							child = children[i];
       
   593 							childName = child.getName();
       
   594 							if (child.isDirectory()
       
   595 									&& childName
       
   596 											.equalsIgnoreCase(traceFolderName)) {
       
   597 								ProjectEngine.traceFolderName = traceFolderName;
       
   598 								break;
       
   599 							}
       
   600 						}
       
   601 						break;
       
   602 					}
       
   603 				}
       
   604 			}
       
   605 
       
   606 			if (found == false) {
       
   607 				parent = parent.getParentFile();
       
   608 			}
       
   609 		}
       
   610 
       
   611 		registerSourceFiles(sources);
       
   612 	}
       
   613 
       
   614 	/**
       
   615 	 * Checks if this folder is the project root
       
   616 	 * 
       
   617 	 * @param name
       
   618 	 *            name of the folder
       
   619 	 * @return true if this folder is the project root
       
   620 	 */
       
   621 	private boolean isProjectRoot(String name) {
       
   622 		boolean retval = false;
       
   623 		if (name.equalsIgnoreCase(traceFolderName)
       
   624 				|| name.equalsIgnoreCase(SymbianConstants.GROUP_DIRECTORY)
       
   625 				|| name.equalsIgnoreCase(SymbianConstants.MMPFILES_DIRECTORY)
       
   626 				|| name
       
   627 						.equalsIgnoreCase(TraceCompilerConstants.TRACES_DIRECTORY)) {
       
   628 			retval = true;
       
   629 		}
       
   630 		return retval;
       
   631 	}
       
   632 
       
   633 	/**
       
   634 	 * Registers source files
       
   635 	 * 
       
   636 	 * @param files
       
   637 	 */
       
   638 	private void registerSourceFiles(ArrayList<String> files) {
       
   639 		if (files.size() > 0) {
       
   640 			String[] fileArr = new String[files.size()];
       
   641 			files.toArray(fileArr);
       
   642 
       
   643 			// Sets the source files to the TraceCompiler document
       
   644 			// factory. It will create a document from each source in the array
       
   645 			FileDocumentMonitor.setFiles(fileArr);
       
   646 			DocumentFactory.registerDocumentFramework(
       
   647 					new FileDocumentMonitor(), StringDocumentFactory.class);
       
   648 		}
       
   649 	}
       
   650 
       
   651 	/**
       
   652 	 * Initializes TraceCompiler
       
   653 	 * @throws TraceCompilerRootException if fail to initialize the plugins
       
   654 	 * @throws TraceCompilerException 
       
   655 	 */
       
   656 	private void start() throws TraceCompilerRootException, TraceCompilerException {
       
   657 
       
   658 		// Starts TraceCompiler. This is normally called from the Eclipse
       
   659 		// plug-in
       
   660 		// activator, but in console case that does not exist
       
   661 		TraceCompilerEngineGlobals.start();
       
   662 				
       
   663 		
       
   664 		//Reads the GroupId values from opensystemtrace_types.h
       
   665 		//If this fails a message is logged and trace compiler stops
       
   666 		GroupNames.initialiseGroupName();
       
   667 
       
   668 		
       
   669 		// Registers a view to TraceCompiler
       
   670 		TraceCompilerEngineGlobals
       
   671 				.setView(new TraceCompilerView(componentPath));
       
   672 
       
   673 		// Registers all plug-in components
       
   674 		for (TraceCompilerPlugin plugin : plugIns) {
       
   675 			TraceCompilerEngineGlobals.registerPlugin(plugin);
       
   676 		}
       
   677 		// Adds a model event listener
       
   678 		TraceCompilerEngineGlobals.getTraceModel().addModelListener(
       
   679 				modelListener);
       
   680 		TraceCompilerEngineGlobals.getTraceModel().addExtensionListener(
       
   681 				modelListener);
       
   682 		TraceCompilerEngineGlobals.getTraceModel().getExtension(
       
   683 				TraceLocationList.class).addLocationListListener(modelListener);
       
   684 		TraceCompilerEngineGlobals.getTraceModel().addProcessingListener(modelListener);
       
   685 	}
       
   686 
       
   687 	/**
       
   688 	 * Parses the sources and generates trace files
       
   689 	 * @throws Exception 
       
   690 	 */
       
   691 	private void buildTraceFiles() throws Exception {
       
   692 		TraceCompilerEngineInterface tbi = TraceCompilerEngineGlobals
       
   693 				.getTraceCompiler();
       
   694 		try {
       
   695 			// Opens a trace project
       
   696 			componentName = TraceUtils.convertName(componentName);
       
   697 
       
   698 			// Set project path before opening project
       
   699 			TraceCompilerEngineGlobals.setProjectPath(componentPath);
       
   700 			tbi.openProject(componentName);
       
   701 			TraceModel model = TraceCompilerEngineGlobals.getTraceModel();
       
   702 			if (model.isValid()) {
       
   703 				model.setID((int) componentUID);
       
   704 
       
   705 				// Location errors are printed after a file changes, but the
       
   706 				// last file is not detected by the listener
       
   707 				if (modelListener.getErrors().size() > 0) {
       
   708 					modelListener.printLocationErrors();
       
   709 					tbi.closeProject();
       
   710 					throw new TraceCompilerRootException(null, null);
       
   711 				}
       
   712 				tbi.exportProject();
       
   713 				tbi.closeProject();
       
   714 			} else {
       
   715 				String msg = "Project creation was cancelled"; //$NON-NLS-1$
       
   716 				throw new TraceCompilerRootException(msg, null);
       
   717 			}
       
   718 		} catch (TraceCompilerException e) {
       
   719 			TraceCompilerEngineGlobals.getEvents().postError(e);
       
   720 			throw new TraceCompilerRootException("Build trace files failed.", e); //$NON-NLS-1$
       
   721 		}
       
   722 	}
       
   723 
       
   724 	/**
       
   725 	 * Shuts down TraceCompiler
       
   726 	 * @throws TraceCompilerException 
       
   727 	 */
       
   728 	private void shutdown() throws TraceCompilerException {
       
   729 		for (TraceCompilerPlugin plugin : plugIns) {
       
   730 			TraceCompilerEngineGlobals.unregisterPlugin(plugin);
       
   731 		}
       
   732 		TraceCompilerEngineGlobals.shutdown();
       
   733 	}
       
   734 
       
   735 	/**
       
   736 	 * Checks if the MMP file is valid
       
   737 	 * 
       
   738 	 * @return true if MMP file is valid
       
   739 	 */
       
   740 	private boolean isMmpValid() {
       
   741 		boolean valid = false;
       
   742 		String pathStr = mmpPath.getAbsolutePath();
       
   743 
       
   744 		if (mmpPath.exists() && pathStr.length() > MMP.length()) {
       
   745 			String end = pathStr.substring(pathStr.length() - MMP.length());
       
   746 			if (end.equalsIgnoreCase(MMP)) {
       
   747 				valid = true;
       
   748 			} else {
       
   749 				TraceCompilerLogger.printError("Invalid MMP file: " + mmpPath.getAbsolutePath()); //$NON-NLS-1$
       
   750 			}
       
   751 		} else {
       
   752 			TraceCompilerLogger.printError("Missing or can not access MMP path: " + mmpPath.getAbsolutePath()); //$NON-NLS-1$
       
   753 		}
       
   754 		return valid;
       
   755 		
       
   756 	}
       
   757 
       
   758 }