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