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