diff -r a151135b0cf9 -r aa2539c91954 tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/rules/RulesEngine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/engine/rules/RulesEngine.java Fri Oct 08 14:56:39 2010 +0300 @@ -0,0 +1,383 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +* Implementation of TraceObjectRuleFactory interface +* +*/ +package com.nokia.tracecompiler.engine.rules; + +import java.util.Iterator; + +import com.nokia.tracecompiler.engine.TraceCompilerEngineConfiguration; +import com.nokia.tracecompiler.engine.TraceCompilerEngineConfigurationListener; +import com.nokia.tracecompiler.engine.TraceCompilerEngineGlobals; +import com.nokia.tracecompiler.engine.header.ComplexHeaderRule; +import com.nokia.tracecompiler.engine.rules.osttrace.OstTraceFormatRule; +import com.nokia.tracecompiler.engine.source.SourceParserRule; +import com.nokia.tracecompiler.engine.source.TraceParameterFormattingRule; +import com.nokia.tracecompiler.model.Trace; +import com.nokia.tracecompiler.model.TraceCompilerException; +import com.nokia.tracecompiler.model.TraceModel; +import com.nokia.tracecompiler.model.TraceModelExtension; +import com.nokia.tracecompiler.model.TraceModelListener; +import com.nokia.tracecompiler.model.TraceModelPersistentExtension; +import com.nokia.tracecompiler.model.TraceModelResetListener; +import com.nokia.tracecompiler.model.TraceObject; +import com.nokia.tracecompiler.model.TraceObjectRuleFactory; +import com.nokia.tracecompiler.model.TraceParameter; +import com.nokia.tracecompiler.project.TraceProjectAPI; +import com.nokia.tracecompiler.rules.FillerParameterRule; +import com.nokia.tracecompiler.source.SourceUtils; + +/** + * Provides rules for trace objects. + * + */ +public class RulesEngine implements TraceObjectRuleFactory { + + /** + * Number of parameters in a simple trace + */ + private static final int SIMPLE_TRACE_MAX_PARAMETER_COUNT = 1; + + /** + * Trace model listener updates the fillers and complex type flagging when + * traces and parameters are modified + */ + private TraceModelListener modelListener; + + /** + * Trace model reset listener uses modelValid to update the complex header + * rules + */ + private TraceModelResetListener resetListener; + + /** + * Manager for plug-in API's + */ + private RulesEnginePluginManager pluginManager; + + /** + * Configuration listener for source format changes + */ + private TraceCompilerEngineConfigurationListener configurationListener = new RulesEngineConfigurationListener( + this); + + /** + * Trace model + */ + private TraceModel model; + + /** + * Constructor + */ + public RulesEngine() { + TraceCompilerEngineGlobals.getConfiguration().addConfigurationListener( + configurationListener); + } + + /* + * (non-Javadoc) + * + * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory# + * createExtension(com.nokia.tracecompiler.model.TraceObject, + * java.lang.String) + */ + public TraceModelPersistentExtension createExtension(TraceObject target, + String name) { + TraceModelPersistentExtension retval = null; + ClassNameWrapper[] table = RulesEngineConstants.PERSISTENT_EXTENSIONS; + for (int i = 0; i < table.length && retval == null; i++) { + if (name.equals(table[i].name)) { + retval = createPersistentExtensionAt(target, i); + } + } + return retval; + } + + /** + * Creates a persistent extension + * + * @param target + * the target object + * @param i + * index to the persistent extensions array + * @return the extension + */ + private TraceModelPersistentExtension createPersistentExtensionAt( + TraceObject target, int i) { + ClassNameWrapper wrapper = RulesEngineConstants.PERSISTENT_EXTENSIONS[i]; + TraceModelPersistentExtension retval = null; + TraceModelPersistentExtension o = target.getExtension(wrapper.clasz); + if (o == null) { + try { + retval = wrapper.clasz.newInstance(); + } catch (Exception e) { + if (TraceCompilerEngineConfiguration.ASSERTIONS_ENABLED) { + TraceCompilerEngineGlobals.getEvents().postAssertionFailed( + "Invalid extension - " + wrapper.name, null); //$NON-NLS-1$ + } + } + } + return retval; + } + + /* + * (non-Javadoc) + * + * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory# + * preProcessNewRules(com.nokia.tracecompiler.model.TraceObject) + */ + public void preProcessNewRules(TraceObject object) { + if (object instanceof TraceModel) { + // NOTE: This is only called once when builder is started + // There is no cleanup code + this.model = (TraceModel) object; + modelListener = new RulesEngineModelListener(this); + resetListener = new RulesEngineResetListener(this, model); + model.addModelListener(modelListener); + model.addResetListener(resetListener); + // Adds the plug-in trace parser / formatter manager to the model as + // extension. The plug-in manager delegates the formatters and + // parsers to this object when plug-in components register to + // TraceCompiler. + pluginManager = new RulesEnginePluginManager(this); + model.addExtension(pluginManager); + createTraceParsers(); + createTraceAPIs(); + } + } + + /** + * Creates the trace parsers and stores them to the model + */ + private void createTraceParsers() { + for (SourceParserRule element : RulesEngineConstants.TRACE_PARSERS) { + // Creates all source parsers specified in the constants + model.addExtension(element); + } + } + + /** + * Creates the default trace API's and adds them to the plug-in manager + */ + private void createTraceAPIs() { + for (TraceProjectAPI api : RulesEngineConstants.TRACE_APIS) { + pluginManager.addAPI(api); + } + } + + /** + * Creates the trace formatter and stores it to the model + */ + void setDefaultTraceAPI() { + // If the formatter did not exist in the project file, it is added based + // on the configuration default + if (model.getExtension(TraceProjectAPI.class) == null) { + String api = TraceCompilerEngineGlobals.getConfiguration().getText( + TraceCompilerEngineConfiguration.FORMATTER_NAME); + traceAPIChanged(api); + } + } + + /** + * API change notification + * + * @param apiName + * the name of new api + */ + void traceAPIChanged(String apiName) { + TraceProjectAPI api = model.getExtension(TraceProjectAPI.class); + boolean found = false; + if (api != null) { + if (api.getName().equals(apiName)) { + found = true; + } else { + model.removeExtension(api); + } + } + if (!found) { + changeTraceAPI(apiName); + } + } + + /** + * Creates a trace API + * + * @param apiName + * the name of the API to be created + */ + void changeTraceAPI(String apiName) { + if (apiName == null || apiName.length() == 0) { + apiName = OstTraceFormatRule.STORAGE_NAME; + } + Iterator apis = pluginManager.getAPIs(); + boolean apifound = false; + while (apis.hasNext()) { + TraceProjectAPI api = apis.next(); + if (api.getName().equals(apiName)) { + model.addExtension(api); + apifound = true; + } + } + if (!apifound) { + // If API from configuration was not found, the first one is used + apis = pluginManager.getAPIs(); + if (apis.hasNext()) { + model.addExtension(apis.next()); + } + } + } + + /* + * (non-Javadoc) + * + * @see com.nokia.tracecompiler.model.TraceObjectRuleFactory# + * postProcessNewRules(com.nokia.tracecompiler.model.TraceObject) + */ + public void postProcessNewRules(TraceObject object) { + } + + /** + * Checks the count and types of parameters of given trace and flags it with + * ComplexParameterRule if necessary + * + * @param trace + * the trace + */ + void checkParameterTypes(Trace trace) { + // When converting traces from source, the converter takes care of + // flagging the traces as complex. The complex flag needs to be checked + // when trace are modified via UI + if (!TraceCompilerEngineGlobals.getSourceContextManager().isConverting()) { + boolean complex = false; + int count = trace.getParameterCount(); + Iterator itr = trace.getParameters(); + while (itr.hasNext() && !complex) { + TraceParameter parameter = itr.next(); + TraceParameterFormattingRule rule = parameter + .getExtension(TraceParameterFormattingRule.class); + boolean isShown = true; + if (rule != null && !rule.isShownInSource()) { + isShown = false; + } + if (isShown) { + complex = !SourceUtils.isSimpleType(parameter); + } else { + count--; + } + } + // Any trace with more than one parameter is a complex trace + if (!complex && count > SIMPLE_TRACE_MAX_PARAMETER_COUNT) { + complex = true; + } + ComplexHeaderRule rule = trace + .getExtension(ComplexHeaderRule.class); + if (complex && rule == null) { + trace.addExtension(new ComplexHeaderRuleImpl()); + } else if (!complex && rule != null) { + trace.removeExtension(rule); + } + } + } + + /** + * Adds fillers to align trace parameters to 32-bit boundaries. + * + * @param trace + * the trace to be updated + * @throws TraceCompilerException + */ + void checkFillerParameters(Trace trace) throws TraceCompilerException { + // Flags the model so listeners don't perform intermediate updates + trace.getModel().startProcessing(); + try { + // Removes all existing fillers + for (int i = 0; i < trace.getParameterCount(); i++) { + TraceParameter parameter = trace.getParameter(i); + if (parameter.getExtension(FillerParameterRule.class) != null) { + trace.removeParameterAt(i); + i--; + } + } + int bytesInBlock = 0; + int parameterIndex = 0; + for (; parameterIndex < trace.getParameterCount(); parameterIndex++) { + TraceParameter parameter = trace.getParameter(parameterIndex); + int paramSize = SourceUtils.mapParameterTypeToSize(parameter); + // Parameters are aligned to 32 bits. Parameter after + // end-of-string is aligned dynamically and thus no filler is + // created for it + if (paramSize == 0 || paramSize == 4 || paramSize == 8) { // CodForChk_Dis_Magic + if (bytesInBlock > 0) { + int fillerCount = 4 - bytesInBlock; // CodForChk_Dis_Magic + for (int i = 0; i < fillerCount; i++) { + createFillerParameter(trace, parameterIndex++); + } + bytesInBlock = 0; + } + } else if (paramSize == 2) { // CodForChk_Dis_Magic + if (bytesInBlock == 1 || bytesInBlock == 3) { // CodForChk_Dis_Magic + createFillerParameter(trace, parameterIndex++); + // If there was 1 existing byte and filler was added, + // the number of bytes in the block is now 4 including + // the 2-byte parameter. If there was 3 bytes, the + // filler brings it to 4 and the 16-bit parameter + // changes it to 2 + bytesInBlock += 3; // CodForChk_Dis_Magic + } else { + bytesInBlock += 2; // CodForChk_Dis_Magic + } + if (bytesInBlock >= 4) { // CodForChk_Dis_Magic + bytesInBlock -= 4; // CodForChk_Dis_Magic + } + } else { + bytesInBlock++; + if (bytesInBlock == 4) { // CodForChk_Dis_Magic + bytesInBlock = 0; + } + } + } + // Adds fillers also the the end of the parameter list + if (bytesInBlock > 0) { + int fillerCount = 4 - bytesInBlock; // CodForChk_Dis_Magic + for (int i = 0; i < fillerCount; i++) { + createFillerParameter(trace, parameterIndex++); + } + bytesInBlock = 0; + } + } finally { + trace.getModel().processingComplete(); + } + } + + /** + * Creates a filler parameter + * + * @param trace + * the trace for the parameter + * @param parameterIndex + * the index where the filler is inserted + * @throws TraceCompilerException + */ + private void createFillerParameter(Trace trace, int parameterIndex) throws TraceCompilerException { + trace.getModel().getFactory().createTraceParameter(parameterIndex, + trace, trace.getParameterCount(), + "Filler", //$NON-NLS-1$ + TraceParameter.HEX8, + new TraceModelExtension[] { new FillerParameterRuleImpl() }); + } + +}