1 17 package org.apache.ldap.server; 18 19 20 import org.apache.ldap.common.MultiException; 21 import org.apache.ldap.common.NotImplementedException; 22 import org.apache.ldap.common.exception.LdapNameNotFoundException; 23 import org.apache.ldap.common.filter.ExprNode; 24 import org.apache.ldap.common.filter.PresenceNode; 25 import org.apache.ldap.common.message.LockableAttributeImpl; 26 import org.apache.ldap.common.message.LockableAttributes; 27 import org.apache.ldap.common.message.LockableAttributesImpl; 28 import org.apache.ldap.common.util.SingletonEnumeration; 29 30 import javax.naming.Name ; 31 import javax.naming.NameNotFoundException ; 32 import javax.naming.NamingEnumeration ; 33 import javax.naming.NamingException ; 34 import javax.naming.directory.*; 35 import javax.naming.ldap.LdapContext ; 36 import java.util.Collections ; 37 import java.util.HashMap ; 38 import java.util.Iterator ; 39 import java.util.Map ; 40 41 42 49 public class RootNexus implements PartitionNexus 50 { 51 52 private static final String ASF = "Apache Software Foundation"; 53 54 55 private static final String VENDORNAME_ATTR = "vendorName"; 56 57 58 private static final String NAMINGCTXS_ATTR = "namingContexts"; 59 60 61 private static RootNexus s_singleton = null; 62 63 64 private boolean closed = false; 65 66 67 private SystemPartition system; 68 69 70 private HashMap backends = new HashMap (); 71 72 73 private final Attributes rootDSE; 74 75 76 84 public RootNexus( SystemPartition system, Attributes rootDSE ) 85 { 86 if ( null != s_singleton ) 87 { 88 throw new IllegalStateException (); 89 } 90 91 s_singleton = this; 92 this.system = system; 93 94 this.rootDSE = rootDSE; 96 Attribute attr = new LockableAttributeImpl( "subschemaSubentry" ); 97 attr.add( "cn=schema,ou=system" ); 98 rootDSE.put( attr ); 99 100 attr = new LockableAttributeImpl( "supportedLDAPVersion" ); 101 rootDSE.put( attr ); 102 attr.add( "3" ); 103 104 attr = new LockableAttributeImpl( "objectClass" ); 105 rootDSE.put( attr ); 106 attr.add( "top" ); 107 attr.add( "extensibleObject" ); 108 109 attr = new LockableAttributeImpl( NAMINGCTXS_ATTR ); 110 rootDSE.put( attr ); 111 112 attr = new LockableAttributeImpl( VENDORNAME_ATTR ); 113 attr.add( ASF ); 114 rootDSE.put( attr ); 115 116 register( this.system ); 118 119 Runtime.getRuntime().addShutdownHook( new Thread ( new Runnable () { 120 public void run() 121 { 122 try 123 { 124 if ( ! isClosed() ) 125 { 126 RootNexus.this.close(); 127 } 128 } 129 catch ( NamingException e ) 130 { 131 e.printStackTrace(); 132 } 135 } 136 }, "RootNexusShutdownHook" ) ); 137 } 138 139 140 144 145 148 public LdapContext getLdapContext() 149 { 150 throw new NotImplementedException(); 151 } 152 153 154 157 public Name getMatchedDn( Name dn, boolean normalized ) throws NamingException 158 { 159 dn = ( Name ) dn.clone(); 160 161 while ( dn.size() > 0 ) 162 { 163 if ( hasEntry( dn ) ) 164 { 165 return dn; 166 } 167 168 dn = dn.getSuffix( 1 ); 169 } 170 171 return dn; 172 } 173 174 175 178 public Name getSuffix( Name dn, boolean normalized ) throws NamingException 179 { 180 ContextPartition backend = getBackend( dn ); 181 182 return backend.getSuffix( normalized ); 183 } 184 185 186 189 public Iterator listSuffixes( boolean normalized ) throws NamingException 190 { 191 return Collections.unmodifiableSet( backends.keySet() ).iterator(); 192 } 193 194 195 200 public Attributes getRootDSE() 201 { 202 return rootDSE; 203 } 204 205 206 210 public void register( ContextPartition backend ) 211 { 212 Attribute namingContexts = rootDSE.get( NAMINGCTXS_ATTR ); 213 214 namingContexts.add( backend.getSuffix( false ).toString() ); 215 216 backends.put( backend.getSuffix( true ).toString(), backend ); 217 } 218 219 220 224 public void unregister( ContextPartition backend ) 225 { 226 Attribute namingContexts = rootDSE.get( NAMINGCTXS_ATTR ); 227 228 namingContexts.remove( backend.getSuffix( false ).toString() ); 229 230 backends.remove( backend.getSuffix( true ).toString() ); 231 } 232 233 234 238 239 242 public void delete( Name dn ) throws NamingException 243 { 244 ContextPartition backend = getBackend( dn ); 245 246 backend.delete( dn ); 247 } 248 249 250 259 public void add( String updn, Name dn, Attributes an_entry ) throws NamingException 260 { 261 ContextPartition backend = getBackend( dn ); 262 263 backend.add( updn, dn, an_entry ); 264 } 265 266 267 270 public void modify( Name dn, int modOp, Attributes mods ) throws NamingException 271 { 272 ContextPartition backend = getBackend( dn ); 273 274 backend.modify( dn, modOp, mods ); 275 } 276 277 278 282 public void modify( Name dn, ModificationItem[] mods ) throws NamingException 283 { 284 ContextPartition backend = getBackend( dn ); 285 286 backend.modify( dn, mods ); 287 } 288 289 290 293 public NamingEnumeration list( Name base ) throws NamingException 294 { 295 ContextPartition backend = getBackend( base ); 296 297 return backend.list( base ); 298 } 299 300 301 304 public NamingEnumeration search( Name base, Map env, ExprNode filter, SearchControls searchCtls ) 305 throws NamingException 306 { 307 308 if ( base.size() == 0 ) 309 { 310 boolean isObjectScope = searchCtls.getSearchScope() == SearchControls.OBJECT_SCOPE; 311 312 boolean isSearchAll = ( ( PresenceNode ) filter ).getAttribute().equalsIgnoreCase( "objectclass" ); 313 314 318 if ( filter instanceof PresenceNode && isObjectScope && isSearchAll ) 319 { 320 Attributes attrs = ( Attributes ) getRootDSE().clone(); 321 322 String [] ids = searchCtls.getReturningAttributes(); 323 324 if ( ids != null && ids.length > 0 ) 325 { 326 boolean doSwap = true; 327 328 Attributes askedFor = new LockableAttributesImpl(); 329 330 for ( int ii = 0; ii < ids.length; ii++ ) 331 { 332 if ( ids[ii].trim().equals( "*" ) ) 333 { 334 doSwap = false; 335 336 break; 337 } 338 339 if ( attrs.get( ids[ii] ) != null ) 340 { 341 askedFor.put( attrs.get( ids[ii] ) ); 342 } 343 } 344 345 if ( doSwap ) 346 { 347 attrs = askedFor; 348 } 349 } 350 351 SearchResult result = new SearchResult( "", null, attrs, false ); 352 353 return new SingletonEnumeration( result ); 354 } 355 356 throw new LdapNameNotFoundException(); 357 } 358 359 ContextPartition backend = getBackend( base ); 360 361 return backend.search( base, env, filter, searchCtls ); 362 } 363 364 365 368 public Attributes lookup( Name dn ) throws NamingException 369 { 370 if ( dn.size() == 0 ) 371 { 372 LockableAttributes retval = ( LockableAttributes ) rootDSE.clone(); 373 374 retval.setLocked( true ); 375 376 return retval; 377 } 378 379 ContextPartition backend = getBackend( dn ); 380 381 return backend.lookup( dn ); 382 } 383 384 385 388 public Attributes lookup( Name dn, String [] attrIds ) throws NamingException 389 { 390 if ( dn.size() == 0 ) 391 { 392 LockableAttributes retval = new LockableAttributesImpl(); 393 394 NamingEnumeration list = rootDSE.getIDs(); 395 396 while ( list.hasMore() ) 397 { 398 String id = ( String ) list.next(); 399 400 Attribute attr = rootDSE.get( id ); 401 402 retval.put( ( Attribute ) attr.clone() ); 403 } 404 405 retval.setLocked( true ); 406 407 return retval; 408 } 409 410 ContextPartition backend = getBackend( dn ); 411 412 return backend.lookup( dn, attrIds ); 413 } 414 415 416 419 public boolean hasEntry( Name dn ) throws NamingException 420 { 421 if ( dn.size() == 0 ) 422 { 423 return true; 424 } 425 426 ContextPartition backend = getBackend( dn ); 427 428 return backend.hasEntry( dn ); 429 } 430 431 432 435 public boolean isSuffix( Name dn ) throws NamingException 436 { 437 return backends.containsKey( dn.toString() ); 438 } 439 440 441 444 public void modifyRn( Name dn, String newRdn, boolean deleteOldRdn ) throws NamingException 445 { 446 ContextPartition backend = getBackend( dn ); 447 448 backend.modifyRn( dn, newRdn, deleteOldRdn ); 449 } 450 451 452 455 public void move( Name oriChildName, Name newParentName ) throws NamingException 456 { 457 ContextPartition backend = getBackend( oriChildName ); 458 459 backend.move( oriChildName, newParentName ); 460 } 461 462 463 467 public void move( Name oldChildDn, Name newParentDn, String newRdn, 468 boolean deleteOldRdn ) throws NamingException 469 { 470 ContextPartition backend = getBackend( oldChildDn ); 471 472 backend.move( oldChildDn, newParentDn, newRdn, deleteOldRdn ); 473 } 474 475 476 479 public void sync() throws NamingException 480 { 481 MultiException error = null; 482 483 Iterator list = this.backends.values().iterator(); 484 485 while ( list.hasNext() ) 486 { 487 BackingStore store = ( BackingStore ) list.next(); 488 489 try 490 { 491 store.sync(); 492 } 493 catch ( NamingException e ) 494 { 495 e.printStackTrace(); 496 497 if ( error == null ) 498 { 499 error = new MultiException( "Grouping many exceptions on root nexus sync()" ); 500 } 501 502 error.addThrowable( e ); 504 } 505 } 506 507 if ( error != null ) 508 { 509 String msg = "Encountered failures while performing a sync() operation on backing stores"; 510 511 NamingException total = new NamingException ( msg ); 512 513 total.setRootCause( error ); 514 } 515 } 516 517 518 521 public boolean isClosed() 522 { 523 return closed; 524 } 525 526 527 530 public synchronized void close() throws NamingException 531 { 532 if ( closed ) 533 { 534 return; 535 } 536 537 MultiException error = null; 538 539 Iterator list = this.backends.values().iterator(); 540 541 while ( list.hasNext() ) 544 { 545 BackingStore store = ( BackingStore ) list.next(); 546 547 try 548 { 549 store.sync(); 550 551 store.close(); 552 } 553 catch ( NamingException e ) 554 { 555 e.printStackTrace(); 556 557 if ( error == null ) 558 { 559 error = new MultiException( "Grouping many exceptions on root nexus close()" ); 560 } 561 562 error.addThrowable( e ); 564 } 565 } 566 567 s_singleton = null; 568 569 closed = true; 570 571 if ( error != null ) 572 { 573 String msg = "Encountered failures while performing a close() operation on backing stores"; 574 575 NamingException total = new NamingException ( msg ); 576 577 total.setRootCause( error ); 578 579 throw total; 580 } 581 } 582 583 584 588 589 596 private ContextPartition getBackend( Name dn ) throws NamingException 597 { 598 Name clonedDn = ( Name ) dn.clone(); 599 600 while ( clonedDn.size() > 0 ) 601 { 602 if ( backends.containsKey( clonedDn.toString() ) ) 603 { 604 return ( ContextPartition ) backends.get( clonedDn.toString() ); 605 } 606 607 clonedDn.remove( clonedDn.size() - 1 ); 608 } 609 610 throw new NameNotFoundException(); 611 } 612 } 613 | Popular Tags |