org.exist.repo.ClasspathHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of exist-core Show documentation
Show all versions of exist-core Show documentation
eXist-db NoSQL Database Core
/*
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
* [email protected]
* http://www.exist-db.org
*
* This library 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.1 of the License, or (at your option) any later version.
*
* This library 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 library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.exist.repo;
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.expath.pkg.repo.FileSystemStorage;
import org.expath.pkg.repo.Package;
import org.expath.pkg.repo.PackageException;
import org.expath.pkg.repo.Packages;
import org.expath.pkg.repo.deps.ProcessorDependency;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
/**
* 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);
@Override
public void prepare(final BrokerPool brokerPool) {
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 {} is not compatible with this version of eXist. To avoid conflicts, Java libraries shipping with this package are not loaded.", pkg.getName());
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 {} is not compatible with this version of eXist. To avoid conflicts, Java libraries shipping with this package are not loaded.", pkg.getName());
} 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(final 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 requiresExistVersion = null;
for (final ProcessorDependency dependency: processorDeps) {
if (Deployment.PROCESSOR_NAME.equals(dependency.getProcessor())) {
if (dependency.getSemver() != null) {
requiresExistVersion = new PackageLoader.Version(dependency.getSemver(), true);
} else if (dependency.getSemverMax() != null || dependency.getSemverMin() != null) {
requiresExistVersion = new PackageLoader.Version(dependency.getSemverMin(), dependency.getSemverMax());
} else if (dependency.getVersions() != null) {
requiresExistVersion = new PackageLoader.Version(dependency.getVersions(), false);
}
break;
}
}
if (requiresExistVersion == null) {
// does the package contain XQuery Module(s) implemented in Java?
final ExistPkgInfo existPkgInfo = (ExistPkgInfo) pkg.getInfo("exist");
if (existPkgInfo == null) {
// no Java modules
return true;
}
final Set javaModules = existPkgInfo.getJavaModules();
if (javaModules == null || javaModules.isEmpty()) {
// no Java modules
return true;
}
/*
There are eXist-db Java modules in the package,
but the package does not declare which version
of eXist-db (the processor) that it depends upon,
therefore we assume it is incompatible.
NOTE - In older versions of eXist-db, if the package
did not declare a dependency on a specific processor
version, we would check whether the version of
eXist-db was between 1.4.0 and 2.2.1
(inclusive). As we are now past eXist-db version
5.2.0, that would always return false!
*/
return false;
} else {
return requiresExistVersion.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