2004-12-29 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / assembly.c
index 2651ff0b0086e9809b341914efda4a4abfcf0034..1822bd8e4a2fbb61031b00aae2c8787a0475d6c7 100644 (file)
@@ -17,9 +17,6 @@
 #include "image.h"
 #include "cil-coff.h"
 #include "rawbuffer.h"
-#ifdef WITH_BUNDLE
-#include "mono-bundle.h"
-#endif
 #include <mono/metadata/loader.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/metadata-internals.h>
@@ -40,8 +37,12 @@ default_path [] = {
        NULL
 };
 
+/* Contains the list of directories to be searched for assemblies (MONO_PATH) */
 static char **assemblies_path = NULL;
 
+/* Contains the list of directories that point to auxiliary GACs */
+static char **extra_gac_paths = NULL;
+
 /*
  * keeps track of loaded assemblies
  */
@@ -54,7 +55,8 @@ static CRITICAL_SECTION assemblies_mutex;
 /* A hastable of thread->assembly list mappings */
 static GHashTable *assemblies_loading;
 
-static char **extra_gac_paths = NULL;
+/* If defined, points to the bundled assembly information */
+const MonoBundledAssembly **bundles;
 
 static gchar*
 encode_public_tok (const guchar *token, gint32 len)
@@ -73,7 +75,8 @@ encode_public_tok (const guchar *token, gint32 len)
 }
 
 static void
-check_path_env (void) {
+check_path_env (void)
+{
        const char *path;
        char **splitted;
        
@@ -120,7 +123,7 @@ check_extra_gac_path_env (void) {
        }
 }
 
-static gboolean
+gboolean
 mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r)
 {
        if (!l->name || !r->name)
@@ -129,46 +132,34 @@ mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r)
        if (strcmp (l->name, r->name))
                return FALSE;
 
-        /*
-         * simply compare names until some other issues are resolved
-         * (version info not getting set correctly for custom
-         * attributes).
-         */
-        /*
+       if (l->culture && r->culture && strcmp (l->culture, r->culture))
+               return FALSE;
+
        if (l->major != r->major || l->minor != r->minor ||
                        l->build != r->build || l->revision != r->revision)
-               return FALSE;
+               if (! ((l->major == 0 && l->minor == 0 && l->build == 0 && l->revision == 0) || (r->major == 0 && r->minor == 0 && r->build == 0 && r->revision == 0)))
+                       return FALSE;
 
-       if (!l->public_tok_value && !r->public_tok_value)
+       if (!l->public_key_token [0] || !r->public_key_token [0])
                return TRUE;
 
-       if ((l->public_tok_value && !r->public_tok_value) || (!l->public_tok_value && r->public_tok_value))
+       if (strcmp (l->public_key_token, r->public_key_token))
                return FALSE;
 
-       if (strcmp (l->public_tok_value, r->public_tok_value))
-               return FALSE;
-        */
        return TRUE;
 }
 
-/* assemblies_mutex must be held by the caller */
 static MonoAssembly*
 search_loaded (MonoAssemblyName* aname)
 {
        GList *tmp;
        MonoAssembly *ass;
        GList *loading;
-       
-       for (tmp = loaded_assemblies; tmp; tmp = tmp->next) {
-               ass = tmp->data;
-               /* g_print ("compare %s %s\n", aname->name, ass->aname.name); */
-               if (!mono_assembly_names_equal (aname, &ass->aname))
-                       continue;
-               /* g_print ("success\n"); */
 
+       ass = mono_assembly_invoke_search_hook (aname);
+       if (ass)
                return ass;
-       }
-
+       
        /*
         * The assembly might be under load by this thread. In this case, it is
         * safe to return an incomplete instance to prevent loops.
@@ -468,6 +459,43 @@ mono_install_assembly_load_hook (MonoAssemblyLoadFunc func, gpointer user_data)
        assembly_load_hook = hook;
 }
 
+typedef struct AssemblySearchHook AssemblySearchHook;
+struct AssemblySearchHook {
+       AssemblySearchHook *next;
+       MonoAssemblySearchFunc func;
+       gpointer user_data;
+};
+
+AssemblySearchHook *assembly_search_hook = NULL;
+
+MonoAssembly*
+mono_assembly_invoke_search_hook (MonoAssemblyName *aname)
+{
+       AssemblySearchHook *hook;
+
+       for (hook = assembly_search_hook; hook; hook = hook->next) {
+               MonoAssembly *ass = hook->func (aname, hook->user_data);
+               if (ass)
+                       return ass;
+       }
+
+       return NULL;
+}
+
+void          
+mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
+{
+       AssemblySearchHook *hook;
+       
+       g_return_if_fail (func != NULL);
+
+       hook = g_new0 (AssemblySearchHook, 1);
+       hook->func = func;
+       hook->user_data = user_data;
+       hook->next = assembly_search_hook;
+       assembly_search_hook = hook;
+}      
+
 typedef struct AssemblyPreLoadHook AssemblyPreLoadHook;
 struct AssemblyPreLoadHook {
        AssemblyPreLoadHook *next;
@@ -561,36 +589,30 @@ absolute_dir (const gchar *filename)
        return res;
 }
 
-static MonoImage*
-do_mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
+/** 
+ * mono_assembly_open_from_bundle:
+ * @filename: Filename requested
+ * @status: return value
+ *
+ * This routine tries to open the assembly specified by `filename' from the
+ * defined bundles, if found, returns the MonoImage for it, if not found
+ * returns NULL
+ */
+static MonoImage *
+mono_assembly_open_from_bundle (const char *filename, MonoImageOpenStatus *status)
 {
-       MonoImage *image = NULL;
-#ifdef WITH_BUNDLE
        int i;
        char *name = g_path_get_basename (filename);
-       char *dot = strrchr (name, '.');
-       GList *tmp;
-       MonoAssembly *ass;
-       
-       if (dot)
-               *dot = 0;
-       /* we do a very simple search for bundled assemblies: it's not a general 
+       MonoImage *image = NULL;
+
+       /*
+        * we do a very simple search for bundled assemblies: it's not a general 
         * purpose assembly loading mechanism.
         */
        EnterCriticalSection (&assemblies_mutex);
-       for (tmp = loaded_assemblies; tmp; tmp = tmp->next) {
-               ass = tmp->data;
-               if (!ass->aname.name)
-                       continue;
-               if (strcmp (name, ass->aname.name))
-                       continue;
-               image = ass->image;
-               break;
-       }
-
-       for (i = 0; !image && bundled_assemblies [i]; ++i) {
-               if (strcmp (bundled_assemblies [i]->name, name) == 0) {
-                       image = mono_image_open_from_data ((char*)bundled_assemblies [i]->data, bundled_assemblies [i]->size, FALSE, status);
+       for (i = 0; !image && bundles [i]; ++i) {
+               if (strcmp (bundles [i]->name, name) == 0) {
+                       image = mono_image_open_from_data ((char*)bundles [i]->data, bundles [i]->size, FALSE, status);
                        break;
                }
        }
@@ -600,7 +622,20 @@ do_mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
                mono_image_addref (image);
                return image;
        }
-#endif
+       return NULL;
+}
+
+static MonoImage*
+do_mono_assembly_open (const char *filename, MonoImageOpenStatus *status)
+{
+       MonoImage *image = NULL;
+
+       if (bundles != NULL){
+               image = mono_assembly_open_from_bundle (filename, status);
+
+               if (image != NULL)
+                       return image;
+       }
        EnterCriticalSection (&assemblies_mutex);
        image = mono_image_open (filename, status);
        LeaveCriticalSection (&assemblies_mutex);
@@ -819,16 +854,16 @@ mono_assembly_load_with_partial_name (const char *name, MonoImageOpenStatus *sta
        memset (&aname, 0, sizeof (MonoAssemblyName));
        aname.name = name;
 
+       res = mono_assembly_loaded (&aname);
+       if (res)
+               return res;
+
        res = invoke_assembly_preload_hook (&aname, assemblies_path);
        if (res) {
                res->in_gac = FALSE;
                return res;
        }
 
-       res = mono_assembly_loaded (&aname);
-       if (res)
-               return res;
-
        fullname = g_strdup_printf ("%s.dll", name);
 
        if (extra_gac_paths) {
@@ -937,16 +972,16 @@ mono_assembly_load (MonoAssemblyName *aname, const char *basedir, MonoImageOpenS
        MonoAssembly *result;
        char *fullpath, *filename;
 
+       result = mono_assembly_loaded (aname);
+       if (result)
+               return result;
+
        result = invoke_assembly_preload_hook (aname, assemblies_path);
        if (result) {
                result->in_gac = FALSE;
                return result;
        }
 
-       result = mono_assembly_loaded (aname);
-       if (result)
-               return result;
-
        /* g_print ("loading %s\n", aname->name); */
        /* special case corlib */
        if (strcmp (aname->name, "mscorlib") == 0) {
@@ -1071,7 +1106,7 @@ mono_assembly_foreach (GFunc func, gpointer user_data)
        GList *copy;
 
        /*
-     * We make a copy of the list to avoid calling the callback inside the 
+        * We make a copy of the list to avoid calling the callback inside the 
         * lock, which could lead to deadlocks.
         */
        EnterCriticalSection (&assemblies_mutex);
@@ -1083,7 +1118,8 @@ mono_assembly_foreach (GFunc func, gpointer user_data)
        g_list_free (copy);
 }
 
-/* Holds the assembly of the application, for
+/*
+ * Holds the assembly of the application, for
  * System.Diagnostics.Process::MainModule
  */
 static MonoAssembly *main_assembly=NULL;
@@ -1105,3 +1141,9 @@ mono_assembly_get_image (MonoAssembly *assembly)
 {
        return assembly->image;
 }
+
+void
+mono_register_bundled_assemblies (const MonoBundledAssembly **assemblies)
+{
+       bundles = assemblies;
+}