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 
  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 import 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 
  47 final 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 }