blob: 66b64a27efec01c570fbd09ffa1bac07dcd52a06 [file] [log] [blame]
Richard S. Hall930fecc2005-08-16 18:33:34 +00001/*
2 * Copyright 2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
Richard S. Hall5a031592005-08-19 19:53:58 +000017package org.apache.felix.moduleloader;
Richard S. Hall930fecc2005-08-16 18:33:34 +000018
19import java.security.AccessController;
20import java.security.PrivilegedAction;
21import java.util.*;
22
23/**
24 * <p>
25 * The <tt>Module</tt> class is a grouping mechanism for application classes
26 * and resources. Conceptually, most applications are grouped into
27 * entities such as JAR files (containing classes and resources) and native
28 * libraries. In some cases, these entities are core application classes and
29 * resources, while in other cases, these entities are ancillary, such as
30 * dynamically loaded plug-ins. Applications place some level of semantics
31 * onto these types of entities or <i>modules</i>, but for the <tt>ModuleLoader</tt>,
32 * no particular semantics are attached to modules (other than they are a grouping
33 * mechanism for classes and resources). This means that the application
34 * is free to map itself into modules any way that is appropriate.
35 * </p>
36 * <p>
37 * A module has the following features:
38 * </p>
39 * <ul>
40 * <li>A unique identifier within the scope of its <tt>ModuleManager</tt>.
41 * </li>
42 * <li>A set of key-value attribute pairs.
43 * </li>
44 * <li>A set of resource sources from which it is possible to
45 * retrieve classes and resources.
46 * </li>
47 * <li>A set of native library sources from which it is possible
48 * to retrieve native libraries.
49 * </li>
50 * </ul>
51 * <p>
52 * A module's identifier must be unique within the scope of its
53 * <tt>ModuleManager</tt>, but there is no meaning associated with it. The
54 * set of attribute-value pairs attached to the module have no meaning to
55 * the <tt>ModuleManager</tt>, nor does it consult them at all. The point
56 * of these attributes is to attach meta-data for use by
57 * <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a> implementations.
58 * Attributes are represented as an array of <tt>Object</tt>
59 * arrays, i.e., <tt>Object[][]</tt>. Each element in the attribute array is
60 * a two-element <tt>Object</tt> array, where <tt>Module.KEY_IDX</tt> is the attribute's
61 * key and <tt>Module.VALUE_IDX</tt> is the attribute's value.
62 * </p>
63 * <p>
64 * The actual contents of a module is contained in two sets of sources
65 * for its resources and native libraries,
66 * <a href="ResourceSource.html"><tt>ResourceSource</tt></a>s
67 * and <a href="LibrarySource.html"><tt>LibrarySource</tt></a>s, respectively.
68 * Each module also has a <a href="ModuleClassLoader.html"><tt>ModuleClassLoader</tt></a>
69 * associated with it. The <tt>ModuleClassLoader</tt> consults these two types
70 * of sources to find classes, resources, and native libraries.
71 * </p>
Richard S. Hall5a031592005-08-19 19:53:58 +000072 * @see org.apache.felix.moduleloader.ModuleManager
73 * @see org.apache.felix.moduleloader.ModuleClassLoader
74 * @see org.apache.felix.moduleloader.ResourceSource
75 * @see org.apache.felix.moduleloader.LibrarySource
Richard S. Hall930fecc2005-08-16 18:33:34 +000076**/
77public class Module
78{
79 /**
80 * This is the index used to retrieve the key of an attribute;
81 * an attribute is represented as an <tt>Object[]</tt> instance.
82 **/
83 public static final int KEY_IDX = 0;
84 /**
85 * This is the index used to retrieve the value of an attribute;
86 * an attribute is represented as an <tt>Object[]</tt> instance.
87 **/
88 public static final int VALUE_IDX = 1;
89
90 private ModuleManager m_mgr = null;
91 private String m_id = null;
92 private boolean m_useParentSource = false;
93 private Map m_attributeMap = new HashMap();
94 private ResourceSource[] m_resSources = null;
95 private LibrarySource[] m_libSources = null;
96 private ModuleClassLoader m_loader = null;
97
98 /**
99 * <p>
100 * Constructs a <tt>Module</tt> instance that will be associated with
101 * the specified <tt>ModuleManager</tt> and will have the specified
102 * identifier, attributes, resource sources, and library sources. In general,
103 * modules should not be created directly, but should be created by making
104 * a call to <tt>ModuleManager.addModule()</tt>.
105 * </p>
106 * @param mgr the <tt>ModuleManager</tt> that will be associated to
107 * the instance.
108 * @param id the identifier of the instance.
109 * @param attributes the set of attributes associated with the instance.
110 * @param resSources the set of <tt>ResourceSource</tt>s associated with
111 * the instance.
112 * @param libSources the set of <tt>LibrarySource</tt>s associated with
113 * the instance.
114 * @param useParentSource a flag indicating whether or not the parent
115 * class loader should be used as a resource source; this is an
116 * ugly hack to allow a module to masquerade as the system
117 * class loader.
Richard S. Hall5a031592005-08-19 19:53:58 +0000118 * @see org.apache.felix.moduleloader.ModuleManager
119 * @see org.apache.felix.moduleloader.ResourceSource
120 * @see org.apache.felix.moduleloader.LibrarySource
Richard S. Hall930fecc2005-08-16 18:33:34 +0000121 **/
122 public Module(
123 ModuleManager mgr, String id, Object[][] attributes,
124 ResourceSource[] resSources, LibrarySource[] libSources,
125 boolean useParentSource)
126 {
127 m_mgr = mgr;
128 m_id = id;
129 m_useParentSource = useParentSource;
130 initialize(attributes, resSources, libSources);
131 }
132
133 /**
134 * <p>
135 * Returns the identifier of the module.
136 * </p>
137 * @return the identifier of the module.
138 **/
139 public String getId()
140 {
141 return m_id;
142 }
143
144 /**
145 * <p>
146 * Returns the attribute set associated with this module. Attributes
147 * are represented as an array of <tt>Object</tt> arrays, i.e.,
148 * <tt>Object[][]</tt>. Each element in the attribute array is
149 * two-element <tt>Object</tt> array, where <tt>Module.KEY_IDX</tt>
150 * is the index to the attribute key and <tt>Module.VALUE_IDX</tt>
151 * is the index to the attribute value. The returned array is a
152 * copy and may be freely modified.
153 * </p>
154 * @return the attribute set associated with this module.
155 **/
156 public synchronized Object[][] getAttributes()
157 {
158 Set s = m_attributeMap.entrySet();
159 Object[][] attributes = new Object[s.size()][];
160 Iterator iter = s.iterator();
161 for (int i = 0; iter.hasNext(); i++)
162 {
163 Map.Entry entry = (Map.Entry) iter.next();
164 attributes[i] = new Object[] { entry.getKey(), entry.getValue() };
165 }
166 return attributes;
167 }
168
169 /**
170 * <p>
171 * Returns the attribute value associated with the specified key.
172 * </p>
173 * @param key the key of the attribute whose value is to be retrieved.
174 * @return the attribute's value or <tt>null</tt>.
175 **/
176 public synchronized Object getAttribute(String key)
177 {
178 return m_attributeMap.get(key);
179 }
180
181 /**
182 * <p>
183 * Sets the attribute value associated with the specified key. The
184 * attribute will be added if it does not currently exist.
185 * </p>
186 * @param key the key of the attribute whose value is to be set.
187 * @param value the new value to be associated with the attribute key.
188 **/
189 public synchronized void setAttribute(String key, Object value)
190 {
191 m_attributeMap.put(key, value);
192 }
193
194 /**
195 * <p>
196 * Returns the array of <tt>ResourceSource</tt>s associated with
197 * the module. The returned array is not a copy and therefore should
198 * not be modified.
199 * </p>
200 * @return the array of <tt>ResourceSource</tt>s associated with
201 * the module.
Richard S. Hall5a031592005-08-19 19:53:58 +0000202 * @see org.apache.felix.moduleloader.ResourceSource
Richard S. Hall930fecc2005-08-16 18:33:34 +0000203 **/
204 public ResourceSource[] getResourceSources()
205 {
206 return m_resSources;
207 }
208
209 /**
210 * <p>
211 * Returns the array of <tt>LibrarySource</tt>s associated with
212 * the module. The returned array is not a copy and therefore should
213 * not be modified.
214 * </p>
215 * @return the array of <tt>LibrarySource</tt>s associated with
216 * the module.
Richard S. Hall5a031592005-08-19 19:53:58 +0000217 * @see org.apache.felix.moduleloader.LibrarySource
Richard S. Hall930fecc2005-08-16 18:33:34 +0000218 **/
219 public LibrarySource[] getLibrarySources()
220 {
221 return m_libSources;
222 }
223
224 /**
225 * <p>
226 * Returns the <tt>ModuleClassLoader</tt> associated with this module.
227 * If a security manager is installed, then this method uses a privileged
228 * action to avoid a security exception being thrown to the caller.
229 * </p>
230 * @return the <tt>ModuleClassLoader</tt> associated with this module.
Richard S. Hall5a031592005-08-19 19:53:58 +0000231 * @see org.apache.felix.moduleloader.ModuleClassLoader
Richard S. Hall930fecc2005-08-16 18:33:34 +0000232 **/
233 public synchronized ModuleClassLoader getClassLoader()
234 {
235 if (m_loader == null)
236 {
237 if (System.getSecurityManager() != null)
238 {
239 m_loader = (ModuleClassLoader) AccessController.doPrivileged(
240 new GetClassLoaderPrivileged(m_mgr, this, m_useParentSource));
241 }
242 else
243 {
244 m_loader = new ModuleClassLoader(m_mgr, this, m_useParentSource);
245 }
246 }
247
248 return m_loader;
249 }
250
251 /**
252 * <p>
253 * Returns the module's identifier.
254 * </p>
255 * @return the module's identifier.
256 **/
257 public String toString()
258 {
259 return m_id;
260 }
261
262 /**
263 * <p>
264 * Resets the module by throwing away its associated class loader and
265 * re-initializing its attributes, resource sources, and library sources
266 * with the specified values.
267 * </p>
268 * @param attributes the new attributes to be associated with the module.
269 * @param resSources the new resource sources to be associated with the module.
270 * @param libSources the new library sources to be associated with the module.
Richard S. Hall5a031592005-08-19 19:53:58 +0000271 * @see org.apache.felix.moduleloader.ResourceSource
272 * @see org.apache.felix.moduleloader.LibrarySource
Richard S. Hall930fecc2005-08-16 18:33:34 +0000273 **/
274 protected synchronized void reset(
275 Object[][] attributes, ResourceSource[] resSources,
276 LibrarySource[] libSources)
277 {
278 // Throw away class loader.
279 m_loader = null;
280 // Clear attribute map.
281 m_attributeMap.clear();
282 // Close all sources.
283 dispose();
284 // Re-initialize.
285 initialize(attributes, resSources, libSources);
286 }
287
288 /**
289 * <p>
290 * Disposes the module by closing all resource and library sources.
291 * </p>
292 **/
293 protected synchronized void dispose()
294 {
295 // Close sources.
296 for (int i = 0; (m_resSources != null) && (i < m_resSources.length); i++)
297 {
298 m_resSources[i].close();
299 }
300 for (int i = 0; (m_libSources != null) && (i < m_libSources.length); i++)
301 {
302 m_libSources[i].close();
303 }
304 }
305
306 /**
307 * <p>
308 * Initializes the module by copying the specified attribute array into
309 * a map and opening all resource and library sources.
310 * </p>
311 * @param attributes the attributes to be put into a map.
312 * @param resSources the resource sources to be opened.
313 * @param libSources the library sources to be opened.
Richard S. Hall5a031592005-08-19 19:53:58 +0000314 * @see org.apache.felix.moduleloader.ResourceSource
315 * @see org.apache.felix.moduleloader.LibrarySource
Richard S. Hall930fecc2005-08-16 18:33:34 +0000316 **/
317 private void initialize(
318 Object[][] attributes, ResourceSource[] resSources, LibrarySource[] libSources)
319 {
320 for (int i = 0; (attributes != null) && (i < attributes.length); i++)
321 {
322 m_attributeMap.put(attributes[i][KEY_IDX], attributes[i][VALUE_IDX]);
323 }
324
325 m_resSources = resSources;
326 m_libSources = libSources;
327
328 // Open sources.
329 for (int i = 0; (m_resSources != null) && (i < m_resSources.length); i++)
330 {
331 m_resSources[i].open();
332 }
333 for (int i = 0; (m_libSources != null) && (i < m_libSources.length); i++)
334 {
335 m_libSources[i].open();
336 }
337 }
338
339 private static class GetClassLoaderPrivileged implements PrivilegedAction
340 {
341 private ModuleManager m_mgr = null;
342 private Module m_module = null;
343 private boolean m_useParentSource = false;
344
345 public GetClassLoaderPrivileged(ModuleManager mgr, Module module, boolean useParentSource)
346 {
347 m_mgr = mgr;
348 m_module = module;
349 m_useParentSource = useParentSource;
350 }
351
352 public Object run()
353 {
354 return new ModuleClassLoader(m_mgr, m_module, m_useParentSource);
355 }
356 }
357}