1 // Native code for VMClassLoader
2 
3 /* Copyright (C) 2002, 2003  Free Software Foundation
4 
5    This file is part of libgcj.
6 
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10 
11 #include <config.h>
12 
13 #include <gcj/cni.h>
14 #include <jvm.h>
15 
16 #include <gnu/gcj/runtime/VMClassLoader.h>
17 #include <java/lang/Class.h>
18 #include <java/lang/StringBuffer.h>
19 #include <java/net/URLClassLoader.h>
20 #include <java/lang/Runtime.h>
21 #include <java/util/HashSet.h>
22 
23 jclass
findClass(jstring name)24 gnu::gcj::runtime::VMClassLoader::findClass (jstring name)
25 {
26   _Jv_Utf8Const *name_u = _Jv_makeUtf8Const (name);
27   jclass klass = _Jv_FindClassInCache (name_u, 0);
28 
29   if (! klass && lib_control != LIB_NEVER)
30     {
31       // Turn `gnu.pkg.quux' into `lib-gnu-pkg-quux'.  Then search for
32       // a module named (eg, on Linux) `lib-gnu-pkg-quux.so', followed
33       // by `lib-gnu-pkg.so' and `lib-gnu.so'.  If loading one of
34       // these causes the class to appear in the cache, then use it.
35       java::lang::StringBuffer *sb = new java::lang::StringBuffer (JvNewStringLatin1("lib-"));
36       // Skip inner classes
37       jstring cn;
38       jint ci = name->indexOf('$');
39       if (ci == -1)
40 	cn = name;
41       else
42 	cn = name->substring (0, ci);
43       jstring so_base_name = (sb->append (cn)->toString ())->replace ('.', '-');
44 
45       using namespace ::java::lang;
46       Runtime *rt = Runtime::getRuntime();
47 
48       // Compare against `3' because that is the length of "lib".
49       while (! klass && so_base_name && so_base_name->length() > 3)
50 	{
51 	  if (lib_control == LIB_CACHE)
52 	    {
53 	      // If we've already tried this name, we're done.
54 	      if (tried_libraries->contains(so_base_name))
55 		break;
56 	      tried_libraries->add(so_base_name);
57 	    }
58 
59 	  jboolean loaded = rt->loadLibraryInternal (so_base_name);
60 
61 	  jint nd = so_base_name->lastIndexOf ('-');
62 	  if (nd == -1)
63 	    so_base_name = NULL;
64 	  else
65 	    so_base_name = so_base_name->substring (0, nd);
66 
67 	  if (loaded)
68 	    klass = _Jv_FindClassInCache (name_u, 0);
69 	}
70     }
71 
72   // Now try loading using the interpreter.
73   if (! klass)
74     klass = java::net::URLClassLoader::findClass (name);
75 
76   return klass;
77 }
78