/*
* Copyright (c) 2008-2019 Emmanuel Dupuy.
* This project is distributed under the GPLv3 license.
* This is a Copyleft license that gives the user the right to use,
* copy and modify the code freely for non-commercial purposes.
*/
package org.jd.gui.service.extension;
import org.jd.gui.util.exception.ExceptionUtil;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
public class ExtensionService {
protected static final ExtensionService EXTENSION_SERVICE = new ExtensionService();
protected static final UrlComparator URL_COMPARATOR = new UrlComparator();
protected ClassLoader extensionClassLoader;
public static ExtensionService getInstance() {
return EXTENSION_SERVICE;
}
protected ExtensionService() {
try {
URI jarUri = ExtensionService.class.getProtectionDomain().getCodeSource().getLocation().toURI();
File baseDirectory = new File(jarUri).getParentFile();
File extDirectory = new File(baseDirectory, "ext");
if (extDirectory.exists() && extDirectory.isDirectory()) {
ArrayList<URL> urls = new ArrayList<>();
searchJarAndMetaInf(urls, extDirectory);
if (!urls.isEmpty()) {
URL[] array = urls.toArray(new URL[urls.size()]);
Arrays.sort(array, URL_COMPARATOR);
extensionClassLoader = new URLClassLoader(array, ExtensionService.class.getClassLoader());
}
}
} catch (Exception e) {
assert ExceptionUtil.printStackTrace(e);
}
extensionClassLoader = ExtensionService.class.getClassLoader();
}
protected void searchJarAndMetaInf(List<URL> urls, File directory) throws Exception {
File metaInf = new File(directory, "META-INF");
if (metaInf.exists() && metaInf.isDirectory()) {
urls.add(directory.toURI().toURL());
} else {
for (File child : directory.listFiles()) {
if (child.isDirectory()) {
searchJarAndMetaInf(urls, child);
} else if (child.getName().toLowerCase().endsWith(".jar")) {
urls.add(new URL("jar", "", child.toURI().toURL().toString() + "!/"));
}
}
}
}
public <T> Collection<T> load(Class<T> service) {
ArrayList<T> list = new ArrayList<>();
Iterator<T> iterator = ServiceLoader.load(service, extensionClassLoader).iterator();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
protected static class UrlComparator implements Comparator<URL> {
@Override
public int compare(URL url1, URL url2) {
return url1.getPath().compareTo(url2.getPath());
}
}
}