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 gnu
.java
.lang
.CPStringBuilder
;
56 import org
.omg
.CORBA
.Any
;
57 import org
.omg
.CORBA
.BAD_OPERATION
;
58 import org
.omg
.CORBA
.BAD_PARAM
;
59 import org
.omg
.CORBA
.CompletionStatus
;
60 import org
.omg
.CORBA
.OBJECT_NOT_EXIST
;
61 import org
.omg
.CORBA
.OBJ_ADAPTER
;
62 import org
.omg
.CORBA
.ORB
;
63 import org
.omg
.CORBA
.SystemException
;
64 import org
.omg
.CORBA
.TCKind
;
65 import org
.omg
.CORBA
.TRANSIENT
;
66 import org
.omg
.CORBA
.UserException
;
67 import org
.omg
.CORBA
.portable
.InputStream
;
68 import org
.omg
.CORBA
.portable
.InvokeHandler
;
69 import org
.omg
.CORBA
.portable
.ObjectImpl
;
70 import org
.omg
.CORBA
.portable
.OutputStream
;
71 import org
.omg
.CORBA
.portable
.ResponseHandler
;
72 import org
.omg
.PortableInterceptor
.ForwardRequest
;
73 import org
.omg
.PortableInterceptor
.ServerRequestInterceptorOperations
;
74 import org
.omg
.PortableServer
.CurrentOperations
;
75 import org
.omg
.PortableServer
.DynamicImplementation
;
76 import org
.omg
.PortableServer
.ImplicitActivationPolicyValue
;
77 import org
.omg
.PortableServer
.POA
;
78 import org
.omg
.PortableServer
.POAManager
;
79 import org
.omg
.PortableServer
.POAManagerPackage
.State
;
80 import org
.omg
.PortableServer
.Servant
;
81 import org
.omg
.PortableServer
.ServantLocatorPackage
.CookieHolder
;
82 import org
.omg
.PortableServer
.ServantRetentionPolicyValue
;
83 import org
.omg
.PortableServer
.portable
.Delegate
;
85 import java
.io
.IOException
;
87 import java
.util
.Arrays
;
90 * Represents a CORBA object, being locally served by the associated servant.
91 * The calls to the object are forwarded to the calls to the servant.
93 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
95 public class gnuServantObject
extends ObjectImpl
96 implements org
.omg
.CORBA
.Object
,
102 * The associated servant that must also implement the {@link InvokeHandler}
103 * interface. This value can be temporary null if the object was created using
104 * POA.create_reference or POA.create_reference_with_id, private to force
105 * always to use {@link setServant}.
107 private Servant servant
;
110 * The Id of this object.
112 public final byte[] Id
;
115 * The poa that takes care about this object.
117 public final gnuPOA poa
;
120 * The POA manager, used to control the work of this object.
122 public final POAManager manager
;
127 public final ORB_1_4 orb
;
130 * The object repository ids, if they were specified separately. Normally, the
131 * ids are requested from the servant.
133 public final String
[] repository_ids
;
136 * True indicates that the NO_RETAIN policy applies for the servant.
137 * The servant must be discarded after the each call.
142 * Create an object with no connected servant. The servant must be set later.
144 * @param a_repository_ids an array of repository ids, can be null (then ids
145 * will be requested from the servant).
146 * @param an_id the object id.
147 * @param a_poa the POA.
149 public gnuServantObject(String
[] a_repository_ids
, byte[] an_id
,
150 gnuPOA a_poa
, ORB_1_4 an_orb
153 repository_ids
= a_repository_ids
;
155 manager
= a_poa
.the_POAManager();
159 noRetain
= poa
.applies(ServantRetentionPolicyValue
.NON_RETAIN
);
163 * Get the IOR as it would be for this object.
167 return orb
.getLocalIor(this);
171 * Create a servant object, associated with the passed servant.
173 * @param a_servant a servant, serving this object.
174 * @param an_id an Object Id for this object.
176 * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler}.
178 public gnuServantObject(Servant a_servant
, byte[] an_id
, ORB_1_4 an_orb
,
183 setServant(a_servant
);
187 manager
= poa
.the_POAManager();
193 repository_ids
= null;
196 noRetain
= poa
!= null && poa
.applies(ServantRetentionPolicyValue
.NON_RETAIN
);
200 * Set a servant, if it has not been previously set.
202 * @param a_servant a servant to set, can be null to indicate the necessity
203 * for the subsequent activation.
205 * @throws BAD_PARAM if the passed servant is not an {@link InvokeHandler} or
206 * {@link DynamicImplementation} and also not null.
208 public void setServant(Servant a_servant
)
210 if (a_servant
!= null &&
211 !(a_servant
instanceof InvokeHandler
) &&
212 !(a_servant
instanceof DynamicImplementation
)
215 throw new BAD_PARAM("Must be either InvokeHandler or " +
216 "DynamicImplementation, but is " + a_servant
223 * Returns the associated servant.
225 public Servant
getServant()
231 * Return the associated invocation handler.
233 public InvokeHandler
getHandler(String operation
, CookieHolder cookie
,
234 boolean forwarding_allowed
235 ) throws gnuForwardRequest
237 if (servant
!= null && !noRetain
)
239 return servantToHandler(servant
);
243 // Use servant locator to locate the servant.
244 if (poa
.servant_locator
!= null)
249 poa
.servant_locator
.preinvoke(Id
, poa
, operation
, cookie
);
250 return servantToHandler(servant
);
252 catch (org
.omg
.PortableServer
.ForwardRequest forw_ex
)
254 if (forwarding_allowed
)
256 throw new gnuForwardRequest(forw_ex
.forward_reference
);
261 ForwardedServant
.create(forw_ex
.forward_reference
);
262 return servantToHandler(servant
);
267 // Use servant activator to locate the servant.
268 if (poa
.applies(ImplicitActivationPolicyValue
.IMPLICIT_ACTIVATION
) &&
269 poa
.applies(ServantRetentionPolicyValue
.RETAIN
)
274 poa
.activate_object_with_id(Id
, servant
, forwarding_allowed
);
275 servant
= poa
.id_to_servant(Id
);
276 return servantToHandler(servant
);
278 catch (gnuForwardRequest forwarded
)
285 new BAD_OPERATION("Unable to activate", Minor
.Activation
,
286 CompletionStatus
.COMPLETED_NO
292 else if (poa
.default_servant
!= null)
294 servant
= poa
.default_servant
;
295 return servantToHandler(servant
);
298 // No servant and no servant manager - throw exception.
301 throw new BAD_OPERATION("Unable to activate", Minor
.Activation
,
302 CompletionStatus
.COMPLETED_NO
309 * Convert the servant to invocation handler.
311 public InvokeHandler
servantToHandler(Servant a_servant
)
313 if (a_servant
instanceof InvokeHandler
)
315 return (InvokeHandler
) a_servant
;
317 else if (a_servant
instanceof DynamicImplementation
)
319 return new DynamicImpHandler((DynamicImplementation
) a_servant
);
323 throw new BAD_OPERATION(a_servant
+
324 " must be either InvokeHandler or " + "POA DynamicImplementation"
330 * Create a servant object, associated with the passed servant. Requests the
331 * object id from the servant. Depending on the policies of the servants POA,
332 * the calls are eithe not synchronized or synchronized on POA or ORB.
334 * @param a_servant a servant, serving this object.
335 * @param an_id an Object Id for this object.
337 public gnuServantObject(Servant a_servant
, gnuPOA a_poa
)
339 this(a_servant
, a_servant
._object_id(), (ORB_1_4
) a_servant
._orb(), a_poa
);
343 * Delegates call to servant, passing the poa and Id.
345 public String
[] _ids()
347 if (repository_ids
== null)
349 return getServant()._all_interfaces(poa
, Id
);
353 return repository_ids
;
358 * Gets a string representation.
360 public String
toString()
362 CPStringBuilder b
= new CPStringBuilder("Servant object (");
363 for (int i
= 0; i
< Id
.length
; i
++)
365 b
.append(Integer
.toHexString(Id
[ i
] & 0xFF));
373 * Always returns true.
375 public boolean _is_local()
381 * Check if this object could be named by the given repository id.
383 * @param idl_id the repository id to check.
385 * @return true if it is one of the possible repository ids of this object.
387 public boolean _is_a(String idl_id
)
389 String
[] maybe
= _ids();
390 for (int i
= 0; i
< maybe
.length
; i
++)
392 if (maybe
[ i
].equals(idl_id
))
401 * Get an ORB, associated with the servant of this object.
407 return getServant()._orb();
411 * Handle the invocation (delegates to servant).
413 * @throws TRANSIENT minor 0x535503e9 if the POA is in discarding mode.
414 * @throws OBJ_ADAPTER minor 0x535503ea if the POA is inactivated.
415 * @throws OBJECT_NOT_EXISTS minor 0x535503ec if this object is inactivated.
417 * @specnote see {@link POAManagerOperations} for specnotes about the minor
420 public OutputStream
_invoke(String method
, InputStream input
,
421 ResponseHandler r_handler
422 ) throws SystemException
424 boolean intercept
= false;
425 ServerRequestInterceptorOperations interceptor
= null;
426 gnuServerRequestInfo info
= null;
427 ResponseHandlerImpl i_handler
= null;
431 if (orb
.iServer
!= null &&
432 r_handler
instanceof ResponseHandlerImpl
435 interceptor
= orb
.iServer
;
437 i_handler
= (ResponseHandlerImpl
) r_handler
;
440 new gnuServerRequestInfo(this, i_handler
.request_header
,
441 i_handler
.reply_header
445 interceptor
.receive_request_service_contexts(info
);
450 CookieHolder cookie
= null;
451 AOM
.Obj self
= poa
.aom
.get(Id
);
453 if (poa
.servant_locator
!= null)
455 // If the servant locator is in use, it is always responsible
456 // for providing the servant.
457 self
.servant
= servant
= null;
458 cookie
= new CookieHolder();
460 else if (self
!= null && self
.isDeactiveted())
463 ImplicitActivationPolicyValue
.IMPLICIT_ACTIVATION
465 poa
.servant_activator
!= null
468 // Reset the servant, forcing the subsequent activation.
473 throw new OBJECT_NOT_EXIST("Object deactivated",
474 0x535503ec, CompletionStatus
.COMPLETED_NO
479 InvokeHandler handler
= getHandler(method
, cookie
, true);
485 d
= servant
._get_delegate();
486 orb
.currents
.put(Thread
.currentThread(), this);
490 // In some cases exception is thrown if the delegate is not set.
492 if (d
instanceof ServantDelegateImpl
)
494 // If the delegate is already set, check maybe we can
495 // reuse the existing instance.
496 if (((ServantDelegateImpl
) d
).object
!= this)
498 servant
._set_delegate(new ServantDelegateImpl(servant
, poa
, Id
));
503 servant
._set_delegate(new ServantDelegateImpl(servant
, poa
, Id
));
508 switch (manager
.get_state().value())
517 interceptor
.receive_request(info
);
520 rt
= handler
._invoke(method
, input
, r_handler
);
524 // Handler is casted into i_handler.
525 if (i_handler
.isExceptionReply())
527 info
.m_reply_header
.reply_status
=
528 ReplyHeader
.USER_EXCEPTION
;
530 // Make Any, holding the user exception.
531 Any a
= orb
.create_any();
532 OutputStream buf
= i_handler
.getBuffer();
533 InputStream in
= buf
.create_input_stream();
534 String uex_idl
= "unknown";
537 in
.mark(Integer
.MAX_VALUE
);
538 uex_idl
= in
.read_string();
541 catch (IOException e
)
543 throw new Unexpected(e
);
548 UserException exception
=
549 ObjectCreator
.readUserException(uex_idl
,
553 ObjectCreator
.insertWithHelper(a
,
559 // Failed due any reason, insert without
561 a
.insert_Streamable(new StreamHolder(
562 buf
.create_input_stream()
567 new RecordTypeCode(TCKind
.tk_except
);
569 r
.setName(ObjectCreator
.getDefaultName(
575 info
.m_usr_exception
= a
;
576 interceptor
.send_exception(info
);
580 info
.m_reply_header
.reply_status
=
581 ReplyHeader
.NO_EXCEPTION
;
582 interceptor
.send_reply(info
);
586 catch (SystemException sys_ex
)
590 info
.m_reply_header
.reply_status
=
591 ReplyHeader
.SYSTEM_EXCEPTION
;
592 info
.m_sys_exception
= sys_ex
;
593 interceptor
.send_exception(info
);
600 case State
._HOLDING
:
602 // The holding mode is implemented
603 // relying on the holding capabilites of the network
605 // TODO FIXME in more recent CORBA applications, the
607 // ORB can free the connection and wait for a server side
608 // notification about the completed request. Implement
610 // as soon as JDK specification would allow bidirectional
615 // Wait till the state will be switched into some other
617 while (manager
.get_state().value() == State
._HOLDING
)
627 catch (InterruptedException ex
)
632 // Handle another mode.
633 return _invoke(method
, input
, r_handler
);
635 case State
._DISCARDING
:
636 throw new TRANSIENT("Discarding mode", 0x535503e9,
637 CompletionStatus
.COMPLETED_NO
640 case State
._INACTIVE
:
641 throw new OBJ_ADAPTER("POA deactivated", 0x535503ea,
642 CompletionStatus
.COMPLETED_NO
646 throw new InternalError(); // No more states.
651 if (poa
.servant_locator
!= null)
653 poa
.servant_locator
.postinvoke(Id
, poa
, method
,
654 cookie
.value
, servant
661 orb
.currents
.remove(Thread
.currentThread());
666 catch (ForwardRequest fex
)
668 // May be thrown by interceptor.
674 info
.m_reply_header
.reply_status
=
675 ReplyHeader
.LOCATION_FORWARD
;
676 info
.m_forward_reference
= fex
.forward
;
679 interceptor
.send_other(info
);
682 catch (ForwardRequest fex2
)
684 info
.m_forward_reference
= fex2
.forward
;
685 fex
.forward
= info
.m_forward_reference
;
689 throw new gnuForwardRequest(fex
.forward
);
691 catch (gnuForwardRequest fex
)
693 // May be thrown during activation.
699 info
.m_reply_header
.reply_status
=
700 ReplyHeader
.LOCATION_FORWARD
;
701 info
.m_forward_reference
= fex
.forward_reference
;
704 interceptor
.send_other(info
);
707 catch (ForwardRequest fex2
)
709 info
.m_forward_reference
= fex2
.forward
;
710 fex
.forward_reference
= (ObjectImpl
) fex2
.forward
;
719 * Compare with another object for equality, comparing the object keys.
721 public boolean equals(java
.lang
.Object other
)
723 if (other
instanceof gnuServantObject
)
725 gnuServantObject o
= (gnuServantObject
) other
;
727 return Arrays
.equals(o
.Id
, Id
);
736 * Get the hash code, based on the object key.
738 public int hashCode()
742 for (int i
= 0; i
< Id
.length
; i
++)
745 if (s
> Integer
.MAX_VALUE
)
747 s
= s
% Integer
.MAX_VALUE
;
752 return (int) (s
% Integer
.MAX_VALUE
);
758 public byte[] get_object_id()
772 * Returns without action.
774 public void _release()
779 * Returns without action.
781 public void _releaseReply(InputStream stream
)
786 * Checks if this object is equivalent to another instance. These objects are
787 * assumed equal if they are connected to the same orb and poa under the same
788 * Id, regardless of they delegates.
790 * @param other instance to check.
793 public boolean _is_equivalent(org
.omg
.CORBA
.Object other
)
795 if (other
instanceof gnuServantObject
)
797 gnuServantObject g
= (gnuServantObject
) other
;
798 return orb
== g
.orb
&& poa
== g
.poa
&& Arrays
.equals(Id
, g
.Id
);
800 else if (other
instanceof IorObject
)
802 IorObject ir
= ((IorObject
) other
);
805 IorDelegate ird
= (IorDelegate
) ir
._get_delegate();
806 byte[] ior_id
= poa
.idFormIor(ird
.getIor().key
);
807 if (ior_id
!= null && Arrays
.equals(ior_id
, Id
))
818 // Non - typical delegate or very specific subclass of
819 // IOR_constructed_object.
820 return super._is_equivalent(other
);
823 return super._is_equivalent(other
);