tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/TraceCompilerMain.java
changeset 56 aa2539c91954
parent 54 a151135b0cf9
child 60 e54443a6878c
child 62 1c2bb2fc7c87
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.Iterator;
       
    29 import java.util.regex.Matcher;
       
    30 import java.util.regex.Pattern;
       
    31 
       
    32 import com.nokia.tracecompiler.document.FileDocumentMonitor;
       
    33 import com.nokia.tracecompiler.document.StringDocumentFactory;
       
    34 import com.nokia.tracecompiler.engine.TraceCompilerEngineEvents;
       
    35 import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
       
    36 import com.nokia.tracecompiler.engine.TraceCompilerEngineInterface;
       
    37 import com.nokia.tracecompiler.engine.TraceLocationList;
       
    38 import com.nokia.tracecompiler.engine.project.ProjectEngine;
       
    39 import com.nokia.tracecompiler.file.FileUtils;
       
    40 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    41 import com.nokia.tracecompiler.model.TraceModel;
       
    42 import com.nokia.tracecompiler.plugin.TraceCompilerPlugin;
       
    43 import com.nokia.tracecompiler.project.GroupNames;
       
    44 import com.nokia.tracecompiler.source.SourceConstants;
       
    45 import com.nokia.tracecompiler.utils.DocumentFactory;
       
    46 import com.nokia.tracecompiler.utils.TraceCompilerVersion;
       
    47 
       
    48 /**
       
    49  * TraceCompiler command-line main class
       
    50  * 
       
    51  */
       
    52 public class TraceCompilerMain {
       
    53 	
       
    54 	/** line separator */
       
    55 	private static String LINE_SEPARATOR =  System.getProperty("line.separator"); //$NON-NLS-1$
       
    56 	
       
    57 	/**
       
    58 	 * Index of third character
       
    59 	 */
       
    60 	private static final int INDEX_OF_THIRD_CHARACTER = 2;
       
    61 
       
    62 	/**
       
    63 	 * Index of first character
       
    64 	 */
       
    65 	private static final int INDEX_OF_FIRST_CHARACTER = 0;
       
    66 	
       
    67 	/**
       
    68 	 * TraceCompiler options
       
    69 	 */
       
    70 	
       
    71 	/**
       
    72 	 * UID : it is used to create the dictionary file
       
    73 	 */
       
    74 	private static final String UID_SWITCH = Messages.getString("TraceCompiler.UidStwich"); //$NON-NLS-1$
       
    75 	private static final String UID_SWITCH_TEXT = Messages.getString("TraceCompiler.UidText"); //$NON-NLS-1$
       
    76 	/**
       
    77 	 * project name : it is used to create the dictionary file
       
    78 	 */
       
    79 	private static final String PRJ_NAME_SWITCH = Messages.getString("TraceCompiler.ProjectSwitch");//$NON-NLS-1$
       
    80 	private static final String PRJ_NAME_SWITCH_TEXT = Messages.getString("TraceCompiler.ProjectText"); //$NON-NLS-1$
       
    81 	/**
       
    82 	 * mmp file path:  may be used to compute the traces folder
       
    83 	 */
       
    84 	private static final String MMP_PATH_SWITCH = Messages.getString("TraceCompiler.MmpSwitch");//$NON-NLS-1$
       
    85 	private static final String MMP_PATH_SWITCH_TEXT = Messages.getString("TraceCompiler.MmpText"); //$NON-NLS-1$
       
    86 	/**
       
    87 	 * traces folder: absolute or relative to the mmp folder
       
    88 	 */
       
    89 	private static final String TRACES_PATH_SWITCH = Messages.getString("TraceCompiler.TracesSwitch");//$NON-NLS-1$
       
    90 	private static final String TRACES_PATH_SWITCH_TEXT = Messages.getString("TraceCompiler.TracesText"); //$NON-NLS-1$
       
    91 	
       
    92 
       
    93 	/**
       
    94 	 * Version option
       
    95 	 */
       
    96 	private static final String VERSION_OPTION = Messages.getString("TraceCompiler.VersionSwitchLong"); //$NON-NLS-1$
       
    97 	private static final String VERSION_OPTION_SF = Messages.getString("TraceCompiler.VersionSwitchShort"); //$NON-NLS-1$
       
    98 	private static final String VERSION_OPTION_INSTRUCTION_TEXT = Messages.getString("TraceCompiler.VersionText"); //$NON-NLS-1$
       
    99 
       
   100 	
       
   101 	/**
       
   102 	 * help option
       
   103 	 */
       
   104 	private static final String HELP_OPTION = Messages.getString("TraceCompiler.HelpSwicthLong"); //$NON-NLS-1$
       
   105 	private static final String HELP_OPTION_SF = Messages.getString("TraceCompiler.HelpSwitchShort"); //$NON-NLS-1$
       
   106 	private static final String HELP_OPTION_INSTRUCTION_TEXT = Messages.getString("TraceCompiler.HelpText"); //$NON-NLS-1$
       
   107 	
       
   108 	/**
       
   109 	 * Verbose option
       
   110 	 */
       
   111 	private static final String VERBOSE_OPTION = Messages.getString("TraceCompiler.VerboseSwitchLong"); //$NON-NLS-1$
       
   112 	private static final String VERBOSE_OPTION_SF = Messages.getString("TraceCompiler.VerboseSwitchShort"); //$NON-NLS-1$
       
   113 	private static final String VERBOSE_OPTION_INSTRUCTION_TEXT = Messages.getString("TraceCompiler.VerboseText"); //$NON-NLS-1$
       
   114 
       
   115 	/**
       
   116 	 * keep going option
       
   117 	 */
       
   118 	private static final String STOP_ON_ERROR_OPTION = Messages.getString("TraceCompiler.StopSwitchLong"); //$NON-NLS-1$
       
   119 	private static final String STOP_ON_ERROR_OPTION_SF = Messages.getString("TraceCompiler.StopSwitchShort"); //$NON-NLS-1$
       
   120 	private static final String STOP_ON_ERROR_OPTION_INSTRUCTION_TEXT = Messages.getString("TraceCompiler.StopText"); //$NON-NLS-1$
       
   121 
       
   122 	
       
   123 
       
   124 	/**
       
   125 	 * Version text
       
   126 	 */
       
   127 	private static final String VERSION_TEXT = Messages.getString("TraceCompiler.DisplayVersionText"); //$NON-NLS-1$
       
   128 
       
   129 	/**
       
   130 	 * Option instruction text
       
   131 	 */
       
   132 	private static final String OPTION_INSTRUCTION_TEXT = Messages.getString("TraceCompiler.Options"); //$NON-NLS-1$
       
   133 	private static final String VALUE=Messages.getString("TraceCompiler.Value"); //$NON-NLS-1$
       
   134 	
       
   135 
       
   136 	
       
   137 	private static final String USAGE = Messages.getString("TraceCompiler.Usage") + LINE_SEPARATOR + //$NON-NLS-1$
       
   138 	Messages.getString("TraceCompiler.UsageText") + LINE_SEPARATOR + //$NON-NLS-1$
       
   139 										"\t" + OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR + //$NON-NLS-1$
       
   140 										"\t" + HELP_OPTION_SF  + ", " + HELP_OPTION + ", " + HELP_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR +   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   141 										"\t" + VERSION_OPTION_SF + ", " + VERSION_OPTION + "\t" +  VERSION_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR +   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   142 										"\t" + VERBOSE_OPTION_SF + ", " + VERBOSE_OPTION + "\t\t" + VERBOSE_OPTION_INSTRUCTION_TEXT + LINE_SEPARATOR +  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
       
   143 										"\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$
       
   144 										"\t" + UID_SWITCH + "=" + VALUE + "\t" + UID_SWITCH_TEXT +  LINE_SEPARATOR + //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   145 										"\t" + PRJ_NAME_SWITCH + "=" + VALUE + "\t" + PRJ_NAME_SWITCH_TEXT +  LINE_SEPARATOR + //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   146 										"\t" + MMP_PATH_SWITCH + "=" + VALUE + "\t" + MMP_PATH_SWITCH_TEXT +  LINE_SEPARATOR + //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   147 										"\t" + TRACES_PATH_SWITCH + "=" + VALUE + "\t" + TRACES_PATH_SWITCH_TEXT; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
       
   148 
       
   149 
       
   150 
       
   151 	/**
       
   152 	 * End of source files tag
       
   153 	 */
       
   154 	private static final String ENDOFSOURCEFILES = Messages.getString("TraceCompiler.EndOfList"); //$NON-NLS-1$
       
   155 
       
   156 	/**
       
   157 	 * MMP file extension
       
   158 	 */
       
   159 	private static final String MMP_FILE_TYPE = Messages.getString("TraceCompiler.MmpExtension"); //$NON-NLS-1$
       
   160 
       
   161 	/**
       
   162 	 * Decode plugins path
       
   163 	 */
       
   164 	private String DECODE_PLUGINS_PATH = Messages.getString("TraceCompiler.PluginPath"); //$NON-NLS-1$
       
   165 
       
   166 	/**
       
   167 	 * Decode plugin name tag
       
   168 	 */
       
   169 	private String DECODE_PLUGIN_NAME_TAG = Messages.getString("TraceCompiler.DecodeText1"); //$NON-NLS-1$
       
   170 
       
   171 	/**
       
   172 	 * Decode plugin class name tag
       
   173 	 */
       
   174 	private String DECODE_PLUGIN_CLASS_NAME_TAG = Messages.getString("TraceCompiler.DecodeText2"); //$NON-NLS-1$
       
   175 
       
   176 	/**
       
   177 	 * Decode plugin engine class name template
       
   178 	 */
       
   179 	private String ENGINE_CLASS_NAME_TEMPLATE = DECODE_PLUGIN_NAME_TAG
       
   180 			+ "Engine"; //$NON-NLS-1$
       
   181 
       
   182 	/**
       
   183 	 * Decode plugin engine file name template
       
   184 	 */
       
   185 	private String ENGINE_FILE_NAME_TEMPLATE = DECODE_PLUGIN_CLASS_NAME_TAG
       
   186 			+ ".class"; //$NON-NLS-1$
       
   187 
       
   188 	/**
       
   189 	 * Decode plugins class template
       
   190 	 */
       
   191 	private String CLASS_TEMPLATE = Messages.getString("TraceCompiler.DecodePluginsNameSpace") + DECODE_PLUGIN_NAME_TAG + "." + DECODE_PLUGIN_CLASS_NAME_TAG; //$NON-NLS-1$ //$NON-NLS-2$	
       
   192 	
       
   193 	//switch with value such as --uid=value
       
   194 	private Pattern valueSwitchPattern = Pattern.compile("(--\\S+)=(\\S+)"); //$NON-NLS-1$
       
   195 	//switches with no values such -v, --version
       
   196 	private Pattern singleSwitchPattern = Pattern.compile("-{1,2}([^=]+)"); //$NON-NLS-1$
       
   197 	
       
   198 	/**
       
   199 	 * list of source files
       
   200 	 */
       
   201 	private ArrayList<String> sources = new ArrayList<String>();
       
   202 	/**
       
   203 	 * traces path
       
   204 	 */
       
   205 	private String traces_path = null;
       
   206 	
       
   207 	
       
   208 	
       
   209 	
       
   210 	/**
       
   211 	 * Main function
       
   212 	 * 
       
   213 	 * @param args
       
   214 	 *            the command line arguments
       
   215 	 */
       
   216 	public static void main(String[] args) {
       
   217 		if (args.length == 0) {
       
   218 			printUsage();
       
   219 			return;
       
   220 		}
       
   221 		
       
   222 		ArrayList<String> list = null;
       
   223 		
       
   224 		//support spaces in switches, build a long string, clean it and convert it back to array - a bit expensive
       
   225 		String tmpString = "";  //$NON-NLS-1$
       
   226 		for (int i = 0; i < args.length; i++) {
       
   227 			tmpString = tmpString + " " + args[i];  //$NON-NLS-1$
       
   228 		}
       
   229 		tmpString = tmpString.replaceAll("\\s*=\\s*", "="); //$NON-NLS-1$ //$NON-NLS-2$
       
   230 		tmpString = tmpString.replaceAll("\\s+", " "); //$NON-NLS-1$ //$NON-NLS-2$
       
   231 		String[] split = tmpString.trim().split(" "); //$NON-NLS-1$
       
   232 		tmpString = null; // not needed anymore
       
   233 		
       
   234 		//rebuild array of arguments
       
   235 		if (split.length > 0) {
       
   236 			list = new ArrayList<String>(Arrays.asList(split));
       
   237 		}
       
   238 				
       
   239 		long startTime = System.currentTimeMillis();
       
   240 		//create a new session of TraceCompiler
       
   241 		TraceCompilerMain console = new TraceCompilerMain();
       
   242 		
       
   243 		try {
       
   244 			console.parseCommandLine(list);
       
   245 		} catch (Exception e) { //should cover IOException and TraceCompilerIllegalArgumentsException
       
   246 			//There is no point to continue if there are problems with the arguments.
       
   247 			TraceCompilerLogger.printError(e.getMessage());
       
   248 			printUsage();
       
   249 			System.exit(1);
       
   250 		}
       
   251 		
       
   252 		boolean error = false;
       
   253 		try {
       
   254 			if(list.size() != 0) {
       
   255 				console.createPlugins();
       
   256 				console.start();
       
   257 				console.buildTraceFiles();				
       
   258 			}
       
   259 		} catch (Exception e) {
       
   260 			if (e instanceof TraceCompilerRootException) {
       
   261 				TraceCompilerLogger.printError(e.getMessage()); 
       
   262 			} //else the error should have been reported earlier
       
   263 			error = true;
       
   264 		} finally {
       
   265 			try {
       
   266 				if (!error) { //check if errors have been logged by EventEngine
       
   267 					TraceCompilerEngineEvents events = TraceCompilerEngineGlobals.getEvents();
       
   268 					if (events != null && events.hasErrorHappened()) {
       
   269 						error = true;
       
   270 					}
       
   271 				}
       
   272 				console.shutdown();
       
   273 			} catch (TraceCompilerException e) {
       
   274 				error = true;
       
   275 			}
       
   276 		}
       
   277 
       
   278 		if (console.projectName != null) {
       
   279 			TraceCompilerLogger.printMessage(console.projectName + Messages.getString("TraceCompiler.Took") //$NON-NLS-1$
       
   280 					+ (System.currentTimeMillis() - startTime) + Messages.getString("TraceCompiler.MS")); //$NON-NLS-1$
       
   281 		}
       
   282 		if (error) {
       
   283 			System.exit(1);
       
   284 		} else {
       
   285 			System.exit(0);
       
   286 		}	
       
   287 	}
       
   288 
       
   289 	/**
       
   290 	 * With Eclipse, the plug-ins are loaded by Eclipse framework. Here they
       
   291 	 * must be manually created and started
       
   292 	 */
       
   293 	private ArrayList<TraceCompilerPlugin> plugIns = new ArrayList<TraceCompilerPlugin>();
       
   294 
       
   295 	/**
       
   296 	 * Model listener
       
   297 	 */
       
   298 	private TraceCompilerModelListener modelListener;
       
   299 
       
   300 	/**
       
   301 	 * Name of the component
       
   302 	 */
       
   303 	private String projectName = null;
       
   304 	
       
   305 
       
   306 	/**
       
   307 	 * UID of the component
       
   308 	 */
       
   309 	private long componentUID = 0L;
       
   310 
       
   311 	/**
       
   312 	 * Component path
       
   313 	 */
       
   314 	private String componentPath = null;
       
   315 
       
   316 	/**
       
   317 	 * MMP file path
       
   318 	 */
       
   319 	private File mmpPath = null;
       
   320 
       
   321 	/**
       
   322 	 * Constructor
       
   323 	 */
       
   324 	TraceCompilerMain() {
       
   325 
       
   326 		// Creates listeners and preferences
       
   327 		modelListener = new TraceCompilerModelListener();
       
   328 	}
       
   329 
       
   330 	/**
       
   331 	 * Creates the plug-ins to be registered with TraceCompiler
       
   332 	 * @throws TraceCompilerRootException if fail to create a valid plugins
       
   333 	 */
       
   334 	private void createPlugins() throws TraceCompilerRootException {
       
   335 		
       
   336 		// Get location of the TraceCompiler
       
   337 		URL path = getClass().getProtectionDomain().getCodeSource()
       
   338 				.getLocation();
       
   339 		String decodePluginsPath = path.getPath();
       
   340 
       
   341 		// If first character is forward slash and it is located before drive
       
   342 		// letter remove it
       
   343 		if (decodePluginsPath.charAt(INDEX_OF_FIRST_CHARACTER) == SourceConstants.FORWARD_SLASH_CHAR
       
   344 				&& decodePluginsPath.charAt(INDEX_OF_THIRD_CHARACTER) == SourceConstants.COLON_CHAR) {
       
   345 			decodePluginsPath = decodePluginsPath.substring(1);
       
   346 		}
       
   347 		
       
   348 		// Concatenate decode plugins path
       
   349 		decodePluginsPath = decodePluginsPath.concat(DECODE_PLUGINS_PATH);
       
   350 		
       
   351 		// Replace slashes with correct separator character
       
   352 		decodePluginsPath = decodePluginsPath.replace(
       
   353 				SourceConstants.FORWARD_SLASH_CHAR, File.separatorChar);
       
   354 		decodePluginsPath = decodePluginsPath.replace(
       
   355 				SourceConstants.BACKSLASH_CHAR, File.separatorChar);
       
   356 		File decodePluginsDir = new File(decodePluginsPath);
       
   357 		String[] decodePlugins = decodePluginsDir.list();
       
   358 		if (decodePlugins != null) {
       
   359 			for (int i = 0; i < decodePlugins.length; i++) {
       
   360 
       
   361 				// Get decode plugin name
       
   362 				String decodePluginName = decodePlugins[i];
       
   363 
       
   364 				// Get decode plugin path
       
   365 				String decodePluginPath = decodePluginsPath
       
   366 						+ File.separatorChar + decodePluginName;
       
   367 
       
   368 				// Decode plugin must be in own directory
       
   369 				Boolean isDirectory = (new File(decodePluginPath))
       
   370 						.isDirectory();
       
   371 				if (isDirectory) {
       
   372 
       
   373 					// Construct decode plugin engine class name
       
   374 					String engineClassName = ENGINE_CLASS_NAME_TEMPLATE
       
   375 							.replaceFirst(DECODE_PLUGIN_NAME_TAG,
       
   376 									decodePluginName.substring(0, 1)
       
   377 											.toUpperCase()
       
   378 											+ decodePluginName.substring(1));
       
   379 
       
   380 					// Construct decode plugin engine file name
       
   381 					String engineFileName = ENGINE_FILE_NAME_TEMPLATE
       
   382 							.replaceFirst(DECODE_PLUGIN_CLASS_NAME_TAG,
       
   383 									engineClassName);
       
   384 					String engineFileFullName = decodePluginPath
       
   385 							+ File.separatorChar + engineFileName;
       
   386 
       
   387 					// Check does engine file exist
       
   388 					Boolean exists = (new File(engineFileFullName)).exists();
       
   389 					if (exists) {
       
   390 						String engineClassFullName = CLASS_TEMPLATE
       
   391 								.replaceFirst(DECODE_PLUGIN_NAME_TAG,
       
   392 										decodePluginName).replaceFirst(
       
   393 										DECODE_PLUGIN_CLASS_NAME_TAG,
       
   394 										engineClassName);
       
   395 						try {
       
   396 							Class<?> engineClass = Class
       
   397 									.forName(engineClassFullName);
       
   398 							TraceCompilerPlugin engine = (TraceCompilerPlugin) engineClass
       
   399 									.newInstance();
       
   400 							plugIns.add(engine);
       
   401 							TraceCompilerLogger.printInfo(Messages.getString(Messages.getString("TraceCompiler.DecodePlugin") + engineClassFullName + Messages.getString("TraceCompiler.Added"))); //$NON-NLS-1$ //$NON-NLS-2$
       
   402 						} catch (Exception e) {
       
   403 							String msg = Messages.getString("TraceCompiler.DecodePlugin" + engineClassFullName + Messages.getString("TraceCompiler.AddingFailed")); //$NON-NLS-1$ //$NON-NLS-2$
       
   404 							throw new TraceCompilerRootException(msg, e); 
       
   405 						}
       
   406 					} else {
       
   407 						String msg = Messages.getString("TraceCompiler.DecodePluginFile") + Messages.getString("TraceCompiler.EngineFullName") + engineFileFullName + Messages.getString("TraceCompiler.DoesNotExist"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   408 						throw new TraceCompilerRootException(msg, null);
       
   409 					}
       
   410 				}
       
   411 			}
       
   412 		}
       
   413 	}
       
   414 
       
   415 	/**
       
   416 	 * Parses the command line
       
   417 	 * 
       
   418 	 * @param args
       
   419 	 *            the arguments
       
   420 	 * @throws TraceCompilerRootException if arguments are invalid
       
   421 	 * @throws IOException 
       
   422 	 */
       
   423 	private void parseCommandLine(ArrayList<String> list) throws TraceCompilerIllegalArgumentsException, IOException {
       
   424 		TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.BuildingTracesMess")); //$NON-NLS-1$
       
   425 		Iterator<String> argIterator = list.iterator();
       
   426 		
       
   427 		if (list.size() == 0) {
       
   428 			printUsage();
       
   429 			System.exit(0);
       
   430 		}
       
   431 		while (argIterator.hasNext()) {
       
   432 			String element = argIterator.next().trim();
       
   433 			Matcher m = singleSwitchPattern.matcher(element);
       
   434 
       
   435 			if (m.matches()) { //it's one of the single switches 
       
   436 				if (element.equalsIgnoreCase(HELP_OPTION) || element.equalsIgnoreCase(HELP_OPTION_SF)) {
       
   437 					printUsage();
       
   438 					System.exit(0);
       
   439 				}
       
   440 				if (element.equalsIgnoreCase(VERBOSE_OPTION) || element.equalsIgnoreCase(VERBOSE_OPTION_SF)) {
       
   441 					TraceCompilerGlobals.setVerbose(true);
       
   442 					TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.veboseEnabled")); //$NON-NLS-1$
       
   443 					continue;
       
   444 				}
       
   445 				if ( element.equalsIgnoreCase(VERSION_OPTION) || element.equalsIgnoreCase(VERSION_OPTION_SF)) {
       
   446 					TraceCompilerLogger.printMessage(VERSION_TEXT + TraceCompilerVersion.getVersion());
       
   447 					System.exit(0);
       
   448 				}
       
   449 				if (element.equalsIgnoreCase(STOP_ON_ERROR_OPTION) || element.equalsIgnoreCase(STOP_ON_ERROR_OPTION_SF)) {
       
   450 					TraceCompilerGlobals.setKeepGoing(false);
       
   451 					TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.StopOnErrorEnabled")); //$NON-NLS-1$
       
   452 					continue;
       
   453 				}
       
   454 				TraceCompilerLogger.printMessage(Messages.getString("TraceCompiler.UnsupportedSwitch")  + element); //$NON-NLS-1$
       
   455 			} else {
       
   456 				m = valueSwitchPattern.matcher(element.trim());
       
   457 				if (m.matches()) { //it's one of the swithes with values
       
   458 					if (m.group(1).equalsIgnoreCase(UID_SWITCH)) {
       
   459 						// UID
       
   460 						try {
       
   461 							componentUID = Long.parseLong(m.group(2),TraceCompilerConstants.HEX_RADIX);	
       
   462 							TraceCompilerLogger.printInfo("Component UID: 0x" + Long.toHexString(componentUID)); //$NON-NLS-1$
       
   463 							if (componentUID <= 0L) {
       
   464 								String msg = Messages.getString("TraceCompiler.componentUidIsNotValidExceptionText") + componentUID; //$NON-NLS-1$
       
   465 								throw new TraceCompilerIllegalArgumentsException(msg, null);
       
   466 							}
       
   467 						} catch (NumberFormatException e) {
       
   468 							String msg = Messages.getString("TraceCompiler.componentUidIsNotValidExceptionText") + componentUID; //$NON-NLS-1$
       
   469 							throw new TraceCompilerIllegalArgumentsException(msg, null);
       
   470 						}
       
   471 					} else {
       
   472 						if (m.group(1).equalsIgnoreCase(PRJ_NAME_SWITCH)) {
       
   473 							// project name
       
   474 							projectName = m.group(2);
       
   475 							TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.CompNameSet") + projectName); //$NON-NLS-1$
       
   476 						} else {
       
   477 							if (m.group(1).equalsIgnoreCase(MMP_PATH_SWITCH)) {
       
   478 								//mmp path. for the moment only the mmp folder is used.
       
   479 								mmpPath = new File(m.group(2));
       
   480 								TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.MMPPathSet") + mmpPath); //$NON-NLS-1$
       
   481 							} else {
       
   482 								if (m.group(1).equalsIgnoreCase(TRACES_PATH_SWITCH)) {
       
   483 									//traces path
       
   484 									traces_path = m.group(2);
       
   485 								} else {
       
   486 									//unsupported switch
       
   487 									TraceCompilerLogger.printMessage(Messages.getString("TraceCompiler.UnsupportedSwitch") + element); //$NON-NLS-1$
       
   488 								}
       
   489 							}
       
   490 						}
       
   491 					}
       
   492 
       
   493 				} else {
       
   494 					//it must be a file name
       
   495 					//it's a good time to stop TC here if the file does not exist
       
   496 					if (!(new File(element)).exists()) {
       
   497 						throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.sourceFileDoesNotExist") + element, null); //$NON-NLS-1$
       
   498 					}
       
   499 					sources.add(element);				
       
   500 				}	
       
   501 			}
       
   502 		}
       
   503 		
       
   504 		// by now, if the user wanted just help or version they would have got it and TC stopped
       
   505 		
       
   506 		if (componentUID <= 0L) {
       
   507 			String msg = Messages.getString("TraceCompiler.componentUidIsNotValidExceptionText") + componentUID; //$NON-NLS-1$
       
   508 			throw new TraceCompilerIllegalArgumentsException(msg, null);
       
   509 		}
       
   510 		
       
   511 		if (projectName == null) {
       
   512 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.projectNameMissing"), null); //$NON-NLS-1$
       
   513 		}
       
   514 		
       
   515 		//if files have not been provided , get them from stdin
       
   516 		if (sources.size() == 0) {
       
   517 			//get them from the stdin
       
   518 			readFromStdin();
       
   519 		}
       
   520 		
       
   521 		if (mmpPath == null ) {
       
   522 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.mmpPathMissing"), null); //$NON-NLS-1$
       
   523 		} else if (!isMmpValid()) {
       
   524 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.invalidMmpExceptionText") + mmpPath, null); //$NON-NLS-1$
       
   525 		}
       
   526 		
       
   527 		if (traces_path == null ) {
       
   528 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.tracesPathMissing"), null); //$NON-NLS-1$
       
   529 		} else {
       
   530 			computeTracesPath(traces_path);
       
   531 		}
       
   532 		
       
   533 		if (sources.size() == 0 ) {
       
   534 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.fileListMissing"), null); //$NON-NLS-1$
       
   535 		}
       
   536 		
       
   537 		//we have all parameters input and validated, register files.
       
   538 		registerSourceFiles(sources);		
       
   539 	}
       
   540 	
       
   541 	
       
   542 	/**
       
   543 	 * If traces path is relative, work out the full path relative to the location of the mmp file
       
   544 	 * @param path
       
   545 	 * @throws TraceCompilerIllegalArgumentsException
       
   546 	 */
       
   547 	private void computeTracesPath(String path) throws TraceCompilerIllegalArgumentsException {
       
   548 		String traces_pathString = path;
       
   549 		traces_pathString = traces_pathString.replace('/', File.separatorChar);
       
   550 		traces_pathString = traces_pathString.replace('\\', File.separatorChar);
       
   551 
       
   552 		File traces_path = new File(traces_pathString);
       
   553 
       
   554 		Pattern p = Pattern.compile("(([a-zA-Z]:[\\\\/])|([\\\\/])).*"); //$NON-NLS-1$
       
   555 		Matcher m = p.matcher(traces_pathString);
       
   556 
       
   557 		if (!m.matches() /*  workaround for isAbsolute in java */) {
       
   558 			//traces path is relative to mmp location
       
   559 			traces_pathString = mmpPath.getAbsoluteFile().getParent() + File.separator + traces_pathString;
       
   560 		}
       
   561 
       
   562 		traces_path = new File(traces_pathString);
       
   563 
       
   564 		if (traces_path.isDirectory() && !traces_path.canWrite()) {
       
   565 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.TracesPathWriteProtected") + traces_path, null); //$NON-NLS-1$
       
   566 		}
       
   567 
       
   568 		boolean dirExists = true;
       
   569 		if (!traces_path.exists()) {
       
   570 			dirExists = FileUtils.createDirectories(traces_path);
       
   571 		}
       
   572 		if (!dirExists) {
       
   573 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.mkdirFailed") + traces_path, null); //$NON-NLS-1$
       
   574 		}
       
   575 
       
   576 		//set component path and trace folder
       
   577 		componentPath = traces_path.getParent();
       
   578 		ProjectEngine.traceFolderName = traces_path.getName();
       
   579 		TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.settingComponentPath") + componentPath); //$NON-NLS-1$
       
   580 		TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.settingTracesPath") + ProjectEngine.traceFolderName); //$NON-NLS-1$
       
   581 	}
       
   582 
       
   583 	private static void printUsage() {
       
   584 		TraceCompilerLogger.printMessage(VERSION_TEXT + TraceCompilerVersion.getVersion());
       
   585 		TraceCompilerLogger.printMessage(USAGE);
       
   586 	}
       
   587 
       
   588 	/**
       
   589 	 * Read information from STDIN
       
   590 	 * @throws IOException if fails to read the input
       
   591 	 * @throws TraceCompilerRootException if the list of files is empty
       
   592 	 */
       
   593 	private void readFromStdin() throws IOException, TraceCompilerIllegalArgumentsException {
       
   594 		TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.ReadingFilesMess")  + ENDOFSOURCEFILES); //$NON-NLS-1$
       
   595 		// Create reader
       
   596 		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
       
   597 
       
   598 			String line = stdin.readLine();
       
   599 						
       
   600 			while (line != null) {
       
   601 				line = line.trim();
       
   602 				if (line.length() > 0) {
       
   603 					// End of source files received
       
   604 					if (line.equals(ENDOFSOURCEFILES)) {
       
   605 						break;
       
   606 					}
       
   607 					line = line.replaceAll("\\s+", ""); //$NON-NLS-1$ //$NON-NLS-2$
       
   608 					Matcher m = valueSwitchPattern.matcher(line.trim());
       
   609 					//because mmp path and traces path can be very long, we should allow them to be input'ed through stdin too.
       
   610 					if (m.matches()) { //it's one of the swithes with values
       
   611 						if (m.group(1).equalsIgnoreCase(MMP_PATH_SWITCH)) {
       
   612 							//mmp path. for the moment only the mmp folder is used.
       
   613 							mmpPath = new File(m.group(2));
       
   614 							TraceCompilerLogger.printInfo(Messages.getString("TraceCompiler.MMPPathSet") + mmpPath); //$NON-NLS-1$
       
   615 						} else {
       
   616 							if (m.group(1).equalsIgnoreCase(TRACES_PATH_SWITCH)) {
       
   617 								//traces path
       
   618 								traces_path = m.group(2);
       
   619 							} else {
       
   620 								//unsupported switch
       
   621 								TraceCompilerLogger.printMessage(Messages.getString("TraceCompiler.UnsupportedSwitch") + line); //$NON-NLS-1$
       
   622 							}
       
   623 						}
       
   624 					} else {
       
   625 
       
   626 						//it must be a file name
       
   627 						//it's a good time to stop TC here if the file does not exist
       
   628 						if (!(new File(line)).exists()) {
       
   629 							throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.sourceFileDoesNotExist") + line, null); //$NON-NLS-1$
       
   630 						}
       
   631 						sources.add(line);
       
   632 					}
       
   633 				}
       
   634 				// Read new line from STDIN
       
   635 				line = stdin.readLine();				
       
   636 			}
       
   637 		stdin.close();
       
   638 	}
       
   639 
       
   640 	/**
       
   641 	 * Registers source files
       
   642 	 * 
       
   643 	 * @param files
       
   644 	 */
       
   645 	private void registerSourceFiles(ArrayList<String> files) throws TraceCompilerIllegalArgumentsException {
       
   646 		if (sources.size() == 0) {
       
   647 			throw new TraceCompilerIllegalArgumentsException(Messages.getString("TraceCompiler.noSourceFilesExceptionText"), null); //$NON-NLS-1$
       
   648 		}
       
   649 		if (files.size() > 0) {
       
   650 			String[] fileArr = new String[files.size()];
       
   651 			files.toArray(fileArr);
       
   652 
       
   653 			// Sets the source files to the TraceCompiler document
       
   654 			// factory. It will create a document from each source in the array
       
   655 			FileDocumentMonitor.setFiles(fileArr);
       
   656 			DocumentFactory.registerDocumentFramework(
       
   657 					new FileDocumentMonitor(), StringDocumentFactory.class);
       
   658 		}
       
   659 	}
       
   660 
       
   661 	/**
       
   662 	 * Initializes TraceCompiler
       
   663 	 * @throws TraceCompilerRootException if fail to initialize the plugins
       
   664 	 * @throws TraceCompilerException 
       
   665 	 */
       
   666 	private void start() throws TraceCompilerRootException, TraceCompilerException {
       
   667 
       
   668 		// Starts TraceCompiler. This is normally called from the Eclipse
       
   669 		// plug-in
       
   670 		// activator, but in console case that does not exist
       
   671 		TraceCompilerEngineGlobals.start();
       
   672 						
       
   673 		//Reads the GroupId values from opensystemtrace_types.h
       
   674 		//If this fails a message is logged and trace compiler stops
       
   675 		GroupNames.initialiseGroupName();
       
   676 
       
   677 		
       
   678 		// Registers a view to TraceCompiler
       
   679 		TraceCompilerEngineGlobals
       
   680 				.setView(new TraceCompilerView(componentPath));
       
   681 
       
   682 		// Registers all plug-in components
       
   683 		for (TraceCompilerPlugin plugin : plugIns) {
       
   684 			TraceCompilerEngineGlobals.registerPlugin(plugin);
       
   685 		}
       
   686 		// Adds a model event listener
       
   687 		TraceCompilerEngineGlobals.getTraceModel().addModelListener(
       
   688 				modelListener);
       
   689 		TraceCompilerEngineGlobals.getTraceModel().addExtensionListener(
       
   690 				modelListener);
       
   691 		TraceCompilerEngineGlobals.getTraceModel().getExtension(
       
   692 				TraceLocationList.class).addLocationListListener(modelListener);
       
   693 		TraceCompilerEngineGlobals.getTraceModel().addProcessingListener(modelListener);
       
   694 	}
       
   695 
       
   696 	/**
       
   697 	 * Parses the sources and generates trace files
       
   698 	 * @throws Exception 
       
   699 	 */
       
   700 	private void buildTraceFiles() throws Exception {
       
   701 		TraceCompilerEngineInterface tbi = TraceCompilerEngineGlobals
       
   702 				.getTraceCompiler();
       
   703 		try {
       
   704 			// Opens a trace project
       
   705 
       
   706 			// Set project path before opening project
       
   707 			TraceCompilerEngineGlobals.setProjectPath(componentPath);
       
   708 			tbi.openProject(projectName);
       
   709 			TraceModel model = TraceCompilerEngineGlobals.getTraceModel();
       
   710 			if (model.isValid()) {
       
   711 				model.setID((int) componentUID);
       
   712 
       
   713 				// Location errors are printed after a file changes, but the
       
   714 				// last file is not detected by the listener
       
   715 				if (modelListener.getErrors().size() > 0) {
       
   716 					modelListener.printLocationErrors();
       
   717 					tbi.closeProject();
       
   718 					throw new TraceCompilerRootException(null, null);
       
   719 				}
       
   720 				tbi.exportProject();
       
   721 				tbi.closeProject();
       
   722 			} else {
       
   723 				String msg = Messages.getString("TraceCompiler.ProjectCancelledMess"); //$NON-NLS-1$
       
   724 				throw new TraceCompilerRootException(msg, null);
       
   725 			}
       
   726 		} catch (TraceCompilerException e) {
       
   727 			TraceCompilerEngineGlobals.getEvents().postError(e);
       
   728 			throw new TraceCompilerRootException(Messages.getString("TraceCompiler.BuildFailed"), e); //$NON-NLS-1$
       
   729 		}
       
   730 	}
       
   731 
       
   732 	/**
       
   733 	 * Shuts down TraceCompiler
       
   734 	 * @throws TraceCompilerException 
       
   735 	 */
       
   736 	private void shutdown() throws TraceCompilerException {
       
   737 		for (TraceCompilerPlugin plugin : plugIns) {
       
   738 			TraceCompilerEngineGlobals.unregisterPlugin(plugin);
       
   739 		}
       
   740 		TraceCompilerEngineGlobals.shutdown();
       
   741 	}
       
   742 
       
   743 	/**
       
   744 	 * Checks if the MMP file is valid
       
   745 	 * 
       
   746 	 * @return true if MMP file is valid
       
   747 	 */
       
   748 	private boolean isMmpValid() {
       
   749 		boolean valid = false;
       
   750 		String pathStr = mmpPath.getAbsolutePath();
       
   751 
       
   752 		if (mmpPath.exists() && pathStr.length() > MMP_FILE_TYPE.length()) {
       
   753 			String end = pathStr.substring(pathStr.length() - MMP_FILE_TYPE.length());
       
   754 			if (end.equalsIgnoreCase(MMP_FILE_TYPE)) {
       
   755 				valid = true;
       
   756 			} else {
       
   757 				TraceCompilerLogger.printError(Messages.getString("TraceCompiler.invalidMmpExceptionText") + mmpPath.getAbsolutePath()); //$NON-NLS-1$
       
   758 			}
       
   759 		} else {
       
   760 			TraceCompilerLogger.printError(Messages.getString("TraceCompiler.InvalidMMP2") + mmpPath.getAbsolutePath()); //$NON-NLS-1$
       
   761 		}
       
   762 		return valid;
       
   763 		
       
   764 	}
       
   765 
       
   766 }