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