2009-05-16 10 views
13

私はリフレクションを使用する必要があるmavenプラグインを作ろうとしています。私は、プロジェクトをプラグインを実行し、プロジェクトのクラスの完全な名前を与え、プラグインはリフレクションによってそれから情報を取得するためにそれをロードします。クラスローダとの奇妙な何かが、それは私がMavenプラグインはクラスをロードできません

Class.forName("package.MyClass"); 

here探し使用するときにクラスを見つけることができないので、私のプラグインのクラスローダーは、ときに実行されている場合、私は非常に把握することはできません、しかしあります

異なるプロジェクトは、そのプロジェクトのクラスにアクセスできます。

答えて

11

私はもっと良い方法があると確信しているが、ここで私はそれが動作するようになった方法は次のとおりです。

はあなたのモジョの上部にあるのjavadocに以下を追加します。 @requiresDependencyResolutionランタイム

はMavenProjectを追加パラメータ:

/** 
* @parameter expression="${project}" 
* @required 
* @readonly 
*/ 
private MavenProject project; 

その後、実行時に依存関係を取得し、独自のクラスローダを行うことができます。

List runtimeClasspathElements = project.getRuntimeClasspathElements(); 
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()]; 
for (int i = 0; i < runtimeClasspathElements.size(); i++) { 
    String element = (String) runtimeClasspathElements.get(i); 
    runtimeUrls[i] = new File(element).toURI().toURL(); 
} 
URLClassLoader newLoader = new URLClassLoader(runtimeUrls, 
    Thread.currentThread().getContextClassLoader()); 

次に、あなたは、この新しいクラスローダを使ってクラスをロードすることができます

Class bundle = newLoader.loadClass("package.MyClass"); 
11

あなたは現在のクラスレルムにランタイムクラスパス要素を追加するためにこれを使用することを検討すべきです。 (あなたはクラスのレルムを取得するためにPluginDescriptorを使用することができます

List<String> runtimeClasspathElements = project.getRuntimeClasspathElements(); 
ClassRealm realm = descriptor.getClassRealm(); 

for (String element : runtimeClasspathElements) 
{ 
    File elementFile = new File(element); 
    realm.addURL(elementFile.toURI().toURL()); 
} 

これは私のために完全に働いた

Daveが尋ねたように、ここでPluginDescriptor取得する方法である:。!

/** 
* The plugin descriptor 
* 
* @parameter default-value="${descriptor}" 
*/ 
private PluginDescriptor descriptor; 
+0

MyMojoのexecuteメソッドからPluginDescriptorへのハンドルを取得するにはどうすればよいですか? – Upgradingdave

+1

ちょっとデイブ、私は私の答えを調整し、うまくいけばそれはあなたを助けます。 (あなたはセッターを必要としません、これは反射を経て設定されるためです)。 – codevour

+0

ありがとうございました、私はどこでもドキュメントでそれを見つけることができませんでした。 – Upgradingdave

1

Iを私はHibernateExporter mojoソースを利用しています。http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.mojo/hibernate3-maven-plugin/2.2/org/codehaus/mojo/hibernate3/HibernateExporterMojo.java?av=f

ここでは、この問題を解決する方法について説明します。
/** 
* @parameter expression="${project}" 
* @required 
* @readonly 
*/ 
private MavenProject project; 

private ClassLoader getClassLoader() throws MojoExecutionException 
{ 
    try 
    { 
    List<String> classpathElements = project.getCompileClasspathElements(); 
    classpathElements.add(project.getBuild().getOutputDirectory()); 
    classpathElements.add(project.getBuild().getTestOutputDirectory()); 
    URL urls[] = new URL[classpathElements.size()]; 

    for (int i = 0; i < classpathElements.size(); ++i) 
    { 
     urls[i] = new File((String) classpathElements.get(i)).toURI().toURL(); 
    } 
    return new URLClassLoader(urls, getClass().getClassLoader()); 
    } 
    catch (Exception e)//gotta catch em all 
    { 
    throw new MojoExecutionException("Couldn't create a classloader.", e); 
    } 
} 

public void execute() throws MojoExecutionException 
{ 
    ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); 
    Thread.currentThread().setContextClassLoader(getClassLoader()); 

    //... your code here ... 
} 

また、適切なMavenProjectクラスを使用していることを確認してください。これをあなたのpomに追加してください

<dependency> 
    <groupId>org.apache.maven</groupId> 
    <artifactId>maven-core</artifactId> 
    <version>3.0.3</version> 
</dependency> 

<dependency> 
    <groupId>org.apache.maven</groupId> 
    <artifactId>maven-plugin-api</artifactId> 
    <version>3.0.3</version> 
</dependency> 
1

これは私とmaven3がプラグインクラスパスに依存するように働いてくれました。

@トリガーは、PluginDescriptorを挿入するために@Componentを使用することです。それ以外の場合は正しく設定されません。

@Component 
private MavenProject project; 
@Component 
private PluginDescriptor descriptor; 

private void addDependenciesToClasspath(String artifactId) { 
    for (Artifact artifact : project.getDependencyArtifacts()) { 
     if (artifact.getArtifactId().equals(artifactId)) { 
      try { 
       final URL url = artifact.getFile().toURI().toURL(); 
       final ClassRealm realm = descriptor.getClassRealm(); 
       realm.addURL(url); 
      } 
      catch (MalformedURLException e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } 
} 
関連する問題