tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/rules/RulesEngine.java
changeset 56 aa2539c91954
equal deleted inserted replaced
54:a151135b0cf9 56:aa2539c91954
       
     1 /*
       
     2 * Copyright (c) 2007 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 * Implementation of TraceObjectRuleFactory interface
       
    17 *
       
    18 */
       
    19 package com.nokia.tracecompiler.engine.rules;
       
    20 
       
    21 import java.util.Iterator;
       
    22 
       
    23 import com.nokia.tracecompiler.engine.TraceCompilerEngineConfiguration;
       
    24 import com.nokia.tracecompiler.engine.TraceCompilerEngineConfigurationListener;
       
    25 import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals;
       
    26 import com.nokia.tracecompiler.engine.header.ComplexHeaderRule;
       
    27 import com.nokia.tracecompiler.engine.rules.osttrace.OstTraceFormatRule;
       
    28 import com.nokia.tracecompiler.engine.source.SourceParserRule;
       
    29 import com.nokia.tracecompiler.engine.source.TraceParameterFormattingRule;
       
    30 import com.nokia.tracecompiler.model.Trace;
       
    31 import com.nokia.tracecompiler.model.TraceCompilerException;
       
    32 import com.nokia.tracecompiler.model.TraceModel;
       
    33 import com.nokia.tracecompiler.model.TraceModelExtension;
       
    34 import com.nokia.tracecompiler.model.TraceModelListener;
       
    35 import com.nokia.tracecompiler.model.TraceModelPersistentExtension;
       
    36 import com.nokia.tracecompiler.model.TraceModelResetListener;
       
    37 import com.nokia.tracecompiler.model.TraceObject;
       
    38 import com.nokia.tracecompiler.model.TraceObjectRuleFactory;
       
    39 import com.nokia.tracecompiler.model.TraceParameter;
       
    40 import com.nokia.tracecompiler.project.TraceProjectAPI;
       
    41 import com.nokia.tracecompiler.rules.FillerParameterRule;
       
    42 import com.nokia.tracecompiler.source.SourceUtils;
       
    43 
       
    44 /**
       
    45  * Provides rules for trace objects.
       
    46  * 
       
    47  */
       
    48 public class RulesEngine implements TraceObjectRuleFactory {
       
    49 
       
    50 	/**
       
    51 	 * Number of parameters in a simple trace
       
    52 	 */
       
    53 	private static final int SIMPLE_TRACE_MAX_PARAMETER_COUNT = 1;
       
    54 
       
    55 	/**
       
    56 	 * Trace model listener updates the fillers and complex type flagging when
       
    57 	 * traces and parameters are modified
       
    58 	 */
       
    59 	private TraceModelListener modelListener;
       
    60 
       
    61 	/**
       
    62 	 * Trace model reset listener uses modelValid to update the complex header
       
    63 	 * rules
       
    64 	 */
       
    65 	private TraceModelResetListener resetListener;
       
    66 
       
    67 	/**
       
    68 	 * Manager for plug-in API's
       
    69 	 */
       
    70 	private RulesEnginePluginManager pluginManager;
       
    71 
       
    72 	/**
       
    73 	 * Configuration listener for source format changes
       
    74 	 */
       
    75 	private TraceCompilerEngineConfigurationListener configurationListener = new RulesEngineConfigurationListener(
       
    76 			this);
       
    77 
       
    78 	/**
       
    79 	 * Trace model
       
    80 	 */
       
    81 	private TraceModel model;
       
    82 
       
    83 	/**
       
    84 	 * Constructor
       
    85 	 */
       
    86 	public RulesEngine() {
       
    87 		TraceCompilerEngineGlobals.getConfiguration().addConfigurationListener(
       
    88 				configurationListener);
       
    89 	}
       
    90 
       
    91 	/*
       
    92 	 * (non-Javadoc)
       
    93 	 * 
       
    94 	 * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory#
       
    95 	 *      createExtension(com.nokia.tracecompiler.model.TraceObject,
       
    96 	 *      java.lang.String)
       
    97 	 */
       
    98 	public TraceModelPersistentExtension createExtension(TraceObject target,
       
    99 			String name) {
       
   100 		TraceModelPersistentExtension retval = null;
       
   101 		ClassNameWrapper[] table = RulesEngineConstants.PERSISTENT_EXTENSIONS;
       
   102 		for (int i = 0; i < table.length && retval == null; i++) {
       
   103 			if (name.equals(table[i].name)) {
       
   104 				retval = createPersistentExtensionAt(target, i);
       
   105 			}
       
   106 		}
       
   107 		return retval;
       
   108 	}
       
   109 
       
   110 	/**
       
   111 	 * Creates a persistent extension
       
   112 	 * 
       
   113 	 * @param target
       
   114 	 *            the target object
       
   115 	 * @param i
       
   116 	 *            index to the persistent extensions array
       
   117 	 * @return the extension
       
   118 	 */
       
   119 	private TraceModelPersistentExtension createPersistentExtensionAt(
       
   120 			TraceObject target, int i) {
       
   121 		ClassNameWrapper wrapper = RulesEngineConstants.PERSISTENT_EXTENSIONS[i];
       
   122 		TraceModelPersistentExtension retval = null;
       
   123 		TraceModelPersistentExtension o = target.getExtension(wrapper.clasz);
       
   124 		if (o == null) {
       
   125 			try {
       
   126 				retval = wrapper.clasz.newInstance();
       
   127 			} catch (Exception e) {
       
   128 				if (TraceCompilerEngineConfiguration.ASSERTIONS_ENABLED) {
       
   129 					TraceCompilerEngineGlobals.getEvents().postAssertionFailed(
       
   130 							"Invalid extension - " + wrapper.name, null); //$NON-NLS-1$
       
   131 				}
       
   132 			}
       
   133 		}
       
   134 		return retval;
       
   135 	}
       
   136 
       
   137 	/*
       
   138 	 * (non-Javadoc)
       
   139 	 * 
       
   140 	 * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory#
       
   141 	 *      preProcessNewRules(com.nokia.tracecompiler.model.TraceObject)
       
   142 	 */
       
   143 	public void preProcessNewRules(TraceObject object) {
       
   144 		if (object instanceof TraceModel) {
       
   145 			// NOTE: This is only called once when builder is started
       
   146 			// There is no cleanup code
       
   147 			this.model = (TraceModel) object;
       
   148 			modelListener = new RulesEngineModelListener(this);
       
   149 			resetListener = new RulesEngineResetListener(this, model);
       
   150 			model.addModelListener(modelListener);
       
   151 			model.addResetListener(resetListener);
       
   152 			// Adds the plug-in trace parser / formatter manager to the model as
       
   153 			// extension. The plug-in manager delegates the formatters and
       
   154 			// parsers to this object when plug-in components register to
       
   155 			// TraceCompiler.
       
   156 			pluginManager = new RulesEnginePluginManager(this);
       
   157 			model.addExtension(pluginManager);
       
   158 			createTraceParsers();
       
   159 			createTraceAPIs();
       
   160 		}
       
   161 	}
       
   162 
       
   163 	/**
       
   164 	 * Creates the trace parsers and stores them to the model
       
   165 	 */
       
   166 	private void createTraceParsers() {
       
   167 		for (SourceParserRule element : RulesEngineConstants.TRACE_PARSERS) {
       
   168 			// Creates all source parsers specified in the constants
       
   169 			model.addExtension(element);
       
   170 		}
       
   171 	}
       
   172 
       
   173 	/**
       
   174 	 * Creates the default trace API's and adds them to the plug-in manager
       
   175 	 */
       
   176 	private void createTraceAPIs() {
       
   177 		for (TraceProjectAPI api : RulesEngineConstants.TRACE_APIS) {
       
   178 			pluginManager.addAPI(api);
       
   179 		}
       
   180 	}
       
   181 
       
   182 	/**
       
   183 	 * Creates the trace formatter and stores it to the model
       
   184 	 */
       
   185 	void setDefaultTraceAPI() {
       
   186 		// If the formatter did not exist in the project file, it is added based
       
   187 		// on the configuration default
       
   188 		if (model.getExtension(TraceProjectAPI.class) == null) {
       
   189 			String api = TraceCompilerEngineGlobals.getConfiguration().getText(
       
   190 					TraceCompilerEngineConfiguration.FORMATTER_NAME);
       
   191 			traceAPIChanged(api);
       
   192 		}
       
   193 	}
       
   194 
       
   195 	/**
       
   196 	 * API change notification
       
   197 	 * 
       
   198 	 * @param apiName
       
   199 	 *            the name of new api
       
   200 	 */
       
   201 	void traceAPIChanged(String apiName) {
       
   202 		TraceProjectAPI api = model.getExtension(TraceProjectAPI.class);
       
   203 		boolean found = false;
       
   204 		if (api != null) {
       
   205 			if (api.getName().equals(apiName)) {
       
   206 				found = true;
       
   207 			} else {
       
   208 				model.removeExtension(api);
       
   209 			}
       
   210 		}
       
   211 		if (!found) {
       
   212 			changeTraceAPI(apiName);
       
   213 		}
       
   214 	}
       
   215 
       
   216 	/**
       
   217 	 * Creates a trace API
       
   218 	 * 
       
   219 	 * @param apiName
       
   220 	 *            the name of the API to be created
       
   221 	 */
       
   222 	void changeTraceAPI(String apiName) {
       
   223 		if (apiName == null || apiName.length() == 0) {
       
   224 			apiName = OstTraceFormatRule.STORAGE_NAME;
       
   225 		}
       
   226 		Iterator<TraceProjectAPI> apis = pluginManager.getAPIs();
       
   227 		boolean apifound = false;
       
   228 		while (apis.hasNext()) {
       
   229 			TraceProjectAPI api = apis.next();
       
   230 			if (api.getName().equals(apiName)) {
       
   231 				model.addExtension(api);
       
   232 				apifound = true;
       
   233 			}
       
   234 		}
       
   235 		if (!apifound) {
       
   236 			// If API from configuration was not found, the first one is used
       
   237 			apis = pluginManager.getAPIs();
       
   238 			if (apis.hasNext()) {
       
   239 				model.addExtension(apis.next());
       
   240 			}
       
   241 		}
       
   242 	}
       
   243 
       
   244 	/*
       
   245 	 * (non-Javadoc)
       
   246 	 * 
       
   247 	 * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory#
       
   248 	 *      postProcessNewRules(com.nokia.tracecompiler.model.TraceObject)
       
   249 	 */
       
   250 	public void postProcessNewRules(TraceObject object) {
       
   251 	}
       
   252 
       
   253 	/**
       
   254 	 * Checks the count and types of parameters of given trace and flags it with
       
   255 	 * ComplexParameterRule if necessary
       
   256 	 * 
       
   257 	 * @param trace
       
   258 	 *            the trace
       
   259 	 */
       
   260 	void checkParameterTypes(Trace trace) {
       
   261 		// When converting traces from source, the converter takes care of
       
   262 		// flagging the traces as complex. The complex flag needs to be checked
       
   263 		// when trace are modified via UI
       
   264 		if (!TraceCompilerEngineGlobals.getSourceContextManager().isConverting()) {
       
   265 			boolean complex = false;
       
   266 			int count = trace.getParameterCount();
       
   267 			Iterator<TraceParameter> itr = trace.getParameters();
       
   268 			while (itr.hasNext() && !complex) {
       
   269 				TraceParameter parameter = itr.next();
       
   270 				TraceParameterFormattingRule rule = parameter
       
   271 						.getExtension(TraceParameterFormattingRule.class);
       
   272 				boolean isShown = true;
       
   273 				if (rule != null && !rule.isShownInSource()) {
       
   274 					isShown = false;
       
   275 				}
       
   276 				if (isShown) {
       
   277 					complex = !SourceUtils.isSimpleType(parameter);
       
   278 				} else {
       
   279 					count--;
       
   280 				}
       
   281 			}
       
   282 			// Any trace with more than one parameter is a complex trace
       
   283 			if (!complex && count > SIMPLE_TRACE_MAX_PARAMETER_COUNT) {
       
   284 				complex = true;
       
   285 			}
       
   286 			ComplexHeaderRule rule = trace
       
   287 					.getExtension(ComplexHeaderRule.class);
       
   288 			if (complex && rule == null) {
       
   289 				trace.addExtension(new ComplexHeaderRuleImpl());
       
   290 			} else if (!complex && rule != null) {
       
   291 				trace.removeExtension(rule);
       
   292 			}
       
   293 		}
       
   294 	}
       
   295 
       
   296 	/**
       
   297 	 * Adds fillers to align trace parameters to 32-bit boundaries.
       
   298 	 * 
       
   299 	 * @param trace
       
   300 	 *            the trace to be updated
       
   301 	 * @throws TraceCompilerException 
       
   302 	 */
       
   303 	void checkFillerParameters(Trace trace) throws TraceCompilerException {
       
   304 		// Flags the model so listeners don't perform intermediate updates
       
   305 		trace.getModel().startProcessing();
       
   306 		try {
       
   307 			// Removes all existing fillers
       
   308 			for (int i = 0; i < trace.getParameterCount(); i++) {
       
   309 				TraceParameter parameter = trace.getParameter(i);
       
   310 				if (parameter.getExtension(FillerParameterRule.class) != null) {
       
   311 					trace.removeParameterAt(i);
       
   312 					i--;
       
   313 				}
       
   314 			}
       
   315 			int bytesInBlock = 0;
       
   316 			int parameterIndex = 0;
       
   317 			for (; parameterIndex < trace.getParameterCount(); parameterIndex++) {
       
   318 				TraceParameter parameter = trace.getParameter(parameterIndex);
       
   319 				int paramSize = SourceUtils.mapParameterTypeToSize(parameter);
       
   320 				// Parameters are aligned to 32 bits. Parameter after
       
   321 				// end-of-string is aligned dynamically and thus no filler is
       
   322 				// created for it
       
   323 				if (paramSize == 0 || paramSize == 4 || paramSize == 8) { // CodForChk_Dis_Magic
       
   324 					if (bytesInBlock > 0) {
       
   325 						int fillerCount = 4 - bytesInBlock; // CodForChk_Dis_Magic
       
   326 						for (int i = 0; i < fillerCount; i++) {
       
   327 							createFillerParameter(trace, parameterIndex++);
       
   328 						}
       
   329 						bytesInBlock = 0;
       
   330 					}
       
   331 				} else if (paramSize == 2) { // CodForChk_Dis_Magic
       
   332 					if (bytesInBlock == 1 || bytesInBlock == 3) { // CodForChk_Dis_Magic
       
   333 						createFillerParameter(trace, parameterIndex++);
       
   334 						// If there was 1 existing byte and filler was added,
       
   335 						// the number of bytes in the block is now 4 including
       
   336 						// the 2-byte parameter. If there was 3 bytes, the
       
   337 						// filler brings it to 4 and the 16-bit parameter
       
   338 						// changes it to 2
       
   339 						bytesInBlock += 3; // CodForChk_Dis_Magic
       
   340 					} else {
       
   341 						bytesInBlock += 2; // CodForChk_Dis_Magic
       
   342 					}
       
   343 					if (bytesInBlock >= 4) { // CodForChk_Dis_Magic
       
   344 						bytesInBlock -= 4; // CodForChk_Dis_Magic
       
   345 					}
       
   346 				} else {
       
   347 					bytesInBlock++;
       
   348 					if (bytesInBlock == 4) { // CodForChk_Dis_Magic
       
   349 						bytesInBlock = 0;
       
   350 					}
       
   351 				}
       
   352 			}
       
   353 			// Adds fillers also the the end of the parameter list
       
   354 			if (bytesInBlock > 0) {
       
   355 				int fillerCount = 4 - bytesInBlock; // CodForChk_Dis_Magic
       
   356 				for (int i = 0; i < fillerCount; i++) {
       
   357 					createFillerParameter(trace, parameterIndex++);
       
   358 				}
       
   359 				bytesInBlock = 0;
       
   360 			}
       
   361 		} finally {
       
   362 			trace.getModel().processingComplete();
       
   363 		}
       
   364 	}
       
   365 
       
   366 	/**
       
   367 	 * Creates a filler parameter
       
   368 	 * 
       
   369 	 * @param trace
       
   370 	 *            the trace for the parameter
       
   371 	 * @param parameterIndex
       
   372 	 *            the index where the filler is inserted
       
   373 	 * @throws TraceCompilerException 
       
   374 	 */
       
   375 	private void createFillerParameter(Trace trace, int parameterIndex) throws TraceCompilerException {
       
   376 		trace.getModel().getFactory().createTraceParameter(parameterIndex,
       
   377 				trace, trace.getParameterCount(),
       
   378 				"Filler", //$NON-NLS-1$
       
   379 				TraceParameter.HEX8,
       
   380 				new TraceModelExtension[] { new FillerParameterRuleImpl() });
       
   381 	}
       
   382 
       
   383 }