Fixing compat aspect in cases where the Set being passed in is unmodifiable.

git-svn-id: 2c527eb49caa05e19d6b2be874bf74fa9d7ea670@601161 13f79535-47bb-0310-9956-ffa450edef68

package org.apache.maven.compat.plugin;

import org.apache.maven.lifecycle.MojoBindingUtils;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.NoSuchPhaseException;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.extension.DefaultExtensionManager;
import org.apache.maven.execution.MavenRealmManager;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ResolutionGroup;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.DefaultPluginManager;
import org.apache.maven.plugin.InvalidPluginException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.version.PluginVersionNotFoundException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.MavenSettingsBuilder;
import org.apache.maven.settings.DefaultMavenSettingsBuilder;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.LogEnabled;

import java.io.IOException;
import java.util.Iterator;
import java.util.Collection;
import java.util.Set;
import java.util.LinkedHashSet;

public privileged aspect Maven20xCompatAspect
{

    // GRAB Session as soon as it's constructed.
    private MavenSession session;

    // GRAB the request when it's passed into a method that returns a corresponding result.
    // NOTE: We'll use this in multiple places below...
    private MavenExecutionRequest request;

    // Grab this so we have a voice!
    private Logger logger;

    // used for injecting plexus-utils into extension and plugin artifact sets.
    private VersionRange vr = null;
    private Artifact plexusUtilsArtifact = null;

    private pointcut mavenEmbedderStop():
        execution( * org.apache.maven.embedder.MavenEmbedder.stop( .. ) );

    // TODO: There must be a more elegant way to release these resources than depending on MavenEmbedder.stop().
    after(): mavenEmbedderStop()
    {
        session = null;
        request = null;
        logger = null;
        vr = null;
        plexusUtilsArtifact = null;
    }

    // pointcut to avoid recursive matching on behavior injected by this aspect.
    private pointcut notHere(): !within( Maven20xCompatAspect );

    private pointcut sessionCreation( MavenSession session ):
        execution( public MavenSession+.new(..) )
        && this( session )
        && notHere();

    // capture the session instance.
    after( MavenSession session ): sessionCreation( session )
    {
        this.session = session;
    }

    // USE Session to compensate for old verifyPlugin(..) API.
    private pointcut verifyPlugin( Plugin plugin, MavenProject project, PluginManager manager ):
        execution( public PluginDescriptor PluginManager+.verifyPlugin( Plugin, MavenProject, Settings, ArtifactRepository ) )
        && args( plugin, project, .. )
        && target( manager )
        && notHere();

    // redirect the old verifyPlugin(..) call to the new one, using the captured session instance above.
    PluginDescriptor around( Plugin plugin,
                             MavenProject project,
                             PluginManager manager )
        throws ArtifactResolutionException, ArtifactNotFoundException, PluginNotFoundException,
        PluginVersionResolutionException, InvalidPluginException, PluginManagerException,
        PluginVersionNotFoundException:
            verifyPlugin( plugin, project, manager )
    {
        return manager.verifyPlugin( plugin, project, session );
    }

    // Re-Introduce old verifyPlugin(..) API.
    public PluginDescriptor PluginManager.verifyPlugin( Plugin plugin,
                                                        MavenProject project,
                                                        Settings settings,
                                                        ArtifactRepository localRepository )
    {
        // this will always be diverted, so no need to do anything.
        return null;
    }

    public PluginDescriptor DefaultPluginManager.verifyPlugin( Plugin plugin,
                                                        MavenProject project,
                                                        Settings settings,
                                                        ArtifactRepository localRepository )
    {
        // this will always be diverted, so no need to do anything.
        return null;
    }

    private pointcut getPluginDescriptorForPrefix( String prefix, PluginManager manager ):
        execution( public PluginDescriptor PluginManager+.getPluginDescriptorForPrefix( String ) )
        && args( prefix )
        && target( manager )
        && notHere();

    PluginDescriptor around( String prefix, PluginManager manager ): getPluginDescriptorForPrefix( prefix, manager )
    {
        // TODO: Implement Me!
        throw new UnsupportedOperationException( "This method has not yet been implemented in Maven's backward-compatibility library." );
    }

    public PluginDescriptor PluginManager.getPluginDescriptorForPrefix( String prefix )
    {
        return null;
    }

    // Intercept retrieval of artifact dependencies of an extension, inject plexus-utils if it's not there.
    private pointcut extDepArtifactsResolved( DefaultExtensionManager mgr ):
        call( public Set ResolutionGroup+.getArtifacts() )
        && within( DefaultExtensionManager+ )
        && this( mgr )
        && notHere();

    // We use the same hack here to make sure that plexus 1.1 is available for extensions that do
    // not declare plexus-utils but need it. MNG-2900
    Set around( DefaultExtensionManager mgr ): extDepArtifactsResolved( mgr )
    {
        Set result = proceed( mgr );

        result = checkPlexusUtils( result, mgr.artifactFactory );

        return result;
    }

    // Intercept retrieval of artifact dependencies of a plugin, inject plexus-utils if it's not there.
    private pointcut pluginDepArtifactsResolved( DefaultPluginManager mgr ):
        call( public Set ResolutionGroup+.getArtifacts() )
        && cflow( execution( Set DefaultPluginManager+.getPluginArtifacts(..) ) )
        && this( mgr )
        && notHere();

    Set around( DefaultPluginManager mgr ): pluginDepArtifactsResolved( mgr )
    {
        Set result = proceed( mgr );

        result = checkPlexusUtils( result, mgr.artifactFactory );

        return result;
    }

    private pointcut methodsTakingRequest( MavenExecutionRequest request ):
        execution( MavenExecutionResult *.*( MavenExecutionRequest ) )
        && !withincode( * *.*( MavenExecutionRequest ) )
        && args( request )
        && notHere();

    // capture the request instance before it's passed into any method that returns a corresponding MavenExecutionResult.
    Object around( MavenExecutionRequest request ): methodsTakingRequest( request )
    {
        this.request = request;

        try
        {
            return proceed( request );
        }
        finally
        {
            this.request = null;
        }
    }

    // USE Request to compensate for old buildSettings() API.
    private pointcut buildSettings( MavenSettingsBuilder builder ):
        execution( public Settings MavenSettingsBuilder+.buildSettings() )
        && target( builder )
        && notHere();

    // redirect old buildSettings() call to the new one, using the request captured above.
    Settings around( MavenSettingsBuilder builder )
        throws IOException, XmlPullParserException:
            buildSettings( builder )
    {
        return builder.buildSettings( request );
    }

    // Re-Introduce old buildSettings() API.
    public Settings MavenSettingsBuilder.buildSettings()
        throws IOException, XmlPullParserException
    {
        return null;
    }

    public Settings DefaultMavenSettingsBuilder.buildSettings()
    throws IOException, XmlPullParserException
    {
        return null;
    }

    private pointcut pluginManager( DefaultPluginManager manager ):
        execution( * DefaultPluginManager.*( .. ) )
        && this( manager );

    private pointcut pluginRealmCreation( Plugin plugin, DefaultPluginManager manager ):
        call( ClassRealm MavenRealmManager+.createPluginRealm( Plugin, Artifact, Collection ) )
        && cflow( pluginManager( manager ) )
        && args( plugin, .. );

    // Add various imports for Xpp3 stuff back into the core realm every time a plugin realm is created.
    ClassRealm around( Plugin plugin, DefaultPluginManager manager ): pluginRealmCreation( plugin, manager )
    {
        ClassRealm pluginRealm = proceed( plugin, manager );

        try
        {
            String parentRealmId = manager.container.getContainerRealm().getId();

            // adding for MNG-3012 to try to work around problems with Xpp3Dom (from plexus-utils)
            // spawning a ClassCastException when a mojo calls plugin.getConfiguration() from maven-model...
            pluginRealm.importFrom( parentRealmId, Xpp3Dom.class.getName() );
            pluginRealm.importFrom( parentRealmId, "org.codehaus.plexus.util.xml.pull" );

            // Adding for MNG-2878, since maven-reporting-impl was removed from the
            // internal list of artifacts managed by maven, the classloader is different
            // between maven-reporting-impl and maven-reporting-api...so this resource
            // is not available from the AbstractMavenReport since it uses:
            // getClass().getResourceAsStream( "/default-report.xml" )
            // (maven-reporting-impl version 2.0; line 134; affects: checkstyle plugin, and probably others)
            pluginRealm.importFrom( parentRealmId, "/default-report.xml" );
        }
        catch ( NoSuchRealmException e )
        {
            // can't happen here. All realms are concretely resolved by now.
        }

        return pluginRealm;
    }

    private pointcut enableLoggingCall( Logger logger ):
        execution( void LogEnabled+.enableLogging( Logger ) )
        && args( logger );

    after( Logger logger ): enableLoggingCall( logger )
    {
        if ( this.logger == null )
        {
            this.logger = logger;
        }
    }

    private pointcut addMojoBindingCall( String phase, MojoBinding binding ):
        call( void LifecycleUtils.addMojoBinding( String, MojoBinding, .. ) )
        && args( phase, binding, .. );

    void around( String phase, MojoBinding binding ): addMojoBindingCall( phase, binding )
    {
        try
        {
            proceed( phase, binding );
        }
        catch ( NoSuchPhaseException e )
        {
            logger.debug( "Mojo execution: " + MojoBindingUtils.toString( binding )
                          + " cannot be attached to lifecycle phase: " + phase
                          + "; it does not exist. Ignoring this binding." );
        }
    }

    // --------------------------
    // UTILITIES
    // --------------------------

    private Set checkPlexusUtils( Set dependencyArtifacts, ArtifactFactory artifactFactory )
    {
        // ----------------------------------------------------------------------------
        // If the plugin already declares a dependency on plexus-utils then we're all
        // set as the plugin author is aware of its use. If we don't have a dependency
        // on plexus-utils then we must protect users from stupid plugin authors who
        // did not declare a direct dependency on plexus-utils because the version
        // Maven uses is hidden from downstream use. We will also bump up any
        // anything below 1.1 to 1.1 as this mimics the behaviour in 2.0.5 where
        // plexus-utils 1.1 was being forced into use.
        // ----------------------------------------------------------------------------

        if ( vr == null )
        {
            try
            {
                vr = VersionRange.createFromVersionSpec( "[1.1,)" );
            }
            catch ( InvalidVersionSpecificationException e )
            {
                // Won't happen
            }
        }

        for ( Iterator i = dependencyArtifacts.iterator(); i.hasNext(); )
        {
            Artifact a = (Artifact) i.next();

            if ( a.getArtifactId().equals( "plexus-utils" )
                 && vr.containsVersion( new DefaultArtifactVersion( a.getVersion() ) ) )
            {
                return dependencyArtifacts;
            }
        }

        // We will add plexus-utils as every plugin was getting this anyway from Maven itself. We will set the
        // version to the latest version we know that works as of the 2.0.6 release. We set the scope to runtime
        // as this is what's implicitly happening in 2.0.6.

        if ( plexusUtilsArtifact == null )
        {
            plexusUtilsArtifact = artifactFactory.createArtifact( "org.codehaus.plexus",
                                                                  "plexus-utils",
                                                                  "1.1",
                                                                  Artifact.SCOPE_RUNTIME,
                                                                  "jar" );
        }

        Set result = new LinkedHashSet( dependencyArtifacts );
        result.add( plexusUtilsArtifact );

        return result;
    }

}

package org.apache.maven.compat.plugin;

import org.apache.maven.lifecycle.MojoBindingUtils;
import org.apache.maven.lifecycle.LifecycleUtils;
import org.apache.maven.lifecycle.NoSuchPhaseException;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.extension.DefaultExtensionManager;
import org.apache.maven.execution.MavenRealmManager;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.metadata.ResolutionGroup;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.lifecycle.model.MojoBinding;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.DefaultPluginManager;
import org.apache.maven.plugin.InvalidPluginException;
import org.apache.maven.plugin.PluginManager;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.version.PluginVersionNotFoundException;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.MavenSettingsBuilder;
import org.apache.maven.settings.DefaultMavenSettingsBuilder;
import org.apache.maven.settings.Settings;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.LogEnabled;

import java.io.IOException;
import java.util.Iterator;
import java.util.Collection;
import java.util.Set;

public privileged aspect Maven20xCompatAspect
{

    // GRAB Session as soon as it's constructed.
    private MavenSession session;

    // GRAB the request when it's passed into a method that returns a corresponding result.
    // NOTE: We'll use this in multiple places below...
    private MavenExecutionRequest request;

    // Grab this so we have a voice!
    private Logger logger;

    // used for injecting plexus-utils into extension and plugin artifact sets.
    private VersionRange vr = null;
    private Artifact plexusUtilsArtifact = null;

    private pointcut mavenEmbedderStop():
        execution( * org.apache.maven.embedder.MavenEmbedder.stop( .. ) );

    // TODO: There must be a more elegant way to release these resources than depending on MavenEmbedder.stop().
    after(): mavenEmbedderStop()
    {
        session = null;
        request = null;
        logger = null;
        vr = null;
        plexusUtilsArtifact = null;
    }

    // pointcut to avoid recursive matching on behavior injected by this aspect.
    private pointcut notHere(): !within( Maven20xCompatAspect );

    private pointcut sessionCreation( MavenSession session ):
        execution( public MavenSession+.new(..) )
        && this( session )
        && notHere();

    // capture the session instance.
    after( MavenSession session ): sessionCreation( session )
    {
        this.session = session;
    }

    // USE Session to compensate for old verifyPlugin(..) API.
    private pointcut verifyPlugin( Plugin plugin, MavenProject project, PluginManager manager ):
        execution( public PluginDescriptor PluginManager+.verifyPlugin( Plugin, MavenProject, Settings, ArtifactRepository ) )
        && args( plugin, project, .. )
        && target( manager )
        && notHere();

    // redirect the old verifyPlugin(..) call to the new one, using the captured session instance above.
    PluginDescriptor around( Plugin plugin,
                             MavenProject project,
                             PluginManager manager )
        throws ArtifactResolutionException, ArtifactNotFoundException, PluginNotFoundException,
        PluginVersionResolutionException, InvalidPluginException, PluginManagerException,
        PluginVersionNotFoundException:
            verifyPlugin( plugin, project, manager )
    {
        return manager.verifyPlugin( plugin, project, session );
    }

    // Re-Introduce old verifyPlugin(..) API.
    public PluginDescriptor PluginManager.verifyPlugin( Plugin plugin,
                                                        MavenProject project,
                                                        Settings settings,
                                                        ArtifactRepository localRepository )
    {
        // this will always be diverted, so no need to do anything.
        return null;
    }

    public PluginDescriptor DefaultPluginManager.verifyPlugin( Plugin plugin,
                                                        MavenProject project,
                                                        Settings settings,
                                                        ArtifactRepository localRepository )
    {
        // this will always be diverted, so no need to do anything.
        return null;
    }

    private pointcut getPluginDescriptorForPrefix( String prefix, PluginManager manager ):
        execution( public PluginDescriptor PluginManager+.getPluginDescriptorForPrefix( String ) )
        && args( prefix )
        && target( manager )
        && notHere();

    PluginDescriptor around( String prefix, PluginManager manager ): getPluginDescriptorForPrefix( prefix, manager )
    {
        // TODO: Implement Me!
        throw new UnsupportedOperationException( "This method has not yet been implemented in Maven's backward-compatibility library." );
    }

    public PluginDescriptor PluginManager.getPluginDescriptorForPrefix( String prefix )
    {
        return null;
    }

    // Intercept retrieval of artifact dependencies of an extension, inject plexus-utils if it's not there.
    private pointcut extDepArtifactsResolved( DefaultExtensionManager mgr ):
        call( public Set ResolutionGroup+.getArtifacts() )
        && within( DefaultExtensionManager+ )
        && this( mgr )
        && notHere();

    // We use the same hack here to make sure that plexus 1.1 is available for extensions that do
    // not declare plexus-utils but need it. MNG-2900
    Set around( DefaultExtensionManager mgr ): extDepArtifactsResolved( mgr )
    {
        Set result = proceed( mgr );

        checkPlexusUtils( result, mgr.artifactFactory );

        return result;
    }

    // Intercept retrieval of artifact dependencies of a plugin, inject plexus-utils if it's not there.
    private pointcut pluginDepArtifactsResolved( DefaultPluginManager mgr ):
        call( public Set ResolutionGroup+.getArtifacts() )
        && cflow( execution( Set DefaultPluginManager+.getPluginArtifacts(..) ) )
        && this( mgr )
        && notHere();

    Set around( DefaultPluginManager mgr ): pluginDepArtifactsResolved( mgr )
    {
        Set result = proceed( mgr );

        checkPlexusUtils( result, mgr.artifactFactory );

        return result;
    }

    private pointcut methodsTakingRequest( MavenExecutionRequest request ):
        execution( MavenExecutionResult *.*( MavenExecutionRequest ) )
        && !withincode( * *.*( MavenExecutionRequest ) )
        && args( request )
        && notHere();

    // capture the request instance before it's passed into any method that returns a corresponding MavenExecutionResult.
    Object around( MavenExecutionRequest request ): methodsTakingRequest( request )
    {
        this.request = request;

        try
        {
            return proceed( request );
        }
        finally
        {
            this.request = null;
        }
    }

    // USE Request to compensate for old buildSettings() API.
    private pointcut buildSettings( MavenSettingsBuilder builder ):
        execution( public Settings MavenSettingsBuilder+.buildSettings() )
        && target( builder )
        && notHere();

    // redirect old buildSettings() call to the new one, using the request captured above.
    Settings around( MavenSettingsBuilder builder )
        throws IOException, XmlPullParserException:
            buildSettings( builder )
    {
        return builder.buildSettings( request );
    }

    // Re-Introduce old buildSettings() API.
    public Settings MavenSettingsBuilder.buildSettings()
        throws IOException, XmlPullParserException
    {
        return null;
    }

    public Settings DefaultMavenSettingsBuilder.buildSettings()
    throws IOException, XmlPullParserException
    {
        return null;
    }

    private pointcut pluginManager( DefaultPluginManager manager ):
        execution( * DefaultPluginManager.*( .. ) )
        && this( manager );

    private pointcut pluginRealmCreation( Plugin plugin, DefaultPluginManager manager ):
        call( ClassRealm MavenRealmManager+.createPluginRealm( Plugin, Artifact, Collection ) )
        && cflow( pluginManager( manager ) )
        && args( plugin, .. );

    // Add various imports for Xpp3 stuff back into the core realm every time a plugin realm is created.
    ClassRealm around( Plugin plugin, DefaultPluginManager manager ): pluginRealmCreation( plugin, manager )
    {
        ClassRealm pluginRealm = proceed( plugin, manager );

        try
        {
            String parentRealmId = manager.container.getContainerRealm().getId();

            // adding for MNG-3012 to try to work around problems with Xpp3Dom (from plexus-utils)
            // spawning a ClassCastException when a mojo calls plugin.getConfiguration() from maven-model...
            pluginRealm.importFrom( parentRealmId, Xpp3Dom.class.getName() );
            pluginRealm.importFrom( parentRealmId, "org.codehaus.plexus.util.xml.pull" );

            // Adding for MNG-2878, since maven-reporting-impl was removed from the
            // internal list of artifacts managed by maven, the classloader is different
            // between maven-reporting-impl and maven-reporting-api...so this resource
            // is not available from the AbstractMavenReport since it uses:
            // getClass().getResourceAsStream( "/default-report.xml" )
            // (maven-reporting-impl version 2.0; line 134; affects: checkstyle plugin, and probably others)
            pluginRealm.importFrom( parentRealmId, "/default-report.xml" );
        }
        catch ( NoSuchRealmException e )
        {
            // can't happen here. All realms are concretely resolved by now.
        }

        return pluginRealm;
    }

    private pointcut enableLoggingCall( Logger logger ):
        execution( void LogEnabled+.enableLogging( Logger ) )
        && args( logger );

    after( Logger logger ): enableLoggingCall( logger )
    {
        if ( this.logger == null )
        {
            this.logger = logger;
        }
    }

    private pointcut addMojoBindingCall( String phase, MojoBinding binding ):
        call( void LifecycleUtils.addMojoBinding( String, MojoBinding, .. ) )
        && args( phase, binding, .. );

    void around( String phase, MojoBinding binding ): addMojoBindingCall( phase, binding )
    {
        try
        {
            proceed( phase, binding );
        }
        catch ( NoSuchPhaseException e )
        {
            logger.debug( "Mojo execution: " + MojoBindingUtils.toString( binding )
                          + " cannot be attached to lifecycle phase: " + phase
                          + "; it does not exist. Ignoring this binding." );
        }
    }

    // --------------------------
    // UTILITIES
    // --------------------------

    private void checkPlexusUtils( Set dependencyArtifacts, ArtifactFactory artifactFactory )
    {
        // ----------------------------------------------------------------------------
        // If the plugin already declares a dependency on plexus-utils then we're all
        // set as the plugin author is aware of its use. If we don't have a dependency
        // on plexus-utils then we must protect users from stupid plugin authors who
        // did not declare a direct dependency on plexus-utils because the version
        // Maven uses is hidden from downstream use. We will also bump up any
        // anything below 1.1 to 1.1 as this mimics the behaviour in 2.0.5 where
        // plexus-utils 1.1 was being forced into use.
        // ----------------------------------------------------------------------------

        if ( vr == null )
        {
            try
            {
                vr = VersionRange.createFromVersionSpec( "[1.1,)" );
            }
            catch ( InvalidVersionSpecificationException e )
            {
                // Won't happen
            }
        }

        boolean plexusUtilsPresent = false;

        for ( Iterator i = dependencyArtifacts.iterator(); i.hasNext(); )
        {
            Artifact a = (Artifact) i.next();

            if ( a.getArtifactId().equals( "plexus-utils" )
                 && vr.containsVersion( new DefaultArtifactVersion( a.getVersion() ) ) )
            {
                plexusUtilsPresent = true;

                break;
            }
        }

        if ( !plexusUtilsPresent )
        {
            // We will add plexus-utils as every plugin was getting this anyway from Maven itself. We will set the
            // version to the latest version we know that works as of the 2.0.6 release. We set the scope to runtime
            // as this is what's implicitly happening in 2.0.6.

            if ( plexusUtilsArtifact == null )
            {
                plexusUtilsArtifact = artifactFactory.createArtifact( "org.codehaus.plexus",
                                                                      "plexus-utils",
                                                                      "1.1",
                                                                      Artifact.SCOPE_RUNTIME,
                                                                      "jar" );
            }

            dependencyArtifacts.add( plexusUtilsArtifact );
        }
    }

}


roo changes

roo changes

// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).

package org.datacite.mds.web;

import java.io.UnsupportedEncodingException;
import java.lang.String;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.datacite.mds.domain.Dataset;
import org.datacite.mds.domain.Metadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

privileged aspect MetadataController_Roo_Controller {

    @Autowired
    private GenericConversionService MetadataController.conversionService;

    @RequestMapping(method = RequestMethod.POST)
    public String MetadataController.create(@Valid Metadata metadata, BindingResult result, Model model, HttpServletRequest request) {
        if (result.hasErrors()) {
            model.addAttribute("metadata", metadata);
            return "metadatas/create";
        }
        metadata.persist();
        return "redirect:/metadatas/" + encodeUrlPathSegment(metadata.getId().toString(), request);
    }

    @RequestMapping(params = "form", method = RequestMethod.GET)
    public String MetadataController.createForm(Model model) {
        model.addAttribute("metadata", new Metadata());
        List dependencies = new ArrayList();
        if (Dataset.countDatasets() == 0) {
            dependencies.add(new String[]{"dataset", "datasets"});
        }
        model.addAttribute("dependencies", dependencies);
        return "metadatas/create";
    }

    @RequestMapping(method = RequestMethod.GET)
    public String MetadataController.list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model model) {
        if (page != null || size != null) {
            int sizeNo = size == null ? 10 : size.intValue();
            model.addAttribute("metadatas", Metadata.findMetadataEntries(page == null ? 0 : (page.intValue() - 1) * sizeNo, sizeNo));
            float nrOfPages = (float) Metadata.countMetadatas() / sizeNo;
            model.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
        } else {
            model.addAttribute("metadatas", Metadata.findAllMetadatas());
        }
        return "metadatas/list";
    }

    @RequestMapping(params = { "find=ByDataset", "form" }, method = RequestMethod.GET)
    public String MetadataController.findMetadatasByDatasetForm(Model model) {
        model.addAttribute("datasets", Dataset.findAllDatasets());
        return "metadatas/findMetadatasByDataset";
    }

    @RequestMapping(params = "find=ByDataset", method = RequestMethod.GET)
    public String MetadataController.findMetadatasByDataset(@RequestParam("dataset") Dataset dataset, Model model) {
        model.addAttribute("metadatas", Metadata.findMetadatasByDataset(dataset).getResultList());
        return "metadatas/list";
    }

    private String MetadataController.encodeUrlPathSegment(String pathSegment, HttpServletRequest request) {
        String enc = request.getCharacterEncoding();
        if (enc == null) {
            enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
        }
        try {
            pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
        }
        catch (UnsupportedEncodingException uee) {}
        return pathSegment;
    }

}

// WARNING: DO NOT EDIT THIS FILE. THIS FILE IS MANAGED BY SPRING ROO.
// You may push code into the target .java compilation unit if you wish to edit any member(s).

package org.datacite.mds.web;

import java.io.UnsupportedEncodingException;
import java.lang.Long;
import java.lang.String;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.datacite.mds.domain.Dataset;
import org.datacite.mds.domain.Metadata;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

privileged aspect MetadataController_Roo_Controller {

    @Autowired
    private GenericConversionService MetadataController.conversionService;

    @RequestMapping(method = RequestMethod.POST)
    public String MetadataController.create(@Valid Metadata metadata, BindingResult result, Model model, HttpServletRequest request) {
        if (result.hasErrors()) {
            model.addAttribute("metadata", metadata);
            return "metadatas/create";
        }
        metadata.persist();
        return "redirect:/metadatas/" + encodeUrlPathSegment(metadata.getId().toString(), request);
    }

    @RequestMapping(params = "form", method = RequestMethod.GET)
    public String MetadataController.createForm(Model model) {
        model.addAttribute("metadata", new Metadata());
        List dependencies = new ArrayList();
        if (Dataset.countDatasets() == 0) {
            dependencies.add(new String[]{"dataset", "datasets"});
        }
        model.addAttribute("dependencies", dependencies);
        return "metadatas/create";
    }

    @RequestMapping(method = RequestMethod.GET)
    public String MetadataController.list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model model) {
        if (page != null || size != null) {
            int sizeNo = size == null ? 10 : size.intValue();
            model.addAttribute("metadatas", Metadata.findMetadataEntries(page == null ? 0 : (page.intValue() - 1) * sizeNo, sizeNo));
            float nrOfPages = (float) Metadata.countMetadatas() / sizeNo;
            model.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
        } else {
            model.addAttribute("metadatas", Metadata.findAllMetadatas());
        }
        return "metadatas/list";
    }

    @RequestMapping(params = { "find=ByDataset", "form" }, method = RequestMethod.GET)
    public String MetadataController.findMetadatasByDatasetForm(Model model) {
        model.addAttribute("datasets", Dataset.findAllDatasets());
        return "metadatas/findMetadatasByDataset";
    }

    @RequestMapping(params = "find=ByDataset", method = RequestMethod.GET)
    public String MetadataController.findMetadatasByDataset(@RequestParam("dataset") Dataset dataset, Model model) {
        model.addAttribute("metadatas", Metadata.findMetadatasByDataset(dataset).getResultList());
        return "metadatas/list";
    }

    private String MetadataController.encodeUrlPathSegment(String pathSegment, HttpServletRequest request) {
        String enc = request.getCharacterEncoding();
        if (enc == null) {
            enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
        }
        try {
            pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
        }
        catch (UnsupportedEncodingException uee) {}
        return pathSegment;
    }

}


Suppressed ProviderNexusAspect to throw NullPointerException in case user wants to create Invocations outside of the server context (e.g. Unit testing)

git-svn-id: 90776817adfbd895fc5cfa90f675377e0a62e745@160541 13f79535-47bb-0310-9956-ffa450edef68

package org.apache.ldap.server.jndi;

import java.util.Map;
import java.util.Stack;
import java.util.Iterator;
import java.util.EmptyStackException;

import javax.naming.Name;
import javax.naming.Context;
import javax.naming.ldap.LdapContext;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.ModificationItem;

import org.apache.ldap.common.filter.ExprNode;
import org.apache.ldap.server.PartitionNexus;
import org.apache.ldap.server.db.Database;
import org.apache.ldap.server.ContextPartition;
import org.apache.ldap.server.invocation.Invocation;

/**
 * Aspect coupling the JNDI provider with the nexus thereby facilitating the
 * injection of interceptors between calls to the nexus from the JNDI.
 *
 * @author Alex Karasulu
 * @author $Author: akarasulu $
 * @version $Revision$
 */
public aspect ProviderNexusAspect
{
    // ------------------------------------------------------------------------
    // M E M B E R   I N T R O D U C T I O N S
    // ------------------------------------------------------------------------

    /**
     * Adds a static ThreadLocal for a Stack of LdapContexts representing nested
     * backend nexus calls made by the JndiProvider's contexts within the same
     * thread of execution.
     */
    private static ThreadLocal JndiProvider.s_contextStacks = new ThreadLocal();

    // ------------------------------------------------------------------------
    // M E T H O D   I N T R O D U C T I O N S
    // ------------------------------------------------------------------------

    /**
     * Pushes a calling LdapContext onto the Thread's ThreadLocal Stack before
     * calls are made on the nexus within the LdapContext code.
     *
     * @param context the caller or the current context for the nexus call
     */
    private static void JndiProvider.push( LdapContext context )
    {
        Stack stack = ( Stack ) s_contextStacks.get();

        if ( null == stack )
        {
            stack = new Stack();
            s_contextStacks.set( stack );
        }

        stack.push( context );
    }

    /**
     * Pops the head of the Thread's ThreadLocal Stack after calls complete on
     * the nexus within the LdapContext code.
     *
     * @return the last LdapContext or caller
     */
    private static LdapContext JndiProvider.pop()
    {
        Stack stack = ( Stack ) s_contextStacks.get();

        if ( null == stack )
        {
            throw new EmptyStackException();
        }

        return ( LdapContext ) stack.pop();
    }

    /**
     * Peeks at the head of the Thread's ThreadLocal Stack.
     *
     * @return the current LdapContext or caller
     */
    static LdapContext JndiProvider.peek()
    {
        Stack stack = ( Stack ) s_contextStacks.get();

        if ( null == stack )
        {
            throw new EmptyStackException();
        }

        return ( LdapContext ) stack.peek();
    }

    // ------------------------------------------------------------------------
    // A S P E C T   M E T H O D S
    // ------------------------------------------------------------------------

    /**
     * Gets a shallow copy of the context stack.
     *
     * @return the context Stack.
     */
    private static Stack getContextStack()
    {
        Stack stack = ( Stack ) JndiProvider.s_contextStacks.get();

        if ( stack == null )
        {
            return null;
        }

        return ( Stack ) stack.clone();
    }

    // ------------------------------------------------------------------------
    // P O I N T   C U T S
    // ------------------------------------------------------------------------

    /**
     * Selects join points on any public method calls made on the BackendNexus
     * interface implementing proxy from code executing within an LdapContext
     * caller.  Makes sure that Proxy methods (static) and the
     * getInvokationHandler() do not get selected.
     *
     * @param caller the calling LdapContext.
     */
    pointcut jndiNexusCalls( Context caller ):
        this( caller ) &&
        ! this( ContextPartition ) &&
        target( PartitionNexus ) &&
        ! target( Database ) &&
        (
        // these are for the ContextPartition interface methods

        // not used anymore since it was moved to RootNexus class
        // call( public Attributes getRootDSE() ) ||

        call( public Name getMatchedDn( Name, boolean ) ) ||
        call( public Name getSuffix( Name, boolean ) ) ||
		call( public Iterator listSuffixes( boolean ) ) ||
		call( public Attributes lookup( Name, String [] ) ) ||

		// these are for BackingStore interface methods
        call( public void add( String, Name, Attributes ) ) ||
        call( public void delete( Name ) ) ||
		call( public boolean hasEntry( Name ) ) ||
        call( public boolean isSuffix( Name ) ) ||
        call( public NamingEnumeration list( Name ) ) ||
		call( public Attributes lookup( Name ) ) ||
        call( public void modify( Name, int, Attributes ) ) ||
        call( public void modify( Name, ModificationItem [] ) ) ||
        call( public void modifyRn( Name, String, boolean ) ) ||
        call( public void move( Name, Name ) ) ||
        call( public void move( Name, Name, String, boolean ) ) ||
        call( public NamingEnumeration
           search( Name, Map, ExprNode, SearchControls ) ) );

    /**
     * Selects join points where the Invokation default constructor executes.
     *
     * @param invocation the Invocation instantiated
     */
    pointcut newInvocation( Invocation invocation ):
        target( invocation ) &&
        execution( Invocation.new(..) );

    // ------------------------------------------------------------------------
    // A D V I C E
    // ------------------------------------------------------------------------

    before( Context caller ):
        jndiNexusCalls( caller )
        {
    		JndiProvider.push( ( LdapContext ) caller );
            //System.out.println( "\npushed " + caller + " for join point "
            //    + thisJoinPoint );
        }

    after( Context caller ):
        jndiNexusCalls( caller )
        {
            LdapContext head = JndiProvider.pop();
            //System.out.println( "\npopped " + caller + " for join point "
            //    + thisJoinPoint );
        }

    after( Invocation invocation ):
        newInvocation( invocation )
        {
            invocation.setContextStack( getContextStack() );
            //System.out.println(
            //    "\nJust set the context stack on a new Invocation: "
            //    + thisJoinPoint );
        }
}

package org.apache.ldap.server.jndi;

import java.util.Map;
import java.util.Stack;
import java.util.Iterator;
import java.util.EmptyStackException;

import javax.naming.Name;
import javax.naming.Context;
import javax.naming.ldap.LdapContext;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.ModificationItem;

import org.apache.ldap.common.filter.ExprNode;
import org.apache.ldap.server.PartitionNexus;
import org.apache.ldap.server.db.Database;
import org.apache.ldap.server.ContextPartition;
import org.apache.ldap.server.invocation.Invocation;

/**
 * Aspect coupling the JNDI provider with the nexus thereby facilitating the
 * injection of interceptors between calls to the nexus from the JNDI.
 *
 * @author Alex Karasulu
 * @author $Author: akarasulu $
 * @version $Revision$
 */
public aspect ProviderNexusAspect
{
    // ------------------------------------------------------------------------
    // M E M B E R   I N T R O D U C T I O N S
    // ------------------------------------------------------------------------

    /**
     * Adds a static ThreadLocal for a Stack of LdapContexts representing nested
     * backend nexus calls made by the JndiProvider's contexts within the same
     * thread of execution.
     */
    private static ThreadLocal JndiProvider.s_contextStacks = new ThreadLocal();

    // ------------------------------------------------------------------------
    // M E T H O D   I N T R O D U C T I O N S
    // ------------------------------------------------------------------------

    /**
     * Pushes a calling LdapContext onto the Thread's ThreadLocal Stack before
     * calls are made on the nexus within the LdapContext code.
     *
     * @param context the caller or the current context for the nexus call
     */
    private static void JndiProvider.push( LdapContext context )
    {
        Stack stack = ( Stack ) s_contextStacks.get();

        if ( null == stack )
        {
            stack = new Stack();
            s_contextStacks.set( stack );
        }

        stack.push( context );
    }

    /**
     * Pops the head of the Thread's ThreadLocal Stack after calls complete on
     * the nexus within the LdapContext code.
     *
     * @return the last LdapContext or caller
     */
    private static LdapContext JndiProvider.pop()
    {
        Stack stack = ( Stack ) s_contextStacks.get();

        if ( null == stack )
        {
            throw new EmptyStackException();
        }

        return ( LdapContext ) stack.pop();
    }

    /**
     * Peeks at the head of the Thread's ThreadLocal Stack.
     *
     * @return the current LdapContext or caller
     */
    static LdapContext JndiProvider.peek()
    {
        Stack stack = ( Stack ) s_contextStacks.get();

        if ( null == stack )
        {
            throw new EmptyStackException();
        }

        return ( LdapContext ) stack.peek();
    }

    // ------------------------------------------------------------------------
    // A S P E C T   M E T H O D S
    // ------------------------------------------------------------------------

    /**
     * Gets a shallow copy of the context stack.
     *
     * @return the context Stack.
     */
    private static Stack getContextStack()
    {
        Stack stack = ( Stack ) JndiProvider.s_contextStacks.get();

        if ( null == stack )
        {
            throw new NullPointerException( "Thread had null stack" );
        }

        return ( Stack ) stack.clone();
    }

    // ------------------------------------------------------------------------
    // P O I N T   C U T S
    // ------------------------------------------------------------------------

    /**
     * Selects join points on any public method calls made on the BackendNexus
     * interface implementing proxy from code executing within an LdapContext
     * caller.  Makes sure that Proxy methods (static) and the
     * getInvokationHandler() do not get selected.
     *
     * @param caller the calling LdapContext.
     */
    pointcut jndiNexusCalls( Context caller ):
        this( caller ) &&
        ! this( ContextPartition ) &&
        target( PartitionNexus ) &&
        ! target( Database ) &&
        (
        // these are for the ContextPartition interface methods

        // not used anymore since it was moved to RootNexus class
        // call( public Attributes getRootDSE() ) ||

        call( public Name getMatchedDn( Name, boolean ) ) ||
        call( public Name getSuffix( Name, boolean ) ) ||
		call( public Iterator listSuffixes( boolean ) ) ||
		call( public Attributes lookup( Name, String [] ) ) ||

		// these are for BackingStore interface methods
        call( public void add( String, Name, Attributes ) ) ||
        call( public void delete( Name ) ) ||
		call( public boolean hasEntry( Name ) ) ||
        call( public boolean isSuffix( Name ) ) ||
        call( public NamingEnumeration list( Name ) ) ||
		call( public Attributes lookup( Name ) ) ||
        call( public void modify( Name, int, Attributes ) ) ||
        call( public void modify( Name, ModificationItem [] ) ) ||
        call( public void modifyRn( Name, String, boolean ) ) ||
        call( public void move( Name, Name ) ) ||
        call( public void move( Name, Name, String, boolean ) ) ||
        call( public NamingEnumeration
           search( Name, Map, ExprNode, SearchControls ) ) );

    /**
     * Selects join points where the Invokation default constructor executes.
     *
     * @param invocation the Invocation instantiated
     */
    pointcut newInvocation( Invocation invocation ):
        target( invocation ) &&
        execution( Invocation.new(..) );

    // ------------------------------------------------------------------------
    // A D V I C E
    // ------------------------------------------------------------------------

    before( Context caller ):
        jndiNexusCalls( caller )
        {
    		JndiProvider.push( ( LdapContext ) caller );
            //System.out.println( "\npushed " + caller + " for join point "
            //    + thisJoinPoint );
        }

    after( Context caller ):
        jndiNexusCalls( caller )
        {
            LdapContext head = JndiProvider.pop();
            //System.out.println( "\npopped " + caller + " for join point "
            //    + thisJoinPoint );
        }

    after( Invocation invocation ):
        newInvocation( invocation )
        {
            invocation.setContextStack( getContextStack() );
            //System.out.println(
            //    "\nJust set the context stack on a new Invocation: "
            //    + thisJoinPoint );
        }
}


Fixed #1741.

Fixed #1741.

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

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

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

import java.util.Map;

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

@SuppressWarnings("restriction")
public privileged aspect ScalaJavaBuilderAspect {
  pointcut build() : execution(IProject[] ScalaJavaBuilder.build(int, Map, IProgressMonitor) throws CoreException);
  pointcut cleanOutputFolders(boolean copyBack) : args(copyBack) && execution(void BatchImageBuilder.cleanOutputFolders(boolean) throws CoreException);
  pointcut isJavaLikeFileName(String fileName) : args(fileName) && execution(boolean Util.isJavaLikeFileName(String));

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

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

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

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

import java.util.Map;

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

@SuppressWarnings("restriction")
public aspect ScalaJavaBuilderAspect {
  pointcut build() : execution(IProject[] ScalaJavaBuilder.build(int, Map, IProgressMonitor) throws CoreException);
  pointcut clean() : execution(void ScalaJavaBuilder.clean(IProgressMonitor) throws CoreException);
  pointcut cleanOutputFolders() : execution(void BatchImageBuilder.cleanOutputFolders(boolean) throws CoreException);
  pointcut isJavaLikeFileName(String fileName) : args(fileName) && execution(boolean Util.isJavaLikeFileName(String));

  void around() : cleanOutputFolders() && cflow(build()) {
    // Just suppress the behaviour
  }

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


[Internal: fix lock timeout metrics]

[Internal: fix lock timeout metrics]

package org.zstack.core.aspect;

import com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException;
import org.springframework.transaction.annotation.Transactional;
import org.zstack.core.db.DatabaseGlobalProperty;
import org.zstack.utils.DebugUtils;
import org.zstack.core.db.DatabaseFacadeImpl;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;

public aspect DbDeadlockAspect {
    private static final CLogger logger = Utils.getLogger(DbDeadlockAspect.class);
    private static ThreadLocal<AtomicInteger> local = new ThreadLocal<>();

    declare error: withincode(@org.springframework.transaction.annotation.Transactional * *.*(..)) && withincode(@org.zstack.core.db.DeadlockAutoRestart * *.*(..)) : "@Transactional and @DeadlockAutoRestart can not be present on the same method. @DeadlockAutoRestart must be on parent method which calls method that has @Transactional";

    Object around() : execution(@org.zstack.core.db.DeadlockAutoRestart * *.*(..)) {
        RuntimeException bad = null;
        int times = DatabaseGlobalProperty.retryTimes;
        AtomicInteger refCount = local.get();
        if (refCount == null) {
            refCount = new AtomicInteger(0);
            local.set(refCount);
        }

        refCount.incrementAndGet();
        try {
            do {
                try {
                    return new Callable<Object>() {
                        @Override
                        @Transactional
                        public Object call() {
                           return proceed();
                        }
                    }.call();
                } catch (RuntimeException re) {
                    int c = refCount.get();
                    DatabaseFacadeImpl.increaseDberror();
                    if (c > 1) {
                        logger.warn(String.format("ref = %s, ask outer deadlock handler to handle it", c));
                        throw re;
                    }

                    times --;
                    bad = re;
                    Throwable root = DebugUtils.getRootCause(re);
                    if (root instanceof MySQLTransactionRollbackException && root.getMessage().contains("Deadlock")) {
                        logger.warn("deadlock happened, retry");
                        DatabaseFacadeImpl.increaseDeadlock();
                        try {
                            TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(400, 600));
                        } catch (InterruptedException e) {
                            logger.warn(e.getMessage(), e);
                        }
                    } else {
                        if (root.getMessage().contains("Lock wait timeout")) {
                            DatabaseFacadeImpl.increaseLocktimeout();
                        }
                        throw re;
                    }
                }
            } while (times > 0);

            logger.warn(String.format("DB deadlock still happens after retrying %s times, give up", DatabaseGlobalProperty.retryTimes));
            throw bad;
        } finally {
            refCount.decrementAndGet();
        }
    }
}

package org.zstack.core.aspect;

import com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException;
import org.springframework.transaction.annotation.Transactional;
import org.zstack.core.db.DatabaseGlobalProperty;
import org.zstack.utils.DebugUtils;
import org.zstack.core.db.DatabaseFacadeImpl;
import org.zstack.utils.Utils;
import org.zstack.utils.logging.CLogger;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;

public aspect DbDeadlockAspect {
    private static final CLogger logger = Utils.getLogger(DbDeadlockAspect.class);
    private static ThreadLocal<AtomicInteger> local = new ThreadLocal<>();

    declare error: withincode(@org.springframework.transaction.annotation.Transactional * *.*(..)) && withincode(@org.zstack.core.db.DeadlockAutoRestart * *.*(..)) : "@Transactional and @DeadlockAutoRestart can not be present on the same method. @DeadlockAutoRestart must be on parent method which calls method that has @Transactional";

    Object around() : execution(@org.zstack.core.db.DeadlockAutoRestart * *.*(..)) {
        RuntimeException bad = null;
        int times = DatabaseGlobalProperty.retryTimes;
        AtomicInteger refCount = local.get();
        if (refCount == null) {
            refCount = new AtomicInteger(0);
            local.set(refCount);
        }

        refCount.incrementAndGet();
        try {
            do {
                try {
                    return new Callable<Object>() {
                        @Override
                        @Transactional
                        public Object call() {
                           return proceed();
                        }
                    }.call();
                } catch (RuntimeException re) {
                    int c = refCount.get();
                    DatabaseFacadeImpl.increaseDberror();
                    if (c > 1) {
                        logger.warn(String.format("ref = %s, ask outer deadlock handler to handle it", c));
                        throw re;
                    }

                    times --;
                    bad = re;
                    Throwable root = DebugUtils.getRootCause(re);
                    if (root instanceof MySQLTransactionRollbackException && root.getMessage().contains("Deadlock")) {
                        logger.warn("deadlock happened, retry");
                        DatabaseFacadeImpl.increaseDeadlock();
                        try {
                            TimeUnit.MILLISECONDS.sleep(ThreadLocalRandom.current().nextInt(400, 600));
                        } catch (InterruptedException e) {
                            logger.warn(e.getMessage(), e);
                        }
                    } else {
                        if (root.getMessage().contains("Deadlock")) {
                            DatabaseFacadeImpl.increaseLocktimeout();
                        }
                        throw re;
                    }
                }
            } while (times > 0);

            logger.warn(String.format("DB deadlock still happens after retrying %s times, give up", DatabaseGlobalProperty.retryTimes));
            throw bad;
        } finally {
            refCount.decrementAndGet();
        }
    }
}


Fixed #2621.

Fixed #2621.

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

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

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

import java.util.Locale;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.SourceAnnotationMethodInfo;
import org.eclipse.jdt.internal.core.SourceMethod;
import org.eclipse.jdt.internal.core.SourceMethodElementInfo;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;

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

@SuppressWarnings("restriction")
public privileged aspect DOMAspect {
  pointcut internalCreateAST(ASTParser parser, IProgressMonitor monitor) :
    execution(ASTNode ASTParser.internalCreateAST(IProgressMonitor)) &&
    args(monitor) &&
    target(parser);

  pointcut convert(SourceTypeConverter stc, SourceMethod methodHandle, SourceMethodElementInfo methodInfo, CompilationResult compilationResult) :
    execution(AbstractMethodDeclaration SourceTypeConverter.convert(SourceMethod, SourceMethodElementInfo, CompilationResult)) &&
    args(methodHandle, methodInfo, compilationResult) &&
    target(stc);

  ASTNode around(ASTParser parser, IProgressMonitor monitor) :
    internalCreateAST(parser, monitor) {
    try {
      if (!(parser.typeRoot instanceof IScalaCompilationUnit))
        return proceed(parser, monitor);

      ICompilationUnit cu = (ICompilationUnit)parser.typeRoot;
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit)cu;

      IType[] topLevelTypes = cu.getTypes();
      int length = topLevelTypes.length;
      if (length == 0)
        throw new IllegalStateException();

      SourceTypeElementInfo[] topLevelInfos = new SourceTypeElementInfo[length];
      for (int i = 0; i < length; i++) {
        topLevelInfos[i] = (SourceTypeElementInfo) ((SourceType)topLevelTypes[i]).getElementInfo();
      }
      char[] fileName = ((ISourceType)topLevelInfos[0]).getFileName();

      CompilationResult result = new CompilationResult(fileName, 1, 1, 100);

      JavaProject javaProject = (JavaProject)cu.getJavaProject();
      Map compilerOptions0 = javaProject.getOptions(true);
      CompilerOptions compilerOptions = new CompilerOptions(compilerOptions0);
      compilerOptions.storeAnnotations = true;

      ProblemReporter problemReporter =
        new ProblemReporter(
          DefaultErrorHandlingPolicies.proceedWithAllProblems(),
          compilerOptions,
          new DefaultProblemFactory(Locale.getDefault()));

      int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE;

      CompilationUnitDeclaration unit =
        SourceTypeConverter.buildCompilationUnit(topLevelInfos, flags, problemReporter, result);

      INameEnvironment ne = javaProject.newSearchableNameEnvironment(DefaultWorkingCopyOwner.PRIMARY);
      final LookupEnvironment le = new LookupEnvironment(null, compilerOptions, problemReporter, ne);
      ITypeRequestor typeRequestor = new ITypeRequestor() {
        public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
          le.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
        }
        public void accept(org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit, AccessRestriction accessRestriction) {}
        public void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction) {}
      };
      le.typeRequestor = typeRequestor;

      le.buildTypeBindings(unit, null);
      le.completeTypeBindings();
      fixTypes(unit.types);

      AST ast = AST.newAST(AST.JLS3);
      ast.setFlag(AST.RESOLVED_BINDINGS);
      ast.setDefaultNodeFlag(ASTNode.ORIGINAL);

      org.eclipse.jdt.core.dom.ASTConverter converter =
        new org.eclipse.jdt.core.dom.ASTConverter(compilerOptions0, true, monitor);

      org.eclipse.jdt.core.dom.BindingResolver resolver =
        new org.eclipse.jdt.core.dom.DefaultBindingResolver(
          unit.scope,
          DefaultWorkingCopyOwner.PRIMARY,
          new org.eclipse.jdt.core.dom.DefaultBindingResolver.BindingTables(),
          true);
      ast.setBindingResolver(resolver);
      converter.setAST(ast);

      ASTNode node = converter.convert(unit, sourceUnit.getContents());
      return node;
    } catch (JavaModelException ex) {
      throw new IllegalArgumentException(ex);
    }
  }

  private void fixTypes(TypeDeclaration[] types) {
    for(int i = 0, iLimit = types.length; i < iLimit ; ++i) {
      TypeDeclaration tpe = types[i];
      tpe.binding.getAnnotationTagBits();
      tpe.scope.buildFields();
      tpe.scope.buildMethods();
      fixFields(tpe.fields);
      fixMethods(tpe.methods);
      fixTypes(tpe.memberTypes);
    }
  }

  private void fixMethods(AbstractMethodDeclaration[] methods) {
    if (methods == null)
      return;

    for(int i = 0, iLimit = methods.length; i < iLimit; ++i) {
      AbstractMethodDeclaration m = methods[i];
      m.bodyStart = m.declarationSourceStart;
      m.bodyEnd = m.declarationSourceEnd;
      m.binding.getAnnotationTagBits();
    }
  }

  private void fixFields(AbstractVariableDeclaration[] fields) {
    if (fields == null)
      return;

    for(int i = 0, iLimit = fields.length; i < iLimit; ++i) {
      AbstractVariableDeclaration f = fields[i];
      f.declarationEnd = f.declarationSourceEnd;
    }
  }

  AbstractMethodDeclaration around(SourceTypeConverter stc, SourceMethod methodHandle, SourceMethodElementInfo methodInfo, CompilationResult compilationResult) throws JavaModelException :
    convert(stc, methodHandle, methodInfo, compilationResult) {
    AbstractMethodDeclaration method;

    /* only source positions available */
    int start = methodInfo.getNameSourceStart();
    int end = methodInfo.getNameSourceEnd();

    // convert 1.5 specific constructs only if compliance is 1.5 or above
    TypeParameter[] typeParams = null;
    if (stc.has1_5Compliance) {
      /* convert type parameters */
      char[][] typeParameterNames = methodInfo.getTypeParameterNames();
      if (typeParameterNames != null) {
        int parameterCount = typeParameterNames.length;
        if (parameterCount > 0) { // method's type parameters must be null if no type parameter
          char[][][] typeParameterBounds = methodInfo.getTypeParameterBounds();
          typeParams = new TypeParameter[parameterCount];
          for (int i = 0; i < parameterCount; i++) {
            typeParams[i] = stc.createTypeParameter(typeParameterNames[i], typeParameterBounds[i], start, end);
          }
        }
      }
    }

    int modifiers = methodInfo.getModifiers();
    if (methodInfo.isConstructor()) {
      ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
      decl.bits &= ~org.eclipse.jdt.internal.compiler.ast.ASTNode.IsDefaultConstructor;
      method = decl;
      decl.typeParameters = typeParams;
    } else {
      MethodDeclaration decl;
      if (methodInfo.isAnnotationMethod()) {
        AnnotationMethodDeclaration annotationMethodDeclaration = new AnnotationMethodDeclaration(compilationResult);

        /* conversion of default value */
        SourceAnnotationMethodInfo annotationMethodInfo = (SourceAnnotationMethodInfo) methodInfo;
        boolean hasDefaultValue = annotationMethodInfo.defaultValueStart != -1 || annotationMethodInfo.defaultValueEnd != -1;
        if ((stc.flags & SourceTypeConverter.FIELD_INITIALIZATION) != 0) {
          if (hasDefaultValue) {
            char[] defaultValueSource = CharOperation.subarray(stc.getSource(), annotationMethodInfo.defaultValueStart, annotationMethodInfo.defaultValueEnd+1);
            if (defaultValueSource != null) {
                Expression expression =  stc.parseMemberValue(defaultValueSource);
                if (expression != null) {
                  annotationMethodDeclaration.defaultValue = expression;
                }
            } else {
              // could not retrieve the default value
              hasDefaultValue = false;
            }
          }
        }
        if (hasDefaultValue)
          modifiers |= ClassFileConstants.AccAnnotationDefault;
        decl = annotationMethodDeclaration;
      } else {
        decl = new MethodDeclaration(compilationResult);
      }

      // convert return type
      decl.returnType = stc.createTypeReference(methodInfo.getReturnTypeName(), start, end);

      // type parameters
      decl.typeParameters = typeParams;

      method = decl;
    }
    method.selector = methodHandle.getElementName().toCharArray();
    boolean isVarargs = (modifiers & ClassFileConstants.AccVarargs) != 0;
    method.modifiers = modifiers & ~ClassFileConstants.AccVarargs;
    method.sourceStart = start;
    method.sourceEnd = end;
    method.declarationSourceStart = methodInfo.getDeclarationSourceStart();
    method.declarationSourceEnd = methodInfo.getDeclarationSourceEnd();

    // convert 1.5 specific constructs only if compliance is 1.5 or above
    if (stc.has1_5Compliance) {
      /* convert annotations */
      method.annotations = stc.convertAnnotations(methodHandle);
    }

    /* convert arguments */
    String[] argumentTypeSignatures = methodHandle.getParameterTypes();
    char[][] argumentNames = methodInfo.getArgumentNames();
    int argumentCount = argumentTypeSignatures == null ? 0 : argumentTypeSignatures.length;
    if (argumentCount > 0) {
      long position = ((long) start << 32) + end;
      method.arguments = new Argument[argumentCount];
      for (int i = 0; i < argumentCount; i++) {
        TypeReference typeReference = stc.createTypeReference(argumentTypeSignatures[i], start, end);
        if (isVarargs && i == argumentCount-1) {
          typeReference.bits |= org.eclipse.jdt.internal.compiler.ast.ASTNode.IsVarArgs;
        }
        method.arguments[i] =
          new Argument(
            argumentNames[i],
            position,
            typeReference,
            ClassFileConstants.AccDefault);
        // do not care whether was final or not
      }
    }

    /* convert thrown exceptions */
    char[][] exceptionTypeNames = methodInfo.getExceptionTypeNames();
    int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
    if (exceptionCount > 0) {
      method.thrownExceptions = new TypeReference[exceptionCount];
      for (int i = 0; i < exceptionCount; i++) {
        method.thrownExceptions[i] =
          stc.createTypeReference(exceptionTypeNames[i], start, end);
      }
    }

    /* convert local and anonymous types */
    if ((stc.flags & SourceTypeConverter.LOCAL_TYPE) != 0) {
      IJavaElement[] children = methodInfo.getChildren();
      int typesLength = 0;
      int childrenLength = children.length;
      for (int i = 0; i < childrenLength; ++i)
        if (children[i] instanceof SourceType)
          ++typesLength;

      if (typesLength != 0) {
        Statement[] statements = new Statement[typesLength];
        int typeIndex = 0;
        for (int i = 0; i < childrenLength; i++) {
          if (children[i] instanceof SourceType) {
            SourceType type = (SourceType) children[i];
            TypeDeclaration localType = stc.convert(type, compilationResult);
            if ((localType.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousType) != 0) {
              QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
              expression.type = localType.superclass;
              localType.superclass = null;
              localType.superInterfaces = null;
              localType.allocation = expression;
              statements[typeIndex] = expression;
            } else {
              statements[typeIndex] = localType;
            }
            ++typeIndex;
          }
        }
        method.statements = statements;
      }
    }

    return method;
  }
}

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

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

import java.util.Locale;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;

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

@SuppressWarnings("restriction")
public privileged aspect DOMAspect {
  pointcut internalCreateAST(ASTParser parser, IProgressMonitor monitor) :
    execution(ASTNode ASTParser.internalCreateAST(IProgressMonitor)) &&
    args(monitor) &&
    target(parser);

  ASTNode around(ASTParser parser, IProgressMonitor monitor) :
    internalCreateAST(parser, monitor) {
    try {
      if (!(parser.typeRoot instanceof IScalaCompilationUnit))
        return proceed(parser, monitor);

      ICompilationUnit cu = (ICompilationUnit)parser.typeRoot;
      org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit)cu;

      IType[] topLevelTypes = cu.getTypes();
      int length = topLevelTypes.length;
      if (length == 0)
        throw new IllegalStateException();

      SourceTypeElementInfo[] topLevelInfos = new SourceTypeElementInfo[length];
      for (int i = 0; i < length; i++) {
        topLevelInfos[i] = (SourceTypeElementInfo) ((SourceType)topLevelTypes[i]).getElementInfo();
      }
      char[] fileName = ((ISourceType)topLevelInfos[0]).getFileName();

      CompilationResult result = new CompilationResult(fileName, 1, 1, 100);

      JavaProject javaProject = (JavaProject)cu.getJavaProject();
      Map compilerOptions0 = javaProject.getOptions(true);
      CompilerOptions compilerOptions = new CompilerOptions(compilerOptions0);
      compilerOptions.storeAnnotations = true;

      ProblemReporter problemReporter =
        new ProblemReporter(
          DefaultErrorHandlingPolicies.proceedWithAllProblems(),
          compilerOptions,
          new DefaultProblemFactory(Locale.getDefault()));

      int flags = SourceTypeConverter.FIELD_AND_METHOD | SourceTypeConverter.MEMBER_TYPE;

      CompilationUnitDeclaration unit =
        SourceTypeConverter.buildCompilationUnit(topLevelInfos, flags, problemReporter, result);

      INameEnvironment ne = javaProject.newSearchableNameEnvironment(DefaultWorkingCopyOwner.PRIMARY);
      final LookupEnvironment le = new LookupEnvironment(null, compilerOptions, problemReporter, ne);
      ITypeRequestor typeRequestor = new ITypeRequestor() {
        public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
          le.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
        }
        public void accept(org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit, AccessRestriction accessRestriction) {}
        public void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction) {}
      };
      le.typeRequestor = typeRequestor;

      le.buildTypeBindings(unit, null);
      le.completeTypeBindings();
      fixTypes(unit.types);

      AST ast = AST.newAST(AST.JLS3);
      ast.setFlag(AST.RESOLVED_BINDINGS);
      ast.setDefaultNodeFlag(ASTNode.ORIGINAL);

      org.eclipse.jdt.core.dom.ASTConverter converter =
        new org.eclipse.jdt.core.dom.ASTConverter(compilerOptions0, true, monitor);

      org.eclipse.jdt.core.dom.BindingResolver resolver =
        new org.eclipse.jdt.core.dom.DefaultBindingResolver(
          unit.scope,
          DefaultWorkingCopyOwner.PRIMARY,
          new org.eclipse.jdt.core.dom.DefaultBindingResolver.BindingTables(),
          true);
      ast.setBindingResolver(resolver);
      converter.setAST(ast);

      ASTNode node = converter.convert(unit, sourceUnit.getContents());
      return node;
    } catch (JavaModelException ex) {
      throw new IllegalArgumentException(ex);
    }
  }

  private void fixTypes(TypeDeclaration[] types) {
    for(int i = 0, iLimit = types.length; i < iLimit ; ++i) {
      TypeDeclaration tpe = types[i];
      tpe.binding.getAnnotationTagBits();
      tpe.scope.buildFields();
      tpe.scope.buildMethods();
      fixFields(tpe.fields);
      fixMethods(tpe.methods);
      fixTypes(tpe.memberTypes);
    }
  }

  private void fixMethods(AbstractMethodDeclaration[] methods) {
    if (methods == null)
      return;

    for(int i = 0, iLimit = methods.length; i < iLimit; ++i) {
      AbstractMethodDeclaration m = methods[i];
      m.bodyStart = m.declarationSourceStart;
      m.bodyEnd = m.declarationSourceEnd;
      m.binding.getAnnotationTagBits();
    }
  }

  private void fixFields(AbstractVariableDeclaration[] fields) {
    if (fields == null)
      return;

    for(int i = 0, iLimit = fields.length; i < iLimit; ++i) {
      AbstractVariableDeclaration f = fields[i];
      f.declarationEnd = f.declarationSourceEnd;
    }
  }
}


removed connection scope access

removed connection scope access

package de.cosmocode.palava.jpa;

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.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;

public final aspect TransactionAspect issingleton() {

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

    private Provider<EntityManager> currentManager;

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

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

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

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

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final EntityManager manager = currentManager.get();
        final EntityTransaction tx = manager.getTransaction();
        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.error("Exception inside automatic transaction context", e);
            tx.rollback();
            throw e;
        }

        try {
            if (localTx) {
                tx.commit();
                LOG.trace("Committed automatic transaction");
            }
            return returnValue;
        } catch (PersistenceException e) {
            LOG.error("Commit in automatic transaction context failed", e);
            tx.rollback();
            throw e;
        }
    }

}

package de.cosmocode.palava.jpa;

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.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;

import de.cosmocode.palava.ipc.IpcConnection;

public final aspect TransactionAspect issingleton() {

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

    private Provider<EntityManager> currentManager;
    private Provider<IpcConnection> currentConnection;

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

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

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

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

    @SuppressAjWarnings("adviceDidNotMatch")
    Object around(): transactional() {
        final IpcConnection connection = currentConnection.get();
        final Key<EntityManager> key = Key.get(EntityManager.class);
        EntityManager manager = connection == null ? null : EntityManager.class.cast(connection.get(key));
        if (manager == null) {
            manager = currentManager.get();
        }
        final EntityTransaction tx = manager.getTransaction();
        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.error("Exception inside automatic transaction context", e);
            tx.rollback();
            throw e;
        }

        try {
            if (localTx) {
                tx.commit();
                LOG.trace("Committed automatic transaction");
            }
            return returnValue;
        } catch (PersistenceException e) {
            LOG.error("Commit in automatic transaction context failed", e);
            tx.rollback();
            throw e;
        }
    }

}


+ temporarily revert change

+ temporarily revert change

/*
 * Copyright 2002-2011 the original author or 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.springframework.cache.aspectj;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cache.interceptor.CacheAspectSupport;
import org.springframework.cache.interceptor.CacheOperationSource;

/**
 * Abstract superaspect for AspectJ cache aspects. Concrete
 * subaspects will implement the cacheMethodExecution()
 * pointcut using a strategy such as Java 5 annotations.
 *
 *
Suitable for use inside or outside the Spring IoC container.
 * Set the "cacheManager" property appropriately, allowing
 * use of any cache implementation supported by Spring.
 *
 *
NB: If a method implements an interface that is itself
 * cache annotated, the relevant Spring cache definition
 * will not be resolved.
 *
 * @author Costin Leau
 * @since 3.1
 */
public abstract aspect AbstractCacheAspect extends CacheAspectSupport {

	protected AbstractCacheAspect() {
	}

	/**
	 * Construct object using the given caching metadata retrieval strategy.
	 * @param cos {@link CacheOperationSource} implementation, retrieving Spring
	 * cache metadata for each joinpoint.
	 */
	protected AbstractCacheAspect(CacheOperationSource... cos) {
		setCacheOperationSources(cos);
	}

	@SuppressAjWarnings("adviceDidNotMatch")
	Object around(final Object cachedObject) : cacheMethodExecution(cachedObject) {
		MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
		Method method = methodSignature.getMethod();

		Callable<Object> ajInvocation = new Callable<Object>() {
			public Object call() {
				return proceed(cachedObject);
			}
		};

		try{
			return execute(ajInvocation, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
		} catch (Exception ex){
			throw new RuntimeException("Cannot cache target ", ex);
		}
	}

	/**
	 * Concrete subaspects must implement this pointcut, to identify
	 * cached methods. For each selected joinpoint, {@link CacheOperationDefinition}
	 * will be retrieved using Spring's {@link CacheOperationSource} interface.
	 */
	protected abstract pointcut cacheMethodExecution(Object cachedObject);

}

/*
 * Copyright 2002-2011 the original author or 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.springframework.cache.aspectj;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;

import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cache.interceptor.CacheAspectSupport;
import org.springframework.cache.interceptor.CacheOperationSource;

/**
 * Abstract superaspect for AspectJ cache aspects. Concrete
 * subaspects will implement the cacheMethodExecution()
 * pointcut using a strategy such as Java 5 annotations.
 *
 *
Suitable for use inside or outside the Spring IoC container.
 * Set the "cacheManager" property appropriately, allowing
 * use of any cache implementation supported by Spring.
 *
 *
NB: If a method implements an interface that is itself
 * cache annotated, the relevant Spring cache definition
 * will not be resolved.
 *
 * @author Costin Leau
 * @since 3.1
 */
public abstract aspect AbstractCacheAspect extends CacheAspectSupport {

	protected AbstractCacheAspect() {
	}

	/**
	 * Construct object using the given caching metadata retrieval strategy.
	 * @param cos {@link CacheOperationSource} implementation, retrieving Spring
	 * cache metadata for each joinpoint.
	 */
	protected AbstractCacheAspect(CacheOperationSource... cos) {
		setCacheOperationSources(cos);
	}

	@SuppressAjWarnings("adviceDidNotMatch")
	Object around(final Object cachedObject) : cacheMethodExecution(cachedObject){
		MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
		Method method = methodSignature.getMethod();

		Callable<Object> ajInvocation = new Callable<Object>() {
			public Object call() {
				return proceed(cachedObject);
			}
		};

		return execute(ajInvocation, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
	}

	/**
	 * Concrete subaspects must implement this pointcut, to identify
	 * cached methods. For each selected joinpoint, {@link CacheOperationDefinition}
	 * will be retrieved using Spring's {@link CacheOperationSource} interface.
	 */
	protected abstract pointcut cacheMethodExecution(Object cachedObject);

}