Improved interface registration mechanism.
Author = sdv@sparc.spb.su r = idk@eng.sun.com git-svn-id: svn://10.0.0.236/trunk@79398 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -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
|
||||
*/
|
||||
Reference in New Issue
Block a user