libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / CORBA / Poa / gnuServantObject.java
blob7e9b4f2f599323db1012a43440ac048578ccd813
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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;
46 import gnu.CORBA.IOR;
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;
89 /**
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,
97 InvokeHandler,
98 CurrentOperations,
99 IorProvider
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;
125 * The orb.
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.
139 boolean noRetain;
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;
154 Id = an_id;
155 manager = a_poa.the_POAManager();
156 poa = a_poa;
157 orb = an_orb;
159 noRetain = poa.applies(ServantRetentionPolicyValue.NON_RETAIN);
163 * Get the IOR as it would be for this object.
165 public IOR getIor()
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,
179 gnuPOA a_poa
182 Id = an_id;
183 setServant(a_servant);
184 poa = a_poa;
185 if (poa != null)
187 manager = poa.the_POAManager();
189 else
191 manager = null;
193 repository_ids = null;
194 orb = an_orb;
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
219 servant = a_servant;
223 * Returns the associated servant.
225 public Servant getServant()
227 return servant;
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);
241 else
243 // Use servant locator to locate the servant.
244 if (poa.servant_locator != null)
248 servant =
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);
258 else
260 servant =
261 ForwardedServant.create(forw_ex.forward_reference);
262 return servantToHandler(servant);
266 else
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)
280 throw forwarded;
282 catch (Exception ex)
284 BAD_OPERATION bad =
285 new BAD_OPERATION("Unable to activate", Minor.Activation,
286 CompletionStatus.COMPLETED_NO
288 bad.initCause(ex);
289 throw bad;
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.
299 else
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);
321 else
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);
351 else
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));
366 b.append(' ');
368 b.append(')');
369 return b.toString();
373 * Always returns true.
375 public boolean _is_local()
377 return true;
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))
394 return true;
397 return false;
401 * Get an ORB, associated with the servant of this object.
403 * @return
405 public ORB _orb()
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
418 * codes.
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;
439 info =
440 new gnuServerRequestInfo(this, i_handler.request_header,
441 i_handler.reply_header
443 intercept = true;
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())
462 if (poa.applies(
463 ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION
464 ) &&
465 poa.servant_activator != null
468 // Reset the servant, forcing the subsequent activation.
469 servant = null;
471 else
473 throw new OBJECT_NOT_EXIST("Object deactivated",
474 0x535503ec, CompletionStatus.COMPLETED_NO
479 InvokeHandler handler = getHandler(method, cookie, true);
481 Delegate d = null;
485 d = servant._get_delegate();
486 orb.currents.put(Thread.currentThread(), this);
488 catch (Exception ex)
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));
501 else
503 servant._set_delegate(new ServantDelegateImpl(servant, poa, Id));
508 switch (manager.get_state().value())
510 case State._ACTIVE :
512 OutputStream rt;
515 if (intercept)
517 interceptor.receive_request(info);
520 rt = handler._invoke(method, input, r_handler);
522 if (intercept)
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();
539 in.reset();
541 catch (IOException e)
543 throw new Unexpected(e);
548 UserException exception =
549 ObjectCreator.readUserException(uex_idl,
553 ObjectCreator.insertWithHelper(a,
554 exception
557 catch (Exception e)
559 // Failed due any reason, insert without
560 // helper.
561 a.insert_Streamable(new StreamHolder(
562 buf.create_input_stream()
566 RecordTypeCode r =
567 new RecordTypeCode(TCKind.tk_except);
568 r.setId(uex_idl);
569 r.setName(ObjectCreator.getDefaultName(
570 uex_idl
575 info.m_usr_exception = a;
576 interceptor.send_exception(info);
578 else
580 info.m_reply_header.reply_status =
581 ReplyHeader.NO_EXCEPTION;
582 interceptor.send_reply(info);
586 catch (SystemException sys_ex)
588 if (intercept)
590 info.m_reply_header.reply_status =
591 ReplyHeader.SYSTEM_EXCEPTION;
592 info.m_sys_exception = sys_ex;
593 interceptor.send_exception(info);
595 throw sys_ex;
598 return rt;
600 case State._HOLDING :
602 // The holding mode is implemented
603 // relying on the holding capabilites of the network
604 // support (if any).
605 // TODO FIXME in more recent CORBA applications, the
606 // client
607 // ORB can free the connection and wait for a server side
608 // notification about the completed request. Implement
609 // this
610 // as soon as JDK specification would allow bidirectional
611 // policy.
612 int sleep = 5;
613 int max = 500;
615 // Wait till the state will be switched into some other
616 // mode.
617 while (manager.get_state().value() == State._HOLDING)
621 Thread.sleep(sleep);
622 if (sleep < max)
624 sleep = max;
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
645 default :
646 throw new InternalError(); // No more states.
649 finally
651 if (poa.servant_locator != null)
653 poa.servant_locator.postinvoke(Id, poa, method,
654 cookie.value, servant
659 finally
661 orb.currents.remove(Thread.currentThread());
662 if (noRetain)
663 servant = null;
666 catch (ForwardRequest fex)
668 // May be thrown by interceptor.
669 if (intercept)
671 Forwarding:
672 while (true)
674 info.m_reply_header.reply_status =
675 ReplyHeader.LOCATION_FORWARD;
676 info.m_forward_reference = fex.forward;
679 interceptor.send_other(info);
680 break Forwarding;
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.
694 if (intercept)
696 Forwarding:
697 while (true)
699 info.m_reply_header.reply_status =
700 ReplyHeader.LOCATION_FORWARD;
701 info.m_forward_reference = fex.forward_reference;
704 interceptor.send_other(info);
705 break Forwarding;
707 catch (ForwardRequest fex2)
709 info.m_forward_reference = fex2.forward;
710 fex.forward_reference = (ObjectImpl) fex2.forward;
714 throw fex;
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);
729 else
731 return false;
736 * Get the hash code, based on the object key.
738 public int hashCode()
740 long s = 0;
741 int v = 1;
742 for (int i = 0; i < Id.length; i++)
744 s += Id [ i ] * v;
745 if (s > Integer.MAX_VALUE)
747 s = s % Integer.MAX_VALUE;
748 v = 1;
750 v = v * 8;
752 return (int) (s % Integer.MAX_VALUE);
756 * Get the object id.
758 public byte[] get_object_id()
760 return Id;
764 * Get POA.
766 public POA get_POA()
768 return poa;
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.
791 * @return
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))
809 return true;
811 else
813 return false;
816 catch (Exception ex)
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);