Improved interface registration mechanism.

Author = sdv@sparc.spb.su
r = idk@eng.sun.com
This commit is contained in:
idk%eng.sun.com 2000-09-17 00:49:42 +00:00
Родитель 6cca586d48
Коммит d780c1dc2a
10 изменённых файлов: 311 добавлений и 158 удалений

Просмотреть файл

@ -31,32 +31,35 @@ import java.io.File;
public class ComponentLoader {
// path to jar file. Name of main class sould to be in MANIFEST.
public static Object loadComponent(String location) {
try {
File file = (new File(location)).getCanonicalFile(); //To avoid spelling diffs, e.g c: and C:
location = file.getAbsolutePath();
if (File.separatorChar != '/') {
location = location.replace(File.separatorChar,'/');
}
if (!location.startsWith("/")) {
location = "/" + location;
}
URL url = new URL("file:"+location);
URLClassLoader loader = URLClassLoader.newInstance(new URL[]{url});
URL manifestURL = new URL("jar:file:"+location+"!/META-INF/MANIFEST.MF");
InputStream inputStream = manifestURL.openStream();
Manifest manifest = new Manifest(inputStream);
Attributes attr = manifest.getMainAttributes();
String componentClassName = attr.getValue("Component-Class");
if (componentClassName == null) {
//nb
return null;
}
Object object = loader.loadClass(componentClassName).newInstance();
return object;
} catch (Exception e) {
try {
File file = (new File(location)).getCanonicalFile(); //To avoid spelling diffs, e.g c: and C:
location = file.getAbsolutePath();
if (File.separatorChar != '/') {
location = location.replace(File.separatorChar,'/');
}
if (!location.startsWith("/")) {
location = "/" + location;
}
URL url = new URL("file:"+location);
URLClassLoader loader = URLClassLoader.newInstance(new URL[]{url});
URL manifestURL = new URL("jar:file:"+location+"!/META-INF/MANIFEST.MF");
InputStream inputStream = manifestURL.openStream();
Manifest manifest = new Manifest(inputStream);
Attributes attr = manifest.getMainAttributes();
String componentClassName = attr.getValue("Component-Class");
if (componentClassName == null) {
//nb
return null;
}
Object object = loader.loadClass(componentClassName).newInstance();
if (object instanceof nsISupports) {
InterfaceRegistry.register((nsISupports)object);
}
return object;
} catch (Exception e) {
e.printStackTrace();
return null;
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,186 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun Microsystems,
* Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s):
* Denis Sharypov <sdv@sparc.spb.su>
*/
package org.mozilla.xpcom;
import java.util.Hashtable;
import java.lang.reflect.*;
class InterfaceRegistry {
private static String IID_STRING = "IID";
private static Hashtable interfaces = null;
private static Hashtable iMethods = null;
private static boolean debug = true;
private InterfaceRegistry() {
}
public static void register(nsISupports obj) {
if (obj == null) {
return;
}
if (interfaces == null) {
interfaces = new Hashtable();
}
if (iMethods == null) {
iMethods = new Hashtable();
}
Class cl = obj.getClass();
if (!cl.isInterface()) {
Class[] ifaces = cl.getInterfaces();
for (int i = 0; i < ifaces.length; i++) {
registerInterfaces(ifaces[i]);
}
} else {
registerInterfaces(cl);
}
}
private static void registerInterfaces(Class cl) {
try {
Object iidStr = cl.getField(IID_STRING).get(cl);
if (iidStr instanceof String) {
IID iid = new IID((String)iidStr);
String[] methodNames = Utilities.getInterfaceMethodNames((String)iidStr);
if (methodNames != null) {
Method[] rmethods = new Method[methodNames.length];
int i = methodNames.length - 1;
Class[] ifaces = new Class[]{cl};
// recursively get all parent interface methods
do {
Method[] methods = ifaces[0].getDeclaredMethods();
int j = methods.length - 1;
while (i >= 0 && j >=0) {
if (methodNames[i].equals(methods[j].getName())) {
rmethods[i--] = methods[j--];
} else {
// put null for notxpcom & noscript methods
rmethods[i--] = null;
}
}
ifaces = ifaces[0].getInterfaces();
// check for single inheritance (xpcom)
} while (ifaces.length == 1);
interfaces.put(iid, cl);
iMethods.put(iid, new MethodArray(rmethods));
debug(cl.getName() + ": " + iid + " ( " + cl + " )");
printMethods(rmethods);
}
}
} catch (NoSuchFieldException e) {
// the interface doesn't define IID field
debug("no such field...");
} catch (IllegalAccessException e1) {
debug("can't access field...");
}
// register interfaces extended by the interface
Class[] ifaces = cl.getInterfaces();
for (int i = 0; i < ifaces.length; i++) {
registerInterfaces(ifaces[i]);
}
}
public static Class getInterface(IID iid) {
Object obj = null;
if (interfaces != null) {
obj = interfaces.get(iid);
}
if (obj == null || !(obj instanceof Class)) {
return null;
}
return (Class)obj;
}
public static Method getMethodByIndex(int index, IID iid) {
Method result = null;
MethodArray m = (MethodArray)iMethods.get(iid);
if (m != null && m.methods !=null) {
try {
result = m.methods[index];
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
public static int getIndexByMethod(Method method, IID iid) {
int result = 0;
MethodArray m = (MethodArray)iMethods.get(iid);
if (m != null && m.methods !=null) {
for (int i = 0; i < m.methods.length; i++) {
if (method.equals(m.methods[i])) {
result = i;
break;
}
}
}
return result;
}
// methods for debugging
private static void printMethods(Method[] methods) {
if (debug) {
for (int i = 0; i < methods.length; i++) {
printMethod(methods[i]);
}
}
}
private static void printMethod(Method m) {
if (m == null) {
System.out.println("<null>");
return;
}
Class retType = m.getReturnType();
Class[] paramTypes = m.getParameterTypes();
String name = m.getName();
System.out.print(Modifier.toString(m.getModifiers()));
System.out.print(" " + retType.getName() + " " + name
+ "(");
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
private static void debug(String str) {
if (debug) {
System.out.println(str);
}
}
}
class MethodArray {
Method[] methods;
MethodArray(Method[] _methods) {
methods = _methods;
}
}

Просмотреть файл

@ -1,83 +0,0 @@
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun Microsystems,
* Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s):
* Igor Kushnirskiy <idk@eng.sun.com>
*/
package org.mozilla.xpcom;
import java.lang.reflect.*;
import java.util.*;
public class ProxyClass { //nb it should not be public
public ProxyClass(IID _iid, Method[] _methods) { //nb it should not be public
iid = _iid;
methods = _methods;
if (classes == null) {
classes = new Hashtable();
}
classes.put(iid, this);
}
Method getMethodByIndex(int mid) { //first method has index equal to 'offset'
System.out.println("--[java]ProxyClass.GetMehodByIndex "+mid);
Method result = null;
try {
result = methods[mid-offset];
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
int getIndexByMethod(Method method) {
int result = 0;
if (method == null
||methods == null) {
return result;
}
for (int i = 0; i < methods.length; i++) {
if (method.equals(methods[i])) {
result = i + offset;
break;
}
}
return result;
}
static ProxyClass getProxyClass(IID iid) {
ProxyClass result = null;
Object obj = null;
if (classes != null) {
obj = classes.get(iid);
if (obj != null
&& (obj instanceof ProxyClass)) {
result = (ProxyClass)obj;
}
}
return result;
}
private IID iid;
private Method[] methods;
private final int offset = 0; //from xpcom
static Hashtable classes = null;
}

Просмотреть файл

@ -30,7 +30,7 @@ public class Utilities {
for (int i = 0; i < args.length; i++) {
System.out.println("--[java]callMethodByIndex args["+i+"] = "+args[i]);
}
Method method = getMethodByIndex(mid,iid);
Method method = InterfaceRegistry.getMethodByIndex(mid,iid);
System.out.println("--[java] org.mozilla.xpcom.Utilities.callMethodByIndex method "+method);
try {
if (method != null) {
@ -42,9 +42,10 @@ public class Utilities {
System.out.println("--callMethodByIndex method finished"+method);
return null; //nb for testing
}
static Object callMethod(long oid, Method method, IID iid, long orb , Object[] args) {
System.out.println("--[java]Utilities.callMethod "+method);
int mid = getIndexByMethod(method, iid);
int mid = InterfaceRegistry.getIndexByMethod(method, iid);
if (mid <= 0) {
System.out.println("--[java]Utilities.callMethod we do not have implementation for "+method);
return null;
@ -52,24 +53,9 @@ public class Utilities {
System.out.println("--[java]Utilities.callMethod "+mid);
return callMethodByIndex(oid,mid,iid.getString(), orb, args);
}
private static Method getMethodByIndex(int index, IID iid) {
Method result = null;
ProxyClass proxyClass = ProxyClass.getProxyClass(iid);
if (proxyClass != null) {
result = proxyClass.getMethodByIndex(index);
}
return result;
}
private static int getIndexByMethod(Method method, IID iid) {
int result = 0;
ProxyClass proxyClass = ProxyClass.getProxyClass(iid);
if (proxyClass != null) {
result = proxyClass.getIndexByMethod(method);
}
return result;
}
private static native Object callMethodByIndex(long oid, int index, String iid, long orb, Object[] args);
static native String[] getInterfaceMethodNames(String iid);
static {
System.loadLibrary("bcjavastubs");
}

Просмотреть файл

@ -0,0 +1,30 @@
/*
* ************* DO NOT EDIT THIS FILE ***********
*
* This file was automatically generated from nsISupports.idl.
*/
package org.mozilla.xpcom;
/**
* Interface nsISupports
*
* IID: 0x00000000-0000-0000-c000-000000000046
*/
public interface nsISupports
{
public static final String IID =
"00000000-0000-0000-c000-000000000046";
/* void QueryInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
public void queryInterface(IID uuid, Object[] obj);
}
/*
* end
*/

Просмотреть файл

@ -18,6 +18,7 @@
*
* Contributor(s):
* Igor Kushnirskiy <idk@eng.sun.com>
* Denis Sharypov <sdv@sparc.spb.su>
*/
#include "nsISupports.h"
#include "org_mozilla_xpcom_Utilities.h"
@ -28,6 +29,7 @@
#include "nsIInterfaceInfo.h"
#include "nsIInterfaceInfoManager.h"
#include "bcJavaMarshalToolkit.h"
#include "ctype.h"
/*
* Class: org_mozilla_xpcom_Utilities
@ -69,3 +71,45 @@ JNIEXPORT jobject JNICALL Java_org_mozilla_xpcom_Utilities_callMethodByIndex
return NULL;
}
/*
* Class: org_mozilla_xpcom_Utilities
* Method: getInterfaceMethodNames
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_mozilla_xpcom_Utilities_getInterfaceMethodNames
(JNIEnv *env, jclass clazz, jstring jiid) {
if (!jiid) {
return NULL;
}
nsIID iid;
const char * str = NULL;
str = env->GetStringUTFChars(jiid, NULL);
iid.Parse(str);
env->ReleaseStringUTFChars(jiid,str);
nsIInterfaceInfo *interfaceInfo;
nsIInterfaceInfoManager* iimgr;
if((iimgr = XPTI_GetInterfaceInfoManager()) != NULL) {
if (NS_FAILED(iimgr->GetInfoForIID(&iid, &interfaceInfo))) {
return NULL; //nb exception handling
}
NS_RELEASE(iimgr);
} else {
return NULL;
}
PRUint16 num;
interfaceInfo->GetMethodCount(&num);
jobjectArray names;
jclass stringClass = env->GetObjectClass(jiid);
names = env->NewObjectArray(num, stringClass, NULL);
nsXPTMethodInfo* info;
char buf[256];
for (int i = 0; i < num; i++) {
interfaceInfo->GetMethodInfo(i, (const nsXPTMethodInfo **)&info);
const char* name = info->GetName();
// first letter of the method name is in lowercase in java
sprintf(buf, "%c%s", tolower(*name), name + 1);
env->SetObjectArrayElement(names, i, env->NewStringUTF(buf));
}
return names;
}

Просмотреть файл

@ -15,6 +15,14 @@ extern "C" {
JNIEXPORT jobject JNICALL Java_org_mozilla_xpcom_Utilities_callMethodByIndex
(JNIEnv *, jclass, jlong, jint, jstring, jlong, jobjectArray);
/*
* Class: org_mozilla_xpcom_Utilities
* Method: getInterfaceMethodNames
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_mozilla_xpcom_Utilities_getInterfaceMethodNames
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -6,9 +6,9 @@
import org.mozilla.xpcom.*;
public interface bcIJavaSample
public interface bcIJavaSample extends nsISupports
{
public static final String BC_IJAVASAMPLE_IID_STRING =
public static final String IID =
"ca1e2656-1dd1-11b2-9c4e-f49ea557abde";
void queryInterface(IID iid, Object[] result);
void test0();

Просмотреть файл

@ -106,9 +106,12 @@ void test() {
nsnull,
NS_GET_IID(bcIJavaSample),
(void**)&test);
if (NS_FAILED(r)) {
printf("--[debug] can not load bcJavaSample\n");
return;
}
//sigsend(P_PID, getpid(),SIGINT);
//test->Test1(2000);
#if 0
test->Test1(1000);
bcIJavaSample *test1;
if (NS_FAILED(r)) {
@ -119,7 +122,6 @@ void test() {
test->QueryInterface(NS_GET_IID(bcIJavaSample),(void**)&test1);
int intArray[] = {1,2,3};
test->Test3(3, intArray);
#endif
{
char ** valueArray = (char **)malloc(sizeof(char*)*4);
valueArray[0] = "hi";

Просмотреть файл

@ -21,6 +21,7 @@
*/
import org.mozilla.xpcom.*;
import java.lang.reflect.*;
public class bcJavaSample implements bcIJavaSample {
public bcJavaSample() {
System.out.println("--[java]bcJavaSample constructor");
@ -71,32 +72,8 @@ public class bcJavaSample implements bcIJavaSample {
String[] returnArray = {"4","3","2","1"};
valueArray[0] = returnArray;
}
static IID bcIJavaSampleIID;
static IID nsISupportsIID;
static {
try {
Method[] methods = null;
Class bcIJavaSampleClass = Class.forName("bcIJavaSample");
Class IIDClass = Class.forName("org.mozilla.xpcom.IID");
methods = new Method[100];
Class ObjectArrayClass = (new Object[1]).getClass();
Class IntArrayClass = (new int[1]).getClass();
Class StringArrayArrayClass = (new String[1][1]).getClass();
methods[0] = bcIJavaSampleClass.getDeclaredMethod("queryInterface",new Class[]{IIDClass,ObjectArrayClass});
methods[3] = bcIJavaSampleClass.getDeclaredMethod("test0",new Class[]{});
methods[4] = bcIJavaSampleClass.getDeclaredMethod("test1",new Class[]{Integer.TYPE});
methods[5] = bcIJavaSampleClass.getDeclaredMethod("test2",new Class[]{bcIJavaSampleClass});
methods[6] = bcIJavaSampleClass.getDeclaredMethod("test3",new Class[]{Integer.TYPE,IntArrayClass});
methods[7] = bcIJavaSampleClass.getDeclaredMethod("test4",new Class[]{Integer.TYPE,StringArrayArrayClass});
System.out.println(methods[0]+" "+methods[3]+" "+methods[4]+" "+methods[5]+" "+methods[6]+" "+methods[7]);
bcIJavaSampleIID = new IID(bcIJavaSample.BC_IJAVASAMPLE_IID_STRING);
nsISupportsIID = new IID("00000000-0000-0000-c000-000000000046");
ProxyFactory.registerInterfaceForIID(bcIJavaSampleClass,bcIJavaSampleIID);
new ProxyClass(bcIJavaSampleIID, methods);
//new ProxyClass(nsISupportsIID, methods);
} catch (Exception e) {
System.out.println(e);
}
}
static IID bcIJavaSampleIID = new IID(bcIJavaSample.IID);
static IID nsISupportsIID = new IID(nsISupports.IID);
};