11package org .knime .scijava .core ;
22
33import java .io .IOException ;
4- import java .net .MalformedURLException ;
54import java .net .URL ;
5+ import java .util .ArrayList ;
66import java .util .Collections ;
77import java .util .Enumeration ;
88import java .util .HashMap ;
99import java .util .HashSet ;
10+ import java .util .List ;
1011import java .util .Map ;
1112import java .util .Set ;
1213
1314import 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 ;
1418import org .eclipse .osgi .util .ManifestElement ;
1519import org .osgi .framework .Bundle ;
1620import org .osgi .framework .BundleException ;
1721import org .osgi .framework .Constants ;
1822import org .osgi .framework .FrameworkUtil ;
23+ import org .osgi .framework .namespace .BundleNamespace ;
24+ import org .osgi .framework .namespace .PackageNamespace ;
1925
2026/**
2127 * ResourceAwareClassLoader
2632 * @author Jonathan Hale (University of Konstanz)
2733 *
2834 */
35+ @ SuppressWarnings ("restriction" )
2936public class ResourceAwareClassLoader extends ClassLoader {
3037
3138 /**
3239 * Resources which need to be treated in a special way.
3340 */
3441 // 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" ,
3743 "META-INF/services/javax.script.ScriptEngineFactory" };
3844
3945 private final Map <String , Set <URL >> urls = new HashMap <String , Set <URL >>();
@@ -77,51 +83,75 @@ public ResourceAwareClassLoader(final ClassLoader parent, Class<?> clazz) {
7783 urls .put (res , new HashSet <URL >());
7884 }
7985
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 );
9987
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+ }
10790
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 );
110104 }
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+ }
111132
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+ }
119141 }
120142 }
121143 }
122144 }
123145 } 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 );
125155 }
126156 }
127157
@@ -133,26 +163,30 @@ public Enumeration<URL> getResources(final String name) throws IOException {
133163 return super .getResources (name );
134164 }
135165
136- for (final URL url : Collections .list (super .getResources (name ))){
166+ for (final URL url : Collections .list (super .getResources (name ))) {
137167 safeAdd (urlList , url );
138168 }
139-
169+
140170 return Collections .enumeration (urlList );
141171 }
142-
172+
143173 /**
144174 * Get a set of file URLs to the bundles dependency bundles.
175+ *
145176 * @return set of dependency bundle file urls
146177 */
147178 public Set <URL > getBundleUrls () {
148179 return bundleUrls ;
149180 }
150-
181+
151182 /*
152183 * Add url to urls while making sure, that the resulting file urls are
153184 * always unique.
185+ *
154186 * @param urls Set to add the url to
187+ *
155188 * @param urlToAdd Url to add to the set
189+ *
156190 * @see FileLocator
157191 */
158192 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) {
173207 // no duplicate found, we can safely add this url.
174208 urls .add (urlToAdd );
175209 }
176-
210+
177211}
0 commit comments