2016-11-25 4 views
3

Maven 모듈의 모든 종속성을 프로그래밍 방식으로 Maven 실행 환경 외부에서 가져올 수 있습니까?Maven : 프로그래밍 방식으로 모든 종속성 얻기

지금까지 내가 가진 :

받는다는 코어를 통해

:

Path pomPath = ...; 
MavenXpp3Reader reader = new MavenXpp3Reader(); 
try (InputStream is = Files.newInputStream(pomPath)) { 
    Model model = reader.read(is); 
    this.mavenProject = new MavenProject(model); 
} 

및 jcabi-오드를 통해 :

File localRepo = Paths.get(System.getProperty("user.home"), ".m2").toFile(); 
new Classpath(mavenProject, localRepo, "runtime") 

이 지금까지 일반적으로 맞습니까?

지금 문제

내가 NullPointerException이납니다 있다는 것입니다 : mavenProject.getRemoteProjectRepositories 이후

Caused by: java.lang.NullPointerException 
    at com.jcabi.aether.Aether.mrepos(Aether.java:197) 
    at com.jcabi.aether.Aether.<init>(Aether.java:140) 
    at com.jcabi.aether.Classpath.<init>(Classpath.java:125) 

()가 null를 돌려줍니다.

MavenProject를 초기화하여 settings.xml 파일 (미러, 프록시, 리포지토리 등)을 고려하여 구성된 원격 리포지토리를 포함하도록 어떻게 초기화 할 수 있습니까?

+0

나는 이것이 올바른 방향으로 가고 있다고 생각하지 않습니다. 대신에 [ – janos

+0

] [http://developer.apache.org/plugins/maven-dependency-plugin/get-mojo.html] [[dependency : get']을보십시오. POM 파일이없고 좌표를 가지고, 당신은 오드를 들여다 볼 수 있습니다. Aether와의 직접적인 의존성을 가져 오려면 [이 답변을 참조하십시오] (http://stackoverflow.com/questions/39638138/find-all-direct-dependencies-of-an-artifact-on-maven-central) . POM을 가지고 있다면,'dependency : get -Dtransitive = false'를 사용하면 직접적인 의존성을 훨씬 쉽게 얻을 수 있습니다. [호출자 API] (http://maven.apache.org/shared/maven-invoker/) – Tunaki

+0

명확히하려면 : POM 파일이 있지만 코드가 Maven 실행 외부에서 실행됩니다. URL (로컬 원격 저장소에서 먼저 다운로드해야 할 수도 있음)의 종속성에 대한 URL을 URLClassLoader에 채 웁니다. 플러그인이 나를 어떻게 도울 지 모르겠다. ... – Puce

답변

4

Maven 플러그인 외부에서 아티팩트를 조작하는 방법은 Aether를 사용하는 것입니다. 팀은 ResolveTransitiveDependencies이라는 주어진 이슈의 전이 의존성을 얻기위한 샘플 프로젝트를 가지고 있습니다. 당신이 (like shown here)을 설정 한 오드 종속성이 있으면, 당신은 간단하게 할 수 있습니다 :

public static void main(final String[] args) throws Exception { 
    DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); 
    RepositorySystem system = newRepositorySystem(locator); 
    RepositorySystemSession session = newSession(system); 

    RemoteRepository central = new RemoteRepository.Builder("central", "default", "http://repo1.maven.org/maven2/").build(); 

    Artifact artifact = new DefaultArtifact("group.id:artifact.id:version"); 

    CollectRequest collectRequest = new CollectRequest(new Dependency(artifact, JavaScopes.COMPILE), Arrays.asList(central)); 
    DependencyFilter filter = DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE); 
    DependencyRequest request = new DependencyRequest(collectRequest, filter); 
    DependencyResult result = system.resolveDependencies(session, request); 

    for (ArtifactResult artifactResult : result.getArtifactResults()) { 
     System.out.println(artifactResult.getArtifact().getFile()); 
    } 
} 

private static RepositorySystem newRepositorySystem(DefaultServiceLocator locator) { 
    locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); 
    locator.addService(TransporterFactory.class, FileTransporterFactory.class); 
    locator.addService(TransporterFactory.class, HttpTransporterFactory.class); 
    return locator.getService(RepositorySystem.class); 
} 

private static RepositorySystemSession newSession(RepositorySystem system) { 
    DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); 
    LocalRepository localRepo = new LocalRepository("target/local-repo"); 
    session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo)); 
    return session; 
} 

이 아티팩트를 다운로드하고 "target/local-repo"로 배치됩니다.

시스템 세션에서 DefaultProxySelectorDefaultMirrorSelector으로 프록시 및 미러를 구성 할 수 있습니다. 이 세션을 채우기 위해 메이븐 설정 파일을 읽고 그것을 사용하는 것이 가능할 것이다, 그러나 이것은 당신이 POM에 액세스 할 수 있기 때문에


당신이 메이븐 자신과의 긴밀한 결합을 원할 때 ... 정말 빨리 정말 추한 처리하고 설정을 고려하기를 원한다면 Maven을 프로그래밍 방식으로 직접 호출하는 것이 훨씬 간단합니다. 이 경우 주어진 POM 파일의 전이 의존성을 포함하여 각 종속성의 경로에 관심이 있습니다. 이를 위해 dependency:list 목표는 outputAbsoluteArtifactFilenametrue으로 설정하는 것과 거의 비슷합니다.

Maven을 프로그래밍 방식으로 호출하려면 Invoker API을 사용할 수 있습니다. 프로젝트에 의존성 추가를 :

<dependency> 
    <groupId>org.apache.maven.shared</groupId> 
    <artifactId>maven-invoker</artifactId> 
    <version>2.2</version> 
</dependency> 

당신은 할 수 있습니다 :

InvocationRequest request = new DefaultInvocationRequest(); 
request.setPomFile(new File(pomPath)); 
request.setGoals(Arrays.asList("dependency:list")); 
Properties properties = new Properties(); 
properties.setProperty("outputFile", "dependencies.txt"); // redirect output to a file 
properties.setProperty("outputAbsoluteArtifactFilename", "true"); // with paths 
properties.setProperty("includeScope", "runtime"); // only runtime (scope compile + runtime) 
// if only interested in scope runtime, you may replace with excludeScope = compile 
request.setProperties(properties); 

Invoker invoker = new DefaultInvoker(); 
// the Maven home can be omitted if the "maven.home" system property is set 
invoker.setMavenHome(new File("/path/to/maven/home")); 
invoker.setOutputHandler(null); // not interested in Maven output itself 
InvocationResult result = invoker.execute(request); 
if (result.getExitCode() != 0) { 
    throw new IllegalStateException("Build failed."); 
} 

Pattern pattern = Pattern.compile("(?:compile|runtime):(.*)"); 
try (BufferedReader reader = Files.newBufferedReader(Paths.get("dependencies.txt"))) { 
    while (!"The following files have been resolved:".equals(reader.readLine())); 
    String line; 
    while ((line = reader.readLine()) != null && !line.isEmpty()) { 
     Matcher matcher = pattern.matcher(line); 
     if (matcher.find()) { 
      // group 1 contains the path to the file 
      System.out.println(matcher.group(1)); 
     } 
    } 
} 

이 포함 호출 요청 생성 : 목표는 호출 시스템 속성을, 당신은에 mvn dependency:list -Dprop=value를 시작 하듯이 명령 줄. 사용할 설정에 대한 경로는 기본적으로 "${user.home}/settings.xml"의 표준 위치로 설정되지만 request.setUserSettingsFile(...)request.setGlobalSettingsFile(...)으로 설정 경로를 지정할 수도 있습니다. 호출자는 "maven.home" 시스템 속성이 설정되지 않은 경우에만 Maven 홈 (즉, 설치 디렉토리)을 설정해야합니다.

dependency:list을 호출 한 결과는 나중에 사후 처리되는 파일로 재 지정됩니다.

group.id:artifact.id:type[:classifier]:version:scope:pathname 

출력에 해결 된 유물의 파일의 경로있는 방법이되지 않습니다 : 목표의 출력은 (아무것도없는 경우 분류가 없을 수) 형식의 종속성 목록 구성 분류자를 빠뜨릴 수 있다는 사실은 파싱을 약간 복잡하게 만듭니다 (경로가 : ...를 포함 할 수 있으므로 한도로 :으로 분할 할 수 없음). 먼저 해결 된 아티팩트는 출력 파일의 "The following files have been resolved:" 행 아래에 있습니다. 원하는 범위가 compile 또는 runtime이므로 compile: 또는 runtime: 이후의 모든 것을 취하는 간단한 정규 표현식으로 이슈 파일의 경로를 가져올 수 있습니다 . 그런 다음 해당 경로를 직접 new File으로 사용할 수 있습니다.

후 처리 중 고리가 너무 부서져 보이면 해결 된 이슈의 파일 이름 만 출력하는 자체 플러그인을 만들 수 있습니다.

+0

감사합니다. 설정 지원 기능을 갖춘 첫 번째 버전을 구현할 수있었습니다. – Puce