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