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.ldap; 27 28 import java.security.AccessControlContext; 29 import java.security.AccessController; 30 import java.security.PrivilegedActionException; 31 import java.security.PrivilegedExceptionAction; 32 import java.util.Vector; 33 import javax.naming.*; 34 import javax.naming.directory.*; 35 import javax.naming.spi.*; 36 import javax.naming.ldap.*; 37 import javax.naming.ldap.LdapName; 38 39 import com.sun.jndi.toolkit.ctx.Continuation; 40 41 final class LdapSearchEnumeration 42 extends AbstractLdapNamingEnumeration<SearchResult> { 43 44 private Name startName; // prefix of names of search results 45 private LdapCtx.SearchArgs searchArgs = null; 46 47 private final AccessControlContext acc = AccessController.getContext(); 48 49 LdapSearchEnumeration(LdapCtx homeCtx, LdapResult search_results, 50 String starter, LdapCtx.SearchArgs args, Continuation cont) 51 throws NamingException { 52 53 super(homeCtx, search_results, 54 args.name, /* listArg */ 55 cont); 56 57 // fully qualified name of starting context of search 58 startName = new LdapName(starter); 59 searchArgs = args; 60 } 61 62 @Override 63 protected SearchResult createItem(String dn, Attributes attrs, 64 Vector<Control> respCtls) 65 throws NamingException { 66 67 Object obj = null; 68 69 String relStart; // name relative to starting search context 70 String relHome; // name relative to homeCtx.currentDN 71 boolean relative = true; // whether relative to currentDN 72 73 // need to strip off all but lowest component of dn 74 // so that is relative to current context (currentDN) 75 76 try { 77 Name parsed = new LdapName(dn); 78 // System.err.println("dn string: " + dn); 79 // System.err.println("dn name: " + parsed); 80 81 if (startName != null && parsed.startsWith(startName)) { 82 relStart = parsed.getSuffix(startName.size()).toString(); 83 relHome = parsed.getSuffix(homeCtx.currentParsedDN.size()).toString(); 84 } else { 85 relative = false; 86 relHome = relStart = 87 LdapURL.toUrlString(homeCtx.hostname, homeCtx.port_number, 88 dn, homeCtx.hasLdapsScheme); 89 } 90 } catch (NamingException e) { 91 // could not parse name 92 relative = false; 93 relHome = relStart = 94 LdapURL.toUrlString(homeCtx.hostname, homeCtx.port_number, 95 dn, homeCtx.hasLdapsScheme); 96 } 97 98 // Name relative to search context 99 CompositeName cn = new CompositeName(); 100 if (!relStart.equals("")) { 101 cn.add(relStart); 102 } 103 104 // Name relative to homeCtx 105 CompositeName rcn = new CompositeName(); 106 if (!relHome.equals("")) { 107 rcn.add(relHome); 108 } 109 //System.err.println("relStart: " + cn); 110 //System.err.println("relHome: " + rcn); 111 112 // Fix attributes to be able to get schema 113 homeCtx.setParents(attrs, rcn); 114 115 // only generate object when requested 116 if (searchArgs.cons.getReturningObjFlag()) { 117 118 if (attrs.get(Obj.JAVA_ATTRIBUTES[Obj.CLASSNAME]) != null) { 119 // Entry contains Java-object attributes (ser/ref object) 120 // serialized object or object reference 121 try { 122 obj = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { 123 @Override 124 public Object run() throws NamingException { 125 return Obj.decodeObject(attrs); 126 } 127 }, acc); 128 } catch (PrivilegedActionException e) { 129 throw (NamingException)e.getException(); 130 } 131 } 132 if (obj == null) { 133 obj = new LdapCtx(homeCtx, dn); 134 } 135 136 // Call getObjectInstance before removing unrequested attributes 137 try { 138 // rcn is either relative to homeCtx or a fully qualified DN 139 obj = DirectoryManager.getObjectInstance( 140 obj, rcn, (relative ? homeCtx : null), 141 homeCtx.envprops, attrs); 142 } catch (NamingException e) { 143 throw e; 144 } catch (Exception e) { 145 NamingException ne = 146 new NamingException( 147 "problem generating object using object factory"); 148 ne.setRootCause(e); 149 throw ne; 150 } 151 152 // remove Java attributes from result, if necessary 153 // Even if CLASSNAME attr not there, there might be some 154 // residual attributes 155 156 String[] reqAttrs; 157 if ((reqAttrs = searchArgs.reqAttrs) != null) { 158 // create an attribute set for those requested 159 Attributes rattrs = new BasicAttributes(true); // caseignore 160 for (int i = 0; i < reqAttrs.length; i++) { 161 rattrs.put(reqAttrs[i], null); 162 } 163 for (int i = 0; i < Obj.JAVA_ATTRIBUTES.length; i++) { 164 // Remove Java-object attributes if not requested 165 if (rattrs.get(Obj.JAVA_ATTRIBUTES[i]) == null) { 166 attrs.remove(Obj.JAVA_ATTRIBUTES[i]); 167 } 168 } 169 } 170 171 } 172 173 /* 174 * name in search result is either the stringified composite name 175 * relative to the search context that can be passed directly to 176 * methods of the search context, or the fully qualified DN 177 * which can be used with the initial context. 178 */ 179 SearchResult sr; 180 if (respCtls != null) { 181 sr = new SearchResultWithControls( 182 (relative ? cn.toString() : relStart), obj, attrs, 183 relative, homeCtx.convertControls(respCtls)); 184 } else { 185 sr = new SearchResult( 186 (relative ? cn.toString() : relStart), 187 obj, attrs, relative); 188 } 189 sr.setNameInNamespace(dn); 190 return sr; 191 } 192 193 @Override 194 public void appendUnprocessedReferrals(LdapReferralException ex) { 195 196 // a referral has been followed so do not create relative names 197 startName = null; 198 super.appendUnprocessedReferrals(ex); 199 } 200 201 @Override 202 protected LdapSearchEnumeration getReferredResults( 203 LdapReferralContext refCtx) throws NamingException { 204 // repeat the original operation at the new context 205 return (LdapSearchEnumeration)refCtx.search( 206 searchArgs.name, searchArgs.filter, searchArgs.cons); 207 } 208 209 @Override 210 protected void update(AbstractLdapNamingEnumeration<SearchResult> ne) { 211 super.update(ne); 212 213 // Update search-specific variables 214 LdapSearchEnumeration se = (LdapSearchEnumeration)ne; 215 startName = se.startName; 216 //VR - keep original args, don't overwite with current args 217 // searchArgs = se.searchArgs; 218 } 219 220 void setStartName(Name nm) { 221 startName = nm; 222 } 223 }