You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ri...@apache.org on 2005/08/16 20:34:41 UTC
svn commit: r233031 [14/21] - in /incubator/oscar/trunk: ./ etc/ lib/ src/
src/org/ src/org/apache/ src/org/apache/osgi/ src/org/apache/osgi/bundle/
src/org/apache/osgi/bundle/bundlerepository/
src/org/apache/osgi/bundle/bundlerepository/kxmlsax/ src/o...
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleClassLoader.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleClassLoader.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleClassLoader.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleClassLoader.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.Enumeration;
+import java.util.Vector;
+
+/**
+ * <p>
+ * Each module that is managed by a <tt>ModuleManager</tt> has a
+ * <tt>ModuleClassLoader</tt> associated with it. The <tt>ModuleClassLoader</tt>
+ * is responsible for loading all classes, resources, and native libraries
+ * for its module. The <tt>ModuleClassLoader</tt> of a module
+ * is accessed using the <tt>Module.getClassLoader()</tt> method. The
+ * <tt>ModuleClassLoader</tt> uses its module's
+ * <a href="ResourceSource.html"><tt>ResourceSource</tt></a>s
+ * and <a href="LibrarySource.html"><tt>LibrarySource</tt></a>s
+ * to perform its function.
+ * </p>
+ * <p>
+ * When loading a class or resource, the <tt>ModuleClassLoader</tt> does
+ * not immediately search its module's <tt>ResourceSource</tt>s, instead
+ * it first delegates the request to the
+ * <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a> of the
+ * <tt>ModuleManager</tt>; this allows applications to inject specific
+ * class/resource loading policies. When the <tt>ModuleClassLoader</tt> delegates
+ * to the search policy, the search policy uses application-specific behavior
+ * to typically service the request from the <tt>ResourceSource</tt>s of
+ * other modules. If the search policy returns a result, then this result is
+ * returned immediately by the <tt>ModuleClassLoader</tt>; otherwise, it searches
+ * the <tt>ResourceSource</tt>s its module in an attempt to satisfy the
+ * original request.
+ * </p>
+ * <p>
+ * <b><i>Important:</i></b> The search policy <i>searches</i> modules in
+ * some application-specific manner in order to find a class or resource.
+ * This <i>search</i> is instigated, either directly or indirectly, by calls
+ * to <tt>ModuleClassLoader.loadClass()</tt> and <tt>ModuleClassLoader.getResource()</tt>,
+ * respectively. In order for the search policy to load a class or resource,
+ * it must <b>not</b> use <tt>ModuleClassLoader.loadClass()</tt> or
+ * <tt>ModuleClassLoader.getResource()</tt> again, because this would result
+ * in an infinite loop. Instead, the <tt>ModuleClassLoader</tt> offers the
+ * the methods <tt>ModuleClassLoader.loadClassFromModule()</tt> and
+ * <tt>ModuleClassLoader.getResourceFromModule()</tt> to search a given module
+ * and to avoid an infinite loop. As an example, consider the following
+ * snippet of code that implements an "exhaustive" search policy:
+ * </p>
+ * <pre>
+ * ...
+ * public Class findClass(Module module, String name)
+ * {
+ * Module[] modules = m_mgr.getModules();
+ * for (int i = 0; i < modules.length; i++)
+ * {
+ * try {
+ * Class clazz = modules[i].getClassLoader().loadClassFromModule(name);
+ * if (clazz != null)
+ * {
+ * return clazz;
+ * }
+ * } catch (Throwable th) {
+ * }
+ * }
+ *
+ * return null;
+ * }
+ * ...
+ * </pre>
+ * <p>
+ * In the above code, the search policy "exhaustively" searches every module in the
+ * <tt>ModuleManager</tt> to find the requested resource. Note that this policy
+ * will also search the module that originated the request, which is not totally
+ * necessary since returning <tt>null</tt> will cause the <tt>ModuleClassLoader</tt>
+ * to search the originating module's <tt>ResourceSource</tt>s.
+ * </p>
+**/
+public class ModuleClassLoader extends SecureClassLoader
+{
+ private ModuleManager m_mgr = null;
+ private Module m_module = null;
+ private boolean m_useParentSource = false;
+
+ /**
+ * <p>
+ * Constructs an instance using the specified <tt>ModuleManager</tt>, for
+ * the specified <tt>Module</tt>. This constructor is protected so that
+ * it cannot be created publicly.
+ * </p>
+ * @param mgr the <tt>ModuleManager</tt> of the <tt>Module</tt>.
+ * @param module the <tt>Module</tt> instance associated with the class loader.
+ **/
+ protected ModuleClassLoader(ModuleManager mgr, Module module, boolean useParentSource)
+ {
+ super(ModuleClassLoader.class.getClassLoader());
+ m_mgr = mgr;
+ m_module = module;
+ m_useParentSource = useParentSource;
+ }
+
+ /**
+ * <p>
+ * This method is nearly an exact copy of the ClassLoader.loadClass()
+ * method. The main difference is that it delegates to its associated
+ * <tt>ModuleManager</tt>'s search policy before calling the
+ * <tt>ClassLoader.findClass()</tt> method. Additionally, the synchronized
+ * modifier was removed from the superclass method; this change was necessary
+ * because ClassLoader class assumes a tree of class loaders, but the class
+ * loading structure in the <tt>ModuleManager</tt> might actually be a graph
+ * of class loaders; thus, it was necessary to loosen the concurrency locking
+ * to allow for cycles.
+ * </p>
+ * @param name the class to be loaded.
+ * @param resolve flag indicating whether the class should be resolved or not.
+ * @return the loaded class.
+ * @throws java.lang.ClassNotFoundException if the class could not be loaded.
+ **/
+ protected Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException
+ {
+ // Make sure the class was not already loaded.
+ Class c = findLoadedClass(name);
+ // Ask the search policy for the clas before consulting the module.
+ c = m_mgr.getSearchPolicy().findClassBeforeModule(getParent(), m_module, name);
+ // If the search policy didn't find it, then consult the module.
+ if (c == null)
+ {
+ c = findClass(name);
+ }
+ // If the module didn't find it, then consult the search policy
+ // one more time.
+ if (c == null)
+ {
+ c = m_mgr.getSearchPolicy().findClassAfterModule(getParent(), m_module, name);
+ }
+ // If still not found, then throw an exception.
+ if (c == null)
+ {
+ throw new ClassNotFoundException(name);
+ }
+ // Otherwise resolve the class.
+ if (resolve)
+ {
+ resolveClass(c);
+ }
+ return c;
+ }
+
+ /**
+ * <p>
+ * This method overriden from from <tt>ClassLoader</tt>.
+ * It is implemented such that it loads classes from the set of
+ * <tt>ResourceSource</tt>s from its associated module.
+ * </p>
+ * @param name the name of the resource to load.
+ * @return the loaded <tt>Class</tt> object.
+ * @throws java.lang.ClassNotFoundException if the class could not be loaded.
+ **/
+ protected Class findClass(String name) throws ClassNotFoundException
+ {
+ Class clazz = findLoadedClass(name);
+
+ // If the parent is used as a source, try to
+ // load the class from it.
+ // TODO: This is really a hack and should be generalized somehow.
+ if (m_useParentSource)
+ {
+ clazz = (getParent() == null) ? null : getParent().loadClass(name);
+ }
+
+ // Otherwise search for class in resource sources.
+ if (clazz == null)
+ {
+ String actual = name.replace('.', '/') + ".class";
+ ResourceSource[] sources = m_module.getResourceSources();
+ for (int i = 0;
+ (clazz == null) && (sources != null) && (i < sources.length);
+ i++)
+ {
+ byte[] bytes = sources[i].getBytes(actual);
+ if (bytes != null)
+ {
+ // We need to try to define a Package object for the class
+ // before we call defineClass(). Get the package name and
+ // see if we have already created the package.
+ String pkgName = Util.getClassPackage(name);
+ if (pkgName.length() > 0)
+ {
+ if (getPackage(pkgName) == null)
+ {
+ Object[] params =
+ m_mgr.getSearchPolicy().definePackage(m_module, pkgName);
+ if (params != null)
+ {
+ definePackage(
+ pkgName,
+ (String) params[0],
+ (String) params[1],
+ (String) params[2],
+ (String) params[3],
+ (String) params[4],
+ (String) params[5],
+ null);
+ }
+ }
+ }
+
+ // Get the code source URL for this class. For concurrency
+ // purposes, we are performing this call outside of the
+ // synchronized block below since we call out to application
+ // code, which might in turn need to call back into the
+ // module loader code. Because of this, it is better to
+ // not be holding any locks before making the call.
+ URL url = m_mgr.getURLPolicy().createCodeSourceURL(
+ m_mgr, m_module);
+
+ // If we have a valid code source URL, then use it to
+ // define the class for security purposes, otherwise
+ // define the class without a code source.
+ if (url != null)
+ {
+ CodeSource cs = new CodeSource(url, (Certificate[]) null);
+ clazz = defineClass(name, bytes, 0, bytes.length, cs);
+ }
+ else
+ {
+ clazz = defineClass(name, bytes, 0, bytes.length);
+ }
+ }
+ }
+ }
+
+ if (clazz != null)
+ {
+ return clazz;
+ }
+
+ return null;
+ }
+
+ /**
+ * <p>
+ * This method is used by <tt>SearchPolicy</tt> instances when they want
+ * to load a class from a module. The search policy is initially invoked when
+ * <tt>ModuleClassLoader.loadClass()</tt> delegates a class loading
+ * request to it. In general, the ultimate goal of the search policy is to
+ * return a class from another module if possible. Unfortunately, if a search
+ * policy tries to directly load a class from another module's class loader, an
+ * infinite loop will result because the module's class loader will delegate the
+ * request back to the search policy. To avoid this situation, search policies
+ * must use this method when trying to load a class from a module.
+ * </p>
+ * @param name the name of the class to load.
+ * @return the loaded class or <tt>null</tt>.
+ **/
+ public Class loadClassFromModule(String name)
+ {
+ try
+ {
+ return findClass(name);
+ } catch (Throwable th) {
+ // Not much we can do.
+// TODO: Do something with this error message.
+// System.err.println("ModuleClassLoader: " + th.getMessage());
+ }
+ return null;
+ }
+
+ /**
+ * <p>
+ * This method is nearly an exact copy of the ClassLoader.getResource()
+ * method. The main difference is that it delegates to its associated
+ * <tt>ModuleManager</tt>'s search policy before calling the
+ * <tt>ClassLoader.findResource()</tt> method.
+ * </p>
+ * @param name the class to be loaded.
+ * @return a URL to the resource or <tt>null</tt> if the resource was not found.
+ **/
+ public URL getResource(String name)
+ {
+ URL url = null;
+
+ // Ask the search policy for the resource.
+ if (m_mgr.getSearchPolicy() != null)
+ {
+ try
+ {
+ url = m_mgr.getSearchPolicy().findResource(getParent(), m_module, name);
+ }
+ catch (ResourceNotFoundException ex)
+ {
+ // We return null here because if SearchPolicy.findResource()
+ // throws an exception we interpret that to mean that the
+ // search should be stopped.
+ return null;
+ }
+ }
+
+ // If not found, then search locally.
+ if (url == null)
+ {
+ url = findResource(name);
+ }
+
+ return url;
+ }
+
+ /**
+ * <p>
+ * This method overriden from from <tt>ClassLoader</tt>.
+ * It is implemented such that it loads resources from the set of
+ * <tt>ResourceSource</tt>s from its associated module.
+ * </p>
+ * @param name the name of the resource to load.
+ * @return the <tt>URL</tt> associated with the resource or <tt>null</tt>.
+ **/
+ protected URL findResource(String name)
+ {
+ URL url = null;
+
+ // If the parent is used as a source, try to
+ // load the class from it.
+ if (m_useParentSource)
+ {
+ url = (getParent() == null) ? null : getParent().getResource(name);
+ }
+
+ // Try to load the resource from the module's resource
+ // sources.
+ if (url == null)
+ {
+ // Remove leading slash, if present.
+ if (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ ResourceSource[] sources = m_module.getResourceSources();
+ for (int i = 0;
+ (url == null) && (sources != null) && (i < sources.length);
+ i++)
+ {
+ if (sources[i].hasResource(name))
+ {
+ url = m_mgr.getURLPolicy().createResourceURL(m_mgr, m_module, i, name);
+ }
+ }
+ }
+
+ return url;
+ }
+
+ /**
+ * <p>
+ * This method is used by <tt>SearchPolicy</tt> instances when they want
+ * to load a resource from a module. The search policy is initially invoked when
+ * <tt>ModuleClassLoader.loadClass()</tt> delegates a resource loading
+ * request to it. In general, the ultimate goal of the search policy is to
+ * return a resource from another module if possible. Unfortunately, if a search
+ * policy tries to directly load a resource from another module's class loader, an
+ * infinite loop will result because the module's class loader will delegate the
+ * request back to the search policy. To avoid this situation, search policies
+ * must use this method when trying to load a resource from a module.
+ * </p>
+ * @param name the name of the resource to load.
+ * @return a URL to the resource or <tt>null</tt>.
+ **/
+ public URL getResourceFromModule(String name)
+ {
+ try
+ {
+ return findResource(name);
+ }
+ catch (Throwable th)
+ {
+ // Ignore and just return null.
+ }
+ return null;
+ }
+
+ protected Enumeration findResources(String name)
+ {
+ Vector v = new Vector();
+ // If the parent is used as a source, try to
+ // load the class from it.
+ if (m_useParentSource)
+ {
+ try
+ {
+ Enumeration e = (getParent() == null)
+ ? null : getParent().getResources(name);
+ while ((e != null) && e.hasMoreElements())
+ {
+ v.addElement(e.nextElement());
+ }
+ }
+ catch (IOException ex)
+ {
+ // What can we do?
+ }
+ }
+
+ // Remove leading slash, if present.
+ if (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ // Try to load the resource from the module's resource
+ // sources.
+
+ ResourceSource[] sources = m_module.getResourceSources();
+ for (int i = 0; (sources != null) && (i < sources.length); i++)
+ {
+ if (sources[i].hasResource(name))
+ {
+ v.addElement(m_mgr.getURLPolicy().createResourceURL(m_mgr, m_module, i, name));
+ }
+ }
+
+ return v.elements();
+ }
+
+ /**
+ * <p>
+ * This method overriden from from <tt>ClassLoader</tt>. It maps a library
+ * name to a library path by consulting the <tt>LibrarySource</tt>s of the
+ * class loader's module.
+ * </p>
+ * @param name the name of the library to find.
+ * @return the file system path of library or <tt>null</tt>
+ **/
+ protected String findLibrary(String name)
+ {
+ // Remove leading slash, if present.
+ if (name.startsWith("/"))
+ {
+ name = name.substring(1);
+ }
+
+ LibrarySource[] sources = m_module.getLibrarySources();
+ for (int i = 0;
+ (sources != null) && (i < sources.length);
+ i++)
+ {
+ String path = sources[i].getPath(name);
+ if (path != null)
+ {
+ return path;
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleEvent.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleEvent.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleEvent.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleEvent.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.util.EventObject;
+
+/**
+ * <p>
+ * This is an event class that is used by the <tt>ModuleManager</tt> to
+ * indicate when modules are added, removed, or reset. To receive these
+ * events, a <tt>ModuleListener</tt> must be added to the <tt>ModuleManager</tt>
+ * instance.
+ * </p>
+ * @see org.apache.osgi.moduleloader.ModuleManager
+ * @see org.apache.osgi.moduleloader.Module
+ * @see org.apache.osgi.moduleloader.ModuleListener
+**/
+public class ModuleEvent extends EventObject
+{
+ private Module m_module = null;
+
+ /**
+ * <p>
+ * Constructs a module event with the specified <tt>ModuleManager</tt>
+ * as the event source and the specified module as the subject of
+ * the event.
+ * </p>
+ * @param mgr the source of the event.
+ * @param module the subject of the event.
+ **/
+ public ModuleEvent(ModuleManager mgr, Module module)
+ {
+ super(mgr);
+ m_module = module;
+ }
+
+ /**
+ * <p>
+ * Returns the module that is the subject of the event.
+ * </p>
+ * @return the module that is the subject of the event.
+ **/
+ public Module getModule()
+ {
+ return m_module;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleListener.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleListener.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleListener.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleListener.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.util.EventListener;
+
+/**
+ * <p>
+ * This interface is an event listener for <tt>ModuleEvent</tt> events.
+ * To receive events, an implementation of this listener must be added
+ * to the <tt>ModuleManager</tt> instance.
+ * </p>
+ * @see org.apache.osgi.moduleloader.ModuleManager
+ * @see org.apache.osgi.moduleloader.ModuleEvent
+**/
+public interface ModuleListener extends EventListener
+{
+ /**
+ * <p>
+ * This method is called after a module is added to the
+ * <tt>ModuleManager</tt>.
+ * </p>
+ * @param event the event object containing the event details.
+ **/
+ public void moduleAdded(ModuleEvent event);
+
+ /**
+ * <p>
+ * This method is called after a module has been reset by the
+ * <tt>ModuleManager</tt>.
+ * </p>
+ * @param event the event object containing the event details.
+ **/
+ public void moduleReset(ModuleEvent event);
+
+ /**
+ * <p>
+ * This method is called after a module is remove from the
+ * <tt>ModuleManager</tt>.
+ * </p>
+ * @param event the event object containing the event details.
+ **/
+ public void moduleRemoved(ModuleEvent event);
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleManager.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleManager.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleManager.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleManager.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,524 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.util.*;
+
+/**
+ * <p>
+ * The <tt>ModuleManager</tt> class is the core facility for defining a
+ * re-usable, policy-driven class loader for applications that require
+ * flexible class loading mechanisms. The <tt>ModuleManager</tt> is not
+ * class loader itself, but it supports the concept of a
+ * <a href="Module.html"><tt>Module</tt></a>,
+ * which is a unit of organization for application classes and resources.
+ * The <tt>ModuleManager</tt> has only a handful of methods that allow
+ * an application to add, remove, reset, and query modules; the intent
+ * is to place as few assumptions in the <tt>ModuleManager</tt> as possible.
+ * </p>
+ * <p>
+ * The idea is simple, allow the application to map itself into modules
+ * however it sees fit and let the <tt>ModuleManager</tt> assume the
+ * responsibility of managing the modules and loading classes and resources
+ * from them as necessary via <a href="ModuleClassLoader.html"><tt>ModuleClassLoader</tt></a>s
+ * that are associated with each module. In order to achieve this goal, though, the
+ * <tt>ModuleManager</tt> must make at least one assumption on behalf of
+ * the application. This assumption is that the loading of classes and resources
+ * from the available modules must happen using a search algorithm
+ * that is particular to the application itself. As a result of this assumption,
+ * the <tt>ModuleManager</tt> requires that the application provide a concrete
+ * implementation of the <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a>
+ * interface.
+ * </p>
+ * <p>
+ * The search policy allows the <tt>ModuleLoader</tt> to let applications inject
+ * their own particular class loading policies, without dictating strict or
+ * constraining base assumptions. Of course, it is likely that many applications
+ * will use the same or very similar search policies. Because of this, another
+ * goal of the <tt>ModuleLoader</tt> approach is to foster a common library of
+ * search policies that applications are free to use or customize as they see
+ * fit. These common search policies are analagous to patterns, where each search
+ * policy is viewable as a <i>class loading pattern</i>. Some initial search
+ * policies included with the <tt>ModuleLoader</tt> are
+ * <a href="search/ExhaustiveSearchPolicy.html"><tt>ExhaustiveSearchPolicy</tt></a>,
+ * <a href="search/SelfContainedSearchPolicy.html"><tt>SelfContainedSearchPolicy</tt></a>, and
+ * <a href="search/ImportSearchPolicy.html"><tt>ImportSearchPolicy</tt></a>.
+ * </p>
+ * <p>
+ * Due to the fact that class loaders are tied to security and resource loading,
+ * the search policy alone is not sufficient for the <tt>ModuleLoader</tt> to
+ * perform its function. To fulfill these other purposes, the <tt>ModuleLoader</tt>
+ * introduces another policy interface, called the <a href="URLPolicy.html"><tt>URLPolicy</tt></a>.
+ * The <tt>URLPolicy</tt> allows the application to inject its particular policy
+ * for to purposes:
+ * </p>
+ * <ol>
+ * <li>Creating the <tt>URL</tt> associated with loading a resource, such as
+ * the <tt>URL</tt> returned from a call to <tt>Class.getResource()</tt>.
+ * </li>
+ * <li>Creating the <tt>URL</tt> that will be associated with a class's
+ * <tt>CodeSource</tt> when defining the class for purposes of security
+ * and assigning permissions.
+ * </li>
+ * </ol>
+ * <p>
+ * The <tt>ModuleLoader</tt> defines a default <tt>URLPolicy</tt>, called
+ * <a href="DefaultURLPolicy.html"><tt>DefaultURLPolicy</tt></a>, that provides
+ * a simple <tt>URLStreamHandler</tt> for accessing resources inside of modules
+ * and that returns <tt>null</tt> for the <tt>CodeSource</tt> <tt>URL</tt>.
+ * Applications only need to supply their own <tt>URLPolicy</tt> if the default
+ * one does not provide the appropriate behavior.
+ * </p>
+ * <p>
+ * It is possible for an application to create multiple instances of the
+ * <tt>ModuleManager</tt> within a single JVM, but it is not possible to
+ * share modules across multiple <tt>ModuleManager</tt>s. A given <tt>ModuleManager</tt>
+ * can only have one <tt>SelectionPolicy</tt> and one <tt>URLPolicy</tt>.
+ * </p>
+ * @see org.apache.osgi.moduleloader.Module
+ * @see org.apache.osgi.moduleloader.ModuleClassLoader
+ * @see org.apache.osgi.moduleloader.SearchPolicy
+ * @see org.apache.osgi.moduleloader.URLPolicy
+ * @see org.apache.osgi.moduleloader.DefaultURLPolicy
+**/
+public class ModuleManager
+{
+ private List m_moduleList = new ArrayList();
+ private Map m_moduleMap = new HashMap();
+ private SearchPolicy m_searchPolicy = null;
+ private URLPolicy m_urlPolicy = null;
+ private ModuleListener[] m_listeners = null;
+ private static final ModuleListener[] m_noListeners = new ModuleListener[0];
+
+ /**
+ * <p>
+ * Constructs a <tt>ModuleManager</tt> instance using the specified
+ * search policy and the default <tt>URL</tt> policy.
+ * </p>
+ * @param searchPolicy the search policy that the instance should use.
+ * @see org.apache.osgi.moduleloader.SearchPolicy
+ **/
+ public ModuleManager(SearchPolicy searchPolicy)
+ {
+ this(searchPolicy, null);
+ }
+
+ /**
+ * <p>
+ * Constructs a <tt>ModuleManager</tt> instance using the specified
+ * search policy and the specified <tt>URL</tt> policy.
+ * </p>
+ * @param searchPolicy the search policy that the instance should use.
+ * @param urlPolicy the <tt>URL</tt> policy that the instance should use.
+ * @see org.apache.osgi.moduleloader.SearchPolicy
+ * @see org.apache.osgi.moduleloader.URLPolicy
+ **/
+ public ModuleManager(SearchPolicy searchPolicy, URLPolicy urlPolicy)
+ {
+ m_listeners = m_noListeners;
+ m_searchPolicy = searchPolicy;
+ m_searchPolicy.setModuleManager(this);
+
+ if (urlPolicy == null)
+ {
+ m_urlPolicy = new DefaultURLPolicy();
+ }
+ else
+ {
+ m_urlPolicy = urlPolicy;
+ }
+ }
+
+ /**
+ * <p>
+ * Returns the <tt>URL</tt> policy used by this instance.
+ * </p>
+ * @return the <tt>URL</tt> policy used by this instance.
+ * @see org.apache.osgi.moduleloader.URLPolicy
+ **/
+ public URLPolicy getURLPolicy()
+ {
+ return m_urlPolicy;
+ }
+
+ /**
+ * <p>
+ * Returns the search policy used by this instance.
+ * </p>
+ * @return the search policy used by this instance.
+ * @see org.apache.osgi.moduleloader.SearchPolicy
+ **/
+ public SearchPolicy getSearchPolicy()
+ {
+ return m_searchPolicy;
+ }
+
+ /**
+ * <p>
+ * Returns an array of all modules being managed by the
+ * <tt>ModuleManager</tt> instance. The array contains a snapshot of
+ * all modules in the <tt>ModuleManager</tt> at the time when this
+ * method was called.
+ * </p>
+ * @return an array of all modules being managed by the <tt>ModuleManager</tt>
+ * instance.
+ * @see org.apache.osgi.moduleloader.Module
+ **/
+ public synchronized Module[] getModules()
+ {
+ Module[] modules = new Module[m_moduleList.size()];
+ return (Module[]) m_moduleList.toArray(modules);
+ }
+
+ /**
+ * <p>
+ * Returns a module associated with the specified identifier.
+ * </p>
+ * @param id the identifier for the module to be retrieved.
+ * @return the module associated with the identifier or <tt>null</tt>.
+ * @see org.apache.osgi.moduleloader.Module
+ **/
+ public synchronized Module getModule(String id)
+ {
+ return (Module) m_moduleMap.get(id);
+ }
+
+ /**
+ * <p>
+ * Adds a module to the module manager. The module will have the specified
+ * unique identifier, with the associated attributes, resource sources, and
+ * library sources. If the identifier is not unique, then an exception is
+ * thrown.
+ * </p>
+ * @param id the unique identifier of the new module.
+ * @param attributes an array of key-value attribute pairs to
+ * associate with the module.
+ * @param resSources an array of <tt>ResourceSource</tt>s to associate
+ * with the module.
+ * @param libSources an array of <tt>LibrarySource</tt>s to associate
+ * with the module.
+ * @return the newly created module.
+ * @throws java.lang.IllegalArgumentException if the module identifier
+ * is not unique.
+ * @see org.apache.osgi.moduleloader.Module
+ * @see org.apache.osgi.moduleloader.ResourceSource
+ * @see org.apache.osgi.moduleloader.LibrarySource
+ **/
+ public Module addModule(String id, Object[][] attributes,
+ ResourceSource[] resSources, LibrarySource[] libSources)
+ {
+ return addModule(id, attributes, resSources, libSources, false);
+ }
+
+ public Module addModule(String id, Object[][] attributes,
+ ResourceSource[] resSources, LibrarySource[] libSources,
+ boolean useParentSource)
+ {
+ Module module = null;
+
+ // Use a synchronized block instead of synchronizing the
+ // method, so we can fire our event outside of the block.
+ synchronized (this)
+ {
+ if (m_moduleMap.get(id) == null)
+ {
+ module = new Module(this, id, attributes, resSources, libSources, useParentSource);
+ m_moduleList.add(module);
+ m_moduleMap.put(id, module);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Module ID must be unique.");
+ }
+ }
+
+ // Fire event here instead of inside synchronized block.
+ fireModuleAdded(module);
+
+ return module;
+ }
+
+ /**
+ * <p>
+ * Resets a given module. In resetting a module, the module's associated
+ * class loader is thrown away; it is the application's responsibility to
+ * determine when and how that application code stops using classes (and
+ * subsequent instances) from the class loader of the reset module.
+ * This method allows the associated elements of the module (i.e.,
+ * attributes, resource sources, and library sources) to be changed also;
+ * if these elements have not changed then they simply need to be passed
+ * back in from the existing module. This method is useful in situations
+ * where the underlying module needs to be changed at run time, such as
+ * might be necessary if a module was updated.
+ * </p>
+ * <p>
+ * The same effect could be achieved by first removing and then re-adding
+ * a module, but with one subtle different. By removing and then re-adding
+ * a module, a new module is created and, thus, all existing references
+ * become invalid. By explicitly having this method, the <tt>ModuleManager</tt>
+ * maintains the integrity of the module reference, which is more intuitive
+ * in the case where an updated module is intended to be the same module,
+ * only updated.
+ * </p>
+ * @param module the module reset.
+ * @param attributes an array of key-value attribute pairs to
+ * associate with the module.
+ * @param resSources an array of <tt>ResourceSource</tt>s to associate
+ * with the module.
+ * @param libSources an array of <tt>LibrarySource</tt>s to associate
+ * with the module.
+ * @see org.apache.osgi.moduleloader.Module
+ * @see org.apache.osgi.moduleloader.ResourceSource
+ * @see org.apache.osgi.moduleloader.LibrarySource
+ **/
+ public void resetModule(
+ Module module, Object[][] attributes,
+ ResourceSource[] resSources, LibrarySource[] libSources)
+ {
+ // Use a synchronized block instead of synchronizing the
+ // method, so we can fire our event outside of the block.
+ synchronized (this)
+ {
+ module = (Module) m_moduleMap.get(module.getId());
+ if (module != null)
+ {
+ module.reset(attributes, resSources, libSources);
+ }
+ else
+ {
+ // Don't fire event.
+ return;
+ }
+ }
+
+ // Fire event here instead of inside synchronized block.
+ fireModuleReset(module);
+ }
+
+ /**
+ * <p>
+ * Removes the specified module from the <tt>ModuleManager</tt>. Removing
+ * a module only removed the module from the <tt>ModuleManager</tt>. It is
+ * the application's responsibility to determine when and how application code
+ * stop using classes (and subsequent instances) that were loaded from
+ * the class loader of the removed module.
+ * </p>
+ * @param module the module to remove.
+ **/
+ public void removeModule(Module module)
+ {
+ // Use a synchronized block instead of synchronizing the
+ // method, so we can fire our event outside of the block.
+ synchronized (this)
+ {
+ if (m_moduleMap.get(module.getId()) != null)
+ {
+ // Remove from data structures.
+ m_moduleList.remove(module);
+ m_moduleMap.remove(module.getId());
+
+ // Dispose of the module.
+ module.dispose();
+ }
+ else
+ {
+ // Don't fire event.
+ return;
+ }
+ }
+
+ // Fire event here instead of inside synchronized block.
+ fireModuleRemoved(module);
+ }
+
+ /**
+ * <p>
+ * Adds a listener to the <tt>ModuleManager</tt> to listen for
+ * module added, reset, and removed events.
+ * </p>
+ * @param l the <tt>ModuleListener</tt> to add.
+ **/
+ public void addModuleListener(ModuleListener l)
+ {
+ // Verify listener.
+ if (l == null)
+ {
+ throw new IllegalArgumentException("Listener is null");
+ }
+
+ // Use the m_noListeners object as a lock.
+ synchronized (m_noListeners)
+ {
+ // If we have no listeners, then just add the new listener.
+ if (m_listeners == m_noListeners)
+ {
+ m_listeners = new ModuleListener[] { l };
+ }
+ // Otherwise, we need to do some array copying.
+ // Notice, the old array is always valid, so if
+ // the dispatch thread is in the middle of a dispatch,
+ // then it has a reference to the old listener array
+ // and is not affected by the new value.
+ else
+ {
+ ModuleListener[] newList = new ModuleListener[m_listeners.length + 1];
+ System.arraycopy(m_listeners, 0, newList, 0, m_listeners.length);
+ newList[m_listeners.length] = l;
+ m_listeners = newList;
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Removes a listener from the <tt>ModuleManager</tt>.
+ * </p>
+ * @param l the <tt>ModuleListener</tt> to remove.
+ **/
+ public void removeModuleListener(ModuleListener l)
+ {
+ // Verify listener.
+ if (l == null)
+ {
+ throw new IllegalArgumentException("Listener is null");
+ }
+
+ // Use the m_noListeners object as a lock.
+ synchronized (m_noListeners)
+ {
+ // Try to find the instance in our list.
+ int idx = -1;
+ for (int i = 0; i < m_listeners.length; i++)
+ {
+ if (m_listeners[i].equals(l))
+ {
+ idx = i;
+ break;
+ }
+ }
+
+ // If we have the instance, then remove it.
+ if (idx >= 0)
+ {
+ // If this is the last listener, then point to empty list.
+ if (m_listeners.length == 1)
+ {
+ m_listeners = m_noListeners;
+ }
+ // Otherwise, we need to do some array copying.
+ // Notice, the old array is always valid, so if
+ // the dispatch thread is in the middle of a dispatch,
+ // then it has a reference to the old listener array
+ // and is not affected by the new value.
+ else
+ {
+ ModuleListener[] newList = new ModuleListener[m_listeners.length - 1];
+ System.arraycopy(m_listeners, 0, newList, 0, idx);
+ if (idx < newList.length)
+ {
+ System.arraycopy(m_listeners, idx + 1, newList, idx,
+ newList.length - idx);
+ }
+ m_listeners = newList;
+ }
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Fires an event indicating that the specified module was added
+ * to the <tt>ModuleManager</tt>.
+ * </p>
+ * @param module the module that was added.
+ **/
+ protected void fireModuleAdded(Module module)
+ {
+ // Event holder.
+ ModuleEvent event = null;
+
+ // Get a copy of the listener array, which is guaranteed
+ // to not be null.
+ ModuleListener[] listeners = m_listeners;
+
+ // Loop through listeners and fire events.
+ for (int i = 0; i < listeners.length; i++)
+ {
+ // Lazily create event.
+ if (event == null)
+ {
+ event = new ModuleEvent(this, module);
+ }
+ listeners[i].moduleAdded(event);
+ }
+ }
+
+ /**
+ * <p>
+ * Fires an event indicating that the specified module was reset.
+ * </p>
+ * @param module the module that was reset.
+ **/
+ protected void fireModuleReset(Module module)
+ {
+ // Event holder.
+ ModuleEvent event = null;
+
+ // Get a copy of the listener array, which is guaranteed
+ // to not be null.
+ ModuleListener[] listeners = m_listeners;
+
+ // Loop through listeners and fire events.
+ for (int i = 0; i < listeners.length; i++)
+ {
+ // Lazily create event.
+ if (event == null)
+ {
+ event = new ModuleEvent(this, module);
+ }
+ listeners[i].moduleReset(event);
+ }
+ }
+
+ /**
+ * <p>
+ * Fires an event indicating that the specified module was removed
+ * from the <tt>ModuleManager</tt>.
+ * </p>
+ * @param module the module that was removed.
+ **/
+ protected void fireModuleRemoved(Module module)
+ {
+ // Event holder.
+ ModuleEvent event = null;
+
+ // Get a copy of the listener array, which is guaranteed
+ // to not be null.
+ ModuleListener[] listeners = m_listeners;
+
+ // Loop through listeners and fire events.
+ for (int i = 0; i < listeners.length; i++)
+ {
+ // Lazily create event.
+ if (event == null)
+ {
+ event = new ModuleEvent(this, module);
+ }
+ listeners[i].moduleRemoved(event);
+ }
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLConnection.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLConnection.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLConnection.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLConnection.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.security.Permission;
+
+class ModuleURLConnection extends URLConnection
+{
+ private ModuleManager m_mgr = null;
+ private int m_contentLength;
+ private long m_contentTime;
+ private String m_contentType;
+ private InputStream m_is;
+
+ public ModuleURLConnection(ModuleManager mgr, URL url)
+ {
+ super(url);
+ m_mgr = mgr;
+ }
+
+ public void connect() throws IOException
+ {
+ if (!connected)
+ {
+ // The URL is constructed like this:
+ // module://<module-id>/<source-idx>/<resource-path>
+ Module module = m_mgr.getModule(url.getHost());
+ if (module == null)
+ {
+ throw new IOException("Unable to find bundle's module.");
+ }
+
+ String resource = url.getFile();
+ if (resource == null)
+ {
+ throw new IOException("Unable to find resource: " + url.toString());
+ }
+ if (resource.startsWith("/"))
+ {
+ resource = resource.substring(1);
+ }
+ int rsIdx = -1;
+ try
+ {
+ rsIdx = Integer.parseInt(resource.substring(0, resource.indexOf("/")));
+ }
+ catch (NumberFormatException ex)
+ {
+ new IOException("Error parsing resource index.");
+ }
+ resource = resource.substring(resource.indexOf("/") + 1);
+
+ // Get the resource bytes from the resource source.
+ byte[] bytes = null;
+ ResourceSource[] resSources = module.getResourceSources();
+ if ((resSources != null) && (rsIdx < resSources.length))
+ {
+ if (resSources[rsIdx].hasResource(resource))
+ {
+ bytes = resSources[rsIdx].getBytes(resource);
+ }
+ }
+
+ if (bytes == null)
+ {
+ throw new IOException("Unable to find resource: " + url.toString());
+ }
+
+ m_is = new ByteArrayInputStream(bytes);
+ m_contentLength = bytes.length;
+ m_contentTime = 0L; // TODO: Change this.
+ m_contentType = URLConnection.guessContentTypeFromName(resource);
+ connected = true;
+ }
+ }
+
+ public InputStream getInputStream()
+ throws IOException
+ {
+ if (!connected)
+ {
+ connect();
+ }
+ return m_is;
+ }
+
+ public int getContentLength()
+ {
+ if (!connected)
+ {
+ try {
+ connect();
+ } catch(IOException ex) {
+ return -1;
+ }
+ }
+ return m_contentLength;
+ }
+
+ public long getLastModified()
+ {
+ if (!connected)
+ {
+ try {
+ connect();
+ } catch(IOException ex) {
+ return 0;
+ }
+ }
+ if (m_contentTime != -1L)
+ {
+ return m_contentTime;
+ }
+ else
+ {
+ return 0L;
+ }
+ }
+
+ public String getContentType()
+ {
+ if (!connected)
+ {
+ try {
+ connect();
+ } catch(IOException ex) {
+ return null;
+ }
+ }
+ return m_contentType;
+ }
+
+ public Permission getPermission()
+ {
+ // TODO: This should probably return a FilePermission
+ // to access the bundle JAR file, but we don't have the
+ // necessary information here to construct the absolute
+ // path of the JAR file...so it would take some
+ // re-arranging to get this to work.
+ return null;
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLStreamHandler.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLStreamHandler.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLStreamHandler.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ModuleURLStreamHandler.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.io.IOException;
+import java.net.*;
+
+class ModuleURLStreamHandler extends URLStreamHandler
+{
+ private ModuleManager m_mgr = null;
+
+ public ModuleURLStreamHandler(ModuleManager mgr)
+ {
+ m_mgr = mgr;
+ }
+
+ protected URLConnection openConnection(URL url) throws IOException
+ {
+ return new ModuleURLConnection(m_mgr, url);
+ }
+}
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceNotFoundException.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceNotFoundException.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceNotFoundException.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceNotFoundException.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+public class ResourceNotFoundException extends Exception
+{
+ public ResourceNotFoundException(String msg)
+ {
+ super(msg);
+ }
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceSource.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceSource.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceSource.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/ResourceSource.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+/**
+ * <p>
+ * This interface represents a source for obtaining resources for a
+ * given module via the module's class loader. A resource source is used
+ * for retrieving both classes and resources; at this level, classes are
+ * treated in an identical manner as an ordinary resource. Resource sources
+ * are completely arbitrary and implementations may load resources from a JAR
+ * file, the network, a database, or anywhere.
+ * </p>
+ * <p>
+ * All resource sources are initialized before first usage via a call
+ * to the <a href="#open()"><tt>ResourceSource.open()</tt></a> method and
+ * are also deinitialized via a call to
+ * <a href="#open()"><tt>ResourceSource.close()</tt></a>. Resource sources
+ * should be implemented such that they can be opened, closed, and then
+ * re-opened.
+ * </p>
+ * @see org.apache.osgi.moduleloader.Module
+ * @see org.apache.osgi.moduleloader.ModuleClassLoader
+**/
+public interface ResourceSource
+{
+ /**
+ * <p>
+ * This method initializes the resource source. It is called when
+ * the associated module is added to the <tt>ModuleManager</tt>. It
+ * is acceptable for implementations to ignore duplicate calls to this
+ * method if the resource source is already opened.
+ * </p>
+ **/
+ public void open();
+
+ /**
+ * <p>
+ * This method de-initializes the resource source. It is called when
+ * the associated module is removed from the <tt>ModuleManager</tt> or
+ * when the module is reset by the <tt>ModuleManager</tt>.
+ * </p>
+ **/
+ public void close();
+
+ /**
+ * <p>
+ * This method returns a boolean indicating whether the resource source
+ * contains the specified resource.
+ * </p>
+ * @param name the name of the resource whose existence is being checked.
+ * @param <tt>true</tt> if the resource source has the resource, <tt>false</tt>
+ * otherwise.
+ * @throws java.lang.IllegalStateException if the resource source has not
+ * been opened.
+ **/
+ public boolean hasResource(String name) throws IllegalStateException;
+
+ /**
+ * <p>
+ * This method returns a byte array of the specified resource's contents.
+ * </p>
+ * @param name the name of the resource to retrieve.
+ * @param a byte array of the resource's contents or <tt>null</tt>
+ * if the resource was not found.
+ * @throws java.lang.IllegalStateException if the resource source has not
+ * been opened.
+ **/
+ public byte[] getBytes(String name) throws IllegalStateException;
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/SearchPolicy.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/SearchPolicy.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/SearchPolicy.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/SearchPolicy.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.net.URL;
+
+/**
+ * <p>
+ * This interface represents a policy to define the most basic behavior
+ * of how classes, resources, and native libraries within a specific instance
+ * of <tt>ModuleManager</tt> are found. A <tt>ModuleManager</tt> manages a set of
+ * <tt>Module</tt>s, each of which is a potential source of classes, resources,
+ * and native libraries. The search policy makes it possible to consult these
+ * sources without hard-coding assumptions about application behavior
+ * or structure. Applicaitons inject their own specific class loading policy
+ * by creating a custom search policy or by selecting a pre-existing search
+ * policy that matches their needs.
+ * </p>
+ * <p>
+ * The search policy is used by <tt>ModuleClassLoader</tt>, of which, there
+ * is one per <tt>Module</tt> within a given <tt>ModuleManager</tt> instance.
+ * The search policy is consulted by the <tt>ModuleClassLoader</tt> whenever
+ * there is a request for a class, resource, or native library. The search
+ * policy will generally search other modules in an application-specific
+ * way in order to find the requested item; for example, an application may
+ * use a policy where module's may import from one another. If the search
+ * policy provides an answer, then the <tt>ModuleClassLoader</tt> will use
+ * this to answer the originating request.
+ * </p>
+ * <p>
+ * <b><i>Important:</i></b> The search policy <i>searches</i> modules in
+ * some application-specific manner in order to find a class or resource.
+ * This <i>search</i> is instigated, either directly or indirectly, by calls
+ * to <tt>ModuleClassLoader.loadClass()</tt> and <tt>ModuleClassLoader.getResource()</tt>,
+ * respectively. In order for the search policy to load a class or resource,
+ * it must <b>not</b> use <tt>ModuleClassLoader.loadClass()</tt> or
+ * <tt>ModuleClassLoader.getResource()</tt> again, because this would result
+ * in an infinite loop. Instead, the <tt>ModuleClassLoader</tt> offers the
+ * the methods <tt>ModuleClassLoader.loadClassFromModule()</tt> and
+ * <tt>ModuleClassLoader.getResourceFromModule()</tt> to search a given module
+ * and to avoid an infinite loop.
+ * </p>
+ * <pre>
+ * ...
+ * public Class findClass(Module module, String name)
+ * {
+ * Module[] modules = m_mgr.getModules();
+ * for (int i = 0; i < modules.length; i++)
+ * {
+ * try {
+ * Class clazz = modules[i].getClassLoader().loadClassFromModule(name);
+ * if (clazz != null)
+ * {
+ * return clazz;
+ * }
+ * } catch (Throwable th) {
+ * }
+ * }
+ *
+ * return null;
+ * }
+ * ...
+ * </pre>
+ * <p>
+ * In the above code, the search policy "exhaustively" searches every module in the
+ * <tt>ModuleManager</tt> to find the requested resource. Note that this policy
+ * will also search the module that originated the request, which is not totally
+ * necessary since returning <tt>null</tt> will cause the <tt>ModuleClassLoader</tt>
+ * to search the originating module's <tt>ResourceSource</tt>s.
+ * </p>
+**/
+public interface SearchPolicy
+{
+ /**
+ * <p>
+ * This method is called once by the <tt>ModuleManager</tt> to
+ * give the search policy instance a reference to its associated
+ * module manager. This method should be implemented such that
+ * it cannot be called twice; calling this method a second time
+ * should produce an illegal state exception.
+ * </p>
+ * @param mgr the module manager associated with this search policy.
+ * @throws java.lang.IllegalStateException if the method is called
+ * more than once.
+ **/
+ public void setModuleManager(ModuleManager mgr)
+ throws IllegalStateException;
+
+ /**
+ * <p>
+ * The <tt>ModuleClassLoader</tt> calls this method before performing
+ * the call to <tt>ClassLoader.defineClass()</tt> to give the search policy
+ * an opportunity to define the <tt>Package</tt> object for the specified
+ * package. The method should return an array of <tt>String</tt> values for
+ * each of the following: specTitle, specVersion, specVendor, implTitle,
+ * implVersion, and implVendor. See <tt>ClassLoader.definePackage()</tt>
+ * for more details. The returned array may contain <tt>null</tt>s, but
+ * the return array must have six elements.
+ * </p>
+ * @param module the module requesting a class from the package.
+ * @param pkgName the package name of the class being requested.
+ * @return an array containing values for creating the <tt>Package</tt>
+ * object for the specified package.
+ **/
+ public Object[] definePackage(Module module, String pkgName);
+
+ /**
+ * <p>
+ * When a module instigates a class load operation, this method is called
+ * to find the desired class for the instigating module. This method is
+ * called <b>before</b> searching the module's resource sources for the class.
+ * How the class is found is dependent upon the search policy implementation.
+ * </p>
+ * <p>
+ * This method may return <tt>null</tt> or throw an exception if the
+ * specified class is not found. Whether a specific search policy
+ * implementation should do one or the other depends on the details
+ * of the specific search policy. The <tt>ModuleClassLoader</tt>
+ * first delegates to this method, then to the local resources
+ * sources of the module, and then finally to then the
+ * <tt>SearchPolicy.findClassAfterModule()</tt> method. If this method
+ * returns null, then the search for the class will continue to these
+ * latter two steps. On the other hand, if this method returns a class
+ * or throws an exception, then the latter two steps will not be searched.
+ * </p>
+ * <p>
+ * <b>Important:</b> If the implementation of this method delegates
+ * the class loading to a <tt>ModuleClassLoader</tt> of another module,
+ * then it should <b>not</b> use the method <tt>ModuleClassLoader.loadClass()</tt>
+ * to load the class; it should use <tt>ModuleClassLoader.loadClassFromModule()</tt>
+ * instead. This is necessary to eliminate an infinite loop that would
+ * occur otherwise. Also, with respect to the <tt>ModuleLoader</tt> framework,
+ * this method will only be called by a single thread at a time and is only
+ * intended to be called by <tt>ModuleClassLoader.loadClass()</tt>.
+ * </p>
+ * @param parent the parent class loader of the delegating class loader.
+ * @param module the target module that is loading the class.
+ * @param name the name of the class being loaded.
+ * @return the class if found, <tt>null</tt> otherwise.
+ * @throws java.lang.ClassNotFoundException if the class could not be
+ * found and the entire search operation should fail.
+ **/
+ public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
+ throws ClassNotFoundException;
+
+ /**
+ * <p>
+ * When a module instigates a class load operation, this method is called
+ * to find the desired class for the instigating module. This method is
+ * called <b>after</b> searching the module's resource sources for the class.
+ * How the class is found is dependent upon the search policy implementation.
+ * </p>
+ * <p>
+ * The <tt>ModuleClassLoader</tt> first delegates to the
+ * <tt>SearchPolicy.findClassBeforeModule() method, then to the local
+ * resources sources of the module, and then finally to this method.
+ * This method is the last attempt to find the class and if it fails
+ * (by either return <tt>null</tt> or throwing an exception), then the
+ * result of the entire class load will fail.
+ * </p>
+ * <p>
+ * <b>Important:</b> If the implementation of this method delegates
+ * the class loading to a <tt>ModuleClassLoader</tt> of another module,
+ * then it should <b>not</b> use the method <tt>ModuleClassLoader.loadClass()</tt>
+ * to load the class; it should use <tt>ModuleClassLoader.loadClassFromModule()</tt>
+ * instead. This is necessary to eliminate an infinite loop that would
+ * occur otherwise. Also, with respect to the <tt>ModuleLoader</tt> framework,
+ * this method will only be called by a single thread at a time and is only
+ * intended to be called by <tt>ModuleClassLoader.loadClass()</tt>.
+ * </p>
+ * @param parent the parent class loader of the delegating class loader.
+ * @param module the target module that is loading the class.
+ * @param name the name of the class being loaded.
+ * @return the class if found, <tt>null</tt> otherwise.
+ * @throws java.lang.ClassNotFoundException if the class could not be
+ * found and the entire search operation should fail.
+ **/
+ public Class findClassAfterModule(ClassLoader parent, Module module, String name)
+ throws ClassNotFoundException;
+
+ /**
+ * <p>
+ * This method tries to find the specified resource for the specified
+ * module. How the resource is found or whether it is actually retrieved
+ * from the specified module is dependent upon the implementation. The
+ * default <tt>ModuleClassLoader.getResource()</tt> method does not do
+ * any searching on its own.
+ * </p>
+ * <p>
+ * This method may return <tt>null</tt> or throw an exception if the
+ * specified resource is not found. Whether a specific search policy
+ * implementation should do one or the other depends on the details
+ * of the specific search policy. The <tt>ModuleClassLoader</tt>
+ * first delegates to this method and then to the local resource
+ * sources of the module. If this method returns null, then the local
+ * resource sources will be searched. On the other hand, if this method
+ * throws an exception, then the local resource sources will not be
+ * searched.
+ * </p>
+ * <p>
+ * <b>Important:</b> If the implementation of this method delegates
+ * the resource loading to a <tt>ModuleClassLoader</tt> of another module,
+ * then it should not use the method <tt>ModuleClassLoader.getResource()</tt>
+ * to get the resource; it should use <tt>ModuleClassLoader.getResourceFromModule()</tt>
+ * instead. This is necessary to eliminate an infinite loop that would
+ * occur otherwise. Also, with respect to the <tt>ModuleLoader</tt> framework,
+ * this method will only be called by a single thread at a time and is not
+ * intended to be called directly.
+ * </p>
+ * @param parent the parent class loader of the delegating class loader.
+ * @param module the target module that is loading the resource.
+ * @param name the name of the resource being loaded.
+ * @return a <tt>URL</tt> to the resource if found, <tt>null</tt> otherwise.
+ * @throws org.apache.osgi.moduleloader.ResourceNotFoundException if the
+ * resource could not be found and the entire search operation
+ * should fail.
+ **/
+ public URL findResource(ClassLoader parent, Module module, String name)
+ throws ResourceNotFoundException;
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/URLPolicy.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/URLPolicy.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/URLPolicy.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/URLPolicy.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+import java.net.URL;
+
+/**
+ * <p>
+ * This interface represents the <tt>ModuleLoader</tt>'s policy for creating
+ * <tt>URL</tt> for resource loading and security purposes. Java requires the
+ * use of <tt>URL</tt>s for resource loading and security. For resource loading,
+ * <tt>URL</tt>s are returned for requested resources. Subsequently, the resource
+ * <tt>URL</tt> is used to create an input stream for reading the resources
+ * bytes. With respect to security, <tt>URL</tt>s are used when defining a
+ * class in order to determine where the code came from, this concept is called
+ * a <tt>CodeSource</tt>. This approach enables Java to assign permissions to
+ * code that originates from particular locations.
+ * </p>
+ * <p>
+ * The <tt>ModuleManager</tt> requires a concrete implementation of this
+ * interface in order to function. Whenever the <tt>ModuleManager</tt> requires
+ * a <tt>URL</tt> for either resource loading or security, it delegates to
+ * the policy implementation. A default implementation is provided,
+ * called <a href="DefaultURLPolicy.html"><tt>DefaultURLPolicy</tt></a>, but
+ * it only supports resource loading, not security.
+ * </p>
+ * @see org.apache.osgi.moduleloader.ModuleManager
+ * @see org.apache.osgi.moduleloader.DefaultURLPolicy
+**/
+public interface URLPolicy
+{
+ /**
+ * <p>
+ * This method should return a <tt>URL</tt> that represents the
+ * location from which the module originated. This <tt>URL</tt>
+ * can be used when assigning permissions to the module, such as
+ * is done in the Java permissions policy file.
+ * </p>
+ * @param mgr the <tt>ModuleManager</tt> of the module.
+ * @param module the module for which the <tt>URL</tt> is to be created.
+ * @return an <tt>URL</tt> to associate with the module.
+ **/
+ public URL createCodeSourceURL(ModuleManager mgr, Module module);
+
+ /**
+ * <p>
+ * This method should return a <tt>URL</tt> that is suitable
+ * for accessing the bytes of the specified resource. It must be possible
+ * open a connection to this <tt>URL</tt>, which may require that
+ * the implementer of this method also introduce a custom
+ * <tt>java.net.URLStreamHander</tt> when creating the <tt>URL</tt>.
+ * </p>
+ * @param mgr the <tt>ModuleManager</tt> of the module.
+ * @param module the module for which the resource is being loaded.
+ * @param rsIdx the index of the <tt>ResourceSource</tt> containing the resource.
+ * @param name the name of the resource being loaded.
+ * @return an <tt>URL</tt> for retrieving the resource.
+ **/
+ public URL createResourceURL(ModuleManager mgr, Module module, int rsIdx, String name);
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/Util.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/Util.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/Util.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/Util.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader;
+
+public class Util
+{
+ public static String getClassName(String className)
+ {
+ if (className == null)
+ {
+ className = "";
+ }
+ return (className.lastIndexOf('.') < 0)
+ ? "" : className.substring(className.lastIndexOf('.') + 1);
+ }
+
+ public static String getClassPackage(String className)
+ {
+ if (className == null)
+ {
+ className = "";
+ }
+ return (className.lastIndexOf('.') < 0)
+ ? "" : className.substring(0, className.lastIndexOf('.'));
+ }
+
+ public static String getResourcePackage(String resource)
+ {
+ if (resource == null)
+ {
+ resource = "";
+ }
+ // NOTE: The package of a resource is tricky to determine since
+ // resources do not follow the same naming conventions as classes.
+ // This code is pessimistic and assumes that the package of a
+ // resource is everything up to the last '/' character. By making
+ // this choice, it will not be possible to load resources from
+ // imports using relative resource names. For example, if a
+ // bundle exports "foo" and an importer of "foo" tries to load
+ // "/foo/bar/myresource.txt", this will not be found in the exporter
+ // because the following algorithm assumes the package name is
+ // "foo.bar", not just "foo". This only affects imported resources,
+ // local resources will work as expected.
+ String pkgName = (resource.startsWith("/")) ? resource.substring(1) : resource;
+ pkgName = (pkgName.lastIndexOf('/') < 0)
+ ? "" : pkgName.substring(0, pkgName.lastIndexOf('/'));
+ pkgName = pkgName.replace('/', '.');
+ return pkgName;
+ }
+}
\ No newline at end of file
Propchange: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/Util.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/CompatibilityPolicy.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/CompatibilityPolicy.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/CompatibilityPolicy.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/CompatibilityPolicy.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader.search;
+
+/**
+ * <p>
+ * This interface represents the naming and version numbering policy of
+ * import and export identifiers for the <tt>ImportSearchPolicy</tt>. A concrete
+ * implementation of this interface is required to create an instance
+ * of <tt>ImportSearchPolicy</tt>. The sole purpose of this interface
+ * is to allow the <tt>ImportSearchPolicy</tt> to determine if one
+ * import/export identifier and version is compatible with another.
+ * </p>
+ * @see org.apache.osgi.moduleloader.search.ImportSearchPolicy
+**/
+public interface CompatibilityPolicy
+{
+ /**
+ * Compares two import/export identifiers.
+ * @param leftId the identifier to test for compatibility.
+ * @param leftVersion the version number to test for compatibility.
+ * @param rightId the identifier used as the compatibility base line.
+ * @param rightVersion the version used as the compatibility base line.
+ * @return <tt>0</tt> if the identifiers are equal, <tt>-1</tt> if the
+ * left identifier is less then the right identifier, and <tt>1</tt>
+ * if the left identifier is greater than the right identifier.
+ * @throws java.lang.IllegalArgumentException if the two identifiers
+ * are not comparable, i.e., they refer to intrinsically different
+ * entities.
+ **/
+ public int compare(
+ Object leftId, Object leftVersion,
+ Object rightId, Object rightVersion);
+
+ /**
+ * Returns whether the first import/export identifer is compatible
+ * with the second; this method should not throw any exceptions.
+ * @param leftId the identifier to test for compatibility.
+ * @param leftVersion the version number to test for compatibility.
+ * @param rightId the identifier used as the compatibility base line.
+ * @param rightVersion the version used as the compatibility base line.
+ * @return <tt>true</tt> if the left version number object is compatible
+ * with the right version number object, otherwise <tt>false</tt>.
+ **/
+ public boolean isCompatible(
+ Object leftId, Object leftVersion,
+ Object rightId, Object rightVersion);
+}
\ No newline at end of file
Added: incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/ExhaustiveSearchPolicy.java
URL: http://svn.apache.org/viewcvs/incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/ExhaustiveSearchPolicy.java?rev=233031&view=auto
==============================================================================
--- incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/ExhaustiveSearchPolicy.java (added)
+++ incubator/oscar/trunk/src/org/apache/osgi/moduleloader/search/ExhaustiveSearchPolicy.java Tue Aug 16 11:33:34 2005
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2005 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.osgi.moduleloader.search;
+
+import java.net.URL;
+
+import org.apache.osgi.moduleloader.*;
+
+/**
+ * <p>
+ * This class implements a <tt>ModuleLoader</tt> search policy that
+ * exhaustively and linearly searches all modules when trying to load
+ * a particular class or resource. As a result of this algorithm, every class loader
+ * for every module is essentially identical, meaning that each will
+ * load a given class or resource from the same class loader. This search policy
+ * provides behavior similar to the standard <tt>CLASSPATH</tt> environment
+ * variable approach. The main difference is that modules can be added
+ * to the module manager at run time; thus, the class path is dynamically
+ * extended. This search policy is not fully dynamic, since it does not
+ * support the removal of modules at run time; if a module is removed from
+ * the module manager at run time, there is no attempt to clean up its
+ * loaded classes.
+ * </p>
+ * @see org.apache.osgi.moduleloader.SearchPolicy
+ * @see org.apache.osgi.moduleloader.Module
+ * @see org.apache.osgi.moduleloader.ModuleClassLoader
+ * @see org.apache.osgi.moduleloader.ModuleManager
+**/
+public class ExhaustiveSearchPolicy implements SearchPolicy
+{
+ private ModuleManager m_mgr = null;
+
+ /**
+ * This method is part of the <tt>SearchPolicy</tt> interface.
+ * This method is called by the <tt>ModuleManager</tt> once to
+ * give the search policy instance a reference to its associated
+ * module manager. This method should be implemented such that
+ * it cannot be called twice; calling this method a second time
+ * should produce an illegal state exception.
+ * @param mgr the module manager associated with this search policy.
+ * @throws java.lang.IllegalStateException if the method is called
+ * more than once.
+ **/
+ public void setModuleManager(ModuleManager mgr)
+ throws IllegalStateException
+ {
+ if (m_mgr == null)
+ {
+ m_mgr = mgr;
+ }
+ else
+ {
+ throw new IllegalStateException("Module manager is already initialized");
+ }
+ }
+
+ public Object[] definePackage(Module module, String pkgName)
+ {
+ return null;
+ }
+
+ /**
+ * This method finds the specified class for the specified module. It
+ * finds the class by linearly asking each module in the module manager
+ * for the specific class. As soon as the class is found, it is returned.
+ * @param parent the parent class loader of the delegating class loader.
+ * @param module the target module that is loading the class.
+ * @param name the name of the class being loaded.
+ * @return the class if found, <tt>null</tt> otherwise.
+ **/
+ public Class findClassBeforeModule(ClassLoader parent, Module module, String name)
+ {
+ // First, try to load from parent.
+ if (parent != null)
+ {
+ try
+ {
+ Class c = parent.loadClass(name);
+ if (c != null)
+ {
+ return c;
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ // Ignore and search modules.
+ }
+ }
+
+ Module[] modules = m_mgr.getModules();
+ for (int i = 0; i < modules.length; i++)
+ {
+ try {
+ Class clazz = modules[i].getClassLoader().loadClassFromModule(name);
+ if (clazz != null)
+ {
+ return clazz;
+ }
+ } catch (Throwable th) {
+ }
+ }
+
+ return null;
+ }
+
+ public Class findClassAfterModule(ClassLoader parent, Module module, String name)
+ {
+ return null;
+ }
+
+ /**
+ * This method finds the specified resource for the specified module. It
+ * finds the resource by linearly asking each module in the module manager
+ * for specific resource. As soon as the resource is found, a <tt>URL</tt>
+ * to it is returned.
+ * @param parent the parent class loader of the delegating class loader.
+ * @param module the target module that is loading the resource.
+ * @param name the name of the resource being loaded.
+ * @return a <tt>URL</tt> to the resource if found, <tt>null</tt> otherwise.
+ **/
+ public URL findResource(ClassLoader parent, Module module, String name)
+ {
+ // First, try to load from parent.
+ if (parent != null)
+ {
+ URL url = parent.getResource(name);
+ if (url != null)
+ {
+ return url;
+ }
+ }
+
+ Module[] modules = m_mgr.getModules();
+ for (int i = 0; i < modules.length; i++)
+ {
+ try {
+ URL url = modules[i].getClassLoader().getResourceFromModule(name);
+ if (url != null)
+ {
+ return url;
+ }
+ } catch (Throwable th) {
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file