001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.jndi.provider.ldap;
019:
020: import java.util.ArrayList;
021: import java.util.Hashtable;
022: import java.util.List;
023: import java.util.Map;
024:
025: import javax.naming.CompositeName;
026: import javax.naming.InvalidNameException;
027: import javax.naming.Name;
028: import javax.naming.NamingEnumeration;
029: import javax.naming.NamingException;
030: import javax.naming.directory.Attribute;
031: import javax.naming.directory.Attributes;
032: import javax.naming.directory.DirContext;
033: import javax.naming.directory.ModificationItem;
034: import javax.naming.directory.SearchControls;
035: import javax.naming.directory.SearchResult;
036: import javax.naming.spi.DirectoryManager;
037: import javax.naming.spi.ResolveResult;
038:
039: import org.apache.harmony.jndi.internal.nls.Messages;
040: import org.apache.harmony.jndi.internal.parser.AttributeTypeAndValuePair;
041: import org.apache.harmony.jndi.provider.GenericURLContext;
042: import org.apache.harmony.jndi.provider.ldap.parser.LdapUrlParser;
043:
044: public class ldapURLContext extends GenericURLContext implements
045: DirContext {
046:
047: /**
048: * Creates instance of this context with empty environment.
049: */
050: public ldapURLContext() {
051: super (null);
052: }
053:
054: /**
055: * Creates instance of this context with specified environment.
056: *
057: * @param environment
058: * Environment to copy.
059: */
060: public ldapURLContext(Hashtable<?, ?> environment) {
061: super (environment);
062: }
063:
064: @Override
065: protected ResolveResult getRootURLContext(String url,
066: Hashtable<?, ?> env) throws NamingException {
067: Hashtable<?, ?> myEnv = null;
068: if (env == null) {
069: myEnv = environment;
070: } else {
071: myEnv = (Hashtable<?, ?>) env.clone();
072: }
073:
074: LdapUrlParser parser = LdapUtils.parserURL(url, false);
075:
076: String host = parser.getHost();
077: int port = parser.getPort();
078: String dn = parser.getBaseObject();
079:
080: LdapClient client = LdapClient.newInstance(host, port, myEnv);
081:
082: LdapContextImpl context = new LdapContextImpl(client,
083: (Hashtable<Object, Object>) myEnv, dn);
084:
085: // not support ldap url + other namespace name
086: return new ResolveResult(context, "");
087: }
088:
089: @Override
090: protected DirContext getContinuationContext(Name name)
091: throws NamingException {
092: return DirectoryManager
093: .getContinuationDirContext(createCannotProceedException(name));
094: }
095:
096: public void bind(Name name, Object obj, Attributes attributes)
097: throws NamingException {
098: if (!(name instanceof CompositeName)) {
099: // jndi.26=URL context can't accept non-composite name: {0}
100: throw new InvalidNameException(Messages.getString(
101: "jndi.26", name)); //$NON-NLS-1$
102: }
103:
104: if (name.size() == 1) {
105: bind(name.get(0), obj, attributes);
106: }
107:
108: DirContext context = getContinuationContext(name);
109:
110: try {
111: context.bind(name.getSuffix(1), obj, attributes);
112:
113: } finally {
114: context.close();
115: }
116:
117: }
118:
119: public void bind(String url, Object obj, Attributes attributes)
120: throws NamingException {
121: ResolveResult result = getRootURLContext(url, environment);
122: DirContext context = (DirContext) result.getResolvedObj();
123:
124: try {
125: context.bind(result.getRemainingName(), obj, attributes);
126: return;
127: } finally {
128: context.close();
129: }
130: }
131:
132: public DirContext createSubcontext(Name name, Attributes attributes)
133: throws NamingException {
134: if (!(name instanceof CompositeName)) {
135: // jndi.26=URL context can't accept non-composite name: {0}
136: throw new InvalidNameException(Messages.getString(
137: "jndi.26", name)); //$NON-NLS-1$
138: }
139:
140: if (name.size() == 1) {
141: return createSubcontext(name.get(0), attributes);
142: }
143: DirContext context = getContinuationContext(name);
144:
145: try {
146: return context.createSubcontext(name.getSuffix(1),
147: attributes);
148: } finally {
149: context.close();
150: }
151: }
152:
153: public DirContext createSubcontext(String url, Attributes attributes)
154: throws NamingException {
155: ResolveResult result = getRootURLContext(url, environment);
156: DirContext context = (DirContext) result.getResolvedObj();
157:
158: try {
159: return context.createSubcontext(result.getRemainingName(),
160: attributes);
161: } finally {
162: context.close();
163: }
164: }
165:
166: public Attributes getAttributes(Name name) throws NamingException {
167: if (!(name instanceof CompositeName)) {
168: // jndi.26=URL context can't accept non-composite name: {0}
169: throw new InvalidNameException(Messages.getString(
170: "jndi.26", name)); //$NON-NLS-1$
171: }
172:
173: if (name.size() == 1) {
174: return getAttributes(name.get(0));
175: }
176: DirContext context = getContinuationContext(name);
177:
178: try {
179: return context.getAttributes(name.getSuffix(1));
180: } finally {
181: context.close();
182: }
183: }
184:
185: public Attributes getAttributes(Name name, String[] as)
186: throws NamingException {
187: if (!(name instanceof CompositeName)) {
188: // jndi.26=URL context can't accept non-composite name: {0}
189: throw new InvalidNameException(Messages.getString(
190: "jndi.26", name)); //$NON-NLS-1$
191: }
192:
193: if (name.size() == 1) {
194: return getAttributes(name.get(0), as);
195: }
196: DirContext context = getContinuationContext(name);
197:
198: try {
199: return context.getAttributes(name.getSuffix(1), as);
200: } finally {
201: context.close();
202: }
203: }
204:
205: public Attributes getAttributes(String url) throws NamingException {
206: ResolveResult result = getRootURLContext(url, environment);
207: DirContext context = (DirContext) result.getResolvedObj();
208:
209: try {
210: return context.getAttributes(result.getRemainingName());
211: } finally {
212: context.close();
213: }
214: }
215:
216: public Attributes getAttributes(String url, String[] as)
217: throws NamingException {
218: ResolveResult result = getRootURLContext(url, environment);
219: DirContext context = (DirContext) result.getResolvedObj();
220:
221: try {
222: return context.getAttributes(result.getRemainingName(), as);
223: } finally {
224: context.close();
225: }
226: }
227:
228: public DirContext getSchema(Name name) throws NamingException {
229: if (!(name instanceof CompositeName)) {
230: // jndi.26=URL context can't accept non-composite name: {0}
231: throw new InvalidNameException(Messages.getString(
232: "jndi.26", name)); //$NON-NLS-1$
233: }
234:
235: if (name.size() == 1) {
236: return getSchema(name.get(0));
237: }
238: DirContext context = getContinuationContext(name);
239:
240: try {
241: return context.getSchema(name.getSuffix(1));
242: } finally {
243: context.close();
244: }
245: }
246:
247: public DirContext getSchema(String url) throws NamingException {
248: ResolveResult result = getRootURLContext(url, environment);
249: DirContext context = (DirContext) result.getResolvedObj();
250:
251: try {
252: return context.getSchema(result.getRemainingName());
253: } finally {
254: context.close();
255: }
256: }
257:
258: public DirContext getSchemaClassDefinition(Name name)
259: throws NamingException {
260: if (!(name instanceof CompositeName)) {
261: // jndi.26=URL context can't accept non-composite name: {0}
262: throw new InvalidNameException(Messages.getString(
263: "jndi.26", name)); //$NON-NLS-1$
264: }
265:
266: if (name.size() == 1) {
267: return getSchemaClassDefinition(name.get(0));
268: }
269: DirContext context = getContinuationContext(name);
270:
271: try {
272: return context.getSchemaClassDefinition(name.getSuffix(1));
273: } finally {
274: context.close();
275: }
276: }
277:
278: public DirContext getSchemaClassDefinition(String url)
279: throws NamingException {
280: ResolveResult result = getRootURLContext(url, environment);
281: DirContext context = (DirContext) result.getResolvedObj();
282:
283: try {
284: return context.getSchema(result.getRemainingName());
285: } finally {
286: context.close();
287: }
288: }
289:
290: public void modifyAttributes(Name name, int i, Attributes attributes)
291: throws NamingException {
292: if (!(name instanceof CompositeName)) {
293: // jndi.26=URL context can't accept non-composite name: {0}
294: throw new InvalidNameException(Messages.getString(
295: "jndi.26", name)); //$NON-NLS-1$
296: }
297:
298: if (name.size() == 1) {
299: modifyAttributes(name.get(0), i, attributes);
300: return;
301: }
302: DirContext context = getContinuationContext(name);
303:
304: try {
305: context.modifyAttributes(name.getSuffix(1), i, attributes);
306: return;
307: } finally {
308: context.close();
309: }
310:
311: }
312:
313: public void modifyAttributes(Name name,
314: ModificationItem[] modificationItems)
315: throws NamingException {
316: if (!(name instanceof CompositeName)) {
317: // jndi.26=URL context can't accept non-composite name: {0}
318: throw new InvalidNameException(Messages.getString(
319: "jndi.26", name)); //$NON-NLS-1$
320: }
321:
322: if (name.size() == 1) {
323: modifyAttributes(name.get(0), modificationItems);
324: return;
325: }
326: DirContext context = getContinuationContext(name);
327:
328: try {
329: context.modifyAttributes(name.getSuffix(1),
330: modificationItems);
331: return;
332: } finally {
333: context.close();
334: }
335:
336: }
337:
338: public void modifyAttributes(String url, int i,
339: Attributes attributes) throws NamingException {
340: ResolveResult result = getRootURLContext(url, environment);
341: DirContext context = (DirContext) result.getResolvedObj();
342:
343: try {
344: context.modifyAttributes(result.getRemainingName(), i,
345: attributes);
346: } finally {
347: context.close();
348: }
349:
350: }
351:
352: public void modifyAttributes(String url,
353: ModificationItem[] modificationItems)
354: throws NamingException {
355: ResolveResult result = getRootURLContext(url, environment);
356: DirContext context = (DirContext) result.getResolvedObj();
357:
358: try {
359: context.modifyAttributes(result.getRemainingName(),
360: modificationItems);
361: } finally {
362: context.close();
363: }
364: }
365:
366: public void rebind(Name name, Object obj, Attributes attributes)
367: throws NamingException {
368: if (!(name instanceof CompositeName)) {
369: // jndi.26=URL context can't accept non-composite name: {0}
370: throw new InvalidNameException(Messages.getString(
371: "jndi.26", name)); //$NON-NLS-1$
372: }
373:
374: if (name.size() == 1) {
375: rebind(name.get(0), obj, attributes);
376: }
377:
378: DirContext context = getContinuationContext(name);
379:
380: try {
381: context.rebind(name.getSuffix(1), obj, attributes);
382:
383: } finally {
384: context.close();
385: }
386:
387: }
388:
389: public void rebind(String url, Object obj, Attributes attributes)
390: throws NamingException {
391: ResolveResult result = getRootURLContext(url, environment);
392: DirContext context = (DirContext) result.getResolvedObj();
393:
394: try {
395: context.rebind(result.getRemainingName(), obj, attributes);
396: } finally {
397: context.close();
398: }
399:
400: }
401:
402: public NamingEnumeration<SearchResult> search(Name name,
403: Attributes attributes) throws NamingException {
404: if (!(name instanceof CompositeName)) {
405: // jndi.26=URL context can't accept non-composite name: {0}
406: throw new InvalidNameException(Messages.getString(
407: "jndi.26", name)); //$NON-NLS-1$
408: }
409:
410: if (name.size() == 1) {
411: return search(name.get(0), attributes);
412: }
413:
414: DirContext context = getContinuationContext(name);
415:
416: try {
417: return context.search(name.getSuffix(1), attributes);
418:
419: } finally {
420: context.close();
421: }
422: }
423:
424: public NamingEnumeration<SearchResult> search(Name name,
425: Attributes attributes, String[] as) throws NamingException {
426: if (!(name instanceof CompositeName)) {
427: // jndi.26=URL context can't accept non-composite name: {0}
428: throw new InvalidNameException(Messages.getString(
429: "jndi.26", name)); //$NON-NLS-1$
430: }
431:
432: if (name.size() == 1) {
433: return search(name.get(0), attributes, as);
434: }
435:
436: DirContext context = getContinuationContext(name);
437:
438: try {
439: return context.search(name.getSuffix(1), attributes, as);
440:
441: } finally {
442: context.close();
443: }
444: }
445:
446: public NamingEnumeration<SearchResult> search(Name name,
447: String filter, Object[] objs, SearchControls searchControls)
448: throws NamingException {
449: if (!(name instanceof CompositeName)) {
450: // jndi.26=URL context can't accept non-composite name: {0}
451: throw new InvalidNameException(Messages.getString(
452: "jndi.26", name)); //$NON-NLS-1$
453: }
454:
455: if (name.size() == 1) {
456: return search(name.get(0), filter, objs, searchControls);
457: }
458:
459: DirContext context = getContinuationContext(name);
460:
461: try {
462: return context.search(name.getSuffix(1), filter, objs,
463: searchControls);
464:
465: } finally {
466: context.close();
467: }
468: }
469:
470: public NamingEnumeration<SearchResult> search(Name name,
471: String filter, SearchControls searchControls)
472: throws NamingException {
473: if (!(name instanceof CompositeName)) {
474: // jndi.26=URL context can't accept non-composite name: {0}
475: throw new InvalidNameException(Messages.getString(
476: "jndi.26", name)); //$NON-NLS-1$
477: }
478:
479: if (name.size() == 1) {
480: return search(name.get(0), filter, searchControls);
481: }
482:
483: DirContext context = getContinuationContext(name);
484:
485: try {
486: return context.search(name.getSuffix(1), filter,
487: searchControls);
488:
489: } finally {
490: context.close();
491: }
492: }
493:
494: public NamingEnumeration<SearchResult> search(String url,
495: Attributes attributes) throws NamingException {
496: return search(url, attributes, null);
497: }
498:
499: /**
500: * <code>url</code> is an LDAP URL, which may contains query ('?') parts,
501: * and any parts in URL should override corresponding arguments. For
502: * example, if <code>url</code> contains filter parts, the
503: * <code>attributes</code> arguments would be useless, LDAP search will
504: * use filter from url.
505: *
506: */
507: public NamingEnumeration<SearchResult> search(String url,
508: Attributes attributes, String[] as) throws NamingException {
509: LdapUrlParser parser = LdapUtils.parserURL(url, true);
510: String dn = parser.getBaseObject();
511: String host = parser.getHost();
512: int port = parser.getPort();
513:
514: LdapClient client = LdapClient.newInstance(host, port,
515: environment);
516: LdapContextImpl context = null;
517: try {
518: context = new LdapContextImpl(client,
519: (Hashtable<Object, Object>) environment, dn);
520:
521: SearchControls controls = parser.getControls();
522: if (controls == null) {
523: controls = new SearchControls();
524: controls.setReturningAttributes(as);
525: } else if (!parser.hasAttributes()) {
526: controls.setReturningAttributes(as);
527: }
528:
529: // construct filter
530: Filter filter = null;
531: if (parser.hasFilter()) {
532: // use filter in url
533: filter = parser.getFilter();
534: } else {
535: // construct filter from attributes
536: if (attributes == null || attributes.size() == 0) {
537: // no attributes, use default filter "(objectClass=*)"
538: filter = new Filter(Filter.PRESENT_FILTER);
539: filter.setValue("objectClass");
540: } else {
541: NamingEnumeration<? extends Attribute> attrs = attributes
542: .getAll();
543: filter = new Filter(Filter.AND_FILTER);
544: while (attrs.hasMore()) {
545: Attribute attr = attrs.next();
546: String type = attr.getID();
547: NamingEnumeration<?> enuValues = attr.getAll();
548: while (enuValues.hasMore()) {
549: Object value = enuValues.next();
550: Filter child = new Filter(
551: Filter.EQUALITY_MATCH_FILTER);
552: child
553: .setValue(new AttributeTypeAndValuePair(
554: type, value));
555: filter.addChild(child);
556: }
557: }
558: }
559: }
560:
561: LdapSearchResult result = context.doSearch(dn, filter,
562: controls);
563:
564: List<SearchResult> list = new ArrayList<SearchResult>();
565: Map<String, Attributes> entries = result.getEntries();
566: for (String name : entries.keySet()) {
567: String relativeName = convertToRelativeName(dn, name);
568: SearchResult sr = new SearchResult(relativeName, null,
569: entries.get(name));
570: sr.setNameInNamespace(name);
571: list.add(sr);
572: }
573:
574: return new LdapNamingEnumeration<SearchResult>(list, result
575: .getException());
576: } finally {
577: if (context != null) {
578: context.close();
579: }
580: }
581: }
582:
583: public NamingEnumeration<SearchResult> search(String url,
584: String filter, Object[] objs, SearchControls searchControls)
585: throws NamingException {
586: LdapUrlParser parser = LdapUtils.parserURL(url, true);
587: String dn = parser.getBaseObject();
588: String host = parser.getHost();
589: int port = parser.getPort();
590:
591: LdapClient client = LdapClient.newInstance(host, port,
592: environment);
593: LdapContextImpl context = null;
594:
595: try {
596: context = new LdapContextImpl(client,
597: (Hashtable<Object, Object>) environment, dn);
598:
599: Filter f = parser.getFilter();
600: if (f == null) {
601: f = LdapUtils.parseFilter(filter, objs);
602: }
603:
604: if (searchControls == null) {
605: searchControls = new SearchControls();
606: }
607: if (parser.getControls() != null) {
608: SearchControls controls = parser.getControls();
609: if (parser.hasAttributes()) {
610: searchControls.setReturningAttributes(controls
611: .getReturningAttributes());
612: }
613: if (parser.hasScope()) {
614: searchControls.setSearchScope(controls
615: .getSearchScope());
616: }
617: }
618:
619: LdapSearchResult result = context.doSearch(dn, f,
620: searchControls);
621:
622: List<SearchResult> list = new ArrayList<SearchResult>();
623: Map<String, Attributes> entries = result.getEntries();
624: for (String name : entries.keySet()) {
625: String relativeName = convertToRelativeName(dn, name);
626: SearchResult sr = new SearchResult(relativeName, null,
627: entries.get(name));
628: sr.setNameInNamespace(name);
629: list.add(sr);
630: }
631:
632: return new LdapNamingEnumeration<SearchResult>(list, result
633: .getException());
634: } finally {
635: if (context != null) {
636: context.close();
637: }
638: }
639: }
640:
641: private String convertToRelativeName(String targetContextDN,
642: String dn) {
643: if (targetContextDN.equals("")) {
644: return dn;
645: }
646:
647: int index = dn.lastIndexOf(targetContextDN);
648:
649: if (index == 0) {
650: return "";
651: }
652:
653: return dn.substring(0, index - 1);
654: }
655:
656: public NamingEnumeration<SearchResult> search(String url,
657: String filter, SearchControls searchControls)
658: throws NamingException {
659: return search(url, filter, new Object[0], searchControls);
660: }
661:
662: }
|