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 Integer.valueOf( 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 obj != null
212                            && m_oid.equals(UnoRuntime.generateOid(obj));
213     }
214 }
215