Milán Major

netscape-revival

1 branch
Code

sun-java/runtime/class.c

/*
 * @(#)class.c	1.44 95/11/15  
 *
 * Copyright (c) 1994 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies. Please refer to the file "copyright.html"
 * for further important copyright and licensing information.
 *
 * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */

/*-
 *      Implementation of class Class
 *
 *      former threadruntime.c, Sun Sep 22 12:09:39 1991
 */

#include <stdio.h>
#include <signal.h>

#include "tree.h"
#include "javaString.h"

#include "monitor.h"
#include "javaThreads.h"
#include "exceptions.h"

#include "java_lang_Class.h"
#include "java_lang_ClassLoader.h"

extern void lock_classes(void), unlock_classes(void);

HClass *
java_lang_Class_forName(HClass *this, HString *classname)
{
    char clname[256], *p;
    ClassClass *cb;
    HClass *h;
    int c;

    javaString2CString(classname, clname, sizeof(clname));
    for (p = clname ; (c = *p); p++) {
	if (c == '.') {
	    *p = '/';
	}
    }
    if ((cb = FindClass(EE(), clname, TRUE)) == 0) {
	SignalError(0, JAVAPKG "ClassNotFoundException", clname);
	return 0;
    }
    h = cbHandle(cb);
    return h;
}

Hjava_lang_String *
java_lang_Class_getName(HClass *this)
{
    ClassClass *cb;
    char clname[256];

    if ((this == NULL) || ((cb = unhand(this)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }

    classname2string(classname(cb), clname, sizeof(clname));
    return makeJavaString(clname, strlen(clname));
}

HClass *
java_lang_Class_getSuperclass(HClass *this)
{
    ClassClass *cb;
    if ((this == NULL) || ((cb = unhand(this)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }
    return cbSuperclass(cb);
}

HArrayOfObject *
java_lang_Class_getInterfaces(HClass *this)
{
    int i;
    ClassClass *cb;
    HArrayOfObject *list;
    ExecEnv *ee = EE();
    HClass **listdata;

    if ((this == NULL) || ((cb = unhand(this)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }

    list = (HArrayOfObject *)ArrayAlloc(T_CLASS, cb->implements_count);
    if (list == 0) {
	SignalError(0, JAVAPKG "OutOfMemoryError", 0);
	return 0;
    }
    listdata = (HClass **)unhand(list)->body;
    listdata[cb->implements_count] = (void *)classJavaLangClass;

    /* See if any of the interfaces that we implement possibly implement icb */
    for (i = 0 ; i < (int)cb->implements_count ; i++) {
	ResolveClassConstant(cb->constantpool, cb->implements[i], ee, 1 << CONSTANT_Class);

	listdata[i] = cbHandle((ClassClass *)(cb->constantpool[cb->implements[i]].p));

    }

    return list;
}

Hjava_lang_ClassLoader *
java_lang_Class_getClassLoader(HClass *this)
{
    ClassClass *cb;
    if ((this == NULL) || ((cb = unhand(this)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }
    return (Hjava_lang_ClassLoader *)cb->loader;
}

HObject *
java_lang_Class_newInstance(HClass *this)
{
    ExecEnv *ee = EE();
    ClassClass *cb;

    if ((this == NULL) || ((cb = unhand(this)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }
    return execute_java_constructor(ee, NULL, cb, "()");
}

long 
java_lang_Class_isInterface(HClass *this) 
{
    ClassClass *cb;
    if ((this == NULL) || ((cb = unhand(this)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }
    return (cb->access & ACC_INTERFACE) ? 1 : 0;
}

/**
 * Class loader
 */

extern ClassClass *(*class_loader_func)(HObject *loader, char *name, long resolve);

static ClassClass *
class_loader(HObject *loader, char *name, long resolve) 
{
    char buf[256], *p;
    HObject *c;

    jio_snprintf(buf, sizeof(buf), "%s", name); /* XXX this should be a *MUCH* more efficient strncpy() */

    for (p = buf ; *p ; p++) {
	if (*p == '/') {
	    *p = '.';
	}
    }
    
    /* XXX: Should we throw an exception when we see any illegal characters here??
     This note was identified by David Hopwood.*/

    c = (HObject *)execute_java_dynamic_method(0, loader, "loadClass", 
					      "(L" JAVAPKG "String;Z)L" JAVAPKG "Class;", 
					      makeJavaString(buf, strlen(buf)), resolve);
    return c ? (ClassClass *)unhand(c) : NULL;
}

HClass *
java_lang_ClassLoader_defineClass(Hjava_lang_ClassLoader *this, Hjava_lang_String * name, HArrayOfByte *data, long offset, long length) 
{
    ClassClass	    *cb;
    unsigned char   *body;
    int32_t	    body_len;
    char	    *detail;
    char	    *ename;
    HClass	    *h;
    char	    *namep;
    int		    ret_val;


    /* XXX: Get a boolean return from the following, and it will not be necessary to create an EE() */
    java_lang_ClassLoader_checkInitialized(this);
    if (exceptionOccurred(EE()))
      return 0;

    if (data == 0) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return 0;
    }
    cb = AllocClass();
    if (cb == 0) {
	SignalError(0, JAVAPKG "OutOfMemoryError", 0);
	return 0;
    }
    cb->loader = (HObject *)this;
    body = (unsigned char *) unhand(data)->body;
    body_len = (int32_t) obj_length(data);
    if (offset < 0 || offset >= body_len || length < 0
		   || offset + length > body_len) {
	SignalError(0, JAVAPKG "ArrayIndexOutOfBoundsException", 0);
	return 0;
    }

    sysAssert(!cb->name);
    if (name) {                        /* Expected class name is optional */
        char *p;
        namep = allocCString(name);
        if (!namep)                    /* out of memory was already signaled */
            return 0;
        for (p = namep; *p; p++)       /* Translate from '.' to '/' separators */
            if ('.' == *p) 
                *p = '/';  
        cb->name = namep;              /* Provide expected name */
    } else {
        cb->name = namep = NULL;       /* Indicate no expectations */
    }

    /* We need to lock the classes while creating the class and adding
     * the class to the list of classes
    */
    lock_classes();
    ret_val = createInternalClass(body + offset, body + offset + length, cb);
    if (namep) {
        sysFree(namep);
        namep = 0;
    }
    if (!ret_val) {
	/*	If there was no exception already (OutOfMemory), then 
		throw a class format error. */
	if (!exceptionOccurred(EE()))
		SignalError(0, JAVAPKG "ClassFormatError", 0);
	unlock_classes();
	return 0;
    }
    AddBinClass(cb);

    /*
    ** AddBinClasses() sets the CCF_IsResolving bit to prevent the class
    ** from being freed during class initialization...
    ** Clear this bit since cb references the class and protects it from
    ** being GCed...
    */
    sysAssert(CCIs(cb, Resolving));
    CCClear(cb, Resolving);

    unlock_classes();

    /*
    ** InitializeClass will lock the class and initialize it if
    ** necessary. Note that we need to hold the CCF_Locked across the
    ** call to prevent the class unloader from unloading this currently
    ** unreferenced class!
    */
    if ((ename = InitializeClass(cb, &detail)) != 0) {
	SignalError(0, ename, detail);
	return 0;
    }
    h = cb->HandleToSelf;		/* now there is a reference from C */
    return h;
}

void
java_lang_ClassLoader_resolveClass(Hjava_lang_ClassLoader *this, HClass *c)
{
    ClassClass  *cb;
    char	*detail;
    char	*ename;

    java_lang_ClassLoader_checkInitialized(this);
    if (exceptionOccurred(EE()))
      return;

    if ((this == NULL) || ((cb = unhand(c)) == NULL)) {
	SignalError(0, JAVAPKG "NullPointerException", 0);
	return;
    }

    /* ResolveClass will lock the class and resolve it if necessary */
    if ((ename = ResolveClass(cb, &detail)) != 0) {
	SignalError(0, ename, detail);
    }
}

HClass *
java_lang_ClassLoader_findSystemClass(Hjava_lang_ClassLoader *this, HString *classname)
{
    char clname[256], *p;
    ClassClass *cb;
    HClass *h;
    int c;

    java_lang_ClassLoader_checkInitialized(this);
    if (exceptionOccurred(EE()))
      return 0;

    javaString2CString(classname, clname, sizeof(clname));
    for (p = clname ; (c = *p); p++) {
	if (c == '.') {
	    *p = '/';
	}
    }
    if ((cb = FindClassFromClass(0, clname, TRUE, 0)) == 0) {
	SignalError(0, JAVAPKG "ClassNotFoundException", clname);
	return 0;
    }
    h = cbHandle(cb);
    return h;
}

void
java_lang_ClassLoader_init(Hjava_lang_ClassLoader *this)
{
    /* make sure the runtime can do upcalls */
    class_loader_func = class_loader;
}

void 
java_lang_ClassLoader_checkInitialized(Hjava_lang_ClassLoader *this) {
    if (this == NULL) {
        SignalError(0, JAVAPKG "NullPointerException", 0);
        return;
    }

    if (!unhand(this)->initialized) {
        SignalError(0, JAVAPKG "SecurityException", "Attempted use of uninitialized ClassLoader");
        return;
    }
}