org.ops4j.pax.url.maven.internal.Connection.java Source code

Java tutorial

Introduction

Here is the source code for org.ops4j.pax.url.maven.internal.Connection.java

Source

/*
 * Copyright 2009 Alin Dreghiciu.
 *
 * 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.ops4j.pax.url.maven.internal;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.maven.mercury.artifact.Artifact;
import org.apache.maven.mercury.artifact.ArtifactMetadata;
import org.apache.maven.mercury.artifact.Quality;
import org.apache.maven.mercury.artifact.QualityRange;
import org.apache.maven.mercury.builder.api.DependencyProcessor;
import org.apache.maven.mercury.repository.api.ArtifactResults;
import org.apache.maven.mercury.repository.api.MetadataResults;
import org.apache.maven.mercury.repository.api.Repository;
import org.apache.maven.mercury.repository.api.RepositoryException;
import org.apache.maven.mercury.repository.local.m2.LocalRepositoryM2;
import org.apache.maven.mercury.repository.remote.m2.RemoteRepositoryM2;
import org.apache.maven.mercury.repository.virtual.VirtualRepositoryReader;
import org.apache.maven.mercury.transport.api.Server;
import org.ops4j.lang.NullArgumentException;
import org.ops4j.pax.url.maven.commons.MavenConfiguration;
import org.ops4j.pax.url.maven.commons.MavenRepositoryURL;

/**
 * An URLConnextion that supports maven: protocol.
 *
 * @author Alin Dreghiciu (adreghiciu@gmail.com)
 * @since 0.5.0, March 22, 2009
 */
public class Connection extends URLConnection {

    /**
     * Logger.
     */
    private static final Log LOG = LogFactory.getLog(Connection.class);
    /**
     * Service configuration.
     */
    private final MavenConfiguration m_configuration;
    /**
     * Parsed url.
     */
    private Parser m_parser;
    /**
     * Mercury virtual repository reader.
     */
    private VirtualRepositoryReader m_vrr;

    /**
     * Creates a new connection.
     *
     * @param url           the url; cannot be null.
     * @param configuration service configuration; cannot be null
     *
     * @throws java.net.MalformedURLException in case of a malformed url
     */
    public Connection(final URL url, final MavenConfiguration configuration) throws MalformedURLException {
        super(url);
        NullArgumentException.validateNotNull(url, "URL cannot be null");
        NullArgumentException.validateNotNull(configuration, "Service configuration");
        m_configuration = configuration;
        m_parser = new Parser(url.getPath());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void connect() throws IOException {
        final List<Repository> repositories = new ArrayList<Repository>();
        final MavenRepositoryURL localRepository = m_configuration.getLocalRepository();
        if (localRepository != null) {
            LOG.debug("Using local repository " + localRepository);
            repositories.add(toRepository(localRepository));
        }
        final List<MavenRepositoryURL> remoteRepos = new ArrayList<MavenRepositoryURL>();
        if (m_parser.getRepositoryURL() != null) {
            remoteRepos.add(m_parser.getRepositoryURL());
        }
        remoteRepos.addAll(m_configuration.getRepositories());
        for (MavenRepositoryURL repositoryURL : remoteRepos) {
            LOG.debug("Using remote repository " + repositoryURL);
            repositories.add(toRepository(repositoryURL));
        }
        try {
            m_vrr = new VirtualRepositoryReader(repositories);
        } catch (RepositoryException e) {
            throw initIOException("Cannot configure Maven repositories", e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public InputStream getInputStream() throws IOException {
        connect();

        LOG.debug("Resolving [" + url.toExternalForm() + "]");

        List<ArtifactMetadata> query = new ArrayList<ArtifactMetadata>();
        final ArtifactMetadata queryMeta = new ArtifactMetadata(m_parser.getGAV());
        query.add(queryMeta);

        final MetadataResults results;
        try {
            results = m_vrr.readVersions(query);
        } catch (RepositoryException e) {
            throw initIOException("Canot determine artifacts versions", e);
        }
        if (results == null) {
            throw new IOException("Cannot determine artifact versions from [" + m_parser.getGAV() + "]");
        }
        if (results.hasExceptions() || !results.hasResults(queryMeta)) {
            //noinspection ThrowableResultOfMethodCallIgnored
            throw initIOException("Cannot determine artifact versions", results.getError(queryMeta));
        }

        final List<ArtifactMetadata> foundArtifacts = results.getResult(queryMeta);
        for (ArtifactMetadata foundArtifact : foundArtifacts) {
            LOG.debug("Found artifact [" + foundArtifact.getGAV() + "]");
        }

        // download the artifact
        // TODO selecting the last artifact in the list is not the correct approach
        final ArtifactMetadata selectedArtifact = foundArtifacts.get(foundArtifacts.size() - 1);

        LOG.debug("Selected artifact [" + selectedArtifact.getGAV() + "]");

        final ArtifactResults artifactResults;
        try {
            artifactResults = m_vrr.readArtifacts(toList(selectedArtifact));
        } catch (RepositoryException e) {
            e.printStackTrace();
            throw initIOException("Canot download artifact [" + selectedArtifact.getGAV() + "]", e);
        }
        if (artifactResults.hasExceptions() || !artifactResults.hasResults(selectedArtifact)) {
            //noinspection ThrowableResultOfMethodCallIgnored
            throw initIOException("Cannot download artifact [" + selectedArtifact.getGAV() + "]",
                    artifactResults.getError(selectedArtifact));
        }
        final List<Artifact> artifacts = artifactResults.getResults(selectedArtifact);
        final File artifactFile = artifacts.get(0).getFile();
        if (artifactFile == null) {
            throw new IOException("Cannot download artifact [" + selectedArtifact.getGAV());
        }
        return new BufferedInputStream(new FileInputStream(artifactFile));

    }

    /**
     * Adapt a {@link MavenRepositoryURL} to a Mercury {@link Repository}.
     *
     * @param repositoryURL to adapt
     *
     * @return adapted
     */
    private Repository toRepository(final MavenRepositoryURL repositoryURL) {
        final Repository repository;
        if (repositoryURL.isFileRepository()) {
            repository = new LocalRepositoryM2(repositoryURL.getId(), repositoryURL.getFile(),
                    DependencyProcessor.NULL_PROCESSOR);
        } else {
            final Server server = new Server(repositoryURL.getId(), repositoryURL.getURL());
            repository = new RemoteRepositoryM2(server.getId(), server, DependencyProcessor.NULL_PROCESSOR);
        }
        repository.setRepositoryQualityRange(
                createQualityRange(repositoryURL.isReleasesEnabled(), repositoryURL.isSnapshotsEnabled()));
        return repository;
    }

    //TODO remove once a version > 1.0-alpha-5 of Mercury and use QualityRange.create
    private static QualityRange createQualityRange(boolean releases, boolean snapshots) {
        if (releases && snapshots) {
            return QualityRange.ALL;
        } else if (releases) {
            return new QualityRange(Quality.ALPHA_QUALITY, true, Quality.RELEASE_QUALITY, true);
        } else if (snapshots) {
            return new QualityRange(Quality.SNAPSHOT_QUALITY, true, Quality.SNAPSHOT_TS_QUALITY, true);
        }

        throw new IllegalArgumentException("Unsuported combination for releases/snapshots");
    }

    /**
     * Creates an IOException with a message and a cause.
     *
     * @param message exception message
     * @param cause   exception cause
     *
     * @return the created IO Exception
     */
    private IOException initIOException(final String message, final Exception cause) {
        IOException exception = new IOException(message);
        exception.initCause(cause);
        return exception;
    }

    /**
     * Utility to add var args elements into a list.
     *
     * @param elements to add
     * @param <T>      any type
     *
     * @return list
     */
    private <T> List<T> toList(final T... elements) {
        final ArrayList<T> list = new ArrayList<T>();
        list.addAll(Arrays.asList(elements));
        return list;
    }

}