refactor of event generation -- compatible with Cugat events

import java.io.*;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.lang.ClassLoader;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.mapred.TaskStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.util.DataChecksum;
import java.net.Socket;

import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.hdfs.DFSClient;

import org.apache.hadoop.mapred.TaskTrackerStatus;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;

/**
 *
 * @author Alejandro
 */

aspect AlojaAspect {

	private static final Log LOG = LogFactory.getLog(AlojaAspect.class);

	/*
	TYPES
	######################################################################################################################################
	######################################################################################################################################
	*/

    public static class Events {

        public static final int JobTracker = 11111;
        public static final int TaskTracker = 11112;
        public static final int NameNode = 11113;
        public static final int SecondaryNameNode = 11114;
        public static final int DataNode = 11115;
        public static final int Task = 11116;
//        public static final int MapTask = 11117;
//        public static final int ReduceTask = 11118;
        public static final int MapOutputBuffer = 33333;
        public static final int MapTaskOutputSize = 44444;
    }

    public static class Values {

       	// Generic
		public static final int End = 0;
        public static final int Start = 1;

        // Events.TaskTracker
		public static final int RunMapper = 8;
        public static final int RunReducer = 9;
        public static final int Combine = 4;
        public static final int ReducerCopyPhase = 10;
        public static final int ReducerSortPhase = 11;
        public static final int ReducerReducePhase = 12;

		// Events.JobTracker
		public static final int HeartBeat = 13;

        public static final int Flush = 1;
        public static final int SortAndSpill = 2;
        public static final int Sort = 3;
        public static final int CreateSpillIndexFile = 5;
        public static final int TotalIndexCacheMemory = 6;
        public static final int SpillRecordDumped = 7;
    }

	/*
	FUNCTIONS
	######################################################################################################################################
	######################################################################################################################################
	*/

	private static long getPID() {
		String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
		return Long.parseLong(name.split("@")[0]);
	}

	private void generateEvent(Integer key, Integer value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	private void generateEvent(Integer key, String value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	/*private void generateEVent(Integer key[], Integer value) {

		StringBuffer output = new StringBuffer();

		output.append()

	}*/

	private void instrumentation(String event, String when) {

		instrumentation(event, when, "");

	}
	private void instrumentation(String event, String when, String additional) {
		try {
			//Add hostname
			String log = InetAddress.getLocalHost().getHostName();
			//Add PID
			log += "," + getPID();
			//Specify event
			log += "," + when + "," + event;
			//Specify event
			log += additional;
			//LOG.info(log);
			//writeLog(logFile,log);

		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	POINTCUTS
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode Pointcut

	pointcut startDataNode(): execution(* org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(..));

	//RegisterNameNode Pointcut

	pointcut initializeNameNode():  execution(* org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(..));

	//RegisterSecondaryNamenode Pointcut

	pointcut initializeSecondaryNameNode(): execution(* org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(..));

	//RegisterTask - CHILD

	//pointcut initializeChild(): call(* org.apache.hadoop.mapred.Child.initMetrics(..)) && withincode(* org.apache.hadoop.mapred.Child.main(..));

	pointcut initializeChild(): execution(* org.apache.hadoop.mapred.Child.main(..));

	//Register JobTracker Pointcut

	pointcut registerJobTracker(): execution(* org.apache.hadoop.mapred.JobTracker.startTracker(..));

	//HEARTBEAT

	pointcut heartbeat(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId): execution(* org.apache.hadoop.mapred.JobTracker.heartbeat(..)) && args(status, restarted, initialContact, acceptNewTasks,responseId);

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	pointcut outputSize(): call (* *.getLen(..)) && withincode(* org.apache.hadoop.mapred.Task.calculateOutputSize());

	/*
		###########################################################################
		############################MAPPER#########################################
		###########################################################################
	*/

	//pointcut maptask(): execution(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut mapper(): call(* org.apache.hadoop.mapred.MapTask.runNewMapper(..)) && withincode(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut flush(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.flush());

	//  ############################SORT AND SPILL#################################

	//Start-End
	pointcut taskSortAndSpill(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill File Size
	pointcut sortAndSpillSpillFile(int numSpills, long size) : call (* *.getSpillFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, size);

	//SpillIndex File Size
	pointcut sortAndSpillSpillIndexFile(int numSpills, long partitions) : call (* *.getSpillIndexFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, partitions);

	//Sort
	pointcut sortAndSpillSort(int kvstart, int endPosition, Object reporter): call(* *.sort(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(..,kvstart,endPosition,reporter);

	//Init Writer
	pointcut sortAndSpillInitWriter() : call (org.apache.hadoop.mapred.IFile.Writer.new(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Close Writer
	pointcut sortAndSpillCloseWriter() : call (void org.apache.hadoop.mapred.IFile.Writer.close(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Write key-value

	//pointcut sortAndSpillWrite(DataInputBuffer key, DataInputBuffer value): call (* *.append(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(key,value) && !within(Aspect);

	//Combiner
	pointcut sortAndSpillCombiner(): call(* *.combine(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill Index File
	pointcut sortAndSpillSpillIndexWrite(): call(* *.writeToFile(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	//REDUCETASK RUN
	pointcut reducer(): execution(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut initCodec(): call(* *.initCodec(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut setPhase(TaskStatus.Phase phase): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..)) && args(phase);

	//pointcut endCopy(): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	//pointcut endSort(): call(* *.getMapOutputKeyClass(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	pointcut defaultBlockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getDefaultBlockSize());
	//pointcut blockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getBlockSize(..));
	pointcut createDFSFile(String src,FsPermission permission,boolean overwrite,boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): execution (* org.apache.hadoop.hdfs.DFSClient.create(..)) && args(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize);
	pointcut runDataStreamer(): execution (* org.apache.hadoop.hdfs.DFSClient.DFSOutputStream.DataStreamer.run());
	//pointcut readEntireBufferFromDataNode(byte buf[],int off,int len): execution(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..)) && args(buf[],off,len);
	//pointcut readFromDataNode(): call (* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.blockSeekTo(..)) && withincode(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..));
	pointcut newBlockReader(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName): execution (* org.apache.hadoop.hdfs.DFSClient.BlockReader.newBlockReader(..)) && args(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName);

	/*
	Advices
	######################################################################################################################################
	######################################################################################################################################
	*/

	// RegiterJobTracker

	after() : registerJobTracker(){
		generateEvent(Events.JobTracker, Values.Start);

	}

	//RegisterTaskTracker ?

	//RegisterNameNode

	after() : initializeNameNode(){
		generateEvent(Events.NameNode, Values.Start);
	}

	//RegisterDataNode

	after() : startDataNode(){
		generateEvent(Events.DataNode, Values.Start);
	}

	//RegisterSecondaryNamenode

	after() : initializeSecondaryNameNode(){
		generateEvent(Events.SecondaryNameNode, Values.Start);
	}

	//HEARTBEAT
	after(TaskTrackerStatus status,boolean restarted,boolean initialContact,boolean acceptNewTasks,short responseId) : heartbeat(status, restarted, initialContact, acceptNewTasks,responseId){
		generateEvent(Events.JobTracker, status.getTrackerName());
	}

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	//RegisterTask CHILD
	after() : initializeChild() { //We need the  PID of this task to be registered
		generateEvent(Events.Task, Values.Start);
	}

/*	after() returning(long size) : outputSize() {
		String s = "Task-outputSize";
		instrumentation(s,"after",", size: " + Long.toString(size));
	}

	/*
		###########################################################################
		############################Mapper#########################################
		###########################################################################
	*/

	/*before() : maptask(){
		generateEvent(Events.MapTask, Values.Start);
	}*/

	before() : mapper(){
		generateEvent(Events.TaskTracker, Values.RunMapper);
	}

	after() : mapper(){
		generateEvent(Events.TaskTracker, Values.End);
	}

	//flush

	before() : flush(){
		String s = "Flush";
		instrumentation(s,"before");
	}

	after() : flush(){
		String s = "Flush";
		instrumentation(s,"after");
	}

	//  ############################SORT AND SPILL#################################

	before() : taskSortAndSpill(){
		String s = "sortAndSpill";
		instrumentation(s,"before");
	}

	after() : taskSortAndSpill(){
		String s = "sortAndSpill";
		instrumentation(s,"after");
	}

	// Spill File Size

	after(int numSpills, long size) returning : sortAndSpillSpillFile(numSpills, size){
		String s = "sortAndSpillSpillFile";
		instrumentation(s,"after",", numSpills: " +Integer.toString(numSpills) + ";size: " + Long.toString((size*numSpills) + size));
	}

	// SpillIndex File Size

	after(int numSpills, long partitions) returning : sortAndSpillSpillIndexFile(numSpills, partitions){
		String s = "sortAndSpillSpillIndexFile";
		instrumentation(s,"after","," + Long.toString(numSpills * partitions));
	}

/*
	before(int length) : kvbufferState(length){

		String s = "kvbufferState";
		File logFile = getFile();
		instrumentation(logFile,s,"before");
		writeLog(logFile,Integer.toString(length));
	}

*/

	before(int kvstart, int endPosition, Object reporter) : sortAndSpillSort(kvstart,endPosition,reporter){
		String s = "sortAndSpillSort";
		instrumentation(s,"before","," + Integer.toString(endPosition - kvstart));
	}
	after(int kvstart, int endPosition, Object reporter) returning : sortAndSpillSort(kvstart,endPosition,reporter){
		String s = "sortAndSpillSort";
		instrumentation(s,"after","," + Integer.toString(endPosition - kvstart));
	}

	// Init writer
	after() returning : sortAndSpillInitWriter(){
		String s = "sortAndSpillInitWriter";
		instrumentation(s,"after");
	}

	// Close writer
	after() returning : sortAndSpillCloseWriter(){
		String s = "sortAndSpillCloseWriter";
		instrumentation(s,"after");
	}

/*
	after(DataInputBuffer key, DataInputBuffer value) returning : sortAndSpillWrite(key,value){
		String s = "sortAndSpillWrite";
		File logFile = getFile();
		instrumentation(logFile,s,"after");
		String log = "," + key.getData(); // + "," + value.getData();
		writeLog(logFile,log);
	}
*/
	before() : sortAndSpillCombiner(){
		String s = "sortAndSpillCombiner";
		instrumentation(s,"before");
	}

	after() returning : sortAndSpillCombiner(){
		String s = "sortAndSpillCombiner";
		instrumentation(s,"after");
	}

	before() : sortAndSpillSpillIndexWrite(){
		String s = "sortAndSpillSpillIndexWrite";
		instrumentation(s,"before");
	}

	after() returning : sortAndSpillSpillIndexWrite(){
		String s = "sortAndSpillSpillIndexWrite";
		instrumentation(s,"after");
	}

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

/*	before() : reducer(){
		String s = "Reducer";
		instrumentation(s,"before");
	}
*/

	before() : initCodec() {
		generateEvent(Events.TaskTracker, Values.RunReducer);
	}

	after() returning : initCodec() {
		generateEvent(Events.TaskTracker, Values.ReducerCopyPhase);
	}

	before(TaskStatus.Phase phase) : setPhase(phase) { //END OF A PHASE (SORT OR COPY)
			generateEvent(Events.TaskTracker, Values.End);
	}

	after(TaskStatus.Phase phase) returning: setPhase(phase) {
		if (phase == TaskStatus.Phase.SORT) {
			generateEvent(Events.TaskTracker, Values.ReducerSortPhase);
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			generateEvent(Events.TaskTracker, Values.ReducerReducePhase);
		}
	}

	after() : reducer(){ //END OF REDUCE PHASE
			generateEvent(Events.TaskTracker, Values.End);	}

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	after() returning(long blockSize) : defaultBlockSize() {
		String s = "Network-defaultBlockSize";
		instrumentation(s,"after",", size: " + Long.toString(blockSize));
	}
	// after() returning(long blockSize) : blockSize() {
	// 	String s = "Network-blockSize";
	// 	File logFile = getFile();
	// 	instrumentation(logFile,s,"after");
	// 	String log = ", size: " + Long.toString(blockSize);
	// 	writeLog(logFile,log);
	// }

	after(String src,FsPermission permission,boolean overwrite, boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): createDFSFile(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize) {
		String s = "Network-CreateDFSFile";

		//MODIFIED!!!!!!-----!!!!!!!!!!!
		instrumentation(s,"after",", path: " + src + ";permission: " + permission.toString() + ";overwrite: " + String.valueOf(overwrite) + ";createParent: " + String.valueOf(createParent) + ";replication: " + Short.toString(replication) + ";blockSize: " + Long.toString(blockSize) + ";buffersize: " + Integer.toString(buffersize));
	}
	before(): runDataStreamer() {
		String s = "DataStreamer";
		instrumentation(s,"after");
	}

	// before(byte buf[],int off, int len) : readEntireBufferFromDataNode(buf[],off,len){
	// 	String s = "Network-ReadEntireBuffer";
	// 	instrumentation(s,"after",", bufferLength: " + Integer.toString(len));
	// }

	// after() returning(DatanodeInfo datanode) : readFromDataNode(){
	// 	String s = "Network-fromDataNode";
	// 	instrumentation(s,"after", ", from : " + datanode.getHostName());
	// }

	after(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName) : newBlockReader(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName) {
		String s = "Network-NewBlockReader";
		String extra = ", DataNode: " + sock.getInetAddress().getCanonicalHostName();
		extra += ";file: " + file;
		//extra += ", length: " + Long.toString(len) + "B";
		extra += ";" + Long.toString(len);
		extra += ";blockId: " + Long.toString(blockId);
		extra += ";startOffset: " + Long.toString(startOffset);
		instrumentation(s,"after",extra);
	}
}

import java.io.*;
import java.util.*;
import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.net.InetAddress;
import java.lang.ClassLoader;
import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.mapred.TaskStatus;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.util.Progressable;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.util.DataChecksum;
import java.net.Socket;

import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.hdfs.DFSClient;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;

/**
 *
 * @author Alejandro
 */

aspect AlojaAspect {

	private static final Log LOG = LogFactory.getLog(AlojaAspect.class);

	/*
	FUNCTIONS
	######################################################################################################################################
	######################################################################################################################################
	*/

	private static long getPID() {
		String name = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
		return Long.parseLong(name.split("@")[0]);
	}

	private void generateEvent(Integer key, Integer value) {
		//2:cpu:app:task:thread:time:type:value
		try{
			String hostname = InetAddress.getLocalHost().getHostName();
			long pid = getPID();
			LOG.info(hostname+","+pid+",2:"+hostname+":2:"+pid+":1:"+System.currentTimeMillis()+":"+key+":"+value);
		}
		catch (Exception e) {
			LOG.error(e, e);

		}
	}

	/*private void generateEVent(Integer key[], Integer value) {

		StringBuffer output = new StringBuffer();

		output.append()

	}*/

	private void instrumentation(String event, String when) {

		instrumentation(event, when, "");

	}
	private void instrumentation(String event, String when, String additional) {
		try {
			//Add hostname
			String log = InetAddress.getLocalHost().getHostName();
			//Add PID
			log += "," + getPID();
			//Specify event
			log += "," + when + "," + event;
			//Specify event
			log += additional;
			LOG.info(log);
			//writeLog(logFile,log);

		}
		catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	POINTCUTS
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode Pointcut

	pointcut startDataNode(): execution(* org.apache.hadoop.hdfs.server.datanode.DataNode.startDataNode(..));

	//RegisterNameNode Pointcut

	pointcut initializeNameNode():  execution(* org.apache.hadoop.hdfs.server.namenode.NameNode.initialize(..));

	//RegisterSecondaryNamenode Pointcut

	pointcut initializeSecondaryNameNode(): execution(* org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.initialize(..));

	//RegisterTask - CHILD

	//pointcut initializeChild(): call(* org.apache.hadoop.mapred.Child.initMetrics(..)) && withincode(* org.apache.hadoop.mapred.Child.main(..));

	pointcut initializeChild(): execution(* org.apache.hadoop.mapred.Child.main(..));

	//Register JobTracker Pointcut

	pointcut registerJobTracker(): execution(* org.apache.hadoop.mapred.JobTracker.startTracker(..));

	//HEARTBEAT

	pointcut heartbeat(): execution(* org.apache.hadoop.mapred.JobTracker.heartbeat(..));

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	pointcut outputSize(): call (* *.getLen(..)) && withincode(* org.apache.hadoop.mapred.Task.calculateOutputSize());

	/*
		###########################################################################
		############################MAPPER#########################################
		###########################################################################
	*/

	pointcut maptask(): execution(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut mapper(): call(* org.apache.hadoop.mapred.MapTask.runNewMapper(..)) && withincode(* org.apache.hadoop.mapred.MapTask.run(..));
	pointcut flush(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.flush());

	//  ############################SORT AND SPILL#################################

	//Start-End
	pointcut taskSortAndSpill(): execution(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill File Size
	pointcut sortAndSpillSpillFile(int numSpills, long size) : call (* *.getSpillFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, size);

	//SpillIndex File Size
	pointcut sortAndSpillSpillIndexFile(int numSpills, long partitions) : call (* *.getSpillIndexFileForWrite(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(numSpills, partitions);

	//Sort
	pointcut sortAndSpillSort(int kvstart, int endPosition, Object reporter): call(* *.sort(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(..,kvstart,endPosition,reporter);

	//Init Writer
	pointcut sortAndSpillInitWriter() : call (org.apache.hadoop.mapred.IFile.Writer.new(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Close Writer
	pointcut sortAndSpillCloseWriter() : call (void org.apache.hadoop.mapred.IFile.Writer.close(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Write key-value

	//pointcut sortAndSpillWrite(DataInputBuffer key, DataInputBuffer value): call (* *.append(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill()) && args(key,value) && !within(Aspect);

	//Combiner
	pointcut sortAndSpillCombiner(): call(* *.combine(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	//Spill Index File
	pointcut sortAndSpillSpillIndexWrite(): call(* *.writeToFile(..)) && withincode(* org.apache.hadoop.mapred.MapTask.MapOutputBuffer.sortAndSpill());

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	//REDUCETASK RUN

	pointcut reducer(): execution(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut initCopy(): call(* *.initCodec(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	pointcut endPhase(TaskStatus.Phase phase): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..)) && args(phase);

	//pointcut endCopy(): call(* *.setPhase(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));
	//pointcut endSort(): call(* *.getMapOutputKeyClass(..)) && withincode(* org.apache.hadoop.mapred.ReduceTask.run(..));

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	pointcut defaultBlockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getDefaultBlockSize());
	//pointcut blockSize(): call(* org.apache.hadoop.hdfs.DFSClient.getBlockSize(..));
	pointcut createDFSFile(String src,FsPermission permission,boolean overwrite,boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): execution (* org.apache.hadoop.hdfs.DFSClient.create(..)) && args(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize);
	pointcut runDataStreamer(): execution (* org.apache.hadoop.hdfs.DFSClient.DFSOutputStream.DataStreamer.run());
	//pointcut readEntireBufferFromDataNode(byte buf[],int off,int len): execution(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..)) && args(buf[],off,len);
	//pointcut readFromDataNode(): call (* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.blockSeekTo(..)) && withincode(* org.apache.hadoop.hdfs.DFSClient.DFSInputStream.read(..));
	pointcut newBlockReader(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName): execution (* org.apache.hadoop.hdfs.DFSClient.BlockReader.newBlockReader(..)) && args(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName);

	/*
	Advices
	######################################################################################################################################
	######################################################################################################################################
	*/

	//RegisterDataNode

	after() : startDataNode(){
		generateEvent(11115, 1);
	}

	//RegisterNameNode

	after() : initializeNameNode(){
		generateEvent(11113, 1);
	}

	//RegisterSecondaryNamenode

	after() : initializeSecondaryNameNode(){
		generateEvent(11114, 1);
	}

	//RegisterTask CHILD

	after() : initializeChild() {
		generateEvent(11116, 1);
	}

	// RegiterJobTracker

	after() : registerJobTracker(){
		generateEvent(11111, 1);

	}

	//HEARTBEAT
	after() : heartbeat(){
		generateEvent(11119, 1);
	}

	/*
		###########################################################################
		############################Task###########################################
		###########################################################################
	*/

	after() returning(long size) : outputSize() {
		String s = "Task-outputSize";
		instrumentation(s,"after",", size: " + Long.toString(size));
	}

	/*
		###########################################################################
		############################Mapper#########################################
		###########################################################################
	*/

	before() : maptask(){
		generateEvent(11116, 1);
	}

	before() : mapper(){
		generateEvent(11117, 1);
	}

	after() : mapper(){
		generateEvent(11117, 0);
	}

	//flush

	before() : flush(){
		String s = "Flush";
		instrumentation(s,"before");
	}

	after() : flush(){
		String s = "Flush";
		instrumentation(s,"after");
	}

	//  ############################SORT AND SPILL#################################

	before() : taskSortAndSpill(){
		String s = "sortAndSpill";
		instrumentation(s,"before");
	}

	after() : taskSortAndSpill(){
		String s = "sortAndSpill";
		instrumentation(s,"after");
	}

	// Spill File Size

	after(int numSpills, long size) returning : sortAndSpillSpillFile(numSpills, size){
		String s = "sortAndSpillSpillFile";
		instrumentation(s,"after",", numSpills: " +Integer.toString(numSpills) + ";size: " + Long.toString((size*numSpills) + size));
	}

	// SpillIndex File Size

	after(int numSpills, long partitions) returning : sortAndSpillSpillIndexFile(numSpills, partitions){
		String s = "sortAndSpillSpillIndexFile";
		instrumentation(s,"after","," + Long.toString(numSpills * partitions));
	}

/*
	before(int length) : kvbufferState(length){

		String s = "kvbufferState";
		File logFile = getFile();
		instrumentation(logFile,s,"before");
		writeLog(logFile,Integer.toString(length));
	}

*/

	before(int kvstart, int endPosition, Object reporter) : sortAndSpillSort(kvstart,endPosition,reporter){
		String s = "sortAndSpillSort";
		instrumentation(s,"before","," + Integer.toString(endPosition - kvstart));
	}
	after(int kvstart, int endPosition, Object reporter) returning : sortAndSpillSort(kvstart,endPosition,reporter){
		String s = "sortAndSpillSort";
		instrumentation(s,"after","," + Integer.toString(endPosition - kvstart));
	}

	// Init writer
	after() returning : sortAndSpillInitWriter(){
		String s = "sortAndSpillInitWriter";
		instrumentation(s,"after");
	}

	// Close writer
	after() returning : sortAndSpillCloseWriter(){
		String s = "sortAndSpillCloseWriter";
		instrumentation(s,"after");
	}

/*
	after(DataInputBuffer key, DataInputBuffer value) returning : sortAndSpillWrite(key,value){
		String s = "sortAndSpillWrite";
		File logFile = getFile();
		instrumentation(logFile,s,"after");
		String log = "," + key.getData(); // + "," + value.getData();
		writeLog(logFile,log);
	}
*/
	before() : sortAndSpillCombiner(){
		String s = "sortAndSpillCombiner";
		instrumentation(s,"before");
	}

	after() returning : sortAndSpillCombiner(){
		String s = "sortAndSpillCombiner";
		instrumentation(s,"after");
	}

	before() : sortAndSpillSpillIndexWrite(){
		String s = "sortAndSpillSpillIndexWrite";
		instrumentation(s,"before");
	}

	after() returning : sortAndSpillSpillIndexWrite(){
		String s = "sortAndSpillSpillIndexWrite";
		instrumentation(s,"after");
	}

	/*
		###########################################################################
		############################REDUCER########################################
		###########################################################################
	*/

	before() : reducer(){
		String s = "Reducer";
		instrumentation(s,"before");
	}

	after() returning : initCopy() {
		String s = "Reducer-copy-phase";
		instrumentation(s,"before");
	}

	before(TaskStatus.Phase phase) : endPhase(phase) {
		if (phase == TaskStatus.Phase.SORT){
			String s = "Reducer-copy-phase";
			instrumentation(s,"after");
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			String s = "Reducer-sort-phase";
			instrumentation(s,"after");
		}
	}

	after(TaskStatus.Phase phase) returning: endPhase(phase) {
		if (phase == TaskStatus.Phase.SORT) {
			String s = "Reducer-sort-phase";
			instrumentation(s,"before");
		}
		else if (phase == TaskStatus.Phase.REDUCE) {
			String s = "Reducer-reduce-phase";
			instrumentation(s,"before");
		}
	}

	after() : reducer(){
		String s = "Reducer-reduce-phase";
		instrumentation(s,"after");
	}

	/*
		###########################################################################
		############################NETWORK########################################
		###########################################################################
	*/

	after() returning(long blockSize) : defaultBlockSize() {
		String s = "Network-defaultBlockSize";
		instrumentation(s,"after",", size: " + Long.toString(blockSize));
	}
	// after() returning(long blockSize) : blockSize() {
	// 	String s = "Network-blockSize";
	// 	File logFile = getFile();
	// 	instrumentation(logFile,s,"after");
	// 	String log = ", size: " + Long.toString(blockSize);
	// 	writeLog(logFile,log);
	// }

	after(String src,FsPermission permission,boolean overwrite, boolean createParent,short replication,long blockSize,Progressable progress, int buffersize): createDFSFile(src,permission,overwrite,createParent,replication,blockSize,progress,buffersize) {
		String s = "Network-CreateDFSFile";

		//MODIFIED!!!!!!-----!!!!!!!!!!!
		instrumentation(s,"after",", path: " + src + ";permission: " + permission.toString() + ";overwrite: " + String.valueOf(overwrite) + ";createParent: " + String.valueOf(createParent) + ";replication: " + Short.toString(replication) + ";blockSize: " + Long.toString(blockSize) + ";buffersize: " + Integer.toString(buffersize));
	}
	before(): runDataStreamer() {
		String s = "DataStreamer";
		instrumentation(s,"after");
	}

	// before(byte buf[],int off, int len) : readEntireBufferFromDataNode(buf[],off,len){
	// 	String s = "Network-ReadEntireBuffer";
	// 	instrumentation(s,"after",", bufferLength: " + Integer.toString(len));
	// }

	// after() returning(DatanodeInfo datanode) : readFromDataNode(){
	// 	String s = "Network-fromDataNode";
	// 	instrumentation(s,"after", ", from : " + datanode.getHostName());
	// }

	after(Socket sock, String file, long blockId, Token<BlockTokenIdentifier> accessToken, long genStamp, long startOffset, long len, int bufferSize, boolean verifyChecksum, String clientName) : newBlockReader(sock,file,blockId,accessToken,genStamp,startOffset,len,bufferSize,verifyChecksum,clientName) {
		String s = "Network-NewBlockReader";
		String extra = ", DataNode: " + sock.getInetAddress().getCanonicalHostName();
		extra += ";file: " + file;
		//extra += ", length: " + Long.toString(len) + "B";
		extra += ";" + Long.toString(len);
		extra += ";blockId: " + Long.toString(blockId);
		extra += ";startOffset: " + Long.toString(startOffset);
		instrumentation(s,"after",extra);
	}
}


Handle AsyncLatch with AspectJ

Handle AsyncLatch with AspectJ

for https://github.com/zxwing/premium/issues/1498

Signed-off-by: David Lee <15c338f3b79a63a0d5423e9c6562cd312918fe74@gmail.com>

package org.zstack.core.aspect;

import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.core.workflow.FlowRollback;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.core.thread.SyncTaskChain;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.core.*;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.exception.CloudRuntimeException;
import org.zstack.header.message.Message;
import org.zstack.utils.DebugUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;

import java.util.List;

public aspect AsyncBackupAspect {
    private final CLogger logger = Utils.getLogger(AsyncBackupAspect.class);

    @Autowired
    private CloudBus bus;
    @Autowired
    private ErrorFacade errf;

    private boolean isAsyncBackup(Object backup) {
        return backup instanceof Message || backup instanceof Completion || backup instanceof ReturnValueCompletion
                || backup instanceof AsyncLatch
                || backup instanceof FlowTrigger || backup instanceof SyncTaskChain
                || backup instanceof NoErrorCompletion || backup instanceof FlowRollback;
    }

    private void backup(List<AsyncBackup> ancestors, Throwable t, boolean flipThrowable) {
        if (ancestors == null || ancestors.isEmpty()) {
            // throw original exception out if no backup specified
            if (t instanceof RuntimeException) {
                throw (RuntimeException)t;
            } else if (t instanceof Error) {
                throw (Error)t;
            } else {
                throw new CloudRuntimeException(t);
            }
        }

        for (AsyncBackup ancestor : ancestors) {
            if (!isAsyncBackup(ancestor)) {
                String info = String.format("%s is not a known AsyncBackup. Someone added this type but forgot changing AsyncBackupAspect, please file bug", ancestor.getClass().getName());
                DebugUtils.dumpStackTrace(info);
                return;
            }

            ErrorCode err = t instanceof OperationFailureException ? ((OperationFailureException) t).getErrorCode() : errf.throwableToInternalError(t);
            if (ancestor instanceof Completion) {
                ((Completion)ancestor).fail(err);
            } else if (ancestor instanceof ReturnValueCompletion) {
                ((ReturnValueCompletion)ancestor).fail(err);
            } else if (ancestor instanceof AsyncLatch) {
                ((AsyncLatch) ancestor).ack();
            } else if (ancestor instanceof FlowTrigger) {
                ((FlowTrigger) ancestor).fail(err);
            } else if (ancestor instanceof FlowRollback) {
                ((FlowRollback) ancestor).rollback();
            } else if (ancestor instanceof  SyncTaskChain) {
                ((SyncTaskChain) ancestor).next();
            } else if (ancestor instanceof NoErrorCompletion) {
                ((NoErrorCompletion) ancestor).done();
            } else if (ancestor instanceof Message) {
                bus.logExceptionWithMessageDump((Message) ancestor, t);
                bus.replyErrorByMessageType((Message) ancestor, err);
            } else {
                throw new CloudRuntimeException("should not be here");
            }
        }

        if (flipThrowable && t instanceof RuntimeException) {
            throw (RuntimeException)t;
        } else {
            logger.warn("unhandled exception happened", t);
        }
    }

    private void backup(List<AsyncBackup> ancestors, Throwable t) {
        backup(ancestors, t, false);
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.Completion+.success()) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.Completion+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.ReturnValueCompletion+.success(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.ReturnValueCompletion+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.NoErrorCompletion+.done()) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.NopeCompletion+.success()) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.NopeCompletion+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.core.cloudbus.CloudBusCallBack+.run(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.core.cloudbus.CloudBusListCallBack+.run(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.core.thread.ChainTask+.run(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t, true);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.rest.AsyncRESTCallback+.timeout(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.rest.AsyncRESTCallback+.success(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.rest.AsyncRESTCallback+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.workflow.FlowDoneHandler+.handle(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.workflow.FlowErrorHandler+.handle(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }
}

package org.zstack.core.aspect;

import org.springframework.beans.factory.annotation.Autowired;
import org.zstack.core.cloudbus.CloudBus;
import org.zstack.core.errorcode.ErrorFacade;
import org.zstack.header.core.workflow.FlowRollback;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.core.thread.SyncTaskChain;
import org.zstack.header.core.workflow.FlowTrigger;
import org.zstack.header.core.*;
import org.zstack.header.errorcode.ErrorCode;
import org.zstack.header.exception.CloudRuntimeException;
import org.zstack.header.message.Message;
import org.zstack.utils.DebugUtils;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;

import java.util.List;

public aspect AsyncBackupAspect {
    private final CLogger logger = Utils.getLogger(AsyncBackupAspect.class);

    @Autowired
    private CloudBus bus;
    @Autowired
    private ErrorFacade errf;

    private boolean isAsyncBackup(Object backup) {
        return backup instanceof Message || backup instanceof Completion || backup instanceof ReturnValueCompletion
                || backup instanceof FlowTrigger || backup instanceof SyncTaskChain
                || backup instanceof NoErrorCompletion || backup instanceof FlowRollback;
    }

    private void backup(List<AsyncBackup> ancestors, Throwable t, boolean flipThrowable) {
        if (ancestors == null || ancestors.isEmpty()) {
            // throw original exception out if no backup specified
            if (t instanceof RuntimeException) {
                throw (RuntimeException)t;
            } else if (t instanceof Error) {
                throw (Error)t;
            } else {
                throw new CloudRuntimeException(t);
            }
        }

        for (AsyncBackup ancestor : ancestors) {
            if (!isAsyncBackup(ancestor)) {
                String info = String.format("%s is not a known AsyncBackup. Someone added this type but forgot changing AsyncBackupAspect, please file bug", ancestor.getClass().getName());
                DebugUtils.dumpStackTrace(info);
                return;
            }

            ErrorCode err = t instanceof OperationFailureException ? ((OperationFailureException) t).getErrorCode() : errf.throwableToInternalError(t);
            if (ancestor instanceof Completion) {
                ((Completion)ancestor).fail(err);
            } else if (ancestor instanceof ReturnValueCompletion) {
                ((ReturnValueCompletion)ancestor).fail(err);
            } else if (ancestor instanceof FlowTrigger) {
                ((FlowTrigger) ancestor).fail(err);
            } else if (ancestor instanceof FlowRollback) {
                ((FlowRollback) ancestor).rollback();
            } else if (ancestor instanceof  SyncTaskChain) {
                ((SyncTaskChain) ancestor).next();
            } else if (ancestor instanceof NoErrorCompletion) {
                ((NoErrorCompletion) ancestor).done();
            } else if (ancestor instanceof Message) {
                bus.logExceptionWithMessageDump((Message) ancestor, t);
                bus.replyErrorByMessageType((Message) ancestor, err);
            } else {
                throw new CloudRuntimeException("should not be here");
            }
        }

        if (flipThrowable && t instanceof RuntimeException) {
            throw (RuntimeException)t;
        } else {
            logger.warn("unhandled exception happened", t);
        }
    }

    private void backup(List<AsyncBackup> ancestors, Throwable t) {
        backup(ancestors, t, false);
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.Completion+.success()) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.Completion+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.ReturnValueCompletion+.success(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.ReturnValueCompletion+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.NoErrorCompletion+.done()) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.NopeCompletion+.success()) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.NopeCompletion+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.core.cloudbus.CloudBusCallBack+.run(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.core.cloudbus.CloudBusListCallBack+.run(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.core.thread.ChainTask+.run(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t, true);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.rest.AsyncRESTCallback+.timeout(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.rest.AsyncRESTCallback+.success(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.rest.AsyncRESTCallback+.fail(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.workflow.FlowDoneHandler+.handle(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }

    void around(org.zstack.header.core.AbstractCompletion completion) : this(completion) && execution(void org.zstack.header.core.workflow.FlowErrorHandler+.handle(..)) {
        try {
            proceed(completion);
        } catch (Throwable  t) {
            backup(completion.getBackups(), t);
        }
    }
}


Removed legacy roo file

Removed legacy roo file


completed rename (pointcuts don't get updated during refactoring!)

package org.directmemory.profiling;

import java.text.DecimalFormat;

import org.directmemory.CacheEntry;
import org.javasimon.SimonManager;
import org.javasimon.Split;
import org.javasimon.Stopwatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public aspect Profiling {
	private static Logger logger=LoggerFactory.getLogger(Profiling.class);

	pointcut putPointcut(String key, Object object) :
		execution(CacheEntry org.directmemory.CacheManager.put(String, Object)) &&
		args(key, object);

	pointcut getPointcut(String key) :
		execution(Object org.directmemory.CacheManager.get(String)) &&
		args(key);

	pointcut removePointcut(String key) :
		execution(CacheEntry org.directmemory.CacheManager.remove(String)) &&
		args(key);

	pointcut disposeExpiredPointcut() :
		execution(void org.directmemory.CacheManager.disposeExpired());

	pointcut moveOffHeapPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.OffHeapStorage.moveIn(CacheEntry)) &&
		args(entry);

	pointcut moveToDiskPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.FileStorage.moveIn(CacheEntry)) &&
		args(entry);

	pointcut fromOffHeapPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.OffHeapStorage.moveToHeap(CacheEntry)) &&
		args(entry);

	pointcut fromDiskPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.FileStorage.moveToHeap(CacheEntry)) &&
		args(entry);

	pointcut disposeOffHeapOverflowPointcut() :
		execution(void org.directmemory.CacheManager.disposeOffHeapOverflow());

	pointcut moveInHeapPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.CacheManager.moveInHeap(CacheEntry)) && args(entry);

	pointcut displayTimingsPointcut() :
		execution(void org.directmemory.CacheManager.displayTimings());

	Object around(String key) : getPointcut(key) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.get");
		Split split = stopWatch.start();
		Object object = proceed(key);
		split.stop();
		return object;
	}

	CacheEntry around(String key, Object object): putPointcut(key, object) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.put");
		Split split = stopWatch.start();
		CacheEntry entry = proceed(key, object);
		split.stop();
		return entry;
    }

	Object around(String key) : removePointcut(key) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.remove");
		Split split = stopWatch.start();
		Object object = proceed(key);
		split.stop();
		return object;
	}

	Object around() : disposeExpiredPointcut() {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.disposeExpired");
		Split split = stopWatch.start();
		Object object = proceed();
		split.stop();
		return object;
	}

	boolean around(CacheEntry entry) : moveOffHeapPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveOffHeap");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	boolean around(CacheEntry entry) : moveToDiskPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveToDisk");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	boolean around(CacheEntry entry) : fromDiskPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveInHeapfromDisk");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	boolean around(CacheEntry entry) : fromOffHeapPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveInHeapfromOffHeap");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	private static String getTiming(Stopwatch sw) {
		Double average = ((double)sw.getTotal() / (double)sw.getCounter() /1000000);
		DecimalFormat df = new DecimalFormat("#.##");
		return
			(sw.getName() + " " + sw.getCounter() + " hits - average " + df.format(average) + " - max active:" + sw.getMaxActive() + " total time " + (sw.getTotal()/1000000))
			+ " - " + sw.toString();
	}

	void around() : displayTimingsPointcut() {
		logger.debug("check: " + thisJoinPoint.toShortString());
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.put")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.get")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.remove")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.disposeExpired")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveOffHeap")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveToDisk")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveInHeapfromOffHeap")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveInHeapfromDisk")));
		sb.append("\r\n}");
		logger.info(sb.toString());
	}
}

package org.directmemory.profiling;

import java.text.DecimalFormat;

import org.directmemory.CacheEntry;
import org.javasimon.SimonManager;
import org.javasimon.Split;
import org.javasimon.Stopwatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public aspect Profiling {
	private static Logger logger=LoggerFactory.getLogger(Profiling.class);

	pointcut putPointcut(String key, Object object) :
		execution(CacheEntry org.directmemory.CacheStore.put(String, Object)) &&
		args(key, object);

	pointcut getPointcut(String key) :
		execution(Object org.directmemory.CacheStore.get(String)) &&
		args(key);

	pointcut removePointcut(String key) :
		execution(CacheEntry org.directmemory.CacheStore.remove(String)) &&
		args(key);

	pointcut disposeExpiredPointcut() :
		execution(void org.directmemory.CacheStore.disposeExpired());

	pointcut moveOffHeapPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.OffHeapStorage.moveIn(CacheEntry)) &&
		args(entry);

	pointcut moveToDiskPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.FileStorage.moveIn(CacheEntry)) &&
		args(entry);

	pointcut fromOffHeapPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.OffHeapStorage.moveToHeap(CacheEntry)) &&
		args(entry);

	pointcut fromDiskPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.storage.FileStorage.moveToHeap(CacheEntry)) &&
		args(entry);

	pointcut disposeOffHeapOverflowPointcut() :
		execution(void org.directmemory.CacheStore.disposeOffHeapOverflow());

	pointcut moveInHeapPointcut(CacheEntry entry) :
		execution(boolean org.directmemory.CacheStore.moveInHeap(CacheEntry)) && args(entry);

	pointcut displayTimingsPointcut() :
		execution(void org.directmemory.CacheStore.displayTimings());

	Object around(String key) : getPointcut(key) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.get");
		Split split = stopWatch.start();
		Object object = proceed(key);
		split.stop();
		return object;
	}

	CacheEntry around(String key, Object object): putPointcut(key, object) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.put");
		Split split = stopWatch.start();
		CacheEntry entry = proceed(key, object);
		split.stop();
		return entry;
    }

	Object around(String key) : removePointcut(key) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.remove");
		Split split = stopWatch.start();
		Object object = proceed(key);
		split.stop();
		return object;
	}

	Object around() : disposeExpiredPointcut() {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.disposeExpired");
		Split split = stopWatch.start();
		Object object = proceed();
		split.stop();
		return object;
	}

	boolean around(CacheEntry entry) : moveOffHeapPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveOffHeap");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	boolean around(CacheEntry entry) : moveToDiskPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveToDisk");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	boolean around(CacheEntry entry) : fromDiskPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveInHeapfromDisk");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	boolean around(CacheEntry entry) : fromOffHeapPointcut(entry) {
		logger.debug("check: " + thisJoinPoint.toShortString());
        Stopwatch stopWatch = SimonManager.getStopwatch("cache.detail.moveInHeapfromOffHeap");
		Split split = stopWatch.start();
		boolean retVal = proceed(entry);
		split.stop();
		return retVal;
	}

	private static String getTiming(Stopwatch sw) {
		Double average = ((double)sw.getTotal() / (double)sw.getCounter() /1000000);
		DecimalFormat df = new DecimalFormat("#.##");
		return
			(sw.getName() + " " + sw.getCounter() + " hits - average " + df.format(average) + " - max active:" + sw.getMaxActive() + " total time " + (sw.getTotal()/1000000))
			+ " - " + sw.toString();
	}

	void around() : displayTimingsPointcut() {
		logger.debug("check: " + thisJoinPoint.toShortString());
		StringBuffer sb = new StringBuffer();
		sb.append("{");
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.put")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.get")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.remove")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.disposeExpired")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveOffHeap")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveToDisk")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveInHeapfromOffHeap")));
		sb.append("\r\n   ");
		sb.append(getTiming(SimonManager.getStopwatch("cache.detail.moveInHeapfromDisk")));
		sb.append("\r\n}");
		logger.info(sb.toString());
	}
}


Add ActorContext interposition

Add ActorContext interposition

package sample;

import static java.lang.Thread.sleep;

import akka.dispatch.verification.Instrumenter;

import akka.actor.ActorRef;
import akka.actor.Actor;
import akka.actor.Props;
import akka.actor.ActorCell;
import akka.actor.ActorSystem;
import akka.actor.ActorContext;

import akka.pattern.AskSupport;

import akka.dispatch.Envelope;
import akka.dispatch.MessageQueue;
import akka.dispatch.MessageDispatcher;

import scala.concurrent.impl.CallbackRunnable;

privileged public aspect WeaveActor {

  Instrumenter inst = Instrumenter.apply();

  pointcut enqueueOperation(MessageQueue me, ActorRef receiver, Envelope handle):
  execution(public * akka.dispatch.MessageQueue.enqueue(ActorRef, Envelope)) &&
  args(receiver, handle) && this(me);

  Object around(MessageQueue me, ActorRef receiver, Envelope handle):
  enqueueOperation(me, receiver, handle) {
	return proceed(me, receiver, handle);
  }

  before(ActorCell me, Object msg):
  execution(* akka.actor.ActorCell.receiveMessage(Object)) &&
  args(msg, ..) && this(me) {
	inst.beforeMessageReceive(me);
  }

  after(ActorCell me, Object msg):
  execution(* akka.actor.ActorCell.receiveMessage(Object)) &&
  args(msg, ..) && this(me) {
	inst.afterMessageReceive(me);
  }

  pointcut dispatchOperation(MessageDispatcher me, ActorCell receiver, Envelope handle):
  execution(* akka.dispatch.MessageDispatcher.dispatch(..)) &&
  args(receiver, handle, ..) && this(me);

  Object around(MessageDispatcher me, ActorCell receiver, Envelope handle):
  dispatchOperation(me, receiver, handle) {
  	if (inst.aroundDispatch(me, receiver, handle))
   		return proceed(me, receiver, handle);
   	else
   		return null;
  }

  after(ActorSystem me, Props props) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorSystem.actorOf(Props)) &&
  args(props) && this(me) {
  	inst.new_actor(me, props, actor);
  }

  after(ActorSystem me, Props props, String name) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorSystem.actorOf(Props, String)) &&
  args(props, name) && this(me) {
  	inst.new_actor(me, props, name, actor);
  }

  after(ActorContext me, Props props) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorContext.actorOf(Props)) &&
  args(props) && this(me) {
  	inst.new_actor(me.system(), props, actor);
  }

  after(ActorContext me, Props props, String name) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorContext.actorOf(Props, String)) &&
  args(props, name) && this(me) {
  	inst.new_actor(me.system(), props, name, actor);
  }

}

package sample;

import static java.lang.Thread.sleep;

import akka.dispatch.verification.Instrumenter;

import akka.actor.ActorRef;
import akka.actor.Actor;
import akka.actor.Props;
import akka.actor.ActorCell;
import akka.actor.ActorSystem;
import akka.actor.ActorContext;

import akka.pattern.AskSupport;

import akka.dispatch.Envelope;
import akka.dispatch.MessageQueue;
import akka.dispatch.MessageDispatcher;

import scala.concurrent.impl.CallbackRunnable;

privileged public aspect WeaveActor {

  Instrumenter inst = Instrumenter.apply();

  pointcut enqueueOperation(MessageQueue me, ActorRef receiver, Envelope handle):
  execution(public * akka.dispatch.MessageQueue.enqueue(ActorRef, Envelope)) &&
  args(receiver, handle) && this(me);

  Object around(MessageQueue me, ActorRef receiver, Envelope handle):
  enqueueOperation(me, receiver, handle) {
	return proceed(me, receiver, handle);
  }

  before(ActorCell me, Object msg):
  execution(* akka.actor.ActorCell.receiveMessage(Object)) &&
  args(msg, ..) && this(me) {
	inst.beforeMessageReceive(me);
  }

  after(ActorCell me, Object msg):
  execution(* akka.actor.ActorCell.receiveMessage(Object)) &&
  args(msg, ..) && this(me) {
	inst.afterMessageReceive(me);
  }

  pointcut dispatchOperation(MessageDispatcher me, ActorCell receiver, Envelope handle):
  execution(* akka.dispatch.MessageDispatcher.dispatch(..)) &&
  args(receiver, handle, ..) && this(me);

  Object around(MessageDispatcher me, ActorCell receiver, Envelope handle):
  dispatchOperation(me, receiver, handle) {
  	if (inst.aroundDispatch(me, receiver, handle))
   		return proceed(me, receiver, handle);
   	else
   		return null;
  }

  after(ActorSystem me, Props props) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorSystem.actorOf(Props)) &&
  args(props) && this(me) {
  	inst.new_actor(me, props, actor);
  }

  after(ActorSystem me, Props props, String name) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorSystem.actorOf(Props, String)) &&
  args(props, name) && this(me) {
  	inst.new_actor(me, props, name, actor);
  }

  after(ActorContext me, Props props) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorSystem.actorOf(Props)) &&
  args(props) && this(me) {
  	inst.new_actor(me.system(), props, actor);
  }

  after(ActorContext me, Props props, String name) returning(ActorRef actor):
  execution(ActorRef akka.actor.ActorSystem.actorOf(Props, String)) &&
  args(props, name) && this(me) {
  	inst.new_actor(me.system(), props, name, actor);
  }

}


validation: style fix

validation: style fix

Signed-off-by: Ketoth Xupack <2ff7bd69a79a23dbf64ebd5846a612566f93fbf7@gmail.com>

package org.nohope.validation;

import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import static org.nohope.reflection.IntrospectionUtils.instanceOf;
import static org.nohope.reflection.IntrospectionUtils.newInstance;
import static org.nohope.validation.MethodsCache.CachedMethod;

/**
 * @author ketoth xupack
 * @since 9/26/13 11:51 AM
 */
public privileged aspect ValidatingAspect {
    private static final MethodsCache methodsCache = new MethodsCache();

    pointcut thisAdvice(): adviceexecution() && within(ValidatingAspect);

    /**
     * matches all constructors with at last one parameter
     * marked with @Nonnull annotation
     */
    pointcut constructorParameters():
            execution(new(.., @org.nohope.validation.Validate (*), ..))
            && !cflow(thisAdvice())
            ;

    /**
     * searches for all methods have at last one parameter
     * annotated with @Nonnull
     */
    pointcut methodParameters():
            execution(* *.*(.., @org.nohope.validation.Validate (*), ..))
            && !cflow(thisAdvice())
            ;

    /**
     * searches for all methods which returns any reference type and
     * annotated with @Nonnull
     */
    static pointcut returnValue():
            execution(@org.nohope.validation.Validate (Object+) *.*(..))
            && !cflow(thisAdvice())
            ;

    private ValidatingAspect() {
    }

    @SuppressWarnings("unchecked")
    private static void validate(final Class<? extends IValidator<?>> clazz,
                                 final Object target) throws ValidatingTypeMismatch,
                                                             ValidatorInitializationException,
                                                             ValidationException {
        if (clazz != null) {
            try {
                final IValidator<?> validator = newInstance(clazz);
                final Class<?> type = validator.getType();
                if (target != null && !instanceOf(target, type)) {
                    throw new ValidatingTypeMismatch();
                }

                // now we are sure that types are compatible
                ((IValidator<Object>) validator).validate(target);
            } catch (NoSuchMethodException
                    | InvocationTargetException
                    | IllegalAccessException
                    | InstantiationException e) {
                throw new ValidatorInitializationException(e);
            }
        }
    }

    @SuppressAjWarnings
    after() returning(final Object ret): returnValue() {
        final MethodSignature sig = (MethodSignature) thisJoinPoint.getStaticPart().getSignature();
        final Method method = sig.getMethod();
        final Validate annotation = method.getAnnotation(Validate.class);
        final CachedMethod cache = methodsCache.get(method);

        final Class<? extends IValidator<?>> clazz = annotation.value();
        try {
            validate(clazz, ret);
        } catch (ValidatingTypeMismatch e) {
            throw new IllegalArgumentException(
                    "Return value of method @Validate("
                    + clazz.getCanonicalName()
                    + ") "
                    + cache
                    + " cannot be applied to "
                    + ret.getClass().getCanonicalName());
        } catch (ValidationException e) {
            throw new IllegalArgumentException(
                    "Validation failed for return value of method @Validate("
                    + clazz.getCanonicalName()
                    + ") "
                    + cache, e);
        } catch (ValidatorInitializationException e) {
            throw new IllegalStateException("Unable to validate return value of @Validate("
                                            + clazz.getCanonicalName()
                                            + ")", e);
        }
    }

    @SuppressAjWarnings
    before(): methodParameters() || constructorParameters() {
        final Signature signature = thisJoinPoint.getStaticPart().getSignature();
        final CachedMethod cache;

        if (signature instanceof MethodSignature) {
            final MethodSignature sig = (MethodSignature) thisJoinPoint.getStaticPart().getSignature();
            final Method method = sig.getMethod();
            cache = methodsCache.get(method);
        } else if (signature instanceof ConstructorSignature) {
            final ConstructorSignature sig = (ConstructorSignature) signature;
            final Constructor method = sig.getConstructor();
            cache = methodsCache.get(method);
        } else {
            throw new IllegalStateException("Illegal advice for " + signature.getClass());
        }

        cache.observeParameters(thisJoinPoint.getArgs(), Validate.class, new MethodsCache.IObserver<Validate>() {
            @Override
            public void observe(final Validate annotation, final Object arg, final int index) {
                final Class<? extends IValidator<?>> clazz = annotation.value();
                try {
                    validate(clazz, arg);
                } catch (ValidatingTypeMismatch e) {
                    throw new IllegalArgumentException(
                            "Argument "
                            + index
                            + " for @Validate("
                            + clazz.getCanonicalName()
                            + ") parameter of "
                            + cache
                            + " cannot be applied to "
                            + arg.getClass().getCanonicalName(), e);
                } catch (ValidatorInitializationException e) {
                    throw new IllegalStateException(
                            "Unable to validate argument "
                            + index
                            + " for @Validate("
                            + clazz.getCanonicalName()
                            + ") parameter of "
                            + cache, e);
                } catch (ValidationException e) {
                    throw new IllegalArgumentException(
                            "Validation failed for argument "
                            + index
                            + " of @Validate("
                            + clazz.getCanonicalName()
                            + ") "
                            + cache, e);
                }
            }
        });
    }
}

package org.nohope.validation;

import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.ConstructorSignature;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import static org.nohope.reflection.IntrospectionUtils.instanceOf;
import static org.nohope.reflection.IntrospectionUtils.newInstance;
import static org.nohope.validation.MethodsCache.CachedMethod;

/**
 * @author ketoth xupack
 * @since 9/26/13 11:51 AM
 */
public privileged aspect ValidatingAspect {
    private static final MethodsCache methodsCache = new MethodsCache();

    pointcut thisAdvice(): adviceexecution() && within(ValidatingAspect);

    /**
     * matches all constructors with at last one parameter
     * marked with @Nonnull annotation
     */
    pointcut constructorParameters():
            execution(new(.., @org.nohope.validation.Validate (*), ..))
            && !cflow(thisAdvice())
            ;

    /**
     * searches for all methods have at last one parameter
     * annotated with @Nonnull
     */
    pointcut methodParameters():
            execution(* *.*(.., @org.nohope.validation.Validate (*), ..))
            && !cflow(thisAdvice())
            ;

    /**
     * searches for all methods which returns any reference type and
     * annotated with @Nonnull
     */
    static pointcut returnValue():
            execution(@org.nohope.validation.Validate (Object+) *.*(..))
            && !cflow(thisAdvice())
            ;

    private ValidatingAspect() {
    }

    private static void validate(final Class<? extends IValidator<?>> clazz,
                                 final Object target) throws ValidatingTypeMismatch,
                                                             ValidatorInitializationException,
                                                             ValidationException {
        if (clazz != null) {
            try {
                final IValidator<?> validator = newInstance(clazz);
                final Class<?> type = validator.getType();
                if (target != null && !instanceOf(target, type)) {
                    throw new ValidatingTypeMismatch();
                }

                // now we are sure that types are compatible
                //noinspection unchecked
                ((IValidator<Object>) validator).validate(target);
            } catch (NoSuchMethodException
                    | InvocationTargetException
                    | IllegalAccessException
                    | InstantiationException e) {
                throw new ValidatorInitializationException(e);
            }
        }
    }

    @SuppressAjWarnings
    after() returning(final Object ret): returnValue() {
        final MethodSignature sig = (MethodSignature) thisJoinPoint.getStaticPart().getSignature();
        final Method method = sig.getMethod();
        final Validate annotation = method.getAnnotation(Validate.class);
        final CachedMethod cache = methodsCache.get(method);

        final Class<? extends IValidator<?>> clazz = annotation.value();
        try {
            validate(clazz, ret);
        } catch (ValidatingTypeMismatch e) {
            throw new IllegalArgumentException(
                    "Return value of method @Validate("
                    + clazz.getCanonicalName()
                    + ") "
                    + cache
                    + " cannot be applied to "
                    + ret.getClass().getCanonicalName());
        } catch (ValidationException e) {
            throw new IllegalArgumentException(
                    "Validation failed for return value of method @Validate("
                    + clazz.getCanonicalName()
                    + ") "
                    + cache, e);
        } catch (ValidatorInitializationException e) {
            throw new IllegalStateException("Unable to validate return value of @Validate("
                                            + clazz.getCanonicalName()
                                            + ")", e);
        }
    }

    @SuppressAjWarnings
    before(): methodParameters() || constructorParameters() {
        final Signature signature = thisJoinPoint.getStaticPart().getSignature();
        final CachedMethod cache;

        if (signature instanceof MethodSignature) {
            final MethodSignature sig = (MethodSignature) thisJoinPoint.getStaticPart().getSignature();
            final Method method = sig.getMethod();
            cache = methodsCache.get(method);
        } else if (signature instanceof ConstructorSignature) {
            final ConstructorSignature sig = (ConstructorSignature) signature;
            final Constructor method = sig.getConstructor();
            cache = methodsCache.get(method);
        } else {
            throw new IllegalStateException("Illegal advice for " + signature.getClass());
        }

        cache.observeParameters(thisJoinPoint.getArgs(), Validate.class, new MethodsCache.IObserver<Validate>() {
            @Override
            public void observe(final Validate annotation, final Object arg, final int index) {
                final Class<? extends IValidator<?>> clazz = annotation.value();
                try {
                    validate(clazz, arg);
                } catch (ValidatingTypeMismatch e) {
                    throw new IllegalArgumentException(
                            "Argument "
                            + index
                            + " for @Validate("
                            + clazz.getCanonicalName()
                            + ") parameter of "
                            + cache
                            + " cannot be applied to "
                            + arg.getClass().getCanonicalName(), e);
                } catch (ValidatorInitializationException e) {
                    throw new IllegalStateException(
                            "Unable to validate argument "
                            + index
                            + " for @Validate("
                            + clazz.getCanonicalName()
                            + ") parameter of "
                            + cache, e);
                } catch (ValidationException e) {
                    throw new IllegalArgumentException(
                            "Validation failed for argument "
                            + index
                            + " of @Validate("
                            + clazz.getCanonicalName()
                            + ") "
                            + cache, e);
                }
            }
        });
    }
}