2012-07-17 28 views
12

Làm thế nào để có được Mô hình tệp pom được giải quyết hoàn toàn?Tôi làm cách nào để có được Mô hình tệp pom được giải quyết hoàn toàn?

này về cơ bản là một rephrasing của How can i programmaticaly build the effective model of a pom file?

Tôi đang xây dựng một plugin maven rằng thực hiện một số quy tắc xác nhận với một tập các mô-đun. Các tệp pom của mô-đun này có sẵn nhưng chúng không phải là một phần của lò phản ứng khi plugin được thực hiện.

tôi có thể đọc một tập tin pom và có được các đối tượng mẫu tương ứng sử dụng phương pháp này (xử lý ngoại lệ loại bỏ vì đơn giản):

private Model pomToModel(String pathToPom) throws Exception { 
    BufferedReader in = new BufferedReader(new FileReader(pathToPom)); 
    MavenXpp3Reader reader = new MavenXpp3Reader(); 
    Model model = reader.read(in); 
    return model; 
} 

Và nó hoạt động nhưng đối tượng mẫu chỉ có cùng một thông tin rằng các tập tin pom có.

Làm thế nào tôi có thể cải thiện phương pháp đó để tôi có thể có được một đối tượng Model "hoàn toàn giải quyết"? Bằng cách giải quyết hoàn toàn, ý tôi là: với tất cả các phụ thuộc transitive và mọi thứ khác từ poms cha mẹ.

Chúc mừng!

+0

Bạn có thể giải thích một chút về các quy tắc xác thực không? – khmarbaise

Trả lời

9

tôi đã làm nó :-)

giúp đỡ: hiệu quả-pom và phụ thuộc: cây thực sự đã không giúp đỡ ở tất cả.

tôi phải xem xét cách maven xây dựng mô hình cho MavenProject đó được tiêm vào mojo. trợ giúp: hiệu quả-pom đã nhận được mô hình giải quyết, và phụ thuộc: cây chỉ xây dựng một DependencyGraph, nhưng nó không tải toàn bộ mô hình cho một pom vào bộ nhớ.

Bằng việc sử dụng mã dưới đây tôi đã có thể để có được một đối tượng mẫu với tất cả các thông tin từ phụ huynh, với $ giải quyết {thuộc tính} biểu thức, và phụ thuộc bắc cầu mở rộng.

Đây là cách:

1) Nhận một ModelResolver

Bạn sẽ cần một thể hiện của giao diện org.apache.maven.model.resolution.ModelResolver. Thật không may, maven không cung cấp một cách dễ dàng thông qua tiêm phụ thuộc (ít nhất là tôi không thể tìm thấy một), vì vậy chúng tôi sẽ phải xây dựng một. Để làm cho mọi thứ trở nên tốt hơn, chỉ có hai triển khai thực hiện của giao diện đó được bảo vệ gói, vì vậy bạn cần sử dụng một số phép thuật phản chiếu để khởi tạo nó. Các lớp cụ thể triển khai thực hiện là DefaultModelResolverProjectModelResolver. tôi đã có thể xây dựng một DefaultModelResolver như thế này

/** 
* The Maven Project Object 
* 
* @parameter expression="${project}" 
* @required2.0 
* @readonly 
*/ 
protected MavenProject project; 

/** 
* @component 
*/ 
protected ArtifactResolver artifactResolver; 

/** 
* @component 
*/ 
protected RemoteRepositoryManager remoteRepositoryManager; 

private Object invoke(Object object, String method) 
     throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { 
    return object.getClass().getMethod(method).invoke(object); 
} 

private org.apache.maven.model.resolution.ModelResolver makeModelResolver() throws MojoExecutionException { 
    try { 
     ProjectBuildingRequest projectBuildingRequest = 
     (ProjectBuildingRequest) invoke(project, "getProjectBuildingRequest"); 

     Class c = Class.forName("org.apache.maven.repository.internal.DefaultModelResolver"); 
     Constructor ct = c.getConstructor(new Class[]{RepositorySystemSession.class, 
       RequestTrace.class, String.class, 
       ArtifactResolver.class, RemoteRepositoryManager.class, 
       List.class}); 
     ct.setAccessible(true); 
     return (org.apache.maven.model.resolution.ModelResolver) ct.newInstance(new Object[]{ 
       projectBuildingRequest.getRepositorySession(), 
       null, null, artifactResolver, remoteRepositoryManager, 
       project.getRemoteProjectRepositories()}); 
    } catch (Exception e) { 
     throw new MojoExecutionException("Error instantiating DefaultModelResolver", e); 
    } 
} 

2) Xây dựng mô hình

Khi bạn có một modelResolver, bạn có thể xây dựng mô hình từ một tập tin pom như thế này:

public Model resolveEffectiveModel(File pomfile) { 
    try { 
     return modelBuilder.build(makeModelBuildRequest(pomfile)).getEffectiveModel(); 
    } catch (Exception e) { 
     throw new RuntimeException(e); 
    } 
} 

private ModelBuildingRequest makeModelBuildRequest(File artifactFile) { 
    DefaultModelBuildingRequest mbr = new DefaultModelBuildingRequest(); 
    mbr.setPomFile(artifactFile); 
    mbr.setModelResolver(modelResolver); // <-- the hard-to-get modelResolver 
    return mbr; 
} 

Không đẹp, nhưng nó có hiệu quả đối với tôi ..: P

+0

Nó cũng làm việc cho tôi. Nhưng tôi thực sự hy vọng có một cách sạch hơn. –

+0

bạn có biết nếu plugin phụ thuộc maven thực hiện điều gì đó tương tự như mã của bạn không? –

+0

ProjectModelResolver không phải là gói riêng tư nhưng nó đòi hỏi một lớp gói riêng tư ReactorModelPool – Puce

1

Các mã nguồn mà bạn tìm kiếm là trong help:effective-pom, ở đâu đó.

--- Sửa cập nhật ---

Sau a quick glance, nó sẽ có vẻ rằng bạn sẽ cần phải xây dựng một Maven Project từ pom đọc. Điều này có khả năng sẽ bao gồm một số bước bao gồm độ phân giải của dự án cha mẹ của POM, tải xuống và phân tích các tạo phẩm trình cắm thêm Maven khác và nối tất cả các tham chiếu với nhau.

Đọc riêng bản thân cấp độ trẻ em sẽ không làm điều đó.

+0

Cảm ơn! Tôi sẽ xem qua một chút. BTW, bạn nên kiểm tra [apache server] (http://edwinbuck.com/) của bạn ;-) –

+0

@ TonyLâmpada Chúc may mắn, và máy chủ Apache đó phục vụ một mục đích, nếu bạn biết đúng URL. :) Nó không chỉ là một trang web vanity, nếu đó là những gì bạn mong đợi. –

+0

trợ giúp: hiệu quả-pom không giúp tôi, nó theo cách khác xung quanh - nó sử dụng mô hình đã được xây dựng mà nó nhận được từ project.getModel(). Nhưng mô hình đó đã được xây dựng sẵn ở một nơi khác. –

1

các maven giúp Plugin làm điều gì đó tương tự khi "mvn giúp đỡ: hiệu quả-pom" được thực thi.

thấy http://svn.apache.org/viewvc/maven/plugins/tags/maven-help-plugin-2.1.1/src/main/java/org/apache/maven/plugins/help/EffectivePomMojo.java?view=markup đối với nguồn.

Tôi nghĩ rằng điều này sẽ không hiển thị các trường hợp phụ thuộc transitive.

Các phụ thuộc mvn: Mục tiêu của cây nào đó: http://svn.apache.org/viewvc/maven/plugins/tags/maven-dependency-plugin-2.4/src/main/java/org/apache/maven/plugin/dependency/TreeMojo.java?view=markup

có lẽ bạn có thể tạo một hỗn hợp của cả hai?

+0

Cảm ơn, tôi cũng sẽ xem xét điều đó! –

+0

Kể từ khi hiệu quả-pom hiện cho dự án maven hiện tại, thường nó không giúp đỡ nhiều như bạn nghĩ. hiệu quả-pom giả định rằng khuôn khổ maven bình thường hiện có đã thực hiện một số công việc. Những gì được gọi là nhiều hơn một dự án maven thứ hai, và chỉ đủ để bootstrap mà vào một pom hoàn toàn giải quyết. –

3

Có thể đã quá muộn cho bạn nhưng nếu có thể giúp đỡ người khác trong tương lai. Vì vậy, tôi đã làm như vậy:

@Component 
private RepositorySystem repositorySystem; 

@Component 
private MavenProjectBuilder mavenProjectBuilder; 

@Parameter(property = "project.remoteArtifactRepositories") 
protected List<ArtifactRepository> remoteRepositories; 

@Parameter(property = "localRepository") 
protected ArtifactRepository localRepository; 

... 
Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId,version); 
MavenProject project = mavenProjectBuilder.buildFromRepository(pomArtifact 
          , remoteRepositories, localRepository); 

Và đó là nó. Nó sẽ hoạt động. Nếu bạn có một số bao bì đặc biệt (ví dụ: gói ...) Trong dự án pom mục tiêu, hãy đảm bảo rằng các plugin liên quan đến các gói đó được cài đặt trong dự án hiện tại của bạn.

+0

Cảm ơn, bạn đã cứu ngày của tôi! :-) – eerriicc

+0

@ romain-gilles bạn sử dụng phiên bản phụ thuộc nào? Có vẻ như MavenProjectBuilder không được chấp nhận trong 3.x, nhưng RepositorySystem không có sẵn trong 2.2.1. Trong Projectxuilder 3.x có sẵn, nhưng nó không thể xây dựng MavenProject –

+0

Tôi tìm thấy câu trả lời cho câu hỏi của tôi, chi tiết bên dưới http://stackoverflow.com/a/39609354/157591 –

0

Chỉ trong trường hợp ai đó muốn, đây là một ví dụ đang chạy trong Groovy. Nó sử dụng Grape để tự động tải các depdencies cần thiết để tiêu thụ tệp pom.xml. Nó tải cả classpath thời gian chạy và classpath thử nghiệm.

@Grapes([ 
     @Grab(group='org.apache.maven', module='maven-core', version='3.0.5'), 
     @Grab(group='org.apache.maven', module='maven-compat', version='3.0.5'), 
     @Grab(group='com.jcabi', module='jcabi-aether', version='0.10.1') 
     ]) 

     // http://www.programcreek.com/java-api-examples/index.php?api=org.apache.maven.project.MavenProjectBuilder See # 20 


import org.codehaus.plexus.DefaultPlexusContainer 
import org.apache.maven.project.MavenProjectBuilder 
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; 
import org.apache.maven.artifact.repository.ArtifactRepository; 
import org.apache.maven.project.DefaultProjectBuilderConfiguration 
import org.apache.maven.artifact.repository.DefaultArtifactRepository 
import com.jcabi.aether.Aether 
import org.sonatype.aether.repository.RemoteRepository; 
import org.sonatype.aether.util.artifact.DefaultArtifact; 
import org.sonatype.aether.artifact.Artifact; 


container=new DefaultPlexusContainer(); 
projectBuilder=(MavenProjectBuilder)container.lookup(MavenProjectBuilder.class.getName()); 
layout=(ArtifactRepositoryLayout)container.lookup(ArtifactRepositoryLayout.class.getName(),"default"); 

def projectInfo(localRepoUrl, pom){ 

    File pomFile = new File(pom); 
    String localRepoUrl2 = "file://" + localRepoUrl; 
    File local = new File(localRepoUrl); 



    ArtifactRepository localRepo=new DefaultArtifactRepository("local",localRepoUrl2,layout); 
    pbConfig=new DefaultProjectBuilderConfiguration().setLocalRepository(localRepo); 
    project = projectBuilder.build(pomFile, pbConfig); 
    aether = new Aether(project, local); 
    [ runtime: resolveDependencies(aether, project, "runtime"), 
     test : resolveDependencies(aether, project, "test") ]; 
} 


def resolveDependencies (aether, project, scope) { 
    depLists = project.getDependencies().collect { 

     art = new DefaultArtifact(it.getGroupId(), it.getArtifactId(), it.getClassifier(), it.getType(), 
            it.getVersion()); 
     Collection<Artifact> deps = aether.resolve(art, scope); 

     deps.collect{ it.getFile().getAbsolutePath() } 

    } 

    [ dependencies : depLists.collect {it.first()}, classpath : depLists.flatten() ] 
} 



println projectInfo("c:/Users/lpmsmith/.m2/repository", "pom.xml"); 
6

Romain cung cấp câu trả lời tốt above, nhưng nó đã được sử dụng một lớp phản đối rằng đã bị xóa khỏi maven 3.x Phiên bản cập nhật là thế này:

@Parameter(defaultValue = "${project}", readonly = true) 
private MavenProject project; 

@Component 
private RepositorySystem repositorySystem; 

@Component 
private ProjectBuilder mavenProjectBuilder; 

@Parameter(defaultValue = "${session}", readonly = true) 
private MavenSession session; 

private MavenProject getMavenProject(String groupId, String artifactId, String version) throws ProjectBuildingException { 

    Artifact pomArtifact = repositorySystem.createProjectArtifact(groupId, artifactId, version); 
    ProjectBuildingResult build = mavenProjectBuilder.build(pomArtifact, session.getProjectBuildingRequest()); 

    return build.getProject(); 

} 

Một ví dụ làm việc là trong hierarchy-maven-plugin

+0

Làm thế nào tôi có thể tiêm 'RepositorySystem'' ProjectBuilder' và 'MavenSession' vào' Component' của tôi ' – DarVar

+0

'@Component (role = MyResolver.class, instantiationStrategy =" per-lookup ") lớp công khai MyResolver {....}' – DarVar

Các vấn đề liên quan