1 20 21 package org.apache.directory.ldapstudio.browser.core.internal.model; 22 23 24 import java.util.Hashtable ; 25 26 import javax.naming.CommunicationException ; 27 import javax.naming.Context ; 28 import javax.naming.InsufficientResourcesException ; 29 import javax.naming.NamingEnumeration ; 30 import javax.naming.NamingException ; 31 import javax.naming.ServiceUnavailableException ; 32 import javax.naming.directory.Attributes ; 33 import javax.naming.directory.ModificationItem ; 34 import javax.naming.directory.SearchControls ; 35 import javax.naming.ldap.Control ; 36 import javax.naming.ldap.InitialLdapContext ; 37 import javax.naming.ldap.LdapContext ; 38 import javax.naming.ldap.StartTlsRequest ; 39 import javax.naming.ldap.StartTlsResponse ; 40 import javax.net.ssl.HostnameVerifier; 41 import javax.net.ssl.SSLSession; 42 43 import org.apache.directory.ldapstudio.browser.core.BrowserCoreMessages; 44 import org.apache.directory.ldapstudio.browser.core.jobs.ExtendedProgressMonitor; 45 46 47 public class JNDIConnectionContext 48 { 49 50 private Control [] connCtls; 51 52 private boolean useStartTLS; 53 54 private String authMethod; 55 56 private String principal; 57 58 private String credentials; 59 60 private Hashtable <String , String > environment; 61 62 private InitialLdapContext context; 63 64 private boolean isConnected; 65 66 private Thread jobThread; 67 68 69 public JNDIConnectionContext() throws NamingException 70 { 71 } 72 73 74 public void connect( String host, int port, boolean useLdaps, boolean useStartTLS, Control [] connCtls, 75 ExtendedProgressMonitor monitor ) throws NamingException 76 { 77 78 this.environment = new Hashtable <String , String >(); 79 this.environment.put( Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory" ); this.environment.put( "java.naming.ldap.version", "3" ); 82 if ( !useLdaps ) 84 { 85 this.environment.put( "com.sun.jndi.ldap.connect.timeout", "10000" ); } 87 this.environment.put( "com.sun.jndi.dns.timeout.initial", "2000" ); this.environment.put( "com.sun.jndi.dns.timeout.retries", "3" ); 90 if ( useLdaps ) 92 { 93 environment.put( Context.PROVIDER_URL, "ldaps://" + host + ":" + port ); environment.put( Context.SECURITY_PROTOCOL, "ssl" ); environment.put( "java.naming.ldap.factory.socket", DummySSLSocketFactory.class.getName() ); } 97 else 98 { 99 environment.put( Context.PROVIDER_URL, "ldap://" + host + ":" + port ); } 101 102 this.useStartTLS = useStartTLS; 103 104 this.connCtls = connCtls; 105 106 this.context = null; 107 this.isConnected = false; 108 this.jobThread = null; 109 110 try 111 { 112 this.doConnect( monitor ); 113 } 114 catch ( NamingException ne ) 115 { 116 this.close(); 117 throw ne; 118 } 119 } 120 121 122 public void bindAnonymous( ExtendedProgressMonitor monitor ) throws NamingException 123 { 124 this.authMethod = "none"; this.principal = ""; this.credentials = ""; 128 try 129 { 130 this.doBind( monitor ); 131 } 132 catch ( NamingException ne ) 133 { 134 this.close(); 135 throw ne; 136 } 137 } 138 139 140 public void bindSimple( String user, String password, ExtendedProgressMonitor monitor ) throws NamingException 141 { 142 this.authMethod = "simple"; this.principal = user; 144 this.credentials = password; 145 146 try 147 { 148 this.doBind( monitor ); 149 } 150 catch ( NamingException ne ) 151 { 152 this.close(); 153 throw ne; 154 } 155 } 156 157 158 public void close() throws NamingException 159 { 160 if ( this.jobThread != null ) 161 { 162 Thread t = this.jobThread; 163 this.jobThread = null; 164 t.interrupt(); 165 } 166 if ( this.context != null ) 167 { 168 this.context.close(); 169 this.context = null; 170 } 171 this.isConnected = false; 172 System.gc(); 173 } 174 175 176 public NamingEnumeration search( final String searchBase, final String filter, final SearchControls controls, 177 final String derefAliasMethod, final String handleReferralsMethod, final Control [] ldapControls, 178 final ExtendedProgressMonitor monitor ) throws NamingException 179 { 180 InnerRunnable runnable = new InnerRunnable() 182 { 183 private NamingEnumeration namingEnumeration = null; 184 185 private NamingException namingException = null; 186 187 188 public void run() 189 { 190 191 try 192 { 193 194 207 LdapContext searchCtx = context.newInstance( ldapControls ); 208 try 209 { 210 searchCtx.addToEnvironment( "java.naming.ldap.derefAliases", derefAliasMethod ); searchCtx.addToEnvironment( Context.REFERRAL, handleReferralsMethod ); 212 213 } 214 catch ( NamingException e ) 215 { 216 this.namingException = e; 217 } 218 219 try 220 { 221 this.namingEnumeration = searchCtx.search( searchBase, filter, controls ); 222 } 223 catch ( NamingException ne ) 224 { 225 this.namingException = ne; 226 } 227 228 } 229 catch ( NamingException e ) 230 { 231 this.namingException = e; 232 } 233 234 } 235 236 237 public NamingException getException() 238 { 239 return this.namingException; 240 } 241 242 243 public Object getResult() 244 { 245 return this.namingEnumeration; 246 } 247 248 249 public void reset() 250 { 251 this.namingEnumeration = null; 252 this.namingException = null; 253 } 254 255 }; 256 this.checkConnectionAndRunAndMonitor( runnable, monitor ); 257 258 if ( runnable.getException() != null ) 259 { 260 throw runnable.getException(); 261 } 262 else if ( runnable.getResult() != null && runnable.getResult() instanceof NamingEnumeration ) 263 { 264 return ( NamingEnumeration ) runnable.getResult(); 265 } 266 else 267 { 268 return null; 269 } 270 } 271 272 273 void modifyAttributes( final String dn, final ModificationItem [] modificationItems, final Control [] controls, 274 final ExtendedProgressMonitor monitor ) throws NamingException 275 { 276 277 InnerRunnable runnable = new InnerRunnable() 278 { 279 private NamingException namingException = null; 280 281 282 public void run() 283 { 284 try 285 { 286 LdapContext modCtx = context.newInstance( controls ); 287 modCtx.addToEnvironment( Context.REFERRAL, "throw" ); 289 modCtx.modifyAttributes( dn, modificationItems ); 290 } 291 catch ( NamingException ne ) 292 { 293 this.namingException = ne; 294 } 295 } 296 297 298 public NamingException getException() 299 { 300 return this.namingException; 301 } 302 303 304 public Object getResult() 305 { 306 return null; 307 } 308 309 310 public void reset() 311 { 312 this.namingException = null; 313 } 314 }; 315 this.checkConnectionAndRunAndMonitor( runnable, monitor ); 316 317 if ( runnable.getException() != null ) 318 { 319 throw runnable.getException(); 320 } 321 } 322 323 324 void rename( final String oldDn, final String newDn, final boolean deleteOldRdn, final Control [] controls, 325 final ExtendedProgressMonitor monitor ) throws NamingException 326 { 327 328 InnerRunnable runnable = new InnerRunnable() 329 { 330 private NamingException namingException = null; 331 332 333 public void run() 334 { 335 try 336 { 337 LdapContext modCtx = context.newInstance( controls ); 338 modCtx.addToEnvironment( Context.REFERRAL, "throw" ); 340 modCtx.rename( oldDn, newDn ); 341 342 } 343 catch ( NamingException ne ) 344 { 345 this.namingException = ne; 346 } 347 } 348 349 350 public NamingException getException() 351 { 352 return this.namingException; 353 } 354 355 356 public Object getResult() 357 { 358 return null; 359 } 360 361 362 public void reset() 363 { 364 this.namingException = null; 365 } 366 }; 367 this.checkConnectionAndRunAndMonitor( runnable, monitor ); 368 369 if ( runnable.getException() != null ) 370 { 371 throw runnable.getException(); 372 } 373 } 374 375 376 void createSubcontext( final String dn, final Attributes attributes, final Control [] controls, 377 final ExtendedProgressMonitor monitor ) throws NamingException 378 { 379 380 InnerRunnable runnable = new InnerRunnable() 381 { 382 private NamingException namingException = null; 383 384 385 public void run() 386 { 387 try 388 { 389 LdapContext modCtx = context.newInstance( controls ); 390 modCtx.addToEnvironment( Context.REFERRAL, "throw" ); 392 modCtx.createSubcontext( dn, attributes ); 393 } 394 catch ( NamingException ne ) 395 { 396 this.namingException = ne; 397 } 398 } 399 400 401 public NamingException getException() 402 { 403 return this.namingException; 404 } 405 406 407 public Object getResult() 408 { 409 return null; 410 } 411 412 413 public void reset() 414 { 415 this.namingException = null; 416 } 417 }; 418 this.checkConnectionAndRunAndMonitor( runnable, monitor ); 419 420 if ( runnable.getException() != null ) 421 { 422 throw runnable.getException(); 423 } 424 } 425 426 427 void destroySubcontext( final String dn, final Control [] controls, final ExtendedProgressMonitor monitor ) 428 throws NamingException 429 { 430 431 InnerRunnable runnable = new InnerRunnable() 432 { 433 private NamingException namingException = null; 434 435 436 public void run() 437 { 438 try 439 { 440 LdapContext modCtx = context.newInstance( controls ); 441 modCtx.addToEnvironment( Context.REFERRAL, "throw" ); 443 modCtx.destroySubcontext( dn ); 444 } 445 catch ( NamingException ne ) 446 { 447 this.namingException = ne; 448 } 449 } 450 451 452 public NamingException getException() 453 { 454 return this.namingException; 455 } 456 457 458 public Object getResult() 459 { 460 return null; 461 } 462 463 464 public void reset() 465 { 466 this.namingException = null; 467 } 468 }; 469 this.checkConnectionAndRunAndMonitor( runnable, monitor ); 470 471 if ( runnable.getException() != null ) 472 { 473 throw runnable.getException(); 474 } 475 } 476 477 478 private void doConnect( final ExtendedProgressMonitor monitor ) throws NamingException 479 { 480 481 this.context = null; 482 this.isConnected = true; 483 484 InnerRunnable runnable = new InnerRunnable() 485 { 486 private NamingException namingException = null; 487 488 489 public void run() 490 { 491 try 492 { 493 context = new InitialLdapContext ( environment, connCtls ); 494 495 if ( useStartTLS ) 496 { 497 try 498 { 499 StartTlsResponse tls = ( StartTlsResponse ) context 500 .extendedOperation( new StartTlsRequest () ); 501 tls.setHostnameVerifier( new HostnameVerifier() 502 { 503 public boolean verify( String arg0, SSLSession arg1 ) 504 { 505 return true; 506 } 507 } ); 508 tls.negotiate( new DummySSLSocketFactory() ); 509 510 } 511 catch ( Exception e ) 512 { 513 this.namingException = new NamingException ( e.getMessage() != null ? e.getMessage() 514 : "Error while establishing TLS session" ); this.namingException.setRootCause( e ); 516 context.close(); 517 } 518 } 519 520 } 521 catch ( NamingException ne ) 522 { 523 this.namingException = ne; 524 } 525 } 526 527 528 public NamingException getException() 529 { 530 return this.namingException; 531 } 532 533 534 public Object getResult() 535 { 536 return null; 537 } 538 539 540 public void reset() 541 { 542 this.namingException = null; 543 } 544 }; 545 this.runAndMonitor( runnable, monitor ); 546 547 if ( runnable.getException() != null ) 548 { 549 throw runnable.getException(); 550 } 551 else if ( this.context != null ) 552 { 553 } 555 else 556 { 557 throw new NamingException ( "???" ); } 559 } 560 561 562 private void doBind( final ExtendedProgressMonitor monitor ) throws NamingException 563 { 564 565 if ( this.context != null && this.isConnected ) 566 { 567 568 InnerRunnable runnable = new InnerRunnable() 569 { 570 private NamingException namingException = null; 571 572 573 public void run() 574 { 575 try 576 { 577 context.removeFromEnvironment( Context.SECURITY_AUTHENTICATION ); 578 context.removeFromEnvironment( Context.SECURITY_PRINCIPAL ); 579 context.removeFromEnvironment( Context.SECURITY_CREDENTIALS ); 580 581 context.addToEnvironment( Context.SECURITY_PRINCIPAL, principal ); 582 context.addToEnvironment( Context.SECURITY_CREDENTIALS, credentials ); 583 context.addToEnvironment( Context.SECURITY_AUTHENTICATION, authMethod ); 584 585 context.reconnect( context.getConnectControls() ); 586 } 587 catch ( NamingException ne ) 588 { 589 this.namingException = ne; 590 } 591 } 592 593 594 public NamingException getException() 595 { 596 return this.namingException; 597 } 598 599 600 public Object getResult() 601 { 602 return null; 603 } 604 605 606 public void reset() 607 { 608 this.namingException = null; 609 } 610 }; 611 this.runAndMonitor( runnable, monitor ); 612 613 if ( runnable.getException() != null ) 614 { 615 throw runnable.getException(); 616 } 617 else if ( this.context != null ) 618 { 619 } 621 else 622 { 623 throw new NamingException ( "???" ); } 625 626 } 627 else 628 { 629 throw new NamingException ( BrowserCoreMessages.model__no_connection ); 630 } 631 } 632 633 634 private void checkConnectionAndRunAndMonitor( final InnerRunnable runnable, final ExtendedProgressMonitor monitor ) 635 throws NamingException 636 { 637 638 640 if ( !this.isConnected || this.context == null ) 642 { 643 this.doConnect( monitor ); 644 this.doBind( monitor ); 645 } 646 if ( this.context == null ) 647 { 648 throw new NamingException ( BrowserCoreMessages.model__no_connection ); 649 } 650 651 for ( int i = 0; i <= 1; i++ ) 653 { 654 655 this.runAndMonitor( runnable, monitor ); 656 657 if ( i == 0 659 && runnable.getException() != null 660 && ( ( runnable.getException() instanceof CommunicationException ) 661 || ( runnable.getException() instanceof ServiceUnavailableException ) || ( runnable.getException() instanceof InsufficientResourcesException ) ) ) 662 { 663 664 this.doConnect( monitor ); 665 this.doBind( monitor ); 666 runnable.reset(); 667 } 668 else 669 { 670 break; 671 } 672 } 673 } 674 675 676 private void runAndMonitor( final InnerRunnable runnable, final ExtendedProgressMonitor monitor ) 677 throws CancelException 678 { 679 680 if ( !monitor.isCanceled() ) 681 { 682 683 ExtendedProgressMonitor.CancelListener listener = new ExtendedProgressMonitor.CancelListener() 685 { 686 public void cancelRequested( ExtendedProgressMonitor.CancelEvent event ) 687 { 688 if ( monitor.isCanceled() ) 689 { 690 if ( jobThread.isAlive() ) 691 { 692 jobThread.interrupt(); 693 } 694 if ( context != null ) 695 { 696 try 697 { 698 context.close(); 699 } 700 catch ( NamingException ne ) 701 { 702 } 703 isConnected = false; 704 context = null; 705 System.gc(); 706 } 707 isConnected = false; 708 } 709 } 710 }; 711 monitor.addCancelListener( listener ); 712 this.jobThread = Thread.currentThread(); 713 714 try 716 { 717 718 727 runnable.run(); 728 } 729 finally 730 { 731 monitor.removeCancelListener( listener ); 732 this.jobThread = null; 733 } 734 735 if ( monitor.isCanceled() ) 736 { 737 throw new CancelException(); 738 } 739 740 } 741 } 742 743 interface InnerRunnable extends Runnable 744 { 745 public NamingException getException(); 746 747 748 public Object getResult(); 749 750 751 public void reset(); 752 } 753 754 } 755 | Popular Tags |