CorbaServerRequestDispatcherImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
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
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
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 *
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.
24 */
25/*
26 * Licensed Materials - Property of IBM
27 * RMI-IIOP v1.0
28 * Copyright IBM Corp. 1998 1999  All Rights Reserved
29 *
30 */
31
32
33package com.sun.corba.se.impl.protocol;
34
35import org.omg.PortableServer.Servant ;
36
37import org.omg.CORBA.SystemException;
38import org.omg.CORBA.INTERNAL;
39import org.omg.CORBA.UNKNOWN;
40import org.omg.CORBA.CompletionStatus;
41import org.omg.CORBA.Any;
42
43import org.omg.CORBA.portable.InvokeHandler;
44import org.omg.CORBA.portable.InputStream;
45import org.omg.CORBA.portable.OutputStream;
46import org.omg.CORBA.portable.UnknownException;
47import org.omg.CORBA.portable.ResponseHandler;
48
49import com.sun.org.omg.SendingContext.CodeBase;
50
51import com.sun.corba.se.pept.encoding.OutputObject;
52import com.sun.corba.se.pept.protocol.MessageMediator;
53
54import com.sun.corba.se.spi.orb.ORB;
55import com.sun.corba.se.spi.orb.ORBVersion;
56import com.sun.corba.se.spi.orb.ORBVersionFactory;
57import com.sun.corba.se.spi.ior.IOR ;
58import com.sun.corba.se.spi.ior.ObjectKey;
59import com.sun.corba.se.spi.ior.ObjectKeyTemplate;
60import com.sun.corba.se.spi.ior.ObjectAdapterId;
61import com.sun.corba.se.spi.oa.ObjectAdapterFactory;
62import com.sun.corba.se.spi.oa.ObjectAdapter;
63import com.sun.corba.se.spi.oa.OAInvocationInfo;
64import com.sun.corba.se.spi.oa.OADestroyed;
65import com.sun.corba.se.spi.oa.NullServant;
66import com.sun.corba.se.spi.protocol.CorbaMessageMediator;
67import com.sun.corba.se.spi.protocol.CorbaServerRequestDispatcher;
68import com.sun.corba.se.spi.protocol.ForwardException ;
69import com.sun.corba.se.spi.protocol.RequestDispatcherRegistry;
70import com.sun.corba.se.spi.transport.CorbaConnection;
71import com.sun.corba.se.spi.logging.CORBALogDomains;
72import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
73
74import com.sun.corba.se.impl.protocol.SpecialMethod ;
75import com.sun.corba.se.spi.servicecontext.ServiceContext;
76import com.sun.corba.se.spi.servicecontext.ServiceContexts;
77import com.sun.corba.se.spi.servicecontext.UEInfoServiceContext;
78import com.sun.corba.se.spi.servicecontext.CodeSetServiceContext;
79import com.sun.corba.se.spi.servicecontext.SendingContextServiceContext;
80import com.sun.corba.se.spi.servicecontext.ORBVersionServiceContext;
81
82import com.sun.corba.se.impl.corba.ServerRequestImpl ;
83import com.sun.corba.se.impl.encoding.MarshalInputStream;
84import com.sun.corba.se.impl.encoding.MarshalOutputStream;
85import com.sun.corba.se.impl.encoding.CodeSetComponentInfo;
86import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry;
87import com.sun.corba.se.impl.orbutil.ORBConstants;
88import com.sun.corba.se.impl.orbutil.ORBUtility;
89import com.sun.corba.se.impl.protocol.RequestCanceledException;
90import com.sun.corba.se.impl.logging.ORBUtilSystemException;
91import com.sun.corba.se.impl.logging.POASystemException;
92
93public class CorbaServerRequestDispatcherImpl
94    implements CorbaServerRequestDispatcher
95{
96    protected ORB orb; // my ORB instance
97    private ORBUtilSystemException wrapper ;
98    private POASystemException poaWrapper ;
99
100    // Added from last version because it broke the build - RTW
101    // XXX remove me and rebuild: probably no longer needed
102    // public static final int UNKNOWN_EXCEPTION_INFO_ID = 9;
103
104    public CorbaServerRequestDispatcherImpl(ORB orb)
105    {
106        this.orb = orb;
107        wrapper = ORBUtilSystemException.get( orb,
108            CORBALogDomains.RPC_PROTOCOL ) ;
109        poaWrapper = POASystemException.get( orb,
110            CORBALogDomains.RPC_PROTOCOL ) ;
111    }
112
113    /** XXX/REVISIT:
114     * We do not want to look for a servant in the POA/ServantManager case,
115     * but we could in most other cases.  The OA could have a method that
116     * returns true if the servant MAY exist, and false only if the servant
117     * definitely DOES NOT exist.
118     *
119     * XXX/REVISIT:
120     * We may wish to indicate OBJECT_HERE by some mechanism other than
121     * returning a null result.
122     *
123     * Called from ORB.locate when a LocateRequest arrives.
124     * Result is not always absolutely correct: may indicate OBJECT_HERE
125     * for non-existent objects, which is resolved on invocation.  This
126     * "bug" is unavoidable, since in general the object may be destroyed
127     * between a locate and a request.  Note that this only checks that
128     * the appropriate ObjectAdapter is available, not that the servant
129     * actually exists.
130     * Need to signal one of OBJECT_HERE, OBJECT_FORWARD, OBJECT_NOT_EXIST.
131     * @return Result is null if object is (possibly) implemented here, otherwise
132     * an IOR indicating objref to forward the request to.
133     * @exception OBJECT_NOT_EXIST is thrown if we know the object does not
134     * exist here, and we are not forwarding.
135     */
136    public IOR locate(ObjectKey okey)
137    {
138        try {
139            if (orb.subcontractDebugFlag)
140                dprint(".locate->");
141
142            ObjectKeyTemplate oktemp = okey.getTemplate() ;
143
144            try {
145                checkServerId(okey);
146            } catch (ForwardException fex) {
147                return fex.getIOR() ;
148            }
149
150            // Called only for its side-effect of throwing appropriate exceptions
151            findObjectAdapter(oktemp);
152
153            return null ;
154        } finally {
155            if (orb.subcontractDebugFlag)
156                dprint(".locate<-");
157        }
158    }
159
160    public void dispatch(MessageMediator messageMediator)
161    {
162        CorbaMessageMediator request = (CorbaMessageMediator) messageMediator;
163        try {
164            if (orb.subcontractDebugFlag) {
165                dprint(".dispatch->: " + opAndId(request));
166            }
167
168            // to set the codebase information, if any transmitted; and also
169            // appropriate ORB Version.
170            consumeServiceContexts(request);
171
172            // Now that we have the service contexts processed and the
173            // correct ORBVersion set, we must finish initializing the
174            // stream.
175            ((MarshalInputStream)request.getInputObject())
176                .performORBVersionSpecificInit();
177
178            ObjectKey okey = request.getObjectKey();
179
180            // Check that this server is the right server
181            try {
182                checkServerId(okey);
183            } catch (ForwardException fex) {
184                if (orb.subcontractDebugFlag) {
185                    dprint(".dispatch: " + opAndId(request)
186                           + ": bad server id");
187                }
188
189                request.getProtocolHandler()
190                    .createLocationForward(request, fex.getIOR(), null);
191                return;
192            }
193
194            String operation = request.getOperationName();
195            ObjectAdapter objectAdapter = null ;
196
197            try {
198                byte[] objectId = okey.getId().getId() ;
199                ObjectKeyTemplate oktemp = okey.getTemplate() ;
200                objectAdapter = findObjectAdapter(oktemp);
201
202                java.lang.Object servant = getServantWithPI(request, objectAdapter,
203                    objectId, oktemp, operation);
204
205                dispatchToServant(servant, request, objectId, objectAdapter);
206            } catch (ForwardException ex) {
207                if (orb.subcontractDebugFlag) {
208                    dprint(".dispatch: " + opAndId(request)
209                           + ": ForwardException caught");
210                }
211
212                // Thrown by Portable Interceptors from InterceptorInvoker,
213                // through Response constructor.
214                request.getProtocolHandler()
215                    .createLocationForward(request, ex.getIOR(), null);
216            } catch (OADestroyed ex) {
217                if (orb.subcontractDebugFlag) {
218                    dprint(".dispatch: " + opAndId(request)
219                           + ": OADestroyed exception caught");
220                }
221
222                // DO NOT CALL THIS HERE:
223                // releaseServant(objectAdapter);
224                // The problem is that OADestroyed is only thrown by oa.enter, in
225                // which case oa.exit should NOT be called, and neither should
226                // the invocationInfo stack be popped.
227
228                // Destroyed POAs can be recreated by normal adapter activation.
229                // So just restart the dispatch.
230                dispatch(request);
231            } catch (RequestCanceledException ex) {
232                if (orb.subcontractDebugFlag) {
233                    dprint(".dispatch: " + opAndId(request)
234                           + ": RequestCanceledException caught");
235                }
236
237                // IDLJ generated non-tie based skeletons do not catch the
238                // RequestCanceledException. Rethrow the exception, which will
239                // cause the worker thread to unwind the dispatch and wait for
240                // other requests.
241                throw ex;
242            } catch (UnknownException ex) {
243                if (orb.subcontractDebugFlag) {
244                    dprint(".dispatch: " + opAndId(request)
245                           + ": UnknownException caught " + ex);
246                }
247
248                // RMIC generated tie skeletons convert all Throwable exception
249                // types (including RequestCanceledException, ThreadDeath)
250                // thrown during reading fragments into UnknownException.
251                // If RequestCanceledException was indeed raised,
252                // then rethrow it, which will eventually cause the worker
253                // thread to unstack the dispatch and wait for other requests.
254                if (ex.originalEx instanceof RequestCanceledException) {
255                    throw (RequestCanceledException) ex.originalEx;
256                }
257
258                ServiceContexts contexts = new ServiceContexts(orb);
259                UEInfoServiceContext usc = new UEInfoServiceContext(
260                    ex.originalEx);
261
262                contexts.put( usc ) ;
263
264                SystemException sysex = wrapper.unknownExceptionInDispatch(
265                        CompletionStatus.COMPLETED_MAYBE, ex ) ;
266                request.getProtocolHandler()
267                    .createSystemExceptionResponse(request, sysex,
268                        contexts);
269            } catch (Throwable ex) {
270                if (orb.subcontractDebugFlag) {
271                    dprint(".dispatch: " + opAndId(request)
272                           + ": other exception " + ex);
273                }
274                request.getProtocolHandler()
275                    .handleThrowableDuringServerDispatch(
276                        request, ex, CompletionStatus.COMPLETED_MAYBE);
277            }
278            return;
279        } finally {
280            if (orb.subcontractDebugFlag) {
281                dprint(".dispatch<-: " + opAndId(request));
282            }
283        }
284    }
285
286    private void releaseServant(ObjectAdapter objectAdapter)
287    {
288        try {
289            if (orb.subcontractDebugFlag) {
290                dprint(".releaseServant->");
291            }
292
293            if (objectAdapter == null) {
294                if (orb.subcontractDebugFlag) {
295                    dprint(".releaseServant: null object adapter");
296                }
297                return ;
298            }
299
300            try {
301                objectAdapter.returnServant();
302            } finally {
303                objectAdapter.exit();
304                orb.popInvocationInfo() ;
305            }
306        } finally {
307            if (orb.subcontractDebugFlag) {
308                dprint(".releaseServant<-");
309            }
310        }
311    }
312
313    // Note that objectAdapter.enter() must be called before getServant.
314    private java.lang.Object getServant(ObjectAdapter objectAdapter, byte[] objectId,
315        String operation)
316        throws OADestroyed
317    {
318        try {
319            if (orb.subcontractDebugFlag) {
320                dprint(".getServant->");
321            }
322
323            OAInvocationInfo info = objectAdapter.makeInvocationInfo(objectId);
324            info.setOperation(operation);
325            orb.pushInvocationInfo(info);
326            objectAdapter.getInvocationServant(info);
327            return info.getServantContainer() ;
328        } finally {
329            if (orb.subcontractDebugFlag) {
330                dprint(".getServant<-");
331            }
332        }
333    }
334
335    protected java.lang.Object getServantWithPI(CorbaMessageMediator request,
336                                                 ObjectAdapter objectAdapter,
337        byte[] objectId, ObjectKeyTemplate oktemp, String operation)
338        throws OADestroyed
339    {
340        try {
341            if (orb.subcontractDebugFlag) {
342                dprint(".getServantWithPI->");
343            }
344
345            // Prepare Portable Interceptors for a new server request
346            // and invoke receive_request_service_contexts.  The starting
347            // point may throw a SystemException or ForwardException.
348            orb.getPIHandler().initializeServerPIInfo(request, objectAdapter,
349                objectId, oktemp);
350            orb.getPIHandler().invokeServerPIStartingPoint();
351
352            objectAdapter.enter() ;
353
354            // This must be set just after the enter so that exceptions thrown by
355            // enter do not cause
356            // the exception reply to pop the thread stack and do an extra oa.exit.
357            if (request != null)
358                request.setExecuteReturnServantInResponseConstructor(true);
359
360            java.lang.Object servant = getServant(objectAdapter, objectId,
361                operation);
362
363            // Note: we do not know the MDI on a null servant.
364            // We only end up in that situation if _non_existent called,
365            // so that the following handleNullServant call does not throw an
366            // exception.
367            String mdi = "unknown" ;
368
369            if (servant instanceof NullServant)
370                handleNullServant(operation, (NullServant)servant);
371            else
372                mdi = objectAdapter.getInterfaces(servant, objectId)[0] ;
373
374            orb.getPIHandler().setServerPIInfo(servant, mdi);
375
376            if (((servant != null) &&
377                !(servant instanceof org.omg.CORBA.DynamicImplementation) &&
378                !(servant instanceof org.omg.PortableServer.DynamicImplementation)) ||
379                (SpecialMethod.getSpecialMethod(operation) != null)) {
380                orb.getPIHandler().invokeServerPIIntermediatePoint();
381            }
382
383            return servant ;
384        } finally {
385            if (orb.subcontractDebugFlag) {
386                dprint(".getServantWithPI<-");
387            }
388        }
389    }
390
391    protected void checkServerId(ObjectKey okey)
392    {
393        try {
394            if (orb.subcontractDebugFlag) {
395                dprint(".checkServerId->");
396            }
397
398            ObjectKeyTemplate oktemp = okey.getTemplate() ;
399            int sId = oktemp.getServerId() ;
400            int scid = oktemp.getSubcontractId() ;
401
402            if (!orb.isLocalServerId(scid, sId)) {
403                if (orb.subcontractDebugFlag) {
404                    dprint(".checkServerId: bad server id");
405                }
406
407                orb.handleBadServerId(okey);
408            }
409        } finally {
410            if (orb.subcontractDebugFlag) {
411                dprint(".checkServerId<-");
412            }
413        }
414    }
415
416    private ObjectAdapter findObjectAdapter(ObjectKeyTemplate oktemp)
417    {
418        try {
419            if (orb.subcontractDebugFlag) {
420                dprint(".findObjectAdapter->");
421            }
422
423            RequestDispatcherRegistry scr = orb.getRequestDispatcherRegistry() ;
424            int scid = oktemp.getSubcontractId() ;
425            ObjectAdapterFactory oaf = scr.getObjectAdapterFactory(scid);
426            if (oaf == null) {
427                if (orb.subcontractDebugFlag) {
428                    dprint(".findObjectAdapter: failed to find ObjectAdapterFactory");
429                }
430
431                throw wrapper.noObjectAdapterFactory() ;
432            }
433
434            ObjectAdapterId oaid = oktemp.getObjectAdapterId() ;
435            ObjectAdapter oa = oaf.find(oaid);
436
437            if (oa == null) {
438                if (orb.subcontractDebugFlag) {
439                    dprint(".findObjectAdapter: failed to find ObjectAdaptor");
440                }
441
442                throw wrapper.badAdapterId() ;
443            }
444
445            return oa ;
446        } finally {
447            if (orb.subcontractDebugFlag) {
448                dprint(".findObjectAdapter<-");
449            }
450        }
451    }
452
453    /** Always throws OBJECT_NOT_EXIST if operation is not a special method.
454    * If operation is _non_existent or _not_existent, this will just
455    * return without performing any action, so that _non_existent can return
456    * false.  Always throws OBJECT_NOT_EXIST for any other special method.
457    * Update for issue 4385.
458    */
459    protected void handleNullServant(String operation, NullServant nserv )
460    {
461        try {
462            if (orb.subcontractDebugFlag) {
463                dprint(".handleNullServant->: " + operation);
464            }
465
466            SpecialMethod specialMethod =
467                SpecialMethod.getSpecialMethod(operation);
468
469            if ((specialMethod == null) ||
470                !specialMethod.isNonExistentMethod()) {
471                if (orb.subcontractDebugFlag) {
472                    dprint(".handleNullServant: " + operation
473                           + ": throwing OBJECT_NOT_EXIST");
474                }
475
476                throw nserv.getException() ;
477            }
478        } finally {
479            if (orb.subcontractDebugFlag) {
480                dprint(".handleNullServant<-: " + operation);
481            }
482        }
483    }
484
485    protected void consumeServiceContexts(CorbaMessageMediator request)
486    {
487        try {
488            if (orb.subcontractDebugFlag) {
489                dprint(".consumeServiceContexts->: "
490                       + opAndId(request));
491            }
492
493            ServiceContexts ctxts = request.getRequestServiceContexts();
494            ServiceContext sc ;
495
496            GIOPVersion giopVersion = request.getGIOPVersion();
497
498            // we cannot depend on this since for our local case, we do not send
499            // in this service context.  Can we rely on just the CodeSetServiceContext?
500            // boolean rtSC = false; // Runtime ServiceContext
501
502            boolean hasCodeSetContext = processCodeSetContext(request, ctxts);
503
504            if (orb.subcontractDebugFlag) {
505                dprint(".consumeServiceContexts: " + opAndId(request)
506                       + ": GIOP version: " + giopVersion);
507                dprint(".consumeServiceContexts: " + opAndId(request)
508                       + ": as code set context? " + hasCodeSetContext);
509            }
510
511            sc = ctxts.get(
512                SendingContextServiceContext.SERVICE_CONTEXT_ID ) ;
513
514            if (sc != null) {
515                SendingContextServiceContext scsc =
516                    (SendingContextServiceContext)sc ;
517                IOR ior = scsc.getIOR() ;
518
519                try {
520                    ((CorbaConnection)request.getConnection())
521                        .setCodeBaseIOR(ior);
522                } catch (ThreadDeath td) {
523                    throw td ;
524                } catch (Throwable t) {
525                    throw wrapper.badStringifiedIor( t ) ;
526                }
527            }
528
529            // the RTSC is sent only once during session establishment.  We
530            // need to find out if the CodeBaseRef is already set.  If yes,
531            // then also the rtSC flag needs to be set to true
532            // this is not possible for the LocalCase since there is no
533            // IIOPConnection for the LocalCase
534
535            // used for a case where we have JDK 1.3 supporting 1.0 protocol,
536            // but sending 2 service contexts, that is not normal as per
537            // GIOP rules, based on above information, we figure out that we
538            // are talking to the legacy ORB and set the ORB Version Accordingly.
539
540            // this special case tell us that it is legacy SUN orb
541            // and not a foreign one
542            // rtSC is not available for localcase due to which this generic
543            // path would fail if relying on rtSC
544            //if (giopVersion.equals(GIOPVersion.V1_0) && hasCodeSetContext && rtSC)
545            boolean isForeignORB = false;
546
547            if (giopVersion.equals(GIOPVersion.V1_0) && hasCodeSetContext) {
548                if (orb.subcontractDebugFlag) {
549                    dprint(".consumeServiceCOntexts: " + opAndId(request)
550                           + ": Determined to be an old Sun ORB");
551                }
552
553                orb.setORBVersion(ORBVersionFactory.getOLD()) ;
554                // System.out.println("setting legacy ORB version");
555            } else {
556                // If it didn't include our ORB version service context (below),
557                // then it must be a foreign ORB.
558                isForeignORB = true;
559            }
560
561            // try to get the ORBVersion sent as part of the ServiceContext
562            // if any
563            sc = ctxts.get( ORBVersionServiceContext.SERVICE_CONTEXT_ID ) ;
564            if (sc != null) {
565                ORBVersionServiceContext ovsc =
566                   (ORBVersionServiceContext) sc;
567
568                ORBVersion version = ovsc.getVersion();
569                orb.setORBVersion(version);
570
571                isForeignORB = false;
572            }
573
574            if (isForeignORB) {
575                if (orb.subcontractDebugFlag) {
576                    dprint(".consumeServiceContexts: " + opAndId(request)
577                           + ": Determined to be a foreign ORB");
578                }
579
580                orb.setORBVersion(ORBVersionFactory.getFOREIGN());
581            }
582        } finally {
583            if (orb.subcontractDebugFlag) {
584                dprint(".consumeServiceContexts<-: " + opAndId(request));
585            }
586        }
587    }
588
589    protected CorbaMessageMediator dispatchToServant(
590        java.lang.Object servant,
591        CorbaMessageMediator req,
592        byte[] objectId, ObjectAdapter objectAdapter)
593    {
594        try {
595            if (orb.subcontractDebugFlag) {
596                dprint(".dispatchToServant->: " + opAndId(req));
597            }
598
599            CorbaMessageMediator response = null ;
600
601            String operation = req.getOperationName() ;
602
603            SpecialMethod method = SpecialMethod.getSpecialMethod(operation) ;
604            if (method != null) {
605                if (orb.subcontractDebugFlag) {
606                    dprint(".dispatchToServant: " + opAndId(req)
607                           + ": Handling special method");
608                }
609
610                response = method.invoke(servant, req, objectId, objectAdapter);
611                return response ;
612            }
613
614            // Invoke on the servant using the portable DSI skeleton
615            if (servant instanceof org.omg.CORBA.DynamicImplementation) {
616                if (orb.subcontractDebugFlag) {
617                    dprint(".dispatchToServant: " + opAndId(req)
618                           + ": Handling old style DSI type servant");
619                }
620
621                org.omg.CORBA.DynamicImplementation dynimpl =
622                    (org.omg.CORBA.DynamicImplementation)servant;
623                ServerRequestImpl sreq = new ServerRequestImpl(req, orb);
624
625                // Note: When/if dynimpl.invoke calls arguments() or
626                // set_exception() then intermediate points are run.
627                dynimpl.invoke(sreq);
628
629                response = handleDynamicResult(sreq, req);
630            } else if (servant instanceof org.omg.PortableServer.DynamicImplementation) {
631                if (orb.subcontractDebugFlag) {
632                    dprint(".dispatchToServant: " + opAndId(req)
633                           + ": Handling POA DSI type servant");
634                }
635
636                org.omg.PortableServer.DynamicImplementation dynimpl =
637                    (org.omg.PortableServer.DynamicImplementation)servant;
638                ServerRequestImpl sreq = new ServerRequestImpl(req, orb);
639
640                // Note: When/if dynimpl.invoke calls arguments() or
641                // set_exception() then intermediate points are run.
642                dynimpl.invoke(sreq);
643
644                response = handleDynamicResult(sreq, req);
645            } else {
646                if (orb.subcontractDebugFlag) {
647                    dprint(".dispatchToServant: " + opAndId(req)
648                           + ": Handling invoke handler type servant");
649                }
650
651                InvokeHandler invhandle = (InvokeHandler)servant ;
652
653                OutputStream stream =
654                    (OutputStream)invhandle._invoke(
655                      operation,
656                      (org.omg.CORBA.portable.InputStream)req.getInputObject(),
657                      req);
658                response = (CorbaMessageMediator)
659                    ((OutputObject)stream).getMessageMediator();
660            }
661
662            return response ;
663        } finally {
664            if (orb.subcontractDebugFlag) {
665                dprint(".dispatchToServant<-: " + opAndId(req));
666            }
667        }
668    }
669
670    protected CorbaMessageMediator handleDynamicResult(
671        ServerRequestImpl sreq,
672        CorbaMessageMediator req)
673    {
674        try {
675            if (orb.subcontractDebugFlag) {
676                dprint(".handleDynamicResult->: " + opAndId(req));
677            }
678
679            CorbaMessageMediator response = null ;
680
681            // Check if ServerRequestImpl.result() has been called
682            Any excany = sreq.checkResultCalled();
683
684            if (excany == null) { // normal return
685                if (orb.subcontractDebugFlag) {
686                    dprint(".handleDynamicResult: " + opAndId(req)
687                           + ": handling normal result");
688                }
689
690                // Marshal out/inout/return parameters into the ReplyMessage
691                response = sendingReply(req);
692                OutputStream os = (OutputStream) response.getOutputObject();
693                sreq.marshalReplyParams(os);
694            }  else {
695                if (orb.subcontractDebugFlag) {
696                    dprint(".handleDynamicResult: " + opAndId(req)
697                           + ": handling error");
698                }
699
700                response = sendingReply(req, excany);
701            }
702
703            return response ;
704        } finally {
705            if (orb.subcontractDebugFlag) {
706                dprint(".handleDynamicResult<-: " + opAndId(req));
707            }
708        }
709    }
710
711    protected CorbaMessageMediator sendingReply(CorbaMessageMediator req)
712    {
713        try {
714            if (orb.subcontractDebugFlag) {
715                dprint(".sendingReply->: " + opAndId(req));
716            }
717
718            ServiceContexts scs = new ServiceContexts(orb);
719            return req.getProtocolHandler().createResponse(req, scs);
720        } finally {
721            if (orb.subcontractDebugFlag) {
722                dprint(".sendingReply<-: " + opAndId(req));
723            }
724        }
725    }
726
727    /** Must always be called, just after the servant's method returns.
728     *  Creates the ReplyMessage header and puts in the transaction context
729     *  if necessary.
730     */
731    protected CorbaMessageMediator sendingReply(CorbaMessageMediator req, Any excany)
732    {
733        try {
734            if (orb.subcontractDebugFlag) {
735                dprint(".sendingReply/Any->: " + opAndId(req));
736            }
737
738            ServiceContexts scs = new ServiceContexts(orb);
739
740            // Check if the servant set a SystemException or
741            // UserException
742            CorbaMessageMediator resp;
743            String repId=null;
744            try {
745                repId = excany.type().id();
746            } catch (org.omg.CORBA.TypeCodePackage.BadKind e) {
747                throw wrapper.problemWithExceptionTypecode( e ) ;
748            }
749
750            if (ORBUtility.isSystemException(repId)) {
751                if (orb.subcontractDebugFlag) {
752                    dprint(".sendingReply/Any: " + opAndId(req)
753                           + ": handling system exception");
754                }
755
756                // Get the exception object from the Any
757                InputStream in = excany.create_input_stream();
758                SystemException ex = ORBUtility.readSystemException(in);
759                // Marshal the exception back
760                resp = req.getProtocolHandler()
761                    .createSystemExceptionResponse(req, ex, scs);
762            } else {
763                if (orb.subcontractDebugFlag) {
764                    dprint(".sendingReply/Any: " + opAndId(req)
765                           + ": handling user exception");
766                }
767
768                resp = req.getProtocolHandler()
769                    .createUserExceptionResponse(req, scs);
770                OutputStream os = (OutputStream)resp.getOutputObject();
771                excany.write_value(os);
772            }
773
774            return resp;
775        } finally {
776            if (orb.subcontractDebugFlag) {
777                dprint(".sendingReply/Any<-: " + opAndId(req));
778            }
779        }
780    }
781
782    /**
783     * Handles setting the connection's code sets if required.
784     * Returns true if the CodeSetContext was in the request, false
785     * otherwise.
786     */
787    protected boolean processCodeSetContext(
788        CorbaMessageMediator request, ServiceContexts contexts)
789    {
790        try {
791            if (orb.subcontractDebugFlag) {
792                dprint(".processCodeSetContext->: " + opAndId(request));
793            }
794
795            ServiceContext sc = contexts.get(
796                CodeSetServiceContext.SERVICE_CONTEXT_ID);
797            if (sc != null) {
798                // Somehow a code set service context showed up in the local case.
799                if (request.getConnection() == null) {
800                    return true;
801                }
802
803                // If it's GIOP 1.0, it shouldn't have this context at all.  Our legacy
804                // ORBs sent it and we need to know if it's here to make ORB versioning
805                // decisions, but we don't use the contents.
806                if (request.getGIOPVersion().equals(GIOPVersion.V1_0)) {
807                    return true;
808                }
809
810                CodeSetServiceContext cssc = (CodeSetServiceContext)sc ;
811                CodeSetComponentInfo.CodeSetContext csctx = cssc.getCodeSetContext();
812
813                // Note on threading:
814                //
815                // getCodeSetContext and setCodeSetContext are synchronized
816                // on the Connection.  At worst, this will result in
817                // multiple threads entering this block and calling
818                // setCodeSetContext but not actually changing the
819                // values on the Connection.
820                //
821                // Alternative would be to lock the connection for the
822                // whole block, but it's fine either way.
823
824                // The connection's codeSetContext is null until we've received a
825                // request with a code set context with the negotiated code sets.
826                if (((CorbaConnection)request.getConnection())
827                    .getCodeSetContext() == null)
828                {
829
830                    // Use these code sets on this connection
831                    if (orb.subcontractDebugFlag) {
832                        dprint(".processCodeSetContext: " + opAndId(request)
833                               + ": Setting code sets to: " + csctx);
834                    }
835
836                    ((CorbaConnection)request.getConnection())
837                        .setCodeSetContext(csctx);
838
839                    // We had to read the method name using ISO 8859-1
840                    // (which is the default in the CDRInputStream for
841                    // char data), but now we may have a new char
842                    // code set.  If it isn't ISO8859-1, we must tell
843                    // the CDR stream to null any converter references
844                    // it has created so that it will reacquire
845                    // the code sets again using the new info.
846                    //
847                    // This should probably compare with the stream's
848                    // char code set rather than assuming it's ISO8859-1.
849                    // (However, the operation name is almost certainly
850                    // ISO8859-1 or ASCII.)
851                    if (csctx.getCharCodeSet() !=
852                        OSFCodeSetRegistry.ISO_8859_1.getNumber()) {
853                        ((MarshalInputStream)request.getInputObject())
854                            .resetCodeSetConverters();
855                    }
856                }
857            }
858
859            // If no code set information is ever sent from the client,
860            // the server will use ISO8859-1 for char and throw an
861            // exception for any wchar transmissions.
862            //
863            // In the local case, we use ORB provided streams for
864            // marshaling and unmarshaling.  Currently, they use
865            // ISO8859-1 for char/string and UTF16 for wchar/wstring.
866            return sc != null ;
867        } finally {
868            if (orb.subcontractDebugFlag) {
869                dprint(".processCodeSetContext<-: " + opAndId(request));
870            }
871        }
872    }
873
874    protected void dprint(String msg)
875    {
876        ORBUtility.dprint("CorbaServerRequestDispatcherImpl", msg);
877    }
878
879    protected String opAndId(CorbaMessageMediator mediator)
880    {
881        return ORBUtility.operationNameAndRequestId(mediator);
882    }
883}
884
885// End of file.
886