CNBindingEnumeration.java revision 820:9205e980062a
1/*
2 * Copyright (c) 1999, 2011, 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.jndi.cosnaming;
27
28import javax.naming.*;
29import javax.naming.spi.NamingManager;
30
31import java.util.NoSuchElementException;
32import java.util.Hashtable;
33
34import org.omg.CosNaming.*;
35
36/**
37  * Implements the JNDI NamingEnumeration interface for COS
38  * Naming. Gets hold of a list of bindings from the COS Naming Server
39  * and allows the client to iterate through them.
40  *
41  * @author Raj Krishnamurthy
42  * @author Rosanna Lee
43  */
44
45final class CNBindingEnumeration
46        implements NamingEnumeration<javax.naming.Binding> {
47
48    private static final int DEFAULT_BATCHSIZE = 100;
49    private BindingListHolder _bindingList; // list of bindings
50    private BindingIterator _bindingIter;   // iterator for getting list of bindings
51    private int counter;                    // pointer in _bindingList
52    private int batchsize = DEFAULT_BATCHSIZE;  // how many to ask for each time
53    private CNCtx _ctx;                     // ctx to list
54    private Hashtable<?,?> _env;            // environment for getObjectInstance
55    private boolean more = false;           // iterator done?
56    private boolean isLookedUpCtx = false;  // iterating on a context beneath this context ?
57
58    /**
59     * Creates a CNBindingEnumeration object.
60     * @param ctx Context to enumerate
61     */
62    CNBindingEnumeration(CNCtx ctx, boolean isLookedUpCtx, Hashtable<?,?> env) {
63        // Get batch size to use
64        String batch = (env != null ?
65            (String)env.get(javax.naming.Context.BATCHSIZE) : null);
66        if (batch != null) {
67            try {
68                batchsize = Integer.parseInt(batch);
69            } catch (NumberFormatException e) {
70                throw new IllegalArgumentException("Batch size not numeric: " + batch);
71            }
72        }
73        _ctx = ctx;
74        _ctx.incEnumCount();
75        this.isLookedUpCtx = isLookedUpCtx;
76        _env = env;
77        _bindingList = new BindingListHolder();
78        BindingIteratorHolder _bindingIterH = new BindingIteratorHolder();
79
80        // Perform listing and request that bindings be returned in _bindingIter
81        // Upon return,_bindingList returns a zero length list
82        _ctx._nc.list(0, _bindingList, _bindingIterH);
83
84        _bindingIter = _bindingIterH.value;
85
86        // Get first batch using _bindingIter
87        if (_bindingIter != null) {
88            more = _bindingIter.next_n(batchsize, _bindingList);
89        } else {
90            more = false;
91        }
92        counter = 0;
93    }
94
95    /**
96     * Returns the next binding in the list.
97     * @exception NamingException any naming exception.
98     */
99
100    public javax.naming.Binding next() throws NamingException {
101        if (more && counter >= _bindingList.value.length) {
102            getMore();
103        }
104        if (more && counter < _bindingList.value.length) {
105            org.omg.CosNaming.Binding bndg = _bindingList.value[counter];
106            counter++;
107            return mapBinding(bndg);
108        } else {
109            throw new NoSuchElementException();
110        }
111    }
112
113
114    /**
115    * Returns true or false depending on whether there are more bindings.
116    * @return boolean value
117    */
118
119    public boolean hasMore() throws NamingException {
120        // If there's more, check whether current bindingList has been exhausted,
121        // and if so, try to get more.
122        // If no more, just say so.
123        return more ? (counter < _bindingList.value.length || getMore()) : false;
124    }
125
126    /**
127     * Returns true or false depending on whether there are more bindings.
128     * Need to define this to satisfy the Enumeration api requirement.
129     * @return boolean value
130     */
131
132    public boolean hasMoreElements() {
133        try {
134            return hasMore();
135        } catch (NamingException e) {
136            return false;
137        }
138    }
139
140    /**
141    * Returns the next binding in the list.
142    * @exception NoSuchElementException Thrown when the end of the
143    * list is reached.
144    */
145
146    public javax.naming.Binding nextElement() {
147        try {
148            return next();
149        } catch (NamingException ne) {
150            throw new NoSuchElementException();
151        }
152    }
153
154    public void close() throws NamingException {
155        more = false;
156        if (_bindingIter != null) {
157            _bindingIter.destroy();
158            _bindingIter = null;
159        }
160        if (_ctx != null) {
161            _ctx.decEnumCount();
162
163            /**
164             * context was obtained by CNCtx, the user doesn't have a handle to
165             * it, close it as we are done enumerating through the context
166             */
167            if (isLookedUpCtx) {
168                _ctx.close();
169            }
170            _ctx = null;
171        }
172    }
173
174    protected void finalize() {
175        try {
176            close();
177        } catch (NamingException e) {
178            // ignore failures
179        }
180    }
181
182    /**
183     * Get the next batch using _bindingIter. Update the 'more' field.
184     */
185    private boolean getMore() throws NamingException {
186        try {
187            more = _bindingIter.next_n(batchsize, _bindingList);
188            counter = 0; // reset
189        } catch (Exception e) {
190            more = false;
191            NamingException ne = new NamingException(
192                "Problem getting binding list");
193            ne.setRootCause(e);
194            throw ne;
195        }
196        return more;
197    }
198
199    /**
200    * Constructs a JNDI Binding object from the COS Naming binding
201    * object.
202    * @exception NameNotFound No objects under the name.
203    * @exception CannotProceed Unable to obtain a continuation context
204    * @exception InvalidName Name not understood.
205    * @exception NamingException One of the above.
206    */
207
208    private javax.naming.Binding mapBinding(org.omg.CosNaming.Binding bndg)
209                throws NamingException {
210        java.lang.Object obj = _ctx.callResolve(bndg.binding_name);
211
212        Name cname = CNNameParser.cosNameToName(bndg.binding_name);
213
214        try {
215            obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
216        } catch (NamingException e) {
217            throw e;
218        } catch (Exception e) {
219            NamingException ne = new NamingException(
220                        "problem generating object using object factory");
221            ne.setRootCause(e);
222            throw ne;
223        }
224
225        // Use cname.toString() instead of bindingName because the name
226        // in the binding should be a composite name
227        String cnameStr = cname.toString();
228        javax.naming.Binding jbndg = new javax.naming.Binding(cnameStr, obj);
229
230        NameComponent[] comps = _ctx.makeFullName(bndg.binding_name);
231        String fullName = CNNameParser.cosNameToInsString(comps);
232        jbndg.setNameInNamespace(fullName);
233        return jbndg;
234    }
235}
236