findinjar.c

来自「基于LWVCL开发的库」· C语言 代码 · 共 790 行 · 第 1/2 页

C
790
字号
/* * 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"#include "defs.h"#if defined(HAVE_SYS_TYPES_H)#include <sys/types.h>#endif /* defined(HAVE_SYS_TYPES_H) */#include <zzip/zzip.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	"rt.jar"classpathEntry* classpath;const char* realClassPath;char* realBootClassPath;void initClasspath(void);static int getClasspathType(const char*);static 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 char* getManifestMainAttribute(ZZIP_DIR*, const 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 = NULL;	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.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_NULLCLASS) {		discardErrorInfo(einfo);		postExceptionMessage(einfo, JAVA_LANG(ClassFormatError),				"Class %s has a null length",				centry->name->data);		return (NULL);	}	if (hand.type == CP_INVALID) {		/* We should only throw a ClassNotFoundException. */		discardErrorInfo(einfo);		postExceptionMessage(einfo,				     JAVA_LANG(ClassNotFoundException),				     "%s",				     centry->name->data);		return (NULL);	}	switch (hand.type) {	case CP_DIR:	case CP_ZIPFILE:		class = newClass();		if (class == NULL) {			postOutOfMemory(einfo);			KFREE(hand.mem);			return (NULL);		}		utf8ConstAssign(class->name, centry->name);		class->centry = centry;		class = readClass(class, &hand, NULL, einfo);		if (hand.base != NULL) {#if defined(KAFFE_STATS)			if (hand.type == CP_ZIPFILE) {				addToCounter(&jarmem, "vmmem-jar files", 1,					-(jlong)GCSIZEOF(hand.base));			}#endif			KFREE(hand.mem);		}		return (class);	case CP_INVALID:	case CP_SOFILE:	case CP_BYTEARRAY:	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);		KAFFEVM_ABORT();	}	return (NULL);}static iStaticLock	jarlock;/* * 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;	classpathEntry* ptr;	int i;	int rc;	/* 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:		{		        ZZIP_FILE * entry;			unsigned char* data;			zzip_size_t length;DBG(CLASSLOOKUP,	dprintf("Opening JAR file %s for %s\n", ptr->path, cname); );			if (ptr->u.jar == 0) {				ptr->u.jar = zzip_opendir(ptr->path);				if (ptr->u.jar == 0) {					break;				}#if defined(HANDLE_MANIFEST_CLASSPATH)				/* handle Manifest Class-Path attribute */				handleManifestClassPath (ptr);#endif			}			entry = zzip_file_open(ptr->u.jar, cname, 0);			if (entry == 0) {				break;			}			length = getUncompressedSize(entry);			if (0 == length) {				hand->type = CP_NULLCLASS;				goto done;			}			data = getDataJarFile(entry);			zzip_file_close(entry);			if (data == 0) {				postExceptionMessage(einfo,					JAVA_IO(IOException),					"Couldn't extract data from jar %s",					ptr->path);				goto done;			}			classFileInit(hand,				      data,				      data,				      length,				      CP_ZIPFILE);			if (Kaffe_JavaVMArgs.enableVerboseClassloading) {				dprintf("Loading %s(%s)\n", cname, ptr->path);			}			goto done;		}		case CP_DIR:		{			struct stat sbuf;			unsigned 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((size_t)sbuf.st_size);				if (data == 0) {					postOutOfMemory(einfo);					goto done;				}			}			i = 0;			while (i < sbuf.st_size) {				ssize_t j;				rc = KREAD(fp, data, (size_t)(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,				      data,				      (unsigned)sbuf.st_size,				      CP_DIR);			KCLOSE(fp);			if (Kaffe_JavaVMArgs.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){	const char* cp;	const char* hm;	size_t len;	classpathEntry* ptr;	DBG(INIT, dprintf("initClasspath()\n"); );	cp = Kaffe_JavaVMArgs.bootClasspath;	hm = Kaffe_JavaVMArgs.classhome;	initStaticLock(&jarlock);	if (cp != NULL && 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);           }        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?