Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 1 | /* |
| 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 17 | package org.apache.felix.moduleloader; |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 18 | |
| 19 | import java.security.AccessController; |
| 20 | import java.security.PrivilegedAction; |
| 21 | import 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 72 | * @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. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 76 | **/ |
| 77 | public 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 118 | * @see org.apache.felix.moduleloader.ModuleManager |
| 119 | * @see org.apache.felix.moduleloader.ResourceSource |
| 120 | * @see org.apache.felix.moduleloader.LibrarySource |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 121 | **/ |
| 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 202 | * @see org.apache.felix.moduleloader.ResourceSource |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 203 | **/ |
| 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 217 | * @see org.apache.felix.moduleloader.LibrarySource |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 218 | **/ |
| 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 231 | * @see org.apache.felix.moduleloader.ModuleClassLoader |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 232 | **/ |
| 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 271 | * @see org.apache.felix.moduleloader.ResourceSource |
| 272 | * @see org.apache.felix.moduleloader.LibrarySource |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 273 | **/ |
| 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. Hall | 5a03159 | 2005-08-19 19:53:58 +0000 | [diff] [blame] | 314 | * @see org.apache.felix.moduleloader.ResourceSource |
| 315 | * @see org.apache.felix.moduleloader.LibrarySource |
Richard S. Hall | 930fecc | 2005-08-16 18:33:34 +0000 | [diff] [blame] | 316 | **/ |
| 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 | } |