You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@maven.apache.org by jaxzin <Br...@espn3.com> on 2008/08/02 06:02:00 UTC

Re: Adding project dependencies and generated classes to classpath of my plugin

So after trying out more complex scenarios with my first solution (like
calling Class.forName from a class that was injected by the Plexus
container) it turned out it wasn't a complete solution.  So learned alot
more about Plexus and the ClassWorlds framework and I ended up discovering a
much more elegant solution.  I created a custom ComponentConfigurator that
adds my project dependencies to the ClassRealm for the mojo.


Here's my ComponentConfigurator:

---------------------------------------------------

package com.example;

import org.codehaus.classworlds.ClassRealm;
import
org.codehaus.plexus.component.configurator.AbstractComponentConfigurator;
import
org.codehaus.plexus.component.configurator.ComponentConfigurationException;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * A custom ComponentConfigurator which adds the project's runtime classpath
elements
 * to the 
 * 
 * @author  mailto:Brian.R.Jackson@espn3.com Brian Jackson 
 * @since Aug 1, 2008 3:04:17 PM
 *
 * @plexus.component
role="org.codehaus.plexus.component.configurator.ComponentConfigurator"
 *                   role-hint="include-project-dependencies"
 * @plexus.requirement
role="org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup"
 *                   role-hint="default"
 */
public class IncludeProjectDependenciesComponentConfigurator extends
AbstractComponentConfigurator {

    private static final Logger LOGGER =
LoggerFactory.getLogger(IncludeProjectDependenciesComponentConfigurator.class);

    public void configureComponent( Object component, PlexusConfiguration
configuration,
                                    ExpressionEvaluator expressionEvaluator,
ClassRealm containerRealm,
                                    ConfigurationListener listener )
        throws ComponentConfigurationException {

        addProjectDependenciesToClassRealm(expressionEvaluator,
containerRealm);

        converterLookup.registerConverter( new ClassRealmConverter(
containerRealm ) );

        ObjectWithFieldsConverter converter = new
ObjectWithFieldsConverter();

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

    private void addProjectDependenciesToClassRealm(ExpressionEvaluator
expressionEvaluator, ClassRealm containerRealm) throws
ComponentConfigurationException {
        List<String> runtimeClasspathElements;
        try {
            //noinspection unchecked
            runtimeClasspathElements = (List<String>)
expressionEvaluator.evaluate("${project.runtimeClasspathElements}");
        } catch (ExpressionEvaluationException e) {
            throw new ComponentConfigurationException("There was a problem
evaluating: ${project.runtimeClasspathElements}", e);
        }

        // Add the project dependencies to the ClassRealm
        final URL[] urls = buildURLs(runtimeClasspathElements);
        for (URL url : urls) {
            containerRealm.addConstituent(url);
        }
    }

    private URL[] buildURLs(List<String> runtimeClasspathElements) throws
ComponentConfigurationException {
        // Add the projects classes and dependencies
        List<URL> urls = new
ArrayList<URL>(runtimeClasspathElements.size());
        for (String element : runtimeClasspathElements) {
            try {
                final URL url = new File(element).toURI().toURL();
                urls.add(url);
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Added to project class loader: " + url);
                }
            } catch (MalformedURLException e) {
                throw new ComponentConfigurationException("Unable to access
project dependency: " + element, e);
            }
        }

        // Add the plugin's dependencies (so Trove stuff works if Trove
isn't on
        return urls.toArray(new URL[urls.size()]);
    }

}

----------------------------------------------------------------------

And then to use it in my mojo, I needed to add the following plugin to my
pom.xml so the plexus doclets are used to create a components.xml:

---------------------------------------

            <plugin>
                <groupId>org.codehaus.plexus</groupId>
                <artifactId>plexus-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>descriptor</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

---------------------------------------
And the last step is to add the following doclet to my Mojo:

  @configurator include-project-dependencies

----------------------------------------

So that ended up being a much more elegant solution and any ClassLoader
issues I had were resolved.

-- 
View this message in context: http://www.nabble.com/Adding-project-dependencies-and-generated-classes-to-classpath-of-my-plugin-tp18624435p18785907.html
Sent from the Maven - Users mailing list archive at Nabble.com.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org