All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.btmatthews.maven.plugins.ldap.mojo.IncludeServerDependenciesComponentConfigurator Maven / Gradle / Ivy

/*
 * Copyright 2008-2016 Brian Thomas Matthews
 *
 * 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 com.btmatthews.maven.plugins.ldap.mojo;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
import org.apache.maven.artifact.repository.RepositoryRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
import org.apache.maven.project.MavenProject;
import org.apache.maven.repository.RepositorySystem;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter;
import org.codehaus.plexus.component.configurator.converters.special.ClassRealmConverter;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author Brian Matthews
 * @since 1.2.0
 */
@Component(role = ComponentConfigurator.class, hint = "include-server-dependencies")
public class IncludeServerDependenciesComponentConfigurator extends AbstractComponentConfigurator {

    /**
     * The plugin configuration element that specifies the LDAP server type.
     */
    private static final String SERVER_TYPE_ATTRIBUTE = "serverType";
    /**
     * The default LDAP server type.
     */
    private static final String DEFAULT_SERVER_TYPE_VALUE = "unboundid";
    /**
     * The group id of the main artifact for the LDAP server type.
     */
    private static final String DEFAULT_GROUP_ID = "com.btmatthews.maven.plugins.ldap";
    /**
     * Used to construct the artifact id of the main artifact for the LDAP server type.
     */
    private static final String DEFAULT_ARTIFACT_ID_FORMAT = "server-{0}";

    @Requirement
    private RepositorySystem repositorySystem;

    /**
     * Configure the Mojo by adding the dependencies for the LDAP server type to the class loader.
     *
     * @param component           The Mojo being configured.
     * @param configuration       The plugin configuration.
     * @param expressionEvaluator Used to evaluate expressions.
     * @param containerRealm      Used to build the class loader.
     * @param listener            Receives notification when configuration is changed.
     * @throws ComponentConfigurationException If there was a problem resolving or locating any of the dependencies.
     */
    @Override
    public void configureComponent(final Object component,
                                   final PlexusConfiguration configuration,
                                   final ExpressionEvaluator expressionEvaluator,
                                   final ClassRealm containerRealm,
                                   final ConfigurationListener listener)
            throws ComponentConfigurationException {

        final String serverType = getServerType(configuration);

        addServerDependenciesToClassRealm(serverType, expressionEvaluator, containerRealm);

        converterLookup.registerConverter(new ClassRealmConverter(containerRealm));

        final ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter();

        converter.processConfiguration(converterLookup, component, containerRealm, configuration,
                expressionEvaluator, listener);

    }

    /**
     * Resolve the dependencies for an LDAP server type and add them to the class loader.
     *
     * @param serverType          The LDAP server type.
     * @param expressionEvaluator Used to evaluate expressions.
     * @param containerRealm      The class loader.
     * @throws ComponentConfigurationException If there was a problem resolving or locating any of the dependencies.
     */
    private void addServerDependenciesToClassRealm(final String serverType,
                                                   final ExpressionEvaluator expressionEvaluator,
                                                   final ClassRealm containerRealm)
            throws ComponentConfigurationException {
        final Collection classpathElements = getServerDependencies(serverType, expressionEvaluator);
        if (classpathElements != null) {
            for (final URL url : buildURLs(classpathElements)) {
                containerRealm.addURL(url);
            }
        }
    }

    /**
     * Retrive the URLs used to locate the JAR files for a list of artifacts.
     *
     * @param classpathElements The list of artifacts.
     * @return The list of URLs.
     * @throws ComponentConfigurationException If any JAR files could not be located.
     */
    private List buildURLs(final Collection classpathElements)
            throws ComponentConfigurationException {
        final List urls = new ArrayList(classpathElements.size());
        for (final Artifact classpathElement : classpathElements) {
            try {
                final URL url = classpathElement.getFile().toURI().toURL();
                urls.add(url);
            } catch (final MalformedURLException e) {
                throw new ComponentConfigurationException("Unable to access project dependency: " + classpathElement, e);
            }
        }
        return urls;
    }

    /**
     * Resolve the LDAP server type artifact and its dependencies.
     *
     * @param serverType          The LDAP server type.
     * @param expressionEvaluator Used to get the Maven project model and repository session objects.
     * @return A list of dependencies required for the LDAP server type.
     * @throws ComponentConfigurationException If the was a problem resolving the dependencies for
     *                                         the LDAP server type.
     */
    private Collection getServerDependencies(final String serverType,
                                                 final ExpressionEvaluator expressionEvaluator)
            throws ComponentConfigurationException {
        try {
            final MavenProject project = (MavenProject) expressionEvaluator.evaluate("${project}");
            final String localRepo = (String) expressionEvaluator.evaluate("${settings.localRepository}");
            final ArtifactRepository localRepository = repositorySystem.createLocalRepository(new File(localRepo));
            final RepositoryRequest repositoryRequest = new DefaultRepositoryRequest();
            repositoryRequest.setRemoteRepositories(project.getRemoteArtifactRepositories());
            repositoryRequest.setLocalRepository(localRepository);
            final ArtifactResolutionRequest request = new ArtifactResolutionRequest(repositoryRequest);
            request.setArtifact(getServerArtifact(serverType));
            request.setResolveTransitively(true);
            final ArtifactResolutionResult result = repositorySystem.resolve(request);
            if (result.isSuccess()) {
                return result.getArtifacts();
            }
            boolean first = true;
            final StringBuilder builder = new StringBuilder("Cannot resolve dependencies: [");
            for (final Artifact artifact : result.getMissingArtifacts()) {
                if (!first) {
                    builder.append(',');
                    first = false;
                }
                builder.append(artifact.getGroupId());
                builder.append(':');
                builder.append(artifact.getArtifactId());
                builder.append(':');
                builder.append(artifact.getVersion());
            }
            builder.append("]");
            throw new ComponentConfigurationException(builder.toString());
        } catch (final ExpressionEvaluationException e) {
            throw new ComponentConfigurationException("Error evaluating expression", e);
        } catch (final InvalidRepositoryException e) {
            throw new ComponentConfigurationException("Error resolving local repository", e);
        }
    }

    /**
     * Get the artifact descriptor for the JAR file that implements support for the LDAP server type.
     *
     * @param serverType The LDAP server type.
     * @return The JAR file artifact descriptor.
     */
    private Artifact getServerArtifact(final String serverType) {
        return repositorySystem.createArtifact(
                DEFAULT_GROUP_ID,
                MessageFormat.format(DEFAULT_ARTIFACT_ID_FORMAT, serverType),
                getClass().getPackage().getImplementationVersion(),
                "runtime",
                "jar");
    }

    /**
     * Determine the configured LDAP server type. If one has not been configured then
     * return the default.
     *
     * @param configuration The plugin configuration.
     * @return The LDAP server type.
     */
    private String getServerType(final PlexusConfiguration configuration) {
        final Pattern pattern = Pattern.compile("\\$\\{[A-Za-z0-9\\._]+\\}");
        for (final PlexusConfiguration cfg : configuration.getChildren()) {
            if (cfg.getName().equals(SERVER_TYPE_ATTRIBUTE)) {
                if (pattern.matcher(cfg.getValue()).matches()) {
                    return DEFAULT_SERVER_TYPE_VALUE;
                } else {
                    return cfg.getValue();
                }
            }
        }
        return DEFAULT_SERVER_TYPE_VALUE;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy