📄 findinjar.c
字号:
/* * findInJar.c * Search the CLASSPATH for the given class or property name. * * Copyright (c) 1996, 1997, 1998, 1999 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. */#include "config.h"#include "debug.h"#include "config-std.h"#include "config-io.h"#include "config-mem.h"#include "gtypes.h"#include "support.h"#include "file.h"#include "exception.h"#include "readClass.h"#include "system.h"#include "errors.h"#include "lerrno.h"#include "locks.h"#include "files.h"#include "baseClasses.h"#include "classMethod.h"#include "external.h"#include "jar.h"#include "jsyscall.h"#include "jni.h"#include "classpath.h"#include "stringSupport.h"#include "stats.h"#include "access.h"#include "gcj/gcj.h"#ifdef __riscos__#include <unixlib/local.h>#endif/* Handle Manifest Class-Path attribute. It will be better to handle that in a ClassLoader. */#define HANDLE_MANIFEST_CLASSPATH 1#define KLASSES_JAR "Klasses.jar"classpathEntry* classpath;char* realClassPath;char* realBootClassPath;void initClasspath(void);static int getClasspathType(const char*);#if 0static void generateMangledName(char*, const char*);#endifstatic void discoverClasspath(const char*);static void makeClasspath(char*);static void findClassInJar(char*, classFile*, struct _errorInfo*);static int insertClasspath(const char* cp, int prepend);#if defined(HANDLE_MANIFEST_CLASSPATH)static int isEntryInClasspath(const char*);static uint8* getManifestMainAttribute(jarFile*, char*);static void handleManifestClassPath (classpathEntry *);#endif/* * Find the named class in a directory or JAR file. * Returns class if successful, NULL otherwise. */Hjava_lang_Class*findClass(classEntry* centry, errorInfo *einfo){ char *buf; classFile hand; const char* cname; Hjava_lang_Class* class = 0; cname = centry->name->data;#if defined(HAVE_GCJ_SUPPORT) /* * XXX: for now, prefer *any* classes given in a .so file * What we really want is to have separate lists for each .so module * so that we can search for classes in the order that the classpath * specifies. * A good reimplementation would use a global hashtable to map * all available names to the sources from which they'd be loaded. */ class = gcjFindClassByUtf8Name(cname, einfo); if (class != 0) { if (Kaffe_JavaVMArgs[0].enableVerboseClassloading) { /* XXX could say from where, but see above */ dprintf("Loading precompiled %s\n", cname); }DBG(GCJ, dprintf(__FUNCTION__": adding class %s to pool@%p\n", cname, centry); ) class->centry = centry; assert(CLASS_GCJ(class)); return (class); }#endif /* Look for the class */DBG(CLASSLOOKUP, dprintf("Scanning for class %s\n", cname); ) buf = checkPtr(KMALLOC(strlen(cname) + 8)); sprintf(buf, "%s.class", cname); /* Find class in Jar file */ findClassInJar(buf, &hand, einfo); KFREE(buf); if (hand.type == CP_INVALID) { /* We should only throw a ClassNotFoundException. */ discardErrorInfo(einfo); postExceptionMessage(einfo, JAVA_LANG(ClassNotFoundException), "%s", centry->name->data); return (0); } switch (hand.type) { case CP_DIR: case CP_ZIPFILE: class = newClass(); if (class == 0) { postOutOfMemory(einfo); KFREE(hand.base); return (0); } utf8ConstAssign(class->name, centry->name); class->centry = centry; class = readClass(class, &hand, NULL, einfo); if (hand.base != 0) {#if defined(KAFFE_STATS) if (hand.type == CP_ZIPFILE) { addToCounter(&jarmem, "vmmem-jar files", 1, -(jlong)GCSIZEOF(hand.base)); }#endif KFREE(hand.base); } return (class); default: break; } /* * Certain classes are essential. If we don't find them then * abort. Note that loadStaticClass will abort for essential * classes, so we only have to check for these two here. */ if (strcmp(cname, "java/lang/ClassNotFoundException") == 0 || strcmp(cname, "java/lang/Object") == 0) { dprintf("Cannot find essential class '%s' in class library ... aborting.\n", cname); ABORT(); } return (0);}/* * Locate the given name in the CLASSPATH. Fill in the provided * classFile handle with a buffer containing the class (or * set the hand->type to CP_INVALID). * * May write into cname. */static voidfindClassInJar(char* cname, classFile* hand, errorInfo *einfo){ char *buf; int fp; static iStaticLock jarlock; classpathEntry* ptr; int i; int rc; int iLockRoot; /* Look for the class */DBG(CLASSLOOKUP, dprintf("Scanning for element %s\n", cname); ); hand->type = CP_INVALID; /* One into the jar at once */ lockStaticMutex(&jarlock); for (ptr = classpath; ptr != 0; ptr = ptr->next) {DBG(CLASSLOOKUP,dprintf("Processing classpath entry '%s'\n", ptr->path); ) switch (ptr->type) { case CP_ZIPFILE: { jarEntry* entry; const char* data;DBG(CLASSLOOKUP, dprintf("Opening JAR file %s for %s\n", ptr->path, cname); ) if (ptr->u.jar == 0) { ptr->u.jar = openJarFile(ptr->path); if (ptr->u.jar == 0) { break; }#if defined(HANDLE_MANIFEST_CLASSPATH) /* handle Manifest Class-Path attribute */ handleManifestClassPath (ptr);#endif } entry = lookupJarFile(ptr->u.jar, cname); if (entry == 0) { break; } data = getDataJarFile(ptr->u.jar, entry); if (data == 0) { postExceptionMessage(einfo, JAVA_IO(IOException), "Couldn't extract data from jar: %s", ptr->u.jar->error); goto done; } classFileInit(hand, data, entry->uncompressedSize, CP_ZIPFILE); if (Kaffe_JavaVMArgs[0].enableVerboseClassloading) { dprintf("Loading %s(%s)", cname, ptr->path); if (entry->compressionMethod != COMPRESSION_STORED) { dprintf(" [compressed]"); } dprintf("\n"); } goto done; } case CP_DIR: { struct stat sbuf; char* data; buf = checkPtr(KMALLOC(strlen(ptr->path) + strlen(file_separator) + strlen(cname) + 1)); sprintf(buf, "%s%s%s", ptr->path, file_separator, cname);DBG(CLASSLOOKUP, dprintf("Opening java file %s for %s\n", buf, cname); ) rc = KOPEN(buf, O_RDONLY|O_BINARY, 0, &fp); KFREE(buf); /* if we can't open the file, we keep looking */ if (rc) { break; /* will be NoClassDefFoundError */ } /* if we can open the file, but cannot stat or read it, * we flag an IOException (!?) */ if ((rc = KFSTAT(fp, &sbuf)) != 0) { KCLOSE(fp); postExceptionMessage(einfo, JAVA_IO(IOException), "Couldn't fstat: %s", SYS_ERROR(rc)); goto done; } /* * XXX Whlist bogus, a zero-length class file poses * no problems for this code. Assume the user of * the file will find that problem... */ data = NULL; if (sbuf.st_size > 0) { data = KMALLOC(sbuf.st_size); if (data == 0) { postOutOfMemory(einfo); goto done; } } i = 0; while (i < sbuf.st_size) { ssize_t j; rc = KREAD(fp, data, sbuf.st_size - i, &j); if (rc != 0) { postExceptionMessage(einfo, JAVA_IO(IOException), "Couldn't read: %s", SYS_ERROR(rc)); KFREE(data); break; } else { if (j > 0) { /* more data */ i += j; } else { /* end of file */ break; } } } classFileInit(hand, data, sbuf.st_size, CP_DIR); KCLOSE(fp); if (Kaffe_JavaVMArgs[0].enableVerboseClassloading) { dprintf("Loading %s\n", cname); } goto done; } /* Ignore bad entries */ default: /* XXX warning.... */ break; } } /* If we call out the loop then we didn't find anything */ assert (hand->type == CP_INVALID); /* cut off the ".class" suffix for the exception msg */ cname[strlen(cname) - strlen(".class")] = '\0'; /* * Technically, we're just loading a file, so use * FileNotFoundException. */ postExceptionMessage(einfo, JAVA_IO(FileNotFoundException), "%s", cname); done:; unlockStaticMutex(&jarlock);}/* * Initialise class path. */voidinitClasspath(void){ char* cp; char* hm; int len; classpathEntry* ptr; DBG(INIT, dprintf("initClasspath()\n"); ) cp = (char*)Kaffe_JavaVMArgs[0].bootClasspath; hm = (char*)Kaffe_JavaVMArgs[0].classhome; if (cp != 0 && cp[0] != '\0') { /* cp may reside in read-only memory, but * makeClasspath writes to it */ char *writable_cp = KMALLOC(strlen(cp) + 1); strcpy(writable_cp, cp); makeClasspath(writable_cp); KFREE(writable_cp); } else if(hm) { discoverClasspath(hm); } len = 0; for (ptr = classpath; ptr != 0; ptr = ptr->next) { len += strlen(ptr->path) + 1; } if (len == 0) { /* Error on classpath will be reported latter */ realBootClassPath = ""; return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -