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