Index: libroar/plugincontainer.c
===================================================================
--- libroar/plugincontainer.c	(revision 5487)
+++ libroar/plugincontainer.c	(revision 5488)
@@ -40,9 +40,39 @@
 struct roar_plugincontainer {
  size_t refc;
+ const struct roar_plugincontainer_callbacks * callbacks;
+ void * userdata;
  struct roar_dl_librarypara * default_para;
  struct roar_dl_lhandle * handle[MAX_PLUGINS];
  size_t deprefc[MAX_PLUGINS];
+ void * context[MAX_PLUGINS];
  size_t numhandles;
 };
+
+static inline void _unload(struct roar_plugincontainer * cont, size_t index) {
+ int err = roar_error;
+
+ if ( cont->callbacks != NULL && cont->callbacks->preunload != NULL )
+  cont->callbacks->preunload(cont, &(cont->context[index]), cont->handle[index]);
+
+ roar_err_set(err);
+ roar_dl_unref(cont->handle[index]);
+ err = roar_error;
+ cont->handle[index] = NULL;
+ cont->numhandles--;
+
+ if ( cont->callbacks != NULL && cont->callbacks->postunload != NULL )
+  cont->callbacks->postunload(cont, &(cont->context[index]));
+
+ if ( cont->context[index] != NULL )
+  if ( cont->callbacks != NULL && cont->callbacks->freecontext != NULL )
+  cont->callbacks->freecontext(cont, &(cont->context[index]));
+
+ if ( cont->context[index] != NULL ) {
+  roar_mm_free(cont->context[index]);
+  cont->context[index] = NULL;
+ }
+
+ roar_err_set(err);
+}
 
 static int _loader(struct roar_dl_librarypara * lhandle, void * loader_userdata, enum roar_dl_loadercmd cmd, void * argp) {
@@ -209,4 +239,7 @@
  }
 
+ if ( cont->callbacks != NULL && cont->callbacks->prefree != NULL )
+  cont->callbacks->prefree(cont, &(cont->userdata));
+
  while (cont->numhandles) {
   for (i = 0; i < MAX_PLUGINS; i++) {
@@ -218,9 +251,18 @@
     continue;
 
-   roar_dl_close(cont->handle[i]);
-   cont->handle[i] = NULL;
-   cont->numhandles--;
-  }
- }
+   _unload(cont, i);
+  }
+ }
+
+ // try to free user data...
+ if ( cont->userdata != NULL ) {
+  if ( cont->callbacks != NULL && cont->callbacks->freeuserdata != NULL ) {
+   cont->callbacks->freeuserdata(cont, &(cont->userdata));
+  }
+ }
+
+ // if still not freed by caller, free it using memmgr.
+ if ( cont->userdata != NULL )
+  roar_mm_free(cont->userdata);
 
  if ( cont->default_para != NULL )
@@ -233,12 +275,52 @@
 }
 
-struct roar_dl_lhandle * roar_plugincontainer_get_lhandle_by_name (struct roar_plugincontainer * cont,
-                                                                   const char * name) {
+int roar_plugincontainer_set_callbacks(struct roar_plugincontainer * cont,
+                                       const struct roar_plugincontainer_callbacks * callbacks) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ cont->callbacks = callbacks;
+
+ return 0;
+}
+
+int roar_plugincontainer_set_userdata(struct roar_plugincontainer * cont, void * userdata) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ cont->userdata = userdata;
+
+ return 0;
+}
+
+void * roar_plugincontainer_get_userdata(struct roar_plugincontainer * cont) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return NULL;
+ }
+
+ if ( cont->userdata == NULL ) {
+  roar_err_set(ROAR_ERROR_NOENT);
+  return NULL;
+ }
+
+ return cont->userdata;
+}
+
+struct roar_plugincontainer_plugininfo roar_plugincontainer_get_info_by_name (struct roar_plugincontainer * cont,
+                                                                              const char * name) {
+ struct roar_plugincontainer_plugininfo ret;
  const struct roar_dl_libraryname * libname;
  size_t i;
 
+ memset(&ret, 0, sizeof(ret));
+
  if ( cont == NULL || name == NULL ) {
   roar_err_set(ROAR_ERROR_FAULT);
-  return NULL;
+  return ret;
  }
 
@@ -252,12 +334,26 @@
   if ( !strcmp(libname->name, name) ) {
    if ( roar_dl_ref(cont->handle[i]) == -1 )
-    return NULL;
-
-   return cont->handle[i];
+    return ret;
+
+   ret.libname  = libname->name;
+   ret.handle   = cont->handle[i];
+   ret.rdepends = cont->deprefc[i];
+   ret.context  = &(cont->context[i]);
+   return ret;
   }
  }
 
  roar_err_set(ROAR_ERROR_NOENT);
- return NULL;
+ return ret;
+}
+
+struct roar_dl_lhandle * roar_plugincontainer_get_lhandle_by_name (struct roar_plugincontainer * cont,
+                                                                   const char * name) {
+ struct roar_plugincontainer_plugininfo info = roar_plugincontainer_get_info_by_name(cont, name);
+
+ if ( info.libname == NULL )
+  return NULL;
+
+ return info.handle;
 }
 
@@ -316,5 +412,11 @@
  }
 
- cont->handle[idx] = roar_dl_open(name, flags, ra_init, para);
+ cont->context[idx] = NULL; // clear context.
+ cont->deprefc[idx] = 0;
+
+ if ( cont->callbacks != NULL && cont->callbacks->preload != NULL )
+  cont->callbacks->preload(cont, &(cont->context[idx]), name, flags, para);
+
+ cont->handle[idx] = roar_dl_open(name, flags, 0, para);
  if ( cont->handle[idx] == NULL ) {
   err = roar_error;
@@ -324,6 +426,29 @@
  }
 
- cont->deprefc[idx] = 0;
  cont->numhandles++;
+
+ if ( cont->callbacks != NULL && cont->callbacks->postload != NULL )
+  cont->callbacks->postload(cont, &(cont->context[idx]), cont->handle[idx], name, flags, para);
+
+ if ( ra_init ) {
+  if ( cont->callbacks != NULL && cont->callbacks->prera_init != NULL )
+   cont->callbacks->prera_init(cont, &(cont->context[idx]), cont->handle[idx], para);
+  if ( roar_dl_ra_init(cont->handle[idx], NULL, para) == -1 ) {
+   err = roar_error;
+
+   if ( cont->callbacks != NULL && cont->callbacks->postra_init != NULL )
+    cont->callbacks->postra_init(cont, &(cont->context[idx]), cont->handle[idx], para);
+
+   _unload(cont, idx);
+
+   roar_dl_para_unref(para);
+   cont->handle[idx] = NULL;
+   roar_error = err;
+   return NULL;
+  }
+
+  if ( cont->callbacks != NULL && cont->callbacks->postra_init != NULL )
+   cont->callbacks->postra_init(cont, &(cont->context[idx]), cont->handle[idx], para);
+ }
 
  roar_dl_para_unref(para);
@@ -369,7 +494,5 @@
     return -1;
    }
-   roar_dl_close(cont->handle[i]);
-   cont->handle[i] = NULL;
-   cont->numhandles--;
+   _unload(cont, i);
    return 0;
   }
@@ -391,5 +514,12 @@
   if ( cont->handle[i] == NULL )
    continue;
+
+  if ( cont->callbacks != NULL && cont->callbacks->prera_init != NULL )
+   cont->callbacks->prera_init(cont, &(cont->context[i]), cont->handle[i], cont->default_para);
+
   roar_dl_ra_init(cont->handle[i], NULL, cont->default_para);
+
+  if ( cont->callbacks != NULL && cont->callbacks->postra_init != NULL )
+   cont->callbacks->postra_init(cont, &(cont->context[i]), cont->handle[i], cont->default_para);
  }
 
