1. /*
  2. * @(#)CorbaContactInfoListIteratorImpl.java 1.29 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.transport;
  8. import java.util.Iterator;
  9. import java.util.List;
  10. import org.omg.CORBA.COMM_FAILURE;
  11. import org.omg.CORBA.CompletionStatus;
  12. import org.omg.CORBA.INTERNAL;
  13. import org.omg.CORBA.SystemException;
  14. import com.sun.corba.se.pept.transport.ContactInfo ;
  15. import com.sun.corba.se.pept.transport.ContactInfoList ;
  16. import com.sun.corba.se.spi.ior.IOR ;
  17. import com.sun.corba.se.spi.logging.CORBALogDomains;
  18. import com.sun.corba.se.spi.orb.ORB ;
  19. import com.sun.corba.se.spi.transport.CorbaContactInfo;
  20. import com.sun.corba.se.spi.transport.CorbaContactInfoList;
  21. import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator;
  22. import com.sun.corba.se.spi.transport.IIOPPrimaryToContactInfo;
  23. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  24. import com.sun.corba.se.impl.protocol.CorbaInvocationInfo;
  25. // REVISIT: create a unit test for this class.
  26. public class CorbaContactInfoListIteratorImpl
  27. implements
  28. CorbaContactInfoListIterator
  29. {
  30. protected ORB orb;
  31. protected CorbaContactInfoList contactInfoList;
  32. protected CorbaContactInfo successContactInfo;
  33. protected CorbaContactInfo failureContactInfo;
  34. protected RuntimeException failureException;
  35. // ITERATOR state
  36. protected Iterator effectiveTargetIORIterator;
  37. protected CorbaContactInfo previousContactInfo;
  38. protected boolean isAddrDispositionRetry;
  39. protected IIOPPrimaryToContactInfo primaryToContactInfo;
  40. protected ContactInfo primaryContactInfo;
  41. protected List listOfContactInfos;
  42. // End ITERATOR state
  43. public CorbaContactInfoListIteratorImpl(
  44. ORB orb,
  45. CorbaContactInfoList corbaContactInfoList,
  46. ContactInfo primaryContactInfo,
  47. List listOfContactInfos)
  48. {
  49. this.orb = orb;
  50. this.contactInfoList = corbaContactInfoList;
  51. this.primaryContactInfo = primaryContactInfo;
  52. if (listOfContactInfos != null) {
  53. // listOfContactInfos is null when used by the legacy
  54. // socket factory. In that case this iterator is NOT used.
  55. this.effectiveTargetIORIterator = listOfContactInfos.iterator();
  56. }
  57. // List is immutable so no need to synchronize access.
  58. this.listOfContactInfos = listOfContactInfos;
  59. this.previousContactInfo = null;
  60. this.isAddrDispositionRetry = false;
  61. this.successContactInfo = null;
  62. this.failureContactInfo = null;
  63. this.failureException = null;
  64. primaryToContactInfo = orb.getORBData().getIIOPPrimaryToContactInfo();
  65. }
  66. ////////////////////////////////////////////////////
  67. //
  68. // java.util.Iterator
  69. //
  70. public boolean hasNext()
  71. {
  72. // REVISIT: Implement as internal closure iterator which would
  73. // wraps sticky or default. Then hasNext and next just call
  74. // the closure.
  75. if (isAddrDispositionRetry) {
  76. return true;
  77. }
  78. boolean result;
  79. if (primaryToContactInfo != null) {
  80. result = primaryToContactInfo.hasNext(primaryContactInfo,
  81. previousContactInfo,
  82. listOfContactInfos);
  83. } else {
  84. result = effectiveTargetIORIterator.hasNext();
  85. }
  86. return result;
  87. }
  88. public Object next()
  89. {
  90. if (isAddrDispositionRetry) {
  91. isAddrDispositionRetry = false;
  92. return previousContactInfo;
  93. }
  94. // We hold onto the last in case we get an addressing
  95. // disposition retry. Then we use it again.
  96. // We also hold onto it for the sticky manager.
  97. if (primaryToContactInfo != null) {
  98. previousContactInfo = (CorbaContactInfo)
  99. primaryToContactInfo.next(primaryContactInfo,
  100. previousContactInfo,
  101. listOfContactInfos);
  102. } else {
  103. previousContactInfo = (CorbaContactInfo)
  104. effectiveTargetIORIterator.next();
  105. }
  106. return previousContactInfo;
  107. }
  108. public void remove()
  109. {
  110. throw new UnsupportedOperationException();
  111. }
  112. ////////////////////////////////////////////////////
  113. //
  114. // com.sun.corba.se.pept.transport.ContactInfoListIterator
  115. //
  116. public ContactInfoList getContactInfoList()
  117. {
  118. return contactInfoList;
  119. }
  120. public void reportSuccess(ContactInfo contactInfo)
  121. {
  122. this.successContactInfo = (CorbaContactInfo)contactInfo;
  123. }
  124. public boolean reportException(ContactInfo contactInfo,
  125. RuntimeException ex)
  126. {
  127. this.failureContactInfo = (CorbaContactInfo)contactInfo;
  128. this.failureException = ex;
  129. if (ex instanceof COMM_FAILURE) {
  130. SystemException se = (SystemException) ex;
  131. if (se.completed == CompletionStatus.COMPLETED_NO) {
  132. if (hasNext()) {
  133. return true;
  134. }
  135. if (contactInfoList.getEffectiveTargetIOR() !=
  136. contactInfoList.getTargetIOR())
  137. {
  138. // retry from root ior
  139. updateEffectiveTargetIOR(contactInfoList.getTargetIOR());
  140. return true;
  141. }
  142. }
  143. }
  144. return false;
  145. }
  146. public RuntimeException getFailureException()
  147. {
  148. if (failureException == null) {
  149. return
  150. ORBUtilSystemException.get( orb,
  151. CORBALogDomains.RPC_TRANSPORT )
  152. .invalidContactInfoListIteratorFailureException();
  153. } else {
  154. return failureException;
  155. }
  156. }
  157. ////////////////////////////////////////////////////
  158. //
  159. // spi.CorbaContactInfoListIterator
  160. //
  161. public void reportAddrDispositionRetry(CorbaContactInfo contactInfo,
  162. short disposition)
  163. {
  164. previousContactInfo.setAddressingDisposition(disposition);
  165. isAddrDispositionRetry = true;
  166. }
  167. public void reportRedirect(CorbaContactInfo contactInfo,
  168. IOR forwardedIOR)
  169. {
  170. updateEffectiveTargetIOR(forwardedIOR);
  171. }
  172. ////////////////////////////////////////////////////
  173. //
  174. // Implementation.
  175. //
  176. //
  177. // REVISIT:
  178. //
  179. // The normal operation for a standard iterator is to throw
  180. // ConcurrentModificationException whenever the underlying collection
  181. // changes. This is implemented by keeping a modification counter (the
  182. // timestamp may fail because the granularity is too coarse).
  183. // Essentially what you need to do is whenever the iterator fails this
  184. // way, go back to ContactInfoList and get a new iterator.
  185. //
  186. // Need to update CorbaClientRequestDispatchImpl to catch and use
  187. // that exception.
  188. //
  189. public void updateEffectiveTargetIOR(IOR newIOR)
  190. {
  191. contactInfoList.setEffectiveTargetIOR(newIOR);
  192. // If we report the exception in _request (i.e., beginRequest
  193. // we cannot throw RemarshalException to the stub because _request
  194. // does not declare that exception.
  195. // To keep the two-level dispatching (first level chooses ContactInfo,
  196. // second level is specific to that ContactInfo/EPT) we need to
  197. // ensure that the request dispatchers get their iterator from the
  198. // InvocationStack (i.e., ThreadLocal). That way if the list iterator
  199. // needs a complete update it happens right here.
  200. ((CorbaInvocationInfo)orb.getInvocationInfo())
  201. .setContactInfoListIterator(contactInfoList.iterator());
  202. }
  203. }
  204. // End of file.