1*a046d00fSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*a046d00fSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*a046d00fSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*a046d00fSAndrew Rist  * distributed with this work for additional information
6*a046d00fSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*a046d00fSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*a046d00fSAndrew Rist  * "License"); you may not use this file except in compliance
9*a046d00fSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*a046d00fSAndrew Rist  *
11*a046d00fSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*a046d00fSAndrew Rist  *
13*a046d00fSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*a046d00fSAndrew Rist  * software distributed under the License is distributed on an
15*a046d00fSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*a046d00fSAndrew Rist  * KIND, either express or implied.  See the License for the
17*a046d00fSAndrew Rist  * specific language governing permissions and limitations
18*a046d00fSAndrew Rist  * under the License.
19*a046d00fSAndrew Rist  *
20*a046d00fSAndrew Rist  *************************************************************/
21*a046d00fSAndrew Rist 
22*a046d00fSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir package com.sun.star.uno;
25cdf0e10cSrcweir 
26cdf0e10cSrcweir import java.io.IOException;
27cdf0e10cSrcweir import java.lang.reflect.Array;
28cdf0e10cSrcweir import java.lang.reflect.Constructor;
29cdf0e10cSrcweir import java.util.ArrayList;
30cdf0e10cSrcweir import java.util.Iterator;
31cdf0e10cSrcweir import com.sun.star.lib.uno.typedesc.TypeDescription;
32cdf0e10cSrcweir import com.sun.star.lib.util.WeakMap;
33cdf0e10cSrcweir 
34cdf0e10cSrcweir /**
35cdf0e10cSrcweir  * The central class needed for implementing or using UNO components in Java.
36cdf0e10cSrcweir  *
37cdf0e10cSrcweir  * <p>The methods <code>queryInterface</code> and <code>areSame</code> delegate
38cdf0e10cSrcweir  * calls to the implementing objects and are used instead of casts,
39cdf0e10cSrcweir  * <code>instanceof</code>, <code>==</code>, and <code>equals</code>.<p>
40cdf0e10cSrcweir  *
41cdf0e10cSrcweir  * <p>For historic reasons, this class is not <code>final</code>, and has a
42cdf0e10cSrcweir  * <code>public</code> constructor.  These artifacts are considered mistakes,
43cdf0e10cSrcweir  * which might be corrected in a future version of this class, so client code
44cdf0e10cSrcweir  * should not rely on them.</p>
45cdf0e10cSrcweir  *
46cdf0e10cSrcweir  * @see com.sun.star.uno.IBridge
47cdf0e10cSrcweir  * @see com.sun.star.uno.IEnvironment
48cdf0e10cSrcweir  * @see com.sun.star.uno.IQueryInterface
49cdf0e10cSrcweir  */
50cdf0e10cSrcweir public class UnoRuntime {
51cdf0e10cSrcweir     /**
52cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, do not create instances of this class.
53cdf0e10cSrcweir      * It is considered a historic mistake to have a <code>public</code>
54cdf0e10cSrcweir      * constructor for this class, which only has <code>static</code> members.
55cdf0e10cSrcweir      * Also, this class might be changed to become <code>final</code> in a
56cdf0e10cSrcweir      * future version.
57cdf0e10cSrcweir      */
58cdf0e10cSrcweir     public UnoRuntime() {}
59cdf0e10cSrcweir 
60cdf0e10cSrcweir     /**
61cdf0e10cSrcweir      * Generates a world wide unique identifier string.
62cdf0e10cSrcweir      *
63cdf0e10cSrcweir      * <p>It is guaranteed that every invocation of this method generates a new
64cdf0e10cSrcweir      * ID, which is unique within the VM.  The quality of &ldquo;world wide
65cdf0e10cSrcweir      * unique&rdquo; will depend on the actual implementation, you should look
66cdf0e10cSrcweir      * at the source to determine if it meets your requirements.</p>
67cdf0e10cSrcweir      *
68cdf0e10cSrcweir      * @return a unique <code>String</code>
69cdf0e10cSrcweir      */
70cdf0e10cSrcweir     public static String getUniqueKey() {
71cdf0e10cSrcweir         synchronized (uniqueKeyLock) {
72cdf0e10cSrcweir             if (uniqueKeyCount == Long.MAX_VALUE) {
73cdf0e10cSrcweir                 long time;
74cdf0e10cSrcweir                 for (time = System.currentTimeMillis(); time == uniqueKeyTime;)
75cdf0e10cSrcweir                 {
76cdf0e10cSrcweir                     // Conservatively sleep for 100 millisecond to wait for
77cdf0e10cSrcweir                     // System.currentTimeMillis() to change:
78cdf0e10cSrcweir                     try {
79cdf0e10cSrcweir                         Thread.sleep(100);
80cdf0e10cSrcweir                     } catch (InterruptedException e) {
81cdf0e10cSrcweir                         Thread.currentThread().interrupt();
82cdf0e10cSrcweir                     }
83cdf0e10cSrcweir                 }
84cdf0e10cSrcweir                 uniqueKeyTime = time;
85cdf0e10cSrcweir                 uniqueKeyCount = Long.MIN_VALUE;
86cdf0e10cSrcweir             }
87cdf0e10cSrcweir             return uniqueKeyHostPrefix + Long.toString(uniqueKeyTime, 16) + ":"
88cdf0e10cSrcweir                 + Long.toString(uniqueKeyCount++, 16);
89cdf0e10cSrcweir         }
90cdf0e10cSrcweir     }
91cdf0e10cSrcweir 
92cdf0e10cSrcweir     /**
93cdf0e10cSrcweir      * Generates a world wide unique object identifier (OID) for the given
94cdf0e10cSrcweir      * Java object.
95cdf0e10cSrcweir      *
96cdf0e10cSrcweir      * <p>It is guaranteed that subsequent calls to this method with the same
97cdf0e10cSrcweir      * Java object will give the same ID.</p>
98cdf0e10cSrcweir      *
99cdf0e10cSrcweir      * <p>This method is generally of little use for client code.  It should be
100cdf0e10cSrcweir      * considered a mistake that this method is published at all.</p>
101cdf0e10cSrcweir      *
102cdf0e10cSrcweir      * @param object any object for which a OID shall be generated; must not be
103cdf0e10cSrcweir      * <code>null</code>
104cdf0e10cSrcweir      * @return the generated OID
105cdf0e10cSrcweir      * @see com.sun.star.uno.IQueryInterface#getOid
106cdf0e10cSrcweir      */
107cdf0e10cSrcweir     public static String generateOid(Object object) {
108cdf0e10cSrcweir         String oid = null;
109cdf0e10cSrcweir         if (object instanceof IQueryInterface) {
110cdf0e10cSrcweir             oid = ((IQueryInterface) object).getOid();
111cdf0e10cSrcweir         }
112cdf0e10cSrcweir         return oid == null ? object.hashCode() + oidSuffix : oid;
113cdf0e10cSrcweir     }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     /**
116cdf0e10cSrcweir      * Queries the given UNO object for the given UNO interface type.
117cdf0e10cSrcweir      *
118cdf0e10cSrcweir      * <p>This method returns <code>null</code> in case the given UNO object
119cdf0e10cSrcweir      * does not support the given UNO interface type (or is itself
120cdf0e10cSrcweir      * <code>null</code>).  Otherwise, a reference to a Java object implementing
121cdf0e10cSrcweir      * the Java interface type corresponding to the given UNO interface is
122cdf0e10cSrcweir      * returned.  In the latter case, it is unspecified whether the returned
123cdf0e10cSrcweir      * Java object is the same as the given object, or is another facet of that
124cdf0e10cSrcweir      * UNO object.</p>
125cdf0e10cSrcweir      *
126cdf0e10cSrcweir      * @param type the requested UNO interface type; must be a <code>Type</code>
127cdf0e10cSrcweir      * object representing a UNO interface type
128cdf0e10cSrcweir      * @param object a reference to any Java object representing (a facet of) a
129cdf0e10cSrcweir      * UNO object; may be <code>null</code>
130cdf0e10cSrcweir      * @return a reference to the requested UNO interface type if available,
131cdf0e10cSrcweir      * otherwise <code>null</code>
132cdf0e10cSrcweir      * @see com.sun.star.uno.IQueryInterface#queryInterface
133cdf0e10cSrcweir      */
134cdf0e10cSrcweir     public static Object queryInterface(Type type, Object object) {
135cdf0e10cSrcweir         // Gracefully handle those situations where the passed in UNO object is
136cdf0e10cSrcweir         // wrapped in an Any.  Strictly speaking, such a situation constitutes a
137cdf0e10cSrcweir         // bug, but it is anticipated that such situations will arise quite
138cdf0e10cSrcweir         // often in practice (especially since UNO Anys containing an XInterface
139cdf0e10cSrcweir         // reference are not wrapped in a Java Any, but UNO Anys containing any
140cdf0e10cSrcweir         // other interface reference are wrapped in a Java Any, which can lead
141cdf0e10cSrcweir         // to confusion).
142cdf0e10cSrcweir         if (object instanceof Any) {
143cdf0e10cSrcweir             Any a = (Any) object;
144cdf0e10cSrcweir             if (a.getType().getTypeClass() == TypeClass.INTERFACE) {
145cdf0e10cSrcweir                 object = a.getObject();
146cdf0e10cSrcweir             }
147cdf0e10cSrcweir         }
148cdf0e10cSrcweir         if (object instanceof IQueryInterface) {
149cdf0e10cSrcweir             object = ((IQueryInterface) object).queryInterface(type);
150cdf0e10cSrcweir             if (object instanceof Any) {
151cdf0e10cSrcweir                 Any a = (Any) object;
152cdf0e10cSrcweir                 object = a.getType().getTypeClass() == TypeClass.INTERFACE
153cdf0e10cSrcweir                     ? a.getObject() : null;
154cdf0e10cSrcweir             }
155cdf0e10cSrcweir         }
156cdf0e10cSrcweir         // Ensure that the object implements the requested interface type:
157cdf0e10cSrcweir         Class c = type.getZClass();
158cdf0e10cSrcweir         if (c == null || !c.isInstance(object)) {
159cdf0e10cSrcweir             object = null;
160cdf0e10cSrcweir         }
161cdf0e10cSrcweir         return object;
162cdf0e10cSrcweir     }
163cdf0e10cSrcweir 
164cdf0e10cSrcweir     /**
165cdf0e10cSrcweir      * Queries the given UNO object for the given Java class (which must
166cdf0e10cSrcweir      * represent a UNO interface type).
167cdf0e10cSrcweir      *
168cdf0e10cSrcweir      * @param ifc a Java class representing a UNO interface type
169cdf0e10cSrcweir      * @param object a reference to any Java object representing (a facet of) a
170cdf0e10cSrcweir      * UNO object; may be <code>null</code>
171cdf0e10cSrcweir      * @return a reference to the requested UNO interface type if available,
172cdf0e10cSrcweir      * otherwise <code>null</code>
173cdf0e10cSrcweir      * @see #queryInterface(Type, Object)
174cdf0e10cSrcweir      */
175cdf0e10cSrcweir     @SuppressWarnings("unchecked")
176cdf0e10cSrcweir     public static <T> T queryInterface(Class<T> zInterface, Object object) {
177cdf0e10cSrcweir         return (T) queryInterface(new Type(zInterface), object);
178cdf0e10cSrcweir     }
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     /**
181cdf0e10cSrcweir        Tests two UNO <code>ANY</code> values for equality.
182cdf0e10cSrcweir 
183cdf0e10cSrcweir        <p>Two UNO values are <dfn>equal</dfn> if and only if they are of the
184cdf0e10cSrcweir        same UNO type&nbsp;<var>t</var>, and they meet the following condition,
185cdf0e10cSrcweir        depending on&nbsp;<var>t</var>:</p>
186cdf0e10cSrcweir        <ul>
187cdf0e10cSrcweir          <li>If <var>t</var> is a primitive type, then both values must denote
188cdf0e10cSrcweir          the same element of the set of values of&nbsp;<var>t</var>.</li>
189cdf0e10cSrcweir 
190cdf0e10cSrcweir          <li>If <var>t</var> is a structured type, then both values must
191cdf0e10cSrcweir          recursively contain corresponding values that are equal.</li>
192cdf0e10cSrcweir 
193cdf0e10cSrcweir          <li>If <var>t</var> is an interface type, then the two values must be
194cdf0e10cSrcweir          either both null references, or both references to the same UNO
195cdf0e10cSrcweir          object.</li>
196cdf0e10cSrcweir        </ul>
197cdf0e10cSrcweir 
198cdf0e10cSrcweir        @param any1 a Java value representing a UNO <code>ANY</code> value.
199cdf0e10cSrcweir 
200cdf0e10cSrcweir        @param any2 a Java value representing a UNO <code>ANY</code> value.
201cdf0e10cSrcweir 
202cdf0e10cSrcweir        @return <code>true</code> if and only if the two arguments represent
203cdf0e10cSrcweir        equal UNO values.
204cdf0e10cSrcweir     */
205cdf0e10cSrcweir     public static boolean areSame(Object any1, Object any2) {
206cdf0e10cSrcweir         Any a1 = Any.complete(any1);
207cdf0e10cSrcweir         Any a2 = Any.complete(any2);
208cdf0e10cSrcweir         Type t = a1.getType();
209cdf0e10cSrcweir         if (!a2.getType().equals(t)) {
210cdf0e10cSrcweir             return false;
211cdf0e10cSrcweir         }
212cdf0e10cSrcweir         Object v1 = a1.getObject();
213cdf0e10cSrcweir         Object v2 = a2.getObject();
214cdf0e10cSrcweir         switch (t.getTypeClass().getValue()) {
215cdf0e10cSrcweir         case TypeClass.VOID_value:
216cdf0e10cSrcweir             return true;
217cdf0e10cSrcweir         case TypeClass.BOOLEAN_value:
218cdf0e10cSrcweir         case TypeClass.BYTE_value:
219cdf0e10cSrcweir         case TypeClass.SHORT_value:
220cdf0e10cSrcweir         case TypeClass.UNSIGNED_SHORT_value:
221cdf0e10cSrcweir         case TypeClass.LONG_value:
222cdf0e10cSrcweir         case TypeClass.UNSIGNED_LONG_value:
223cdf0e10cSrcweir         case TypeClass.HYPER_value:
224cdf0e10cSrcweir         case TypeClass.UNSIGNED_HYPER_value:
225cdf0e10cSrcweir         case TypeClass.FLOAT_value:
226cdf0e10cSrcweir         case TypeClass.DOUBLE_value:
227cdf0e10cSrcweir         case TypeClass.CHAR_value:
228cdf0e10cSrcweir         case TypeClass.STRING_value:
229cdf0e10cSrcweir         case TypeClass.TYPE_value:
230cdf0e10cSrcweir             return v1.equals(v2);
231cdf0e10cSrcweir         case TypeClass.SEQUENCE_value:
232cdf0e10cSrcweir             int n = Array.getLength(v1);
233cdf0e10cSrcweir             if (n != Array.getLength(v2)) {
234cdf0e10cSrcweir                 return false;
235cdf0e10cSrcweir             }
236cdf0e10cSrcweir             for (int i = 0; i < n; ++i) {
237cdf0e10cSrcweir                 // Recursively using areSame on Java values that are (boxed)
238cdf0e10cSrcweir                 // elements of Java arrays representing UNO sequence values,
239cdf0e10cSrcweir                 // instead of on Java values that are representations of UNO ANY
240cdf0e10cSrcweir                 // values, works by chance:
241cdf0e10cSrcweir                 if (!areSame(Array.get(v1, i), Array.get(v2, i))) {
242cdf0e10cSrcweir                     return false;
243cdf0e10cSrcweir                 }
244cdf0e10cSrcweir             }
245cdf0e10cSrcweir             return true;
246cdf0e10cSrcweir         case TypeClass.ENUM_value:
247cdf0e10cSrcweir             return v1 == v2;
248cdf0e10cSrcweir         case TypeClass.STRUCT_value:
249cdf0e10cSrcweir         case TypeClass.EXCEPTION_value:
250cdf0e10cSrcweir             IFieldDescription[] fs;
251cdf0e10cSrcweir             try {
252cdf0e10cSrcweir                 fs = TypeDescription.getTypeDescription(t).
253cdf0e10cSrcweir                     getFieldDescriptions();
254cdf0e10cSrcweir             } catch (ClassNotFoundException e) {
255cdf0e10cSrcweir                 throw new java.lang.RuntimeException(e.toString());
256cdf0e10cSrcweir             }
257cdf0e10cSrcweir             for (int i = 0; i< fs.length; ++i) {
258cdf0e10cSrcweir                 Type ft = new Type(fs[i].getTypeDescription());
259cdf0e10cSrcweir                 try {
260cdf0e10cSrcweir                     // Recursively using areSame on Java values that are (boxed)
261cdf0e10cSrcweir                     // fields of Java classes representing UNO struct or
262cdf0e10cSrcweir                     // exception values, instead of on Java values that are
263cdf0e10cSrcweir                     // representations of UNO ANY values, works by chance:
264cdf0e10cSrcweir                     if (!areSame(
265cdf0e10cSrcweir                             completeValue(ft, fs[i].getField().get(v1)),
266cdf0e10cSrcweir                             completeValue(ft, fs[i].getField().get(v2))))
267cdf0e10cSrcweir                     {
268cdf0e10cSrcweir                         return false;
269cdf0e10cSrcweir                     }
270cdf0e10cSrcweir                 } catch (IllegalAccessException e) {
271cdf0e10cSrcweir                     throw new java.lang.RuntimeException(e.toString());
272cdf0e10cSrcweir                 }
273cdf0e10cSrcweir             }
274cdf0e10cSrcweir             return true;
275cdf0e10cSrcweir         case TypeClass.INTERFACE_value:
276cdf0e10cSrcweir             return v1 == v2
277cdf0e10cSrcweir                 || (v1 instanceof IQueryInterface
278cdf0e10cSrcweir                     && ((IQueryInterface) v1).isSame(v2))
279cdf0e10cSrcweir                 || (v2 instanceof IQueryInterface
280cdf0e10cSrcweir                     && ((IQueryInterface) v2).isSame(v1));
281cdf0e10cSrcweir         default:
282cdf0e10cSrcweir             throw new java.lang.RuntimeException(
283cdf0e10cSrcweir                 "com.sun.star.uno.Any has bad com.sun.star.uno.TypeClass");
284cdf0e10cSrcweir         }
285cdf0e10cSrcweir     }
286cdf0e10cSrcweir 
287cdf0e10cSrcweir     /**
288cdf0e10cSrcweir        Complete a UNO value (make sure it is no invalid <code>null</code>
289cdf0e10cSrcweir        value).
290cdf0e10cSrcweir 
291cdf0e10cSrcweir        <p>This is useful for members of parameterized type of instantiated
292cdf0e10cSrcweir        polymorphic struct types, as <code>null</code> is a valid value there
293cdf0e10cSrcweir        (and only there, for all types except <code>ANY</code> and interface
294cdf0e10cSrcweir        types).</p>
295cdf0e10cSrcweir 
296cdf0e10cSrcweir        @param type a non-void, non-exception UNO type.
297cdf0e10cSrcweir 
298cdf0e10cSrcweir        @param value a Java value representing a UNO value of the given UNO type,
299cdf0e10cSrcweir        or <code>null</code>.
300cdf0e10cSrcweir 
301cdf0e10cSrcweir        @return the given value, or the neutral value of the given type, if the
302cdf0e10cSrcweir        given value was an invalid <code>null</code> value.
303cdf0e10cSrcweir 
304cdf0e10cSrcweir        @since UDK 3.2.3
305cdf0e10cSrcweir     */
306cdf0e10cSrcweir     public static final Object completeValue(Type type, Object value) {
307cdf0e10cSrcweir         if (value != null) {
308cdf0e10cSrcweir             return value;
309cdf0e10cSrcweir         }
310cdf0e10cSrcweir         switch (type.getTypeClass().getValue()) {
311cdf0e10cSrcweir         case TypeClass.BOOLEAN_value:
312cdf0e10cSrcweir             return Boolean.FALSE;
313cdf0e10cSrcweir         case TypeClass.BYTE_value:
314cdf0e10cSrcweir             return new Byte((byte) 0);
315cdf0e10cSrcweir         case TypeClass.SHORT_value:
316cdf0e10cSrcweir         case TypeClass.UNSIGNED_SHORT_value:
317cdf0e10cSrcweir             return new Short((short) 0);
318cdf0e10cSrcweir         case TypeClass.LONG_value:
319cdf0e10cSrcweir         case TypeClass.UNSIGNED_LONG_value:
320cdf0e10cSrcweir             return new Integer(0);
321cdf0e10cSrcweir         case TypeClass.HYPER_value:
322cdf0e10cSrcweir         case TypeClass.UNSIGNED_HYPER_value:
323cdf0e10cSrcweir             return new Long(0L);
324cdf0e10cSrcweir         case TypeClass.FLOAT_value:
325cdf0e10cSrcweir             return new Float(0.0f);
326cdf0e10cSrcweir         case TypeClass.DOUBLE_value:
327cdf0e10cSrcweir             return new Double(0.0);
328cdf0e10cSrcweir         case TypeClass.CHAR_value:
329cdf0e10cSrcweir             return new Character('\u0000');
330cdf0e10cSrcweir         case TypeClass.STRING_value:
331cdf0e10cSrcweir             return "";
332cdf0e10cSrcweir         case TypeClass.TYPE_value:
333cdf0e10cSrcweir             return Type.VOID;
334cdf0e10cSrcweir         case TypeClass.ANY_value:
335cdf0e10cSrcweir         case TypeClass.INTERFACE_value:
336cdf0e10cSrcweir             return null;
337cdf0e10cSrcweir         case TypeClass.SEQUENCE_value:
338cdf0e10cSrcweir             return Array.newInstance(type.getZClass().getComponentType(), 0);
339cdf0e10cSrcweir         case TypeClass.STRUCT_value:
340cdf0e10cSrcweir             try {
341cdf0e10cSrcweir                 return type.getZClass().getConstructor(null).newInstance(null);
342cdf0e10cSrcweir             } catch (java.lang.RuntimeException e) {
343cdf0e10cSrcweir                 throw e;
344cdf0e10cSrcweir             } catch (java.lang.Exception e) {
345cdf0e10cSrcweir                 throw new java.lang.RuntimeException(e.toString());
346cdf0e10cSrcweir             }
347cdf0e10cSrcweir         case TypeClass.ENUM_value:
348cdf0e10cSrcweir             try {
349cdf0e10cSrcweir                 return type.getZClass().getMethod("getDefault", null).invoke(
350cdf0e10cSrcweir                     null, null);
351cdf0e10cSrcweir             } catch (java.lang.RuntimeException e) {
352cdf0e10cSrcweir                 throw e;
353cdf0e10cSrcweir             } catch (java.lang.Exception e) {
354cdf0e10cSrcweir                 throw new java.lang.RuntimeException(e.toString());
355cdf0e10cSrcweir             }
356cdf0e10cSrcweir         default:
357cdf0e10cSrcweir             throw new IllegalArgumentException(
358cdf0e10cSrcweir                 "com.sun.star.uno.UnoRuntime.completeValue called with bad"
359cdf0e10cSrcweir                 + " com.sun.star.uno.Type");
360cdf0e10cSrcweir         }
361cdf0e10cSrcweir     }
362cdf0e10cSrcweir 
363cdf0e10cSrcweir     /**
364cdf0e10cSrcweir      * Gets the current context of the current thread, or <code>null</code> if
365cdf0e10cSrcweir      * no context has been set for the current thread.
366cdf0e10cSrcweir      *
367cdf0e10cSrcweir      * <p>The current context is thread local, which means that this method
368cdf0e10cSrcweir      * returns the context that was last set for this thread.</p>
369cdf0e10cSrcweir      *
370cdf0e10cSrcweir      * @return the current context of the current thread, or <code>null</code>
371cdf0e10cSrcweir      * if no context has been set for the current thread
372cdf0e10cSrcweir      */
373cdf0e10cSrcweir     public static XCurrentContext getCurrentContext() {
374cdf0e10cSrcweir         return (XCurrentContext) currentContext.get();
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir     /**
378cdf0e10cSrcweir      * Sets the current context for the current thread.
379cdf0e10cSrcweir      *
380cdf0e10cSrcweir      * <p>The current context is thread local.  To support a stacking behaviour,
381cdf0e10cSrcweir      * every function that sets the current context should reset it to the
382cdf0e10cSrcweir      * original value when exiting (for example, within a <code>finally</code>
383cdf0e10cSrcweir      * block).</p>
384cdf0e10cSrcweir      *
385cdf0e10cSrcweir      * @param context the context to be set; if <code>null</code>, any
386cdf0e10cSrcweir      * previously set context will be removed
387cdf0e10cSrcweir     */
388cdf0e10cSrcweir     public static void setCurrentContext(XCurrentContext context) {
389cdf0e10cSrcweir         // optimize this by using Java 1.5 ThreadLocal.remove if context == null
390cdf0e10cSrcweir         currentContext.set(context);
391cdf0e10cSrcweir     }
392cdf0e10cSrcweir 
393cdf0e10cSrcweir     /**
394cdf0e10cSrcweir      * Retrieves an environment of type <code>name</code> with context
395cdf0e10cSrcweir      * <code>context</code>.
396cdf0e10cSrcweir      *
397cdf0e10cSrcweir      * <p>Environments are held weakly by this class.  If the requested
398cdf0e10cSrcweir      * environment already exists, this methods simply returns it.  Otherwise,
399cdf0e10cSrcweir      * this method looks for it under
400cdf0e10cSrcweir      * <code>com.sun.star.lib.uno.environments.<var>name</var>.<!--
401cdf0e10cSrcweir      * --><var>name</var>_environment</code>.</p>
402cdf0e10cSrcweir      *
403cdf0e10cSrcweir      * @param name the name of the environment
404cdf0e10cSrcweir      * @param context the context of the environment
405cdf0e10cSrcweir      * @see com.sun.star.uno.IEnvironment
406cdf0e10cSrcweir      *
407cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
408cdf0e10cSrcweir      * offering a replacement.
409cdf0e10cSrcweir      */
410cdf0e10cSrcweir     public static IEnvironment getEnvironment(String name, Object context)
411cdf0e10cSrcweir         throws java.lang.Exception
412cdf0e10cSrcweir     {
413cdf0e10cSrcweir         synchronized (environments) {
414cdf0e10cSrcweir             IEnvironment env = (IEnvironment) WeakMap.getValue(
415cdf0e10cSrcweir                 environments.get(name + context));
416cdf0e10cSrcweir             if (env == null) {
417cdf0e10cSrcweir                 Class c = Class.forName(
418cdf0e10cSrcweir                     "com.sun.star.lib.uno.environments." + name + "." + name
419cdf0e10cSrcweir                     + "_environment");
420cdf0e10cSrcweir                 Constructor ctor = c.getConstructor(
421cdf0e10cSrcweir                     new Class[] { Object.class });
422cdf0e10cSrcweir                 env = (IEnvironment) ctor.newInstance(new Object[] { context });
423cdf0e10cSrcweir                 environments.put(name + context, env);
424cdf0e10cSrcweir             }
425cdf0e10cSrcweir             return  env;
426cdf0e10cSrcweir         }
427cdf0e10cSrcweir     }
428cdf0e10cSrcweir 
429cdf0e10cSrcweir     /**
430cdf0e10cSrcweir      * Gets a bridge from environment <code>from</code> to environment
431cdf0e10cSrcweir      * <code>to</code>.
432cdf0e10cSrcweir      *
433cdf0e10cSrcweir      * <p>Creates a new bridge, if the requested bridge does not yet exist, and
434cdf0e10cSrcweir      * hands the arguments to the bridge.</p>
435cdf0e10cSrcweir      *
436cdf0e10cSrcweir      * <p>If the requested bridge does not exist, it is searched for in package
437cdf0e10cSrcweir      * <code>com.sun.star.lib.uno.bridges.<var>from</var>_<var>to</var>;</code>
438cdf0e10cSrcweir      * and the root classpath as
439cdf0e10cSrcweir      * <code><var>from</var>_<var>to</var>_bridge</code>.</p>
440cdf0e10cSrcweir      *
441cdf0e10cSrcweir      * @param from the source environment
442cdf0e10cSrcweir      * @param to the target environment
443cdf0e10cSrcweir      * @param args the initial arguments for the bridge
444cdf0e10cSrcweir      * @return the requested bridge
445cdf0e10cSrcweir      * @see #getBridgeByName
446cdf0e10cSrcweir      * @see com.sun.star.uno.IBridge
447cdf0e10cSrcweir      * @see com.sun.star.uno.IEnvironment
448cdf0e10cSrcweir      *
449cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
450cdf0e10cSrcweir      * offering a replacement.
451cdf0e10cSrcweir      */
452cdf0e10cSrcweir     public static IBridge getBridge(
453cdf0e10cSrcweir         IEnvironment from, IEnvironment to, Object[] args)
454cdf0e10cSrcweir         throws java.lang.Exception
455cdf0e10cSrcweir     {
456cdf0e10cSrcweir         synchronized (bridges) {
457cdf0e10cSrcweir             String name = from.getName() + "_" + to.getName();
458cdf0e10cSrcweir             String hashName = from.getName() + from.getContext() + "_"
459cdf0e10cSrcweir                 + to.getName() + to.getContext();
460cdf0e10cSrcweir             IBridge bridge = (IBridge) WeakMap.getValue(bridges.get(hashName));
461cdf0e10cSrcweir             if(bridge == null) {
462cdf0e10cSrcweir                 Class zClass = null;
463cdf0e10cSrcweir                 String className =  name + "_bridge";
464cdf0e10cSrcweir                 try {
465cdf0e10cSrcweir                     zClass = Class.forName(className);
466cdf0e10cSrcweir                 } catch (ClassNotFoundException e) {
467cdf0e10cSrcweir                     className = "com.sun.star.lib.uno.bridges." + name + "."
468cdf0e10cSrcweir                         + className;
469cdf0e10cSrcweir                     zClass = Class.forName(className);
470cdf0e10cSrcweir                 }
471cdf0e10cSrcweir                 Class[] signature = {
472cdf0e10cSrcweir                     IEnvironment.class, IEnvironment.class, args.getClass() };
473cdf0e10cSrcweir                 Constructor constructor = zClass.getConstructor(signature);
474cdf0e10cSrcweir                 Object[] iargs = { from, to, args };
475cdf0e10cSrcweir                 bridge = (IBridge) constructor.newInstance(iargs);
476cdf0e10cSrcweir                 bridges.put(hashName, bridge);
477cdf0e10cSrcweir             }
478cdf0e10cSrcweir             return bridge;
479cdf0e10cSrcweir         }
480cdf0e10cSrcweir     }
481cdf0e10cSrcweir 
482cdf0e10cSrcweir     /**
483cdf0e10cSrcweir      * Gets a bridge from environment <code>from</code> to environment
484cdf0e10cSrcweir      * <code>to</code>.
485cdf0e10cSrcweir      *
486cdf0e10cSrcweir      * <p>Creates a new bridge, if the requested bridge does not yet exist, and
487cdf0e10cSrcweir      * hands the arguments to the bridge.</p>
488cdf0e10cSrcweir      *
489cdf0e10cSrcweir      * <p>If the requested bridge does not exist, it is searched for in package
490cdf0e10cSrcweir      * <code>com.sun.star.lib.uno.bridges.<var>from</var>_<var>to</var>;</code>
491cdf0e10cSrcweir      * and the root classpath as
492cdf0e10cSrcweir      * <code><var>from</var>_<var>to</var>_bridge</code>.  The used environments
493cdf0e10cSrcweir      * are retrieved through <code>getEnvironment</code>.</p>
494cdf0e10cSrcweir      *
495cdf0e10cSrcweir      * @param from the name of the source environment
496cdf0e10cSrcweir      * @param fromContext the context for the source environment
497cdf0e10cSrcweir      * @param to the name of the target environment
498cdf0e10cSrcweir      * @param toContext the context for the target environment
499cdf0e10cSrcweir      * @param args the initial arguments for the bridge
500cdf0e10cSrcweir      * @return the requested bridge
501cdf0e10cSrcweir      * @see #getBridge
502cdf0e10cSrcweir      * @see #getEnvironment
503cdf0e10cSrcweir      * @see com.sun.star.uno.IBridge
504cdf0e10cSrcweir      * @see com.sun.star.uno.IEnvironment
505cdf0e10cSrcweir      *
506cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
507cdf0e10cSrcweir      * offering a replacement.
508cdf0e10cSrcweir      */
509cdf0e10cSrcweir     public static IBridge getBridgeByName(
510cdf0e10cSrcweir         String from, Object fromContext, String to, Object toContext,
511cdf0e10cSrcweir         Object[] args) throws java.lang.Exception
512cdf0e10cSrcweir     {
513cdf0e10cSrcweir         return getBridge(
514cdf0e10cSrcweir             getEnvironment(from, fromContext), getEnvironment(to, toContext),
515cdf0e10cSrcweir             args);
516cdf0e10cSrcweir     }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     /**
519cdf0e10cSrcweir      * Returns an array of all active bridges.
520cdf0e10cSrcweir      *
521cdf0e10cSrcweir      * @return an array of <code>IBridge</code> objects
522cdf0e10cSrcweir      * @see com.sun.star.uno.IBridge
523cdf0e10cSrcweir      *
524cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
525cdf0e10cSrcweir      * offering a replacement.
526cdf0e10cSrcweir      */
527cdf0e10cSrcweir     public static IBridge[] getBridges() {
528cdf0e10cSrcweir         ArrayList l = new ArrayList();
529cdf0e10cSrcweir         synchronized (bridges) {
530cdf0e10cSrcweir             for (Iterator i = bridges.values().iterator(); i.hasNext();) {
531cdf0e10cSrcweir                 Object o = WeakMap.getValue(i.next());
532cdf0e10cSrcweir                 if (o != null) {
533cdf0e10cSrcweir                     l.add(o);
534cdf0e10cSrcweir                 }
535cdf0e10cSrcweir             }
536cdf0e10cSrcweir         }
537cdf0e10cSrcweir         return (IBridge[]) l.toArray(new IBridge[l.size()]);
538cdf0e10cSrcweir     }
539cdf0e10cSrcweir 
540cdf0e10cSrcweir     /**
541cdf0e10cSrcweir      * Gets a mapping from environment <code>from</code> to environment
542cdf0e10cSrcweir      * <code>to</code>.
543cdf0e10cSrcweir      *
544cdf0e10cSrcweir      * <p>Mappings are like bridges, except that with mappings one can only map
545cdf0e10cSrcweir      * in one direction.  Mappings are here for compatibility with the binary
546cdf0e10cSrcweir      * UNO API.  Mappings are implemented as wrappers around bridges.</p>
547cdf0e10cSrcweir      *
548cdf0e10cSrcweir      * @param from the source environment
549cdf0e10cSrcweir      * @param to the target environment
550cdf0e10cSrcweir      * @return the requested mapping
551cdf0e10cSrcweir      * @see com.sun.star.uno.IEnvironment
552cdf0e10cSrcweir      * @see com.sun.star.uno.IMapping
553cdf0e10cSrcweir      *
554cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
555cdf0e10cSrcweir      * offering a replacement.
556cdf0e10cSrcweir      */
557cdf0e10cSrcweir     public static IMapping getMapping(IEnvironment from, IEnvironment to)
558cdf0e10cSrcweir         throws java.lang.Exception
559cdf0e10cSrcweir     {
560cdf0e10cSrcweir         IBridge bridge;
561cdf0e10cSrcweir         try {
562cdf0e10cSrcweir             bridge = getBridge(from, to, null);
563cdf0e10cSrcweir         }
564cdf0e10cSrcweir         catch (ClassNotFoundException e) {
565cdf0e10cSrcweir             bridge = new BridgeTurner(getBridge(to, from, null));
566cdf0e10cSrcweir         }
567cdf0e10cSrcweir         return new MappingWrapper(bridge);
568cdf0e10cSrcweir     }
569cdf0e10cSrcweir 
570cdf0e10cSrcweir     /**
571cdf0e10cSrcweir      * Gets a mapping from environment <code>from</code> to environment
572cdf0e10cSrcweir      * <code>to</code>.
573cdf0e10cSrcweir      *
574cdf0e10cSrcweir      * <p>The used environments are retrieved through
575cdf0e10cSrcweir      * <code>getEnvironment</code>.</p>
576cdf0e10cSrcweir      *
577cdf0e10cSrcweir      * @param from the name of the source environment
578cdf0e10cSrcweir      * @param to the name of the target environment
579cdf0e10cSrcweir      * @return the requested mapping
580cdf0e10cSrcweir      * @see #getEnvironment
581cdf0e10cSrcweir      * @see #getMapping
582cdf0e10cSrcweir      * @see com.sun.star.uno.IMapping
583cdf0e10cSrcweir      *
584cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
585cdf0e10cSrcweir      * offering a replacement.
586cdf0e10cSrcweir      */
587cdf0e10cSrcweir     public static IMapping getMappingByName(String from, String to)
588cdf0e10cSrcweir         throws java.lang.Exception
589cdf0e10cSrcweir     {
590cdf0e10cSrcweir         return getMapping(getEnvironment(from, null), getEnvironment(to, null));
591cdf0e10cSrcweir     }
592cdf0e10cSrcweir 
593cdf0e10cSrcweir     /**
594cdf0e10cSrcweir      * Resets this <code>UnoRuntime</code> to its initial state.
595cdf0e10cSrcweir      *
596cdf0e10cSrcweir      * <p>Releases all references to bridges and environments.</p>
597cdf0e10cSrcweir      *
598cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, this method is deprecated, without
599cdf0e10cSrcweir      * offering a replacement.
600cdf0e10cSrcweir      */
601cdf0e10cSrcweir     static public boolean reset() {
602cdf0e10cSrcweir         synchronized (bridges) {
603cdf0e10cSrcweir             for (Iterator i = bridges.values().iterator(); i.hasNext();) {
604cdf0e10cSrcweir                 IBridge b = (IBridge) WeakMap.getValue(i.next());
605cdf0e10cSrcweir                 if (b != null) {
606cdf0e10cSrcweir                     // The following call to dispose was originally made to
607cdf0e10cSrcweir                     // com.sun.star.lib.sandbox.Disposable.dispose, which cannot
608cdf0e10cSrcweir                     // throw an InterruptedException or IOException:
609cdf0e10cSrcweir                     try {
610cdf0e10cSrcweir                         b.dispose();
611cdf0e10cSrcweir                     } catch (InterruptedException e) {
612cdf0e10cSrcweir                         Thread.currentThread().interrupted();
613cdf0e10cSrcweir                         throw new RuntimeException(
614cdf0e10cSrcweir                             "Unexpected exception in UnoRuntime.reset: " + e);
615cdf0e10cSrcweir                     } catch (IOException e) {
616cdf0e10cSrcweir                         throw new RuntimeException(
617cdf0e10cSrcweir                             "Unexpected exception in UnoRuntime.reset: " + e);
618cdf0e10cSrcweir                     }
619cdf0e10cSrcweir                 }
620cdf0e10cSrcweir             }
621cdf0e10cSrcweir             bridges.clear();
622cdf0e10cSrcweir         }
623cdf0e10cSrcweir         environments.clear();
624cdf0e10cSrcweir         return bridges.isEmpty() && environments.isEmpty();
625cdf0e10cSrcweir     }
626cdf0e10cSrcweir 
627cdf0e10cSrcweir     /**
628cdf0e10cSrcweir      * @deprecated As of UDK&nbsp;3.2.0, do not use this internal field.
629cdf0e10cSrcweir      */
630cdf0e10cSrcweir     static public final boolean DEBUG = false;
631cdf0e10cSrcweir 
632cdf0e10cSrcweir     private static final class BridgeTurner implements IBridge {
633cdf0e10cSrcweir         public BridgeTurner(IBridge bridge) {
634cdf0e10cSrcweir             this.bridge = bridge;
635cdf0e10cSrcweir         }
636cdf0e10cSrcweir 
637cdf0e10cSrcweir         public Object mapInterfaceTo(Object object, Type type) {
638cdf0e10cSrcweir             return bridge.mapInterfaceFrom(object, type);
639cdf0e10cSrcweir         }
640cdf0e10cSrcweir 
641cdf0e10cSrcweir         public Object mapInterfaceFrom(Object object, Type type) {
642cdf0e10cSrcweir             return bridge.mapInterfaceTo(object, type);
643cdf0e10cSrcweir         }
644cdf0e10cSrcweir 
645cdf0e10cSrcweir         public IEnvironment getSourceEnvironment() {
646cdf0e10cSrcweir             return bridge.getTargetEnvironment();
647cdf0e10cSrcweir         }
648cdf0e10cSrcweir 
649cdf0e10cSrcweir         public IEnvironment getTargetEnvironment() {
650cdf0e10cSrcweir             return bridge.getSourceEnvironment();
651cdf0e10cSrcweir         }
652cdf0e10cSrcweir 
653cdf0e10cSrcweir         public void acquire() {
654cdf0e10cSrcweir             bridge.acquire();
655cdf0e10cSrcweir         }
656cdf0e10cSrcweir 
657cdf0e10cSrcweir         public void release() {
658cdf0e10cSrcweir             bridge.release();
659cdf0e10cSrcweir         }
660cdf0e10cSrcweir 
661cdf0e10cSrcweir         public void dispose() throws InterruptedException, IOException {
662cdf0e10cSrcweir             bridge.dispose();
663cdf0e10cSrcweir         }
664cdf0e10cSrcweir 
665cdf0e10cSrcweir         private final IBridge bridge;
666cdf0e10cSrcweir     }
667cdf0e10cSrcweir 
668cdf0e10cSrcweir     private static final class MappingWrapper implements IMapping {
669cdf0e10cSrcweir         public MappingWrapper(IBridge bridge) {
670cdf0e10cSrcweir             this.bridge = bridge;
671cdf0e10cSrcweir         }
672cdf0e10cSrcweir 
673cdf0e10cSrcweir         public Object mapInterface(Object object, Type type) {
674cdf0e10cSrcweir             return bridge.mapInterfaceTo(object, type);
675cdf0e10cSrcweir         }
676cdf0e10cSrcweir 
677cdf0e10cSrcweir         private final IBridge bridge;
678cdf0e10cSrcweir     }
679cdf0e10cSrcweir 
680cdf0e10cSrcweir     private static final String uniqueKeyHostPrefix
681cdf0e10cSrcweir     = Integer.toString(new Object().hashCode(), 16) + ":";
682cdf0e10cSrcweir     private static final Object uniqueKeyLock = new Object();
683cdf0e10cSrcweir     private static long uniqueKeyTime = System.currentTimeMillis();
684cdf0e10cSrcweir     private static long uniqueKeyCount = Long.MIN_VALUE;
685cdf0e10cSrcweir 
686cdf0e10cSrcweir     private static final String oidSuffix = ";java[];" + getUniqueKey();
687cdf0e10cSrcweir 
688cdf0e10cSrcweir     private static final ThreadLocal currentContext = new ThreadLocal();
689cdf0e10cSrcweir 
690cdf0e10cSrcweir     private static final WeakMap environments = new WeakMap();
691cdf0e10cSrcweir     private static final WeakMap bridges = new WeakMap();
692cdf0e10cSrcweir }
693