package org.apache.maven.extension;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

import static org.apache.maven.container.ContainerUtils.findChildComponentHints;

import org.apache.maven.MavenArtifactFilterManager;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.manager.WagonManager;
import org.apache.maven.artifact.metadata.ArtifactMetadataRetrievalException;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
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.resolver.ArtifactResolutionResult;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.model.Extension;
import org.apache.maven.plugin.DefaultPluginManager;
import org.apache.maven.project.DefaultProjectBuilderConfiguration;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilderConfiguration;
import org.apache.maven.wagon.Wagon;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.classworlds.ClassWorld;
import org.codehaus.classworlds.DuplicateRealmException;
import org.codehaus.classworlds.NoSuchRealmException;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.context.ContextException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;

import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarFile;

/**
 * Used to locate extensions.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @author Jason van Zyl
 * @version $Id$
 */
public class DefaultExtensionManager
    extends AbstractLogEnabled
    implements ExtensionManager, Contextualizable
{
    private ArtifactResolver artifactResolver;

    private ArtifactFactory artifactFactory;

    private ArtifactMetadataSource artifactMetadataSource;

    private DefaultPlexusContainer container;

    private ArtifactFilter artifactFilter = MavenArtifactFilterManager.createExtensionFilter();

    private WagonManager wagonManager;

    private PlexusContainer extensionContainer;

    private static final String CONTAINER_NAME = "extensions";

    public void addExtension( Extension extension,
                              MavenProject project,
                              ArtifactRepository localRepository )
        throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException
    {
        addExtension( extension, project, new DefaultProjectBuilderConfiguration().setLocalRepository( localRepository ) );
    }
    
    public void addExtension( Extension extension,
                              MavenProject project,
                              ProjectBuilderConfiguration builderConfig )
        throws ArtifactResolutionException, PlexusContainerException, ArtifactNotFoundException
    {
        String extensionId = ArtifactUtils.versionlessKey( extension.getGroupId(), extension.getArtifactId() );

        getLogger().debug( "Initialising extension: " + extensionId );

        Artifact artifact = (Artifact) project.getExtensionArtifactMap().get( extensionId );

        if ( artifact != null )
        {
            ArtifactFilter filter = new ProjectArtifactExceptionFilter( artifactFilter, project.getArtifact() );
            
            ArtifactMetadataSource metadataSource = builderConfig.getMetadataSource();
            if ( metadataSource == null )
            {
                metadataSource = artifactMetadataSource;
            }

            ResolutionGroup resolutionGroup;
            try
            {
                resolutionGroup = metadataSource.retrieve( artifact, builderConfig.getLocalRepository(),
                                                                   project.getRemoteArtifactRepositories() );
            }
            catch ( ArtifactMetadataRetrievalException e )
            {
                throw new ArtifactResolutionException( "Unable to download metadata from repository for plugin '" +
                    artifact.getId() + "': " + e.getMessage(), artifact, e );
            }

            // 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<Artifact> rgArtifacts = resolutionGroup.getArtifacts();
            rgArtifacts = DefaultPluginManager.checkPlexusUtils( rgArtifacts, artifactFactory );

            Set<Artifact> dependencies = new LinkedHashSet<Artifact>();
            dependencies.add( artifact );
            dependencies.addAll( rgArtifacts );

            // Make sure that we do not influence the dependenecy resolution of extensions with the project's
            // dependencyManagement

            ArtifactResolutionResult result = artifactResolver.resolveTransitively( dependencies, project.getArtifact(),
                                                                                    Collections.EMPTY_MAP,
                                                                                    //project.getManagedVersionMap(),
                                                                                    builderConfig.getLocalRepository(),
                                                                                    project.getRemoteArtifactRepositories(),
                                                                                    metadataSource, filter );

            // gross hack for some backwards compat (MNG-2749)
            // if it is a lone artifact, then we assume it to be a resource package, and put it in the main container
            // as before. If it has dependencies, that's when we risk conflict and exile to the child container
            // jvz: we have to make this 2 because plexus is always added now.

            Set<Artifact> artifacts = result.getArtifacts();

            // Lifecycles are loaded by the Lifecycle executor by looking up lifecycle definitions from the
            // core container. So we need to look if an extension has a lifecycle mapping and use the container
            // and not an extension container. (MNG-2831)

            if ( extensionContainsLifeycle( artifact.getFile() ) )
            {
                for ( Artifact a : artifacts )
                {
                    if ( artifactFilter.include( a ) )
                    {
                        getLogger().debug( "Adding extension to core container: " + a.getFile() );

                        container.addJarResource( a.getFile() );
                    }
                }
            }
            else if ( artifacts.size() == 2 )
            {
                for ( Artifact a : artifacts )
                {
                    if ( !a.getArtifactId().equals( "plexus-utils" ) )
                    {
                        a = project.replaceWithActiveArtifact( a );

                        getLogger().debug( "Adding extension to core container: " + a.getFile() );

                        container.addJarResource( a.getFile() );
                    }
                }
            }
            else
            {
                // create a child container for the extension
                // TODO: this could surely be simpler/different on trunk with the new classworlds

                if ( extensionContainer == null )
                {
                    extensionContainer = createContainer();
                }

                for ( Artifact a : (Set<Artifact>) result.getArtifacts() )
                {
                    a = project.replaceWithActiveArtifact( a );

                    getLogger().debug( "Adding to extension classpath: " + a.getFile() );

                    extensionContainer.addJarResource( a.getFile() );
                }

                if ( getLogger().isDebugEnabled() )
                {
                    getLogger().debug( "Extension container contents:" );
                    extensionContainer.getContainerRealm().display();
                }
            }
        }
    }

    private PlexusContainer createContainer()
        throws PlexusContainerException
    {
        DefaultPlexusContainer child = new DefaultPlexusContainer();

        ClassWorld classWorld = container.getClassWorld();
        child.setClassWorld( classWorld );

        ClassRealm childRealm = null;

        // note: ideally extensions would live in their own realm, but this would mean that things like wagon-scm would
        // have no way to obtain SCM extensions
        String childRealmId = "plexus.core.child-container[" + CONTAINER_NAME + "]";
        try
        {
            childRealm = classWorld.getRealm( childRealmId );
        }
        catch ( NoSuchRealmException e )
        {
            try
            {
                childRealm = classWorld.newRealm( childRealmId );
            }
            catch ( DuplicateRealmException impossibleError )
            {
                getLogger().error( "An impossible error has occurred. After getRealm() failed, newRealm() " +
                    "produced duplication error on same id!", impossibleError );
            }
        }

        childRealm.setParent( container.getContainerRealm() );

        child.setCoreRealm( childRealm );

        child.setName( CONTAINER_NAME );

        // This is what we are skipping - we use the parent realm, but not the parent container since otherwise
        // we won't reload component descriptors that already exist in there
//        child.setParentPlexusContainer( this );

        // ----------------------------------------------------------------------
        // Set all the child elements from the parent that were set
        // programmatically.
        // ----------------------------------------------------------------------

        child.setLoggerManager( container.getLoggerManager() );

        child.initialize();

        child.start();

        return child;
    }

    public void registerWagons()
    {
        if ( extensionContainer != null )
        {
            Set<String> wagons = findChildComponentHints( Wagon.ROLE, container, extensionContainer );
            if ( wagons != null && !wagons.isEmpty() )
            {
                getLogger().debug( "Wagons to register: " + wagons );
                wagonManager.registerWagons( wagons, extensionContainer );
            }
        }
        else
        {
            getLogger().debug( "Wagons could not be registered as the extension container was never created" );
        }
    }
    
    @SuppressWarnings( "unchecked" )
    public Map<String, ArtifactHandler> getArtifactTypeHandlers()
    {
        Map<String, ArtifactHandler> result = new HashMap<String, ArtifactHandler>();
        
        if ( extensionContainer != null )
        {
            try
            {
                result.putAll( extensionContainer.lookupMap( ArtifactHandler.ROLE ) );
            }
            catch ( ComponentLookupException e )
            {
                getLogger().debug( "ArtifactHandler extensions could not be loaded: " + e.getMessage(), e );
            }
        }
        else
        {
            try
            {
                result.putAll( container.lookupMap( ArtifactHandler.ROLE ) );
            }
            catch ( ComponentLookupException e )
            {
                getLogger().debug( "ArtifactHandler extensions could not be loaded: " + e.getMessage(), e );
            }
        }
        
        return result;
    }

    public void contextualize( Context context )
        throws ContextException
    {
        container = (DefaultPlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
    }

    private static final class ProjectArtifactExceptionFilter
        implements ArtifactFilter
    {
        private ArtifactFilter passThroughFilter;

        private String projectDependencyConflictId;

        ProjectArtifactExceptionFilter( ArtifactFilter passThroughFilter,
                                        Artifact projectArtifact )
        {
            this.passThroughFilter = passThroughFilter;
            projectDependencyConflictId = projectArtifact.getDependencyConflictId();
        }

        public boolean include( Artifact artifact )
        {
            String depConflictId = artifact.getDependencyConflictId();

            return projectDependencyConflictId.equals( depConflictId ) || passThroughFilter.include( artifact );
        }
    }

    private boolean extensionContainsLifeycle( File extension )
    {
        JarFile f;

        try
        {
            f = new JarFile( extension );

            InputStream is = f.getInputStream( f.getEntry( "META-INF/plexus/components.xml" ) );

            if ( is == null )
            {
                return false;
            }

            Xpp3Dom dom = Xpp3DomBuilder.build( new InputStreamReader( is ) );

            Xpp3Dom[] components = dom.getChild( "components" ).getChildren( "component" );

            for ( int i = 0; i < components.length; i++ )
            {
                if ( components[i].getChild( "role" ).getValue().equals( "org.apache.maven.lifecycle.mapping.LifecycleMapping" ) )
                {
                    return true;
                }
            }
        }
        catch( Exception e )
        {
            // do nothing
        }

        return false;
    }
}
