Here's a patch which takes into account the classpath entries specified in a 
jar's manifest. I have included a jar with a very simple test case.

Regards,

Carlos Valiente <[EMAIL PROTECTED]>
? kaffe-classpath.diff
Index: kaffe/kaffevm/findInJar.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/findInJar.c,v
retrieving revision 1.44
diff -u -r1.44 findInJar.c
--- kaffe/kaffevm/findInJar.c	2000/09/09 18:06:34	1.44
+++ kaffe/kaffevm/findInJar.c	2001/05/17 18:42:23
@@ -168,9 +168,12 @@
 	classFile hand;
 	ssize_t j;
 	jarEntry* entry;
+	char *mfclasspath;
+	char *jardir;
 	static iLock* jarlock;
 	classpathEntry* ptr;
-	int i;
+	classpathEntry* newEntry;
+	int i, l;
 	int rc;
 	int iLockRoot;
 
@@ -182,6 +185,7 @@
 	lockStaticMutex(&jarlock);
 
 	for (ptr = classpath; ptr != 0; ptr = ptr->next) {
+DBG(CLASSLOOKUP,dprintf("Processing classpath entry '%s'\n", ptr->path);	)
 		hand.type = ptr->type;
 		switch (ptr->type) {
 		case CP_ZIPFILE:
@@ -195,7 +199,74 @@
 
 			entry = lookupJarFile(ptr->u.jar, cname);
 			if (entry == 0) {
-				break;
+				/* Entry was not there; see if there's a Class-Path
+				   attribute in the manifest and have a look there */
+				mfclasspath = getManifestMainAttribute(ptr->u.jar, "Class-Path");
+				if(mfclasspath == 0)
+					break;
+DBG(CLASSLOOKUP,		dprintf("%s: Manifest 'Class-Path' attribute is '%s'\n", ptr->path, mfclasspath);	)
+
+				buf = mfclasspath;
+				while(*mfclasspath) {
+					while(*mfclasspath != ' ' &&
+						*mfclasspath != '\t' &&
+						*mfclasspath != '\0')
+						++mfclasspath;
+						
+					*mfclasspath = '\0';
+
+					/* Insert manifest classpath entries */
+					
+					newEntry = KMALLOC(sizeof(classpathEntry));
+					newEntry->u.jar = 0;
+					
+					/* Manifest classpath entries can be either
+					absolute or relative to the location
+					of the jar file. */
+					
+					if(buf[0] != file_separator[0]) {
+						/* Path is relative. First, get the directory
+						of the jar file */
+						jardir = KMALLOC(PATH_MAX);
+						strcpy(jardir, ptr->path);
+						l = strlen(jardir - 1);
+						while(jardir[l] != file_separator[0] &&
+							l > 0)
+							--l;
+						jardir[l] = '\0';
+
+						/* Now build entry's path */
+						newEntry->path = KMALLOC(PATH_MAX);
+						if(jardir[0] != '\0')
+							sprintf(newEntry->path, "%s%s%s", jardir, file_separator, buf);
+						else
+							strcpy(newEntry->path, buf);
+					}
+					else {
+						/* Path is absolute */
+						newEntry->path = KMALLOC(strlen(buf) + 1);
+						strcpy(newEntry->path, buf);
+					}
+
+					/* Check whether it's a jar or a directory */
+					rc = KOPEN(newEntry->path, O_RDONLY, 0, &fp);
+					if(rc == 0) {
+						rc = KFSTAT(fp, &sbuf);
+						if(rc == 0) {
+							newEntry->type = S_ISDIR(sbuf.st_mode) ? 
+										CP_DIR: CP_ZIPFILE;
+										
+							/* OK, insert the new entry after the current one */
+							newEntry->next = ptr->next;
+							ptr->next = newEntry;
+						}
+						KCLOSE(fp);
+					}
+					
+					/* Go to the following classpath element */
+					buf = mfclasspath;
+				} 
+				continue;
 			}
 			hand.base = getDataJarFile(ptr->u.jar, entry);
 			if (hand.base == 0) {
Index: kaffe/kaffevm/jar.c
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jar.c,v
retrieving revision 1.18
diff -u -r1.18 jar.c
--- kaffe/kaffevm/jar.c	2000/08/26 22:21:56	1.18
+++ kaffe/kaffevm/jar.c	2001/05/17 18:42:24
@@ -322,6 +322,58 @@
 	}
 }
 
+uint8* getManifestMainAttribute(jarFile* file, char* attrName)
+{
+	jarEntry* mf;
+	uint8* mfdata;
+	uint8* attrEntry;
+	uint8* ret;
+	int i, posAttrValue;
+	
+	/* Locate manifest entry in jar */
+	mf = lookupJarFile(file, "META-INF/MANIFEST.MF");
+	if(mf == 0)
+		return (0);
+	
+	/* Read it */
+	mfdata = getDataJarFile(file, mf);
+	if(mfdata == 0)
+		return (0);
+	
+	/* Look for the desired entry */
+	attrEntry = mfdata;
+	for(i = 0; i < mf->uncompressedSize; ++i) {
+		if(mfdata[i] == '\n') {
+			mfdata[i] = '\0';
+			/* Ecco! this line begins with the attribute's name */
+			if(strstr(attrEntry, attrName)) {
+				/* Skip 'attrName:' */
+				posAttrValue = strlen(attrName) + 1;
+				attrEntry += posAttrValue;
+				
+				/* Skip initial whitespace */
+				while(*attrEntry == ' ' ||
+					*attrEntry == '\t')
+					++attrEntry;
+				
+				/* Now look for end of string */
+				while(attrEntry[i] != '\n' && i < mf->uncompressedSize)
+					++i;
+				attrEntry[i] = '\0';
+				
+				/* OK, allocate memory for the result and return */
+				ret = KMALLOC(strlen(attrEntry) + 1);
+				strcpy(ret, attrEntry);
+				KFREE(mfdata);
+				return ret;
+			}
+			attrEntry = mfdata + i + 1;
+		}
+	}
+	KFREE(mfdata);
+	return (0);
+}
+
 void
 closeJarFile(jarFile* file)
 {
Index: kaffe/kaffevm/jar.h
===================================================================
RCS file: /cvs/kaffe/kaffe/kaffe/kaffevm/jar.h,v
retrieving revision 1.5
diff -u -r1.5 jar.h
--- kaffe/kaffevm/jar.h	2000/10/05 22:24:05	1.5
+++ kaffe/kaffevm/jar.h	2001/05/17 18:42:25
@@ -141,5 +141,6 @@
 void		closeJarFile(jarFile*);
 jarEntry*	lookupJarFile(jarFile*, char*);
 uint8*		getDataJarFile(jarFile*, jarEntry*);
+uint8*		getManifestMainAttribute(jarFile*, char*);
 
 #endif

ClassPathMF.jar

Reply via email to