All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lesfurets.jenkins.unit.global.lib.LibraryLoader.groovy Maven / Gradle / Ivy

package com.lesfurets.jenkins.unit.global.lib

import java.nio.file.Files
import java.util.function.Consumer
import java.util.function.Predicate

import org.apache.commons.io.FilenameUtils
import org.codehaus.groovy.runtime.DefaultGroovyMethods

import groovy.transform.CompileStatic

/**
 * Loads global shared libraries to groovy class loader
 */
@CompileStatic
class LibraryLoader {

    private final GroovyClassLoader groovyClassLoader

    private final Map libraryDescriptions

    final Map libRecords = new HashMap<>()

    LibraryLoader(GroovyClassLoader groovyClassLoader, Map libraryDescriptions) {
        this.groovyClassLoader = groovyClassLoader
        this.libraryDescriptions = libraryDescriptions
    }

    static String getLibraryId(LibraryConfiguration lib, String version = null) {
        return "$lib.name@${version ?: lib.defaultVersion}"
    }

    /**
     * Loads all implicit library configurations
     */
    void loadImplicitLibraries() {
        libraryDescriptions.values().stream()
                .filter { it.implicit }
                .filter { !libRecords.containsKey(getLibraryId(it)) }
                .forEach {
            doLoadLibrary(it)
        }
    }

    /**
     * Load library described by expression if it corresponds to a known library configuration
     * @param expression
     * @throws Exception
     */
    void loadLibrary(String expression) throws Exception {
        def lib = parse(expression)
        def libName = lib[0]
        def version = lib[1]
        def library = libraryDescriptions.get(libName)
        if (!library) {
            throw new Exception("Library description '$libName' not found")
        }
        if (!matches(libName, version, library)) {
            throw new Exception("Library '$expression' does not match description $library")
        }
        if (!libRecords.containsKey(getLibraryId(library, version))) {
            doLoadLibrary(library, version)
        }
    }

    /**
     * Loads library to groovy class loader.
     * @param library library configuration.
     * @param version version to load, if null loads the default version defined in configuration.
     * @throws Exception
     */
    private void doLoadLibrary(LibraryConfiguration library, String version = null) throws Exception {
        println "Loading shared library ${library.name} with version ${version ?: library.defaultVersion}"
        try {
            def urls = library.retriever.retrieve(library.name, version ?: library.defaultVersion, library.targetPath)
            def record = new LibraryRecord(library, version ?: library.defaultVersion, urls.path)
            libRecords.put(record.getIdentifier(), record)
            def globalVars = [:]
            urls.forEach { URL url ->
                def file = new File(url.toURI())

                def srcPath = file.toPath().resolve('src')
                def varsPath = file.toPath().resolve('vars')
                def resourcesPath = file.toPath().resolve('resources')
                groovyClassLoader.addURL(srcPath.toUri().toURL())
                groovyClassLoader.addURL(varsPath.toUri().toURL())
                groovyClassLoader.addURL(resourcesPath.toUri().toURL())

                if (varsPath.toFile().exists()) {
                    Files.list(varsPath)
                                    .map { it.toFile() }
                                    .filter ({File it -> it.name.endsWith('.groovy') } as Predicate)
                                    .map { FilenameUtils.getBaseName(it.name) }
                                    .filter ({String it -> !globalVars.containsValue(it) } as Predicate)
                                    .forEach ({ String it ->
                        def clazz = groovyClassLoader.loadClass(it)
                        // instanciate by invokeConstructor to avoid interception
                        Object var = DefaultGroovyMethods.newInstance(clazz)
                        globalVars.put(it, var)
                    } as Consumer)
                }
            }
            record.definedGlobalVars = globalVars
        } catch (Exception e) {
            throw new LibraryLoadingException(e, library, version)
        }
    }

    private static String[] parse(String identifier) {
        identifier.split('@')
        int at = identifier.indexOf('@')
        if (at == -1) {
            return [identifier, null] as String[] // pick up defaultVersion
        } else {
            return [identifier.substring(0, at), identifier.substring(at + 1)] as String[]
        }
    }

    private static boolean matches(String libName, String version, LibraryConfiguration libraryDescription) {
        if (libraryDescription.name == libName) {
            if (version == null) {
                return true
            }
            if (libraryDescription.allowOverride || libraryDescription.defaultVersion == version) {
                return true
            }
        }
        return false
    }

    static class LibraryLoadingException extends Exception {

        LibraryLoadingException(Throwable cause, LibraryConfiguration configuration, String version) {
            super("Error on loading library ${LibraryLoader.getLibraryId(configuration, version)} : ${cause.message}", cause)
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy