CorbaContactInfoListIteratorImpl.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2002, 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
26package com.sun.corba.se.impl.transport;
27
28import java.util.Iterator;
29import java.util.List;
30
31import org.omg.CORBA.COMM_FAILURE;
32import org.omg.CORBA.CompletionStatus;
33import org.omg.CORBA.INTERNAL;
34import org.omg.CORBA.SystemException;
35
36import com.sun.corba.se.pept.transport.ContactInfo ;
37import com.sun.corba.se.pept.transport.ContactInfoList ;
38
39import com.sun.corba.se.spi.ior.IOR ;
40import com.sun.corba.se.spi.logging.CORBALogDomains;
41import com.sun.corba.se.spi.orb.ORB ;
42import com.sun.corba.se.spi.transport.CorbaContactInfo;
43import com.sun.corba.se.spi.transport.CorbaContactInfoList;
44import com.sun.corba.se.spi.transport.CorbaContactInfoListIterator;
45import com.sun.corba.se.spi.transport.IIOPPrimaryToContactInfo;
46
47import com.sun.corba.se.impl.logging.ORBUtilSystemException;
48import com.sun.corba.se.impl.protocol.CorbaInvocationInfo;
49
50// REVISIT: create a unit test for this class.
51
52public class CorbaContactInfoListIteratorImpl
53    implements
54        CorbaContactInfoListIterator
55{
56    protected ORB orb;
57    protected CorbaContactInfoList contactInfoList;
58    protected CorbaContactInfo successContactInfo;
59    protected CorbaContactInfo failureContactInfo;
60    protected RuntimeException failureException;
61
62    // ITERATOR state
63    protected Iterator effectiveTargetIORIterator;
64    protected CorbaContactInfo previousContactInfo;
65    protected boolean isAddrDispositionRetry;
66    protected IIOPPrimaryToContactInfo primaryToContactInfo;
67    protected ContactInfo primaryContactInfo;
68    protected List listOfContactInfos;
69    // End ITERATOR state
70
71    public CorbaContactInfoListIteratorImpl(
72        ORB orb,
73        CorbaContactInfoList corbaContactInfoList,
74        ContactInfo primaryContactInfo,
75        List listOfContactInfos)
76    {
77        this.orb = orb;
78        this.contactInfoList = corbaContactInfoList;
79        this.primaryContactInfo = primaryContactInfo;
80        if (listOfContactInfos != null) {
81            // listOfContactInfos is null when used by the legacy
82            // socket factory.  In that case this iterator is NOT used.
83            this.effectiveTargetIORIterator = listOfContactInfos.iterator();
84        }
85        // List is immutable so no need to synchronize access.
86        this.listOfContactInfos = listOfContactInfos;
87
88        this.previousContactInfo = null;
89        this.isAddrDispositionRetry = false;
90
91        this.successContactInfo = null;
92        this.failureContactInfo = null;
93        this.failureException = null;
94
95        primaryToContactInfo = orb.getORBData().getIIOPPrimaryToContactInfo();
96    }
97
98    ////////////////////////////////////////////////////
99    //
100    // java.util.Iterator
101    //
102
103    public boolean hasNext()
104    {
105        // REVISIT: Implement as internal closure iterator which would
106        // wraps sticky or default.  Then hasNext and next just call
107        // the closure.
108
109        if (isAddrDispositionRetry) {
110            return true;
111        }
112
113        boolean result;
114
115        if (primaryToContactInfo != null) {
116            result = primaryToContactInfo.hasNext(primaryContactInfo,
117                                                  previousContactInfo,
118                                                  listOfContactInfos);
119        } else {
120            result = effectiveTargetIORIterator.hasNext();
121        }
122
123        return result;
124    }
125
126    public Object next()
127    {
128        if (isAddrDispositionRetry) {
129            isAddrDispositionRetry = false;
130            return previousContactInfo;
131        }
132
133        // We hold onto the last in case we get an addressing
134        // disposition retry.  Then we use it again.
135
136        // We also hold onto it for the sticky manager.
137
138        if (primaryToContactInfo != null) {
139            previousContactInfo = (CorbaContactInfo)
140                primaryToContactInfo.next(primaryContactInfo,
141                                          previousContactInfo,
142                                          listOfContactInfos);
143        } else {
144            previousContactInfo = (CorbaContactInfo)
145                effectiveTargetIORIterator.next();
146        }
147
148        return previousContactInfo;
149    }
150
151    public void remove()
152    {
153        throw new UnsupportedOperationException();
154    }
155
156    ////////////////////////////////////////////////////
157    //
158    // com.sun.corba.se.pept.transport.ContactInfoListIterator
159    //
160
161    public ContactInfoList getContactInfoList()
162    {
163        return contactInfoList;
164    }
165
166    public void reportSuccess(ContactInfo contactInfo)
167    {
168        this.successContactInfo = (CorbaContactInfo)contactInfo;
169    }
170
171    public boolean reportException(ContactInfo contactInfo,
172                                   RuntimeException ex)
173    {
174        this.failureContactInfo = (CorbaContactInfo)contactInfo;
175        this.failureException = ex;
176        if (ex instanceof COMM_FAILURE) {
177            SystemException se = (SystemException) ex;
178            if (se.completed == CompletionStatus.COMPLETED_NO) {
179                if (hasNext()) {
180                    return true;
181                }
182                if (contactInfoList.getEffectiveTargetIOR() !=
183                    contactInfoList.getTargetIOR())
184                {
185                    // retry from root ior
186                    updateEffectiveTargetIOR(contactInfoList.getTargetIOR());
187                    return true;
188                }
189            }
190        }
191        return false;
192    }
193
194    public RuntimeException getFailureException()
195    {
196        if (failureException == null) {
197            return
198                ORBUtilSystemException.get( orb,
199                                            CORBALogDomains.RPC_TRANSPORT )
200                    .invalidContactInfoListIteratorFailureException();
201        } else {
202            return failureException;
203        }
204    }
205
206    ////////////////////////////////////////////////////
207    //
208    // spi.CorbaContactInfoListIterator
209    //
210
211    public void reportAddrDispositionRetry(CorbaContactInfo contactInfo,
212                                           short disposition)
213    {
214        previousContactInfo.setAddressingDisposition(disposition);
215        isAddrDispositionRetry = true;
216    }
217
218    public void reportRedirect(CorbaContactInfo contactInfo,
219                               IOR forwardedIOR)
220    {
221        updateEffectiveTargetIOR(forwardedIOR);
222    }
223
224    ////////////////////////////////////////////////////
225    //
226    // Implementation.
227    //
228
229    //
230    // REVISIT:
231    //
232    // The normal operation for a standard iterator is to throw
233    // ConcurrentModificationException whenever the underlying collection
234    // changes.  This is implemented by keeping a modification counter (the
235    // timestamp may fail because the granularity is too coarse).
236    // Essentially what you need to do is whenever the iterator fails this
237    // way, go back to ContactInfoList and get a new iterator.
238    //
239    // Need to update CorbaClientRequestDispatchImpl to catch and use
240    // that exception.
241    //
242
243    public void updateEffectiveTargetIOR(IOR newIOR)
244    {
245        contactInfoList.setEffectiveTargetIOR(newIOR);
246        // If we report the exception in _request (i.e., beginRequest
247        // we cannot throw RemarshalException to the stub because _request
248        // does not declare that exception.
249        // To keep the two-level dispatching (first level chooses ContactInfo,
250        // second level is specific to that ContactInfo/EPT) we need to
251        // ensure that the request dispatchers get their iterator from the
252        // InvocationStack (i.e., ThreadLocal). That way if the list iterator
253        // needs a complete update it happens right here.
254        ((CorbaInvocationInfo)orb.getInvocationInfo())
255            .setContactInfoListIterator(contactInfoList.iterator());
256    }
257}
258
259// End of file.
260