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