1 /* 2 * Copyright (c) 2008-2019 Emmanuel Dupuy. 3 * This project is distributed under the GPLv3 license. 4 * This is a Copyleft license that gives the user the right to use, 5 * copy and modify the code freely for non-commercial purposes. 6 */ 7 8 package org.jd.gui.service.extension; 9 10 import org.jd.gui.util.exception.ExceptionUtil; 11 12 import java.io.File; 13 import java.net.URI; 14 import java.net.URL; 15 import java.net.URLClassLoader; 16 import java.util.*; 17 18 public class ExtensionService { 19 protected static final ExtensionService EXTENSION_SERVICE = new ExtensionService(); 20 protected static final UrlComparator URL_COMPARATOR = new UrlComparator(); 21 22 protected ClassLoader extensionClassLoader; 23 getInstance()24 public static ExtensionService getInstance() { 25 return EXTENSION_SERVICE; 26 } 27 ExtensionService()28 protected ExtensionService() { 29 try { 30 URI jarUri = ExtensionService.class.getProtectionDomain().getCodeSource().getLocation().toURI(); 31 File baseDirectory = new File(jarUri).getParentFile(); 32 File extDirectory = new File(baseDirectory, "ext"); 33 34 if (extDirectory.exists() && extDirectory.isDirectory()) { 35 ArrayList<URL> urls = new ArrayList<>(); 36 37 searchJarAndMetaInf(urls, extDirectory); 38 39 if (!urls.isEmpty()) { 40 URL[] array = urls.toArray(new URL[urls.size()]); 41 Arrays.sort(array, URL_COMPARATOR); 42 extensionClassLoader = new URLClassLoader(array, ExtensionService.class.getClassLoader()); 43 } 44 } 45 } catch (Exception e) { 46 assert ExceptionUtil.printStackTrace(e); 47 } 48 49 extensionClassLoader = ExtensionService.class.getClassLoader(); 50 } 51 searchJarAndMetaInf(List<URL> urls, File directory)52 protected void searchJarAndMetaInf(List<URL> urls, File directory) throws Exception { 53 File metaInf = new File(directory, "META-INF"); 54 55 if (metaInf.exists() && metaInf.isDirectory()) { 56 urls.add(directory.toURI().toURL()); 57 } else { 58 for (File child : directory.listFiles()) { 59 if (child.isDirectory()) { 60 searchJarAndMetaInf(urls, child); 61 } else if (child.getName().toLowerCase().endsWith(".jar")) { 62 urls.add(new URL("jar", "", child.toURI().toURL().toString() + "!/")); 63 } 64 } 65 } 66 } 67 load(Class<T> service)68 public <T> Collection<T> load(Class<T> service) { 69 ArrayList<T> list = new ArrayList<>(); 70 Iterator<T> iterator = ServiceLoader.load(service, extensionClassLoader).iterator(); 71 72 while (iterator.hasNext()) { 73 list.add(iterator.next()); 74 } 75 76 return list; 77 } 78 79 protected static class UrlComparator implements Comparator<URL> { 80 @Override compare(URL url1, URL url2)81 public int compare(URL url1, URL url2) { 82 return url1.getPath().compareTo(url2.getPath()); 83 } 84 } 85 } 86