* Makefile.in: Rebuilt.
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 Aug 2003 22:17:37 +0000 (22:17 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 28 Aug 2003 22:17:37 +0000 (22:17 +0000)
* Makefile.am (ordinary_java_source_files): Added new files.
* java/lang/Class.h (_Jv_sharedlib_register_hook): Declare as
friend.
* java/net/URLClassLoader.java (findClass): Don't use
findURLResource.  Use loader's getClass method.
(URLLoader.getClass): New method.
(addURL): Handle `gcjlib' URLs.
(SoURLLoader): New class.
(SoResource): Likewise.
* gnu/gcj/protocol/gcjlib/Connection.java: New file.
* gnu/gcj/protocol/gcjlib/Handler.java: New file.
* include/jvm.h (struct _Jv_core_chain): Moved from natCore.cc.
(_Jv_RegisterCoreHook): Declare.
(_Jv_FindCore): Declare.
* gnu/gcj/runtime/SharedLibHelper.java: New file.
* gnu/gcj/runtime/natSharedLibLoader.cc (CoreHookFunc): New
typedef.
(core_hook): New function.
(struct SharedLibDummy) [saved_core]: New field.
(init): Set _Jv_RegisterCoreHook.  Throw exception on failure.
(register_hook): Set protection domain and class loader on new
class.
(finalize): Free core chain.
* gnu/gcj/Core.java (Core): New constructor.
* gnu/gcj/runtime/SharedLibLoader.java: Rewrote to use
SharedLibHelper.
* gnu/gcj/natCore.cc (_Jv_RegisterResource): Indentation fixlet.
(_Jv_create_core): New function.
(create): Use it.
(default_register_resource): New function.
(_Jv_RegisterCoreHook): New global.
(_Jv_RegisterResource): Use it.
(core_chain_struct): Removed.
(_Jv_FindCore): New function.
(_Jv_FreeCoreChain): New function.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70892 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
libjava/ChangeLog
libjava/Makefile.am
libjava/Makefile.in
libjava/gnu/gcj/Core.java
libjava/gnu/gcj/natCore.cc
libjava/gnu/gcj/protocol/core/Connection.java
libjava/gnu/gcj/protocol/gcjlib/Connection.java [new file with mode: 0644]
libjava/gnu/gcj/protocol/gcjlib/Handler.java [new file with mode: 0644]
libjava/gnu/gcj/runtime/SharedLibHelper.java [new file with mode: 0644]
libjava/gnu/gcj/runtime/SharedLibLoader.java
libjava/gnu/gcj/runtime/natSharedLibLoader.cc
libjava/include/jvm.h
libjava/java/lang/Class.h
libjava/java/net/URLClassLoader.java

index c9e8984..178a2aa 100644 (file)
@@ -1,3 +1,42 @@
+2003-08-28  Tom Tromey  <tromey@redhat.com>
+
+       * Makefile.in: Rebuilt.
+       * Makefile.am (ordinary_java_source_files): Added new files.
+       * java/lang/Class.h (_Jv_sharedlib_register_hook): Declare as
+       friend.
+       * java/net/URLClassLoader.java (findClass): Don't use
+       findURLResource.  Use loader's getClass method.
+       (URLLoader.getClass): New method.
+       (addURL): Handle `gcjlib' URLs.
+       (SoURLLoader): New class.
+       (SoResource): Likewise.
+       * gnu/gcj/protocol/gcjlib/Connection.java: New file.
+       * gnu/gcj/protocol/gcjlib/Handler.java: New file.
+       * include/jvm.h (struct _Jv_core_chain): Moved from natCore.cc.
+       (_Jv_RegisterCoreHook): Declare.
+       (_Jv_FindCore): Declare.
+       * gnu/gcj/runtime/SharedLibHelper.java: New file.
+       * gnu/gcj/runtime/natSharedLibLoader.cc (CoreHookFunc): New
+       typedef.
+       (core_hook): New function.
+       (struct SharedLibDummy) [saved_core]: New field.
+       (init): Set _Jv_RegisterCoreHook.  Throw exception on failure.
+       (register_hook): Set protection domain and class loader on new
+       class.
+       (finalize): Free core chain.
+       * gnu/gcj/Core.java (Core): New constructor.
+       * gnu/gcj/runtime/SharedLibLoader.java: Rewrote to use
+       SharedLibHelper.
+       * gnu/gcj/natCore.cc (_Jv_RegisterResource): Indentation fixlet.
+       (_Jv_create_core): New function.
+       (create): Use it.
+       (default_register_resource): New function.
+       (_Jv_RegisterCoreHook): New global.
+       (_Jv_RegisterResource): Use it.
+       (core_chain_struct): Removed.
+       (_Jv_FindCore): New function.
+       (_Jv_FreeCoreChain): New function.
+
 2003-08-29  Michael Koch  <konqueror@gmx.de>
 
        * java/net/natInetAddressWin32.cc,
index c43d6b0..4329340 100644 (file)
@@ -1965,12 +1965,15 @@ gnu/gcj/protocol/http/Connection.java \
 gnu/gcj/protocol/http/Handler.java \
 gnu/gcj/protocol/jar/Connection.java \
 gnu/gcj/protocol/jar/Handler.java \
+gnu/gcj/protocol/gcjlib/Connection.java \
+gnu/gcj/protocol/gcjlib/Handler.java \
 gnu/gcj/runtime/FileDeleter.java \
 gnu/gcj/runtime/FinalizerThread.java \
 gnu/gcj/runtime/FirstThread.java \
 gnu/gcj/runtime/JNIWeakRef.java \
 gnu/gcj/runtime/MethodRef.java \
 gnu/gcj/runtime/NameFinder.java \
+gnu/gcj/runtime/SharedLibHelper.java \
 gnu/gcj/runtime/SharedLibLoader.java \
 gnu/gcj/runtime/StackTrace.java \
 gnu/gcj/runtime/StringBuffer.java \
index 2c5a932..df65652 100644 (file)
@@ -1727,12 +1727,15 @@ gnu/gcj/protocol/http/Connection.java \
 gnu/gcj/protocol/http/Handler.java \
 gnu/gcj/protocol/jar/Connection.java \
 gnu/gcj/protocol/jar/Handler.java \
+gnu/gcj/protocol/gcjlib/Connection.java \
+gnu/gcj/protocol/gcjlib/Handler.java \
 gnu/gcj/runtime/FileDeleter.java \
 gnu/gcj/runtime/FinalizerThread.java \
 gnu/gcj/runtime/FirstThread.java \
 gnu/gcj/runtime/JNIWeakRef.java \
 gnu/gcj/runtime/MethodRef.java \
 gnu/gcj/runtime/NameFinder.java \
+gnu/gcj/runtime/SharedLibHelper.java \
 gnu/gcj/runtime/SharedLibLoader.java \
 gnu/gcj/runtime/StackTrace.java \
 gnu/gcj/runtime/StringBuffer.java \
@@ -2752,6 +2755,8 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/gnu/gcj/protocol/core/natCoreInputStream.P \
 .deps/gnu/gcj/protocol/file/Connection.P \
 .deps/gnu/gcj/protocol/file/Handler.P \
+.deps/gnu/gcj/protocol/gcjlib/Connection.P \
+.deps/gnu/gcj/protocol/gcjlib/Handler.P \
 .deps/gnu/gcj/protocol/http/Connection.P \
 .deps/gnu/gcj/protocol/http/Handler.P \
 .deps/gnu/gcj/protocol/jar/Connection.P \
@@ -2760,6 +2765,7 @@ DEP_FILES =  .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
 .deps/gnu/gcj/runtime/FinalizerThread.P \
 .deps/gnu/gcj/runtime/FirstThread.P .deps/gnu/gcj/runtime/JNIWeakRef.P \
 .deps/gnu/gcj/runtime/MethodRef.P .deps/gnu/gcj/runtime/NameFinder.P \
+.deps/gnu/gcj/runtime/SharedLibHelper.P \
 .deps/gnu/gcj/runtime/SharedLibLoader.P \
 .deps/gnu/gcj/runtime/StackTrace.P .deps/gnu/gcj/runtime/StringBuffer.P \
 .deps/gnu/gcj/runtime/VMClassLoader.P \
index 15a7e5c..80d623c 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001  Free Software Foundation
+/* Copyright (C) 2001, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -14,5 +14,8 @@ public class Core
 
   public RawData ptr;
   public int length;
-}
 
+  Core ()
+  {
+  }
+}
index 75a7ad0..91b0247 100644 (file)
@@ -1,6 +1,6 @@
 // natCore -- C++ side of Core
 
-/* Copyright (C) 2001, 2002  Free Software Foundation
+/* Copyright (C) 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -21,40 +21,49 @@ details.  */
 #include <java/io/IOException.h>
 #include <gnu/gcj/Core.h>
 
-typedef struct core_chain_struct
+// List of global core values.
+static _Jv_core_chain *root;
+
+static void
+default_register_resource (_Jv_core_chain *node)
 {
-  int name_length;
-  const char *name;
-  int data_length;
-  const void *data;
-  
-  struct core_chain_struct *next;
-} core_chain;
+  node->next = root;
+  root = node;
+}
 
-static core_chain *root;
+// This is set only when a lock is held on java.lang.Class.
+// This function is called to handle a new core node.
+void (*_Jv_RegisterCoreHook) (_Jv_core_chain *) = default_register_resource;
 
-void _Jv_RegisterResource (void *vptr)
+void
+_Jv_RegisterResource (void *vptr)
 {
-  char *rptr = (char *)vptr;
+  char *rptr = (char *) vptr;
 
-  // These are permanent data structures for now.  This routine is
-  // called from a static constructor, so we shouldn't depend on too
-  // much existing infrastructure.
-  core_chain *cc = (core_chain *) _Jv_Malloc (sizeof (core_chain));
+  _Jv_core_chain *cc = (_Jv_core_chain *) _Jv_Malloc (sizeof (_Jv_core_chain));
 
   cc->name_length = ((int *)rptr)[0];
   cc->data_length = ((int *)rptr)[1];
-  cc->name = rptr + 2*sizeof(int);
+  cc->name = rptr + 2 * sizeof (int);
   cc->data = cc->name + cc->name_length;
+  cc->next = NULL;
 
-  // Add this new item to the chain...
-  core_chain *old_root = root;
-  cc->next = old_root;
-  root = cc;
+  (*_Jv_RegisterCoreHook) (cc);
 }
 
-gnu::gcj::Core *
-gnu::gcj::Core::create (jstring name)
+void
+_Jv_FreeCoreChain (_Jv_core_chain *chain)
+{
+  while (chain != NULL)
+    {
+      _Jv_core_chain *next = chain->next;
+      _Jv_Free (chain);
+      chain = next;
+    }
+}
+
+_Jv_core_chain *
+_Jv_FindCore (_Jv_core_chain *node, jstring name)
 {
   char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (name) + 1);
   jsize total = JvGetStringUTFRegion (name, 0, name->length(), buf);
@@ -68,23 +77,38 @@ gnu::gcj::Core::create (jstring name)
       --total;
     }
 
-  core_chain *node = root;
-
   while (node)
     {
       if (total == node->name_length
          && strncmp (buf, node->name, total) == 0)
-       {
-         gnu::gcj::Core *core = 
-           (gnu::gcj::Core *) _Jv_AllocObject(&gnu::gcj::Core::class$,
-                                              sizeof (gnu::gcj::Core));
-         core->ptr = (gnu::gcj::RawData *) node->data;
-         core->length = node->data_length;
-         return core;
-       }
-      else
-       node = node->next;
+       return node;
+      node = node->next;
+    }
+
+  return NULL;
+}
+
+gnu::gcj::Core *
+_Jv_create_core (_Jv_core_chain *node, jstring name)
+{
+  node = _Jv_FindCore (node, name);
+
+  gnu::gcj::Core *core = NULL;
+  if (node)
+    {
+      core = (gnu::gcj::Core *) _Jv_AllocObject(&gnu::gcj::Core::class$,
+                                               sizeof (gnu::gcj::Core));
+      core->ptr = (gnu::gcj::RawData *) node->data;
+      core->length = node->data_length;
     }
+  return core;
+}
 
-  throw new java::io::IOException (JvNewStringLatin1 ("can't open core"));
+gnu::gcj::Core *
+gnu::gcj::Core::create (jstring name)
+{
+  gnu::gcj::Core *core = _Jv_create_core (root, name);
+  if (core == NULL)
+    throw new java::io::IOException (JvNewStringLatin1 ("can't open core"));
+  return core;
 }
index 5bcbb86..95d7096 100644 (file)
@@ -1,6 +1,6 @@
 // Connection.java - Implementation of URLConnection for core protocol.
 
-/* Copyright (C) 2001  Free Software Foundation
+/* Copyright (C) 2001, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -55,7 +55,7 @@ class Connection extends URLConnection
 
     if (! doInput)
       throw new ProtocolException("Can't open InputStream if doInput is false");
-    return new BufferedInputStream(new CoreInputStream (core));
+    return new CoreInputStream (core);
   }
 
   // Override default method in URLConnection.
diff --git a/libjava/gnu/gcj/protocol/gcjlib/Connection.java b/libjava/gnu/gcj/protocol/gcjlib/Connection.java
new file mode 100644 (file)
index 0000000..0b76357
--- /dev/null
@@ -0,0 +1,60 @@
+// Connection.java - Implementation of URLConnection for gcjlib
+// protocol.
+
+/* Copyright (C) 2003  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.protocol.gcjlib;
+import java.io.*;
+import java.net.*;
+import gnu.gcj.Core;
+import gnu.gcj.protocol.core.CoreInputStream;
+import gnu.gcj.runtime.SharedLibHelper;
+
+/**
+ * @author Tom Tromey <tromey@redhat.com>
+ * @date January 10, 2003
+ */
+
+class Connection extends URLConnection
+{
+  String solib;
+  String name;
+  Core core;
+
+  public Connection (URL url) throws MalformedURLException
+  {
+    super (url);
+    int index = url.getFile().indexOf("!/");
+    if (index == -1)
+      throw new MalformedURLException("couldn't find !/ in gcjlib URL");
+
+    name = url.getFile().substring(index + 2);
+    solib = url.getFile().substring(0, index);
+  }
+
+  public void connect() throws IOException
+  {
+    if (core != null)
+      return;
+    // We can't create a new SharedLibHelper here, since we don't know
+    // what parent class loader to use.
+    SharedLibHelper helper = SharedLibHelper.findHelper(solib);
+    if (helper == null)
+      throw new IOException("library not loaded: " + solib);
+    core = helper.findCore(name);
+    if (core == null)
+      throw new IOException("couldn't find core object: " + name);
+  }
+
+  public InputStream getInputStream() throws IOException
+  {
+    connect();
+    return new CoreInputStream(core);
+  }
+}
diff --git a/libjava/gnu/gcj/protocol/gcjlib/Handler.java b/libjava/gnu/gcj/protocol/gcjlib/Handler.java
new file mode 100644 (file)
index 0000000..fe767cd
--- /dev/null
@@ -0,0 +1,24 @@
+// Handler.java - URLStreamHandler for gcjlib protocol.
+
+/* Copyright (C) 2003  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.protocol.gcjlib;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.io.IOException;
+
+public class Handler extends URLStreamHandler
+{
+  protected URLConnection openConnection(URL url) throws IOException
+  {
+    return new Connection(url);
+  }
+}
diff --git a/libjava/gnu/gcj/runtime/SharedLibHelper.java b/libjava/gnu/gcj/runtime/SharedLibHelper.java
new file mode 100644 (file)
index 0000000..9e170a1
--- /dev/null
@@ -0,0 +1,144 @@
+/* Copyright (C) 2001, 2003  Free Software Foundation
+
+   This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+details.  */
+
+package gnu.gcj.runtime;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.HashMap;
+import java.security.*;
+import gnu.gcj.Core;
+
+public class SharedLibHelper
+{
+  /** Load a shared library, and associate a ClassLoader with it.
+   * @param libname named of shared library (passed to dlopen)
+   * @param parent the parent ClassLoader
+   * @parem flags passed to dlopen
+   */
+  SharedLibHelper(String libname, ClassLoader parent, CodeSource source,
+                 int flags)
+  {
+    // FIXME: ask security manager first.
+    loader = parent;
+    baseName = libname;
+    domain = new ProtectionDomain(source,
+                                 Policy.getPolicy().getPermissions(source));
+    this.flags = flags;
+  }
+
+  public static SharedLibHelper findHelper (String libname)
+  {
+    synchronized (map)
+      {
+       WeakReference ref = (WeakReference) map.get(libname);
+       if (ref != null)
+         return (SharedLibHelper) ref.get();
+       return null;
+      }
+  }
+
+  public static SharedLibHelper findHelper (ClassLoader loader, String libname,
+                                           CodeSource source)
+  {
+    synchronized (map)
+      {
+       SharedLibHelper result;
+       WeakReference ref = (WeakReference) map.get(libname);
+       if (ref != null)
+         {
+           result = (SharedLibHelper) ref.get();
+           if (result != null)
+             {
+               if (result.loader != loader)
+                 // FIXME
+                 throw new UnknownError();
+               return result;
+             }
+         }
+
+       result = new SharedLibHelper(libname, loader, source, 0);
+       map.put(libname, new WeakReference(result));
+       return result;
+      }
+  }
+
+  public native void finalize ();
+
+  public Class findClass(String name)
+  {
+    ensureInit();
+    return (Class) classMap.get(name);
+  }
+
+  public URL findResource (String name)
+  {
+    ensureInit();
+    if (! hasResource(name))
+      return null;
+    try
+      {
+       return new URL("gcjlib", "", -1, baseName + "!/" + name);
+      }
+    catch (MalformedURLException _)
+      {
+      }
+    return null;
+  }
+
+  public native Core findCore (String name);
+
+  void ensureInit()
+  {
+    synchronized (classMap)
+      {
+       if (initialized)
+         return;
+       init();
+       initialized = true;
+      }
+  }
+
+  native boolean hasResource(String name);
+  native void init();
+
+  /** Called during dlopen's processing of the init section. */
+  void registerClass(String name, Class cls)
+  {
+    classMap.put(name, cls);
+  }
+
+  /** The handle returned by dlopen. */
+  gnu.gcj.RawData handler;
+
+  /** Holds a _Jv_core_chain for the loader.  */
+  gnu.gcj.RawData core_chain;
+
+  /** Map classnames to Classes. */
+  HashMap classMap = new HashMap(20);
+
+  /** Class loader we're helping.  */
+  ClassLoader loader;
+
+  /** Name of base file.  */
+  String baseName;
+
+  /** Protection domain for loaded classes.  */
+  ProtectionDomain domain;
+
+  /** Flags to pass to dlopen.  FIXME: platform dependent.
+      0 is always "sensible" (defined by us).  */
+  int flags;
+
+  /** True if we've been initialized.  */
+  boolean initialized = false;
+
+  /** Map shared library names to a helper object.  This uses weak
+      references in the values so we don't prevent collection.  */
+  static HashMap map = new HashMap ();
+}
index cfcd04e..1f80bbc 100644 (file)
@@ -7,7 +7,12 @@ Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 details.  */
 
 package gnu.gcj.runtime;
-import java.util.Hashtable;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.util.Enumeration;
+import java.util.Vector;
 
 /**
  * A ClassLoader backed by a gcj-compiled shared library.
@@ -16,55 +21,59 @@ import java.util.Hashtable;
 
 public class SharedLibLoader extends ClassLoader
 {
-  public native void finalize ();
-
-  /** Called during dlopen's processing of the init section. */
-  void registerClass(String name, Class cls)
-  {
-    classMap.put(name, cls);
-  }
-
   /** Load a shared library, and associate a ClassLoader with it.
    * @param libname named of shared library (passed to dlopen)
    * @param parent the parent ClassLoader
-   * @param flags passed to dlopen
+   * @parem flags passed to dlopen
    */
   public SharedLibLoader(String libname, ClassLoader parent, int flags)
   {
     super(parent);
-    init(libname, flags);
+    URL url;
+    try
+      {
+       url = new URL("file", "", libname);
+      }
+    catch (MalformedURLException _)
+      {
+       url = null;
+      }
+    helper = SharedLibHelper.findHelper(this, libname,
+                                       new CodeSource(url, null));
   }
 
-
   /** Load a shared library, and asociate a ClassLoader with it.
    * @param libname named of shared library (passed to dlopen)
    */
   public SharedLibLoader(String libname)
   {
-    super(getSystemClassLoader());
-    init(libname, 0);
-  }
-
-  native void init(String libname, int flags);
-
-  public Class loadClass(String name)
-    throws ClassNotFoundException
-  {
-    return super.loadClass(name);
+    this(libname, getSystemClassLoader(), 0);
   }
 
   public Class findClass(String name)
     throws ClassNotFoundException
   {
-    Object cls = classMap.get(name);
+    Class cls = helper.findClass(name);
     if (cls == null)
       throw new ClassNotFoundException(name);
-    return (Class) cls;
+    return cls;
   }
 
-  /** The handle returned by dlopen. */
-  gnu.gcj.RawData handler;
+  public URL findResource (String name)
+  {
+    return helper.findResource(name);
+  }
+
+  public Enumeration findResources (String name) throws IOException
+  {
+    URL url = findResource(name);
+    if (url == null)
+      return null;
+    Vector v = new Vector(1);
+    v.add(url);
+    return v.elements();
+  }
 
-  /** Map classnames to Classes. */
-  Hashtable classMap = new Hashtable(20);
+  /** The helper that does the work for us.  */
+  SharedLibHelper helper;
 }
index 49bcfb4..46eef75 100644 (file)
@@ -1,4 +1,4 @@
-// natSharedLibLoader.cc - Implementation of FirstThread native methods.
+// natSharedLibLoader.cc - Implementation of SharedLibHelper native methods.
 
 /* Copyright (C) 2001, 2003  Free Software Foundation
 
@@ -11,74 +11,113 @@ details.  */
 #include <config.h>
 
 #include <gcj/cni.h>
-#include <gnu/gcj/runtime/SharedLibLoader.h>
+#include <jvm.h>
+#include <gnu/gcj/runtime/SharedLibHelper.h>
 #include <java/io/IOException.h>
 #include <java/lang/UnsupportedOperationException.h>
-#include <java/lang/UnsatisfiedLinkError.h>
+#include <java/lang/UnknownError.h>
 
 #ifdef HAVE_DLOPEN
 #include <dlfcn.h>
 
 /* Only used during dlopen, while having a lock on Class.class. */
-static gnu::gcj::runtime::SharedLibLoader* curLoader;
+static java::lang::ClassLoader *curLoader;
+static gnu::gcj::runtime::SharedLibHelper *curHelper;
 
 typedef void (*ClassHookFunc) (jclass);
+typedef void (*CoreHookFunc) (_Jv_core_chain *);
+
+void
+_Jv_sharedlib_register_hook (jclass cls)
+{
+  curHelper->registerClass(cls->getName(), cls);
+  cls->protectionDomain = curHelper->domain;
+  cls->loader = curLoader;
+}
 
 static void
-::register_hook(jclass cls)
+core_hook (_Jv_core_chain *chain)
 {
-  curLoader->registerClass(cls->getName(), cls);
+  chain->next = (_Jv_core_chain *) curHelper->core_chain;
+  curHelper->core_chain = (gnu::gcj::RawData *) chain;
 }
 
 struct SharedLibDummy
 {
   ClassHookFunc saved;
+  CoreHookFunc saved_core;
   SharedLibDummy()
   {
     saved = _Jv_RegisterClassHook;
+    saved_core = _Jv_RegisterCoreHook;
   }
   ~SharedLibDummy()
   {
     _Jv_RegisterClassHook = saved;
+    _Jv_RegisterCoreHook = saved_core;
     curLoader = NULL;
   }
 };
 #endif
 
 void
-gnu::gcj::runtime::SharedLibLoader::init(jstring libname, jint flags)
+gnu::gcj::runtime::SharedLibHelper::init(void)
 {
 #ifdef HAVE_DLOPEN
-  jint len = _Jv_GetStringUTFLength (libname);
-  char lname[len + 1];
-  JvGetStringUTFRegion (libname, 0, libname->length(), lname);
-  lname[len] = '\0';
+  char *lname = (char *) __builtin_alloca (JvGetStringUTFLength (baseName)
+                                          + 1);
+  jsize total = JvGetStringUTFRegion (baseName, 0, baseName->length(), lname);
+  lname[total] = '\0';
 
   if (flags==0)
-    flags = RTLD_LAZY;
+    flags = RTLD_GLOBAL | RTLD_LAZY;
   JvSynchronize dummy1(&java::lang::Class::class$);
   SharedLibDummy dummy2;
-  curLoader = this;
-  _Jv_RegisterClassHook = ::register_hook;
+  curLoader = loader;
+  curHelper = this;
+  _Jv_RegisterClassHook = _Jv_sharedlib_register_hook;
+  _Jv_RegisterCoreHook = core_hook;
   void *h = dlopen(lname, flags);
   if (h == NULL)
     {
       const char *msg = dlerror();
-      jstring str = JvNewStringLatin1 (lname);
-      str = str->concat (JvNewStringLatin1 (": "));
-      str = str->concat (JvNewStringLatin1 (msg));
-      throw new java::lang::UnsatisfiedLinkError (str);
+      throw new java::lang::UnknownError(JvNewStringLatin1(msg));
     }
   handler = (gnu::gcj::RawData*) h;
 #else
-  const char *msg = "SharedLibLoader is not supported on this platform";
+  const char *msg
+    = "shared library class loading is not supported on this platform";
   throw new java::lang::UnsupportedOperationException(JvNewStringLatin1(msg));
 #endif
 }
 
+jboolean
+gnu::gcj::runtime::SharedLibHelper::hasResource (jstring name)
+{
+#ifdef HAVE_DLOPEN
+  _Jv_core_chain *node = _Jv_FindCore ((_Jv_core_chain *) core_chain, name);
+  return node != NULL;
+#else
+  return false;
+#endif
+}
+
+gnu::gcj::Core *
+gnu::gcj::runtime::SharedLibHelper::findCore (jstring name)
+{
+#ifdef HAVE_DLOPEN
+  extern gnu::gcj::Core *_Jv_create_core (_Jv_core_chain *node, jstring name);
+  ensureInit();
+  return _Jv_create_core ((_Jv_core_chain *) core_chain, name);
+#else
+  return NULL;
+#endif
+}
+
 void
-gnu::gcj::runtime::SharedLibLoader::finalize()
+gnu::gcj::runtime::SharedLibHelper::finalize()
 {
+  _Jv_FreeCoreChain ((_Jv_core_chain *) core_chain);
 #ifdef HAVE_DLOPEN
   dlclose (handler);
 #endif
index 9af9dc7..a114e55 100644 (file)
@@ -466,6 +466,22 @@ bool _Jv_VerifyClassName (_Jv_Utf8Const *name);
 bool _Jv_VerifyIdentifier (_Jv_Utf8Const *);
 bool _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2);
 
+struct _Jv_core_chain
+{
+  int name_length;
+  const char *name;
+  int data_length;
+  const void *data;
+
+  struct _Jv_core_chain *next;
+};
+
+// This is called when new core data is loaded.
+extern void (*_Jv_RegisterCoreHook) (_Jv_core_chain *);
+
+_Jv_core_chain *_Jv_FindCore (_Jv_core_chain *node, jstring name);
+void _Jv_FreeCoreChain (_Jv_core_chain *chain);
+
 #ifdef ENABLE_JVMPI
 
 #include "jvmpi.h"
index 06c9c80..9bcff6f 100644 (file)
@@ -369,6 +369,8 @@ private:
   friend class gnu::gcj::runtime::StackTrace;
   friend class java::io::VMObjectStreamClass;
 
+  friend void _Jv_sharedlib_register_hook (jclass klass);
+
   // Chain for class pool.
   jclass next;
   // Name of class.
index 9a468bf..e1c789d 100644 (file)
@@ -1,5 +1,5 @@
 /* URLClassLoader.java --  ClassLoader that loads classes from one or more URLs
-   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -59,6 +59,7 @@ import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
+import gnu.gcj.runtime.SharedLibHelper;
 
 /**
  * A secure class loader that can load classes and resources from
@@ -194,6 +195,17 @@ public class URLClassLoader extends SecureClassLoader
     }
 
     /**
+     * Returns a <code>Class</code> loaded by this
+     * <code>URLLoader</code>, or <code>null</code> when this loader
+     * either can't load the class or doesn't know how to load classes
+     * at all.
+     */
+    Class getClass(String className)
+    {
+      return null;
+    }
+
+    /**
      * Returns a <code>Resource</code> loaded by this
      * <code>URLLoader</code>, or <code>null</code> when no
      * <code>Resource</code> with the given name exists.
@@ -282,7 +294,7 @@ public class URLClassLoader extends SecureClassLoader
     {
       super(classloader, baseURL);
 
-      // cache url prefix for all resources in this jar url
+      // Cache url prefix for all resources in this jar url.
       String external = baseURL.toExternalForm();
       StringBuffer sb = new StringBuffer(external.length() + 6);
       sb.append("jar:");
@@ -448,12 +460,12 @@ public class URLClassLoader extends SecureClassLoader
     {
       return stream;
     }
-                        
+
     public int getLength()
     {
       return length;
     }
-                
+
     public URL getURL()
     {
       return url;
@@ -461,6 +473,63 @@ public class URLClassLoader extends SecureClassLoader
   }
 
   /**
+   * A <code>SoURLLoader</code> is a type of <code>URLLoader</code>
+   * that loads classes and resources from a shared library.
+   */
+  final static class SoURLLoader extends URLLoader
+  {
+    SharedLibHelper helper;
+
+    SoURLLoader(URLClassLoader classloader, URL url)
+    {
+      super(classloader, url);
+      helper = SharedLibHelper.findHelper(classloader, url.getFile(),
+                                         noCertCodeSource);
+    }
+
+    Class getClass(String className)
+    {
+      return helper.findClass(className);
+    }
+
+    Resource getResource(String name)
+    {
+      URL url = helper.findResource(name);
+      if (url == null)
+       return null;
+      return new SoResource(this, name, url);
+    }
+  }
+
+  final static class SoResource extends Resource
+  {
+    SoResource(SoURLLoader loader, String name, URL url)
+    {
+      super(loader, name);
+      this.url = url;
+    }
+
+    InputStream getInputStream() throws IOException
+    {
+      URLConnection conn = url.openConnection();
+      return conn.getInputStream();
+    }
+
+    public int getLength()
+    {
+      // FIXME we could find this by asking the core object.
+      return -1;
+    }
+
+    public URL getURL ()
+    {
+      return url;
+    }
+
+    final URL url;
+  }
+
+  /**
    * A <code>FileURLLoader</code> is a type of <code>URLLoader</code>
    * only loading from file url.
    */
@@ -644,7 +713,7 @@ public class URLClassLoader extends SecureClassLoader
     //   for cache initial size
     synchronized(factoryCache)
       {
-       if(factory != null && factoryCache.get(factory) == null)
+       if (factory != null && factoryCache.get(factory) == null)
          factoryCache.put(factory, new HashMap(5));
       }
   }
@@ -667,21 +736,24 @@ public class URLClassLoader extends SecureClassLoader
        if (newUrl == null)
          return; // Silently ignore...
         
-       // check global cache to see if there're already url loader
-       // for this url
+       // Check global cache to see if there're already url loader
+       // for this url.
        URLLoader loader = (URLLoader)urlloaders.get(newUrl);
        if (loader == null)
          {
            String file = newUrl.getFile();
+           String protocol = newUrl.getProtocol();
            // Check that it is not a directory
-           if (! (file.endsWith("/") || file.endsWith(File.separator)))
+           if ("gcjlib".equals(protocol))
+             loader = new SoURLLoader(this, newUrl);
+           else if (! (file.endsWith("/") || file.endsWith(File.separator)))
              loader = new JarURLLoader(this, newUrl);
-           else if ("file".equals(newUrl.getProtocol()))
+           else if ("file".equals(protocol))
              loader = new FileURLLoader(this, newUrl);
            else
              loader = new RemoteURLLoader(this, newUrl);
 
-           // cache it
+           // Cache it.
            urlloaders.put(newUrl, loader);
          }
 
@@ -764,7 +836,20 @@ public class URLClassLoader extends SecureClassLoader
   {
     // Just try to find the resource by the (almost) same name
     String resourceName = className.replace('.', '/') + ".class";
-    Resource resource = findURLResource(resourceName);
+    int max = urls.size();
+    Resource resource = null;
+    for (int i = 0; i < max && resource == null; i++)
+      {
+       URLLoader loader = (URLLoader)urlinfos.elementAt(i);
+       if (loader == null)
+         continue;
+
+       Class k = loader.getClass(className);
+       if (k != null)
+         return k;
+
+       resource = loader.getResource(resourceName);
+      }
     if (resource == null)
       throw new ClassNotFoundException(className + " not found in " + urls);
 
@@ -907,12 +992,12 @@ public class URLClassLoader extends SecureClassLoader
     URLStreamHandler handler;
     synchronized (factoryCache)
       {
-       // check if there're handler for the same protocol in cache
+       // Check if there're handler for the same protocol in cache.
        HashMap cache = (HashMap)factoryCache.get(factory);
        handler = (URLStreamHandler)cache.get(protocol);
        if(handler == null)
          {
-           // add it to cache
+           // Add it to cache.
            handler = factory.createURLStreamHandler(protocol);
            cache.put(protocol, handler);
          }
@@ -971,23 +1056,23 @@ public class URLClassLoader extends SecureClassLoader
     // First get the permissions that would normally be granted
     PermissionCollection permissions = super.getPermissions(source);
         
-    // Now add the any extra permissions depending on the URL location
+    // Now add any extra permissions depending on the URL location.
     URL url = source.getLocation();
     String protocol = url.getProtocol();
     if (protocol.equals("file"))
       {
        String file = url.getFile();
-       // If the file end in / it must be an directory
+       // If the file end in / it must be an directory.
        if (file.endsWith("/") || file.endsWith(File.separator))
          {
            // Grant permission to read everything in that directory and
-           // all subdirectories
+           // all subdirectories.
            permissions.add(new FilePermission(file + "-", "read"));
          }
        else
          {
-           // It is a 'normal' file
-           // Grant permission to access that file
+           // It is a 'normal' file.
+           // Grant permission to access that file.
            permissions.add(new FilePermission(file, "read"));
          }
       }