Package org.apache.maven.archiva.reporting.processor

Source Code of org.apache.maven.archiva.reporting.processor.LocationArtifactReportProcessor

package org.apache.maven.archiva.reporting.processor;

/*
* 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 org.apache.commons.io.IOUtils;
import org.apache.maven.archiva.reporting.database.ArtifactResultsDatabase;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
* Validate the location of the artifact based on the values indicated
* in its pom (both the pom packaged with the artifact & the pom in the
* file system).
*
* @plexus.component role="org.apache.maven.archiva.reporting.processor.ArtifactReportProcessor" role-hint="artifact-location"
*/
public class LocationArtifactReportProcessor
    implements ArtifactReportProcessor
{
    /**
     * @plexus.requirement
     */
    private ArtifactFactory artifactFactory;

    // TODO: share with other code with the same
    private static final Set JAR_FILE_TYPES = new HashSet( Arrays.asList( new String[] {
        "jar",
        "war",
        "par",
        "ejb",
        "ear",
        "rar",
        "sar" } ) );

    /**
     * @plexus.requirement
     */
    private ArtifactResultsDatabase database;

    private static final String POM = "pom";

    private static final String ROLE_HINT = "artifact-location";

    /**
     * Check whether the artifact is in its proper location. The location of the artifact
     * is validated first against the groupId, artifactId and versionId in the specified model
     * object (pom in the file system). Then unpack the artifact (jar file) and get the model (pom)
     * included in the package. If a model exists inside the package, then check if the artifact's
     * location is valid based on the location specified in the pom. Check if the both the location
     * specified in the file system pom and in the pom included in the package is the same.
     */
    public void processArtifact( Artifact artifact, Model model )
    {
        ArtifactRepository repository = artifact.getRepository();

        if ( !"file".equals( repository.getProtocol() ) )
        {
            // We can't check other types of URLs yet. Need to use Wagon, with an exists() method.
            throw new UnsupportedOperationException( "Can't process repository '" + repository.getUrl()
                + "'. Only file based repositories are supported" );
        }

        adjustDistributionArtifactHandler( artifact );

        String artifactPath = repository.pathOf( artifact );

        if ( model != null )
        {
            // only check if it is a standalone POM, or an artifact other than a POM
            // ie, don't check the location of the POM for another artifact matches that of the artifact
            if ( !POM.equals( artifact.getType() ) || POM.equals( model.getPackaging() ) )
            {
                //check if the artifact is located in its proper location based on the info
                //specified in the model object/pom
                Artifact modelArtifact = artifactFactory.createArtifactWithClassifier( model.getGroupId(), model
                    .getArtifactId(), model.getVersion(), artifact.getType(), artifact.getClassifier() );

                adjustDistributionArtifactHandler( modelArtifact );
                String modelPath = repository.pathOf( modelArtifact );
                if ( !modelPath.equals( artifactPath ) )
                {
                    addFailure( artifact, "repository-pom-location",
                                "The artifact is out of place. It does not match the specified location in the repository pom: "
                                    + modelPath );
                }
            }
        }

        // get the location of the artifact itself
        File file = new File( repository.getBasedir(), artifactPath );

        if ( file.exists() )
        {
            if ( JAR_FILE_TYPES.contains( artifact.getType() ) )
            {
                //unpack the artifact (using the groupId, artifactId & version specified in the artifact object itself
                //check if the pom is included in the package
                Model extractedModel = readArtifactModel( file, artifact );

                if ( extractedModel != null )
                {
                    Artifact extractedArtifact = artifactFactory.createBuildArtifact( extractedModel.getGroupId(),
                                                                                      extractedModel.getArtifactId(),
                                                                                      extractedModel.getVersion(),
                                                                                      extractedModel.getPackaging() );
                    if ( !repository.pathOf( extractedArtifact ).equals( artifactPath ) )
                    {
                        addFailure( artifact, "packaged-pom-location",
                                    "The artifact is out of place. It does not match the specified location in the packaged pom." );
                    }
                }
            }
        }
        else
        {
            addFailure( artifact, "missing-artifact", "The artifact file [" + file + "] cannot be found for metadata." );
        }
    }

    private void addFailure( Artifact artifact, String problem, String reason )
    {
        // TODO: reason could be an i18n key derived from the processor and the problem ID and the
        database.addFailure( artifact, ROLE_HINT, problem, reason );
    }

    private static void adjustDistributionArtifactHandler( Artifact artifact )
    {
        // need to tweak these as they aren't currently in the known type converters. TODO - add them in Maven
        if ( "distribution-zip".equals( artifact.getType() ) )
        {
            artifact.setArtifactHandler( new DefaultArtifactHandler( "zip" ) );
        }
        else if ( "distribution-tgz".equals( artifact.getType() ) )
        {
            artifact.setArtifactHandler( new DefaultArtifactHandler( "tar.gz" ) );
        }
    }

    private Model readArtifactModel( File file, Artifact artifact )
    {
        Model model = null;

        JarFile jar = null;
        try
        {
            jar = new JarFile( file );

            //Get the entry and its input stream.
            JarEntry entry = jar.getJarEntry( "META-INF/maven/" + artifact.getGroupId() + "/"
                + artifact.getArtifactId() + "/pom.xml" );

            // If the entry is not null, extract it.
            if ( entry != null )
            {
                model = readModel( jar.getInputStream( entry ) );

                if ( model.getGroupId() == null )
                {
                    model.setGroupId( model.getParent().getGroupId() );
                }
                if ( model.getVersion() == null )
                {
                    model.setVersion( model.getParent().getVersion() );
                }
            }
        }
        catch ( IOException e )
        {
            addWarning( artifact, "Unable to read artifact to extract model: " + e );
        }
        catch ( XmlPullParserException e )
        {
            addWarning( artifact, "Unable to parse extracted model: " + e );
        }
        finally
        {
            if ( jar != null )
            {
                //noinspection UnusedCatchParameter
                try
                {
                    jar.close();
                }
                catch ( IOException e )
                {
                    // ignore
                }
            }
        }
        return model;
    }

    private void addWarning( Artifact artifact, String reason )
    {
        // TODO: reason could be an i18n key derived from the processor and the problem ID and the
        database.addWarning( artifact, ROLE_HINT, "bad-location", reason );
    }

    private Model readModel( InputStream entryStream )
        throws IOException, XmlPullParserException
    {
        Reader isReader = new InputStreamReader( entryStream );

        Model model;
        try
        {
            MavenXpp3Reader pomReader = new MavenXpp3Reader();
            model = pomReader.read( isReader );
        }
        finally
        {
            IOUtils.closeQuietly( isReader );
        }
        return model;
    }

}
TOP

Related Classes of org.apache.maven.archiva.reporting.processor.LocationArtifactReportProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.