org.eclipse.aether.ant.AntRepoSys.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.aether.ant.AntRepoSys.java

Source

/*******************************************************************************
 * Copyright (c) 2010, 2014 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Sonatype, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.aether.ant;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.maven.model.Model;
import org.apache.maven.model.building.DefaultModelBuilderFactory;
import org.apache.maven.model.building.DefaultModelBuildingRequest;
import org.apache.maven.model.building.FileModelSource;
import org.apache.maven.model.building.ModelBuilder;
import org.apache.maven.model.building.ModelBuildingException;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.resolution.ModelResolver;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuilder;
import org.apache.maven.settings.building.SettingsBuildingException;
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.condition.Os;
import org.apache.tools.ant.types.Reference;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.aether.ConfigurationProperties;
import org.eclipse.aether.DefaultRepositoryCache;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.ant.listeners.AntRepositoryListener;
import org.eclipse.aether.ant.listeners.AntTransferListener;
import org.eclipse.aether.ant.types.Authentication;
import org.eclipse.aether.ant.types.Dependencies;
import org.eclipse.aether.ant.types.Dependency;
import org.eclipse.aether.ant.types.Exclusion;
import org.eclipse.aether.ant.types.LocalRepository;
import org.eclipse.aether.ant.types.Mirror;
import org.eclipse.aether.ant.types.Pom;
import org.eclipse.aether.ant.types.Proxy;
import org.eclipse.aether.ant.types.RemoteRepositories;
import org.eclipse.aether.ant.types.RemoteRepository;
import org.eclipse.aether.ant.util.AetherUtils;
import org.eclipse.aether.ant.util.ConverterUtils;
import org.eclipse.aether.ant.util.SettingsUtils;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.impl.DefaultServiceLocator;
import org.eclipse.aether.impl.RemoteRepositoryManager;
import org.eclipse.aether.repository.AuthenticationSelector;
import org.eclipse.aether.repository.LocalRepositoryManager;
import org.eclipse.aether.repository.MirrorSelector;
import org.eclipse.aether.repository.ProxySelector;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.spi.log.Logger;
import org.eclipse.aether.transport.classpath.ClasspathTransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.eclipse.aether.util.repository.AuthenticationBuilder;
import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector;
import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
import org.eclipse.aether.util.repository.DefaultMirrorSelector;
import org.eclipse.aether.util.repository.DefaultProxySelector;

/**
 */
public class AntRepoSys {

    private static boolean OS_WINDOWS = Os.isFamily("windows");

    private static final ModelBuilder modelBuilder = new DefaultModelBuilderFactory().newInstance();

    private static final SettingsBuilder settingsBuilder = new DefaultSettingsBuilderFactory().newInstance();

    private static final SettingsDecrypter settingsDecrypter = new AntSettingsDecryptorFactory().newInstance();

    private final Project project;

    private final DefaultServiceLocator locator;

    private RepositorySystem repoSys;

    private RemoteRepositoryManager remoteRepoMan;

    private File userSettings;

    private File globalSettings;

    private Settings settings;

    private final List<Mirror> mirrors = new CopyOnWriteArrayList<Mirror>();

    private final List<Proxy> proxies = new CopyOnWriteArrayList<Proxy>();

    private final List<Authentication> authentications = new CopyOnWriteArrayList<Authentication>();

    private LocalRepository localRepository;

    private Pom defaultPom;

    private static <T> boolean eq(T o1, T o2) {
        return (o1 == null) ? o2 == null : o1.equals(o2);
    }

    public static synchronized AntRepoSys getInstance(Project project) {
        Object obj = project.getReference(Names.ID);
        if (obj instanceof AntRepoSys) {
            return (AntRepoSys) obj;
        }
        AntRepoSys instance = new AntRepoSys(project);
        project.addReference(Names.ID, instance);
        instance.initDefaults();
        return instance;
    }

    private AntRepoSys(Project project) {
        this.project = project;

        locator = MavenRepositorySystemUtils.newServiceLocator();
        locator.setErrorHandler(new AntServiceLocatorErrorHandler(project));
        locator.setServices(Logger.class, new AntLogger(project));
        locator.setServices(ModelBuilder.class, modelBuilder);
        locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
        locator.addService(TransporterFactory.class, FileTransporterFactory.class);
        locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
        locator.addService(TransporterFactory.class, ClasspathTransporterFactory.class);
    }

    private void initDefaults() {
        RemoteRepository repo = new RemoteRepository();
        repo.setProject(project);
        repo.setId("central");
        repo.setUrl("http://repo1.maven.org/maven2/");
        project.addReference(Names.ID_CENTRAL, repo);

        repo = new RemoteRepository();
        repo.setProject(project);
        repo.setRefid(new Reference(project, Names.ID_CENTRAL));
        RemoteRepositories repos = new RemoteRepositories();
        repos.setProject(project);
        repos.addRemoterepo(repo);
        project.addReference(Names.ID_DEFAULT_REPOS, repos);
    }

    public synchronized RepositorySystem getSystem() {
        if (repoSys == null) {
            repoSys = locator.getService(RepositorySystem.class);
            if (repoSys == null) {
                throw new BuildException("The repository system could not be initialized");
            }
        }
        return repoSys;
    }

    private synchronized RemoteRepositoryManager getRemoteRepoMan() {
        if (remoteRepoMan == null) {
            remoteRepoMan = locator.getService(RemoteRepositoryManager.class);
            if (remoteRepoMan == null) {
                throw new BuildException("The repository system could not be initialized");
            }
        }
        return remoteRepoMan;
    }

    public RepositorySystemSession getSession(Task task, LocalRepository localRepo) {
        DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();

        Map<Object, Object> configProps = new LinkedHashMap<Object, Object>();
        configProps.put(ConfigurationProperties.USER_AGENT, getUserAgent());
        configProps.putAll((Map<?, ?>) project.getProperties());
        processServerConfiguration(configProps);
        session.setConfigProperties(configProps);

        session.setOffline(isOffline());
        session.setUserProperties(project.getUserProperties());

        session.setProxySelector(getProxySelector());
        session.setMirrorSelector(getMirrorSelector());
        session.setAuthenticationSelector(getAuthSelector());

        session.setCache(new DefaultRepositoryCache());

        session.setRepositoryListener(new AntRepositoryListener(task));
        session.setTransferListener(new AntTransferListener(task));

        session.setLocalRepositoryManager(getLocalRepoMan(session, localRepo));

        session.setWorkspaceReader(ProjectWorkspaceReader.getInstance());

        return session;
    }

    private String getUserAgent() {
        StringBuilder buffer = new StringBuilder(128);

        buffer.append("Apache-Ant/").append(project.getProperty("ant.version"));
        buffer.append(" (");
        buffer.append("Java ").append(System.getProperty("java.version"));
        buffer.append("; ");
        buffer.append(System.getProperty("os.name")).append(" ").append(System.getProperty("os.version"));
        buffer.append(")");
        buffer.append(" Aether");

        return buffer.toString();
    }

    private boolean isOffline() {
        String prop = project.getProperty(Names.PROPERTY_OFFLINE);
        if (prop != null) {
            return Boolean.parseBoolean(prop);
        }
        return getSettings().isOffline();
    }

    private void processServerConfiguration(Map<Object, Object> configProps) {
        Settings settings = getSettings();
        for (Server server : settings.getServers()) {
            if (server.getConfiguration() != null) {
                Xpp3Dom dom = (Xpp3Dom) server.getConfiguration();
                for (int i = dom.getChildCount() - 1; i >= 0; i--) {
                    Xpp3Dom child = dom.getChild(i);
                    if ("wagonProvider".equals(child.getName())) {
                        dom.removeChild(i);
                    } else if ("httpHeaders".equals(child.getName())) {
                        configProps.put(ConfigurationProperties.HTTP_HEADERS + "." + server.getId(),
                                getHttpHeaders(child));
                    }
                }

                configProps.put("aether.connector.wagon.config." + server.getId(), dom);
            }

            configProps.put("aether.connector.perms.fileMode." + server.getId(), server.getFilePermissions());
            configProps.put("aether.connector.perms.dirMode." + server.getId(), server.getDirectoryPermissions());
        }
    }

    private Map<String, String> getHttpHeaders(Xpp3Dom dom) {
        Map<String, String> headers = new HashMap<String, String>();
        for (int i = 0; i < dom.getChildCount(); i++) {
            Xpp3Dom child = dom.getChild(i);
            Xpp3Dom name = child.getChild("name");
            Xpp3Dom value = child.getChild("value");
            if (name != null && name.getValue() != null) {
                headers.put(name.getValue(), (value != null) ? value.getValue() : null);
            }
        }
        return Collections.unmodifiableMap(headers);
    }

    private File getDefaultLocalRepoDir() {
        String dir = project.getProperty("maven.repo.local");
        if (dir != null) {
            return project.resolveFile(dir);
        }

        Settings settings = getSettings();
        if (settings.getLocalRepository() != null) {
            return new File(settings.getLocalRepository());
        }

        return new File(new File(project.getProperty("user.home"), ".m2"), "repository");
    }

    private LocalRepositoryManager getLocalRepoMan(RepositorySystemSession session, LocalRepository localRepo) {
        if (localRepo == null) {
            localRepo = localRepository;
        }

        File repoDir;
        if (localRepo != null && localRepo.getDir() != null) {
            repoDir = localRepo.getDir();
        } else {
            repoDir = getDefaultLocalRepoDir();
        }

        org.eclipse.aether.repository.LocalRepository repo = new org.eclipse.aether.repository.LocalRepository(
                repoDir);

        return getSystem().newLocalRepositoryManager(session, repo);
    }

    private synchronized Settings getSettings() {
        if (settings == null) {
            DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
            request.setUserSettingsFile(getUserSettings());
            request.setGlobalSettingsFile(getGlobalSettings());
            request.setSystemProperties(getSystemProperties());
            request.setUserProperties(getUserProperties());

            try {
                settings = settingsBuilder.build(request).getEffectiveSettings();
            } catch (SettingsBuildingException e) {
                project.log("Could not process settings.xml: " + e.getMessage(), e, Project.MSG_WARN);
            }

            SettingsDecryptionResult result = settingsDecrypter
                    .decrypt(new DefaultSettingsDecryptionRequest(settings));
            settings.setServers(result.getServers());
            settings.setProxies(result.getProxies());
        }
        return settings;
    }

    private ProxySelector getProxySelector() {
        DefaultProxySelector selector = new DefaultProxySelector();

        for (Proxy proxy : proxies) {
            selector.add(ConverterUtils.toProxy(proxy), proxy.getNonProxyHosts());
        }

        Settings settings = getSettings();
        for (org.apache.maven.settings.Proxy proxy : settings.getProxies()) {
            AuthenticationBuilder auth = new AuthenticationBuilder();
            auth.addUsername(proxy.getUsername()).addPassword(proxy.getPassword());
            selector.add(new org.eclipse.aether.repository.Proxy(proxy.getProtocol(), proxy.getHost(),
                    proxy.getPort(), auth.build()), proxy.getNonProxyHosts());
        }

        return selector;
    }

    private MirrorSelector getMirrorSelector() {
        DefaultMirrorSelector selector = new DefaultMirrorSelector();

        for (Mirror mirror : mirrors) {
            selector.add(mirror.getId(), mirror.getUrl(), mirror.getType(), false, mirror.getMirrorOf(), null);
        }

        Settings settings = getSettings();
        for (org.apache.maven.settings.Mirror mirror : settings.getMirrors()) {
            selector.add(String.valueOf(mirror.getId()), mirror.getUrl(), mirror.getLayout(), false,
                    mirror.getMirrorOf(), mirror.getMirrorOfLayouts());
        }

        return selector;
    }

    private AuthenticationSelector getAuthSelector() {
        DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector();

        Collection<String> ids = new HashSet<String>();
        for (Authentication auth : authentications) {
            List<String> servers = auth.getServers();
            if (!servers.isEmpty()) {
                org.eclipse.aether.repository.Authentication a = ConverterUtils.toAuthentication(auth);
                for (String server : servers) {
                    if (ids.add(server)) {
                        selector.add(server, a);
                    }
                }
            }
        }

        Settings settings = getSettings();
        for (Server server : settings.getServers()) {
            AuthenticationBuilder auth = new AuthenticationBuilder();
            auth.addUsername(server.getUsername()).addPassword(server.getPassword());
            auth.addPrivateKey(server.getPrivateKey(), server.getPassphrase());
            selector.add(server.getId(), auth.build());
        }

        return new ConservativeAuthenticationSelector(selector);
    }

    public synchronized void setUserSettings(File file) {
        if (!eq(this.userSettings, file)) {
            settings = null;
        }
        this.userSettings = file;
    }

    /* UT */File getUserSettings() {
        if (userSettings == null) {
            userSettings = AetherUtils.findUserSettings(project);
        }
        return userSettings;
    }

    public void setGlobalSettings(File file) {
        if (!eq(this.globalSettings, file)) {
            settings = null;
        }
        this.globalSettings = file;
    }

    /* UT */File getGlobalSettings() {
        if (globalSettings == null) {
            globalSettings = AetherUtils.findGlobalSettings(project);
        }
        return globalSettings;
    }

    public void addProxy(Proxy proxy) {
        proxies.add(proxy);
    }

    public void addMirror(Mirror mirror) {
        mirrors.add(mirror);
    }

    public void addAuthentication(Authentication authentication) {
        authentications.add(authentication);
    }

    public void setLocalRepository(LocalRepository localRepository) {
        this.localRepository = localRepository;
    }

    public Model loadModel(Task task, File pomFile, boolean local, RemoteRepositories remoteRepositories) {
        RepositorySystemSession session = getSession(task, null);

        remoteRepositories = remoteRepositories == null ? AetherUtils.getDefaultRepositories(project)
                : remoteRepositories;

        List<org.eclipse.aether.repository.RemoteRepository> repositories = ConverterUtils
                .toRepositories(task.getProject(), session, remoteRepositories, getRemoteRepoMan());

        ModelResolver modelResolver = new AntModelResolver(session, "project", getSystem(), getRemoteRepoMan(),
                repositories);

        Settings settings = getSettings();

        try {
            DefaultModelBuildingRequest request = new DefaultModelBuildingRequest();
            request.setLocationTracking(true);
            request.setProcessPlugins(false);
            if (local) {
                request.setPomFile(pomFile);
                request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
            } else {
                request.setModelSource(new FileModelSource(pomFile));
                request.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
            }
            request.setSystemProperties(getSystemProperties());
            request.setUserProperties(getUserProperties());
            request.setProfiles(SettingsUtils.convert(settings.getProfiles()));
            request.setActiveProfileIds(settings.getActiveProfiles());
            request.setModelResolver(modelResolver);
            return modelBuilder.build(request).getEffectiveModel();
        } catch (ModelBuildingException e) {
            throw new BuildException("Could not load POM " + pomFile + ": " + e.getMessage(), e);
        }
    }

    private Properties getSystemProperties() {
        Properties props = new Properties();
        getEnvProperties(props);
        props.putAll(System.getProperties());
        ConverterUtils.addProperties(props, project.getProperties());
        return props;
    }

    private Properties getEnvProperties(Properties props) {
        if (props == null) {
            props = new Properties();
        }
        boolean envCaseInsensitive = OS_WINDOWS;
        for (Map.Entry<String, String> entry : System.getenv().entrySet()) {
            String key = entry.getKey();
            if (envCaseInsensitive) {
                key = key.toUpperCase(Locale.ENGLISH);
            }
            key = "env." + key;
            props.put(key, entry.getValue());
        }
        return props;
    }

    private Properties getUserProperties() {
        return ConverterUtils.addProperties(null, project.getUserProperties());
    }

    /**
     * Sets the default POM.
     */
    public void setDefaultPom(Pom pom) {
        this.defaultPom = pom;
    }

    /**
     * Returns the current default POM.
     */
    public Pom getDefaultPom() {
        return defaultPom;
    }

    public CollectResult collectDependencies(Task task, Dependencies dependencies, LocalRepository localRepository,
            RemoteRepositories remoteRepositories) {
        RepositorySystemSession session = getSession(task, localRepository);

        remoteRepositories = remoteRepositories == null ? AetherUtils.getDefaultRepositories(project)
                : remoteRepositories;

        List<org.eclipse.aether.repository.RemoteRepository> repos = ConverterUtils.toRepositories(project, session,
                remoteRepositories, getRemoteRepoMan());

        CollectRequest collectRequest = new CollectRequest();
        collectRequest.setRequestContext("project");

        for (org.eclipse.aether.repository.RemoteRepository repo : repos) {
            task.getProject().log("Using remote repository " + repo, Project.MSG_VERBOSE);
            collectRequest.addRepository(repo);
        }

        if (dependencies != null) {
            List<Exclusion> globalExclusions = dependencies.getExclusions();
            Collection<String> ids = new HashSet<String>();

            for (Dependency dep : dependencies.getDependencies()) {
                ids.add(dep.getVersionlessKey());
                collectRequest.addDependency(ConverterUtils.toDependency(dep, globalExclusions, session));
            }

            if (dependencies.getPom() != null) {
                Model model = dependencies.getPom().getModel(task);
                for (org.apache.maven.model.Dependency dep : model.getDependencies()) {
                    Dependency dependency = new Dependency();
                    dependency.setArtifactId(dep.getArtifactId());
                    dependency.setClassifier(dep.getClassifier());
                    dependency.setGroupId(dep.getGroupId());
                    dependency.setScope(dep.getScope());
                    dependency.setType(dep.getType());
                    dependency.setVersion(dep.getVersion());
                    if (ids.contains(dependency.getVersionlessKey())) {
                        continue;
                    }
                    if (dep.getSystemPath() != null && dep.getSystemPath().length() > 0) {
                        dependency.setSystemPath(task.getProject().resolveFile(dep.getSystemPath()));
                    }
                    for (org.apache.maven.model.Exclusion exc : dep.getExclusions()) {
                        Exclusion exclusion = new Exclusion();
                        exclusion.setGroupId(exc.getGroupId());
                        exclusion.setArtifactId(exc.getArtifactId());
                        exclusion.setClassifier("*");
                        exclusion.setExtension("*");
                        dependency.addExclusion(exclusion);
                    }
                    collectRequest
                            .addDependency(ConverterUtils.toDependency(dependency, globalExclusions, session));
                }
            }
        }

        task.getProject().log("Collecting dependencies", Project.MSG_VERBOSE);

        CollectResult result;
        try {
            result = getSystem().collectDependencies(session, collectRequest);
        } catch (DependencyCollectionException e) {
            throw new BuildException("Could not collect dependencies: " + e.getMessage(), e);
        }

        return result;
    }

}