001/* 002 * Copyright 2009-2014 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2009-2014 UnboundID Corp. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.migrate.jndi; 022 023 024 025import java.util.Collection; 026import javax.naming.NamingEnumeration; 027import javax.naming.NamingException; 028import javax.naming.directory.Attributes; 029import javax.naming.directory.BasicAttribute; 030import javax.naming.directory.BasicAttributes; 031import javax.naming.directory.DirContext; 032import javax.naming.directory.ModificationItem; 033import javax.naming.directory.SearchResult; 034import javax.naming.ldap.BasicControl; 035import javax.naming.ldap.ExtendedResponse; 036 037import com.unboundid.asn1.ASN1Exception; 038import com.unboundid.asn1.ASN1OctetString; 039import com.unboundid.ldap.sdk.Attribute; 040import com.unboundid.ldap.sdk.Control; 041import com.unboundid.ldap.sdk.Entry; 042import com.unboundid.ldap.sdk.ExtendedRequest; 043import com.unboundid.ldap.sdk.ExtendedResult; 044import com.unboundid.ldap.sdk.Modification; 045import com.unboundid.ldap.sdk.ModificationType; 046import com.unboundid.util.NotMutable; 047import com.unboundid.util.ThreadSafety; 048import com.unboundid.util.ThreadSafetyLevel; 049 050import static com.unboundid.util.StaticUtils.*; 051 052 053 054/** 055 * This utility class provides a set of methods that may be used to convert 056 * between data structures in the Java Naming and Directory Interface (JNDI) 057 * and the corresponding data structures in the UnboundID LDAP SDK for Java. 058 */ 059@NotMutable() 060@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 061public final class JNDIConverter 062{ 063 /** 064 * An empty array of attributes. 065 */ 066 private static final Attribute[] NO_ATTRIBUTES = new Attribute[0]; 067 068 069 070 071 /** 072 * An empty array of JNDI controls. 073 */ 074 private static final javax.naming.ldap.Control[] NO_JNDI_CONTROLS = 075 new javax.naming.ldap.Control[0]; 076 077 078 079 /** 080 * An empty array of SDK modifications. 081 */ 082 private static final Modification[] NO_MODIFICATIONS = new Modification[0]; 083 084 085 086 /** 087 * An empty array of JNDI modification items. 088 */ 089 private static final ModificationItem[] NO_MODIFICATION_ITEMS = 090 new ModificationItem[0]; 091 092 093 094 095 /** 096 * An empty array of SDK controls. 097 */ 098 private static final Control[] NO_SDK_CONTROLS = new Control[0]; 099 100 101 102 103 /** 104 * Prevent this utility class from being instantiated. 105 */ 106 private JNDIConverter() 107 { 108 // No implementation required. 109 } 110 111 112 113 /** 114 * Converts the provided JNDI attribute to an LDAP SDK attribute. 115 * 116 * @param a The attribute to be converted. 117 * 118 * @return The LDAP SDK attribute that corresponds to the provided JNDI 119 * attribute. 120 * 121 * @throws NamingException If a problem is encountered during the conversion 122 * process. 123 */ 124 public static Attribute convertAttribute( 125 final javax.naming.directory.Attribute a) 126 throws NamingException 127 { 128 if (a == null) 129 { 130 return null; 131 } 132 133 final String name = a.getID(); 134 final ASN1OctetString[] values = new ASN1OctetString[a.size()]; 135 136 for (int i=0; i < values.length; i++) 137 { 138 final Object value = a.get(i); 139 if (value instanceof byte[]) 140 { 141 values[i] = new ASN1OctetString((byte[]) value); 142 } 143 else 144 { 145 values[i] = new ASN1OctetString(String.valueOf(value)); 146 } 147 } 148 149 return new Attribute(name, values); 150 } 151 152 153 154 /** 155 * Converts the provided LDAP SDK attribute to a JNDI attribute. 156 * 157 * @param a The attribute to be converted. 158 * 159 * @return The JNDI attribute that corresponds to the provided LDAP SDK 160 * attribute. 161 */ 162 public static javax.naming.directory.Attribute convertAttribute( 163 final Attribute a) 164 { 165 if (a == null) 166 { 167 return null; 168 } 169 170 final BasicAttribute attr = new BasicAttribute(a.getName(), true); 171 for (final String v : a.getValues()) 172 { 173 attr.add(v); 174 } 175 176 return attr; 177 } 178 179 180 181 /** 182 * Converts the provided JNDI attributes to an array of LDAP SDK attributes. 183 * 184 * @param a The attributes to be converted. 185 * 186 * @return The array of LDAP SDK attributes that corresponds to the 187 * provided JNDI attributes. 188 * 189 * @throws NamingException If a problem is encountered during the conversion 190 * process. 191 */ 192 public static Attribute[] convertAttributes(final Attributes a) 193 throws NamingException 194 { 195 if (a == null) 196 { 197 return NO_ATTRIBUTES; 198 } 199 200 int i=0; 201 final Attribute[] attributes = new Attribute[a.size()]; 202 final NamingEnumeration<? extends javax.naming.directory.Attribute> e = 203 a.getAll(); 204 205 try 206 { 207 while (e.hasMoreElements()) 208 { 209 attributes[i++] = convertAttribute(e.next()); 210 } 211 } 212 finally 213 { 214 e.close(); 215 } 216 217 return attributes; 218 } 219 220 221 222 /** 223 * Converts the provided array of LDAP SDK attributes to a set of JNDI 224 * attributes. 225 * 226 * @param a The array of attributes to be converted. 227 * 228 * @return The JNDI attributes that corresponds to the provided LDAP SDK 229 * attributes. 230 */ 231 public static Attributes convertAttributes(final Attribute... a) 232 { 233 final BasicAttributes attrs = new BasicAttributes(true); 234 if (a == null) 235 { 236 return attrs; 237 } 238 239 for (final Attribute attr : a) 240 { 241 attrs.put(convertAttribute(attr)); 242 } 243 244 return attrs; 245 } 246 247 248 249 /** 250 * Converts the provided collection of LDAP SDK attributes to a set of JNDI 251 * attributes. 252 * 253 * @param a The collection of attributes to be converted. 254 * 255 * @return The JNDI attributes that corresponds to the provided LDAP SDK 256 * attributes. 257 */ 258 public static Attributes convertAttributes(final Collection<Attribute> a) 259 { 260 final BasicAttributes attrs = new BasicAttributes(true); 261 if (a == null) 262 { 263 return attrs; 264 } 265 266 for (final Attribute attr : a) 267 { 268 attrs.put(convertAttribute(attr)); 269 } 270 271 return attrs; 272 } 273 274 275 276 /** 277 * Converts the provided JNDI control to an LDAP SDK control. 278 * 279 * @param c The control to be converted. 280 * 281 * @return The LDAP SDK control that corresponds to the provided JNDI 282 * control. 283 * 284 * @throws NamingException If a problem is encountered during the conversion 285 * process. 286 */ 287 public static Control convertControl(final javax.naming.ldap.Control c) 288 throws NamingException 289 { 290 if (c == null) 291 { 292 return null; 293 } 294 295 final ASN1OctetString value; 296 final byte[] valueBytes = c.getEncodedValue(); 297 if ((valueBytes == null) || (valueBytes.length == 0)) 298 { 299 value = null; 300 } 301 else 302 { 303 try 304 { 305 value = ASN1OctetString.decodeAsOctetString(valueBytes); 306 } 307 catch (ASN1Exception ae) 308 { 309 throw new NamingException(getExceptionMessage(ae)); 310 } 311 } 312 313 return new Control(c.getID(), c.isCritical(), value); 314 } 315 316 317 318 /** 319 * Converts the provided LDAP SDK control to a JNDI control. 320 * 321 * @param c The control to be converted. 322 * 323 * @return The JNDI control that corresponds to the provided LDAP SDK 324 * control. 325 */ 326 public static javax.naming.ldap.Control convertControl(final Control c) 327 { 328 if (c == null) 329 { 330 return null; 331 } 332 333 final ASN1OctetString value = c.getValue(); 334 if (value == null) 335 { 336 return new BasicControl(c.getOID(), c.isCritical(), null); 337 } 338 else 339 { 340 return new BasicControl(c.getOID(), c.isCritical(), value.encode()); 341 } 342 } 343 344 345 346 /** 347 * Converts the provided array of JNDI controls to an array of LDAP SDK 348 * controls. 349 * 350 * @param c The array of JNDI controls to be converted. 351 * 352 * @return The array of LDAP SDK controls that corresponds to the provided 353 * array of JNDI controls. 354 * 355 * @throws NamingException If a problem is encountered during the conversion 356 * process. 357 */ 358 public static Control[] convertControls(final javax.naming.ldap.Control... c) 359 throws NamingException 360 { 361 if (c == null) 362 { 363 return NO_SDK_CONTROLS; 364 } 365 366 final Control[] controls = new Control[c.length]; 367 for (int i=0; i < controls.length; i++) 368 { 369 controls[i] = convertControl(c[i]); 370 } 371 372 return controls; 373 } 374 375 376 377 /** 378 * Converts the provided array of LDAP SDK controls to an array of JNDI 379 * controls. 380 * 381 * @param c The array of LDAP SDK controls to be converted. 382 * 383 * @return The array of JNDI controls that corresponds to the provided array 384 * of LDAP SDK controls. 385 */ 386 public static javax.naming.ldap.Control[] convertControls(final Control... c) 387 { 388 if (c == null) 389 { 390 return NO_JNDI_CONTROLS; 391 } 392 393 final javax.naming.ldap.Control[] controls = 394 new javax.naming.ldap.Control[c.length]; 395 for (int i=0; i < controls.length; i++) 396 { 397 controls[i] = convertControl(c[i]); 398 } 399 400 return controls; 401 } 402 403 404 405 /** 406 * Converts the provided JNDI extended request to an LDAP SDK extended 407 * request. 408 * 409 * @param r The request to be converted. 410 * 411 * @return The LDAP SDK extended request that corresponds to the provided 412 * JNDI extended request. 413 * 414 * @throws NamingException If a problem is encountered during the conversion 415 * process. 416 */ 417 public static ExtendedRequest convertExtendedRequest( 418 final javax.naming.ldap.ExtendedRequest r) 419 throws NamingException 420 { 421 if (r == null) 422 { 423 return null; 424 } 425 426 return JNDIExtendedRequest.toSDKExtendedRequest(r); 427 } 428 429 430 431 /** 432 * Converts the provided LDAP SDK extended request to a JNDI extended request. 433 * 434 * @param r The request to be converted. 435 * 436 * @return The JNDI extended request that corresponds to the provided LDAP 437 * SDK extended request. 438 */ 439 public static javax.naming.ldap.ExtendedRequest convertExtendedRequest( 440 final ExtendedRequest r) 441 { 442 if (r == null) 443 { 444 return null; 445 } 446 447 return new JNDIExtendedRequest(r); 448 } 449 450 451 452 /** 453 * Converts the provided JNDI extended response to an LDAP SDK extended 454 * result. 455 * 456 * @param r The response to be converted. 457 * 458 * @return The LDAP SDK extended result that corresponds to the provided 459 * JNDI extended response. 460 * 461 * @throws NamingException If a problem is encountered during the conversion 462 * process. 463 */ 464 public static ExtendedResult convertExtendedResponse(final ExtendedResponse r) 465 throws NamingException 466 { 467 if (r == null) 468 { 469 return null; 470 } 471 472 return JNDIExtendedResponse.toSDKExtendedResult(r); 473 } 474 475 476 477 /** 478 * Converts the provided LDAP SDK extended result to a JNDI extended response. 479 * 480 * @param r The result to be converted. 481 * 482 * @return The JNDI extended response that corresponds to the provided LDAP 483 * SDK extended result. 484 */ 485 public static ExtendedResponse convertExtendedResult(final ExtendedResult r) 486 { 487 if (r == null) 488 { 489 return null; 490 } 491 492 return new JNDIExtendedResponse(r); 493 } 494 495 496 497 /** 498 * Converts the provided JNDI modification item to an LDAP SDK modification. 499 * 500 * @param m The JNDI modification item to be converted. 501 * 502 * @return The LDAP SDK modification that corresponds to the provided JNDI 503 * modification item. 504 * 505 * @throws NamingException If a problem is encountered during the conversion 506 * process. 507 */ 508 public static Modification convertModification(final ModificationItem m) 509 throws NamingException 510 { 511 if (m == null) 512 { 513 return null; 514 } 515 516 final ModificationType modType; 517 switch (m.getModificationOp()) 518 { 519 case DirContext.ADD_ATTRIBUTE: 520 modType = ModificationType.ADD; 521 break; 522 case DirContext.REMOVE_ATTRIBUTE: 523 modType = ModificationType.DELETE; 524 break; 525 case DirContext.REPLACE_ATTRIBUTE: 526 modType = ModificationType.REPLACE; 527 break; 528 default: 529 throw new NamingException("Unsupported modification type " + m); 530 } 531 532 final Attribute a = convertAttribute(m.getAttribute()); 533 534 return new Modification(modType, a.getName(), a.getRawValues()); 535 } 536 537 538 539 /** 540 * Converts the provided LDAP SDK modification to a JNDI modification item. 541 * 542 * @param m The LDAP SDK modification to be converted. 543 * 544 * @return The JNDI modification item that corresponds to the provided LDAP 545 * SDK modification. 546 * 547 * @throws NamingException If a problem is encountered during the conversion 548 * process. 549 */ 550 public static ModificationItem convertModification(final Modification m) 551 throws NamingException 552 { 553 if (m == null) 554 { 555 return null; 556 } 557 558 final int modType; 559 switch (m.getModificationType().intValue()) 560 { 561 case ModificationType.ADD_INT_VALUE: 562 modType = DirContext.ADD_ATTRIBUTE; 563 break; 564 case ModificationType.DELETE_INT_VALUE: 565 modType = DirContext.REMOVE_ATTRIBUTE; 566 break; 567 case ModificationType.REPLACE_INT_VALUE: 568 modType = DirContext.REPLACE_ATTRIBUTE; 569 break; 570 default: 571 throw new NamingException("Unsupported modification type " + m); 572 } 573 574 return new ModificationItem(modType, convertAttribute(m.getAttribute())); 575 } 576 577 578 579 /** 580 * Converts the provided array of JNDI modification items to an array of LDAP 581 * SDK modifications. 582 * 583 * @param m The array of JNDI modification items to be converted. 584 * 585 * @return The array of LDAP SDK modifications that corresponds to the 586 * provided array of JNDI modification items. 587 * 588 * @throws NamingException If a problem is encountered during the conversion 589 * process. 590 */ 591 public static Modification[] convertModifications(final ModificationItem... m) 592 throws NamingException 593 { 594 if (m == null) 595 { 596 return NO_MODIFICATIONS; 597 } 598 599 final Modification[] mods = new Modification[m.length]; 600 for (int i=0; i < m.length; i++) 601 { 602 mods[i] = convertModification(m[i]); 603 } 604 605 return mods; 606 } 607 608 609 610 /** 611 * Converts the provided array of LDAP SDK modifications to an array of JNDI 612 * modification items. 613 * 614 * @param m The array of LDAP SDK modifications to be converted. 615 * 616 * @return The array of JNDI modification items that corresponds to the 617 * provided array of LDAP SDK modifications. 618 * 619 * @throws NamingException If a problem is encountered during the conversion 620 * process. 621 */ 622 public static ModificationItem[] convertModifications(final Modification... m) 623 throws NamingException 624 { 625 if (m == null) 626 { 627 return NO_MODIFICATION_ITEMS; 628 } 629 630 final ModificationItem[] mods = new ModificationItem[m.length]; 631 for (int i=0; i < m.length; i++) 632 { 633 mods[i] = convertModification(m[i]); 634 } 635 636 return mods; 637 } 638 639 640 641 /** 642 * Converts the provided JNDI search result object to an LDAP SDK entry. 643 * 644 * @param r The JNDI search result object to be converted. 645 * 646 * @return The LDAP SDK entry that corresponds to the provided JNDI search 647 * result. 648 * 649 * @throws NamingException If a problem is encountered during the conversion 650 * process. 651 */ 652 public static Entry convertSearchEntry(final SearchResult r) 653 throws NamingException 654 { 655 if (r == null) 656 { 657 return null; 658 } 659 660 return new Entry(r.getName(), convertAttributes(r.getAttributes())); 661 } 662 663 664 665 /** 666 * Converts the provided LDAP SDK entry to a JNDI search result. 667 * 668 * @param e The entry to be converted to a JNDI search result. 669 * 670 * @return The JNDI search result that corresponds to the provided LDAP SDK 671 * entry. 672 */ 673 public static SearchResult convertSearchEntry(final Entry e) 674 { 675 if (e == null) 676 { 677 return null; 678 } 679 680 final Collection<Attribute> attrs = e.getAttributes(); 681 final Attribute[] attributes = new Attribute[attrs.size()]; 682 attrs.toArray(attributes); 683 684 return new SearchResult(e.getDN(), null, convertAttributes(attributes)); 685 } 686}