org.talend.components.api.component.runtime.DependenciesReader.java Source code

Java tutorial

Introduction

Here is the source code for org.talend.components.api.component.runtime.DependenciesReader.java

Source

// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package org.talend.components.api.component.runtime;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.talend.components.api.exception.ComponentException;
import org.talend.components.api.exception.error.ComponentsApiErrorCode;
import org.talend.daikon.exception.ExceptionContext;

/**
 * this will locate a read the dependencies file for a given artifact.
 * This file shall be located in : META-INF/mavenGroupId/mavenArtifactId/dependencies.txt
 * this file is generated by the maven-dependency-plugin plugin in a list format.
 * 
 * <pre>
 * {@code
    
The following files have been resolved:
org.apache.maven:maven-core:jar:3.3.3:compile
org.springframework:spring-beans:jar:4.2.0.RELEASE:test
org.talend.components:components-common:jar:0.4.0.BUILD-SNAPSHOT:compile
log4j:log4j:jar:1.2.17:test
org.eclipse.aether:aether-impl:jar:1.0.0.v20140518:compile
   * }
 * </pre>
 **
 */
public class DependenciesReader {

    private String depTxtPath;

    /**
     * we use the <code>mavenGroupId<code> and <code>mavenArtifactId<code> to located the file that should be parsed
     */
    public DependenciesReader(String mavenGroupId, String mavenArtifactId) {
        depTxtPath = computeDependenciesFilePath(mavenGroupId, mavenArtifactId);
    }

    /**
     * we use the <code>depTxtPath<code> to located the file that should be parsed
     */
    public DependenciesReader(String depTxtPath) {
        this.depTxtPath = depTxtPath;
    }

    /**
     * this will locate the file META-INF/mavenGroupId/mavenArtifactId/dependencies.txt and parse it to extract
     * the dependencies of the component except the test depenencies.
     * 
     * @param mavenGroupId group id of the component to locate the dep file
     * @param mavenArtifactId artifact id of the component to locate the dep file.
     * @param classLoader used to locate the file using {@link ClassLoader#getResourceAsStream(String)}
     * @return set of string pax-url formated
     * @throws IOException if reading the file failed.
     */
    public Set<String> getDependencies(ClassLoader classLoader) throws IOException {
        ClassLoader zeClassLoader = classLoader;
        if (zeClassLoader == null) {
            zeClassLoader = this.getClass().getClassLoader();
        }
        try (InputStream depStream = zeClassLoader.getResourceAsStream(depTxtPath)) {
            if (depStream == null) {
                throw new ComponentException(ComponentsApiErrorCode.COMPUTE_DEPENDENCIES_FAILED,
                        ExceptionContext.withBuilder().put("path", depTxtPath).build());
            } // else we found it so parse it now
            return parseDependencies(depStream);
        }
    }

    /**
     * reads a stream following the maven-dependency-plugin plugin :list format
     * 
     * <pre>
    * {@code
        
    The following files have been resolved:
    org.apache.maven:maven-core:jar:3.3.3:compile
    org.springframework:spring-beans:jar:4.2.0.RELEASE:test
    org.talend.components:components-common:jar:0.4.0.BUILD-SNAPSHOT:compile
    log4j:log4j:jar:1.2.17:test
    org.eclipse.aether:aether-impl:jar:1.0.0.v20140518:compile
       * }
     * </pre>
     * 
     * and return a list of mvn url strings following the <a href="https://ops4j1.jira.com/wiki/display/paxurl/Mvn+Protocol"
     * >pax-urm mvn</a> protocol
     * .<br>
     * this will ignore test dependencies.
     * 
     * 
     * 
     * @param depStream of the dependencies file
     * @return a list of maven url strings
     * @throws IOException if read fails.
     */
    public Set<String> parseDependencies(InputStream depStream) throws IOException {
        Set<String> mvnUris = new HashSet<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(depStream, "UTF-8"));
        // java 8 version
        // reader.lines().filter(line -> StringUtils.countMatches(line, ":") > 3).//
        // filter(line -> !line.endsWith("test")).//
        // forEach(line -> mvnUris.add(parseMvnUri(line)));
        while (reader.ready()) {
            String line = reader.readLine();
            if ((org.apache.commons.lang3.StringUtils.countMatches(line, ":") > 3) && !line.endsWith("test")) {
                mvnUris.add(parseMvnUri(line));
            } // else not an expected dependencies so ignor it.
        }
        return mvnUris;
    }

    public String getDependencyFilePath() {
        return depTxtPath;
    }

    /**
     * return the location for resolving the depenencies.txt file inside a jar or folder.
     * 
     * @param mavenGroupId, groupId create a location path.
     * @param mavenArtifactId, artifactid used to create the location path.
     * @return "META-INF/maven/" + mavenGroupId + "/" + mavenArtifactId + "/dependencies.txt"
     */
    public static String computeDependenciesFilePath(String mavenGroupId, String mavenArtifactId) {
        return "META-INF/maven/" + mavenGroupId + "/" + mavenArtifactId + "/dependencies.txt";
    }

    /**
     * expecting groupId:artifactId:type[:classifier]:version:scope and output.
     * 
     * <pre>
     * {@code
     * mvn-uri := 'mvn:' [ repository-url '!' ] group-id '/' artifact-id [ '/' [version] [ '/' [type] [ '/' classifier ] ] ] ]
       * }
     * </pre>
     * 
     * @param s
     * @return pax-url formatted string
     */
    String parseMvnUri(String dependencyString) {
        String s = dependencyString.trim();
        int indexOfGpSeparator = s.indexOf(':');
        String groupId = s.substring(0, indexOfGpSeparator);
        int indexOfArtIdSep = s.indexOf(':', indexOfGpSeparator + 1);
        String artifactId = s.substring(indexOfGpSeparator + 1, indexOfArtIdSep);
        int indexOfTypeSep = s.indexOf(':', indexOfArtIdSep + 1);
        String type = s.substring(indexOfArtIdSep + 1, indexOfTypeSep);
        int lastIndex = indexOfTypeSep;
        String classifier = null;
        if (StringUtils.countMatches(s, ":") > 4) {// we have a classifier too
            int indexOfClassifSep = s.indexOf(':', indexOfTypeSep + 1);
            classifier = s.substring(indexOfTypeSep + 1, indexOfClassifSep);
            lastIndex = indexOfClassifSep;
        } // else no classifier.
        int indexOfVersionSep = s.indexOf(':', lastIndex + 1);
        String version = s.substring(lastIndex + 1, indexOfVersionSep);
        // we ignor the scope here
        return "mvn:" + groupId + '/' + artifactId + '/' + version + '/' + type
                + (classifier != null ? '/' + classifier : "");
    }

}