001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.server.core.jndi; 021 022 023import java.io.Serializable; 024import java.text.ParseException; 025import java.util.ArrayList; 026import java.util.Hashtable; 027import java.util.List; 028 029import javax.naming.Name; 030import javax.naming.NamingEnumeration; 031import javax.naming.NamingException; 032import javax.naming.Reference; 033import javax.naming.Referenceable; 034import javax.naming.directory.Attributes; 035import javax.naming.directory.DirContext; 036import javax.naming.directory.InvalidAttributeIdentifierException; 037import javax.naming.directory.InvalidAttributeValueException; 038import javax.naming.directory.InvalidAttributesException; 039import javax.naming.directory.InvalidSearchFilterException; 040import javax.naming.directory.ModificationItem; 041import javax.naming.directory.SearchControls; 042import javax.naming.directory.SearchResult; 043import javax.naming.event.EventDirContext; 044import javax.naming.event.NamingListener; 045import javax.naming.ldap.LdapName; 046import javax.naming.spi.DirStateFactory; 047import javax.naming.spi.DirectoryManager; 048 049import org.apache.directory.api.ldap.model.entry.Attribute; 050import org.apache.directory.api.ldap.model.entry.AttributeUtils; 051import org.apache.directory.api.ldap.model.entry.Entry; 052import org.apache.directory.api.ldap.model.entry.Modification; 053import org.apache.directory.api.ldap.model.exception.LdapException; 054import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeTypeException; 055import org.apache.directory.api.ldap.model.exception.LdapNoSuchAttributeException; 056import org.apache.directory.api.ldap.model.filter.AndNode; 057import org.apache.directory.api.ldap.model.filter.BranchNode; 058import org.apache.directory.api.ldap.model.filter.EqualityNode; 059import org.apache.directory.api.ldap.model.filter.ExprNode; 060import org.apache.directory.api.ldap.model.filter.FilterParser; 061import org.apache.directory.api.ldap.model.filter.PresenceNode; 062import org.apache.directory.api.ldap.model.filter.SimpleNode; 063import org.apache.directory.api.ldap.model.message.AliasDerefMode; 064import org.apache.directory.api.ldap.model.message.SearchScope; 065import org.apache.directory.api.ldap.model.name.Dn; 066import org.apache.directory.api.ldap.util.JndiUtils; 067import org.apache.directory.api.util.Strings; 068import org.apache.directory.server.core.api.CoreSession; 069import org.apache.directory.server.core.api.DirectoryService; 070import org.apache.directory.server.core.api.LdapPrincipal; 071import org.apache.directory.server.core.api.entry.ServerEntryUtils; 072import org.apache.directory.server.core.api.event.DirectoryListener; 073import org.apache.directory.server.core.api.event.NotificationCriteria; 074import org.apache.directory.server.core.api.filtering.EntryFilteringCursor; 075import org.apache.directory.server.core.api.interceptor.context.HasEntryOperationContext; 076import org.apache.directory.server.i18n.I18n; 077 078 079/** 080 * The DirContext implementation for the Server Side JNDI LDAP provider. 081 * 082 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 083 */ 084public abstract class ServerDirContext extends ServerContext implements EventDirContext 085{ 086 // ------------------------------------------------------------------------ 087 // Constructors 088 // ------------------------------------------------------------------------ 089 090 /** 091 * Creates a new ServerDirContext by reading the PROVIDER_URL to resolve the 092 * distinguished name for this context. 093 * 094 * @param service the parent service that manages this context 095 * @param env the environment used for this context 096 * @throws NamingException if something goes wrong 097 */ 098 public ServerDirContext( DirectoryService service, Hashtable<String, Object> env ) throws Exception 099 { 100 super( service, env ); 101 } 102 103 104 /** 105 * Creates a new ServerDirContext with a distinguished name which is used to 106 * set the PROVIDER_URL to the distinguished name for this context. 107 * 108 * @param service The DirectoryService instance 109 * @param principal the principal which is propagated 110 * @param dn the distinguished name of this context 111 * @throws Exception If we weren't able to create the ServerDirContext instance 112 */ 113 public ServerDirContext( DirectoryService service, LdapPrincipal principal, Name dn ) throws Exception 114 { 115 super( service, principal, dn ); 116 } 117 118 119 // ------------------------------------------------------------------------ 120 // DirContext Implementations 121 // ------------------------------------------------------------------------ 122 123 public ServerDirContext( DirectoryService service, CoreSession session, Name bindDn ) throws Exception 124 { 125 super( service, session, bindDn ); 126 } 127 128 129 /** 130 * @see javax.naming.directory.DirContext#getAttributes(java.lang.String) 131 */ 132 public Attributes getAttributes( String name ) throws NamingException 133 { 134 return getAttributes( new LdapName( name ) ); 135 } 136 137 138 /** 139 * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name) 140 */ 141 public Attributes getAttributes( Name name ) throws NamingException 142 { 143 Attributes attrs = null; 144 145 try 146 { 147 attrs = ServerEntryUtils.toBasicAttributes( doLookupOperation( buildTarget( JndiUtils.fromName( name ) ) ) ); 148 } 149 catch ( Exception e ) 150 { 151 JndiUtils.wrap( e ); 152 } 153 154 return attrs; 155 } 156 157 158 /** 159 * @see javax.naming.directory.DirContext#getAttributes(java.lang.String, 160 * java.lang.String[]) 161 */ 162 public Attributes getAttributes( String name, String[] attrIds ) throws NamingException 163 { 164 return getAttributes( new LdapName( name ), attrIds ); 165 } 166 167 168 /** 169 * @see javax.naming.directory.DirContext#getAttributes(javax.naming.Name, 170 * java.lang.String[]) 171 */ 172 public Attributes getAttributes( Name name, String[] attrIds ) throws NamingException 173 { 174 Attributes attrs = null; 175 try 176 { 177 attrs = ServerEntryUtils.toBasicAttributes( doLookupOperation( buildTarget( JndiUtils.fromName( name ) ), 178 attrIds ) ); 179 } 180 catch ( Exception e ) 181 { 182 JndiUtils.wrap( e ); 183 } 184 185 return attrs; 186 } 187 188 189 /** 190 * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, 191 * int, javax.naming.directory.Attributes) 192 */ 193 public void modifyAttributes( String name, int modOp, Attributes attrs ) throws NamingException 194 { 195 modifyAttributes( new LdapName( name ), modOp, AttributeUtils.toCaseInsensitive( attrs ) ); 196 } 197 198 199 /** 200 * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, 201 * int, javax.naming.directory.Attributes) 202 */ 203 public void modifyAttributes( Name name, int modOp, Attributes attrs ) throws NamingException 204 { 205 List<ModificationItem> modItems = null; 206 207 if ( attrs != null ) 208 { 209 modItems = new ArrayList<>( attrs.size() ); 210 NamingEnumeration<? extends javax.naming.directory.Attribute> e = attrs.getAll(); 211 212 while ( e.hasMore() ) 213 { 214 modItems.add( new ModificationItem( modOp, e.next() ) ); 215 } 216 } 217 218 List<Modification> newMods = null; 219 220 try 221 { 222 newMods = ServerEntryUtils.convertToServerModification( 223 modItems, 224 getDirectoryService().getSchemaManager() ); 225 } 226 catch ( LdapNoSuchAttributeException lnsae ) 227 { 228 throw new InvalidAttributesException( lnsae.getMessage() ); 229 } 230 catch ( LdapException le ) 231 { 232 throw new InvalidAttributeValueException( le.getMessage() ); 233 } 234 235 try 236 { 237 doModifyOperation( buildTarget( JndiUtils.fromName( name ) ), newMods ); 238 } 239 catch ( Exception e ) 240 { 241 JndiUtils.wrap( e ); 242 } 243 } 244 245 246 /** 247 * @see javax.naming.directory.DirContext#modifyAttributes(java.lang.String, 248 * javax.naming.directory.ModificationItem[]) 249 */ 250 public void modifyAttributes( String name, ModificationItem[] mods ) throws NamingException 251 { 252 modifyAttributes( new LdapName( name ), mods ); 253 } 254 255 256 /** 257 * @see javax.naming.directory.DirContext#modifyAttributes( 258 * javax.naming.Name, javax.naming.directory.ModificationItem[]) 259 */ 260 public void modifyAttributes( Name name, ModificationItem[] mods ) throws NamingException 261 { 262 List<Modification> newMods; 263 264 try 265 { 266 newMods = ServerEntryUtils 267 .toServerModification( mods, getDirectoryService().getSchemaManager() ); 268 } 269 catch ( LdapException le ) 270 { 271 throw new InvalidAttributesException( le.getMessage() ); 272 } 273 274 try 275 { 276 doModifyOperation( buildTarget( JndiUtils.fromName( name ) ), newMods ); 277 } 278 catch ( Exception e ) 279 { 280 JndiUtils.wrap( e ); 281 } 282 } 283 284 285 /** 286 * @see javax.naming.directory.DirContext#modifyAttributes( 287 * javax.naming.Name, javax.naming.directory.ModificationItem[]) 288 * 289 * @param name The entry to modify 290 * @param mods The modifications to apply 291 * @throws NamingException If the modify operation failed 292 */ 293 public void modifyAttributes( Name name, List<ModificationItem> mods ) throws NamingException 294 { 295 List<Modification> newMods; 296 try 297 { 298 newMods = ServerEntryUtils 299 .convertToServerModification( mods, 300 getDirectoryService().getSchemaManager() ); 301 } 302 catch ( LdapException le ) 303 { 304 throw new InvalidAttributesException( le.getMessage() ); 305 } 306 307 try 308 { 309 doModifyOperation( buildTarget( JndiUtils.fromName( name ) ), newMods ); 310 } 311 catch ( Exception e ) 312 { 313 JndiUtils.wrap( e ); 314 } 315 } 316 317 318 /** 319 * @see javax.naming.directory.DirContext#bind(java.lang.String, 320 * java.lang.Object, javax.naming.directory.Attributes) 321 */ 322 public void bind( String name, Object obj, Attributes attrs ) throws NamingException 323 { 324 bind( new LdapName( name ), obj, AttributeUtils.toCaseInsensitive( attrs ) ); 325 } 326 327 328 /** 329 * @see javax.naming.directory.DirContext#bind(javax.naming.Name, 330 * java.lang.Object, javax.naming.directory.Attributes) 331 */ 332 public void bind( Name name, Object obj, Attributes attrs ) throws NamingException 333 { 334 if ( ( null == obj ) && ( null == attrs ) ) 335 { 336 throw new NamingException( I18n.err( I18n.ERR_499 ) ); 337 } 338 339 // A null attrs defaults this to the Context.bind() operation 340 if ( null == attrs ) 341 { 342 super.bind( name, obj ); 343 return; 344 } 345 346 Dn target = buildTarget( JndiUtils.fromName( name ) ); 347 348 Entry serverEntry = null; 349 350 try 351 { 352 serverEntry = ServerEntryUtils.toServerEntry( AttributeUtils.toCaseInsensitive( attrs ), target, 353 getDirectoryService().getSchemaManager() ); 354 } 355 catch ( LdapInvalidAttributeTypeException liate ) 356 { 357 throw new InvalidAttributesException( liate.getMessage() ); 358 } 359 360 // No object binding so we just add the attributes 361 if ( null == obj ) 362 { 363 Entry clone = serverEntry.clone(); 364 try 365 { 366 doAddOperation( target, clone ); 367 } 368 catch ( Exception e ) 369 { 370 JndiUtils.wrap( e ); 371 } 372 return; 373 } 374 375 // First, use state factories to do a transformation 376 DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, this, getEnvironment(), attrs ); 377 Entry outServerEntry = null; 378 379 try 380 { 381 outServerEntry = ServerEntryUtils.toServerEntry( 382 res.getAttributes(), target, getDirectoryService().getSchemaManager() ); 383 } 384 catch ( LdapInvalidAttributeTypeException le ) 385 { 386 throw new InvalidAttributesException( le.getMessage() ); 387 } 388 389 if ( outServerEntry != serverEntry ) 390 { 391 Entry clone = serverEntry.clone(); 392 393 if ( ( outServerEntry != null ) && ( outServerEntry.size() > 0 ) ) 394 { 395 for ( Attribute attribute : outServerEntry ) 396 { 397 try 398 { 399 clone.put( attribute ); 400 } 401 catch ( LdapException e ) 402 { 403 // TODO Auto-generated catch block 404 } 405 } 406 } 407 408 try 409 { 410 // setup the op context 411 doAddOperation( target, clone ); 412 } 413 catch ( Exception e ) 414 { 415 JndiUtils.wrap( e ); 416 } 417 418 return; 419 } 420 421 // Check for Referenceable 422 if ( obj instanceof Referenceable ) 423 { 424 throw new NamingException( I18n.err( I18n.ERR_493 ) ); 425 } 426 427 // Store different formats 428 if ( obj instanceof Reference ) 429 { 430 // Store as ref and add outAttrs 431 throw new NamingException( I18n.err( I18n.ERR_494 ) ); 432 } 433 else if ( obj instanceof Serializable ) 434 { 435 // Serialize and add outAttrs 436 Entry clone = serverEntry.clone(); 437 438 if ( outServerEntry.size() > 0 ) 439 { 440 for ( Attribute attribute : outServerEntry ) 441 { 442 try 443 { 444 clone.put( attribute ); 445 } 446 catch ( LdapException le ) 447 { 448 throw new InvalidAttributesException( le.getMessage() ); 449 } 450 } 451 } 452 453 try 454 { 455 // Serialize object into entry attributes and add it. 456 JavaLdapSupport.serialize( serverEntry, obj, getDirectoryService().getSchemaManager() ); 457 458 // setup the op context 459 doAddOperation( target, clone ); 460 } 461 catch ( Exception e ) 462 { 463 JndiUtils.wrap( e ); 464 } 465 } 466 else if ( obj instanceof DirContext ) 467 { 468 // Grab attributes and merge with outAttrs 469 Entry entry = null; 470 471 try 472 { 473 entry = ServerEntryUtils.toServerEntry( ( ( DirContext ) obj ).getAttributes( "" ), target, 474 getDirectoryService().getSchemaManager() ); 475 } 476 catch ( LdapInvalidAttributeTypeException liate ) 477 { 478 throw new InvalidAttributeIdentifierException( liate.getMessage() ); 479 } 480 481 if ( ( outServerEntry != null ) && ( outServerEntry.size() > 0 ) ) 482 { 483 for ( Attribute attribute : outServerEntry ) 484 { 485 try 486 { 487 entry.put( attribute ); 488 } 489 catch ( LdapException le ) 490 { 491 throw new InvalidAttributeValueException( le.getMessage() ); 492 } 493 } 494 } 495 496 try 497 { 498 // setup the op context 499 doAddOperation( target, entry ); 500 } 501 catch ( Exception e ) 502 { 503 JndiUtils.wrap( e ); 504 } 505 } 506 else 507 { 508 throw new NamingException( I18n.err( I18n.ERR_495, obj ) ); 509 } 510 } 511 512 513 /** 514 * @see javax.naming.directory.DirContext#rebind(java.lang.String, 515 * java.lang.Object, javax.naming.directory.Attributes) 516 */ 517 public void rebind( String name, Object obj, Attributes attrs ) throws NamingException 518 { 519 rebind( new LdapName( name ), obj, AttributeUtils.toCaseInsensitive( attrs ) ); 520 } 521 522 523 /** 524 * @see javax.naming.directory.DirContext#rebind(javax.naming.Name, 525 * java.lang.Object, javax.naming.directory.Attributes) 526 */ 527 public void rebind( Name name, Object obj, Attributes attrs ) throws NamingException 528 { 529 Dn target = buildTarget( JndiUtils.fromName( name ) ); 530 531 try 532 { 533 HasEntryOperationContext hasEntryContext = new HasEntryOperationContext( getSession(), target ); 534 535 if ( getDirectoryService().getOperationManager().hasEntry( hasEntryContext ) ) 536 { 537 doDeleteOperation( target ); 538 } 539 } 540 catch ( Exception e ) 541 { 542 JndiUtils.wrap( e ); 543 } 544 545 bind( name, obj, AttributeUtils.toCaseInsensitive( attrs ) ); 546 } 547 548 549 /** 550 * @see javax.naming.directory.DirContext#createSubcontext(java.lang.String, 551 * javax.naming.directory.Attributes) 552 */ 553 public DirContext createSubcontext( String name, Attributes attrs ) throws NamingException 554 { 555 Attributes attributes = AttributeUtils.toCaseInsensitive( attrs ); 556 return createSubcontext( new LdapName( name ), attributes ); 557 } 558 559 560 /** 561 * @see javax.naming.directory.DirContext#createSubcontext( 562 * javax.naming.Name, javax.naming.directory.Attributes) 563 */ 564 public DirContext createSubcontext( Name name, Attributes attrs ) throws NamingException 565 { 566 if ( null == attrs ) 567 { 568 return ( DirContext ) super.createSubcontext( name ); 569 } 570 571 Dn target = buildTarget( JndiUtils.fromName( name ) ); 572 573 attrs = AttributeUtils.toCaseInsensitive( attrs ); 574 Attributes attributes = ( Attributes ) attrs.clone(); 575 576 // Add the new context to the server which as a side effect adds 577 try 578 { 579 Entry serverEntry = ServerEntryUtils.toServerEntry( attributes, 580 target, getDirectoryService().getSchemaManager() ); 581 doAddOperation( target, serverEntry ); 582 } 583 catch ( Exception e ) 584 { 585 JndiUtils.wrap( e ); 586 } 587 588 // Initialize the new context 589 ServerLdapContext ctx = null; 590 591 try 592 { 593 ctx = new ServerLdapContext( getService(), getSession().getEffectivePrincipal(), JndiUtils.toName( target ) ); 594 } 595 catch ( Exception e ) 596 { 597 JndiUtils.wrap( e ); 598 } 599 600 return ctx; 601 } 602 603 604 /** 605 * Presently unsupported operation! 606 */ 607 public DirContext getSchema( Name name ) throws NamingException 608 { 609 throw new UnsupportedOperationException(); 610 } 611 612 613 /** 614 * Presently unsupported operation! 615 */ 616 public DirContext getSchema( String name ) throws NamingException 617 { 618 throw new UnsupportedOperationException(); 619 } 620 621 622 /** 623 * Presently unsupported operation! 624 */ 625 public DirContext getSchemaClassDefinition( Name name ) throws NamingException 626 { 627 throw new UnsupportedOperationException(); 628 } 629 630 631 /** 632 * Presently unsupported operation! 633 */ 634 public DirContext getSchemaClassDefinition( String name ) throws NamingException 635 { 636 throw new UnsupportedOperationException(); 637 } 638 639 640 // ------------------------------------------------------------------------ 641 // Search Operation Implementations 642 // ------------------------------------------------------------------------ 643 644 /** 645 * @see javax.naming.directory.DirContext#search(java.lang.String, 646 * javax.naming.directory.Attributes) 647 */ 648 public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes ) throws NamingException 649 { 650 return search( new LdapName( name ), matchingAttributes, null ); 651 } 652 653 654 /** 655 * @see javax.naming.directory.DirContext#search(javax.naming.Name, 656 * javax.naming.directory.Attributes) 657 */ 658 public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes ) throws NamingException 659 { 660 return search( name, AttributeUtils.toCaseInsensitive( matchingAttributes ), null ); 661 } 662 663 664 /** 665 * @see javax.naming.directory.DirContext#search(java.lang.String, 666 * javax.naming.directory.Attributes, java.lang.String[]) 667 */ 668 public NamingEnumeration<SearchResult> search( String name, Attributes matchingAttributes, 669 String[] attributesToReturn ) throws NamingException 670 { 671 return search( new LdapName( name ), AttributeUtils.toCaseInsensitive( matchingAttributes ), attributesToReturn ); 672 } 673 674 675 /** 676 * @see javax.naming.directory.DirContext#search(javax.naming.Name, 677 * javax.naming.directory.Attributes, java.lang.String[]) 678 */ 679 public NamingEnumeration<SearchResult> search( Name name, Attributes matchingAttributes, String[] attributesToReturn ) 680 throws NamingException 681 { 682 SearchControls ctls = new SearchControls(); 683 Dn target = buildTarget( JndiUtils.fromName( name ) ); 684 685 // If we need to return specific attributes add em to the SearchControls 686 if ( null != attributesToReturn ) 687 { 688 ctls.setReturningAttributes( attributesToReturn ); 689 } 690 691 // If matchingAttributes is null/empty use a match for everything filter 692 matchingAttributes = AttributeUtils.toCaseInsensitive( matchingAttributes ); 693 694 if ( ( null == matchingAttributes ) || ( matchingAttributes.size() <= 0 ) ) 695 { 696 PresenceNode filter = new PresenceNode( objectClassAT ); 697 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() ); 698 try 699 { 700 EntryFilteringCursor cursor = doSearchOperation( target, aliasDerefMode, filter, ctls ); 701 return new NamingEnumerationAdapter( cursor ); 702 } 703 catch ( Exception e ) 704 { 705 JndiUtils.wrap( e ); 706 } 707 } 708 709 // Handle simple filter expressions without multiple terms 710 if ( matchingAttributes.size() == 1 ) 711 { 712 NamingEnumeration<? extends javax.naming.directory.Attribute> list = matchingAttributes.getAll(); 713 javax.naming.directory.Attribute attr = list.next(); 714 list.close(); 715 716 if ( attr.size() == 1 ) 717 { 718 Object value = attr.get(); 719 SimpleNode<?> node; 720 String attributeType = attr.getID(); 721 722 if ( value instanceof byte[] ) 723 { 724 node = new EqualityNode<>( attributeType, ( byte[] ) value ); 725 } 726 else 727 { 728 node = new EqualityNode<>( attributeType, ( String ) value ); 729 } 730 731 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() ); 732 733 try 734 { 735 EntryFilteringCursor cursor = doSearchOperation( target, aliasDerefMode, node, ctls ); 736 return new NamingEnumerationAdapter( cursor ); 737 } 738 catch ( Exception e ) 739 { 740 JndiUtils.wrap( e ); 741 return null; // shut compiler up 742 } 743 } 744 } 745 746 /* 747 * Go through the set of attributes using each attribute value pair as 748 * an attribute value assertion within one big AND filter expression. 749 */ 750 javax.naming.directory.Attribute attr; 751 SimpleNode node; 752 BranchNode filter = new AndNode(); 753 NamingEnumeration<? extends javax.naming.directory.Attribute> list = matchingAttributes.getAll(); 754 755 // Loop through each attribute value pair 756 while ( list.hasMore() ) 757 { 758 attr = list.next(); 759 760 /* 761 * According to JNDI if an attribute in the matchingAttributes 762 * list does not have any values then we match for just the presence 763 * of the attribute in the entry 764 */ 765 if ( attr.size() == 0 ) 766 { 767 filter.addNode( new PresenceNode( attr.getID() ) ); 768 continue; 769 } 770 771 /* 772 * With 1 or more value we build a set of simple nodes and add them 773 * to the AND node - each attribute value pair is a simple Ava node. 774 */ 775 for ( int ii = 0; ii < attr.size(); ii++ ) 776 { 777 Object val = attr.get( ii ); 778 779 // Add simpel Ava node if its value is a String 780 if ( val instanceof String ) 781 { 782 node = new EqualityNode<String>( attr.getID(), ( String ) val ); 783 filter.addNode( node ); 784 } 785 } 786 } 787 788 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() ); 789 try 790 { 791 EntryFilteringCursor cursor = doSearchOperation( target, aliasDerefMode, filter, ctls ); 792 return new NamingEnumerationAdapter( cursor ); 793 } 794 catch ( Exception e ) 795 { 796 JndiUtils.wrap( e ); 797 return null; // shut compiler up 798 } 799 } 800 801 802 /** 803 * @see javax.naming.directory.DirContext#search(java.lang.String, 804 * java.lang.String, javax.naming.directory.SearchControls) 805 */ 806 public NamingEnumeration<SearchResult> search( String name, String filter, SearchControls cons ) 807 throws NamingException 808 { 809 return search( new LdapName( name ), filter, cons ); 810 } 811 812 813 /** 814 * A search overload that is used for optimizing search handling in the 815 * LDAP protocol provider which deals with an ExprNode instance rather than 816 * a String for the filter. 817 * 818 * @param name the relative name of the object serving as the search base 819 * @param filter the search filter as an expression tree 820 * @param cons the search controls to use 821 * @return an enumeration over the SearchResults 822 * @throws NamingException if there are problems performing the search 823 */ 824 public NamingEnumeration<SearchResult> search( Name name, ExprNode filter, SearchControls cons ) 825 throws NamingException 826 { 827 Dn target = buildTarget( JndiUtils.fromName( name ) ); 828 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() ); 829 try 830 { 831 return new NamingEnumerationAdapter( doSearchOperation( target, aliasDerefMode, filter, cons ) ); 832 } 833 catch ( Exception e ) 834 { 835 JndiUtils.wrap( e ); 836 return null; // shut compiler up 837 } 838 } 839 840 841 /** 842 * @see javax.naming.directory.DirContext#search(javax.naming.Name, 843 * java.lang.String, javax.naming.directory.SearchControls) 844 */ 845 public NamingEnumeration<SearchResult> search( Name name, String filter, SearchControls cons ) 846 throws NamingException 847 { 848 ExprNode filterNode; 849 Dn target = buildTarget( JndiUtils.fromName( name ) ); 850 851 try 852 { 853 filterNode = FilterParser.parse( schemaManager, filter ); 854 } 855 catch ( ParseException pe ) 856 { 857 InvalidSearchFilterException isfe = new InvalidSearchFilterException( I18n.err( I18n.ERR_500, filter ) ); 858 isfe.setRootCause( pe ); 859 throw isfe; 860 } 861 862 AliasDerefMode aliasDerefMode = AliasDerefMode.getEnum( getEnvironment() ); 863 864 try 865 { 866 EntryFilteringCursor cursor = doSearchOperation( target, aliasDerefMode, filterNode, cons ); 867 return new NamingEnumerationAdapter( cursor ); 868 } 869 catch ( Exception e ) 870 { 871 JndiUtils.wrap( e ); 872 return null; // shut compiler up 873 } 874 } 875 876 877 /** 878 * @see javax.naming.directory.DirContext#search(java.lang.String, 879 * java.lang.String, java.lang.Object[], 880 * javax.naming.directory.SearchControls) 881 */ 882 public NamingEnumeration<SearchResult> search( String name, String filterExpr, Object[] filterArgs, 883 SearchControls cons ) throws NamingException 884 { 885 return search( new LdapName( name ), filterExpr, filterArgs, cons ); 886 } 887 888 889 /** 890 * @see javax.naming.directory.DirContext#search(javax.naming.Name, 891 * java.lang.String, java.lang.Object[], 892 * javax.naming.directory.SearchControls) 893 */ 894 public NamingEnumeration<SearchResult> search( Name name, String filterExpr, Object[] filterArgs, 895 SearchControls cons ) throws NamingException 896 { 897 int start; 898 int index; 899 900 StringBuilder buf = new StringBuilder( filterExpr ); 901 902 // Scan until we hit the end of the string buffer 903 for ( int ii = 0; ii < buf.length(); ii++ ) 904 { 905 try 906 { 907 // Advance until we hit the start of a variable 908 while ( ii < buf.length() && '{' != buf.charAt( ii ) ) 909 { 910 ii++; 911 } 912 913 // Record start of variable at '{' 914 start = ii; 915 916 // Advance to the end of a variable at '}' 917 while ( '}' != buf.charAt( ii ) ) 918 { 919 ii++; 920 } 921 } 922 catch ( IndexOutOfBoundsException e ) 923 { 924 // End of filter so done. 925 break; 926 } 927 928 // Parse index 929 index = Integer.parseInt( buf.substring( start + 1, ii ) ); 930 931 if ( filterArgs[index] instanceof String ) 932 { 933 /* 934 * Replace the '{ i }' with the string representation of the value 935 * held in the filterArgs array at index index. 936 */ 937 buf.replace( start, ii + 1, ( String ) filterArgs[index] ); 938 } 939 else if ( filterArgs[index] instanceof byte[] ) 940 { 941 String hexstr = "#" + Strings.toHexString( ( byte[] ) filterArgs[index] ); 942 buf.replace( start, ii + 1, hexstr ); 943 } 944 else 945 { 946 /* 947 * Replace the '{ i }' with the string representation of the value 948 * held in the filterArgs array at index index. 949 */ 950 buf.replace( start, ii + 1, filterArgs[index].toString() ); 951 } 952 } 953 954 return search( name, buf.toString(), cons ); 955 } 956 957 958 // ------------------------------------------------------------------------ 959 // EventDirContext implementations 960 // ------------------------------------------------------------------------ 961 962 public void addNamingListener( Name name, String filterStr, SearchControls searchControls, 963 NamingListener namingListener ) throws NamingException 964 { 965 ExprNode filter; 966 967 try 968 { 969 filter = FilterParser.parse( schemaManager, filterStr ); 970 } 971 catch ( Exception e ) 972 { 973 NamingException e2 = new NamingException( I18n.err( I18n.ERR_501, filterStr ) ); 974 e2.setRootCause( e ); 975 throw e2; 976 } 977 978 try 979 { 980 DirectoryListener listener = new EventListenerAdapter( ( ServerLdapContext ) this, namingListener ); 981 NotificationCriteria criteria = new NotificationCriteria( schemaManager ); 982 criteria.setFilter( filter ); 983 criteria.setScope( SearchScope.getSearchScope( searchControls.getSearchScope() ) ); 984 criteria.setAliasDerefMode( AliasDerefMode.getEnum( getEnvironment() ) ); 985 criteria.setBase( buildTarget( JndiUtils.fromName( name ) ) ); 986 987 getDirectoryService().getEventService().addListener( listener, criteria ); 988 getListeners().put( namingListener, listener ); 989 } 990 catch ( Exception e ) 991 { 992 JndiUtils.wrap( e ); 993 } 994 } 995 996 997 public void addNamingListener( String name, String filter, SearchControls searchControls, 998 NamingListener namingListener ) throws NamingException 999 { 1000 addNamingListener( new LdapName( name ), filter, searchControls, namingListener ); 1001 } 1002 1003 1004 public void addNamingListener( Name name, String filterExpr, Object[] filterArgs, SearchControls searchControls, 1005 NamingListener namingListener ) throws NamingException 1006 { 1007 int start; 1008 StringBuilder buf = new StringBuilder( filterExpr ); 1009 1010 // Scan until we hit the end of the string buffer 1011 for ( int ii = 0; ii < buf.length(); ii++ ) 1012 { 1013 // Advance until we hit the start of a variable 1014 while ( '{' != buf.charAt( ii ) ) 1015 { 1016 ii++; 1017 } 1018 1019 // Record start of variable at '{' 1020 start = ii; 1021 1022 // Advance to the end of a variable at '}' 1023 while ( '}' != buf.charAt( ii ) ) 1024 { 1025 ii++; 1026 } 1027 1028 /* 1029 * Replace the '{ i }' with the string representation of the value 1030 * held in the filterArgs array at index index. 1031 */ 1032 buf.replace( start, ii + 1, filterArgs[ii].toString() ); 1033 } 1034 1035 addNamingListener( name, buf.toString(), searchControls, namingListener ); 1036 } 1037 1038 1039 public void addNamingListener( String name, String filter, Object[] objects, SearchControls searchControls, 1040 NamingListener namingListener ) throws NamingException 1041 { 1042 addNamingListener( new LdapName( name ), filter, objects, searchControls, namingListener ); 1043 } 1044}