1 /* gnuServantObject.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu
.CORBA
.Poa
;
41 import gnu
.CORBA
.GIOP
.ReplyHeader
;
42 import gnu
.CORBA
.IorDelegate
;
43 import gnu
.CORBA
.IorObject
;
44 import gnu
.CORBA
.Interceptor
.gnuServerRequestInfo
;
45 import gnu
.CORBA
.typecodes
.RecordTypeCode
;
47 import gnu
.CORBA
.IorProvider
;
48 import gnu
.CORBA
.Minor
;
49 import gnu
.CORBA
.ObjectCreator
;
50 import gnu
.CORBA
.Unexpected
;
51 import gnu
.CORBA
.ResponseHandlerImpl
;
52 import gnu
.CORBA
.StreamHolder
;
54 import org
.omg
.CORBA
.Any
;
55 import org
.omg
.CORBA
.BAD_OPERATION
;
56 import org
.omg
.CORBA
.BAD_PARAM
;
57 import org
.omg
.CORBA
.CompletionStatus
;
58 import org
.omg
.CORBA
.OBJECT_NOT_EXIST
;
59 import org
.omg
.CORBA
.OBJ_ADAPTER
;
60 import org
.omg
.CORBA
.ORB
;
61 import org
.omg
.CORBA
.SystemException
;
62 import org
.omg
.CORBA
.TCKind
;
63 import org
.omg
.CORBA
.TRANSIENT
;
64 import org
.omg
.CORBA
.UserException
;
65 import org
.omg
.CORBA
.portable
.InputStream
;
66 import org
.omg
.CORBA
.portable
.InvokeHandler
;
67 import org
.omg
.CORBA
.portable
.ObjectImpl
;
68 import org
.omg
.CORBA
.portable
.OutputStream
;
69 import org
.omg
.CORBA
.portable
.ResponseHandler
;
70 import org
.omg
.PortableInterceptor
.ForwardRequest
;
71 import org
.omg
.PortableInterceptor
.ServerRequestInterceptorOperations
;
72 import org
.omg
.PortableServer
.CurrentOperations
;
73 import org
.omg
.PortableServer
.DynamicImplementation
;
74 import org
.omg
.PortableServer
.ImplicitActivationPolicyValue
;
75 import org
.omg
.PortableServer
.POA
;
76 import org
.omg
.PortableServer
.POAManager
;
77 import org
.omg
.PortableServer
.POAManagerPackage
.State
;
78 import org
.omg
.PortableServer
.Servant
;
79 import org
.omg
.PortableServer
.ServantLocatorPackage
.CookieHolder
;
80 import org
.omg
.PortableServer
.ServantRetentionPolicyValue
;
81 import org
.omg
.PortableServer
.portable
.Delegate
;
83 import java
.io
.IOException
;
85 import java
.util
.Arrays
;
88 * Represents a CORBA object, being locally served by the associated servant.
89 * The calls to the object are forwarded to the calls to the servant.
91 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
93 public class gnuServantObject
extends ObjectImpl
94 implements org
.omg
.CORBA
.Object
,
100 * The associated servant that must also implement the {@link InvokeHandler}
101 * interface. This value can be temporary null if the object was created using
102 * POA.create_reference or POA.create_reference_with_id, private to force
103 * always to use {@link setServant}.
105 private Servant servant
;
108 * The Id of this object.
110 public final byte[] Id
;
113 * The poa that takes care about this object.
115 public final gnuPOA poa
;
118 * The POA manager, used to control the work of this object.
120 public final POAManager manager
;
125 public final ORB_1_4 orb
;
128 * The object repository ids, if they were specified separately. Normally, the
129 * ids are requested from the servant.
131 public final String
[] repository_ids
;
134 * Create an object with no connected servant. The servant must be set later.
136 * @param a_repository_ids an array of repository ids, can be null (then ids
137 * will be requested from the servant).
138 * @param an_id the object id.
139 * @param a_poa the POA.
141 public gnuServantObject(String
[] a_repository_ids
, byte[] an_id
,
142 gnuPOA a_poa
, ORB_1_4 an_orb
145 repository_ids
= a_repository_ids
;
147 manager
= a_poa
.the_POAManager();
153 * Get the IOR as it would be for this object.
157 return orb
.getLocalIor(this);
161 * Create a servant object, associated with the passed servant.
163 * @param a_servant a servant, serving this object.
164 * @param an_id an Object Id for this object.
166 * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler}.
168 public gnuServantObject(Servant a_servant
, byte[] an_id
, ORB_1_4 an_orb
,
173 setServant(a_servant
);
177 manager
= poa
.the_POAManager();
183 repository_ids
= null;
188 * Set a servant, if it has not been previously set.
190 * @param a_servant a servant to set, can be null to indicate the necessity
191 * for the subsequent activation.
193 * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler} or
194 * {@link DynamicImplementation} and also not null.
196 public void setServant(Servant a_servant
)
198 if (a_servant
!= null &&
199 !(a_servant
instanceof InvokeHandler
) &&
200 !(a_servant
instanceof DynamicImplementation
)
203 throw new BAD_PARAM("Must be either InvokeHandler or " +
204 "DynamicImplementation, but is " + a_servant
211 * Returns the associated servant.
213 public Servant
getServant()
219 * Return the associated invocation handler.
221 public InvokeHandler
getHandler(String operation
, CookieHolder cookie
,
222 boolean forwarding_allowed
223 ) throws gnuForwardRequest
227 return servantToHandler(servant
);
231 // Use servant locator to locate the servant.
232 if (poa
.servant_locator
!= null)
237 poa
.servant_locator
.preinvoke(Id
, poa
, operation
, cookie
);
238 return servantToHandler(servant
);
240 catch (org
.omg
.PortableServer
.ForwardRequest forw_ex
)
242 if (forwarding_allowed
)
244 throw new gnuForwardRequest(forw_ex
.forward_reference
);
249 ForwardedServant
.create(forw_ex
.forward_reference
);
250 return servantToHandler(servant
);
255 // Use servant activator to locate the servant.
256 if (poa
.applies(ImplicitActivationPolicyValue
.IMPLICIT_ACTIVATION
) &&
257 poa
.applies(ServantRetentionPolicyValue
.RETAIN
)
262 poa
.activate_object_with_id(Id
, servant
, forwarding_allowed
);
263 servant
= poa
.id_to_servant(Id
);
264 return servantToHandler(servant
);
266 catch (gnuForwardRequest forwarded
)
273 new BAD_OPERATION("Unable to activate", Minor
.Activation
,
274 CompletionStatus
.COMPLETED_NO
280 else if (poa
.default_servant
!= null)
282 servant
= poa
.default_servant
;
283 return servantToHandler(servant
);
286 // No servant and no servant manager - throw exception.
289 throw new BAD_OPERATION("Unable to activate", Minor
.Activation
,
290 CompletionStatus
.COMPLETED_NO
297 * Convert the servant to invocation handler.
299 public InvokeHandler
servantToHandler(Servant a_servant
)
301 if (a_servant
instanceof InvokeHandler
)
303 return (InvokeHandler
) a_servant
;
305 else if (a_servant
instanceof DynamicImplementation
)
307 return new DynamicImpHandler((DynamicImplementation
) a_servant
);
311 throw new BAD_OPERATION(a_servant
+
312 " must be either InvokeHandler or " + "POA DynamicImplementation"
318 * Create a servant object, associated with the passed servant. Requests the
319 * object id from the servant. Depending on the policies of the servants POA,
320 * the calls are eithe not synchronized or synchronized on POA or ORB.
322 * @param a_servant a servant, serving this object.
323 * @param an_id an Object Id for this object.
325 public gnuServantObject(Servant a_servant
, gnuPOA a_poa
)
327 this(a_servant
, a_servant
._object_id(), (ORB_1_4
) a_servant
._orb(), a_poa
);
331 * Delegates call to servant, passing the poa and Id.
333 public String
[] _ids()
335 if (repository_ids
== null)
337 return getServant()._all_interfaces(poa
, Id
);
341 return repository_ids
;
346 * Gets a string representation.
348 public String
toString()
350 StringBuffer b
= new StringBuffer("Servant object (");
351 for (int i
= 0; i
< Id
.length
; i
++)
353 b
.append(Integer
.toHexString(Id
[ i
] & 0xFF));
361 * Always returns true.
363 public boolean _is_local()
369 * Check if this object could be named by the given repository id.
371 * @param idl_id the repository id to check.
373 * @return true if it is one of the possible repository ids of this object.
375 public boolean _is_a(String idl_id
)
377 String
[] maybe
= _ids();
378 for (int i
= 0; i
< maybe
.length
; i
++)
380 if (maybe
[ i
].equals(idl_id
))
389 * Get an ORB, associated with the servant of this object.
395 return getServant()._orb();
399 * Handle the invocation (delegates to servant).
401 * @throws TRANSIENT minor 0x535503e9 if the POA is in discarding mode.
402 * @throws OBJ_ADAPTER minor 0x535503ea if the POA is inactivated.
403 * @throws OBJECT_NOT_EXISTS minor 0x535503ec if this object is inactivated.
405 * @specnote see {@link POAManagerOperations} for specnotes about the minor
408 public OutputStream
_invoke(String method
, InputStream input
,
409 ResponseHandler r_handler
410 ) throws SystemException
412 boolean intercept
= false;
413 ServerRequestInterceptorOperations interceptor
= null;
414 gnuServerRequestInfo info
= null;
415 ResponseHandlerImpl i_handler
= null;
419 if (orb
.iServer
!= null &&
420 r_handler
instanceof ResponseHandlerImpl
423 interceptor
= orb
.iServer
;
425 i_handler
= (ResponseHandlerImpl
) r_handler
;
428 new gnuServerRequestInfo(this, i_handler
.request_header
,
429 i_handler
.reply_header
433 interceptor
.receive_request_service_contexts(info
);
438 CookieHolder cookie
= null;
439 AOM
.Obj self
= poa
.aom
.get(Id
);
441 if (poa
.servant_locator
!= null)
443 // If the servant locator is in use, it is always responsible
444 // for providing the servant.
445 self
.servant
= servant
= null;
446 cookie
= new CookieHolder();
448 else if (self
!= null && self
.isDeactiveted())
451 ImplicitActivationPolicyValue
.IMPLICIT_ACTIVATION
453 poa
.servant_activator
!= null
456 // Reset the servant, forcing the subsequent activation.
461 throw new OBJECT_NOT_EXIST("Object deactivated",
462 0x535503ec, CompletionStatus
.COMPLETED_NO
467 InvokeHandler handler
= getHandler(method
, cookie
, true);
473 d
= servant
._get_delegate();
474 orb
.currents
.put(Thread
.currentThread(), this);
478 // In some cases exception is thrown if the delegate is not set.
480 if (d
instanceof ServantDelegateImpl
)
482 // If the delegate is already set, check maybe we can
483 // reuse the existing instance.
484 if (((ServantDelegateImpl
) d
).object
!= this)
486 servant
._set_delegate(new ServantDelegateImpl(servant
, poa
, Id
));
491 servant
._set_delegate(new ServantDelegateImpl(servant
, poa
, Id
));
496 switch (manager
.get_state().value())
505 interceptor
.receive_request(info
);
508 rt
= handler
._invoke(method
, input
, r_handler
);
512 // Handler is casted into i_handler.
513 if (i_handler
.isExceptionReply())
515 info
.m_reply_header
.reply_status
=
516 ReplyHeader
.USER_EXCEPTION
;
518 // Make Any, holding the user exception.
519 Any a
= orb
.create_any();
520 OutputStream buf
= i_handler
.getBuffer();
521 InputStream in
= buf
.create_input_stream();
522 String uex_idl
= "unknown";
525 in
.mark(Integer
.MAX_VALUE
);
526 uex_idl
= in
.read_string();
529 catch (IOException e
)
531 throw new Unexpected(e
);
536 UserException exception
=
537 ObjectCreator
.readUserException(uex_idl
,
541 ObjectCreator
.insertWithHelper(a
,
547 // Failed due any reason, insert without
549 a
.insert_Streamable(new StreamHolder(
550 buf
.create_input_stream()
555 new RecordTypeCode(TCKind
.tk_except
);
557 r
.setName(ObjectCreator
.getDefaultName(
563 info
.m_usr_exception
= a
;
564 interceptor
.send_exception(info
);
568 info
.m_reply_header
.reply_status
=
569 ReplyHeader
.NO_EXCEPTION
;
570 interceptor
.send_reply(info
);
574 catch (SystemException sys_ex
)
578 info
.m_reply_header
.reply_status
=
579 ReplyHeader
.SYSTEM_EXCEPTION
;
580 info
.m_sys_exception
= sys_ex
;
581 interceptor
.send_exception(info
);
588 case State
._HOLDING
:
590 // The holding mode is implemented
591 // relying on the holding capabilites of the network
593 // TODO FIXME in more recent CORBA applications, the
595 // ORB can free the connection and wait for a server side
596 // notification about the completed request. Implement
598 // as soon as JDK specification would allow bidirectional
603 // Wait till the state will be switched into some other
605 while (manager
.get_state().value() == State
._HOLDING
)
615 catch (InterruptedException ex
)
620 // Handle another mode.
621 return _invoke(method
, input
, r_handler
);
623 case State
._DISCARDING
:
624 throw new TRANSIENT("Discarding mode", 0x535503e9,
625 CompletionStatus
.COMPLETED_NO
628 case State
._INACTIVE
:
629 throw new OBJ_ADAPTER("POA deactivated", 0x535503ea,
630 CompletionStatus
.COMPLETED_NO
634 throw new InternalError(); // No more states.
639 if (poa
.servant_locator
!= null)
641 poa
.servant_locator
.postinvoke(Id
, poa
, method
,
642 cookie
.value
, servant
650 orb
.currents
.remove(Thread
.currentThread());
653 catch (ForwardRequest fex
)
655 // May be thrown by interceptor.
661 info
.m_reply_header
.reply_status
=
662 ReplyHeader
.LOCATION_FORWARD
;
663 info
.m_forward_reference
= fex
.forward
;
666 interceptor
.send_other(info
);
669 catch (ForwardRequest fex2
)
671 info
.m_forward_reference
= fex2
.forward
;
672 fex
.forward
= info
.m_forward_reference
;
676 throw new gnuForwardRequest(fex
.forward
);
678 catch (gnuForwardRequest fex
)
680 // May be thrown during activation.
686 info
.m_reply_header
.reply_status
=
687 ReplyHeader
.LOCATION_FORWARD
;
688 info
.m_forward_reference
= fex
.forward_reference
;
691 interceptor
.send_other(info
);
694 catch (ForwardRequest fex2
)
696 info
.m_forward_reference
= fex2
.forward
;
697 fex
.forward_reference
= (ObjectImpl
) fex2
.forward
;
706 * Compare with another object for equality, comparing the object keys.
708 public boolean equals(java
.lang
.Object other
)
710 if (other
instanceof gnuServantObject
)
712 gnuServantObject o
= (gnuServantObject
) other
;
714 return Arrays
.equals(o
.Id
, Id
);
723 * Get the hash code, based on the object key.
725 public int hashCode()
729 for (int i
= 0; i
< Id
.length
; i
++)
732 if (s
> Integer
.MAX_VALUE
)
734 s
= s
% Integer
.MAX_VALUE
;
739 return (int) (s
% Integer
.MAX_VALUE
);
745 public byte[] get_object_id()
759 * Returns without action.
761 public void _release()
766 * Returns without action.
768 public void _releaseReply(InputStream stream
)
773 * Checks if this object is equivalent to another instance. These objects are
774 * assumed equal if they are connected to the same orb and poa under the same
775 * Id, regardless of they delegates.
777 * @param another instance to check.
780 public boolean _is_equivalent(org
.omg
.CORBA
.Object other
)
782 if (other
instanceof gnuServantObject
)
784 gnuServantObject g
= (gnuServantObject
) other
;
785 return orb
== g
.orb
&& poa
== g
.poa
&& Arrays
.equals(Id
, g
.Id
);
787 else if (other
instanceof IorObject
)
789 IorObject ir
= ((IorObject
) other
);
792 IorDelegate ird
= (IorDelegate
) ir
._get_delegate();
793 byte[] ior_id
= poa
.idFormIor(ird
.getIor().key
);
794 if (ior_id
!= null && Arrays
.equals(ior_id
, Id
))
805 // Non - typical delegate or very specific subclass of
806 // IOR_constructed_object.
807 return super._is_equivalent(other
);
810 return super._is_equivalent(other
);