Formatting

Formatting

/*
 * Copyright (c) 2013 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.eigengo.monitor.agent.akka;

import akka.actor.*;
import org.eigengo.monitor.agent.AgentConfiguration;
import org.eigengo.monitor.output.CounterInterface;
import scala.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Contains advices for monitoring behaviour of an actor; typically imprisoned in an {@code ActorCell}.
 */
public aspect ActorCellMonitoringAspect extends AbstractMonitoringAspect issingleton() {
    private AkkaAgentConfiguration agentConfiguration;
    private final CounterInterface counterInterface;
    private final Option<String> noActorClazz = Option.empty();
    private final ConcurrentHashMap<Option<String>, AtomicLong> samplingCounters  = new ConcurrentHashMap<Option<String>, AtomicLong>();
    private final ConcurrentHashMap<Option<String>, AtomicInteger> numberOfActors = new ConcurrentHashMap<Option<String>, AtomicInteger>();

    /**
     * Constructs this aspect
     */
    public ActorCellMonitoringAspect() {
        AgentConfiguration<AkkaAgentConfiguration> configuration = getAgentConfiguration("akka", AkkaAgentConfigurationJapi.apply());
        this.agentConfiguration = configuration.agent();
        this.counterInterface = createCounterInterface(configuration.common());
    }

    /**
     * Injects the new {@code AkkaAgentConfiguration} instance.
     *
     * @param agentConfiguration the new configuration
     */
    synchronized final void setAgentConfiguration(AkkaAgentConfiguration agentConfiguration) {
        this.agentConfiguration = agentConfiguration;
    }

    /**
     * decide whether to include this ActorCell in our measurements
     * */
    private boolean includeActorPath(final PathAndClass pathAndClass) {
        // do not monitor our own output code
        if (pathAndClass.actorClassName().isDefined()) {
            if (pathAndClass.actorClassName().get().startsWith("org.eigengo.monitor.output")) return false;
        }

        // skip if not included
        if (!this.agentConfiguration.included().accept(pathAndClass)) return false;
        // skip if excluded
        if (this.agentConfiguration.excluded().accept(pathAndClass)) return false;

        // skip system actor checks if we wish to monitor them
        if (this.agentConfiguration.includeSystemAgents()) return true;

        String userOrSystem = pathAndClass.actorPath().getElements().iterator().next();
        return "user".equals(userOrSystem);
    }

    /**
     * get the sample rate for an actor
     * */
    private int getSampleRate(final PathAndClass pathAndClass) {
        return this.agentConfiguration.sampling().getRate(pathAndClass);
    }

    /**
     * decide whether to sample an actor on a particular occasion
     *
     * @param pathAndClass
     * @return true if we should sample this actor, otherwise false.
     */
    private final boolean sampleMessage(final PathAndClass pathAndClass) {
        int sampleRate = getSampleRate(pathAndClass);
        if (sampleRate == 1) return true;

        this.samplingCounters.putIfAbsent(pathAndClass.actorClassName(), new AtomicLong(0));
        long timesSeenSoFar = this.samplingCounters.get(pathAndClass.actorClassName()).incrementAndGet();
        return (timesSeenSoFar % sampleRate == 1); // == 1 to log first value (incrementAndGet returns updated value)
    }

    /**
     * get the tags for the cell
     * */
    private String[] getTags(final ActorPath actorPath, final Actor actor) {
        List<String> tags = new ArrayList<String>();

        // TODO: Improve detection of routed actors. This relies only on the naming :(.
        String lastPathElement = actorPath.elements().last();
        if (lastPathElement.startsWith("$")) {
            // this is routed actor.
            tags.add(actorPath.parent().toString());
            if (this.agentConfiguration.includeRoutees()) tags.add(actorPath.toString());
        } else {
            // there is no supervisor
            tags.add(actorPath.toString());
        }
        if (actor != null) {
            tags.add(String.format("akka:%s.%s", actor.context().system().name(), actor.getClass().getCanonicalName()));
        }

        return tags.toArray(new String[tags.size()]);
    }

    /**
     * returns the canonical name of the actor type associated with an ActorCell
     * */
    private String uncheckedActorNameFrom(final ActorCell actorCell) {
        return uncheckedActorNameFrom(actorCell.props());
    }

    /**
     * returns the canonical name of the actor type associated with a Props instance
     * */
    private String uncheckedActorNameFrom(final Props props) {
        return props.actorClass().getCanonicalName();
    }

    /**
     * Advises the {@code ActorCell.receiveMessage(message: Object): Unit}
     * We proceed with the pointcut if the actor is to be included in the monitoring *and* this is
     * the 'multiple-of-n'th time we've seen a message for an actor with a sample rate of n.
     *
     * Currently, we sample queue size, the fact that the message is delivered, the simple name of the class of the
     * message, and the time taken to complete the actor's reactive action.
     *
     * @param actorCell the ActorCell where the actor that receives the message "lives"
     * @param msg the incoming message
     */
    Object around(ActorCell actorCell, Object msg) : Pointcuts.actorCellReceiveMessage(actorCell, msg) {

        final ActorPath actorPath = actorCell.self().path();
        final PathAndClass pathAndClass = new PathAndClass(actorPath, Option.apply(uncheckedActorNameFrom(actorCell)));
        if (!includeActorPath(pathAndClass) || !sampleMessage(pathAndClass)) return proceed(actorCell, msg);

        int samplingRate = getSampleRate(pathAndClass);

        // we tag by actor name
        final String[] tags = getTags(actorPath, actorCell.actor());

        // record the queue size
        this.counterInterface.recordGaugeValue("akka.queue.size", actorCell.numberOfMessages(), tags);
        // record the message, general and specific
        this.counterInterface.incrementCounter("akka.actor.delivered", samplingRate, tags);
        this.counterInterface.incrementCounter("akka.actor.delivered." + msg.getClass().getSimpleName(), samplingRate, tags);

        // measure the time. we're using the ``nanoTime`` call to access the high-precision timer.
        // since we're not really interested in wall time, but just some increasing measure of
        // elapsed time
        Object result = null;
        final long start = System.nanoTime();
        // result will always be ``null``, because target returns ``Unit``
        result = proceed(actorCell, msg);
        // ns or µs is too fine. ms will do for now.
        final long duration = (System.nanoTime() - start) / 1000000;

        // record the actor duration
        this.counterInterface.recordExecutionTime("akka.actor.duration", (int)duration, tags);

        // return null would do the trick, but we want to be _proper_.
        return result;
    }

    /**
     * Advises the {@code ActorCell.handleInvokeFailure(_, failure: Throwable): Unit}
     *
     * @param actorCell the ActorCell where the error spreads from
     * @param failure the exception that escaped from the {@code receive} method
     */
    before(ActorCell actorCell, Throwable failure) : Pointcuts.actorCellHandleInvokeFailure(actorCell, failure) {
        // record the error, general and specific
        String[] tags = getTags(actorCell.self().path(), actorCell.actor());
        this.counterInterface.incrementCounter("akka.actor.error", tags);
        this.counterInterface.incrementCounter(String.format("akka.actor.error.%s", failure.getMessage()), tags);
    }

    /**
     * Advises the {@code EventStream.publish(event: Any): Unit}
     *
     * @param event the received event
     */
    before(Object event) : Pointcuts.eventStreamPublish(event) {
        if (event instanceof UnhandledMessage) {
            UnhandledMessage unhandledMessage = (UnhandledMessage)event;
            String[] tags = getTags(unhandledMessage.recipient().path(), null);
            this.counterInterface.incrementCounter("akka.actor.undelivered", tags);
            this.counterInterface.incrementCounter("akka.actor.undelivered." + unhandledMessage.getMessage().getClass().getSimpleName(), tags);
        }
    }

    /**
     * Advises the {@code actorOf} method of {@code ActorRefFactory} implementations
     *
     * @param props the {@code Props} instance used in the call
     * @param actor the {@code ActorRef} returned from the call
     */
    after(Props props) returning (ActorRef actor) : Pointcuts.anyActorOf(props) {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(props);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // increment and get the current number of actors of this type (if the value was 0, then this returns 1 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).incrementAndGet();

        // record the current number of actors of this type
        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

    /**
     * Advises the {@code LocalActorRef.stop} method
     *
     * @param actorCell the {@code ActorCell} of the actor being stopped
     */
    after(ActorCell actorCell) : Pointcuts.actorCellInternalStop(actorCell) {
        if (!includeActorPath(new PathAndClass(actorCell.self().path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(actorCell);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // decrement and get the current number of actors of this type (if the value was 1, then this returns 0 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).decrementAndGet();

        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

}

/*
 * Copyright (c) 2013 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.eigengo.monitor.agent.akka;

import akka.actor.*;
import org.eigengo.monitor.agent.AgentConfiguration;
import org.eigengo.monitor.output.CounterInterface;
import scala.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Contains advices for monitoring behaviour of an actor; typically imprisoned in an {@code ActorCell}.
 */
public aspect ActorCellMonitoringAspect extends AbstractMonitoringAspect issingleton() {
    private AkkaAgentConfiguration agentConfiguration;
    private final CounterInterface counterInterface;
    private final Option<String> noActorClazz = Option.empty();
    private final ConcurrentHashMap<Option<String>, AtomicLong> samplingCounters  = new ConcurrentHashMap<Option<String>, AtomicLong>();
    private final ConcurrentHashMap<Option<String>, AtomicInteger> numberOfActors = new ConcurrentHashMap<Option<String>, AtomicInteger>();

    /**
     * Constructs this aspect
     */
    public ActorCellMonitoringAspect() {
        AgentConfiguration<AkkaAgentConfiguration> configuration = getAgentConfiguration("akka", AkkaAgentConfigurationJapi.apply());
        this.agentConfiguration = configuration.agent();
        this.counterInterface = createCounterInterface(configuration.common());
    }

    /**
     * Injects the new {@code AkkaAgentConfiguration} instance.
     *
     * @param agentConfiguration the new configuration
     */
    synchronized final void setAgentConfiguration(AkkaAgentConfiguration agentConfiguration) {
        this.agentConfiguration = agentConfiguration;
    }

    /**
     * decide whether to include this ActorCell in our measurements
     * */
    private boolean includeActorPath(final PathAndClass pathAndClass) {
        // do not monitor our own output code
        if (pathAndClass.actorClassName().isDefined()) {
            if (pathAndClass.actorClassName().get().startsWith("org.eigengo.monitor.output")) return false;
        }

        // skip if not included
        if (!this.agentConfiguration.included().accept(pathAndClass)) return false;
        // skip if excluded
        if (this.agentConfiguration.excluded().accept(pathAndClass)) return false;

        // skip system actor checks if we wish to monitor them
        if (this.agentConfiguration.includeSystemAgents()) return true;

        String userOrSystem = pathAndClass.actorPath().getElements().iterator().next();
        return "user".equals(userOrSystem);
    }

    /**
     * get the sample rate for an actor
     * */
    private int getSampleRate(final PathAndClass pathAndClass) {
        return this.agentConfiguration.sampling().getRate(pathAndClass);
    }

    /**
     * decide whether to sample an actor on a particular occasion
     *
     * @param pathAndClass
     * @return true if we should sample this actor, otherwise false.
     */
    private final boolean sampleMessage(final PathAndClass pathAndClass) {
        int sampleRate = getSampleRate(pathAndClass);
        if (sampleRate == 1) return true;

        this.samplingCounters.putIfAbsent(pathAndClass.actorClassName(), new AtomicLong(0));
        long timesSeenSoFar = this.samplingCounters.get(pathAndClass.actorClassName()).incrementAndGet();
        return (timesSeenSoFar % sampleRate == 1); // == 1 to log first value (incrementAndGet returns updated value)
    }

    /**
     * get the tags for the cell
     * */
    private String[] getTags(final ActorPath actorPath, final Actor actor) {
        List<String> tags = new ArrayList<String>();

        // TODO: Improve detection of routed actors. This relies only on the naming :(.
        String lastPathElement = actorPath.elements().last();
        if (lastPathElement.startsWith("$")) {
            // this is routed actor.
            tags.add(actorPath.parent().toString());
            if (this.agentConfiguration.includeRoutees()) tags.add(actorPath.toString());
        } else {
            // there is no supervisor
            tags.add(actorPath.toString());
        }
        if (actor != null) {
            tags.add(String.format("akka:%s.%s", actor.context().system().name(), actor.getClass().getCanonicalName()));
        }

        return tags.toArray(new String[tags.size()]);
    }

    /**
     * returns the canonical name of the actor type associated with an ActorCell
     * */
    private String uncheckedActorNameFrom(final ActorCell actorCell) {
        return uncheckedActorNameFrom(actorCell.props());
    }

    /**
     * returns the canonical name of the actor type associated with a Props instance
     * */
    private String uncheckedActorNameFrom(final Props props) {
        return props.actorClass().getCanonicalName();
    }

    /**
     * Advises the {@code ActorCell.receiveMessage(message: Object): Unit}
     * We proceed with the pointcut if the actor is to be included in the monitoring *and* this is
     * the 'multiple-of-n'th time we've seen a message for an actor with a sample rate of n.
     *
     * Currently, we sample queue size, the fact that the message is delivered, the simple name of the class of the
     * message, and the time taken to complete the actor's reactive action.
     *
     * @param actorCell the ActorCell where the actor that receives the message "lives"
     * @param msg the incoming message
     */
    Object around(ActorCell actorCell, Object msg) : Pointcuts.actorCellReceiveMessage(actorCell, msg) {

        final ActorPath actorPath = actorCell.self().path();
        final PathAndClass pathAndClass = new PathAndClass(actorPath, Option.apply(uncheckedActorNameFrom(actorCell)));
        if (!includeActorPath(pathAndClass) || !sampleMessage(pathAndClass)) return proceed(actorCell, msg);

        int samplingRate = getSampleRate(pathAndClass);

        // we tag by actor name
        final String[] tags = getTags(actorPath, actorCell.actor());

        // record the queue size
        this.counterInterface.recordGaugeValue("akka.queue.size", actorCell.numberOfMessages(), tags);
        // record the message, general and specific
        this.counterInterface.incrementCounter("akka.actor.delivered", samplingRate, tags);
        this.counterInterface.incrementCounter("akka.actor.delivered." + msg.getClass().getSimpleName(), samplingRate, tags);

        // measure the time. we're using the ``nanoTime`` call to access the high-precision timer.
        // since we're not really interested in wall time, but just some increasing measure of
        // elapsed time
        Object result = null;
        final long start = System.nanoTime();
        // result will always be ``null``, because target returns ``Unit``
        result = proceed(actorCell, msg);
        // ns or µs is too fine. ms will do for now.
        final long duration = (System.nanoTime() - start) / 1000000;

        // record the actor duration
        this.counterInterface.recordExecutionTime("akka.actor.duration", (int)duration, tags);

        // return null would do the trick, but we want to be _proper_.
        return result;
    }

    /**
     * Advises the {@code ActorCell.handleInvokeFailure(_, failure: Throwable): Unit}
     *
     * @param actorCell the ActorCell where the error spreads from
     * @param failure the exception that escaped from the {@code receive} method
     */
    before(ActorCell actorCell, Throwable failure) : Pointcuts.actorCellHandleInvokeFailure(actorCell, failure) {
        // record the error, general and specific
        String[] tags = getTags(actorCell.self().path(), actorCell.actor());
        this.counterInterface.incrementCounter("akka.actor.error", tags);
        this.counterInterface.incrementCounter(String.format("akka.actor.error.%s", failure.getMessage()), tags);
    }

    /**
     * Advises the {@code EventStream.publish(event: Any): Unit}
     *
     * @param event the received event
     */
    before(Object event) : Pointcuts.eventStreamPublish(event) {
        if (event instanceof UnhandledMessage) {
            UnhandledMessage unhandledMessage = (UnhandledMessage)event;
            String[] tags = getTags(unhandledMessage.recipient().path(), null);
            this.counterInterface.incrementCounter("akka.actor.undelivered", tags);
            this.counterInterface.incrementCounter("akka.actor.undelivered." + unhandledMessage.getMessage().getClass().getSimpleName(), tags);
        }
    }

    /**
     * Advises the {@code actorOf} method of {@code ActorRefFactory} implementations
     *
     * @param props the {@code Props} instance used in the call
     * @param actor the {@code ActorRef} returned from the call
     */
    after(Props props) returning (ActorRef actor): Pointcuts.anyActorOf(props) {
        recordActorCreation(props, actor);
    }

    /**
     * method containing the recording logic for advising actor creation
     * */
    private void recordActorCreation(Props props, ActorRef actor) {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(props);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // increment and get the current number of actors of this type (if the value was 0, then this returns 1 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).incrementAndGet();

        // record the current number of actors of this type
        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

    /**
     * Advises the {@code LocalActorRef.stop} method
     *
     * @param actorCell the {@code ActorCell} of the actor being stopped
     */
    after(ActorCell actorCell) : Pointcuts.actorCellInternalStop(actorCell) {
        if (!includeActorPath(new PathAndClass(actorCell.self().path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(actorCell);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // decrement and get the current number of actors of this type (if the value was 1, then this returns 0 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).decrementAndGet();

        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

}


organized imports

organized imports

package de.cosmocode.palava.security.aspectj;

import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;

abstract aspect AbstractSecurityAspect {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractSecurityAspect.class);

    private Provider<Subject> provider;

    @Inject
    void setProvider(Provider<Subject> provider) {
        this.provider = Preconditions.checkNotNull(provider, "Provider");
    }

    protected Subject getCurrentUser() {
        return provider.get();
    }

    pointcut createInjector(): call(Injector Guice.createInjector(..));

    after() returning (Injector injector): createInjector() {
        LOG.trace("Injecting members on {}", this);
        if (provider == null) {
            injector.injectMembers(this);
        } else {
            throw new IllegalStateException("An injector has already been created");
        }
    }

}

package de.cosmocode.palava.security.aspectj;

import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Guice;
import com.google.inject.Provider;

abstract aspect AbstractSecurityAspect {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractSecurityAspect.class);

    private Provider<Subject> provider;

    @Inject
    void setProvider(Provider<Subject> provider) {
        this.provider = Preconditions.checkNotNull(provider, "Provider");
    }

    protected Subject getCurrentUser() {
        return provider.get();
    }

    pointcut createInjector(): call(Injector Guice.createInjector(..));

    after() returning (Injector injector): createInjector() {
        LOG.trace("Injecting members on {}", this);
        if (provider == null) {
            injector.injectMembers(this);
        } else {
            throw new IllegalStateException("An injector has already been created");
        }
    }

}


comment formatting

comment formatting

/*
 * Copyright (c) 2013 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.eigengo.monitor.agent.akka;

import akka.actor.*;
import org.eigengo.monitor.agent.AgentConfiguration;
import org.eigengo.monitor.output.CounterInterface;
import scala.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Contains advices for monitoring behaviour of an actor; typically imprisoned in an {@code ActorCell}.
 */
public aspect ActorCellMonitoringAspect extends AbstractMonitoringAspect issingleton() {
    private AkkaAgentConfiguration agentConfiguration;
    private final CounterInterface counterInterface;
    private final Option<String> noActorClazz = Option.empty();
    private final ConcurrentHashMap<Option<String>, AtomicLong> samplingCounters  = new ConcurrentHashMap<Option<String>, AtomicLong>();
    private final ConcurrentHashMap<Option<String>, AtomicInteger> numberOfActors = new ConcurrentHashMap<Option<String>, AtomicInteger>();

    /**
     * Constructs this aspect
     */
    public ActorCellMonitoringAspect() {
        AgentConfiguration<AkkaAgentConfiguration> configuration = getAgentConfiguration("akka", AkkaAgentConfigurationJapi.apply());
        this.agentConfiguration = configuration.agent();
        this.counterInterface = createCounterInterface(configuration.common());
    }

    /**
     * Injects the new {@code AkkaAgentConfiguration} instance.
     *
     * @param agentConfiguration the new configuration
     */
    synchronized final void setAgentConfiguration(AkkaAgentConfiguration agentConfiguration) {
        this.agentConfiguration = agentConfiguration;
    }

    /**
     * decide whether to include this ActorCell in our measurements
     * */
    private boolean includeActorPath(final PathAndClass pathAndClass) {
        if (!this.agentConfiguration.incuded().accept(pathAndClass)) return false;
        if (this.agentConfiguration.excluded().accept(pathAndClass)) return false;

        if (this.agentConfiguration.includeSystemAgents()) return true;

        String userOrSystem = pathAndClass.actorPath().getElements().iterator().next();
        return "user".equals(userOrSystem);
    }

    /**
     * get the sample rate for an actor
     * */
    private int getSampleRate(final PathAndClass pathAndClass) {
        return this.agentConfiguration.sampling().getRate(pathAndClass);
    }

    /**
     * decide whether to sample an actor on a particular occasion
     *
     * @param pathAndClass
     * @return true if we should sample this actor, otherwise false.
     */
    private final boolean sampleMessage(final PathAndClass pathAndClass) {
        int sampleRate = getSampleRate(pathAndClass);
        if (sampleRate == 1) return true;

        this.samplingCounters.putIfAbsent(pathAndClass.actorClassName(), new AtomicLong(0));
        long timesSeenSoFar = this.samplingCounters.get(pathAndClass.actorClassName()).incrementAndGet();
        return (timesSeenSoFar % sampleRate == 1); // == 1 to log first value (incrementAndGet returns updated value)
    }

    /**
     * get the tags for the cell
     * */
    private String[] getTags(final ActorPath actorPath, final Actor actor) {
        List<String> tags = new ArrayList<String>();

        // TODO: Improve detection of routed actors. This relies only on the naming :(.
        String lastPathElement = actorPath.elements().last();
        if (lastPathElement.startsWith("$")) {
            // this is routed actor.
            tags.add(actorPath.parent().toString());
            if (this.agentConfiguration.includeRoutees()) tags.add(actorPath.toString());
        } else {
            // there is no supervisor
            tags.add(actorPath.toString());
        }
        if (actor != null) {
            tags.add(String.format("akka:%s.%s", actor.context().system().name(), actor.getClass().getCanonicalName()));
        }

        return tags.toArray(new String[tags.size()]);
    }

    /**
     * returns the canonical name of the actor type associated with an ActorCell
     * */
    private String uncheckedActorNameFrom(final ActorCell actorCell) {
        return uncheckedActorNameFrom(actorCell.props());
    }

    /**
     * returns the canonical name of the actor type associated with a Props instance
     * */
    private String uncheckedActorNameFrom(final Props props) {
        return props.actorClass().getCanonicalName();
    }

    /**
     * Advises the {@code ActorCell.receiveMessage(message: Object): Unit}
     * We proceed with the pointcut if the actor is to be included in the monitoring *and* this is
     * the 'multiple-of-n'th time we've seen a message for an actor with a sample rate of n.
     *
     * Currently, we sample queue size, the fact that the message is delivered, the simple name of the class of the
     * message, and the time taken to complete the actor's reactive action.
     *
     * @param actorCell the ActorCell where the actor that receives the message "lives"
     * @param msg the incoming message
     */
    Object around(ActorCell actorCell, Object msg) : Pointcuts.actorCellReceiveMessage(actorCell, msg) {
        final ActorPath actorPath = actorCell.self().path();
        final PathAndClass pathAndClass = new PathAndClass(actorPath, Option.apply(uncheckedActorNameFrom(actorCell)));
        if (!includeActorPath(pathAndClass) || !sampleMessage(pathAndClass)) return proceed(actorCell, msg);

        int samplingRate = getSampleRate(pathAndClass);

        // we tag by actor name
        final String[] tags = getTags(actorPath, actorCell.actor());

        // record the queue size
        this.counterInterface.recordGaugeValue("akka.queue.size", actorCell.numberOfMessages(), tags);
        // record the message, general and specific
        this.counterInterface.incrementCounter("akka.actor.delivered", samplingRate, tags);
        this.counterInterface.incrementCounter("akka.actor.delivered." + msg.getClass().getSimpleName(), samplingRate, tags);

        // measure the time. we're using the ``nanoTime`` call to access the high-precision timer.
        // since we're not really interested in wall time, but just some increasing measure of
        // elapsed time
        Object result = null;
        final long start = System.nanoTime();
        // result will always be ``null``, because target returns ``Unit``
        result = proceed(actorCell, msg);
        // ns or µs is too fine. ms will do for now.
        final long duration = (System.nanoTime() - start) / 1000000;

        // record the actor duration
        this.counterInterface.recordExecutionTime("akka.actor.duration", (int)duration, tags);

        // return null would do the trick, but we want to be _proper_.
        return result;
    }

    /**
     * Advises the {@code ActorCell.handleInvokeFailure(_, failure: Throwable): Unit}
     *
     * @param actorCell the ActorCell where the error spreads from
     * @param failure the exception that escaped from the {@code receive} method
     */
    before(ActorCell actorCell, Throwable failure) : Pointcuts.actorCellHandleInvokeFailure(actorCell, failure) {
        // record the error, general and specific
        String[] tags = getTags(actorCell.self().path(), actorCell.actor());
        this.counterInterface.incrementCounter("akka.actor.error", tags);
        this.counterInterface.incrementCounter(String.format("akka.actor.error.%s", failure.getMessage()), tags);
    }

    /**
     * Advises the {@code EventStream.publish(event: Any): Unit}
     *
     * @param event the received event
     */
    before(Object event) : Pointcuts.eventStreamPublish(event) {
        if (event instanceof UnhandledMessage) {
            UnhandledMessage unhandledMessage = (UnhandledMessage)event;
            String[] tags = getTags(unhandledMessage.recipient().path(), null);
            this.counterInterface.incrementCounter("akka.actor.undelivered", tags);
            this.counterInterface.incrementCounter("akka.actor.undelivered." + unhandledMessage.getMessage().getClass().getSimpleName(), tags);
        }
    }

    /**
     * Advises the {@code actorOf} method of {@code ActorCell} and {@code ActorSystem}
     *
     * @param props the {@code Props} instance used in the call
     * @param actor the {@code ActorRef} returned from the call
     */
    after(Props props) returning (ActorRef actor): Pointcuts.anyActorOf(props) {
        recordActorCreation(props, actor);
    }
    /**
     * Advises the {@code actorOf} method of {@code ActorCell} and {@code ActorSystem} when actor is named in construction
     *
     * @param props the {@code Props} instance used in the call
     * @param actorName the {@code String} used to name the actor at creation site
     * @param actor the {@code ActorRef} returned from the call
     */
    after(Props props, String actorName) returning (ActorRef actor): Pointcuts.namedActorOf(props, actorName) {
        recordActorCreation(props, actor);
    }

    /**
     * method containing the recording logic for advising actor creation
     * */
    private void recordActorCreation(Props props, ActorRef actor) {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(props);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // increment and get the current number of actors of this type (if the value was 0, then this returns 1 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).incrementAndGet();

        // record the current number of actors of this type
        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

    /**
     * Advises the {@code LocalActorRef.stop} method
     *
     * @param actorCell the {@code ActorCell} of the actor being stopped
     */
    after(ActorCell actorCell) : Pointcuts.actorCellInternalStop(actorCell) {
        if (!includeActorPath(new PathAndClass(actorCell.self().path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(actorCell);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // decrement and get the current number of actors of this type (if the value was 1, then this returns 0 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).decrementAndGet();

        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

}

/*
 * Copyright (c) 2013 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.eigengo.monitor.agent.akka;

import akka.actor.*;
import org.eigengo.monitor.agent.AgentConfiguration;
import org.eigengo.monitor.output.CounterInterface;
import scala.Option;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Contains advices for monitoring behaviour of an actor; typically imprisoned in an {@code ActorCell}.
 */
public aspect ActorCellMonitoringAspect extends AbstractMonitoringAspect issingleton() {
    private AkkaAgentConfiguration agentConfiguration;
    private final CounterInterface counterInterface;
    private final Option<String> noActorClazz = Option.empty();
    private final ConcurrentHashMap<Option<String>, AtomicLong> samplingCounters  = new ConcurrentHashMap<Option<String>, AtomicLong>();
    private final ConcurrentHashMap<Option<String>, AtomicInteger> numberOfActors = new ConcurrentHashMap<Option<String>, AtomicInteger>();

    /**
     * Constructs this aspect
     */
    public ActorCellMonitoringAspect() {
        AgentConfiguration<AkkaAgentConfiguration> configuration = getAgentConfiguration("akka", AkkaAgentConfigurationJapi.apply());
        this.agentConfiguration = configuration.agent();
        this.counterInterface = createCounterInterface(configuration.common());
    }

    /**
     * Injects the new {@code AkkaAgentConfiguration} instance.
     *
     * @param agentConfiguration the new configuration
     */
    synchronized final void setAgentConfiguration(AkkaAgentConfiguration agentConfiguration) {
        this.agentConfiguration = agentConfiguration;
    }

    // decide whether to include this ActorCell in our measurements
    private boolean includeActorPath(final PathAndClass pathAndClass) {
        if (!this.agentConfiguration.incuded().accept(pathAndClass)) return false;
        if (this.agentConfiguration.excluded().accept(pathAndClass)) return false;

        if (this.agentConfiguration.includeSystemAgents()) return true;

        String userOrSystem = pathAndClass.actorPath().getElements().iterator().next();
        return "user".equals(userOrSystem);
    }

    // get the sample rate for an actor
    private int getSampleRate(final PathAndClass pathAndClass) {
        return this.agentConfiguration.sampling().getRate(pathAndClass);
    }

    // decide whether to sample an actor on a particular occasion
    private final boolean sampleMessage(final PathAndClass pathAndClass) {
        int sampleRate = getSampleRate(pathAndClass);
        if (sampleRate == 1) return true;

        this.samplingCounters.putIfAbsent(pathAndClass.actorClassName(), new AtomicLong(0));
        long timesSeenSoFar = this.samplingCounters.get(pathAndClass.actorClassName()).incrementAndGet();
        return (timesSeenSoFar % sampleRate == 1); // == 1 to log first value (incrementAndGet returns updated value)
    }

    // get the tags for the cell
    private String[] getTags(final ActorPath actorPath, final Actor actor) {
        List<String> tags = new ArrayList<String>();

        // TODO: Improve detection of routed actors. This relies only on the naming :(.
        String lastPathElement = actorPath.elements().last();
        if (lastPathElement.startsWith("$")) {
            // this is routed actor.
            tags.add(actorPath.parent().toString());
            if (this.agentConfiguration.includeRoutees()) tags.add(actorPath.toString());
        } else {
            // there is no supervisor
            tags.add(actorPath.toString());
        }
        if (actor != null) {
            tags.add(String.format("akka:%s.%s", actor.context().system().name(), actor.getClass().getCanonicalName()));
        }

        return tags.toArray(new String[tags.size()]);
    }

    // returns the canonical name of the actor type associated with an ActorCell
    private String uncheckedActorNameFrom(final ActorCell actorCell) {
        return uncheckedActorNameFrom(actorCell.props());
    }

    // returns the canonical name of the actor type associated with a Props instance
    private String uncheckedActorNameFrom(final Props props) {
        return props.actorClass().getCanonicalName();
    }

    /**
     * Advises the {@code ActorCell.receiveMessage(message: Object): Unit}
     * We proceed with the pointcut if the actor is to be included in the monitoring *and* this is
     * the 'multiple-of-n'th time we've seen a message for an actor with a sample rate of n.
     *
     * Currently, we sample queue size, the fact that the message is delivered, the simple name of the class of the
     * message, and the time taken to complete the actor's reactive action.
     *
     * @param actorCell the ActorCell where the actor that receives the message "lives"
     * @param msg the incoming message
     */
    Object around(ActorCell actorCell, Object msg) : Pointcuts.actorCellReceiveMessage(actorCell, msg) {
        final ActorPath actorPath = actorCell.self().path();
        final PathAndClass pathAndClass = new PathAndClass(actorPath, Option.apply(uncheckedActorNameFrom(actorCell)));
        if (!includeActorPath(pathAndClass) || !sampleMessage(pathAndClass)) return proceed(actorCell, msg);

        int samplingRate = getSampleRate(pathAndClass);

        // we tag by actor name
        final String[] tags = getTags(actorPath, actorCell.actor());

        // record the queue size
        this.counterInterface.recordGaugeValue("akka.queue.size", actorCell.numberOfMessages(), tags);
        // record the message, general and specific
        this.counterInterface.incrementCounter("akka.actor.delivered", samplingRate, tags);
        this.counterInterface.incrementCounter("akka.actor.delivered." + msg.getClass().getSimpleName(), samplingRate, tags);

        // measure the time. we're using the ``nanoTime`` call to access the high-precision timer.
        // since we're not really interested in wall time, but just some increasing measure of
        // elapsed time
        Object result = null;
        final long start = System.nanoTime();
        // result will always be ``null``, because target returns ``Unit``
        result = proceed(actorCell, msg);
        // ns or µs is too fine. ms will do for now.
        final long duration = (System.nanoTime() - start) / 1000000;

        // record the actor duration
        this.counterInterface.recordExecutionTime("akka.actor.duration", (int)duration, tags);

        // return null would do the trick, but we want to be _proper_.
        return result;
    }

    /**
     * Advises the {@code ActorCell.handleInvokeFailure(_, failure: Throwable): Unit}
     *
     * @param actorCell the ActorCell where the error spreads from
     * @param failure the exception that escaped from the {@code receive} method
     */
    before(ActorCell actorCell, Throwable failure) : Pointcuts.actorCellHandleInvokeFailure(actorCell, failure) {
        // record the error, general and specific
        String[] tags = getTags(actorCell.self().path(), actorCell.actor());
        this.counterInterface.incrementCounter("akka.actor.error", tags);
        this.counterInterface.incrementCounter(String.format("akka.actor.error.%s", failure.getMessage()), tags);
    }

    /**
     * Advises the {@code EventStream.publish(event: Any): Unit}
     *
     * @param event the received event
     */
    before(Object event) : Pointcuts.eventStreamPublish(event) {
        if (event instanceof UnhandledMessage) {
            UnhandledMessage unhandledMessage = (UnhandledMessage)event;
            String[] tags = getTags(unhandledMessage.recipient().path(), null);
            this.counterInterface.incrementCounter("akka.actor.undelivered", tags);
            this.counterInterface.incrementCounter("akka.actor.undelivered." + unhandledMessage.getMessage().getClass().getSimpleName(), tags);
        }
    }

    /**
     * Advises the {@code actorOf} method of {@code ActorCell} and {@code ActorSystem}
     *
     * @param props the {@code Props} instance used in the call
     * @param actor the {@code ActorRef} returned from the call
     */
    after(Props props) returning (ActorRef actor): Pointcuts.anyActorOf(props) {
        recordActorCreation(props, actor);
    }
    /**
     * Advises the {@code actorOf} method of {@code ActorCell} and {@code ActorSystem} when actor is named in construction
     *
     * @param props the {@code Props} instance used in the call
     * @param actorName the {@code String} used to name the actor at creation site
     * @param actor the {@code ActorRef} returned from the call
     */
    after(Props props, String actorName) returning (ActorRef actor): Pointcuts.namedActorOf(props, actorName) {
        recordActorCreation(props, actor);
    }

    // method containing the recording logic for advising actor creation
    private void recordActorCreation(Props props, ActorRef actor) {
        if (!includeActorPath(new PathAndClass(actor.path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(props);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // increment and get the current number of actors of this type (if the value was 0, then this returns 1 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).incrementAndGet();

        // record the current number of actors of this type
        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

    /**
     * Advises the {@code LocalActorRef.stop} method
     *
     *
     * @param actorCell the {@code ActorCell} of the actor being stopped
     */
    after(ActorCell actorCell) : Pointcuts.actorCellInternalStop(actorCell) {
        if (!includeActorPath(new PathAndClass(actorCell.self().path(), this.noActorClazz))) return;
        final String uncheckedClassName = uncheckedActorNameFrom(actorCell);
        final Option<String> className = Option.apply(uncheckedClassName);

        this.numberOfActors.putIfAbsent(className, new AtomicInteger(0));
        // decrement and get the current number of actors of this type (if the value was 1, then this returns 0 -- which is correct)
        final int currentNumberOfActors = this.numberOfActors.get(className).decrementAndGet();

        this.counterInterface.recordGaugeValue("akka.actor.count", currentNumberOfActors, uncheckedClassName);
    }

}


perform precheck about injection

perform precheck about injection

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.cosmocode.palava.jta;

import javax.transaction.NotSupportedException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;

public abstract aspect AbstractUserTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractUserTransactionAspect.class);

    private Provider<UserTransaction> provider;

    @Inject
    void setProvider(Provider<UserTransaction> provider) {
        this.provider = Preconditions.checkNotNull(provider, "Provider");
    }

    protected abstract pointcut transactional();

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        Preconditions.checkNotNull(provider, "Provider not injected yet");
        final UserTransaction tx = provider.get();
        LOG.trace("Using transaction {}", tx);

        try {
            LOG.trace("Status of transaction: {}", tx.getStatus());
        } catch (SystemException e) {
            throw new IllegalStateException(e);
        }

        final boolean local;

        try {
            local = tx.getStatus() == Status.STATUS_NO_TRANSACTION;
        } catch (SystemException e) {
            throw new IllegalStateException(e);
        }

        if (local) {
            LOG.debug("Beginning automatic transaction {}", tx);
            try {
                tx.begin();
            } catch (NotSupportedException e) {
                throw new IllegalStateException(e);
            } catch (SystemException e) {
                throw new IllegalStateException(e);
            }
        } else {
            LOG.trace("Transaction {} already active", tx);
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (Exception e) {
            try {
                if (local &&
                    (tx.getStatus() == Status.STATUS_ACTIVE || tx.getStatus() == Status.STATUS_MARKED_ROLLBACK)) {
                    LOG.info("Rolling back local/active transaction {}", tx);
                    tx.rollback();
                } else if (tx.getStatus() != Status.STATUS_ROLLEDBACK || tx.getStatus() != Status.STATUS_ROLLING_BACK) {
                    LOG.debug("Setting transaction {} as rollback only", tx);
                    tx.setRollbackOnly();
                }
            } catch (Exception inner) {
                LOG.error("Rollback failed", inner);
            }
            throw new IllegalStateException(e);
        }

        final int status;

        try {
            status = tx.getStatus();
        } catch (SystemException e) {
            throw new IllegalStateException(e);
        }

        if (local) {
            if (status == Status.STATUS_MARKED_ROLLBACK) {
                try {
                    LOG.debug("Rolling back marked transaction {}", tx);
                    tx.rollback();
                } catch (SystemException e) {
                    throw new IllegalStateException(e);
                }
            } else {
                try {
                    tx.commit();
                    LOG.debug("Committed automatic transaction {}", tx);
                } catch (Exception e) {
                    try {
                        LOG.info("Rolling back transaction {}", tx);
                        tx.rollback();
                    } catch (Exception inner) {
                        LOG.error("Rollback failed", inner);
                    }
                    throw new IllegalStateException(e);
                }
            }
        }

        return returnValue;
    }

}

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.cosmocode.palava.jta;

import javax.transaction.NotSupportedException;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;

public abstract aspect AbstractUserTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractUserTransactionAspect.class);

    private Provider<UserTransaction> provider;

    @Inject
    void setProvider(Provider<UserTransaction> provider) {
        this.provider = Preconditions.checkNotNull(provider, "Provider");
    }

    protected abstract pointcut transactional();

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final UserTransaction tx = provider.get();
        LOG.trace("Using transaction {}", tx);

        try {
            LOG.trace("Status of transaction: {}", tx.getStatus());
        } catch (SystemException e) {
            throw new IllegalStateException(e);
        }

        final boolean local;

        try {
            local = tx.getStatus() == Status.STATUS_NO_TRANSACTION;
        } catch (SystemException e) {
            throw new IllegalStateException(e);
        }

        if (local) {
            LOG.debug("Beginning automatic transaction {}", tx);
            try {
                tx.begin();
            } catch (NotSupportedException e) {
                throw new IllegalStateException(e);
            } catch (SystemException e) {
                throw new IllegalStateException(e);
            }
        } else {
            LOG.trace("Transaction {} already active", tx);
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (Exception e) {
            try {
                if (local &&
                    (tx.getStatus() == Status.STATUS_ACTIVE || tx.getStatus() == Status.STATUS_MARKED_ROLLBACK)) {
                    LOG.info("Rolling back local/active transaction {}", tx);
                    tx.rollback();
                } else if (tx.getStatus() != Status.STATUS_ROLLEDBACK || tx.getStatus() != Status.STATUS_ROLLING_BACK) {
                    LOG.debug("Setting transaction {} as rollback only", tx);
                    tx.setRollbackOnly();
                }
            } catch (Exception inner) {
                LOG.error("Rollback failed", inner);
            }
            throw new IllegalStateException(e);
        }

        final int status;

        try {
            status = tx.getStatus();
        } catch (SystemException e) {
            throw new IllegalStateException(e);
        }

        if (local) {
            if (status == Status.STATUS_MARKED_ROLLBACK) {
                try {
                    LOG.debug("Rolling back marked transaction {}", tx);
                    tx.rollback();
                } catch (SystemException e) {
                    throw new IllegalStateException(e);
                }
            } else {
                try {
                    tx.commit();
                    LOG.debug("Committed automatic transaction {}", tx);
                } catch (Exception e) {
                    try {
                        LOG.info("Rolling back transaction {}", tx);
                        tx.rollback();
                    } catch (Exception inner) {
                        LOG.error("Rollback failed", inner);
                    }
                    throw new IllegalStateException(e);
                }
            }
        }

        return returnValue;
    }

}


do not log error, someone else is responsible for this

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.cosmocode.palava.jpa.aspectj;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;
import de.cosmocode.palava.jpa.Transactional;

public final aspect EntityTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(EntityTransactionAspect.class);

    private Provider<EntityManager> currentManager;

    @Inject
    public void setProvider(Provider<EntityManager> manager) {
        this.currentManager = Preconditions.checkNotNull(manager, "Manager");
    }

    pointcut transactional(): execution(@Transactional * *.*(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final EntityManager manager = currentManager.get();
        LOG.trace("Retrieved entitymanager {}", manager);
        final EntityTransaction tx = manager.getTransaction();
        LOG.trace("Using transaction {}", tx);
        final boolean localTx = !tx.isActive();

        if (localTx) {
            LOG.trace("Beginning automatic transaction");
            tx.begin();
        } else {
            LOG.trace("Transaction already active");
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (RuntimeException e) {
            LOG.debug("Exception inside automatic transaction context; rolling back", e);
            tx.rollback();
            throw e;
        }

        if (localTx && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.debug("Transaction was marked as rollback only. Rolling back...");
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction");
                } catch (PersistenceException e) {
                    LOG.debug("Commit in automatic transaction context failed", e);
                    if (tx.isActive()) {
                        LOG.debug("Rolling back {}", tx);
                        tx.rollback();
                    } else {
                        LOG.debug("Can't roll back inactive transaction {}", tx);
                    }
                    throw e;
                }
            }
        }

        return returnValue;
    }

}

/**
 * Copyright 2010 CosmoCode GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package de.cosmocode.palava.jpa.aspectj;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;
import com.google.inject.Provider;

import de.cosmocode.palava.core.aop.AbstractPalavaAspect;
import de.cosmocode.palava.jpa.Transactional;

public final aspect EntityTransactionAspect extends AbstractPalavaAspect issingleton() {

    private static final Logger LOG = LoggerFactory.getLogger(EntityTransactionAspect.class);

    private Provider<EntityManager> currentManager;

    @Inject
    public void setProvider(Provider<EntityManager> manager) {
        this.currentManager = Preconditions.checkNotNull(manager, "Manager");
    }

    pointcut transactional(): execution(@Transactional * *.*(..));

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final EntityManager manager = currentManager.get();
        LOG.trace("Retrieved entitymanager {}", manager);
        final EntityTransaction tx = manager.getTransaction();
        LOG.trace("Using transaction {}", tx);
        final boolean localTx = !tx.isActive();

        if (localTx) {
            LOG.trace("Beginning automatic transaction");
            tx.begin();
        } else {
            LOG.trace("Transaction already active");
        }

        final Object returnValue;

        try {
            returnValue = proceed();
        } catch (RuntimeException e) {
            LOG.debug("Exception inside automatic transaction context; rolling back", e);
            tx.rollback();
            throw e;
        }

        if (localTx && tx.isActive()) {
            if (tx.getRollbackOnly()) {
                LOG.debug("Transaction was marked as rollback only. Rolling back...");
                tx.rollback();
            } else {
                try {
                    tx.commit();
                    LOG.trace("Committed automatic transaction");
                } catch (PersistenceException e) {
                    LOG.error("Commit in automatic transaction context failed", e);
                    if (tx.isActive()) {
                        LOG.debug("Rolling back {}", tx);
                        tx.rollback();
                    } else {
                        LOG.debug("Can't roll back inactive transaction {}", tx);
                    }
                    throw e;
                }
            }
        }

        return returnValue;
    }

}


Corrected pointcut and factored out recursive call.

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

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

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

import java.util.ArrayList;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.hierarchy.ChangeCollector;

import scala.tools.eclipse.contribution.weaving.jdt.IScalaElement;

@SuppressWarnings("restriction")
public privileged aspect HierarchyAspect {

  pointcut getAllTypesFromElement(ChangeCollector cc, IJavaElement element, ArrayList allTypes) :
    execution(void ChangeCollector.getAllTypesFromElement(IJavaElement, ArrayList)) &&
    args(element, allTypes) &&
    target(cc);

  void around(ChangeCollector cc, IJavaElement element, ArrayList allTypes) throws JavaModelException :
    getAllTypesFromElement(cc, element, allTypes) {
    getAllTypesFromElement0(cc, element, allTypes);
  }

  public void getAllTypesFromElement0(ChangeCollector cc, IJavaElement element, ArrayList allTypes) throws JavaModelException {
    switch (element.getElementType()) {
      case IJavaElement.COMPILATION_UNIT:
        IType[] types = ((ICompilationUnit)element).getTypes();
        for (int i = 0, length = types.length; i < length; i++) {
          IType type = types[i];
          allTypes.add(type);
          getAllTypesFromElement0(cc, type, allTypes);
        }
        break;
      case IJavaElement.TYPE:
        types = ((IType)element).getTypes();
        for (int i = 0, length = types.length; i < length; i++) {
          IType type = types[i];
          allTypes.add(type);
          getAllTypesFromElement0(cc, type, allTypes);
        }
        break;
      case IJavaElement.INITIALIZER:
      case IJavaElement.FIELD:
      case IJavaElement.METHOD:
        IJavaElement[] children = ((IMember)element).getChildren();
        for (int i = 0, length = children.length; i < length; i++) {
          IJavaElement child = children[i];
          if (child instanceof IType) {
            IType type = (IType)child;
            allTypes.add(type);
            getAllTypesFromElement0(cc, type, allTypes);
          } else if(child instanceof IScalaElement) {
            getAllTypesFromElement0(cc, child, allTypes);
          }
        }
        break;
    }
  }
}

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

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

import java.util.ArrayList;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.hierarchy.ChangeCollector;

import scala.tools.eclipse.contribution.weaving.jdt.IScalaElement;

@SuppressWarnings("restriction")
public privileged aspect HierarchyAspect {

  pointcut getAllTypesFromElement(ChangeCollector cc, JavaElement element, ArrayList allTypes) :
    execution(void ChangeCollector.getAllTypesFromElement(JavaElement, ArrayList)) &&
    args(element, allTypes) &&
    target(cc);

  void around(ChangeCollector cc, JavaElement element, ArrayList allTypes) throws JavaModelException :
    getAllTypesFromElement(cc, element, allTypes) {
    switch (element.getElementType()) {
      case IJavaElement.COMPILATION_UNIT:
        IType[] types = ((ICompilationUnit)element).getTypes();
        for (int i = 0, length = types.length; i < length; i++) {
          IType type = types[i];
          allTypes.add(type);
          cc.getAllTypesFromElement(type, allTypes);
        }
        break;
      case IJavaElement.TYPE:
        types = ((IType)element).getTypes();
        for (int i = 0, length = types.length; i < length; i++) {
          IType type = types[i];
          allTypes.add(type);
          cc.getAllTypesFromElement(type, allTypes);
        }
        break;
      case IJavaElement.INITIALIZER:
      case IJavaElement.FIELD:
      case IJavaElement.METHOD:
        IJavaElement[] children = ((IMember)element).getChildren();
        for (int i = 0, length = children.length; i < length; i++) {
          IJavaElement child = children[i];
          if (child instanceof IType) {
            IType type = (IType)child;
            allTypes.add(type);
            cc.getAllTypesFromElement(type, allTypes);
          } else if(child instanceof IScalaElement) {
            cc.getAllTypesFromElement(child, allTypes);
          }
        }
        break;
    }
  }
}


full ovirt-sync aspect for MigrateVm and AddDisk as well

	package org.ovirt.engine.core.bll;

	import java.util.*;

	import org.ovirt.engine.core.common.action.LockProperties;
	import org.ovirt.engine.core.common.action.LockProperties.Scope;
	import org.ovirt.engine.core.common.locks.LockingGroup;
	import org.ovirt.engine.core.bll.CommandBase;
	import org.ovirt.engine.core.utils.lock.EngineLock;
	import org.ovirt.engine.core.common.utils.Pair;
	import org.ovirt.engine.core.common.action.VdcReturnValueBase;
	import org.ovirt.engine.core.common.businessentities.IVdsAsyncCommand;
	import org.ovirt.engine.core.common.errors.EngineMessage;

	public privileged aspect Locks {

		void around(CommandBase command): execution(* endActionInTransactionScope()) && this(command) {
			try {
	          proceed(command);
	        }
	        finally {
	          command.freeLockEndAction();
	        }
	    }

	   boolean around(CommandBase command): execution(* internalCanDoAction()) && this(command) {
	        boolean result = false;
	        try {
	          result = proceed(command);
	        }
	        finally {
	          if (!result) {
	            command.freeLock();
	          }
	        }
	        return result;
	   }

	   void around(CommandBase command): execution(* freeLock()) && this(command) {
            if (command.context.getLock() != null) {
                command.getLockManager().releaseLock(command.context.getLock());
                command.log.info("Lock freed to object '{}'", command.context.getLock());
                command.context.withLock(null);
                // free other locks here to guarantee they will be freed only once
                command.freeCustomLocks();
            }
        }

	    VdcReturnValueBase around(CommandBase command): execution(* executeAction()) && this(command) {
	        try {
	          return proceed(command);
	        }
	        finally {
	          command.freeLockExecute();
	        }
	    }

	    boolean around(CommandBase commandBase): execution(* CommandBase.acquireLock()) && this(commandBase) {
	        LockProperties lockProperties = commandBase.getLockProperties();
	        boolean returnValue = true;
	        if (!Scope.None.equals(lockProperties.getScope())) {
	            commandBase.releaseLocksAtEndOfExecute = Scope.Execution.equals(lockProperties.getScope());
	            if (!lockProperties.isWait()) {
	                returnValue = commandBase.acquireLockInternal();
	            } else {
	                commandBase.acquireLockAndWait();
	            }
	        }
	        return returnValue;
	    }

		boolean around(CommandBase command): execution(* acquireLockInternal()) && this(command) {
	        // if commandLock is null then we acquire new lock, otherwise probably we got lock from caller command.
	        if (command.context.getLock() == null) {
	            EngineLock lock = command.buildLock();
	            if (lock != null) {
	                Pair<Boolean, Set<String>> lockAcquireResult = command.getLockManager().acquireLock(lock);
	                if (lockAcquireResult.getFirst()) {
	                    command.log.info("Lock Acquired to object '{}'", lock);
	                    command.context.withLock(lock);
	                } else {
	                    command.log.info("Failed to Acquire Lock to object '{}'", lock);
	                    command.getReturnValue().getCanDoActionMessages()
	                    .addAll(command.extractVariableDeclarations(lockAcquireResult.getSecond()));
	                    return false;
	                }
	            }
	        }
	        return true;
	   }

	   void around(CommandBase command): execution(* acquireLockAndWait()) && this(command) {
	        // if commandLock is null then we acquire new lock, otherwise probably we got lock from caller command.
	         if (command.context.getLock() == null) {
	            Map<String, Pair<String, String>> exclusiveLocks = command.getExclusiveLocks();
	             if (exclusiveLocks != null) {
	                 EngineLock lock = new EngineLock(exclusiveLocks, null);
	                 command.getLockManager().acquireLockWait(lock);
	                 command.context.withLock(lock);
	            }
	         }
	    }

		VdcReturnValueBase around(CommandBase commandBase): execution(* endAction()) && this(commandBase) {
	        VdcReturnValueBase result = null;
	        try {
	            commandBase.initiateLockEndAction();
	            result = proceed(commandBase);
	        } finally {
	            commandBase.freeLockEndAction();
	        }
	        return result;
	    }

	    private void CommandBase.freeLockExecute() {
	        if (releaseLocksAtEndOfExecute || !getSucceeded() ||
	                (noAsyncOperations() && !(this instanceof IVdsAsyncCommand))) {
	            freeLock();
	        }
	    }

		/**
	     * If the command has more than one task handler, we can reach the end action
	     * phase and in that phase execute the next task handler. In that case, we
	     * don't want to release the locks, so we ask whether we're not in execute state.
	     */
	    private void CommandBase.freeLockEndAction() {
	        if (getActionState() != CommandActionState.EXECUTE) {
	            freeLock();
	        }
	    }

		/**
	     * The following method should initiate a lock , in order to release it at endAction()
	     */
	    private void CommandBase.initiateLockEndAction() {
	        if (context.getLock() == null) {
	            LockProperties lockProperties = getLockProperties();
	            if (Scope.Command.equals(lockProperties.getScope())) {
	                context.withLock(buildLock());
	            }

	        }
	    }

	    private EngineLock CommandBase.buildLock() {
	        EngineLock lock = null;
	        Map<String, Pair<String, String>> exclusiveLocks = getExclusiveLocks();
	        Map<String, Pair<String, String>> sharedLocks = getSharedLocks();
	        if (exclusiveLocks != null || sharedLocks != null) {
	            lock = new EngineLock(exclusiveLocks, sharedLocks);
	        }
	        return lock;
	    }

		LockProperties around(LockProperties lockProperties, org.ovirt.engine.core.bll.ExportVmTemplateCommand command): execution(* applyLockProperties(..)) && args(lockProperties) && target(command) {
			return lockProperties.withScope(Scope.Execution);
		}

		Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.ExportVmTemplateCommand command): execution(* getExclusiveLocks()) && target(command) {
			Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

			locks.put(command.getVmTemplateId().toString(),
				LockMessagesMatchUtil.makeLockingPair(LockingGroup.REMOTE_TEMPLATE, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

			return locks;
		}

		Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.ExportVmTemplateCommand command): execution(* getSharedLocks()) && target(command) {
			Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

			locks.put(command.getVmTemplateId().toString(),
				LockMessagesMatchUtil.makeLockingPair(LockingGroup.TEMPLATE, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

			return locks;
		}

		LockProperties around(LockProperties lockProperties, org.ovirt.engine.core.bll.MigrateVmCommand command): execution(* applyLockProperties(..)) && args(lockProperties) && target(command) {
			return lockProperties.withScope(Scope.Command);
		}

		Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.MigrateVmCommand command): execution(* getExclusiveLocks()) && target(command) {
			Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

			locks.put(command.getVmId().toString(),
				LockMessagesMatchUtil.makeLockingPair(LockingGroup.VM, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

			return locks;
		}

		LockProperties around(LockProperties lockProperties, org.ovirt.engine.core.bll.AddDiskCommand command): execution(* applyLockProperties(..)) && args(lockProperties) && target(command) {
			return lockProperties.withScope(Scope.Execution);
		}

		Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.AddDiskCommand command): execution(* getExclusiveLocks()) && target(command) {
			Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

			locks.put(command.getVmId().toString(),
				LockMessagesMatchUtil.makeLockingPair(LockingGroup.VM_DISK_BOOT, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

			return locks;
		}

		Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.AddDiskCommand command): execution(* getSharedLocks()) && target(command) {
			Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

			locks.put(command.getVmId().toString(),
				LockMessagesMatchUtil.makeLockingPair(LockingGroup.VM, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

			return locks;
		}

	}

	package org.ovirt.engine.core.bll;

	import java.util.*;

	import org.ovirt.engine.core.common.action.LockProperties;
	import org.ovirt.engine.core.common.action.LockProperties.Scope;
	import org.ovirt.engine.core.common.locks.LockingGroup;
	import org.ovirt.engine.core.bll.CommandBase;
	import org.ovirt.engine.core.utils.lock.EngineLock;
	import org.ovirt.engine.core.common.utils.Pair;
	import org.ovirt.engine.core.common.action.VdcReturnValueBase;
	import org.ovirt.engine.core.common.businessentities.IVdsAsyncCommand;
	import org.ovirt.engine.core.common.errors.EngineMessage;

	public privileged aspect Locks {

		void around(CommandBase command): execution(* endActionInTransactionScope()) && this(command) {
			try {
	          proceed(command);
	        }
	        finally {
	          command.freeLockEndAction();
	        }
	    }

	   boolean around(CommandBase command): execution(* internalCanDoAction()) && this(command) {
	        boolean result = false;
	        try {
	          result = proceed(command);
	        }
	        finally {
	          if (!result) {
	            command.freeLock();
	          }
	        }
	        return result;
	   }

	   void around(CommandBase command): execution(* freeLock()) && this(command) {
            if (command.context.getLock() != null) {
                command.getLockManager().releaseLock(command.context.getLock());
                command.log.info("Lock freed to object '{}'", command.context.getLock());
                command.context.withLock(null);
                // free other locks here to guarantee they will be freed only once
                command.freeCustomLocks();
            }
        }

	    VdcReturnValueBase around(CommandBase command): execution(* executeAction()) && this(command) {
	        try {
	          return proceed(command);
	        }
	        finally {
	          command.freeLockExecute();
	        }
	    }

	    boolean around(CommandBase commandBase): execution(* CommandBase.acquireLock()) && this(commandBase) {
	        LockProperties lockProperties = commandBase.getLockProperties();
	        boolean returnValue = true;
	        if (!Scope.None.equals(lockProperties.getScope())) {
	            commandBase.releaseLocksAtEndOfExecute = Scope.Execution.equals(lockProperties.getScope());
	            if (!lockProperties.isWait()) {
	                returnValue = commandBase.acquireLockInternal();
	            } else {
	                commandBase.acquireLockAndWait();
	            }
	        }
	        return returnValue;
	    }

		boolean around(CommandBase command): execution(* acquireLockInternal()) && this(command) {
	        // if commandLock is null then we acquire new lock, otherwise probably we got lock from caller command.
	        if (command.context.getLock() == null) {
	            EngineLock lock = command.buildLock();
	            if (lock != null) {
	                Pair<Boolean, Set<String>> lockAcquireResult = command.getLockManager().acquireLock(lock);
	                if (lockAcquireResult.getFirst()) {
	                    command.log.info("Lock Acquired to object '{}'", lock);
	                    command.context.withLock(lock);
	                } else {
	                    command.log.info("Failed to Acquire Lock to object '{}'", lock);
	                    command.getReturnValue().getCanDoActionMessages()
	                    .addAll(command.extractVariableDeclarations(lockAcquireResult.getSecond()));
	                    return false;
	                }
	            }
	        }
	        return true;
	   }

	   void around(CommandBase command): execution(* acquireLockAndWait()) && this(command) {
	        // if commandLock is null then we acquire new lock, otherwise probably we got lock from caller command.
	         if (command.context.getLock() == null) {
	            Map<String, Pair<String, String>> exclusiveLocks = command.getExclusiveLocks();
	             if (exclusiveLocks != null) {
	                 EngineLock lock = new EngineLock(exclusiveLocks, null);
	                 command.getLockManager().acquireLockWait(lock);
	                 command.context.withLock(lock);
	            }
	         }
	    }

		VdcReturnValueBase around(CommandBase commandBase): execution(* endAction()) && this(commandBase) {
	        VdcReturnValueBase result = null;
	        try {
	            commandBase.initiateLockEndAction();
	            result = proceed(commandBase);
	        } finally {
	            commandBase.freeLockEndAction();
	        }
	                return result;
	        }

	   private void CommandBase.freeLockExecute() {
	        if (releaseLocksAtEndOfExecute || !getSucceeded() ||
	                (noAsyncOperations() && !(this instanceof IVdsAsyncCommand))) {
	            freeLock();
	        }
	    }

		/**
	     * If the command has more than one task handler, we can reach the end action
	     * phase and in that phase execute the next task handler. In that case, we
	     * don't want to release the locks, so we ask whether we're not in execute state.
	     */
	    private void CommandBase.freeLockEndAction() {
	        if (getActionState() != CommandActionState.EXECUTE) {
	            freeLock();
	        }
	    }

		/**
	     * The following method should initiate a lock , in order to release it at endAction()
	     */
	    private void CommandBase.initiateLockEndAction() {
	        if (context.getLock() == null) {
	            LockProperties lockProperties = getLockProperties();
	            if (Scope.Command.equals(lockProperties.getScope())) {
	                context.withLock(buildLock());
	            }

	        }
	    }

	    private EngineLock CommandBase.buildLock() {
	        EngineLock lock = null;
	        Map<String, Pair<String, String>> exclusiveLocks = getExclusiveLocks();
	        Map<String, Pair<String, String>> sharedLocks = getSharedLocks();
	        if (exclusiveLocks != null || sharedLocks != null) {
	            lock = new EngineLock(exclusiveLocks, sharedLocks);
	        }
	        return lock;
	    }

			LockProperties around(LockProperties lockProperties, org.ovirt.engine.core.bll.ExportVmTemplateCommand command): execution(* applyLockProperties(..)) && args(lockProperties) && target(command) {
				return lockProperties.withScope(Scope.Execution);
			}

			Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.ExportVmTemplateCommand command): execution(* getExclusiveLocks()) && target(command) {
			        Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

		locks.put(command.getVmTemplateId().toString(),
			LockMessagesMatchUtil.makeLockingPair(LockingGroup.REMOTE_TEMPLATE, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

				return locks;
			    }

		Map<String, Pair<String, String>> around(org.ovirt.engine.core.bll.ExportVmTemplateCommand command): execution(* getSharedLocks()) && target(command) {
		    Map<String, Pair<String, String>> locks = new HashMap<String, Pair<String, String>>();

		locks.put(command.getVmTemplateId().toString(),
			LockMessagesMatchUtil.makeLockingPair(LockingGroup.TEMPLATE, EngineMessage.ACTION_TYPE_FAILED_OBJECT_LOCKED));

		    return locks;
		}

	}


Move api.context.getUtil() into compatibility aspect. -- try not using obviously broken aspectj

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package compatibility.com.xpn.xwiki.api;

import com.xpn.xwiki.api.Context;
import com.xpn.xwiki.util.Util;

/**
 * Add a backward compatibility layer to the {@link Context} class.
 *
 * @version $Id$
 */
public privileged aspect ContextCompatibilityAspect
{
    /**
     * @return true it's main wiki's context, false otherwise.
     * @deprecated replaced by {@link Context#isMainWiki()} since 1.4M1.
     */
    @Deprecated
    public boolean Context.isVirtual()
    {
        return !this.isMainWiki();
    }

    /**
     * Returns an instance of the {@link com.xpn.xwiki.util.Util} class.
     *
     * @return an instance of the {@link com.xpn.xwiki.util.Util} class
     * @see Util
     * @deprecated since 2.6M1 the functions provided by Util are internal, please do not use them.
     */
    @Deprecated
    public Util Context.getUtil()
    {
        return this.context.getUtil();
    }
}

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package compatibility.com.xpn.xwiki.api;

import com.xpn.xwiki.api.Context;

/**
 * Add a backward compatibility layer to the {@link Context} class.
 *
 * @version $Id$
 */
public privileged aspect ContextCompatibilityAspect
{
    /**
     * @return true it's main wiki's context, false otherwise.
     * @deprecated replaced by {@link Context#isMainWiki()} since 1.4M1.
     */
    @Deprecated
    public boolean Context.isVirtual()
    {
        return !this.isMainWiki();
    }

    /**
     * Returns an instance of the {@link com.xpn.xwiki.util.Util} class.
     *
     * @return an instance of the {@link com.xpn.xwiki.util.Util} class
     * @see Util
     * @deprecated since 2.6M1 the functions provided by Util are internal, please do not use them.
     */
    @Deprecated
    public Util getUtil()
    {
        return this.context.getUtil();
    }
}


begin to implement StatPlayerWiseGraph

begin to implement StatPlayerWiseGraph


- Remove pointcut to deleted interface - Reflect new .fp package in pointcut

package tlc2.tool.distributed;

public aspect RMIMethodMonitorAspect {

	// catch all method calls to RMI methods
	pointcut callToRemoteMethod() :
		   execution(* tlc2.tool.distributed.InternRMI.*(..))
		|| execution(* tlc2.tool.distributed.TLCServerRMI.*(..))
		|| execution(* tlc2.tool.distributed.TLCWorkerRMI.*(..))
		|| execution(* tlc2.tool.distributed.fp.FPSetRMI.*(..))

	before(): (callToRemoteMethod()) {
		RMIMethodMonitor.entering(thisJoinPoint);
	}
}

package tlc2.tool.distributed;

public aspect RMIMethodMonitorAspect {

	// catch all method calls to RMI methods
	pointcut callToRemoteMethod() :
		   execution(* tlc2.tool.distributed.InternRMI.*(..))
		|| execution(* tlc2.tool.distributed.TLCServerRMI.*(..))
		|| execution(* tlc2.tool.distributed.TLCWorkerRMI.*(..))
		|| execution(* tlc2.tool.distributed.FPSetRMI.*(..))
		|| execution(* tlc2.tool.distributed.FPIntSetRMI.*(..));

	before(): (callToRemoteMethod()) {
		RMIMethodMonitor.entering(thisJoinPoint);
	}
}


Added is* getters to excluded checker methods

package net.etalia.crepuscolo.check;

import java.lang.reflect.Method;
import java.util.Stack;

import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;

import net.etalia.crepuscolo.domain.Authenticable;
import net.etalia.crepuscolo.services.AuthService;
import net.etalia.crepuscolo.services.AuthService.Verification;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Configurable
public aspect CheckAspect {

	pointcut checkMethod() :
		(
		execution(@(@CheckerAnnotation *) * *.*(..))
		||
		execution(* *.*(@(@CheckerAnnotation *) (*),..))
		||
		execution(* *.*(*, @(@CheckerAnnotation *) (*),..))
		||
		execution(* *.*(*, *, @(@CheckerAnnotation *) (*),..))
		||
		execution(* *.*(*, *, *, @(@CheckerAnnotation *) (*),..))
		||
		execution(@CheckerAnnotation * *.*(..))
		)
		&& !execution(* (@(Entity || MappedSuperclass) *).get*())
		&& !execution(* (@(Entity || MappedSuperclass) *).is*());

	@Autowired(required=true)
	private AuthService authService;

	private CheckerFactory checkerFactory;

	public void setAuthService(AuthService authService) {
		this.authService = authService;
	}

	public void setCheckerFactory(CheckerFactory cf) {
		this.checkerFactory = cf;
	}

	private ThreadLocal<Boolean> probing = new ThreadLocal<Boolean>();
	private ThreadLocal<Boolean> skip = new ThreadLocal<Boolean>();
	private ThreadLocal<Boolean> nullAuth = new ThreadLocal<Boolean>();
	private ThreadLocal<Stack<String>> mode = new ThreadLocal<Stack<String>>();

	public class JoinPointCheckPoint implements CheckPoint {

		private JoinPoint jp;

		public JoinPointCheckPoint(JoinPoint jp) {
			this.jp = jp;
		}

		@Override
		@Transactional(propagation=Propagation.REQUIRES_NEW)
		public String getAuthenticableId(Verification level) {
			if (nullAuth.get() == Boolean.TRUE) return null;
			return authService.getPrincipalUserId(level);
		}

		@Override
		@Transactional(propagation=Propagation.REQUIRES_NEW)
		public Authenticable getAuthenticable(Verification level) {
			if (nullAuth.get() == Boolean.TRUE) return null;
			return authService.getPrincipalUser(level);
		}

		@Override
		public Object getInstance() {
			return jp.getThis();
		}

		@Override
		public Method getMethod() {
			return ((MethodSignature)jp.getSignature()).getMethod();
		}

		@Override
		public Object[] getParameters() {
			return jp.getArgs();
		}

		@Override
		public boolean isInMode(String testMode) {
			return CheckAspect.this.isInMode(testMode);
		}

	}

	before() :
		checkMethod()
		&& !cflowbelow(checkMethod())
	{
		if (checkerFactory == null) return;
		if (skip.get() == Boolean.TRUE) return;

		Checker checker = checkerFactory.getFor(((MethodSignature)thisJoinPointStaticPart.getSignature()).getMethod());

		int code = checker.check(new JoinPointCheckPoint(thisJoinPoint));
		if (code != 0) {
			throw new AuthException().statusCode(code);
		}
		if (this.probing.get() == Boolean.TRUE) {
			throw new AuthException().statusCode(100);
		}
	}

	public void probing(boolean set) {
		if (set) {
			this.probing.set(true);
		} else {
			this.probing.remove();
		}
	}

	public void nullAuth(boolean set) {
		if (set) {
			this.nullAuth.set(true);
		} else {
			this.nullAuth.remove();
		}
	}

	public void skip(boolean set) {
		if (set) {
			this.skip.set(true);
		} else {
			this.skip.remove();
		}
	}

	public boolean isSkipping() {
		return this.skip.get() == Boolean.TRUE;
	}
	public boolean isProbing() {
		return this.probing.get() == Boolean.TRUE;
	}
	public boolean isNullAuth() {
		return this.nullAuth.get() == Boolean.TRUE;
	}

	public void enterMode(String pmode) {
		Stack<String> stack = mode.get();
		if (stack == null) {
			stack = new Stack<String>();
			mode.set(stack);
		}
		stack.add(pmode);
	}

	public void exitMode() {
		Stack<String> stack = mode.get();
		if (stack == null) return;
		stack.pop();
	}

	public boolean isInMode(String testMode) {
		Stack<String> stack = mode.get();
		if (stack == null || stack.size() == 0) return testMode == null;
		return stack.contains(testMode);
	}

	Object around() :
		execution (@CheckNoAuth * *.*(..))
	{
		boolean prenullauth = this.nullAuth.get() == Boolean.TRUE;
		try {
			nullAuth(true);
			return proceed();
		} finally {
			nullAuth(prenullauth);
		}
	}

	Object around() :
		execution (@CheckNoChecks * *.*(..))
	{
		boolean preskip = this.skip.get() == Boolean.TRUE;
		try {
			skip(true);
			return proceed();
		} finally {
			skip(preskip);
		}
	}

	before(String setMode) :
		execution (@CheckMode * (@Controller *).*(..))
		&& @annotation(CheckMode(setMode))
	{
		enterMode(setMode);
	}

	Object around(String setMode) :
		execution (@CheckMode * *.*(..))
		&& @annotation(CheckMode(setMode))
	{
		enterMode(setMode);
		try {
			return proceed(setMode);
		} finally {
			exitMode();
		}
	}

	public void clear() {
		this.mode.remove();
		this.nullAuth.remove();
		this.probing.remove();
		this.skip.remove();
	}
}

package net.etalia.crepuscolo.check;

import java.lang.reflect.Method;
import java.util.Stack;

import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;

import net.etalia.crepuscolo.domain.Authenticable;
import net.etalia.crepuscolo.services.AuthService;
import net.etalia.crepuscolo.services.AuthService.Verification;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Configurable
public aspect CheckAspect {

	pointcut checkMethod() :
		(
		execution(@(@CheckerAnnotation *) * *.*(..))
		||
		execution(* *.*(@(@CheckerAnnotation *) (*),..))
		||
		execution(* *.*(*, @(@CheckerAnnotation *) (*),..))
		||
		execution(* *.*(*, *, @(@CheckerAnnotation *) (*),..))
		||
		execution(* *.*(*, *, *, @(@CheckerAnnotation *) (*),..))
		||
		execution(@CheckerAnnotation * *.*(..))
		)
		&& !execution(* (@(Entity || MappedSuperclass) *).get*());

	@Autowired(required=true)
	private AuthService authService;

	private CheckerFactory checkerFactory;

	public void setAuthService(AuthService authService) {
		this.authService = authService;
	}

	public void setCheckerFactory(CheckerFactory cf) {
		this.checkerFactory = cf;
	}

	private ThreadLocal<Boolean> probing = new ThreadLocal<Boolean>();
	private ThreadLocal<Boolean> skip = new ThreadLocal<Boolean>();
	private ThreadLocal<Boolean> nullAuth = new ThreadLocal<Boolean>();
	private ThreadLocal<Stack<String>> mode = new ThreadLocal<Stack<String>>();

	public class JoinPointCheckPoint implements CheckPoint {

		private JoinPoint jp;

		public JoinPointCheckPoint(JoinPoint jp) {
			this.jp = jp;
		}

		@Override
		@Transactional(propagation=Propagation.REQUIRES_NEW)
		public String getAuthenticableId(Verification level) {
			if (nullAuth.get() == Boolean.TRUE) return null;
			return authService.getPrincipalUserId(level);
		}

		@Override
		@Transactional(propagation=Propagation.REQUIRES_NEW)
		public Authenticable getAuthenticable(Verification level) {
			if (nullAuth.get() == Boolean.TRUE) return null;
			return authService.getPrincipalUser(level);
		}

		@Override
		public Object getInstance() {
			return jp.getThis();
		}

		@Override
		public Method getMethod() {
			return ((MethodSignature)jp.getSignature()).getMethod();
		}

		@Override
		public Object[] getParameters() {
			return jp.getArgs();
		}

		@Override
		public boolean isInMode(String testMode) {
			return CheckAspect.this.isInMode(testMode);
		}

	}

	before() :
		checkMethod()
		&& !cflowbelow(checkMethod())
	{
		if (checkerFactory == null) return;
		if (skip.get() == Boolean.TRUE) return;

		Checker checker = checkerFactory.getFor(((MethodSignature)thisJoinPointStaticPart.getSignature()).getMethod());

		int code = checker.check(new JoinPointCheckPoint(thisJoinPoint));
		if (code != 0) {
			throw new AuthException().statusCode(code);
		}
		if (this.probing.get() == Boolean.TRUE) {
			throw new AuthException().statusCode(100);
		}
	}

	public void probing(boolean set) {
		if (set) {
			this.probing.set(true);
		} else {
			this.probing.remove();
		}
	}

	public void nullAuth(boolean set) {
		if (set) {
			this.nullAuth.set(true);
		} else {
			this.nullAuth.remove();
		}
	}

	public void skip(boolean set) {
		if (set) {
			this.skip.set(true);
		} else {
			this.skip.remove();
		}
	}

	public boolean isSkipping() {
		return this.skip.get() == Boolean.TRUE;
	}
	public boolean isProbing() {
		return this.probing.get() == Boolean.TRUE;
	}
	public boolean isNullAuth() {
		return this.nullAuth.get() == Boolean.TRUE;
	}

	public void enterMode(String pmode) {
		Stack<String> stack = mode.get();
		if (stack == null) {
			stack = new Stack<String>();
			mode.set(stack);
		}
		stack.add(pmode);
	}

	public void exitMode() {
		Stack<String> stack = mode.get();
		if (stack == null) return;
		stack.pop();
	}

	public boolean isInMode(String testMode) {
		Stack<String> stack = mode.get();
		if (stack == null || stack.size() == 0) return testMode == null;
		return stack.contains(testMode);
	}

	Object around() :
		execution (@CheckNoAuth * *.*(..))
	{
		boolean prenullauth = this.nullAuth.get() == Boolean.TRUE;
		try {
			nullAuth(true);
			return proceed();
		} finally {
			nullAuth(prenullauth);
		}
	}

	Object around() :
		execution (@CheckNoChecks * *.*(..))
	{
		boolean preskip = this.skip.get() == Boolean.TRUE;
		try {
			skip(true);
			return proceed();
		} finally {
			skip(preskip);
		}
	}

	before(String setMode) :
		execution (@CheckMode * (@Controller *).*(..))
		&& @annotation(CheckMode(setMode))
	{
		enterMode(setMode);
	}

	Object around(String setMode) :
		execution (@CheckMode * *.*(..))
		&& @annotation(CheckMode(setMode))
	{
		enterMode(setMode);
		try {
			return proceed(setMode);
		} finally {
			exitMode();
		}
	}

	public void clear() {
		this.mode.remove();
		this.nullAuth.remove();
		this.probing.remove();
		this.skip.remove();
	}
}