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

org.exist.repo.ClasspathHelper Maven / Gradle / Ivy

/*
 * eXist Open Source Native XML Database
 * Copyright (C) 2012-2015 The eXist-db Project
 * http://exist-db.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
package org.exist.repo;

import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Optional;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.exist.SystemProperties;
import org.exist.start.Classpath;
import org.exist.start.EXistClassLoader;
import org.exist.storage.BrokerPool;
import org.exist.storage.BrokerPoolService;
import org.exist.storage.BrokerPoolServiceException;
import org.expath.pkg.repo.*;
import org.expath.pkg.repo.Package;
import org.expath.pkg.repo.deps.ProcessorDependency;

/**
 * Helper class to construct classpath for expath modules containing
 * jar files. Part of start.jar
 */
public class ClasspathHelper implements BrokerPoolService {

    private final static Logger LOG = LogManager.getLogger(ClasspathHelper.class);

    // if no eXist version is specified in the expath-pkg.xml, we assume it is 2.2 or older
    private final static PackageLoader.Version DEFAULT_VERSION = new PackageLoader.Version("1.4.0", "2.2.1");

    @Override
    public void prepare(final BrokerPool brokerPool) throws BrokerPoolServiceException {
        final ClassLoader loader = brokerPool.getClassLoader();
        if (!(loader instanceof EXistClassLoader)) {
            return;
        }
        final Classpath cp = new Classpath();
        scanPackages(brokerPool, cp);
        ((EXistClassLoader)loader).addURLs(cp);
    }

    public static void updateClasspath(BrokerPool pool, org.expath.pkg.repo.Package pkg) throws PackageException {
        final ClassLoader loader = pool.getClassLoader();
        if (!(loader instanceof EXistClassLoader))
            {return;}
        if (!isCompatible(pkg)) {
            LOG.warn("Package " + pkg.getName() + " is not compatible with this version of eXist. " +
                "To avoid conflicts, Java libraries shipping with this package are not loaded.");
            return;
        }
        final FileSystemStorage.FileSystemResolver resolver = (FileSystemStorage.FileSystemResolver) pkg.getResolver();
        final Path packageDir = resolver.resolveResourceAsFile(".");
        final Classpath cp = new Classpath();
        try {
            scanPackageDir(cp, packageDir);
            ((EXistClassLoader)loader).addURLs(cp);
        } catch (final IOException e) {
            LOG.warn("An error occurred while updating classpath for package " + pkg.getName(), e);
        }
    }

    private static void scanPackages(BrokerPool pool, Classpath classpath) {
        try {
            final Optional repo = pool.getExpathRepo();
	    if (repo.isPresent()) {
            for (final Packages pkgs : repo.get().getParentRepo().listPackages()) {
                final Package pkg = pkgs.latest();
                if (!isCompatible(pkg)) {
                    LOG.warn("Package " + pkg.getName() + " is not compatible with this version of eXist. " +
                            "To avoid conflicts, Java libraries shipping with this package are not loaded.");
                } else {
                    try {
                        final FileSystemStorage.FileSystemResolver resolver = (FileSystemStorage.FileSystemResolver) pkg.getResolver();
                        final Path packageDir = resolver.resolveResourceAsFile(".");
                        scanPackageDir(classpath, packageDir);
                    } catch (final IOException e) {
                        LOG.warn("An error occurred while updating classpath for package " + pkg.getName(), e);
                    }
                }
            }
	    }
        } catch (final Exception e) {
            LOG.warn("An error occurred while updating classpath for packages", e);
        }
    }

    private static boolean isCompatible(Package pkg) throws PackageException {
        // determine the eXist-db version this package is compatible with
        final Collection processorDeps = pkg.getProcessorDeps();
        final String procVersion = SystemProperties.getInstance().getSystemProperty("product-version", "1.0");
        PackageLoader.Version processorVersion = DEFAULT_VERSION;
        for (ProcessorDependency dependency: processorDeps) {
            if (Deployment.PROCESSOR_NAME.equals(dependency.getProcessor())) {
                if (dependency.getSemver() != null) {
                    processorVersion = new PackageLoader.Version(dependency.getSemver(), true);
                } else if (dependency.getSemverMax() != null || dependency.getSemverMin() != null) {
                    processorVersion = new PackageLoader.Version(dependency.getSemverMin(), dependency.getSemverMax());
                } else if (dependency.getVersions() != null) {
                    processorVersion = new PackageLoader.Version(dependency.getVersions(), false);
                }
                break;
            }
        }
        return processorVersion.getDependencyVersion().isCompatible(procVersion);
    }

    private static void scanPackageDir(Classpath classpath, Path module) throws IOException {
        final Path dotExist =  module.resolve(".exist");
        if (Files.exists(dotExist)) {
            if (!Files.isDirectory(dotExist)) {
                throw new IOException("The .exist config dir is not a dir: " + dotExist);
            }

            final Path cp = dotExist.resolve("classpath.txt");
            if (Files.exists(cp)) {
                try (final BufferedReader reader = Files.newBufferedReader(cp)) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        classpath.addComponent(line);
                    }
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy