diff options
author | epaen | 2013-07-12 07:21:40 +0000 |
---|---|---|
committer | epaen | 2013-07-12 14:42:41 +0000 |
commit | d9149c07da6e79281b8f7b03805e79e409391ea3 (patch) | |
tree | e88d60100ec6bd7f79c4c7f5550600526eccaecf /runtime/org.eclipse.etrice.runtime.java.aspects | |
parent | d65e1d1bdd43feadb43261b85aac2d8aef5e089c (diff) | |
download | org.eclipse.etrice-d9149c07da6e79281b8f7b03805e79e409391ea3.tar.gz org.eclipse.etrice-d9149c07da6e79281b8f7b03805e79e409391ea3.tar.xz org.eclipse.etrice-d9149c07da6e79281b8f7b03805e79e409391ea3.zip |
Initial commit of AspectJ trace logging library and example project
based on HelloWorld tutorial
Change-Id: Ieee4607f12a0846e764ee55df47d23d29edb75b9
Diffstat (limited to 'runtime/org.eclipse.etrice.runtime.java.aspects')
10 files changed, 356 insertions, 0 deletions
diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/.classpath b/runtime/org.eclipse.etrice.runtime.java.aspects/.classpath new file mode 100644 index 000000000..a6af4ec59 --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/.classpath @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.etrice.runtime.java"/> + <classpathentry kind="con" path="org.eclipse.ajdt.core.ASPECTJRT_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/.externalToolBuilders/org.eclipse.etrice.runtime.java.aspects.launch b/runtime/org.eclipse.etrice.runtime.java.aspects/.externalToolBuilders/org.eclipse.etrice.runtime.java.aspects.launch new file mode 100644 index 000000000..b65829f25 --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/.externalToolBuilders/org.eclipse.etrice.runtime.java.aspects.launch @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> +<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/> +<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/> +<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/> +<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="true"/> +<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.etrice.runtime.java.aspects"/> +<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/org.eclipse.etrice.runtime.java.aspects/build.xml}"/> +<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value=""/> +<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/> +</launchConfiguration> diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/.gitignore b/runtime/org.eclipse.etrice.runtime.java.aspects/.gitignore new file mode 100644 index 000000000..ba077a403 --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/.gitignore @@ -0,0 +1 @@ +bin diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/.project b/runtime/org.eclipse.etrice.runtime.java.aspects/.project new file mode 100644 index 000000000..4cc0d387f --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/.project @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.etrice.runtime.java.aspects</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.ajdt.core.ajbuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> + <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/org.eclipse.etrice.runtime.java.aspects.launch</value> + </dictionary> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.ajdt.ui.ajnature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.pde.PluginNature</nature> + </natures> +</projectDescription> diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/.settings/org.eclipse.jdt.core.prefs b/runtime/org.eclipse.etrice.runtime.java.aspects/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..8000cd6ca --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/META-INF/MANIFEST.MF b/runtime/org.eclipse.etrice.runtime.java.aspects/META-INF/MANIFEST.MF new file mode 100644 index 000000000..e903b3386 --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/META-INF/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: eTrice Java Runtime Aspects +Bundle-SymbolicName: org.eclipse.etrice.runtime.java.aspects +Bundle-Version: 0.3.0.qualifier +Export-Package: org.eclipse.etrice.runtime.java.aspects +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/build.properties b/runtime/org.eclipse.etrice.runtime.java.aspects/build.properties new file mode 100644 index 000000000..b107977f4 --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/build.properties @@ -0,0 +1,3 @@ +source.. = src/ +bin.includes = META-INF/,\ + . diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/build.xml b/runtime/org.eclipse.etrice.runtime.java.aspects/build.xml new file mode 100644 index 000000000..3b7733551 --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/build.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +====================================================================== +Bundles the aspects into a JAR library in the "release" folder + +NOTE: this build script must be run as part of the Eclipse build +process. External build is not yet supported. +====================================================================== +--> +<project name="org.eclipse.etrice.runtime.java.aspects" default="package-jar"> + <description>Contains aspects which apply to the eTrice Java runtime</description> + <target name="init"> + <!-- TODO: set up basedir if not in eclipse --> + <!-- TODO: set up classpath with aspectj weaver if not in eclipse --> + <property name="jardir" value="${basedir}/dist" /> + <property name="bindir" value="${basedir}/bin" /> + <property name="srcdir" value="${basedir}/src" /> + </target> + <target name="package-jar" depends="init"> + <jar destfile="${jardir}/org.eclipse.etrice.runtime.java.aspects.jar"> + <fileset dir="${bindir}" includes="**/*" /> + <fileset dir="${srcdir}" includes="**/*" /> + </jar> + </target> +</project> diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/dist/org.eclipse.etrice.runtime.java.aspects.jar b/runtime/org.eclipse.etrice.runtime.java.aspects/dist/org.eclipse.etrice.runtime.java.aspects.jar Binary files differnew file mode 100644 index 000000000..359d70d4e --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/dist/org.eclipse.etrice.runtime.java.aspects.jar diff --git a/runtime/org.eclipse.etrice.runtime.java.aspects/src/org/eclipse/etrice/runtime/java/aspects/AbstractRTTrace.aj b/runtime/org.eclipse.etrice.runtime.java.aspects/src/org/eclipse/etrice/runtime/java/aspects/AbstractRTTrace.aj new file mode 100644 index 000000000..a0e5b296e --- /dev/null +++ b/runtime/org.eclipse.etrice.runtime.java.aspects/src/org/eclipse/etrice/runtime/java/aspects/AbstractRTTrace.aj @@ -0,0 +1,248 @@ +/******************************************************************************* + * Copyright (c) 2013 protos software gmbh (http://www.protos.de). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Eyrak Paen (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.runtime.java.aspects; + +import java.util.Map; +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import org.eclipse.etrice.runtime.java.debugging.DebuggingService; +import org.eclipse.etrice.runtime.java.messaging.IRTObject; +import org.eclipse.etrice.runtime.java.messaging.RTObject; +import org.eclipse.etrice.runtime.java.modelbase.RTSystem; +import org.eclipse.etrice.runtime.java.modelbase.SubSystemClassBase; + +/** + * A simple trace aspect that produces synchronous MSC traces using the eTrice + * MSCLogger provided by DebuggingService. + */ +public abstract aspect AbstractRTTrace { + DebuggingService dbgSvc = DebuggingService.getInstance(); + + /** + * Used to keep track of the object context of constructor calls. Each + * thread has its own stack of objects. + */ + Map<Thread, Deque<Object>> ctorFrames = new HashMap<Thread, Deque<Object>>(); + + /** + * Used to keep track of the object context of superclass inits. Each + * thread has its own stack of objects. + */ + Map<Thread, Deque<Object>> initFrames = new HashMap<Thread, Deque<Object>>(); + + /** + * Used to keep track of the object context of superclass inits. Each + * thread has its own stack of objects. + */ + Map<Thread, Object> lastFinishedInit = new HashMap<Thread, Object>(); + + /** + * Matches joinpoints in classes that implement IRTObject, except for + * concrete base implementation RTObject. Provided as a convenience for + * subclasses. + */ + public pointcut rtClasses(): within(RTObject+ && !RTObject); + + /** + * Matches join points in SubSystemClassBase constructor. Allows exclusion + * of joinpoints that occur before DebuggingService is initialized. + */ + pointcut subsystemConstructors(): withincode(SubSystemClassBase+.new(..)); + + /** + * Matches calls to methods of IRTObject, to reduce verboseness of traces. + */ + pointcut traceCallFilter(): call(* IRTObject.*(..)); + + /** + * Includes join points from trace pointcuts. Concrete extensions of this + * aspect must implement this pointcut. + */ + public abstract pointcut traceScope(); + + /** + * Excludes join points from trace pointcuts. Concrete extensions of this + * aspect must implement this pointcut. + */ + public abstract pointcut traceFilter(); + + /** + * Matches method calls from IRTObject to IRTObject. The pointcut uses the + * abstract pointcuts {@link AbstractRTTrace.traceScope} and + * {@link AbstractRTTrace.traceFilter} to control which join points are + * included and excluded, respectively. {@link AbstractRTTrace.traceFilter} is + * applied as a logical NOT. + * + * This pointcut also filters out calls to IRTObject methods and calls to + * the SubSystem constructors that might occur before DebuggingService is + * initialized. + */ + pointcut rtMethodCall(IRTObject src, IRTObject tgt): + traceScope() && + !traceFilter() && + !traceCallFilter() && + call(* *(..)) && + !cflow(subsystemConstructors()) && + this(src) && this(IRTObject) && + target(tgt) && target(IRTObject); + + pointcut rtConstructor(): + traceScope() && + !traceFilter() && + !cflow(subsystemConstructors()) && + !call(RTSystem.new(..)) && !initialization(RTSystem.new(..)); + + pointcut rtConstructorCall(IRTObject src): + rtConstructor() && + call(*.new(..)) && + this(src) && this(IRTObject); + + pointcut rtConstructorInit(IRTObject tgt): + rtConstructor() && + initialization(*.new(..)) && + this(tgt) && this(IRTObject); + + /** + * Logs trace messages before called methods using the MSCLogger provided + * by the DebuggerService singleton. + */ + before(IRTObject src, IRTObject tgt): rtMethodCall(src, tgt) { + String srcLabel = getRTObjectLabel(src); + String tgtLabel = getRTObjectLabel(tgt); + String msgLabel = getMessageLabel(thisJoinPoint.getSignature().getName()); + dbgSvc.getSyncLogger().addMessageSyncCall(srcLabel, tgtLabel, msgLabel); + } + + /** + * Logs trace messages after called methods using the MSCLogger provided + * by the DebuggerService singleton. + */ + after(IRTObject src, IRTObject tgt): rtMethodCall(src, tgt) { + String srcLabel = getRTObjectLabel(src); + String tgtLabel = getRTObjectLabel(tgt); + String msgLabel = getMessageLabel(thisJoinPoint.getSignature().getName()); + dbgSvc.getSyncLogger().addMessageSyncReturn(srcLabel, tgtLabel, msgLabel); + } + + before(IRTObject src): rtConstructorCall(src) { + // add src object to constructor call stack + Deque<Object> stack = getCtorStack(Thread.currentThread()); + // if src is already on the stack, this means that we're past the superclass initializations but still inside src's init + if(stack.isEmpty() || src != stack.peekFirst()) { + stack.offerFirst(src); + } + // Testing + //System.out.println("ctor called in "+getObjectLabel(src)); + } + + before(IRTObject tgt): rtConstructorInit(tgt) { + Deque<Object> initStack = getInitStack(Thread.currentThread()); + Deque<Object> stack = getCtorStack(Thread.currentThread()); + + Object src = stack.peekFirst(); + if((initStack.isEmpty() || tgt != initStack.peekFirst()) && + tgt != lastFinishedInit.get(Thread.currentThread())) { + String srcLabel = getObjectLabel(src); + String tgtLabel = getObjectLabel(tgt); + dbgSvc.getSyncLogger().addMessageCreate(srcLabel, tgtLabel); + // Testing + // System.out.println("(!)"); + } + initStack.offerFirst(tgt); + // Testing + /*String srcLabel = getObjectLabel(src); + String tgtLabel = getObjectLabel(tgt); + System.out.println(srcLabel+"->"+tgtLabel+" (dtn="+thisJoinPoint.getSignature().getDeclaringTypeName()+",tgt="+src.getClass().getName()+")"); + */ + } + + after(IRTObject tgt): rtConstructorInit(tgt) { + Deque<Object> initStack = getInitStack(Thread.currentThread()); + initStack.pollFirst(); + lastFinishedInit.put(Thread.currentThread(), tgt); + // Testing + /*Deque<Object> stack = getCtorStack(Thread.currentThread()); + Object src = stack.peekFirst(); + String srcLabel = getObjectLabel(src); + String tgtLabel = getObjectLabel(tgt); + System.out.println(srcLabel+"<-"+tgtLabel+" (dtn="+thisJoinPoint.getSignature().getDeclaringTypeName()+",tgt="+src.getClass().getName()+")"); + */ + } + + after(IRTObject src): rtConstructorCall(src) { + // add src object to constructor call stack + Deque<Object> stack = getCtorStack(Thread.currentThread()); + stack.pollFirst(); + // Testing + // System.out.println("ctor returned to "+getObjectLabel(src)); + } + + /** + * Builds an MSC source or target label from the IRTObject's instance path. + * @param obj + * @return IRTObject instance label + */ + static String getRTObjectLabel(IRTObject obj) { + String label; + if(obj == null) { + label = "unknown"; + } + else { + label = obj.getInstancePath(); + } + return label; + } + + static String getObjectLabel(Object obj) { + String label; + if(obj == null) { + label = "unknown"; + } + else if(obj instanceof IRTObject) { + label = getRTObjectLabel((IRTObject)obj); + } + else { + label = obj.toString(); + } + return label; + } + + /** + * Builds a MSC message label that includes the current thread's Id. + * @param msg + * @return message label with thread Id + */ + static String getMessageLabel(String msg) { + String label = msg + " (tid=" + Thread.currentThread().getId() + ")"; + return label; + } + + Deque<Object> getCtorStack(Thread t) { + Deque<Object> stack = ctorFrames.get(t); + if(stack == null) { + stack = new LinkedList<Object>(); + ctorFrames.put(t, stack); + } + return stack; + } + + Deque<Object> getInitStack(Thread t) { + Deque<Object> stack = initFrames.get(t); + if(stack == null) { + stack = new LinkedList<Object>(); + initFrames.put(t, stack); + } + return stack; + } +} |