blob: 22867fc3b4943c1866b6cc5f551bcb5af3771d5c [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
package com.sun.star.bridges.jni_uno;
import com.sun.star.lib.util.AsynchronousFinalizer;
import com.sun.star.lib.util.NativeLibraryLoader;
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.IEnvironment;
import com.sun.star.uno.IQueryInterface;
//==============================================================================
public final class JNI_proxy implements java.lang.reflect.InvocationHandler
{
static {
NativeLibraryLoader.loadLibrary(JNI_proxy.class.getClassLoader(),
"java_uno");
}
protected static ClassLoader s_classloader =
JNI_proxy.class.getClassLoader();
protected static Class s_InvocationHandler [] =
new Class [] { java.lang.reflect.InvocationHandler.class };
protected long m_bridge_handle;
protected IEnvironment m_java_env;
protected long m_receiver_handle;
protected long m_td_handle;
protected Type m_type;
protected String m_oid;
protected Class m_class;
//__________________________________________________________________________
public static String get_stack_trace( Throwable throwable )
throws Throwable
{
boolean current_trace = false;
if (null == throwable)
{
throwable = new Throwable();
current_trace = true;
}
java.io.StringWriter string_writer =
new java.io.StringWriter();
java.io.PrintWriter print_writer =
new java.io.PrintWriter( string_writer, true );
throwable.printStackTrace( print_writer );
print_writer.flush();
print_writer.close();
string_writer.flush();
String trace = string_writer.toString();
if (current_trace)
{
// cut out first two lines
int n = trace.indexOf( '\n' );
n = trace.indexOf( '\n', n +1 );
trace = trace.substring( n +1 );
}
return "\njava stack trace:\n" + trace;
}
//__________________________________________________________________________
private native void finalize( long bridge_handle );
//__________________________________________________________________________
public void finalize()
{
AsynchronousFinalizer.add(new AsynchronousFinalizer.Job() {
public void run() throws Throwable {
JNI_proxy.this.finalize( m_bridge_handle );
}
});
}
//__________________________________________________________________________
private JNI_proxy(
long bridge_handle, IEnvironment java_env,
long receiver_handle, long td_handle, Type type, String oid )
{
m_bridge_handle = bridge_handle;
m_java_env = java_env;
m_receiver_handle = receiver_handle;
m_td_handle = td_handle;
m_type = type;
m_oid = oid;
m_class = m_type.getZClass();
}
//__________________________________________________________________________
public static Object create(
long bridge_handle, IEnvironment java_env,
long receiver_handle, long td_handle, Type type, String oid,
java.lang.reflect.Constructor proxy_ctor )
throws Throwable
{
JNI_proxy handler = new JNI_proxy(
bridge_handle, java_env, receiver_handle, td_handle, type, oid );
Object proxy = proxy_ctor.newInstance( new Object [] { handler } );
return java_env.registerInterface( proxy, new String [] { oid }, type );
}
//__________________________________________________________________________
public static java.lang.reflect.Constructor get_proxy_ctor( Class clazz )
throws Throwable
{
Class proxy_class = java.lang.reflect.Proxy.getProxyClass(
s_classloader,
new Class [] { clazz, IQueryInterface.class,
com.sun.star.lib.uno.Proxy.class } );
return proxy_class.getConstructor( s_InvocationHandler );
}
//__________________________________________________________________________
private native Object dispatch_call(
long bridge_handle, String decl_class, String method, Object args [] )
throws Throwable;
// InvocationHandler impl
//__________________________________________________________________________
public Object invoke(
Object proxy, java.lang.reflect.Method method, Object args [] )
throws Throwable
{
Class decl_class = method.getDeclaringClass();
String method_name = method.getName();
if (Object.class.equals( decl_class ))
{
if (method_name.equals( "hashCode" ))
{
// int hashCode()
return new Integer( m_oid.hashCode() );
}
else if (method_name.equals( "equals" ))
{
// boolean equals( Object obj )
return isSame(args[0]);
}
else if (method_name.equals( "toString" ))
{
// String toString()
return this.toString() + " [oid=" + m_oid +
", type=" + m_type.getTypeName() + "]";
}
}
// UNO interface call
else if (decl_class.isAssignableFrom( m_class ))
{
// dispatch interface call
return dispatch_call(
m_bridge_handle, decl_class.getName(), method_name, args );
}
// IQueryInterface impl
else if (IQueryInterface.class.equals( decl_class ))
{
if (method_name.equals( "queryInterface" ))
{
// Object queryInterface( Type type )
Object registered_proxy =
m_java_env.getRegisteredInterface( m_oid, (Type)args[ 0 ] );
if (null == registered_proxy)
{
return dispatch_call(
m_bridge_handle,
"com.sun.star.uno.XInterface", method_name, args );
}
else
{
return registered_proxy;
}
}
else if (method_name.equals( "isSame" ))
{
// boolean isSame( Object object )
return isSame(args[0]);
}
else if (method_name.equals( "getOid" ))
{
// String getOid()
return m_oid;
}
}
throw new com.sun.star.uno.RuntimeException(
"[jni_uno bridge error] unexpected call on proxy " +
proxy.toString() + ": " + method.toString() );
}
private Boolean isSame(Object obj) {
return new Boolean(obj != null
&& m_oid.equals(UnoRuntime.generateOid(obj)));
}
}