1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 package com.sun.star.bridges.jni_uno; 25 26 import com.sun.star.lib.util.AsynchronousFinalizer; 27 import com.sun.star.lib.util.NativeLibraryLoader; 28 import com.sun.star.uno.Type; 29 import com.sun.star.uno.UnoRuntime; 30 import com.sun.star.uno.IEnvironment; 31 import com.sun.star.uno.IQueryInterface; 32 33 34 //============================================================================== 35 public final class JNI_proxy implements java.lang.reflect.InvocationHandler 36 { 37 static { JNI_proxy.class.getClassLoader()38 NativeLibraryLoader.loadLibrary(JNI_proxy.class.getClassLoader(), 39 "java_uno"); 40 } 41 protected static ClassLoader s_classloader = 42 JNI_proxy.class.getClassLoader(); 43 protected static Class s_InvocationHandler [] = 44 new Class [] { java.lang.reflect.InvocationHandler.class }; 45 46 protected long m_bridge_handle; 47 protected IEnvironment m_java_env; 48 protected long m_receiver_handle; 49 protected long m_td_handle; 50 protected Type m_type; 51 protected String m_oid; 52 protected Class m_class; 53 54 //__________________________________________________________________________ get_stack_trace( Throwable throwable )55 public static String get_stack_trace( Throwable throwable ) 56 throws Throwable 57 { 58 boolean current_trace = false; 59 if (null == throwable) 60 { 61 throwable = new Throwable(); 62 current_trace = true; 63 } 64 java.io.StringWriter string_writer = 65 new java.io.StringWriter(); 66 java.io.PrintWriter print_writer = 67 new java.io.PrintWriter( string_writer, true ); 68 throwable.printStackTrace( print_writer ); 69 print_writer.flush(); 70 print_writer.close(); 71 string_writer.flush(); 72 String trace = string_writer.toString(); 73 if (current_trace) 74 { 75 // cut out first two lines 76 int n = trace.indexOf( '\n' ); 77 n = trace.indexOf( '\n', n +1 ); 78 trace = trace.substring( n +1 ); 79 } 80 return "\njava stack trace:\n" + trace; 81 } 82 83 //__________________________________________________________________________ finalize( long bridge_handle )84 private native void finalize( long bridge_handle ); 85 86 //__________________________________________________________________________ finalize()87 public void finalize() 88 { 89 AsynchronousFinalizer.add(new AsynchronousFinalizer.Job() { 90 public void run() throws Throwable { 91 JNI_proxy.this.finalize( m_bridge_handle ); 92 } 93 }); 94 } 95 96 //__________________________________________________________________________ JNI_proxy( long bridge_handle, IEnvironment java_env, long receiver_handle, long td_handle, Type type, String oid )97 private JNI_proxy( 98 long bridge_handle, IEnvironment java_env, 99 long receiver_handle, long td_handle, Type type, String oid ) 100 { 101 m_bridge_handle = bridge_handle; 102 m_java_env = java_env; 103 m_receiver_handle = receiver_handle; 104 m_td_handle = td_handle; 105 m_type = type; 106 m_oid = oid; 107 m_class = m_type.getZClass(); 108 } 109 110 //__________________________________________________________________________ create( long bridge_handle, IEnvironment java_env, long receiver_handle, long td_handle, Type type, String oid, java.lang.reflect.Constructor proxy_ctor )111 public static Object create( 112 long bridge_handle, IEnvironment java_env, 113 long receiver_handle, long td_handle, Type type, String oid, 114 java.lang.reflect.Constructor proxy_ctor ) 115 throws Throwable 116 { 117 JNI_proxy handler = new JNI_proxy( 118 bridge_handle, java_env, receiver_handle, td_handle, type, oid ); 119 Object proxy = proxy_ctor.newInstance( new Object [] { handler } ); 120 return java_env.registerInterface( proxy, new String [] { oid }, type ); 121 } 122 123 //__________________________________________________________________________ get_proxy_ctor( Class clazz )124 public static java.lang.reflect.Constructor get_proxy_ctor( Class clazz ) 125 throws Throwable 126 { 127 Class proxy_class = java.lang.reflect.Proxy.getProxyClass( 128 s_classloader, 129 new Class [] { clazz, IQueryInterface.class, 130 com.sun.star.lib.uno.Proxy.class } ); 131 return proxy_class.getConstructor( s_InvocationHandler ); 132 } 133 134 //__________________________________________________________________________ dispatch_call( long bridge_handle, String decl_class, String method, Object args [] )135 private native Object dispatch_call( 136 long bridge_handle, String decl_class, String method, Object args [] ) 137 throws Throwable; 138 139 // InvocationHandler impl 140 //__________________________________________________________________________ invoke( Object proxy, java.lang.reflect.Method method, Object args [] )141 public Object invoke( 142 Object proxy, java.lang.reflect.Method method, Object args [] ) 143 throws Throwable 144 { 145 Class decl_class = method.getDeclaringClass(); 146 String method_name = method.getName(); 147 148 if (Object.class.equals( decl_class )) 149 { 150 if (method_name.equals( "hashCode" )) 151 { 152 // int hashCode() 153 return new Integer( m_oid.hashCode() ); 154 } 155 else if (method_name.equals( "equals" )) 156 { 157 // boolean equals( Object obj ) 158 return isSame(args[0]); 159 } 160 else if (method_name.equals( "toString" )) 161 { 162 // String toString() 163 return this.toString() + " [oid=" + m_oid + 164 ", type=" + m_type.getTypeName() + "]"; 165 } 166 } 167 // UNO interface call 168 else if (decl_class.isAssignableFrom( m_class )) 169 { 170 // dispatch interface call 171 return dispatch_call( 172 m_bridge_handle, decl_class.getName(), method_name, args ); 173 } 174 // IQueryInterface impl 175 else if (IQueryInterface.class.equals( decl_class )) 176 { 177 if (method_name.equals( "queryInterface" )) 178 { 179 // Object queryInterface( Type type ) 180 Object registered_proxy = 181 m_java_env.getRegisteredInterface( m_oid, (Type)args[ 0 ] ); 182 if (null == registered_proxy) 183 { 184 return dispatch_call( 185 m_bridge_handle, 186 "com.sun.star.uno.XInterface", method_name, args ); 187 } 188 else 189 { 190 return registered_proxy; 191 } 192 } 193 else if (method_name.equals( "isSame" )) 194 { 195 // boolean isSame( Object object ) 196 return isSame(args[0]); 197 } 198 else if (method_name.equals( "getOid" )) 199 { 200 // String getOid() 201 return m_oid; 202 } 203 } 204 205 throw new com.sun.star.uno.RuntimeException( 206 "[jni_uno bridge error] unexpected call on proxy " + 207 proxy.toString() + ": " + method.toString() ); 208 } 209 isSame(Object obj)210 private Boolean isSame(Object obj) { 211 return new Boolean(obj != null 212 && m_oid.equals(UnoRuntime.generateOid(obj))); 213 } 214 } 215