/*
 * java.lang.ClassLoader.c
 *
 * Copyright (c) 1996,97 T. J. Wilkinson & Associates, London, UK.
 *
 * See the file "lib-license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Written by Tim Wilkinson <tim@tjwassoc.co.uk>
 */

#include "config.h"
#include "config-std.h"
#include "config-mem.h"
#include "../../../../kaffe/kaffevm/gtypes.h"
#include "../../../../kaffe/kaffevm/file.h"
#include "../../../../kaffe/kaffevm/readClass.h"
#include "../../../../kaffe/kaffevm/constants.h"
#include "../../../../kaffe/kaffevm/access.h"
#include "../../../../kaffe/kaffevm/classMethod.h"
#include "../../../../kaffe/kaffevm/object.h"
#include "../../../../kaffe/kaffevm/itypes.h"
#include <native.h>
#include "defs.h"

extern Hjava_lang_Class ClassClass;

extern classFile findInJar(char*);

/*
 * Initialise this class loader.
 */
void
java_lang_ClassLoader_init(struct Hjava_lang_ClassLoader* this)
{
	/* Does nothing */
}

/*
 * Translate an array of bytes into a class.
 */
struct Hjava_lang_Class*
java_lang_ClassLoader_defineClass0(struct Hjava_lang_ClassLoader* this, HArrayOfByte* data, jint offset, jint length)
{
	Hjava_lang_Class* clazz;
	classFile hand;
	hand.base = &unhand(data)->body[offset];
	hand.buf = hand.base;
	hand.size = length;

	clazz = (Hjava_lang_Class*)newObject(&ClassClass);
	return (readClass(clazz, &hand, this));
}

/*
 * Resolve classes reference by this class.
 */
void
java_lang_ClassLoader_resolveClass0(struct Hjava_lang_ClassLoader* this, struct Hjava_lang_Class* class)
{
	processClass(class, CSTATE_LINKED);
}

/*
 * Load a system class.
 */
struct Hjava_lang_Class*
java_lang_ClassLoader_findSystemClass0(struct Hjava_lang_ClassLoader* this, struct Hjava_lang_String* str)
{
	int len = javaStringLength(str);
	Utf8Const* c;
	char* name;
#if INTERN_UTF8CONSTS
	char buffer[100];
	if (len <= 100) {
		name = buffer;
	}
	else {
		name = malloc (len);
	}
#else
	c = malloc(sizeof(Utf8Const) + len + 1);
	name = c->data;
#endif
        javaString2CString(str, name, len+1);
	classname2pathname (name, name);
#if INTERN_UTF8CONSTS
	c = makeUtf8Const (name, len);
	if (name != buffer) {
		free(name);
	}
#else /* ! INTERN_UTF8CONSTS */
	c->length = len;
	c->hash = (uint16) hashUtf8String (name, len);
#endif /* ! INTERN_UTF8CONSTS */
	return (loadClass(c, 0));
}

/*
 * Locate the requested resource in the current Jar files and create a
 *  stream to the data.
 */
struct Hjava_io_InputStream*
java_lang_ClassLoader_getSystemResourceAsStream0(struct Hjava_lang_String* str)
{
	char* name;
	struct Hjava_io_InputStream* in;
	classFile hand;
	HArrayOfByte* data;

	in = NULL;
	name = makeCString(str);
	hand = findInJar(name);
	free(name);
	if (hand.type == 0) {
		return (NULL);
	}

	/* Copy data from returned buffer into Java byte array.  Be nice
	 * to avoid this copy but we cannot for the moment.
	 */
	data = (HArrayOfByte*)AllocArray(hand.size, TYPE_Byte);
	memcpy(unhand(data)->body, hand.buf, hand.size);
	if (hand.base != NULL) {
		free(hand.base);
	}

	/* Create input stream using byte array */
	in = (struct Hjava_io_InputStream*)execute_java_constructor(NULL, "java.io.ByteArrayInputStream", NULL, "([B)V", data);
	return (in);
}

/*
 * ???
 */
struct Hjava_lang_String*
java_lang_ClassLoader_getSystemResourceAsName0(struct Hjava_lang_String* str)
{
	return (NULL);
}
