Initial source commit.


git-svn-id: https://svn.apache.org/repos/asf/incubator/oscar/trunk@233031 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/osgi/moduleloader/Module.java b/src/org/apache/osgi/moduleloader/Module.java
new file mode 100644
index 0000000..c33a5fa
--- /dev/null
+++ b/src/org/apache/osgi/moduleloader/Module.java
@@ -0,0 +1,357 @@
+/*
+ *   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.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.*;
+
+/**
+ * <p>
+ * The <tt>Module</tt> class is a grouping mechanism for application classes
+ * and resources. Conceptually, most applications are grouped into
+ * entities such as JAR files (containing classes and resources) and native
+ * libraries. In some cases, these entities are core application classes and
+ * resources, while in other cases, these entities are ancillary, such as
+ * dynamically loaded plug-ins. Applications place some level of semantics
+ * onto these types of entities or <i>modules</i>, but for the <tt>ModuleLoader</tt>,
+ * no particular semantics are attached to modules (other than they are a grouping
+ * mechanism for classes and resources). This means that the application
+ * is free to map itself into modules any way that is appropriate.
+ * </p>
+ * <p>
+ * A module has the following features:
+ * </p>
+ * <ul>
+ *   <li>A unique identifier within the scope of its <tt>ModuleManager</tt>.
+ *   </li>
+ *   <li>A set of key-value attribute pairs.
+ *   </li>
+ *   <li>A set of resource sources from which it is possible to
+ *       retrieve classes and resources.
+ *   </li>
+ *   <li>A set of native library sources from which it is possible
+ *       to retrieve native libraries.
+ *   </li>
+ * </ul>
+ * <p>
+ * A module's identifier must be unique within the scope of its
+ * <tt>ModuleManager</tt>, but there is no meaning associated with it. The
+ * set of attribute-value pairs attached to the module have no meaning to
+ * the <tt>ModuleManager</tt>, nor does it consult them at all. The point
+ * of these attributes is to attach meta-data for use by
+ * <a href="SearchPolicy.html"><tt>SearchPolicy</tt></a> implementations.
+ * Attributes are represented as an array of <tt>Object</tt>
+ * arrays, i.e., <tt>Object[][]</tt>. Each element in the attribute array is
+ * a two-element <tt>Object</tt> array, where <tt>Module.KEY_IDX</tt> is the attribute's
+ * key and <tt>Module.VALUE_IDX</tt> is the attribute's value.
+ * </p>
+ * <p>
+ * The actual contents of a module is contained in two sets of sources
+ * for its resources and native libraries,
+ * <a href="ResourceSource.html"><tt>ResourceSource</tt></a>s
+ * and <a href="LibrarySource.html"><tt>LibrarySource</tt></a>s, respectively.
+ * Each module also has a <a href="ModuleClassLoader.html"><tt>ModuleClassLoader</tt></a>
+ * associated with it. The <tt>ModuleClassLoader</tt> consults these two types
+ * of sources to find classes, resources, and native libraries.
+ * </p>
+ * @see org.apache.osgi.moduleloader.ModuleManager
+ * @see org.apache.osgi.moduleloader.ModuleClassLoader
+ * @see org.apache.osgi.moduleloader.ResourceSource
+ * @see org.apache.osgi.moduleloader.LibrarySource
+**/
+public class Module
+{
+    /**
+     * This is the index used to retrieve the key of an attribute;
+     * an attribute is represented as an <tt>Object[]</tt> instance.
+    **/
+    public static final int KEY_IDX = 0;
+    /**
+     * This is the index used to retrieve the value of an attribute;
+     * an attribute is represented as an <tt>Object[]</tt> instance.
+    **/
+    public static final int VALUE_IDX = 1;
+
+    private ModuleManager m_mgr = null;
+    private String m_id = null;
+    private boolean m_useParentSource = false;
+    private Map m_attributeMap = new HashMap();
+    private ResourceSource[] m_resSources = null;
+    private LibrarySource[] m_libSources = null;
+    private ModuleClassLoader m_loader = null;
+
+    /**
+     * <p>
+     * Constructs a <tt>Module</tt> instance that will be associated with
+     * the specified <tt>ModuleManager</tt> and will have the specified
+     * identifier, attributes, resource sources, and library sources. In general,
+     * modules should not be created directly, but should be created by making
+     * a call to <tt>ModuleManager.addModule()</tt>.
+     * </p>
+     * @param mgr the <tt>ModuleManager</tt> that will be associated to
+     *       the instance.
+     * @param id the identifier of the instance.
+     * @param attributes the set of attributes associated with the instance.
+     * @param resSources the set of <tt>ResourceSource</tt>s associated with
+     *        the instance.
+     * @param libSources the set of <tt>LibrarySource</tt>s associated with
+     *        the instance.
+     * @param useParentSource a flag indicating whether or not the parent
+     *        class loader should be used as a resource source; this is an
+     *        ugly hack to allow a module to masquerade as the system
+     *        class loader.
+     * @see org.apache.osgi.moduleloader.ModuleManager
+     * @see org.apache.osgi.moduleloader.ResourceSource
+     * @see org.apache.osgi.moduleloader.LibrarySource
+    **/
+    public Module(
+        ModuleManager mgr, String id, Object[][] attributes,
+        ResourceSource[] resSources, LibrarySource[] libSources,
+        boolean useParentSource)
+    {
+        m_mgr = mgr;
+        m_id = id;
+        m_useParentSource = useParentSource;
+        initialize(attributes, resSources, libSources);
+    }
+
+    /**
+     * <p>
+     * Returns the identifier of the module.
+     * </p>
+     * @return the identifier of the module.
+    **/
+    public String getId()
+    {
+        return m_id;
+    }
+
+    /**
+     * <p>
+     * Returns the attribute set associated with this module. Attributes
+     * are represented as an array of <tt>Object</tt> arrays, i.e.,
+     * <tt>Object[][]</tt>. Each element in the attribute array is
+     * two-element <tt>Object</tt> array, where <tt>Module.KEY_IDX</tt>
+     * is the index to the attribute key and <tt>Module.VALUE_IDX</tt>
+     * is the index to the attribute value. The returned array is a
+     * copy and may be freely modified.
+     * </p>
+     * @return the attribute set associated with this module.
+    **/
+    public synchronized Object[][] getAttributes()
+    {
+        Set s = m_attributeMap.entrySet();
+        Object[][] attributes = new Object[s.size()][];
+        Iterator iter = s.iterator();
+        for (int i = 0; iter.hasNext(); i++)
+        {
+            Map.Entry entry = (Map.Entry) iter.next();
+            attributes[i] = new Object[] { entry.getKey(), entry.getValue() };
+        }
+        return attributes;
+    }
+
+    /**
+     * <p>
+     * Returns the attribute value associated with the specified key.
+     * </p>
+     * @param key the key of the attribute whose value is to be retrieved.
+     * @return the attribute's value or <tt>null</tt>.
+    **/
+    public synchronized Object getAttribute(String key)
+    {
+        return m_attributeMap.get(key);
+    }
+
+    /**
+     * <p>
+     * Sets the attribute value associated with the specified key. The
+     * attribute will be added if it does not currently exist.
+     * </p>
+     * @param key the key of the attribute whose value is to be set.
+     * @param value the new value to be associated with the attribute key.
+    **/
+    public synchronized void setAttribute(String key, Object value)
+    {
+        m_attributeMap.put(key, value);
+    }
+
+    /**
+     * <p>
+     * Returns the array of <tt>ResourceSource</tt>s associated with
+     * the module. The returned array is not a copy and therefore should
+     * not be modified.
+     * </p>
+     * @return the array of <tt>ResourceSource</tt>s associated with
+     *         the module.
+     * @see org.apache.osgi.moduleloader.ResourceSource
+    **/
+    public ResourceSource[] getResourceSources()
+    {
+        return m_resSources;
+    }
+
+    /**
+     * <p>
+     * Returns the array of <tt>LibrarySource</tt>s associated with
+     * the module. The returned array is not a copy and therefore should
+     * not be modified.
+     * </p>
+     * @return the array of <tt>LibrarySource</tt>s associated with
+     *         the module.
+     * @see org.apache.osgi.moduleloader.LibrarySource
+    **/
+    public LibrarySource[] getLibrarySources()
+    {
+        return m_libSources;
+    }
+
+    /**
+     * <p>
+     * Returns the <tt>ModuleClassLoader</tt> associated with this module.
+     * If a security manager is installed, then this method uses a privileged
+     * action to avoid a security exception being thrown to the caller.
+     * </p>
+     * @return the <tt>ModuleClassLoader</tt> associated with this module.
+     * @see org.apache.osgi.moduleloader.ModuleClassLoader
+    **/
+    public synchronized ModuleClassLoader getClassLoader()
+    {
+        if (m_loader == null)
+        {
+            if (System.getSecurityManager() != null)
+            {
+                m_loader = (ModuleClassLoader) AccessController.doPrivileged(
+                    new GetClassLoaderPrivileged(m_mgr, this, m_useParentSource));
+            }
+            else
+            {
+                m_loader = new ModuleClassLoader(m_mgr, this, m_useParentSource);
+            }
+        }
+
+        return m_loader;
+    }
+
+    /**
+     * <p>
+     * Returns the module's identifier.
+     * </p>
+     * @return the module's identifier.
+    **/
+    public String toString()
+    {
+        return m_id;
+    }
+
+    /**
+     * <p>
+     * Resets the module by throwing away its associated class loader and
+     * re-initializing its attributes, resource sources, and library sources
+     * with the specified values.
+     * </p>
+     * @param attributes the new attributes to be associated with the module.
+     * @param resSources the new resource sources to be associated with the module.
+     * @param libSources the new library sources to be associated with the module.
+     * @see org.apache.osgi.moduleloader.ResourceSource
+     * @see org.apache.osgi.moduleloader.LibrarySource
+    **/
+    protected synchronized void reset(
+        Object[][] attributes, ResourceSource[] resSources,
+        LibrarySource[] libSources)
+    {
+        // Throw away class loader.
+        m_loader = null;
+        // Clear attribute map.
+        m_attributeMap.clear();
+        // Close all sources.
+        dispose();
+        // Re-initialize.
+        initialize(attributes, resSources, libSources);
+    }
+
+    /**
+     * <p>
+     * Disposes the module by closing all resource and library sources.
+     * </p>
+    **/
+    protected synchronized void dispose()
+    {
+        // Close sources.
+        for (int i = 0; (m_resSources != null) && (i < m_resSources.length); i++)
+        {
+            m_resSources[i].close();
+        }
+        for (int i = 0; (m_libSources != null) && (i < m_libSources.length); i++)
+        {
+            m_libSources[i].close();
+        }
+    }
+
+    /**
+     * <p>
+     * Initializes the module by copying the specified attribute array into
+     * a map and opening all resource and library sources.
+     * </p>
+     * @param attributes the attributes to be put into a map.
+     * @param resSources the resource sources to be opened.
+     * @param libSources the library sources to be opened.
+     * @see org.apache.osgi.moduleloader.ResourceSource
+     * @see org.apache.osgi.moduleloader.LibrarySource
+    **/
+    private void initialize(
+        Object[][] attributes, ResourceSource[] resSources, LibrarySource[] libSources)
+    {
+        for (int i = 0; (attributes != null) && (i < attributes.length); i++)
+        {
+            m_attributeMap.put(attributes[i][KEY_IDX], attributes[i][VALUE_IDX]);
+        }
+
+        m_resSources = resSources;
+        m_libSources = libSources;
+
+        // Open sources.
+        for (int i = 0; (m_resSources != null) && (i < m_resSources.length); i++)
+        {
+            m_resSources[i].open();
+        }
+        for (int i = 0; (m_libSources != null) && (i < m_libSources.length); i++)
+        {
+            m_libSources[i].open();
+        }
+    }
+
+    private static class GetClassLoaderPrivileged implements PrivilegedAction
+    {
+        private ModuleManager m_mgr = null;
+        private Module m_module = null;
+        private boolean m_useParentSource = false;
+
+        public GetClassLoaderPrivileged(ModuleManager mgr, Module module, boolean useParentSource)
+        {
+            m_mgr = mgr;
+            m_module = module;
+            m_useParentSource = useParentSource;
+        }
+
+        public Object run()
+        {
+            return new ModuleClassLoader(m_mgr, m_module, m_useParentSource);
+        }
+    }
+}
\ No newline at end of file