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