4
|
1 |
/*
|
5555
|
2 |
* Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
|
4
|
3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
4 |
*
|
|
5 |
* This code is free software; you can redistribute it and/or modify it
|
|
6 |
* under the terms of the GNU General Public License version 2 only, as
|
5555
|
7 |
* published by the Free Software Foundation. Oracle designates this
|
4
|
8 |
* particular file as subject to the "Classpath" exception as provided
|
5555
|
9 |
* by Oracle in the LICENSE file that accompanied this code.
|
4
|
10 |
*
|
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that
|
|
15 |
* accompanied this code).
|
|
16 |
*
|
|
17 |
* You should have received a copy of the GNU General Public License version
|
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
20 |
*
|
5555
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
22 |
* or visit www.oracle.com if you need additional information or have any
|
|
23 |
* questions.
|
4
|
24 |
*/
|
|
25 |
|
|
26 |
/*
|
|
27 |
* Licensed Materials - Property of IBM
|
|
28 |
* RMI-IIOP v1.0
|
|
29 |
* Copyright IBM Corp. 1998 1999 All Rights Reserved
|
|
30 |
*
|
|
31 |
*/
|
|
32 |
|
|
33 |
package com.sun.corba.se.impl.util;
|
|
34 |
|
|
35 |
import org.omg.CORBA.SystemException;
|
|
36 |
import org.omg.CORBA.CompletionStatus;
|
|
37 |
import org.omg.CORBA.BAD_OPERATION;
|
|
38 |
import org.omg.CORBA.BAD_INV_ORDER;
|
|
39 |
import org.omg.CORBA.BAD_PARAM;
|
|
40 |
import org.omg.CORBA.ORB;
|
|
41 |
import org.omg.CORBA.Any;
|
|
42 |
import org.omg.CORBA.TypeCode;
|
|
43 |
import org.omg.CORBA.Principal;
|
|
44 |
import org.omg.CORBA.portable.InputStream;
|
|
45 |
import org.omg.CORBA.portable.OutputStream;
|
|
46 |
import org.omg.CORBA.portable.BoxedValueHelper;
|
|
47 |
import org.omg.CORBA.portable.ValueFactory;
|
|
48 |
import org.omg.CORBA.portable.Streamable;
|
|
49 |
import org.omg.CORBA.portable.Delegate;
|
|
50 |
|
|
51 |
|
|
52 |
import java.util.Hashtable;
|
|
53 |
import java.util.NoSuchElementException;
|
|
54 |
|
|
55 |
import java.rmi.Remote;
|
|
56 |
import java.rmi.NoSuchObjectException;
|
|
57 |
import java.rmi.RemoteException;
|
|
58 |
import java.rmi.server.RemoteStub;
|
|
59 |
|
|
60 |
import javax.rmi.PortableRemoteObject;
|
|
61 |
import javax.rmi.CORBA.Stub;
|
|
62 |
import javax.rmi.CORBA.Tie;
|
|
63 |
import javax.rmi.CORBA.Util;
|
|
64 |
|
|
65 |
import java.io.Serializable;
|
|
66 |
import java.io.File;
|
|
67 |
import java.io.FileInputStream;
|
|
68 |
|
|
69 |
import org.omg.PortableServer.POA;
|
|
70 |
|
|
71 |
import com.sun.org.omg.SendingContext.CodeBase;
|
|
72 |
|
|
73 |
import com.sun.corba.se.spi.logging.CORBALogDomains ;
|
|
74 |
import com.sun.corba.se.spi.presentation.rmi.PresentationManager;
|
|
75 |
import com.sun.corba.se.spi.presentation.rmi.StubAdapter ;
|
|
76 |
|
|
77 |
import com.sun.corba.se.impl.logging.UtilSystemException ;
|
|
78 |
import com.sun.corba.se.impl.logging.OMGSystemException ;
|
|
79 |
|
|
80 |
/**
|
|
81 |
* Handy class full of static functions.
|
|
82 |
*/
|
|
83 |
public final class Utility {
|
|
84 |
|
|
85 |
public static final String STUB_PREFIX = "_";
|
|
86 |
public static final String RMI_STUB_SUFFIX = "_Stub";
|
|
87 |
public static final String DYNAMIC_STUB_SUFFIX = "_DynamicStub" ;
|
|
88 |
public static final String IDL_STUB_SUFFIX = "Stub";
|
|
89 |
public static final String TIE_SUFIX = "_Tie";
|
|
90 |
private static IdentityHashtable tieCache = new IdentityHashtable();
|
|
91 |
private static IdentityHashtable tieToStubCache = new IdentityHashtable();
|
|
92 |
private static IdentityHashtable stubToTieCache = new IdentityHashtable();
|
|
93 |
private static Object CACHE_MISS = new Object();
|
|
94 |
private static UtilSystemException wrapper = UtilSystemException.get(
|
|
95 |
CORBALogDomains.UTIL ) ;
|
|
96 |
private static OMGSystemException omgWrapper = OMGSystemException.get(
|
|
97 |
CORBALogDomains.UTIL ) ;
|
|
98 |
|
|
99 |
/**
|
|
100 |
* Ensure that stubs, ties, and implementation objects
|
|
101 |
* are 'connected' to the runtime. Converts implementation
|
|
102 |
* objects to a type suitable for sending on the wire.
|
|
103 |
* @param obj the object to connect.
|
|
104 |
* @param orb the ORB to connect to if obj is exported to IIOP.
|
|
105 |
* @param convertToStub true if implementation types should be
|
|
106 |
* converted to Stubs rather than just org.omg.CORBA.Object.
|
|
107 |
* @return the connected object.
|
|
108 |
* @exception NoSuchObjectException if obj is an implementation
|
|
109 |
* which has not been exported.
|
|
110 |
*/
|
|
111 |
public static Object autoConnect(Object obj, ORB orb, boolean convertToStub)
|
|
112 |
{
|
|
113 |
if (obj == null) {
|
|
114 |
return obj;
|
|
115 |
}
|
|
116 |
|
|
117 |
if (StubAdapter.isStub(obj)) {
|
|
118 |
try {
|
|
119 |
StubAdapter.getDelegate(obj) ;
|
|
120 |
} catch (BAD_OPERATION okay) {
|
|
121 |
try {
|
|
122 |
StubAdapter.connect( obj, orb ) ;
|
|
123 |
} catch (RemoteException e) {
|
|
124 |
// The stub could not be connected because it
|
|
125 |
// has an invalid IOR...
|
|
126 |
throw wrapper.objectNotConnected( e,
|
|
127 |
obj.getClass().getName() ) ;
|
|
128 |
}
|
|
129 |
}
|
|
130 |
|
|
131 |
return obj;
|
|
132 |
}
|
|
133 |
|
|
134 |
if (obj instanceof Remote) {
|
|
135 |
Remote remoteObj = (Remote)obj;
|
|
136 |
Tie theTie = Util.getTie(remoteObj);
|
|
137 |
if (theTie != null) {
|
|
138 |
try {
|
|
139 |
theTie.orb();
|
|
140 |
} catch (SystemException okay) {
|
|
141 |
theTie.orb(orb);
|
|
142 |
}
|
|
143 |
|
|
144 |
if (convertToStub) {
|
|
145 |
Object result = loadStub(theTie,null,null,true);
|
|
146 |
if (result != null) {
|
|
147 |
return result;
|
|
148 |
} else {
|
|
149 |
throw wrapper.couldNotLoadStub(obj.getClass().getName());
|
|
150 |
}
|
|
151 |
} else {
|
|
152 |
return StubAdapter.activateTie( theTie );
|
|
153 |
}
|
|
154 |
} else {
|
|
155 |
// This is an implementation object which has not been
|
|
156 |
// exported to IIOP OR is a JRMP stub or implementation
|
|
157 |
// object which cannot be marshalled into an ORB stream...
|
|
158 |
throw wrapper.objectNotExported( obj.getClass().getName() ) ;
|
|
159 |
}
|
|
160 |
}
|
|
161 |
|
|
162 |
// Didn't need to do anything, just return the input...
|
|
163 |
|
|
164 |
return obj;
|
|
165 |
}
|
|
166 |
|
|
167 |
/*
|
|
168 |
* Get a new instance of an RMI-IIOP Tie for the
|
|
169 |
* given server object.
|
|
170 |
*/
|
|
171 |
public static Tie loadTie(Remote obj) {
|
|
172 |
Tie result = null;
|
|
173 |
Class objClass = obj.getClass();
|
|
174 |
|
|
175 |
// Have we tried to find this guy before?
|
|
176 |
|
|
177 |
synchronized (tieCache) {
|
|
178 |
|
|
179 |
Object it = tieCache.get(obj);
|
|
180 |
|
|
181 |
if (it == null) {
|
|
182 |
|
|
183 |
// No, so try it...
|
|
184 |
|
|
185 |
try {
|
|
186 |
|
|
187 |
// First try the classname...
|
|
188 |
|
|
189 |
result = loadTie(objClass);
|
|
190 |
|
|
191 |
// If we don't have a valid tie at this point,
|
|
192 |
// walk up the parent chain until we either
|
|
193 |
// load a tie or encounter PortableRemoteObject
|
|
194 |
// or java.lang.Object...
|
|
195 |
|
|
196 |
while (result == null &&
|
|
197 |
(objClass = objClass.getSuperclass()) != null &&
|
|
198 |
objClass != PortableRemoteObject.class &&
|
|
199 |
objClass != Object.class) {
|
|
200 |
|
|
201 |
result = loadTie(objClass);
|
|
202 |
}
|
|
203 |
} catch (Exception ex) {
|
|
204 |
wrapper.loadTieFailed( ex, objClass.getName() ) ;
|
|
205 |
}
|
|
206 |
|
|
207 |
// Did we get it?
|
|
208 |
|
|
209 |
if (result == null) {
|
|
210 |
|
|
211 |
// Nope, so cache that fact...
|
|
212 |
|
|
213 |
tieCache.put(obj,CACHE_MISS);
|
|
214 |
|
|
215 |
} else {
|
|
216 |
|
|
217 |
// Yes, so cache it...
|
|
218 |
|
|
219 |
tieCache.put(obj,result);
|
|
220 |
}
|
|
221 |
} else {
|
|
222 |
|
|
223 |
// Yes, return a new instance or fail again if
|
|
224 |
// it was a miss last time...
|
|
225 |
|
|
226 |
if (it != CACHE_MISS) {
|
|
227 |
try {
|
|
228 |
result = (Tie) it.getClass().newInstance();
|
|
229 |
} catch (Exception e) {
|
|
230 |
}
|
|
231 |
}
|
|
232 |
}
|
|
233 |
}
|
|
234 |
|
|
235 |
return result;
|
|
236 |
}
|
|
237 |
|
|
238 |
/*
|
|
239 |
* Load an RMI-IIOP Tie
|
|
240 |
*/
|
|
241 |
private static Tie loadTie(Class theClass)
|
|
242 |
{
|
|
243 |
return com.sun.corba.se.spi.orb.ORB.getStubFactoryFactory().
|
|
244 |
getTie( theClass ) ;
|
|
245 |
}
|
|
246 |
|
|
247 |
/*
|
|
248 |
* Clear the stub/tie caches. Intended for use by
|
|
249 |
* test code.
|
|
250 |
*/
|
|
251 |
public static void clearCaches() {
|
|
252 |
synchronized (tieToStubCache) {
|
|
253 |
tieToStubCache.clear();
|
|
254 |
}
|
|
255 |
synchronized (tieCache) {
|
|
256 |
tieCache.clear();
|
|
257 |
}
|
|
258 |
synchronized (stubToTieCache) {
|
|
259 |
stubToTieCache.clear();
|
|
260 |
}
|
|
261 |
}
|
|
262 |
|
|
263 |
/*
|
|
264 |
* Load a class and check that it is assignable to a given type.
|
|
265 |
* @param className the class name.
|
|
266 |
* @param remoteCodebase the codebase to use. May be null.
|
|
267 |
* @param loader the class loader of last resort. May be null.
|
|
268 |
* @param expectedType the expected type. May be null.
|
|
269 |
* @return the loaded class.
|
|
270 |
*/
|
|
271 |
static Class loadClassOfType(String className, String remoteCodebase,
|
|
272 |
ClassLoader loader, Class expectedType,
|
|
273 |
ClassLoader expectedTypeClassLoader) throws ClassNotFoundException
|
|
274 |
{
|
|
275 |
Class loadedClass = null;
|
|
276 |
|
|
277 |
try {
|
|
278 |
//Sequence finding of the stubs according to spec
|
|
279 |
try{
|
|
280 |
//If-else is put here for speed up of J2EE.
|
|
281 |
//According to the OMG spec, the if clause is not dead code.
|
|
282 |
//It can occur if some compiler has allowed generation
|
|
283 |
//into org.omg.stub hierarchy for non-offending
|
|
284 |
//classes. This will encourage people to
|
|
285 |
//produce non-offending class stubs in their own hierarchy.
|
|
286 |
if (!PackagePrefixChecker.hasOffendingPrefix(
|
|
287 |
PackagePrefixChecker.withoutPackagePrefix(className))){
|
|
288 |
loadedClass = Util.loadClass(
|
|
289 |
PackagePrefixChecker.withoutPackagePrefix(className),
|
|
290 |
remoteCodebase,
|
|
291 |
loader);
|
|
292 |
} else {
|
|
293 |
loadedClass = Util.loadClass(className, remoteCodebase,
|
|
294 |
loader);
|
|
295 |
}
|
|
296 |
} catch (ClassNotFoundException cnfe) {
|
|
297 |
loadedClass = Util.loadClass(className, remoteCodebase,
|
|
298 |
loader);
|
|
299 |
}
|
|
300 |
if (expectedType == null)
|
|
301 |
return loadedClass;
|
|
302 |
} catch (ClassNotFoundException cnfe) {
|
|
303 |
if (expectedType == null)
|
|
304 |
throw cnfe;
|
|
305 |
}
|
|
306 |
|
|
307 |
// If no class was loaded, or if the loaded class is not of the
|
|
308 |
// correct type, make a further attempt to load the correct class
|
|
309 |
// using the classloader of the expected type.
|
|
310 |
// _REVISIT_ Is this step necessary, or should the Util,loadClass
|
|
311 |
// algorithm always produce a valid class if the setup is correct?
|
|
312 |
// Does the OMG standard algorithm need to be changed to include
|
|
313 |
// this step?
|
|
314 |
if (loadedClass == null || !expectedType.isAssignableFrom(loadedClass)){
|
|
315 |
if (expectedType.getClassLoader() != expectedTypeClassLoader)
|
|
316 |
throw new IllegalArgumentException(
|
|
317 |
"expectedTypeClassLoader not class loader of " +
|
|
318 |
"expected Type.");
|
|
319 |
|
|
320 |
if (expectedTypeClassLoader != null)
|
|
321 |
loadedClass = expectedTypeClassLoader.loadClass(className);
|
|
322 |
else {
|
|
323 |
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
|
324 |
if (cl == null)
|
|
325 |
cl = ClassLoader.getSystemClassLoader();
|
|
326 |
|
|
327 |
loadedClass = cl.loadClass(className);
|
|
328 |
}
|
|
329 |
}
|
|
330 |
|
|
331 |
return loadedClass;
|
|
332 |
}
|
|
333 |
|
|
334 |
/*
|
|
335 |
* Load a class and check that it is compatible with a given type.
|
|
336 |
* @param className the class name.
|
|
337 |
* @param remoteCodebase the codebase to use. May be null.
|
|
338 |
* @param loadingContext the loading context. May be null.
|
|
339 |
* @param relatedType the related type. May be null.
|
|
340 |
* @return the loaded class.
|
|
341 |
*/
|
|
342 |
public static Class loadClassForClass (String className,
|
|
343 |
String remoteCodebase,
|
|
344 |
ClassLoader loader,
|
|
345 |
Class relatedType,
|
|
346 |
ClassLoader relatedTypeClassLoader)
|
|
347 |
throws ClassNotFoundException
|
|
348 |
{
|
|
349 |
if (relatedType == null)
|
|
350 |
return Util.loadClass(className, remoteCodebase, loader);
|
|
351 |
|
|
352 |
Class loadedClass = null;
|
|
353 |
try {
|
|
354 |
loadedClass = Util.loadClass(className, remoteCodebase, loader);
|
|
355 |
} catch (ClassNotFoundException cnfe) {
|
|
356 |
if (relatedType.getClassLoader() == null)
|
|
357 |
throw cnfe;
|
|
358 |
}
|
|
359 |
|
|
360 |
// If no class was not loaded, or if the loaded class is not of the
|
|
361 |
// correct type, make a further attempt to load the correct class
|
|
362 |
// using the classloader of the related type.
|
|
363 |
// _REVISIT_ Is this step necessary, or should the Util,loadClass
|
|
364 |
// algorithm always produce a valid class if the setup is correct?
|
|
365 |
// Does the OMG standard algorithm need to be changed to include
|
|
366 |
// this step?
|
|
367 |
if (loadedClass == null ||
|
|
368 |
(loadedClass.getClassLoader() != null &&
|
|
369 |
loadedClass.getClassLoader().loadClass(relatedType.getName()) !=
|
|
370 |
relatedType))
|
|
371 |
{
|
|
372 |
if (relatedType.getClassLoader() != relatedTypeClassLoader)
|
|
373 |
throw new IllegalArgumentException(
|
|
374 |
"relatedTypeClassLoader not class loader of relatedType.");
|
|
375 |
|
|
376 |
if (relatedTypeClassLoader != null)
|
|
377 |
loadedClass = relatedTypeClassLoader.loadClass(className);
|
|
378 |
}
|
|
379 |
|
|
380 |
return loadedClass;
|
|
381 |
}
|
|
382 |
|
|
383 |
/**
|
|
384 |
* Get the helper for an IDLValue
|
|
385 |
*
|
|
386 |
* Throws MARSHAL exception if no helper found.
|
|
387 |
*/
|
|
388 |
public static BoxedValueHelper getHelper(Class clazz, String codebase,
|
|
389 |
String repId)
|
|
390 |
{
|
|
391 |
String className = null;
|
|
392 |
if (clazz != null) {
|
|
393 |
className = clazz.getName();
|
|
394 |
if (codebase == null)
|
|
395 |
codebase = Util.getCodebase(clazz);
|
|
396 |
} else {
|
|
397 |
if (repId != null)
|
|
398 |
className = RepositoryId.cache.getId(repId).getClassName();
|
|
399 |
if (className == null) // no repId or unrecognized repId
|
|
400 |
throw wrapper.unableLocateValueHelper(
|
|
401 |
CompletionStatus.COMPLETED_MAYBE);
|
|
402 |
}
|
|
403 |
|
|
404 |
try {
|
|
405 |
ClassLoader clazzLoader =
|
|
406 |
(clazz == null ? null : clazz.getClassLoader());
|
|
407 |
Class helperClass =
|
|
408 |
loadClassForClass(className+"Helper", codebase, clazzLoader,
|
|
409 |
clazz, clazzLoader);
|
|
410 |
return (BoxedValueHelper)helperClass.newInstance();
|
|
411 |
|
|
412 |
} catch (ClassNotFoundException cnfe) {
|
|
413 |
throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE,
|
|
414 |
cnfe );
|
|
415 |
} catch (IllegalAccessException iae) {
|
|
416 |
throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE,
|
|
417 |
iae );
|
|
418 |
} catch (InstantiationException ie) {
|
|
419 |
throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE,
|
|
420 |
ie );
|
|
421 |
} catch (ClassCastException cce) {
|
|
422 |
throw wrapper.unableLocateValueHelper( CompletionStatus.COMPLETED_MAYBE,
|
|
423 |
cce );
|
|
424 |
}
|
|
425 |
}
|
|
426 |
|
|
427 |
/**
|
|
428 |
* Get the factory for an IDLValue
|
|
429 |
*
|
|
430 |
* Throws MARSHAL exception if no factory found.
|
|
431 |
*/
|
|
432 |
public static ValueFactory getFactory(Class clazz, String codebase,
|
|
433 |
ORB orb, String repId)
|
|
434 |
{
|
|
435 |
ValueFactory factory = null;
|
|
436 |
if ((orb != null) && (repId != null)) {
|
|
437 |
try {
|
|
438 |
factory = ((org.omg.CORBA_2_3.ORB)orb).lookup_value_factory(
|
|
439 |
repId);
|
|
440 |
} catch (org.omg.CORBA.BAD_PARAM ex) {
|
|
441 |
// Try other way
|
|
442 |
}
|
|
443 |
}
|
|
444 |
|
|
445 |
String className = null;
|
|
446 |
if (clazz != null) {
|
|
447 |
className = clazz.getName();
|
|
448 |
if (codebase == null)
|
|
449 |
codebase = Util.getCodebase(clazz);
|
|
450 |
} else {
|
|
451 |
if (repId != null)
|
|
452 |
className = RepositoryId.cache.getId(repId).getClassName();
|
|
453 |
if (className == null) // no repId or unrecognized repId
|
|
454 |
throw omgWrapper.unableLocateValueFactory(
|
|
455 |
CompletionStatus.COMPLETED_MAYBE);
|
|
456 |
}
|
|
457 |
|
|
458 |
// if earlier search found a non-default factory, or the same default
|
|
459 |
// factory that loadClassForClass would return, bale out now...
|
|
460 |
if (factory != null &&
|
|
461 |
(!factory.getClass().getName().equals(className+"DefaultFactory") ||
|
|
462 |
(clazz == null && codebase == null)))
|
|
463 |
return factory;
|
|
464 |
|
|
465 |
try {
|
|
466 |
ClassLoader clazzLoader =
|
|
467 |
(clazz == null ? null : clazz.getClassLoader());
|
|
468 |
Class factoryClass =
|
|
469 |
loadClassForClass(className+"DefaultFactory", codebase,
|
|
470 |
clazzLoader, clazz, clazzLoader);
|
|
471 |
return (ValueFactory)factoryClass.newInstance();
|
|
472 |
|
|
473 |
} catch (ClassNotFoundException cnfe) {
|
|
474 |
throw omgWrapper.unableLocateValueFactory(
|
|
475 |
CompletionStatus.COMPLETED_MAYBE, cnfe);
|
|
476 |
} catch (IllegalAccessException iae) {
|
|
477 |
throw omgWrapper.unableLocateValueFactory(
|
|
478 |
CompletionStatus.COMPLETED_MAYBE, iae);
|
|
479 |
} catch (InstantiationException ie) {
|
|
480 |
throw omgWrapper.unableLocateValueFactory(
|
|
481 |
CompletionStatus.COMPLETED_MAYBE, ie);
|
|
482 |
} catch (ClassCastException cce) {
|
|
483 |
throw omgWrapper.unableLocateValueFactory(
|
|
484 |
CompletionStatus.COMPLETED_MAYBE, cce);
|
|
485 |
}
|
|
486 |
}
|
|
487 |
|
|
488 |
/*
|
|
489 |
* Load an RMI-IIOP Stub given a Tie.
|
|
490 |
* @param tie the tie.
|
|
491 |
* @param stubClass the stub class. May be null.
|
|
492 |
* @param remoteCodebase the codebase to use. May be null.
|
|
493 |
* @param onlyMostDerived if true, will fail if cannot load a stub for the
|
|
494 |
* first repID in the tie. If false, will walk all repIDs.
|
|
495 |
* @return the stub or null if not found.
|
|
496 |
*/
|
|
497 |
|
|
498 |
public static Remote loadStub(Tie tie,
|
|
499 |
PresentationManager.StubFactory stubFactory,
|
|
500 |
String remoteCodebase,
|
|
501 |
boolean onlyMostDerived)
|
|
502 |
{
|
|
503 |
StubEntry entry = null;
|
|
504 |
|
|
505 |
// Do we already have it cached?
|
|
506 |
synchronized (tieToStubCache) {
|
|
507 |
Object cached = tieToStubCache.get(tie);
|
|
508 |
if (cached == null) {
|
|
509 |
// No, so go try to load it...
|
|
510 |
entry = loadStubAndUpdateCache(
|
|
511 |
tie, stubFactory, remoteCodebase, onlyMostDerived);
|
|
512 |
} else {
|
|
513 |
// Yes, is it a stub? If not, it was a miss last
|
|
514 |
// time, so return null again...
|
|
515 |
if (cached != CACHE_MISS) {
|
|
516 |
// It's a stub.
|
|
517 |
entry = (StubEntry) cached;
|
|
518 |
|
|
519 |
// Does the cached stub meet the requirements
|
|
520 |
// of the caller? If the caller does not require
|
|
521 |
// the most derived stub and does not require
|
|
522 |
// a specific stub type, we don't have to check
|
|
523 |
// any further because the cached type is good
|
|
524 |
// enough...
|
|
525 |
if (!entry.mostDerived && onlyMostDerived) {
|
|
526 |
// We must reload because we do not have
|
|
527 |
// the most derived cached already...
|
|
528 |
// The stubFactory arg must be null here
|
|
529 |
// to force onlyMostDerived=true to work
|
|
530 |
// correctly.
|
|
531 |
entry = loadStubAndUpdateCache(tie,null,
|
|
532 |
remoteCodebase,true);
|
|
533 |
} else if (stubFactory != null &&
|
|
534 |
!StubAdapter.getTypeIds(entry.stub)[0].equals(
|
|
535 |
stubFactory.getTypeIds()[0]) )
|
|
536 |
{
|
|
537 |
// We do not have exactly the right stub. First, try to
|
|
538 |
// upgrade the cached stub by forcing it to the most
|
|
539 |
// derived stub...
|
|
540 |
entry = loadStubAndUpdateCache(tie,null,
|
|
541 |
remoteCodebase,true);
|
|
542 |
|
|
543 |
// If that failed, try again with the exact type
|
|
544 |
// we need...
|
|
545 |
if (entry == null) {
|
|
546 |
entry = loadStubAndUpdateCache(tie,stubFactory,
|
|
547 |
remoteCodebase,onlyMostDerived);
|
|
548 |
}
|
|
549 |
} else {
|
|
550 |
// Use the cached stub. Is the delegate set?
|
|
551 |
try {
|
|
552 |
Delegate stubDel = StubAdapter.getDelegate(
|
|
553 |
entry.stub ) ;
|
|
554 |
} catch (Exception e2) {
|
|
555 |
// No, so set it if we can...
|
|
556 |
try {
|
|
557 |
Delegate del = StubAdapter.getDelegate(
|
|
558 |
tie ) ;
|
|
559 |
StubAdapter.setDelegate( entry.stub,
|
|
560 |
del ) ;
|
|
561 |
} catch (Exception e) {}
|
|
562 |
}
|
|
563 |
}
|
|
564 |
}
|
|
565 |
}
|
|
566 |
}
|
|
567 |
|
|
568 |
if (entry != null) {
|
|
569 |
return (Remote)entry.stub;
|
|
570 |
} else {
|
|
571 |
return null;
|
|
572 |
}
|
|
573 |
}
|
|
574 |
|
|
575 |
/*
|
|
576 |
* Load an RMI-IIOP Stub given a Tie, but do not look in the cache.
|
|
577 |
* This method must be called with the lock held for tieToStubCache.
|
|
578 |
* @param tie the tie.
|
|
579 |
* @param stubFactory the stub factory. May be null.
|
|
580 |
* @param remoteCodebase the codebase to use. May be null.
|
|
581 |
* @param onlyMostDerived if true, will fail if cannot load a stub for the
|
|
582 |
* first repID in the tie. If false, will walk all repIDs.
|
|
583 |
* @return the StubEntry or null if not found.
|
|
584 |
*/
|
|
585 |
private static StubEntry loadStubAndUpdateCache (
|
|
586 |
Tie tie, PresentationManager.StubFactory stubFactory,
|
|
587 |
String remoteCodebase, boolean onlyMostDerived)
|
|
588 |
{
|
|
589 |
org.omg.CORBA.Object stub = null;
|
|
590 |
StubEntry entry = null;
|
|
591 |
boolean tieIsStub = StubAdapter.isStub( tie ) ;
|
|
592 |
|
|
593 |
if (stubFactory != null) {
|
|
594 |
try {
|
|
595 |
stub = stubFactory.makeStub();
|
|
596 |
} catch (Throwable e) {
|
|
597 |
wrapper.stubFactoryCouldNotMakeStub( e ) ;
|
|
598 |
if (e instanceof ThreadDeath) {
|
|
599 |
throw (ThreadDeath) e;
|
|
600 |
}
|
|
601 |
}
|
|
602 |
} else {
|
|
603 |
String[] ids = null;
|
|
604 |
if (tieIsStub) {
|
|
605 |
ids = StubAdapter.getTypeIds( tie ) ;
|
|
606 |
} else {
|
|
607 |
// This will throw an exception if the tie
|
|
608 |
// is not a Servant. XXX Handle this better?
|
|
609 |
ids = ((org.omg.PortableServer.Servant)tie).
|
|
610 |
_all_interfaces( null, null );
|
|
611 |
}
|
|
612 |
|
|
613 |
if (remoteCodebase == null) {
|
|
614 |
remoteCodebase = Util.getCodebase(tie.getClass());
|
|
615 |
}
|
|
616 |
|
|
617 |
if (ids.length == 0) {
|
|
618 |
stub = new org.omg.stub.java.rmi._Remote_Stub();
|
|
619 |
} else {
|
|
620 |
// Now walk all the RepIDs till we find a stub or fail...
|
|
621 |
for (int i = 0; i < ids.length; i++) {
|
|
622 |
if (ids[i].length() == 0) {
|
|
623 |
stub = new org.omg.stub.java.rmi._Remote_Stub();
|
|
624 |
break;
|
|
625 |
}
|
|
626 |
|
|
627 |
try {
|
|
628 |
PresentationManager.StubFactoryFactory stubFactoryFactory =
|
|
629 |
com.sun.corba.se.spi.orb.ORB.getStubFactoryFactory();
|
|
630 |
RepositoryId rid = RepositoryId.cache.getId( ids[i] ) ;
|
|
631 |
String className = rid.getClassName() ;
|
|
632 |
boolean isIDLInterface = rid.isIDLType() ;
|
|
633 |
stubFactory = stubFactoryFactory.createStubFactory(
|
|
634 |
className, isIDLInterface, remoteCodebase, null,
|
|
635 |
tie.getClass().getClassLoader() ) ;
|
|
636 |
stub = stubFactory.makeStub();
|
|
637 |
break;
|
|
638 |
} catch (Exception e) {
|
|
639 |
wrapper.errorInMakeStubFromRepositoryId( e ) ;
|
|
640 |
}
|
|
641 |
|
|
642 |
if (onlyMostDerived)
|
|
643 |
break;
|
|
644 |
}
|
|
645 |
}
|
|
646 |
}
|
|
647 |
|
|
648 |
if (stub == null) {
|
|
649 |
// Stub == null, so cache the miss...
|
|
650 |
tieToStubCache.put(tie,CACHE_MISS);
|
|
651 |
} else {
|
|
652 |
if (tieIsStub) {
|
|
653 |
try {
|
|
654 |
Delegate del = StubAdapter.getDelegate( tie ) ;
|
|
655 |
StubAdapter.setDelegate( stub, del ) ;
|
|
656 |
} catch( Exception e1 ) {
|
|
657 |
// The tie does not have a delegate set, so stash
|
|
658 |
// this tie away using the stub as a key so that
|
|
659 |
// later, when the stub is connected, we can find
|
|
660 |
// and connect the tie as well...
|
|
661 |
|
|
662 |
synchronized (stubToTieCache) {
|
|
663 |
stubToTieCache.put(stub,tie);
|
|
664 |
}
|
|
665 |
}
|
|
666 |
} else {
|
|
667 |
// Tie extends Servant
|
|
668 |
try {
|
|
669 |
Delegate delegate = StubAdapter.getDelegate( tie ) ;
|
|
670 |
StubAdapter.setDelegate( stub, delegate ) ;
|
|
671 |
} catch( org.omg.CORBA.BAD_INV_ORDER bad) {
|
|
672 |
synchronized (stubToTieCache) {
|
|
673 |
stubToTieCache.put(stub,tie);
|
|
674 |
}
|
|
675 |
} catch( Exception e ) {
|
|
676 |
// Exception is caught because of any of the
|
|
677 |
// following reasons
|
|
678 |
// 1) POA is not associated with the TIE
|
|
679 |
// 2) POA Policies for the tie-associated POA
|
|
680 |
// does not support _this_object() call.
|
|
681 |
throw wrapper.noPoa( e ) ;
|
|
682 |
}
|
|
683 |
}
|
|
684 |
// Update the cache...
|
|
685 |
entry = new StubEntry(stub,onlyMostDerived);
|
|
686 |
tieToStubCache.put(tie,entry);
|
|
687 |
}
|
|
688 |
|
|
689 |
return entry;
|
|
690 |
}
|
|
691 |
|
|
692 |
/*
|
|
693 |
* If we loadStub(Tie,...) stashed away a tie which was
|
|
694 |
* not connected, remove it from the cache and return
|
|
695 |
* it.
|
|
696 |
*/
|
|
697 |
public static Tie getAndForgetTie (org.omg.CORBA.Object stub) {
|
|
698 |
synchronized (stubToTieCache) {
|
|
699 |
return (Tie) stubToTieCache.remove(stub);
|
|
700 |
}
|
|
701 |
}
|
|
702 |
|
|
703 |
/*
|
|
704 |
* Remove any cached Stub for the given tie.
|
|
705 |
*/
|
|
706 |
public static void purgeStubForTie (Tie tie) {
|
|
707 |
StubEntry entry;
|
|
708 |
synchronized (tieToStubCache) {
|
|
709 |
entry = (StubEntry)tieToStubCache.remove(tie);
|
|
710 |
}
|
|
711 |
if (entry != null) {
|
|
712 |
synchronized (stubToTieCache) {
|
|
713 |
stubToTieCache.remove(entry.stub);
|
|
714 |
}
|
|
715 |
}
|
|
716 |
}
|
|
717 |
|
|
718 |
/*
|
|
719 |
* Remove cached tie/servant pair.
|
|
720 |
*/
|
|
721 |
public static void purgeTieAndServant (Tie tie) {
|
|
722 |
synchronized (tieCache) {
|
|
723 |
Object target = tie.getTarget();
|
|
724 |
if (target != null)
|
|
725 |
tieCache.remove(target);
|
|
726 |
}
|
|
727 |
}
|
|
728 |
|
|
729 |
/*
|
|
730 |
* Convert a RepId to a stubName...
|
|
731 |
*/
|
|
732 |
public static String stubNameFromRepID (String repID) {
|
|
733 |
|
|
734 |
// Convert the typeid to a RepositoryId instance, get
|
|
735 |
// the className and mangle it as needed...
|
|
736 |
|
|
737 |
RepositoryId id = RepositoryId.cache.getId(repID);
|
|
738 |
String className = id.getClassName();
|
|
739 |
|
|
740 |
if (id.isIDLType()) {
|
|
741 |
className = idlStubName(className);
|
|
742 |
} else {
|
|
743 |
className = stubName(className);
|
|
744 |
}
|
|
745 |
return className;
|
|
746 |
}
|
|
747 |
|
|
748 |
|
|
749 |
/*
|
|
750 |
* Load an RMI-IIOP Stub. This is used in PortableRemoteObject.narrow.
|
|
751 |
*/
|
|
752 |
public static Remote loadStub (org.omg.CORBA.Object narrowFrom,
|
|
753 |
Class narrowTo)
|
|
754 |
{
|
|
755 |
Remote result = null;
|
|
756 |
|
|
757 |
try {
|
|
758 |
// Get the codebase from the delegate to use when loading
|
|
759 |
// the new stub, if possible...
|
|
760 |
String codebase = null;
|
|
761 |
try {
|
|
762 |
// We can't assume that narrowFrom is a CORBA_2_3 stub, yet
|
|
763 |
// it may have a 2_3 Delegate that provides a codebase. Swallow
|
|
764 |
// the ClassCastException otherwise.
|
|
765 |
Delegate delegate = StubAdapter.getDelegate( narrowFrom ) ;
|
|
766 |
codebase = ((org.omg.CORBA_2_3.portable.Delegate)delegate).
|
|
767 |
get_codebase(narrowFrom);
|
|
768 |
|
|
769 |
} catch (ClassCastException e) {
|
|
770 |
wrapper.classCastExceptionInLoadStub( e ) ;
|
|
771 |
}
|
|
772 |
|
|
773 |
PresentationManager.StubFactoryFactory sff =
|
|
774 |
com.sun.corba.se.spi.orb.ORB.getStubFactoryFactory() ;
|
|
775 |
PresentationManager.StubFactory sf = sff.createStubFactory(
|
|
776 |
narrowTo.getName(), false, codebase, narrowTo,
|
|
777 |
narrowTo.getClassLoader() ) ;
|
|
778 |
result = (Remote)sf.makeStub() ;
|
|
779 |
StubAdapter.setDelegate( result,
|
|
780 |
StubAdapter.getDelegate( narrowFrom ) ) ;
|
|
781 |
} catch (Exception err) {
|
|
782 |
wrapper.exceptionInLoadStub( err ) ;
|
|
783 |
}
|
|
784 |
|
|
785 |
return result;
|
|
786 |
}
|
|
787 |
|
|
788 |
/*
|
|
789 |
* Load an RMI-IIOP Stub class. This is used in the
|
|
790 |
* StaticStubFactoryFactory code.
|
|
791 |
*/
|
|
792 |
public static Class loadStubClass(String repID,
|
|
793 |
String remoteCodebase,
|
|
794 |
Class expectedType)
|
|
795 |
throws ClassNotFoundException
|
|
796 |
{
|
|
797 |
// Get the repID and check for "" special case.
|
|
798 |
// We should never be called with it (See CDRInputStream
|
|
799 |
// and the loadStub() method)...
|
|
800 |
|
|
801 |
if (repID.length() == 0) {
|
|
802 |
throw new ClassNotFoundException();
|
|
803 |
}
|
|
804 |
|
|
805 |
// Get the stubname from the repID and load
|
|
806 |
// the class. If we have a valid 'sender', fall
|
|
807 |
// back to using its codebase if we need to...
|
|
808 |
String className = Utility.stubNameFromRepID(repID);
|
|
809 |
ClassLoader expectedTypeClassLoader = (expectedType == null ? null :
|
|
810 |
expectedType.getClassLoader());
|
|
811 |
|
|
812 |
try {
|
|
813 |
return loadClassOfType(className,
|
|
814 |
remoteCodebase,
|
|
815 |
expectedTypeClassLoader,
|
|
816 |
expectedType,
|
|
817 |
expectedTypeClassLoader);
|
|
818 |
} catch (ClassNotFoundException e) {
|
|
819 |
return loadClassOfType(PackagePrefixChecker.packagePrefix() + className,
|
|
820 |
remoteCodebase,
|
|
821 |
expectedTypeClassLoader,
|
|
822 |
expectedType,
|
|
823 |
expectedTypeClassLoader);
|
|
824 |
}
|
|
825 |
}
|
|
826 |
|
|
827 |
/**
|
|
828 |
* Create an RMI stub name.
|
|
829 |
*/
|
|
830 |
public static String stubName (String className)
|
|
831 |
{
|
|
832 |
return stubName( className, false ) ;
|
|
833 |
}
|
|
834 |
|
|
835 |
public static String dynamicStubName( String className )
|
|
836 |
{
|
|
837 |
return stubName( className, true ) ;
|
|
838 |
}
|
|
839 |
|
|
840 |
private static String stubName( String className,
|
|
841 |
boolean isDynamic )
|
|
842 |
{
|
|
843 |
String name = stubNameForCompiler( className, isDynamic ) ;
|
|
844 |
if (PackagePrefixChecker.hasOffendingPrefix( name ))
|
|
845 |
name = PackagePrefixChecker.packagePrefix() + name ;
|
|
846 |
return name ;
|
|
847 |
}
|
|
848 |
|
|
849 |
public static String stubNameForCompiler (String className)
|
|
850 |
{
|
|
851 |
return stubNameForCompiler( className, false ) ;
|
|
852 |
}
|
|
853 |
|
|
854 |
private static String stubNameForCompiler( String className,
|
|
855 |
boolean isDynamic )
|
|
856 |
{
|
|
857 |
int index = className.indexOf('$');
|
|
858 |
if (index < 0) {
|
|
859 |
index = className.lastIndexOf('.');
|
|
860 |
}
|
|
861 |
|
|
862 |
String suffix = isDynamic ? DYNAMIC_STUB_SUFFIX :
|
|
863 |
RMI_STUB_SUFFIX ;
|
|
864 |
|
|
865 |
if (index > 0) {
|
|
866 |
return className.substring(0,index+1) + STUB_PREFIX +
|
|
867 |
className.substring(index+1) + suffix;
|
|
868 |
} else {
|
|
869 |
return STUB_PREFIX + className + suffix;
|
|
870 |
}
|
|
871 |
}
|
|
872 |
|
|
873 |
/**
|
|
874 |
* Create an RMI tie name.
|
|
875 |
*/
|
|
876 |
public static String tieName (String className)
|
|
877 |
{
|
|
878 |
return
|
|
879 |
PackagePrefixChecker.hasOffendingPrefix(tieNameForCompiler(className)) ?
|
|
880 |
PackagePrefixChecker.packagePrefix() + tieNameForCompiler(className) :
|
|
881 |
tieNameForCompiler(className);
|
|
882 |
}
|
|
883 |
|
|
884 |
public static String tieNameForCompiler (String className)
|
|
885 |
{
|
|
886 |
int index = className.indexOf('$');
|
|
887 |
if (index < 0) {
|
|
888 |
index = className.lastIndexOf('.');
|
|
889 |
}
|
|
890 |
if (index > 0) {
|
|
891 |
return className.substring(0,index+1) +
|
|
892 |
STUB_PREFIX +
|
|
893 |
className.substring(index+1) +
|
|
894 |
TIE_SUFIX;
|
|
895 |
} else {
|
|
896 |
return STUB_PREFIX +
|
|
897 |
className +
|
|
898 |
TIE_SUFIX;
|
|
899 |
}
|
|
900 |
}
|
|
901 |
|
|
902 |
/**
|
|
903 |
* Throws the CORBA equivalent of a java.io.NotSerializableException
|
|
904 |
*/
|
|
905 |
public static void throwNotSerializableForCorba(String className) {
|
|
906 |
throw omgWrapper.notSerializable( CompletionStatus.COMPLETED_MAYBE,
|
|
907 |
className ) ;
|
|
908 |
}
|
|
909 |
|
|
910 |
/**
|
|
911 |
* Create an IDL stub name.
|
|
912 |
*/
|
|
913 |
public static String idlStubName(String className)
|
|
914 |
{
|
|
915 |
String result = null;
|
|
916 |
int index = className.lastIndexOf('.');
|
|
917 |
if (index > 0) {
|
|
918 |
result = className.substring(0,index+1) +
|
|
919 |
STUB_PREFIX +
|
|
920 |
className.substring(index+1) +
|
|
921 |
IDL_STUB_SUFFIX;
|
|
922 |
} else {
|
|
923 |
result = STUB_PREFIX +
|
|
924 |
className +
|
|
925 |
IDL_STUB_SUFFIX;
|
|
926 |
}
|
|
927 |
return result;
|
|
928 |
}
|
|
929 |
|
|
930 |
public static void printStackTrace()
|
|
931 |
{
|
|
932 |
Throwable thr = new Throwable( "Printing stack trace:" ) ;
|
|
933 |
thr.fillInStackTrace() ;
|
|
934 |
thr.printStackTrace() ;
|
|
935 |
}
|
|
936 |
|
|
937 |
/**
|
|
938 |
* Read an object reference from the input stream and narrow
|
|
939 |
* it to the desired type.
|
|
940 |
* @param in the stream to read from.
|
|
941 |
* @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
|
|
942 |
*/
|
|
943 |
public static Object readObjectAndNarrow(InputStream in,
|
|
944 |
Class narrowTo)
|
|
945 |
throws ClassCastException
|
|
946 |
{
|
|
947 |
Object result = in.read_Object();
|
|
948 |
if (result != null)
|
|
949 |
return PortableRemoteObject.narrow(result, narrowTo);
|
|
950 |
else
|
|
951 |
return null;
|
|
952 |
}
|
|
953 |
|
|
954 |
/**
|
|
955 |
* Read an abstract interface type from the input stream and narrow
|
|
956 |
* it to the desired type.
|
|
957 |
* @param in the stream to read from.
|
|
958 |
* @throws ClassCastException if narrowFrom cannot be cast to narrowTo.
|
|
959 |
*/
|
|
960 |
public static Object readAbstractAndNarrow(
|
|
961 |
org.omg.CORBA_2_3.portable.InputStream in, Class narrowTo)
|
|
962 |
throws ClassCastException
|
|
963 |
{
|
|
964 |
Object result = in.read_abstract_interface();
|
|
965 |
if (result != null)
|
|
966 |
return PortableRemoteObject.narrow(result, narrowTo);
|
|
967 |
else
|
|
968 |
return null;
|
|
969 |
}
|
|
970 |
|
|
971 |
|
|
972 |
/** Converts an Ascii Character into Hexadecimal digit
|
|
973 |
*/
|
|
974 |
static int hexOf( char x )
|
|
975 |
{
|
|
976 |
int val;
|
|
977 |
|
|
978 |
val = x - '0';
|
|
979 |
if (val >=0 && val <= 9)
|
|
980 |
return val;
|
|
981 |
|
|
982 |
val = (x - 'a') + 10;
|
|
983 |
if (val >= 10 && val <= 15)
|
|
984 |
return val;
|
|
985 |
|
|
986 |
val = (x - 'A') + 10;
|
|
987 |
if (val >= 10 && val <= 15)
|
|
988 |
return val;
|
|
989 |
|
|
990 |
throw wrapper.badHexDigit() ;
|
|
991 |
}
|
|
992 |
}
|
|
993 |
|
|
994 |
class StubEntry {
|
|
995 |
org.omg.CORBA.Object stub;
|
|
996 |
boolean mostDerived;
|
|
997 |
|
|
998 |
StubEntry(org.omg.CORBA.Object stub, boolean mostDerived) {
|
|
999 |
this.stub = stub;
|
|
1000 |
this.mostDerived = mostDerived;
|
|
1001 |
}
|
|
1002 |
}
|