org.datacleaner.extensions.ExtensionPackage Maven / Gradle / Ivy
/**
* DataCleaner (community edition)
* Copyright (C) 2014 Free Software Foundation, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.datacleaner.extensions;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.metamodel.util.HasName;
import org.datacleaner.descriptors.ClasspathScanDescriptorProvider;
import org.datacleaner.descriptors.CompositeDescriptorProvider;
import org.datacleaner.descriptors.DescriptorProvider;
import org.datacleaner.util.FileFilters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Represents an extension/plug-in package that the user has installed. An
* extension is based on a set of (JAR) files and optionally some metadata about
* these.
*/
public final class ExtensionPackage implements Serializable, HasName {
private static final long serialVersionUID = 1L;
private static final Logger logger = LoggerFactory.getLogger(ExtensionPackage.class);
private static Collection _allExtensionClassLoaders = new ArrayList<>();
private final File[] _files;
private final String _name;
private final String _scanPackage;
private final boolean _scanRecursive;
private final Map _additionalProperties;
private transient boolean _loaded = false;
private transient int _loadedAnalyzers;
private transient int _loadedTransformers;
private transient int _loadedFilters;
private transient int _loadedRenderers;
private transient ClassLoader _classLoader;
public ExtensionPackage(final String name, String scanPackage, final boolean scanRecursive, final File[] files) {
_name = name;
if (scanPackage == null) {
scanPackage = "";
}
_scanPackage = scanPackage;
_scanRecursive = scanRecursive;
_files = files;
_additionalProperties = new HashMap<>();
}
/**
* Gets the classloader that represents the currently loaded extensions'
* classes.
*
* @return
*/
public static ClassLoader getExtensionClassLoader() {
final Collection childClassLoaders = new ArrayList<>();
childClassLoaders.addAll(_allExtensionClassLoaders);
childClassLoaders.add(ClassLoaderUtils.getParentClassLoader());
return new CompoundClassLoader(childClassLoaders);
}
public File[] getFiles() {
return Arrays.copyOf(_files, _files.length);
}
/**
* Determines if this extension is externally installed from a file not in
* the primary classpath.
*
* @return
*/
public boolean isExternal() {
return _files != null && _files.length > 0;
}
/**
* Determines if this extension is internally installed by being placed on
* the primary classpath.
*
* @return
*/
private boolean isInternal() {
return !isExternal();
}
/**
* Gets the name of the extension
*/
@Override
public String getName() {
return _name;
}
public String getScanPackage() {
return _scanPackage;
}
public boolean isScanRecursive() {
return _scanRecursive;
}
public void loadExtension() {
if (isInternal()) {
// no reason to change _latestClassLoader
_classLoader = ClassLoaderUtils.getParentClassLoader();
return;
}
synchronized (ExtensionPackage.class) {
// Each extension is loaded using its own ExtensionClassLoader. This
// loader has 2 parents. The first is an URL class loader
// provided by ClassLoaderUtils. This class loader loads classes
// specific to the extension. The second class loader resolves all
// classes already loaded from the main locations.
_classLoader = ClassLoaderUtils.createClassLoader(getJarFiles(), ClassLoaderUtils.getParentClassLoader());
_allExtensionClassLoaders.add(_classLoader);
}
}
private File[] getJarFiles() {
if (_files.length == 1 && _files[0].isDirectory()) {
return _files[0].listFiles(FileFilters.JAR);
}
return _files;
}
public ExtensionPackage loadDescriptors(final DescriptorProvider descriptorProvider) throws IllegalStateException {
if (!_loaded) {
final ClasspathScanDescriptorProvider classpathScanner;
if (descriptorProvider instanceof ClasspathScanDescriptorProvider) {
classpathScanner = (ClasspathScanDescriptorProvider) descriptorProvider;
} else if (descriptorProvider instanceof CompositeDescriptorProvider) {
classpathScanner = ((CompositeDescriptorProvider) descriptorProvider).findClasspathScanProvider();
} else {
throw new IllegalStateException(
"Can only load user extensions when descriptor provider is of classpath scanner type.");
}
final int analyzersBefore = classpathScanner.getAnalyzerDescriptors().size();
final int transformersBefore = classpathScanner.getTransformerDescriptors().size();
final int filtersBefore = classpathScanner.getFilterDescriptors().size();
final int renderersBefore = classpathScanner.getRendererBeanDescriptors().size();
if (_classLoader == null) {
loadExtension();
}
if (_scanPackage != null) {
classpathScanner.scanPackage(_scanPackage, _scanRecursive, _classLoader, true, getJarFiles());
}
_loadedAnalyzers = classpathScanner.getAnalyzerDescriptors().size() - analyzersBefore;
_loadedTransformers = classpathScanner.getTransformerDescriptors().size() - transformersBefore;
_loadedFilters = classpathScanner.getFilterDescriptors().size() - filtersBefore;
_loadedRenderers = classpathScanner.getRendererBeanDescriptors().size() - renderersBefore;
_loaded = true;
logger.info("Succesfully loaded extension '{}' containing {} analyzers, {} transformers, {} filters,"
+ " {} renderers", getName(), getLoadedAnalyzers(), getLoadedTransformers(), getLoadedFilters(),
getLoadedRenderers());
}
return this;
}
public Map getAdditionalProperties() {
return _additionalProperties;
}
public boolean isLoaded() {
return _loaded;
}
public int getLoadedRenderers() {
return _loadedRenderers;
}
public int getLoadedAnalyzers() {
return _loadedAnalyzers;
}
public int getLoadedFilters() {
return _loadedFilters;
}
public int getLoadedTransformers() {
return _loadedTransformers;
}
public String getDescription() {
return _additionalProperties.get("description");
}
public String getVersion() {
return _additionalProperties.get("version");
}
public String getUrl() {
return _additionalProperties.get("url");
}
public String getAuthor() {
return _additionalProperties.get("author");
}
/**
* Returns the name of the package.
*/
public String toString() {
return getName();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy