2005-10-08 Zoltan Varga <vargaz@freemail.hu>
authorZoltan Varga <vargaz@gmail.com>
Fri, 7 Oct 2005 22:45:36 +0000 (22:45 -0000)
committerZoltan Varga <vargaz@gmail.com>
Fri, 7 Oct 2005 22:45:36 +0000 (22:45 -0000)
* assembly.c (mono_stringify_assembly_name): New helper function.

* class.c: Use mono_stringify_assembly_name instead of the similar
static function.

* assembly.h assembly.c: Add support for calling a postload search
hook if an assembly cannot be loaded.

* appdomain.c: Register new search hooks which call the AssemblyResolve
events in AppDomain. Fixes #75231

svn path=/trunk/mono/; revision=51452

mono/metadata/ChangeLog
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/assembly.h

index 855a8367e9b171a722a0a88a19c86fddc173ddff..63ec843dfb17325642a0f3b3502d3de1623acca2 100644 (file)
@@ -1,3 +1,16 @@
+2005-10-08  Zoltan Varga  <vargaz@freemail.hu>
+
+       * assembly.c (mono_stringify_assembly_name): New helper function.
+
+       * class.c: Use mono_stringify_assembly_name instead of the similar
+       static function.
+
+       * assembly.h assembly.c: Add support for calling a postload search 
+       hook if an assembly cannot be loaded.
+
+       * appdomain.c: Register new search hooks which call the AssemblyResolve
+       events in AppDomain. Fixes #75231
+
 2005-10-07  Martin Baulig  <martin@ximian.com>
 
        * mono-debug.c (mono_debug_add_method): Create a wrapper entry for
index 38b8699dd053b1c6b2f373a1c47e441d593e5ec3..21943000e177e98f85960c9f29ecd4b4335f8c87 100644 (file)
@@ -48,6 +48,10 @@ static MonoAssembly *
 mono_domain_assembly_search (MonoAssemblyName *aname,
                                                         gpointer user_data);
 
+static MonoAssembly *
+mono_domain_assembly_postload_search (MonoAssemblyName *aname,
+                                                                         gpointer user_data);
+
 static void
 mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data);
 
@@ -87,6 +91,8 @@ mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb,
        mono_install_assembly_refonly_preload_hook (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (FALSE));
        mono_install_assembly_refonly_search_hook (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE));
+       mono_install_assembly_postload_search_hook (mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE));
+       mono_install_assembly_postload_refonly_search_hook (mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE));
        mono_install_assembly_load_hook (mono_domain_fire_assembly_load, NULL);
        mono_install_lookup_dynamic_token (mono_reflection_lookup_dynamic_token);
 
@@ -557,6 +563,28 @@ try_assembly_resolve (MonoDomain *domain, MonoString *fname, gboolean refonly)
        return (MonoReflectionAssembly *) mono_runtime_invoke (method, domain->domain, params, NULL);
 }
 
+static MonoAssembly *
+mono_domain_assembly_postload_search (MonoAssemblyName *aname,
+                                                                         gpointer user_data)
+{
+       gboolean refonly = GPOINTER_TO_UINT (user_data);
+       MonoReflectionAssembly *assembly;
+       MonoDomain *domain = mono_domain_get ();
+       char *aname_str;
+
+       aname_str = mono_stringify_assembly_name (aname);
+
+       /* FIXME: We invoke managed code here, so there is a potential for deadlocks */
+       assembly = try_assembly_resolve (domain, mono_string_new (domain, aname_str), refonly);
+
+       g_free (aname_str);
+
+       if (assembly)
+               return assembly->assembly;
+       else
+               return NULL;
+}
+       
 /*
  * LOCKING: assumes assemblies_lock in the domain is already locked.
  */
index ce3bc04b910c3d344219122813ab977c4f9cf0c0..7dce02c1b1f0d1783ac36f0ed89ea18de9cbea18 100644 (file)
@@ -129,12 +129,12 @@ static GHashTable *assemblies_refonly_loading;
 /* If defined, points to the bundled assembly information */
 const MonoBundledAssembly **bundles;
 
-/* Reflection only private hook functions */
-static MonoAssembly* mono_assembly_refonly_invoke_search_hook (MonoAssemblyName *aname);
-
 /* Loaded assembly binding info */
 static GSList *loaded_assembly_bindings = NULL;
 
+static MonoAssembly*
+mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, gboolean refonly, gboolean postload);
+
 static gchar*
 encode_public_tok (const guchar *token, gint32 len)
 {
@@ -369,7 +369,7 @@ search_loaded (MonoAssemblyName* aname, gboolean refonly)
        MonoAssembly *ass;
        GList *loading;
 
-       ass = refonly ? mono_assembly_refonly_invoke_search_hook (aname) : mono_assembly_invoke_search_hook (aname);
+       ass = mono_assembly_invoke_search_hook_internal (aname, refonly, FALSE);
        if (ass)
                return ass;
        
@@ -507,6 +507,24 @@ mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname)
        return TRUE;
 }
 
+/*
+ * mono_stringify_assembly_name:
+ *
+ *   Convert @aname into its string format. The returned string is dynamically
+ * allocated and should be freed by the caller.
+ */
+char*
+mono_stringify_assembly_name (MonoAssemblyName *aname)
+{
+       return g_strdup_printf (
+               "%s, Version=%d.%d.%d.%d, Culture=%s%s%s",
+               aname->name,
+               aname->major, aname->minor, aname->build, aname->revision,
+               aname->culture && *aname->culture? aname->culture: "neutral",
+               aname->public_key_token [0] ? ", PublicKeyToken=" : "",
+               aname->public_key_token [0] ? (char *)aname->public_key_token : "");
+}
+
 static gchar*
 assemblyref_public_tok (MonoImage *image, guint32 key_index, guint32 flags)
 {
@@ -757,42 +775,37 @@ typedef struct AssemblySearchHook AssemblySearchHook;
 struct AssemblySearchHook {
        AssemblySearchHook *next;
        MonoAssemblySearchFunc func;
+       gboolean refonly;
+       gboolean postload;
        gpointer user_data;
 };
 
 AssemblySearchHook *assembly_search_hook = NULL;
-static AssemblySearchHook *assembly_refonly_search_hook = NULL;
 
-MonoAssembly*
-mono_assembly_invoke_search_hook (MonoAssemblyName *aname)
+static MonoAssembly*
+mono_assembly_invoke_search_hook_internal (MonoAssemblyName *aname, gboolean refonly, gboolean postload)
 {
        AssemblySearchHook *hook;
 
        for (hook = assembly_search_hook; hook; hook = hook->next) {
-               MonoAssembly *ass = hook->func (aname, hook->user_data);
-               if (ass)
-                       return ass;
+               if ((hook->refonly == refonly) && (hook->postload == postload)) {
+                       MonoAssembly *ass = hook->func (aname, hook->user_data);
+                       if (ass)
+                               return ass;
+               }
        }
 
        return NULL;
 }
 
-static MonoAssembly*
-mono_assembly_refonly_invoke_search_hook (MonoAssemblyName *aname)
+MonoAssembly*
+mono_assembly_invoke_search_hook (MonoAssemblyName *aname)
 {
-       AssemblySearchHook *hook;
-
-       for (hook = assembly_refonly_search_hook; hook; hook = hook->next) {
-               MonoAssembly *ass = hook->func (aname, hook->user_data);
-               if (ass)
-                       return ass;
-       }
-
-       return NULL;
+       return mono_assembly_invoke_search_hook_internal (aname, FALSE, FALSE);
 }
 
-void          
-mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
+static void
+mono_install_assembly_search_hook_internal (MonoAssemblySearchFunc func, gpointer user_data, gboolean refonly, gboolean postload)
 {
        AssemblySearchHook *hook;
        
@@ -801,22 +814,34 @@ mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_da
        hook = g_new0 (AssemblySearchHook, 1);
        hook->func = func;
        hook->user_data = user_data;
+       hook->refonly = refonly;
+       hook->postload = postload;
        hook->next = assembly_search_hook;
        assembly_search_hook = hook;
+}
+
+void          
+mono_install_assembly_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
+{
+       mono_install_assembly_search_hook_internal (func, user_data, FALSE, FALSE);
 }      
 
 void
 mono_install_assembly_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
 {
-       AssemblySearchHook *hook;
+       mono_install_assembly_search_hook_internal (func, user_data, TRUE, FALSE);
+}
 
-       g_return_if_fail (func != NULL);
+void          
+mono_install_assembly_postload_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
+{
+       mono_install_assembly_search_hook_internal (func, user_data, FALSE, TRUE);
+}      
 
-       hook = g_new0 (AssemblySearchHook, 1);
-       hook->func = func;
-       hook->user_data = user_data;
-       hook->next = assembly_refonly_search_hook;
-       assembly_refonly_search_hook = hook;
+void
+mono_install_assembly_postload_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data)
+{
+       mono_install_assembly_search_hook_internal (func, user_data, TRUE, TRUE);
 }
 
 typedef struct AssemblyPreLoadHook AssemblyPreLoadHook;
@@ -1874,7 +1899,10 @@ mono_assembly_load_full (MonoAssemblyName *aname, const char *basedir, MonoImage
                        return result;
        }
 
-       return NULL;
+       /* Try a postload search hook */
+       result = mono_assembly_invoke_search_hook_internal (aname, refonly, TRUE);
+
+       return result;
 }
 
 MonoAssembly*
index a8c0b4e5719c1c4427963458eb91484853ad0765..b46a169550d2e7e2faccb7bf3311b4879b8a2b6b 100644 (file)
@@ -43,6 +43,7 @@ MonoAssembly *mono_assembly_get_main   (void);
 MonoImage    *mono_assembly_get_image  (MonoAssembly *assembly);
 gboolean      mono_assembly_fill_assembly_name (MonoImage *image, MonoAssemblyName *aname);
 gboolean      mono_assembly_names_equal (MonoAssemblyName *l, MonoAssemblyName *r);
+char*         mono_stringify_assembly_name (MonoAssemblyName *aname);
 
 /* Installs a function which is called each time a new assembly is loaded. */
 typedef void  (*MonoAssemblyLoadFunc)         (MonoAssembly *assembly, gpointer user_data);
@@ -58,6 +59,17 @@ void               mono_install_assembly_refonly_search_hook (MonoAssemblySearchFunc fu
 
 MonoAssembly* mono_assembly_invoke_search_hook (MonoAssemblyName *aname);
 
+/*
+ * Installs a new search function which is used as a last resort when loading 
+ * an assembly fails. This could invoke AssemblyResolve events.
+ */
+void          
+mono_install_assembly_postload_search_hook (MonoAssemblySearchFunc func, gpointer user_data);
+
+void          
+mono_install_assembly_postload_refonly_search_hook (MonoAssemblySearchFunc func, gpointer user_data);
+
+
 /* Installs a function which is called before a new assembly is loaded
  * The hook are invoked from last hooked to first. If any of them returns
  * a non-null value, that will be the value returned in mono_assembly_load */