1
1
package org .knime .scijava .core ;
2
2
3
3
import java .io .IOException ;
4
- import java .net .MalformedURLException ;
5
4
import java .net .URL ;
5
+ import java .util .ArrayList ;
6
6
import java .util .Collections ;
7
7
import java .util .Enumeration ;
8
8
import java .util .HashMap ;
9
9
import java .util .HashSet ;
10
+ import java .util .List ;
10
11
import java .util .Map ;
11
12
import java .util .Set ;
12
13
13
14
import org .eclipse .core .runtime .FileLocator ;
15
+ import org .eclipse .osgi .container .ModuleWire ;
16
+ import org .eclipse .osgi .container .ModuleWiring ;
17
+ import org .eclipse .osgi .internal .loader .EquinoxClassLoader ;
14
18
import org .eclipse .osgi .util .ManifestElement ;
15
19
import org .osgi .framework .Bundle ;
16
20
import org .osgi .framework .BundleException ;
17
21
import org .osgi .framework .Constants ;
18
22
import org .osgi .framework .FrameworkUtil ;
23
+ import org .osgi .framework .namespace .BundleNamespace ;
24
+ import org .osgi .framework .namespace .PackageNamespace ;
19
25
20
26
/**
21
27
* ResourceAwareClassLoader
26
32
* @author Jonathan Hale (University of Konstanz)
27
33
*
28
34
*/
35
+ @ SuppressWarnings ("restriction" )
29
36
public class ResourceAwareClassLoader extends ClassLoader {
30
37
31
38
/**
32
39
* Resources which need to be treated in a special way.
33
40
*/
34
41
// TODO make an extension point to add resources as needed (later)
35
- private final String [] RESOURCES = new String [] {
36
- "META-INF/json/org.scijava.plugin.Plugin" ,
42
+ private final String [] RESOURCES = new String [] { "META-INF/json/org.scijava.plugin.Plugin" ,
37
43
"META-INF/services/javax.script.ScriptEngineFactory" };
38
44
39
45
private final Map <String , Set <URL >> urls = new HashMap <String , Set <URL >>();
@@ -77,51 +83,75 @@ public ResourceAwareClassLoader(final ClassLoader parent, Class<?> clazz) {
77
83
urls .put (res , new HashSet <URL >());
78
84
}
79
85
80
- final String requireBundle = (String ) FrameworkUtil .getBundle (clazz )
81
- .getHeaders ().get (Constants .REQUIRE_BUNDLE );
82
- try {
83
- final ManifestElement [] elements = ManifestElement .parseHeader (
84
- Constants .BUNDLE_CLASSPATH , requireBundle );
85
- for (final ManifestElement manifestElement : elements ) {
86
- final Bundle bundle = org .eclipse .core .runtime .Platform
87
- .getBundle (manifestElement .getValue ());
88
-
89
- try {
90
- // get file url for this bundle
91
- bundleUrls .add (new URL ("file://"
92
- + FileLocator .getBundleFile (bundle )
93
- .getAbsolutePath ()));
94
- } catch (MalformedURLException e1 ) {
95
- e1 .printStackTrace ();
96
- } catch (IOException e1 ) {
97
- e1 .printStackTrace ();
98
- }
86
+ processBuddies (clazz );
99
87
100
- for (final String res : RESOURCES ) {
101
- Enumeration <URL > resources ;
102
- try {
103
- resources = bundle .getResources (res );
104
- } catch (IOException e ) {
105
- continue ;
106
- }
88
+ processBundle (FrameworkUtil .getBundle (clazz ), true );
89
+ }
107
90
108
- if (resources == null ) {
109
- continue ;
91
+ private void processBuddies (Class <?> clazz ) {
92
+ final EquinoxClassLoader loader = (EquinoxClassLoader ) clazz .getClassLoader ();
93
+ ArrayList <ModuleWiring > allDependents = new ArrayList <ModuleWiring >();
94
+ List <ModuleWire > providedWires = loader .getBundleLoader ().getWiring ().getProvidedModuleWires (null );
95
+ if (providedWires != null ) {
96
+ for (ModuleWire wire : providedWires ) {
97
+ String namespace = wire .getRequirement ().getNamespace ();
98
+ if (PackageNamespace .PACKAGE_NAMESPACE .equals (namespace )
99
+ || BundleNamespace .BUNDLE_NAMESPACE .equals (namespace )) {
100
+ ModuleWiring dependent = wire .getRequirerWiring ();
101
+ if (!allDependents .contains (dependent )) {
102
+ bundleUrls .add (createBundleURL (dependent .getBundle ()));
103
+ processBundle (dependent .getBundle (), false );
110
104
}
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ private void processBundle (final Bundle b , final boolean addRessources ) {
111
+ final String requireBundle = (String ) b .getHeaders ().get (Constants .REQUIRE_BUNDLE );
112
+ try {
113
+ final ManifestElement [] elements = ManifestElement .parseHeader (Constants .BUNDLE_CLASSPATH , requireBundle );
114
+ for (final ManifestElement manifestElement : elements ) {
115
+ final Bundle bundle = org .eclipse .core .runtime .Platform .getBundle (manifestElement .getValue ());
116
+
117
+ // get file url for this bundle
118
+ bundleUrls .add (createBundleURL (bundle ));
119
+
120
+ if (addRessources ) {
121
+ for (final String res : RESOURCES ) {
122
+ Enumeration <URL > resources ;
123
+ try {
124
+ resources = bundle .getResources (res );
125
+ } catch (IOException e ) {
126
+ continue ;
127
+ }
128
+
129
+ if (resources == null ) {
130
+ continue ;
131
+ }
111
132
112
- while (resources .hasMoreElements ()) {
113
- final URL resource = resources .nextElement ();
114
- // we want to avoid transitive resolving of dependencies
115
- final String host = resource .getHost ();
116
- if (bundle .getBundleId () == Long .valueOf (host
117
- .substring (0 , host .indexOf ("." )))) {
118
- safeAdd (urls .get (res ), resource );
133
+ while (resources .hasMoreElements ()) {
134
+ final URL resource = resources .nextElement ();
135
+ // we want to avoid transitive resolving of
136
+ // dependencies
137
+ final String host = resource .getHost ();
138
+ if (bundle .getBundleId () == Long .valueOf (host .substring (0 , host .indexOf ("." )))) {
139
+ safeAdd (urls .get (res ), resource );
140
+ }
119
141
}
120
142
}
121
143
}
122
144
}
123
145
} catch (BundleException e ) {
124
- e .printStackTrace ();
146
+ throw new RuntimeException (e );
147
+ }
148
+ }
149
+
150
+ private URL createBundleURL (final Bundle bundle ) {
151
+ try {
152
+ return new URL ("file://" + FileLocator .getBundleFile (bundle ).getAbsolutePath ());
153
+ } catch (IOException e ) {
154
+ throw new RuntimeException (e );
125
155
}
126
156
}
127
157
@@ -133,26 +163,30 @@ public Enumeration<URL> getResources(final String name) throws IOException {
133
163
return super .getResources (name );
134
164
}
135
165
136
- for (final URL url : Collections .list (super .getResources (name ))){
166
+ for (final URL url : Collections .list (super .getResources (name ))) {
137
167
safeAdd (urlList , url );
138
168
}
139
-
169
+
140
170
return Collections .enumeration (urlList );
141
171
}
142
-
172
+
143
173
/**
144
174
* Get a set of file URLs to the bundles dependency bundles.
175
+ *
145
176
* @return set of dependency bundle file urls
146
177
*/
147
178
public Set <URL > getBundleUrls () {
148
179
return bundleUrls ;
149
180
}
150
-
181
+
151
182
/*
152
183
* Add url to urls while making sure, that the resulting file urls are
153
184
* always unique.
185
+ *
154
186
* @param urls Set to add the url to
187
+ *
155
188
* @param urlToAdd Url to add to the set
189
+ *
156
190
* @see FileLocator
157
191
*/
158
192
private static void safeAdd (final Set <URL > urls , final URL urlToAdd ) {
@@ -173,5 +207,5 @@ private static void safeAdd(final Set<URL> urls, final URL urlToAdd) {
173
207
// no duplicate found, we can safely add this url.
174
208
urls .add (urlToAdd );
175
209
}
176
-
210
+
177
211
}
0 commit comments