зеркало из https://github.com/mozilla/gecko-dev.git
Improved interface registration mechanism.
Author = sdv@sparc.spb.su r = idk@eng.sun.com
This commit is contained in:
Родитель
6cca586d48
Коммит
d780c1dc2a
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче