type patterns fixed

type patterns fixed

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Igor Konev
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.jvnet.zephyr.activeobject.aspect;

import org.jvnet.zephyr.activeobject.annotation.Active;
import org.jvnet.zephyr.activeobject.annotation.Exclude;
import org.jvnet.zephyr.activeobject.annotation.Include;
import org.jvnet.zephyr.activeobject.annotation.Oneway;
import org.jvnet.zephyr.activeobject.disposer.Disposer;
import org.jvnet.zephyr.activeobject.mailbox.Mailbox;
import org.jvnet.zephyr.activeobject.mailbox.MailboxFactory;
import org.jvnet.zephyr.activeobject.mailbox.ReflectiveMailboxFactory;
import org.jvnet.zephyr.activeobject.support.ActiveObjectThread;
import org.jvnet.zephyr.activeobject.util.concurrent.RunnableFutureTask;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public final aspect ActiveObjectAspect pertypewithin(ActiveObject+) {

    declare error: execution(@Include @Exclude * *.*(..)): "@Include and @Exclude on the same method are not allowed";
    declare error: execution(@Include static * *.*(..)): "@Include on a static method is not allowed";
    declare error: execution(@Exclude static * *.*(..)): "@Exclude on a static method is not allowed";
    declare error: execution(@Oneway static * *.*(..)): "@Oneway on a static method is not allowed";
    declare error: execution(@Oneway !void *.*(..)): "@Oneway requires void return type";
    declare error: execution(@Oneway * *.*(..) throws Throwable+ && !(Error+ || RuntimeException+)):
            "@Oneway allows throwing unchecked exceptions only";
    declare warning: execution(@Include public * *.*(..)): "@Include on a public method is redundand";
    declare warning: execution(@Exclude !public * *.*(..)): "@Exclude on a non-public method is redundand";
    declare parents: @Active * implements ActiveObject;

    private static final Disposer disposer = new Disposer();
    private Class<?> declaringType;
    private MailboxFactory mailboxFactory;
    private long timeout;
    private ActiveObjectThread ActiveObject.thread;

    after() returning: staticinitialization(ActiveObject+) {
        declaringType = thisJoinPointStaticPart.getSignature().getDeclaringType();
        Active annotation = declaringType.getAnnotation(Active.class);

        Class<?> cls = annotation.mailbox();
        Constructor<?> constructor;
        try {
            constructor = (Constructor<?>) cls.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        if (Mailbox.class.isAssignableFrom(cls)) {
            mailboxFactory = new ReflectiveMailboxFactory((Constructor<? extends Mailbox>) constructor);
        } else {
            try {
                mailboxFactory = (MailboxFactory) constructor.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof Error) {
                    throw (Error) cause;
                } else if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else {
                    throw new RuntimeException(cause);
                }
            }
        }

        timeout = annotation.timeout();
        if (timeout < 0) {
            throw new RuntimeException("timeout < 0");
        }
    }

    after(ActiveObject obj) returning: initialization((ActiveObject+ && !ActiveObject).new(..)) && this(obj) {
        if (obj.getClass() == declaringType) {
            ActiveObjectThread thread = new ActiveObjectThread(mailboxFactory.create());
            thread.setName(obj.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(obj)));
            thread.setDaemon(true);
            disposer.register(obj, thread);
            obj.thread = thread;
            thread.start();
        }
    }

    Object around(final ActiveObject obj): (execution(!@Exclude !@Oneway public * ActiveObject+.*(..))
            || execution(@Include !@Oneway !public * ActiveObject+.*(..))) && this(obj) {
        ActiveObjectThread thread = obj.thread;
        if (Thread.currentThread() == thread) {
            return proceed(obj);
        }

        RunnableFuture<?> task = new RunnableFutureTask<Object>() {
            @Override
            public void run() {
                Object result;
                try {
                    result = proceed(obj);
                } catch (Throwable e) {
                    setException(e);
                    return;
                }
                set(result);
            }
        };

        boolean interrupted = false;
        try {
            while (true) {
                try {
                    thread.getMailbox().enqueue(task);
                    break;
                } catch (InterruptedException ignored) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }

        try {
            interrupted = false;
            try {
                while (true) {
                    try {
                        if (timeout > 0) {
                            try {
                                return task.get(timeout, TimeUnit.MILLISECONDS);
                            } catch (TimeoutException e) {
                                throw new RuntimeException(e);
                            }
                        } else {
                            return task.get();
                        }
                    } catch (InterruptedException ignored) {
                        interrupted = true;
                    }
                }
            } finally {
                if (interrupted) {
                    Thread.currentThread().interrupt();
                }
            }
        } catch (ExecutionException e) {
            throw ActiveObjectAspect.<RuntimeException>throwException(e.getCause());
        }
    }

    @SuppressWarnings("unchecked")
    private static <E extends Throwable> E throwException(Throwable exception) throws E {
        throw (E) exception;
    }

    void around(final ActiveObject obj): (execution(!@Exclude @Oneway public void ActiveObject+.*(..))
            || execution(@Include @Oneway !public void ActiveObject+.*(..))) && this(obj) {
        ActiveObjectThread thread = obj.thread;
        if (Thread.currentThread() == thread) {
            proceed(obj);
            return;
        }

        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    proceed(obj);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        };

        boolean interrupted = false;
        try {
            while (true) {
                try {
                    thread.getMailbox().enqueue(task);
                    break;
                } catch (InterruptedException ignored) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private interface ActiveObject {
    }
}

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Igor Konev
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package org.jvnet.zephyr.activeobject.aspect;

import org.jvnet.zephyr.activeobject.annotation.Active;
import org.jvnet.zephyr.activeobject.annotation.Exclude;
import org.jvnet.zephyr.activeobject.annotation.Include;
import org.jvnet.zephyr.activeobject.annotation.Oneway;
import org.jvnet.zephyr.activeobject.disposer.Disposer;
import org.jvnet.zephyr.activeobject.mailbox.Mailbox;
import org.jvnet.zephyr.activeobject.mailbox.MailboxFactory;
import org.jvnet.zephyr.activeobject.mailbox.ReflectiveMailboxFactory;
import org.jvnet.zephyr.activeobject.support.ActiveObjectThread;
import org.jvnet.zephyr.activeobject.util.concurrent.RunnableFutureTask;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public final aspect ActiveObjectAspect pertypewithin(ActiveObject+) {

    declare error: execution(@Include @Exclude * *.*(..)): "@Include and @Exclude on the same method are not allowed";
    declare error: execution(@Include static * *.*(..)): "@Include on a static method is not allowed";
    declare error: execution(@Exclude static * *.*(..)): "@Exclude on a static method is not allowed";
    declare error: execution(@Oneway static * *.*(..)): "@Oneway on a static method is not allowed";
    declare error: execution(@Oneway !void *.*(..)): "@Oneway requires void return type";
    declare error: execution(@Oneway * *.*(..) throws Throwable+ && !(Error+ || RuntimeException+)):
            "@Oneway allows throwing unchecked exceptions only";
    declare warning: execution(@Include public * *.*(..)): "@Include on a public method is redundand";
    declare warning: execution(@Exclude !public * *.*(..)): "@Exclude on a non-public method is redundand";
    declare parents: @Active * implements ActiveObject;

    private static final Disposer disposer = new Disposer();
    private Class<?> declaringType;
    private MailboxFactory mailboxFactory;
    private long timeout;
    private ActiveObjectThread ActiveObject.thread;

    after() returning: staticinitialization(*) {
        declaringType = thisJoinPointStaticPart.getSignature().getDeclaringType();
        Active annotation = declaringType.getAnnotation(Active.class);

        Class<?> cls = annotation.mailbox();
        Constructor<?> constructor;
        try {
            constructor = (Constructor<?>) cls.getConstructor();
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
        if (Mailbox.class.isAssignableFrom(cls)) {
            mailboxFactory = new ReflectiveMailboxFactory((Constructor<? extends Mailbox>) constructor);
        } else {
            try {
                mailboxFactory = (MailboxFactory) constructor.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                Throwable cause = e.getCause();
                if (cause instanceof Error) {
                    throw (Error) cause;
                } else if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else {
                    throw new RuntimeException(cause);
                }
            }
        }

        timeout = annotation.timeout();
        if (timeout < 0) {
            throw new RuntimeException("timeout < 0");
        }
    }

    after(ActiveObject obj) returning: initialization((!ActiveObject).new(..)) && this(obj) {
        if (obj.getClass() == declaringType) {
            ActiveObjectThread thread = new ActiveObjectThread(mailboxFactory.create());
            thread.setName(obj.getClass().getName() + '@' + Integer.toHexString(System.identityHashCode(obj)));
            thread.setDaemon(true);
            disposer.register(obj, thread);
            obj.thread = thread;
            thread.start();
        }
    }

    Object around(final ActiveObject obj): (execution(!@Exclude !@Oneway public * *(..))
            || execution(@Include !@Oneway !public * *(..))) && this(obj) {
        ActiveObjectThread thread = obj.thread;
        if (Thread.currentThread() == thread) {
            return proceed(obj);
        }

        RunnableFuture<?> task = new RunnableFutureTask<Object>() {
            @Override
            public void run() {
                Object result;
                try {
                    result = proceed(obj);
                } catch (Throwable e) {
                    setException(e);
                    return;
                }
                set(result);
            }
        };

        boolean interrupted = false;
        try {
            while (true) {
                try {
                    thread.getMailbox().enqueue(task);
                    break;
                } catch (InterruptedException ignored) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }

        try {
            interrupted = false;
            try {
                while (true) {
                    try {
                        if (timeout > 0) {
                            try {
                                return task.get(timeout, TimeUnit.MILLISECONDS);
                            } catch (TimeoutException e) {
                                throw new RuntimeException(e);
                            }
                        } else {
                            return task.get();
                        }
                    } catch (InterruptedException ignored) {
                        interrupted = true;
                    }
                }
            } finally {
                if (interrupted) {
                    Thread.currentThread().interrupt();
                }
            }
        } catch (ExecutionException e) {
            throw ActiveObjectAspect.<RuntimeException>throwException(e.getCause());
        }
    }

    @SuppressWarnings("unchecked")
    private static <E extends Throwable> E throwException(Throwable exception) throws E {
        throw (E) exception;
    }

    void around(final ActiveObject obj): (execution(!@Exclude @Oneway public void *(..))
            || execution(@Include @Oneway !public void *(..))) && this(obj) {
        ActiveObjectThread thread = obj.thread;
        if (Thread.currentThread() == thread) {
            proceed(obj);
            return;
        }

        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    proceed(obj);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        };

        boolean interrupted = false;
        try {
            while (true) {
                try {
                    thread.getMailbox().enqueue(task);
                    break;
                } catch (InterruptedException ignored) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private interface ActiveObject {
    }
}


comments for PDFGraph feature

comments for PDFGraph feature

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFMergerUtility;

import de.erichseifert.gral.io.plots.DrawableWriter;
import de.erichseifert.gral.io.plots.DrawableWriterFactory;

public privileged aspect GraphExport {

    /**
     * Add graph to PDF
     */
    after(PDDocument document) returning() throws IOException
    : execution (* PDFReportListener.drawTable(PDDocument))
    && args(document) {

        // create bytes array from graph
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DrawableWriter wr = DrawableWriterFactory.getInstance().get("application/pdf");
        wr.write(Graph.createPlot(), baos, 800, 600);
        baos.flush();
        byte[] bytes = baos.toByteArray();
        baos.close();

        PDDocument picture = PDDocument.load(new ByteArrayInputStream(bytes));
        new PDFMergerUtility().appendDocument(document, picture);
        picture.close();
    }
}

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFMergerUtility;

import de.erichseifert.gral.io.plots.DrawableWriter;
import de.erichseifert.gral.io.plots.DrawableWriterFactory;

public privileged aspect GraphExport {

    after(PDDocument document) returning() throws IOException
    : execution (* PDFReportListener.drawTable(PDDocument))
    && args(document) {

        // create bytes array from graph
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DrawableWriter wr = DrawableWriterFactory.getInstance().get("application/pdf");
        wr.write(Graph.createPlot(), baos, 800, 600);
        baos.flush();
        byte[] bytes = baos.toByteArray();
        baos.close();

        PDDocument picture = PDDocument.load(new ByteArrayInputStream(bytes));
        new PDFMergerUtility().appendDocument(document, picture);
        picture.close();
    }
}


Updated the around pointcuts.

Updated the around pointcuts.

The important issue is to ensure that the lock/unlock methods and the
monitor steps are performed atomically.

This still might not be the best approach - it seems artifical as we
lock an object whilst locking it (tryLock). Perhaps it would be better
protected by the monitor object, but if tryLock is false this introduces
unnecessary contention.

package benchmark.competition.java.jUnitRV_MMT.monitoring;

import java.util.concurrent.locks.Lock;

import monitoring.impl.MonitorFactory;
import monitoring.intf.Monitor;
import properties.Property;
import properties.competition.JavaRV_mmt;
import structure.impl.other.Verdict;
import structure.intf.QEA;
import benchmark.competition.java.jUnitRV_MMT.ExampleLocking;

public aspect JUnitRV_MMTThreeAspect {

	private final Monitor monitor;

	private final int RUN = 1;
	private final int LOCK_TRUE = 2;
	private final int UNLOCK = 3;
	private final int ACTION = 4;

	public JUnitRV_MMTThreeAspect() {
		QEA qea = new JavaRV_mmt().make(Property.JAVARV_MMT_THREE);
		monitor = MonitorFactory.create(qea);
	}

	pointcut run(ExampleLocking thread) : execution(void ExampleLocking.run())
		&& target(thread);

	pointcut action(ExampleLocking thread) : call(void ExampleLocking.action())
		&& target(thread);

	before(ExampleLocking thread) : run(thread) {
		Verdict verdict = null;
		synchronized (monitor) {
			verdict = monitor.step(RUN, thread);
		}
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JUnitRV (MMT) 3. [thread="
							+ thread
							+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
		}
	};

	boolean around(Lock lockObj, ExampleLocking thread) :
			call(boolean Lock.tryLock())
			&& cflow(call(boolean ExampleLocking.lock())) && target(lockObj)
			&& this(thread) {

		boolean result = false;
		// We perform the lock and the monitor step as an atomic action
		// i.e. whilst holding the lockObj, so that we cannot be interrupted
		synchronized (lockObj) {
			result = proceed(lockObj, thread);
			if (result) {
				Verdict verdict = null;
				// Ordering between lockObj and monitor important
				synchronized (monitor) {
					verdict = monitor.step(LOCK_TRUE, thread);
				}
				if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
					System.err
							.println("Violation in JUnitRV (MMT) 3. [thread="
									+ thread
									+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
				}

			}
		}
		return result;
	};

	void around(Lock lockObj, ExampleLocking thread) :
		call(void Lock.unlock()) && cflow(call(void ExampleLocking.unlock()))
		&& target(lockObj) && this(thread) {

		// We perform the unlock and the monitor step as an atomic action
		// i.e. whilst holding the lockObj, so that we cannot be interrupted
		Verdict verdict = null;
		synchronized (lockObj) {
			proceed(lockObj, thread);
			// Ordering between lockObj and monitor important
			synchronized (monitor) {
				verdict = monitor.step(LOCK_TRUE, thread);
			}
		}
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JUnitRV (MMT) 3. [thread="
							+ thread
							+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
		}
	};

	before(ExampleLocking thread) : action(thread) {
		Verdict verdict = null;
		synchronized (monitor) {
			verdict = monitor.step(ACTION, thread);
		}
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JUnitRV (MMT) 3. [id="
							+ thread
							+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
		}
	};

}

package benchmark.competition.java.jUnitRV_MMT.monitoring;

import java.util.concurrent.locks.Lock;

import monitoring.impl.MonitorFactory;
import monitoring.intf.Monitor;
import properties.Property;
import properties.competition.JavaRV_mmt;
import structure.impl.other.Verdict;
import structure.intf.QEA;
import benchmark.competition.java.jUnitRV_MMT.ExampleLocking;

public aspect JUnitRV_MMTThreeAspect {

	private final Monitor monitor;

	private final int RUN = 1;
	private final int LOCK_TRUE = 2;
	private final int UNLOCK = 3;
	private final int ACTION = 4;

	public JUnitRV_MMTThreeAspect() {
		QEA qea = new JavaRV_mmt().make(Property.JAVARV_MMT_THREE);
		monitor = MonitorFactory.create(qea);
	}

	pointcut run(ExampleLocking thread) : execution(void ExampleLocking.run())
		&& target(thread);

	pointcut action(ExampleLocking thread) : call(void ExampleLocking.action())
		&& target(thread);

	before(ExampleLocking thread) : run(thread) {
		Verdict verdict = null;
		synchronized (monitor) {
			verdict = monitor.step(RUN, thread);
		}
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JUnitRV (MMT) 3. [thread="
							+ thread
							+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
		}
	};

	boolean around(Lock lockObj, ExampleLocking thread) :
			call(boolean Lock.tryLock())
			&& cflow(call(boolean ExampleLocking.lock())) && target(lockObj)
			&& this(thread) {

		boolean result = false;
		synchronized (lockObj) {
			result = proceed(lockObj, thread); // TODO Not sure if this is right
		}
		if (result) {
			Verdict verdict = null;
			synchronized (monitor) {
				verdict = monitor.step(LOCK_TRUE, thread);
			}
			if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
				System.err
						.println("Violation in JUnitRV (MMT) 3. [thread="
								+ thread
								+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
			}

		}
		return result;
	};

	void around(Lock lockObj, ExampleLocking thread) :
		call(void Lock.unlock()) && cflow(call(void ExampleLocking.unlock()))
		&& target(lockObj) && this(thread) {

		synchronized (lockObj) {
			proceed(lockObj, thread); // TODO Not sure if this is right
		}
		Verdict verdict = null;
		synchronized (monitor) {
			verdict = monitor.step(LOCK_TRUE, thread);
		}
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JUnitRV (MMT) 3. [thread="
							+ thread
							+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
		}
	};

	before(ExampleLocking thread) : action(thread) {
		Verdict verdict = null;
		synchronized (monitor) {
			verdict = monitor.step(ACTION, thread);
		}
		if (verdict == Verdict.FAILURE || verdict == Verdict.WEAK_FAILURE) {
			System.err
					.println("Violation in JUnitRV (MMT) 3. [id="
							+ thread
							+ "]. - A thread has to call lock (returning true) to acquire the lock before it may call action - A call to lock only returns true, if no thread is currently holding the lock.");
		}
	};

}


BuildManagers weren't deleting invalidated classfiles; dependency tracker was only recording the dependency of Foo$.class on the source of object Foo ... Foo.class is now also recorded; the Eclipse Java builder could copy modified Scala sources to the output folder during incremental builds. Fixes #2428.

git-svn-id: f4ecfe233223879a4a16cd7937f11b5152963d8e@18920 5e8d7ff9-d8ef-0310-90f0-a4852d11357a

/*
 * Copyright 2005-2009 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.contribution.weaving.jdt.builderoptions;

import org.eclipse.core.resources.IResource;

import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.internal.core.builder.BatchImageBuilder;
import org.eclipse.jdt.internal.core.builder.JavaBuilder;
//import org.eclipse.jdt.internal.core.builder.ClasspathMultiDirectory;
import org.eclipse.jdt.internal.core.util.Util;

@SuppressWarnings("restriction")
public privileged aspect ScalaJavaBuilderAspect {
  pointcut build() :
    execution(IProject[] ScalaJavaBuilder.build(int, Map, IProgressMonitor) throws CoreException);

  pointcut cleanOutputFolders(boolean copyBack) :
    args(copyBack) &&
    execution(void BatchImageBuilder.cleanOutputFolders(boolean) throws CoreException);

  pointcut isJavaLikeFileName(String fileName) :
    args(fileName) &&
    execution(boolean Util.isJavaLikeFileName(String));

  pointcut filterExtraResource(IResource resource) :
    args(resource) &&
    execution(boolean JavaBuilder.filterExtraResource(IResource));

  void around(BatchImageBuilder builder, boolean copyBack) throws CoreException :
    target(builder) &&
    cleanOutputFolders(copyBack) &&
    cflow(build()) {
    // Suppress the cleaning behaviour but do the extra resource copying if requested
    if (copyBack)
      for (int i = 0, l = builder.sourceLocations.length; i < l; i++) {
        org.eclipse.jdt.internal.core.builder.ClasspathMultiDirectory sourceLocation = builder.sourceLocations[i];
        if (sourceLocation.hasIndependentOutputFolder)
          builder.copyExtraResourcesBack(sourceLocation, false);
      }
  }

  boolean around(String fileName) :
    isJavaLikeFileName(fileName) &&
    cflow(build()) &&
    !cflow(cleanOutputFolders(*)) {
    if (fileName != null && fileName.endsWith("scala"))
      return false;
    else
      return proceed(fileName);
  }

  boolean around(IResource resource) :
    filterExtraResource(resource) &&
    cflow(build()) {
    return resource.getName().endsWith(".scala") || proceed(resource);
  }
}

/*
 * Copyright 2005-2009 LAMP/EPFL
 */
// $Id$

package scala.tools.eclipse.contribution.weaving.jdt.builderoptions;

import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.internal.core.builder.BatchImageBuilder;
//import org.eclipse.jdt.internal.core.builder.ClasspathMultiDirectory;
import org.eclipse.jdt.internal.core.util.Util;

@SuppressWarnings("restriction")
public privileged aspect ScalaJavaBuilderAspect {
  pointcut build() :
    execution(IProject[] ScalaJavaBuilder.build(int, Map, IProgressMonitor) throws CoreException);

  pointcut cleanOutputFolders(boolean copyBack) :
    args(copyBack) &&
    execution(void BatchImageBuilder.cleanOutputFolders(boolean) throws CoreException);

  pointcut isJavaLikeFileName(String fileName) :
    args(fileName) &&
    execution(boolean Util.isJavaLikeFileName(String));

  void around(BatchImageBuilder builder, boolean copyBack) throws CoreException :
    target(builder) &&
    cleanOutputFolders(copyBack) &&
    cflow(build()) {
    // Suppress the cleaning behaviour but do the extra resource copying if requested
    if (copyBack)
      for (int i = 0, l = builder.sourceLocations.length; i < l; i++) {
        org.eclipse.jdt.internal.core.builder.ClasspathMultiDirectory sourceLocation = builder.sourceLocations[i];
        if (sourceLocation.hasIndependentOutputFolder)
          builder.copyExtraResourcesBack(sourceLocation, false);
      }
  }

  boolean around(String fileName) :
    isJavaLikeFileName(fileName) &&
    cflow(build()) &&
    !cflow(cleanOutputFolders(*)) {
    if (fileName != null && fileName.endsWith("scala"))
      return false;
    else
      return proceed(fileName);
  }
}


handling TrackNRestart for Runnable. Refactorization of restart for KCall.

package org.parallelj.tracknrestart.aspects;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;

import org.apache.log4j.Logger;
import org.parallelj.Programs;
import org.parallelj.Programs.ProcessHelper;
import org.parallelj.internal.kernel.KCall;
import org.parallelj.internal.kernel.KProcess;
import org.parallelj.internal.reflect.ProgramAdapter.Adapter;
import org.parallelj.tracknrestart.annotations.TrackNRestart;
import org.parallelj.tracknrestart.listeners.ForEachListener;
import org.parallelj.tracknrestart.plugins.TrackNRestartPlugin;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobPersistenceException;
import org.parallelj.tracknrestart.ReturnCodes;

privileged public aspect QuartzContextAdapter percflow (execution(public void Job+.execute(..) throws JobExecutionException)) {

	declare precedence :
		org.parallelj.tracknrestart.aspects.QuartzContextAdapter,
		org.parallelj.launching.quartz.JobsAdapter;

	static Logger logger = Logger.getLogger("org.parallelj.tracknrestart.QuartzContextAdapter");

	private X root;

	String result = ReturnCodes.SUCCESS.name();

	//---------------------------------------------------------------------------------------------------

	declare parents:
		(@org.parallelj.launching.QuartzExecution *) implements Job;

	public void Job.execute(JobExecutionContext context)
			throws JobExecutionException {

		ProcessHelper<?> p = null;
		logger.debug("-----------------------------------------------------------------------------------------------------");
		logger.debug("STARTING //J Root Program "+this.getClass().getName());

		p = Programs.as((Adapter) this);

		try {
			//TODO voir avec Christophe @IN
			Field f = this.getClass().getDeclaredField("data1");
			f.setAccessible(true);
			f.set(this, context.getJobDetail().getJobDataMap().get("data1"));
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		p.execute().join();

		logger.debug("ENDING   //J Root Program "+this.getClass().getName());
		logger.debug("-----------------------------------------------------------------------------------------------------");
		context.setResult(String.valueOf(p.getState()));
	}

	//---------------------------------------------------------------------------------------------------

	public interface X {};

	declare parents:
		(org.quartz.Job+ && !org.quartz.Job) implements X;

	declare parents:
		(org.parallelj.internal.kernel.KCall) implements X;

//	declare parents:
//		(org.parallelj.mirror.Element+) implements X;

//	declare parents:
//		(org.parallelj.internal.kernel.callback.Entry+) implements X;

//	declare parents:
//		(org.parallelj.internal.kernel.callback.Exit+) implements X;

	private ForEachListener X.forEachListener = null;

	public ForEachListener X.getForEachListener() {
		return forEachListener;
	}

	public void X.setForEachListener(ForEachListener forEachListener) {
		this.forEachListener = forEachListener;
	}

	private String X.restartedFireInstanceId = null;

	public String X.getRestartedFireInstanceId() {
		return restartedFireInstanceId;
	}

	public void X.setRestartedFireInstanceId(String restartedFireInstanceId) {
		this.restartedFireInstanceId = restartedFireInstanceId;
	}

	//---------------------------------------------------------------------------------------------------

	//JobExecutionContext --> Job
	before(X self, JobExecutionContext jobExecutionContext):
		execution(public void Job+.execute(..) throws JobExecutionException)
		&& this(self)
		&& args(jobExecutionContext) {

		//logger.debug("ASPECT BEFORE:execution(public void Job+.execute(..) throws JobExecutionException) && this(self) && args(jobExecutionContext)");

		self.setRestartedFireInstanceId(jobExecutionContext.getJobDetail().getJobDataMap().getString(TrackNRestartPlugin.RESTARTED_FIRE_INSTANCE_ID));
		self.setForEachListener((ForEachListener) jobExecutionContext.getJobDetail().getJobDataMap().get(TrackNRestartPlugin.FOR_EACH_LISTENER));
		//logger.debug("job="+self);
		//logger.debug("restartedFireInstanceId="+self.getRestartedFireInstanceId());
		//logger.debug("forEachListener="+self.getForEachListener());

		this.root = self;
	}

	after(X self, JobExecutionContext jobExecutionContext):
		execution(public void Job+.execute(..) throws JobExecutionException)
		&& this(self)
		&& args(jobExecutionContext) {

		//logger.debug("ASPECT AFTER:execution(public void Job+.execute(..) throws JobExecutionException) && this(self) && args(jobExecutionContext)");
		jobExecutionContext.setResult(result);
	}

	after(X self):
		execution(protected KCall.new(..)) && this(self) {

		//logger.debug("ASPECT AFTER:protected execution(protected KCall.new(..)) && this(self)");
		//logger.debug("self="+self);
		self.setRestartedFireInstanceId(root.getRestartedFireInstanceId());
		self.setForEachListener(root.getForEachListener());
		//logger.debug("restartedFireInstanceId="+self.getRestartedFireInstanceId());
		//logger.debug("forEachListener="+self.getForEachListener());
	}

	after(X self):
		execution(protected KProcess.new(..)) && this(self) {

		//logger.debug("ASPECT AFTER:protected execution(protected KProcess.new(..)) && this(self)");
		//logger.debug("self="+self);
		self.setRestartedFireInstanceId(root.getRestartedFireInstanceId());
		self.setForEachListener(root.getForEachListener());
		//logger.debug("restartedFireInstanceId="+self.getRestartedFireInstanceId());
		//logger.debug("forEachListener="+self.getForEachListener());
	}

    pointcut enter(KCall _kCall): call(* org.parallelj.internal.kernel.callback.Entry+.enter(KCall)) && args(_kCall);
    pointcut invoke(): call(public Object Method.invoke(Object, ..)) && !within(QuartzContextAdapter);

//pdx
// Runnable program. ----------------------------------------------------------------------------------------------------------------------------------

    public interface Y {};

  	private Object Y.context = null;

  	public Object Y.getContext() {
  		return context;
  	}

  	public void Y.setContext(Object context) {
  		this.context=context;
  	}

    declare parents:
		(java.lang.Runnable+ ) implements X, Y;

    // 1) Transfert from RunnableCall to Runnable.
  	after(Object self) returning (Runnable ret):
    	 execution(* org.parallelj.internal.kernel.procedure.RunnableProcedure.RunnableCall.toRunnable())
      && this(self)  {

    	 ((X)ret).setForEachListener(((X)self).getForEachListener());
    	 ((X)ret).setRestartedFireInstanceId(((X)self).getRestartedFireInstanceId());
    	 ((Y)ret).setContext(((org.parallelj.internal.kernel.KCall)self).getContext());
    }

     // 2) Interception around call of run.
     void around(Object self): call(* run(..))
     && within(org.parallelj.internal.kernel.procedure.RunnableProcedure.RunnableCall)
     && within(Runnable+)  && this(self)  {

    	 String restartedFireInstanceId = ((X) self).getRestartedFireInstanceId();
    	 ForEachListener forEachListener = ((X)self).getForEachListener();
    	 Object program =  ((Y)self).getContext();

    	 if (isToProcess(restartedFireInstanceId,forEachListener,program)) {
    		try {
    			proceed(self);
     			if (isTrackNRestartAnnoted(program)) {
     				String oid = getOID(program);
   					track(forEachListener, oid, true);
     			}
    		} catch (Exception e) {
 				if (isTrackNRestartAnnoted(program)){
 					String oid = getOID(program);
 					if (isTrackNRestartExceptionPermitted(program, e)) {
	 					track(forEachListener, oid, false);
					} else {
						abortAbruptly();
						throw new TrackNRestartException("Exception thrown ("+e.getClass().getName()+") is not in list of permitted exceptions "+filteredExceptionsAsString(getTrackNRestartAnnotedException(program)));
					}
 				}
    		}
     	} else {
     		if (isTrackNRestartAnnoted(program)) {
 				String oid = getOID(program);
 				track(forEachListener, oid, true);
			} else {
				abortAbruptly();
				throw new TrackNRestartException("Unable to get iteration OID while 'tracking' context.");
 			}
     	}
     }

     /**
      * Track the execution (success or failure).
      * @param forEachListener listener handling Quartz backend.
      * @param oid unique identifier
      * @param success boolean indicating if processing is a success or a failure.
      */
     private void track(ForEachListener forEachListener, String oid, boolean success) {
	     try {
				forEachListener.forEachInstanceComplete(oid, success);
	     } catch (JobPersistenceException e) {
				abortAbruptly();
				throw new TrackNRestartException("Unable to read status for iteration '"+ oid + "'.", e);
		} catch (SQLException e) {
				abortAbruptly();
				throw new TrackNRestartException("Unable to read status for iteration '"+ oid + "'.", e);
		}
     }

// restart part ----------------------------------------------------------------------------------------------------------------------------------------

     Object around(Object oo, KCall _kCall)  :
        invoke() && args(oo, ..) && cflow(enter(_kCall)) {

    	if (isToProcess( ((X) _kCall).getRestartedFireInstanceId(),((X) _kCall).getForEachListener(), oo)) {
               return proceed(oo, _kCall);
        } else {
               return null;
        }
     }

    /**
     * Check if an iterable must be processed. This means if the iterable is not already processed or the element was processed in error.
     * @param restartedFireInstanceId id of the batch to be restarted.
     * @param forEachListener listener handling request to Quartz.
     * @param program instance of the program processing the iterable.
     * @return true iterable has to be processed, false else.
     */
    private boolean isToProcess(String restartedFireInstanceId,  ForEachListener forEachListener, Object program)   {
		boolean result = true;
		if (program != null) {
			if (program.getClass().isAnnotationPresent(TrackNRestart.class)) {
				String oid = getOID(program);
				if (oid != null) {
					if (restartedFireInstanceId != null) {
						// logger.debug("Processing in restarting mode for oid : ["
						// + oid + "] ,program : [" + program +
						// "] ,instanceId :[" +instanceId+ "]");
						try {
							result = !forEachListener.isForEachInstanceIgnorable(restartedFireInstanceId, oid);
							// logger.debug(result ?
							// "This OID has not been already processed or" +
							// " already processed in error, so its processing is not skipped":
							// "This OID ("+oid+") has been already successfully processed, so its processing is skipped");
						} catch (JobPersistenceException e) {
							abortAbruptly();
							throw new TrackNRestartException(
									"Unable to read status for iteration '"
											+ oid + "'.", e);
						} catch (SQLException e) {
							abortAbruptly();
							throw new TrackNRestartException(
									"Unable to read status for iteration '"
											+ oid + "'.", e);
						}
					} else {
						// logger.debug("Processing in normal mode (ie not restarting mode) for : ["
						// + oid + "] ,program : [" + program + "]");
					}
				}
			}
		}
		return result;
	}

    /**
     * Get unique identifier returned by the program (the program contains value to be processed).
     * @param program
     * @return unique identifier.
     */
	private String getOID(Object program) {
		String result = null;
		try {
			Method m = program.getClass().getDeclaredMethod("getOID",
					new Class[] {});
			return (String) m.invoke(program, new Object[] {});
		} catch (SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NoSuchMethodException e1) {
			abortAbruptly();
			throw new TrackNRestartException(
					"No getOID() method found while program " + program
							+ " was annotated @TrackNRestart.", e1);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * Indicate of the Program contains annotation TrackNRestart.
	 * @param program
	 * @return true if program is annoted.
	 */
	private boolean isTrackNRestartAnnoted(Object program) {
		return program.getClass().isAnnotationPresent(TrackNRestart.class);
	}

	/**
	 * Check if the raised exception belong to the allowed ones in TrackNRestart annotation.
	 * @param program
	 * @param exception raised
	 * @return true if exception is allowed, false else.
	 */
	private boolean isTrackNRestartExceptionPermitted(Object program, Exception exception) {
		boolean result = false;
		Class<? extends Throwable>[] filteredExceptions =  getTrackNRestartAnnotedException(program);
		for (int i = 0; i < filteredExceptions.length; i++) {
				if (filteredExceptions[i].isAssignableFrom(exception.getClass())) {
					return true;
			}
		}
		return false;
	}

	/**
	 * Return exceptions defined in TrackNRestart annotation.
	 * @param program
	 * @return array of exceptions
	 */
	private Class<? extends Throwable>[] getTrackNRestartAnnotedException (Object program) {
		return program.getClass().getAnnotation(TrackNRestart.class).filteredExceptions();
	}

// tracking part ----------------------------------------------------------------------------------------------------------------------------------------
   after(Object oo, KCall _kCall) returning :
    	invoke() && args(oo, ..) && cflow(enter(_kCall)) {

		//logger.debug("ASPECT AFTER RETURNING");
		//logger.debug("_KCall="+_kCall);
		track(_kCall, oo, true, null);
    }

    after(Object oo, KCall _kCall) throwing (InvocationTargetException ite) :
    	invoke() && args(oo, ..) && cflow(enter(_kCall)) {

		//logger.debug("ASPECT AFTER THROWING (InvocationTargetException)");
		//logger.debug("_KCall="+_kCall);
		this.result = "FAILURE";
		track(_kCall, oo, false, ite);
    }

	private void track(KCall _kCall, Object program, boolean success,
			InvocationTargetException ite) {
		String oid = null;

		try {
			if (program != null) {
				Class<? extends Object> clazz = program.getClass();
				if (clazz.isAnnotationPresent(TrackNRestart.class)) {
					Method m = clazz
							.getDeclaredMethod("getOID", new Class[] {});
					oid = (String) m.invoke(program, new Object[] {});
					if (oid != null) {
						if (success == true) {
							persist(_kCall, success, oid);
						} else {
							Class<? extends Throwable>[] filteredExceptions = clazz
									.getAnnotation(TrackNRestart.class)
									.filteredExceptions();
							if (isIteCausePermittedInList(ite,
									filteredExceptions)) {
								persist(_kCall, success, oid);
							} else {
								abortAbruptly();
								throw new TrackNRestartException(
										"Exception thrown ("
												+ ite.getCause().getClass()
														.getName()
												+ ") is not in list of permitted exceptions "
												+ filteredExceptionsAsString(filteredExceptions));
							}
						}
						if (logger.isDebugEnabled()) {
							// logger.debug("oid='" + oid +
							// "' persisted with status='" + (success ?
							// ReturnCodes.SUCCESS : "FAILURE") + "' "+ (ite ==
							// null ? "" : ", cause : " + ite.getCause()));
						}
					} else {
						abortAbruptly();
						throw new TrackNRestartException(
								"Unable to get iteration OID while 'tracking' context.");
					}
				}
			}
		} catch (NoSuchMethodException e) {
			abortAbruptly();
			throw new TrackNRestartException(
					"No getOID() method found while program " + program
							+ " was annotated @TrackNRestart.", e);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JobPersistenceException e) {
			abortAbruptly();
			throw new TrackNRestartException("Unable to persist status ['"
					+ (success ? ReturnCodes.SUCCESS : "FAILURE")
					+ "'] for iteration '" + oid + "'.", e);
		} catch (SQLException e) {
			abortAbruptly();
			throw new TrackNRestartException("Unable to persist status ['"
					+ (success ? ReturnCodes.SUCCESS : "FAILURE")
					+ "'] for iteration '" + oid + "'.", e);
		}
	}

	private boolean isIteCausePermittedInList(InvocationTargetException ite,
			Class<? extends Throwable>[] filteredExceptions) {
		for (int i = 0; i < filteredExceptions.length; i++) {
			if (filteredExceptions[i].isAssignableFrom(ite.getCause()
					.getClass()))
				return true;
		}
		return false;
	}

	private String filteredExceptionsAsString(
			Class<? extends Throwable>[] filteredExceptions) {
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (int i = 0; i < filteredExceptions.length; i++) {
			if (i > 0)
				sb.append(", ");
			sb.append(filteredExceptions[i].getName());
		}
		sb.append("]");
		return sb.toString();
	}

	private void persist(KCall _kCall, boolean success, String oid)
			throws JobPersistenceException, SQLException {
		((X) _kCall).getForEachListener().forEachInstanceComplete(oid, success);
	}

	private void abortAbruptly() {
		this.result = "ABORTED";
		Programs.as((Adapter) this.root).abort();
	}

}

package org.parallelj.tracknrestart.aspects;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.SQLException;

import org.apache.log4j.Logger;
import org.parallelj.Programs;
import org.parallelj.Programs.ProcessHelper;
import org.parallelj.internal.kernel.KCall;
import org.parallelj.internal.kernel.KProcess;
import org.parallelj.internal.reflect.ProgramAdapter.Adapter;
import org.parallelj.tracknrestart.annotations.TrackNRestart;
import org.parallelj.tracknrestart.listeners.ForEachListener;
import org.parallelj.tracknrestart.plugins.TrackNRestartPlugin;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobPersistenceException;
import org.parallelj.tracknrestart.ReturnCodes;

privileged public aspect QuartzContextAdapter percflow (execution(public void Job+.execute(..) throws JobExecutionException)) {

	declare precedence :
		org.parallelj.tracknrestart.aspects.QuartzContextAdapter,
		org.parallelj.launching.quartz.JobsAdapter;

	static Logger logger = Logger.getLogger("org.parallelj.tracknrestart.QuartzContextAdapter");

	private X root;

	String result = ReturnCodes.SUCCESS.name();

	//---------------------------------------------------------------------------------------------------

	declare parents:
		(@org.parallelj.launching.QuartzExecution *) implements Job;

	public void Job.execute(JobExecutionContext context)
			throws JobExecutionException {

		ProcessHelper<?> p = null;
		logger.debug("-----------------------------------------------------------------------------------------------------");
		logger.debug("STARTING //J Root Program "+this.getClass().getName());

		p = Programs.as((Adapter) this);

		try {
			//TODO voir avec Christophe @IN
			Field f = this.getClass().getDeclaredField("data1");
			f.setAccessible(true);
			f.set(this, context.getJobDetail().getJobDataMap().get("data1"));
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		p.execute().join();

		logger.debug("ENDING   //J Root Program "+this.getClass().getName());
		logger.debug("-----------------------------------------------------------------------------------------------------");
		context.setResult(String.valueOf(p.getState()));
	}

	//---------------------------------------------------------------------------------------------------

	public interface X {};

	declare parents:
		(org.quartz.Job+ && !org.quartz.Job) implements X;

	declare parents:
		(org.parallelj.internal.kernel.KCall) implements X;

//	declare parents:
//		(org.parallelj.mirror.Element+) implements X;

//	declare parents:
//		(org.parallelj.internal.kernel.callback.Entry+) implements X;

//	declare parents:
//		(org.parallelj.internal.kernel.callback.Exit+) implements X;

	private ForEachListener X.forEachListener = null;

	public ForEachListener X.getForEachListener() {
		return forEachListener;
	}

	public void X.setForEachListener(ForEachListener forEachListener) {
		this.forEachListener = forEachListener;
	}

	private String X.restartedFireInstanceId = null;

	public String X.getRestartedFireInstanceId() {
		return restartedFireInstanceId;
	}

	public void X.setRestartedFireInstanceId(String restartedFireInstanceId) {
		this.restartedFireInstanceId = restartedFireInstanceId;
	}

	//---------------------------------------------------------------------------------------------------

	//JobExecutionContext --> Job
	before(X self, JobExecutionContext jobExecutionContext):
		execution(public void Job+.execute(..) throws JobExecutionException)
		&& this(self)
		&& args(jobExecutionContext) {

		//logger.debug("ASPECT BEFORE:execution(public void Job+.execute(..) throws JobExecutionException) && this(self) && args(jobExecutionContext)");

		self.setRestartedFireInstanceId(jobExecutionContext.getJobDetail().getJobDataMap().getString(TrackNRestartPlugin.RESTARTED_FIRE_INSTANCE_ID));
		self.setForEachListener((ForEachListener) jobExecutionContext.getJobDetail().getJobDataMap().get(TrackNRestartPlugin.FOR_EACH_LISTENER));
		//logger.debug("job="+self);
		//logger.debug("restartedFireInstanceId="+self.getRestartedFireInstanceId());
		//logger.debug("forEachListener="+self.getForEachListener());

		this.root = self;
	}

	after(X self, JobExecutionContext jobExecutionContext):
		execution(public void Job+.execute(..) throws JobExecutionException)
		&& this(self)
		&& args(jobExecutionContext) {

		//logger.debug("ASPECT AFTER:execution(public void Job+.execute(..) throws JobExecutionException) && this(self) && args(jobExecutionContext)");
		jobExecutionContext.setResult(result);
	}

	after(X self):
		execution(protected KCall.new(..)) && this(self) {

		//logger.debug("ASPECT AFTER:protected execution(protected KCall.new(..)) && this(self)");
		//logger.debug("self="+self);
		self.setRestartedFireInstanceId(root.getRestartedFireInstanceId());
		self.setForEachListener(root.getForEachListener());
		//logger.debug("restartedFireInstanceId="+self.getRestartedFireInstanceId());
		//logger.debug("forEachListener="+self.getForEachListener());
	}

	after(X self):
		execution(protected KProcess.new(..)) && this(self) {

		//logger.debug("ASPECT AFTER:protected execution(protected KProcess.new(..)) && this(self)");
		//logger.debug("self="+self);
		self.setRestartedFireInstanceId(root.getRestartedFireInstanceId());
		self.setForEachListener(root.getForEachListener());
		//logger.debug("restartedFireInstanceId="+self.getRestartedFireInstanceId());
		//logger.debug("forEachListener="+self.getForEachListener());
	}

    pointcut enter(KCall _kCall): call(* org.parallelj.internal.kernel.callback.Entry+.enter(KCall)) && args(_kCall);
    pointcut invoke(): call(public Object Method.invoke(Object, ..)) && !within(QuartzContextAdapter);

// restart part ----------------------------------------------------------------------------------------------------------------------------------------
    Object around(Object oo, KCall _kCall)  :
        invoke() && args(oo, ..) && cflow(enter(_kCall)) {

        if (restart(_kCall, oo)) {
               return proceed(oo, _kCall);
        } else {
               return null;
        }
     }

	private boolean restart(KCall _kCall, Object program) {
		boolean result = true;
		if (program != null) {
			if (program.getClass().isAnnotationPresent(TrackNRestart.class)) {
				String oid = getOID(program);
				if (oid != null) {
					String instanceId = ((X) _kCall)
							.getRestartedFireInstanceId();
					if (instanceId != null) {
						// logger.debug("Processing in restarting mode for oid : ["
						// + oid + "] ,program : [" + program +
						// "] ,instanceId :[" +instanceId+ "]");
						try {
							result = !((X) _kCall)
									.getForEachListener()
									.isForEachInstanceIgnorable(instanceId, oid);
							// logger.debug(result ?
							// "This OID has not been already processed or" +
							// " already processed in error, so its processing is not skipped":
							// "This OID ("+oid+") has been already successfully processed, so its processing is skipped");
						} catch (JobPersistenceException e) {
							abortAbruptly();
							throw new TrackNRestartException(
									"Unable to read status for iteration '"
											+ oid + "'.", e);
						} catch (SQLException e) {
							abortAbruptly();
							throw new TrackNRestartException(
									"Unable to read status for iteration '"
											+ oid + "'.", e);
						}
					} else {
						// logger.debug("Processing in normal mode (ie not restarting mode) for : ["
						// + oid + "] ,program : [" + program + "]");
					}
				}
			}
		}
		return result;
	}

	private String getOID(Object program) {
		String result = null;
		try {
			Method m = program.getClass().getDeclaredMethod("getOID",
					new Class[] {});
			return (String) m.invoke(program, new Object[] {});
		} catch (SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (NoSuchMethodException e1) {
			abortAbruptly();
			throw new TrackNRestartException(
					"No getOID() method found while program " + program
							+ " was annotated @TrackNRestart.", e1);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}

// tracking part ----------------------------------------------------------------------------------------------------------------------------------------
   after(Object oo, KCall _kCall) returning :
    	invoke() && args(oo, ..) && cflow(enter(_kCall)) {

		//logger.debug("ASPECT AFTER RETURNING");
		//logger.debug("_KCall="+_kCall);
		track(_kCall, oo, true, null);
    }

    after(Object oo, KCall _kCall) throwing (InvocationTargetException ite) :
    	invoke() && args(oo, ..) && cflow(enter(_kCall)) {

		//logger.debug("ASPECT AFTER THROWING (InvocationTargetException)");
		//logger.debug("_KCall="+_kCall);
		this.result = "FAILURE";
		track(_kCall, oo, false, ite);
    }

	private void track(KCall _kCall, Object program, boolean success,
			InvocationTargetException ite) {
		String oid = null;

		try {
			if (program != null) {
				Class<? extends Object> clazz = program.getClass();
				if (clazz.isAnnotationPresent(TrackNRestart.class)) {
					Method m = clazz
							.getDeclaredMethod("getOID", new Class[] {});
					oid = (String) m.invoke(program, new Object[] {});
					if (oid != null) {
						if (success == true) {
							persist(_kCall, success, oid);
						} else {
							Class<? extends Throwable>[] filteredExceptions = clazz
									.getAnnotation(TrackNRestart.class)
									.filteredExceptions();
							if (isIteCausePermittedInList(ite,
									filteredExceptions)) {
								persist(_kCall, success, oid);
							} else {
								abortAbruptly();
								throw new TrackNRestartException(
										"Exception thrown ("
												+ ite.getCause().getClass()
														.getName()
												+ ") is not in list of permitted exceptions "
												+ filteredExceptionsAsString(filteredExceptions));
							}
						}
						if (logger.isDebugEnabled()) {
							// logger.debug("oid='" + oid +
							// "' persisted with status='" + (success ?
							// ReturnCodes.SUCCESS : "FAILURE") + "' "+ (ite ==
							// null ? "" : ", cause : " + ite.getCause()));
						}
					} else {
						abortAbruptly();
						throw new TrackNRestartException(
								"Unable to get iteration OID while 'tracking' context.");
					}
				}
			}
		} catch (NoSuchMethodException e) {
			abortAbruptly();
			throw new TrackNRestartException(
					"No getOID() method found while program " + program
							+ " was annotated @TrackNRestart.", e);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (JobPersistenceException e) {
			abortAbruptly();
			throw new TrackNRestartException("Unable to persist status ['"
					+ (success ? ReturnCodes.SUCCESS : "FAILURE")
					+ "'] for iteration '" + oid + "'.", e);
		} catch (SQLException e) {
			abortAbruptly();
			throw new TrackNRestartException("Unable to persist status ['"
					+ (success ? ReturnCodes.SUCCESS : "FAILURE")
					+ "'] for iteration '" + oid + "'.", e);
		}
	}

	private boolean isIteCausePermittedInList(InvocationTargetException ite,
			Class<? extends Throwable>[] filteredExceptions) {
		for (int i = 0; i < filteredExceptions.length; i++) {
			if (filteredExceptions[i].isAssignableFrom(ite.getCause()
					.getClass()))
				return true;
		}
		return false;
	}

	private String filteredExceptionsAsString(
			Class<? extends Throwable>[] filteredExceptions) {
		StringBuffer sb = new StringBuffer();
		sb.append("[");
		for (int i = 0; i < filteredExceptions.length; i++) {
			if (i > 0)
				sb.append(", ");
			sb.append(filteredExceptions[i].getName());
		}
		sb.append("]");
		return sb.toString();
	}

	private void persist(KCall _kCall, boolean success, String oid)
			throws JobPersistenceException, SQLException {
		((X) _kCall).getForEachListener().forEachInstanceComplete(oid, success);
	}

	private void abortAbruptly() {
		this.result = "ABORTED";
		Programs.as((Adapter) this.root).abort();
	}

}