1 /*
   2  * Copyright (c) 1999, 2005, 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 
  26 package com.sun.jndi.cosnaming;
  27 
  28 import javax.naming.*;
  29 import javax.naming.spi.NamingManager;
  30 
  31 import java.util.NoSuchElementException;
  32 import java.util.Hashtable;
  33 
  34 import 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 
  45 final 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 }