KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ungoverned > oscar > OSGiImportSearchPolicy


1 /*
2  * Oscar - An implementation of the OSGi framework.
3  * Copyright (c) 2004, Richard S. Hall
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of the ungoverned.org nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * Contact: Richard S. Hall (heavy@ungoverned.org)
33  * Contributor(s):
34  *
35 **/

36 package org.ungoverned.oscar;
37
38 import java.net.URL JavaDoc;
39
40 import org.ungoverned.moduleloader.Module;
41 import org.ungoverned.moduleloader.ResourceNotFoundException;
42 import org.ungoverned.moduleloader.search.ImportSearchPolicy;
43
44 /**
45  * This class extends <tt>ImportSearchPolicy</tt> in order to implement
46  * dynamic package import as defined by the OSGi specification. It does this
47  * by overriding the <tt>ImportSearchPolicy.findClass()</tt> and
48  * <tt>ImportSearchPolicy.findResource()</tt> methods. By default, this
49  * class lets requests fall through to the super class, but if either
50  * method throws an exception or returns <tt>null</tt>, then it checks
51  * the dynamic import meta-data for the associated bundle.
52 **/

53 public class OSGiImportSearchPolicy extends ImportSearchPolicy
54 {
55     /**
56      * This is the name of the "dynamic-imports" meta-data attribute that
57      * should be attached to each module. The value of this attribute
58      * is of type <tt>String[]</tt> and contains dynamic import package
59      * specs as defined by the OSGi bundle manifest specification.
60     **/

61     public static final String JavaDoc DYNAMIC_IMPORTS_ATTR = "dynamic-imports";
62
63     private Oscar m_oscar = null;
64
65     public OSGiImportSearchPolicy(Oscar oscar)
66     {
67         super(new OSGiCompatibilityPolicy(oscar), new OSGiSelectionPolicy(oscar));
68         m_oscar = oscar;
69     }
70
71     public Class JavaDoc findClass(Module module, String JavaDoc name)
72         throws ClassNotFoundException JavaDoc
73     {
74         Class JavaDoc clazz = super.findClass(module, name);
75
76         if (clazz == null)
77         {
78             clazz = findClassDynamic(module, name);
79         }
80
81         return clazz;
82     }
83
84     public URL JavaDoc findResource(Module module, String JavaDoc name)
85         throws ResourceNotFoundException
86     {
87         URL JavaDoc url = super.findResource(module, name);
88
89         if (url == null)
90         {
91             url = findResourceDynamic(module, name);
92         }
93
94         return url;
95     }
96
97     protected Class JavaDoc findClassDynamic(Module module, String JavaDoc name)
98     {
99         // There is an overriding assumption here that a package is
100
// never split across bundles. If a package can be split
101
// across bundles, then this will fail.
102

103         try
104         {
105             BundleImpl bundle =
106                 (BundleImpl) m_oscar.getBundle(
107                     BundleInfo.getBundleIdFromModuleId(module.getId()));
108             BundleInfo info = bundle.getInfo();
109
110             // See if the target package name matches the package
111
// spec for this dynamic import.
112
int idx = name.lastIndexOf('.');
113             if (idx < 0)
114             {
115                 // Ignore classes with no package.
116
return null;
117             }
118             String JavaDoc pkgTarget = name.substring(0, idx);
119
120             // Check the dynamic import specs for a match of
121
// the target package.
122
String JavaDoc[] dynImports = OSGiImportSearchPolicy.getDynamicImports(module);
123             boolean matches = false;
124             for (int i = 0; !matches && (i < dynImports.length); i++)
125             {
126                 // Star matches everything.
127
if (dynImports[i].equals("*"))
128                 {
129                     matches = true;
130                 }
131                 // Packages ending in ".*" must match starting strings.
132
else if (dynImports[i].endsWith(".*"))
133                 {
134                     matches = pkgTarget.regionMatches(
135                         0, dynImports[i], 0, dynImports[i].length() - 2);
136                 }
137                 // Or we can have a precise match.
138
else
139                 {
140                     matches = pkgTarget.equals(dynImports[i]);
141                 }
142             }
143
144             // If the target package does not match any dynamically imported
145
// packages or if the module already imports the target package,
146
// then just return null. The module may already import the target
147
// package if the class being searched for does not actually exist.
148
if (!matches || ImportSearchPolicy.doesImport(module, pkgTarget))
149             {
150                 return null;
151             }
152
153             // Try to add the import, which will also resolve the import
154
// if the module is currently active.
155
int[] version = { 0, 0, 0 };
156             if (m_oscar.addImport(module, pkgTarget, version, false))
157             {
158                 // Get the module that resolves the package so we can use
159
// its class loader to load the target class; it is only
160
// necessary to load the class manually this first time
161
// because we have dynamically add the dynamically imported
162
// package to the importing module's meta-data, so future
163
// attempts to load classes from the dynamically imported
164
// package will be processed in the normal fashion.
165
Module resolvingModule =
166                     ImportSearchPolicy.getImportResolvingModule(module, pkgTarget);
167                 if (resolvingModule != null)
168                 {
169                     // Now try to get the class from the exporter.
170
return resolvingModule.getClassLoader().loadClass(name);
171                 }
172             }
173         }
174         catch (Exception JavaDoc ex)
175         {
176             Oscar.error("Unable to dynamically import package.", ex);
177         }
178
179         return null;
180     }
181
182     protected URL JavaDoc findResourceDynamic(Module module, String JavaDoc name)
183     {
184         // There is an overriding assumption here that a package is
185
// never split across bundles. If a package can be split
186
// across bundles, then this will fail.
187

188         try
189         {
190             BundleImpl bundle =
191                 (BundleImpl) m_oscar.getBundle(
192                     BundleInfo.getBundleIdFromModuleId(module.getId()));
193             BundleInfo info = bundle.getInfo();
194
195             // See if the target package name matches the package
196
// spec for this dynamic import.
197
int idx = name.lastIndexOf('/');
198             if (idx < 0)
199             {
200                 // Ignore resources with no package.
201
return null;
202             }
203             String JavaDoc pkgTarget = name.substring(0, idx);
204             pkgTarget = pkgTarget.replace('/', '.');
205
206             // Check the dynamic import specs for a match of
207
// the target package.
208
String JavaDoc[] dynImports = OSGiImportSearchPolicy.getDynamicImports(module);
209             boolean matches = false;
210             for (int i = 0; !matches && (i < dynImports.length); i++)
211             {
212                 // Star matches everything.
213
if (dynImports[i].equals("*"))
214                 {
215                     matches = true;
216                 }
217                 // Packages ending in ".*" must match starting strings.
218
else if (dynImports[i].endsWith(".*"))
219                 {
220                     matches = pkgTarget.regionMatches(
221                         0, dynImports[i], 0, dynImports[i].length() - 2);
222                 }
223                 // Or we can have a precise match.
224
else
225                 {
226                     matches = pkgTarget.equals(dynImports[i]);
227                 }
228             }
229
230             // If the target package does not match any dynamically imported
231
// packages or if the module already imports the target package,
232
// then just return null. The module may already import the target
233
// package if the class being searched for does not actually exist.
234
if (!matches || ImportSearchPolicy.doesImport(module, pkgTarget))
235             {
236                 return null;
237             }
238
239             // Try to add the import, which will also resolve the import
240
// if the module is currently active.
241
int[] version = { 0, 0, 0 };
242             if (m_oscar.addImport(module, pkgTarget, version, false))
243             {
244                 // Get the module that resolves the package so we can use
245
// its class loader to load the target class; it is only
246
// necessary to load the class manually this first time
247
// because we have dynamically add the dynamically imported
248
// package to the importing module's meta-data, so future
249
// attempts to load classes from the dynamically imported
250
// package will be processed in the normal fashion.
251
Module resolvingModule =
252                     ImportSearchPolicy.getImportResolvingModule(module, pkgTarget);
253                 if (resolvingModule != null)
254                 {
255                     // Now try to get the resource from the exporter.
256
return resolvingModule.getClassLoader().getResource(name);
257                 }
258             }
259         }
260         catch (Exception JavaDoc ex)
261         {
262             Oscar.error("Unable to dynamically import package.", ex);
263         }
264
265         return null;
266     }
267
268     /**
269      * Utility method that returns the <tt>DYNAMIC_IMPORTS_ATTR</tt>
270      * attribute for the specified module.
271      * @param module the module whose <tt>DYNAMIC_IMPORTS_ATTR</tt>
272      * attribute is to be retrieved.
273      * @return an <tt>String[]</tt>.
274     **/

275     public static String JavaDoc[] getDynamicImports(Module module)
276     {
277         Object JavaDoc value = module.getAttribute(OSGiImportSearchPolicy.DYNAMIC_IMPORTS_ATTR);
278         if (value != null)
279         {
280             return (String JavaDoc[]) value;
281         }
282         return new String JavaDoc[0];
283     }
284 }
Popular Tags