www.pudn.com > use-2.3.0.zip > USEMonitor.java.template
// -*- mode: java -*-
@FILE_HEADER@
package org.tzi.use.monitor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.SourceLocation;
import java.net.Socket;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Set;
import java.util.IdentityHashMap;
/**
* Interface to be implemented (by introduction) by all monitored
* classes. This maps every monitored java object to a unique USE
* object.
*/
interface USEObject {
int getUSEId();
void setUSEId(int id);
}
aspect USEMonitor {
/**
* Set to true if source location should be output as comments in
* USE commands.
*/
private static final boolean LOG_LOCATION = false;
// --- introductions
/**
* Let all observed classes implement the interface USEObject.
*/
declare parents: (
@INTRODUCTION_PARENTS@
) implements USEObject;
/**
* Adds a private ID field to every class that is used to assign
* every new object a unique identifier. This identifier maps USE
* objects to Java objects and vice versa.
*/
private int (
@INTRODUCTION_USEID_FIELD@
).fUSEId;
/**
* Returns the unique ID of an object. Implements the interface
* USEObject.
*/
public int (
@INTRODUCTION_USEID_GETTER@
).getUSEId() { return fUSEId; }
/**
* Sets the unique ID of an object. Implements the interface
* USEObject.
*/
public void (
@INTRODUCTION_USEID_SETTER@
).setUSEId(int id) { fUSEId = id; }
// --- pointcuts
/**
* Monitored classes.
*/
pointcut pcClass() :
@POINTCUT_CLASS@
;
/**
* The constructors of monitored classes.
*/
pointcut pcConstructor(Object _this) :
this(_this) && pcClass() && execution(new(..));
/**
* The methods of monitored classes.
*/
pointcut pcMethod(Object t) :
target(t) && pcClass() && (
@POINTCUT_METHOD@
);
/**
* The field setters of monitored classes.
*/
pointcut pcSetter(Object t, Object _args) :
target(t) && pcClass() && args(_args) && (
@POINTCUT_SETTER@
);
// /**
// * Calls to add methods on collections.
// */
// pointcut pcSetAdd(Object o, Company _this, Object _who) :
// monitoredClass() && target(o) && this(_this)
// && call(* *.add(Object))
// && args(_who);
// /**
// * Calls to remove methods on collections.
// */
// pointcut pcSetRemove(Object o, Company _this, Object _who) :
// monitoredClass() && target(o) && this(_this)
// && call(* *.remove(Object)) && args(_who);
// --- advices
/**
* Monitor object creation.
*/
before (Object _this) : pcConstructor(_this) {
logLocation(thisJoinPoint, "before constructor execution");
// assign object a unique ID for identification in USE
USEObject uobj = (USEObject) _this;
// object may already have an ID when the constructor of a
// super class has been called before
if ( uobj.getUSEId() > 0 )
return;
uobj.setUSEId(fNextId++);
// strip off package name
String classname = thisJoinPoint.getTarget().getClass().getName();
int n = classname.lastIndexOf('.');
if ( n >= 0 && n < classname.length() - 1 )
classname = classname.substring(n + 1);
log("!create " + getUSEObjectName(_this) + " : " + classname);
}
after(Object t) : pcConstructor(t) {
logLocation(thisJoinPoint, "after constructor execution");
log("check");
}
/**
* Monitor method execution.
*/
before (Object t) : pcMethod(t) {
logLocation(thisJoinPoint, "before method execution");
Object[] args = thisJoinPoint.getArgs();
StringBuffer sargs = new StringBuffer();
for (int i = 0; i < args.length; i++) {
if ( i > 0 )
sargs.append(", ");
if ( args[i] instanceof USEObject ) {
int oid = ((USEObject) args[i]).getUSEId();
sargs.append("obj" + oid);
} else if ( args[i] instanceof String )
sargs.append("'" + args[i] + "'");
else
sargs.append(args[i]);
}
String methodName = thisJoinPoint.getSignature().getName();
log("!openter " + getUSEObjectName(t) + " " + methodName + "(" + sargs + ")");
}
after(Object t) returning (Object retVal) : pcMethod(t) {
logLocation(thisJoinPoint, "after method execution");
log("!opexit " + (( retVal == null ) ? "" : retVal));
}
/**
* Trace field setters.
*/
after(Object t, Object newValue) : pcSetter(t, newValue) {
logLocation(thisJoinPoint, "setting field");
String value = newValue.toString();
if ( newValue instanceof String )
value = "'" + value + "'";
String attrName = thisJoinPoint.getSignature().getName();
// filter assignments to fields related to associations
// FIXME: generalize
if ( ! attrName.equals("employee") )
log("!set " + getUSEObjectName(t) + "." + attrName + " := " + value);
else
fFields.put(newValue, attrName);
}
// /**
// * Insert association links.
// */
// after(Object o, Company _this, Object _who) : pcSetAdd(o, _this, _who) {
// logLocation(thisJoinPoint, "adding link");
// if ( fFields.containsKey(o) ) {
// log("!insert ("
// + getUSEObjectName(_who) + ", "
// + getUSEObjectName(_this)
// + ") into WorksFor");
// }
// }
// /**
// * Insert association links.
// */
// after(Object o, Company _this, Object _who) : pcSetRemove(o, _this, _who) {
// logLocation(thisJoinPoint, "removing link");
// if ( fFields.containsKey(o) ) {
// log("!delete ("
// + getUSEObjectName(_who) + ", "
// + getUSEObjectName(_this)
// + ") from WorksFor");
// }
// }
// after(Object o) : pcSetGetter(o) {
// logLocation(thisJoinPoint, "----------------- pcSetGetter");
// log("* " + o + ", " + thisJoinPoint.getSignature());
// }
/**
* The next unique ID assigned to a new object.
*/
private static int fNextId = 1;
/**
* Map of field values to field names. Used for identifying
* modifications of association elements.
*/
private IdentityHashMap fFields = new IdentityHashMap(); // (Object -> String fieldname)
// helpers
private String getUSEObjectName(Object obj) {
int id = ((USEObject) obj).getUSEId();
return "obj" + id;
}
private void logLocation(JoinPoint jp, String msg) {
if ( LOG_LOCATION ) {
SourceLocation loc = jp.getSourceLocation();
log("-- " + loc.getFileName() + ":" + loc.getLine() + ": " + msg);
}
}
private Socket fSocket;
private boolean fInitDone;
private PrintWriter fOut;
/**
* Initializes a socket connection to USE.
*/
private void initSocket() {
fInitDone = true;
try {
fSocket = new Socket("localhost", 1777);
// flush after each line of output
fOut = new PrintWriter(fSocket.getOutputStream(), true);
} catch (IOException ex) {
System.err.println("can't connect to localhost/1777: " + ex.getMessage());
if ( fSocket != null ) {
try {
fSocket.close();
} catch (IOException e) { }
}
}
}
/**
* Outputs commands either to socket or stdout
*/
private void log(String msg) {
if ( fSocket == null && ! fInitDone )
initSocket();
if ( fOut != null ) {
fOut.println(msg);
} else {
System.out.println(msg);
}
}
}