001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2007-2010 Sun Microsystems, Inc. 015 * Portions Copyright 2012-2016 ForgeRock AS. 016 */ 017package org.opends.admin.ads; 018 019import static org.forgerock.util.Utils.*; 020import static org.opends.messages.QuickSetupMessages.*; 021 022import java.io.File; 023import java.util.HashMap; 024import java.util.HashSet; 025import java.util.LinkedHashSet; 026import java.util.LinkedList; 027import java.util.Map; 028import java.util.Set; 029import java.util.SortedSet; 030import java.util.TreeSet; 031 032import javax.naming.CompositeName; 033import javax.naming.InvalidNameException; 034import javax.naming.NameAlreadyBoundException; 035import javax.naming.NameNotFoundException; 036import javax.naming.NamingEnumeration; 037import javax.naming.NamingException; 038import javax.naming.NoPermissionException; 039import javax.naming.NotContextException; 040import javax.naming.directory.Attribute; 041import javax.naming.directory.Attributes; 042import javax.naming.directory.BasicAttribute; 043import javax.naming.directory.BasicAttributes; 044import javax.naming.directory.DirContext; 045import javax.naming.directory.SearchControls; 046import javax.naming.directory.SearchResult; 047import javax.naming.ldap.Control; 048import javax.naming.ldap.InitialLdapContext; 049import javax.naming.ldap.LdapContext; 050import javax.naming.ldap.LdapName; 051import javax.naming.ldap.Rdn; 052 053import org.forgerock.i18n.LocalizableMessage; 054import org.forgerock.i18n.slf4j.LocalizedLogger; 055import org.opends.admin.ads.ADSContextException.ErrorType; 056import org.opends.admin.ads.util.ConnectionWrapper; 057import org.opends.quicksetup.Constants; 058import org.opends.server.schema.SchemaConstants; 059import org.opends.server.types.HostPort; 060 061/** Class used to update and read the contents of the Administration Data. */ 062public class ADSContext 063{ 064 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 065 066 /** 067 * Enumeration containing the different server properties syntaxes that could 068 * be stored in the ADS. 069 */ 070 public enum ADSPropertySyntax 071 { 072 /** String syntax. */ 073 STRING, 074 /** Integer syntax. */ 075 INTEGER, 076 /** Boolean syntax. */ 077 BOOLEAN, 078 /** Certificate;binary syntax. */ 079 CERTIFICATE_BINARY 080 } 081 082 /** Enumeration containing the different server properties that are stored in the ADS. */ 083 public enum ServerProperty 084 { 085 /** The ID used to identify the server. */ 086 ID("id",ADSPropertySyntax.STRING), 087 /** The host name of the server. */ 088 HOST_NAME("hostname",ADSPropertySyntax.STRING), 089 /** The LDAP port of the server. */ 090 LDAP_PORT("ldapport",ADSPropertySyntax.INTEGER), 091 /** The JMX port of the server. */ 092 JMX_PORT("jmxport",ADSPropertySyntax.INTEGER), 093 /** The JMX secure port of the server. */ 094 JMXS_PORT("jmxsport",ADSPropertySyntax.INTEGER), 095 /** The LDAPS port of the server. */ 096 LDAPS_PORT("ldapsport",ADSPropertySyntax.INTEGER), 097 /** The administration connector port of the server. */ 098 ADMIN_PORT("adminport",ADSPropertySyntax.INTEGER), 099 /** The certificate used by the server. */ 100 CERTIFICATE("certificate",ADSPropertySyntax.STRING), 101 /** The path where the server is installed. */ 102 INSTANCE_PATH("instancepath",ADSPropertySyntax.STRING), 103 /** The description of the server. */ 104 DESCRIPTION("description",ADSPropertySyntax.STRING), 105 /** The OS of the machine where the server is installed. */ 106 HOST_OS("os",ADSPropertySyntax.STRING), 107 /** Whether LDAP is enabled or not. */ 108 LDAP_ENABLED("ldapEnabled",ADSPropertySyntax.BOOLEAN), 109 /** Whether LDAPS is enabled or not. */ 110 LDAPS_ENABLED("ldapsEnabled",ADSPropertySyntax.BOOLEAN), 111 /** Whether ADMIN is enabled or not. */ 112 ADMIN_ENABLED("adminEnabled",ADSPropertySyntax.BOOLEAN), 113 /** Whether StartTLS is enabled or not. */ 114 STARTTLS_ENABLED("startTLSEnabled",ADSPropertySyntax.BOOLEAN), 115 /** Whether JMX is enabled or not. */ 116 JMX_ENABLED("jmxEnabled",ADSPropertySyntax.BOOLEAN), 117 /** Whether JMX is enabled or not. */ 118 JMXS_ENABLED("jmxsEnabled",ADSPropertySyntax.BOOLEAN), 119 /** The location of the server. */ 120 LOCATION("location",ADSPropertySyntax.STRING), 121 /** The groups to which this server belongs. */ 122 GROUPS("memberofgroups",ADSPropertySyntax.STRING), 123 /** The unique name of the instance key public-key certificate. */ 124 INSTANCE_KEY_ID("ds-cfg-key-id",ADSPropertySyntax.STRING), 125 /** 126 * The instance key-pair public-key certificate. Note: This attribute 127 * belongs to an instance key entry, separate from the server entry and 128 * named by the ds-cfg-key-id attribute from the server entry. 129 */ 130 INSTANCE_PUBLIC_KEY_CERTIFICATE("ds-cfg-public-key-certificate", ADSPropertySyntax.CERTIFICATE_BINARY); 131 132 private final String attrName; 133 private final ADSPropertySyntax attSyntax; 134 135 /** 136 * Private constructor. 137 * 138 * @param n 139 * the name of the attribute. 140 * @param s 141 * the name of the syntax. 142 */ 143 private ServerProperty(String n, ADSPropertySyntax s) 144 { 145 attrName = n; 146 attSyntax = s; 147 } 148 149 /** 150 * Returns the attribute name. 151 * 152 * @return the attribute name. 153 */ 154 public String getAttributeName() 155 { 156 return attrName; 157 } 158 159 /** 160 * Returns the attribute syntax. 161 * 162 * @return the attribute syntax. 163 */ 164 public ADSPropertySyntax getAttributeSyntax() 165 { 166 return attSyntax; 167 } 168 } 169 170 /** Default global admin UID. */ 171 public static final String GLOBAL_ADMIN_UID = "admin"; 172 173 /** The list of server properties that are multivalued. */ 174 private static final Set<ServerProperty> MULTIVALUED_SERVER_PROPERTIES = new HashSet<>(); 175 static 176 { 177 MULTIVALUED_SERVER_PROPERTIES.add(ServerProperty.GROUPS); 178 } 179 180 /** The default server group which will contain all registered servers. */ 181 private static final String ALL_SERVERGROUP_NAME = "all-servers"; 182 183 /** Enumeration containing the different server group properties that are stored in the ADS. */ 184 private enum ServerGroupProperty 185 { 186 /** The UID of the server group. */ 187 UID("cn"), 188 /** The description of the server group. */ 189 DESCRIPTION("description"), 190 /** The members of the server group. */ 191 MEMBERS("uniqueMember"); 192 193 private final String attrName; 194 195 /** 196 * Private constructor. 197 * 198 * @param n 199 * the attribute name. 200 */ 201 private ServerGroupProperty(String n) 202 { 203 attrName = n; 204 } 205 206 /** 207 * Returns the attribute name. 208 * 209 * @return the attribute name. 210 */ 211 public String getAttributeName() 212 { 213 return attrName; 214 } 215 } 216 217 /** The list of server group properties that are multivalued. */ 218 private static final Set<ServerGroupProperty> MULTIVALUED_SERVER_GROUP_PROPERTIES = new HashSet<>(); 219 static 220 { 221 MULTIVALUED_SERVER_GROUP_PROPERTIES.add(ServerGroupProperty.MEMBERS); 222 } 223 224 /** The enumeration containing the different Administrator properties. */ 225 public enum AdministratorProperty 226 { 227 /** The UID of the administrator. */ 228 UID("id", ADSPropertySyntax.STRING), 229 /** The password of the administrator. */ 230 PASSWORD("password", ADSPropertySyntax.STRING), 231 /** The description of the administrator. */ 232 DESCRIPTION("description", ADSPropertySyntax.STRING), 233 /** The DN of the administrator. */ 234 ADMINISTRATOR_DN("administrator dn", ADSPropertySyntax.STRING), 235 /** The administrator privilege. */ 236 PRIVILEGE("privilege", ADSPropertySyntax.STRING); 237 238 private final String attrName; 239 private final ADSPropertySyntax attrSyntax; 240 241 /** 242 * Private constructor. 243 * 244 * @param n 245 * the name of the attribute. 246 * @param s 247 * the name of the syntax. 248 */ 249 private AdministratorProperty(String n, ADSPropertySyntax s) 250 { 251 attrName = n; 252 attrSyntax = s; 253 } 254 255 /** 256 * Returns the attribute name. 257 * 258 * @return the attribute name. 259 */ 260 public String getAttributeName() 261 { 262 return attrName; 263 } 264 265 /** 266 * Returns the attribute syntax. 267 * 268 * @return the attribute syntax. 269 */ 270 public ADSPropertySyntax getAttributeSyntax() 271 { 272 return attrSyntax; 273 } 274 } 275 276 /** The context used to retrieve information. */ 277 private final InitialLdapContext dirContext; 278 private final ConnectionWrapper connectionWrapper; 279 280 /** 281 * Constructor of the ADSContext. 282 * 283 * @param connectionWrapper 284 * provide connection either via JNDI or Ldap Connection 285 */ 286 public ADSContext(ConnectionWrapper connectionWrapper) 287 { 288 this.connectionWrapper = connectionWrapper; 289 this.dirContext = connectionWrapper.getLdapContext(); 290 } 291 292 /** 293 * Returns the DirContext used to retrieve information by this ADSContext. 294 * 295 * @return the DirContext used to retrieve information by this ADSContext. 296 */ 297 public InitialLdapContext getDirContext() 298 { 299 return dirContext; 300 } 301 302 /** 303 * Returns the connection used to retrieve information by this ADSContext. 304 * 305 * @return the connection 306 */ 307 public ConnectionWrapper getConnection() 308 { 309 return connectionWrapper; 310 } 311 312 /** 313 * Returns the host name and port number of this connection. 314 * 315 * @return the hostPort of this connection 316 */ 317 public HostPort getHostPort() 318 { 319 return connectionWrapper.getHostPort(); 320 } 321 322 /** 323 * Method called to register a server in the ADS. 324 * 325 * @param serverProperties 326 * the properties of the server. 327 * @throws ADSContextException 328 * if the server could not be registered. 329 */ 330 public void registerServer(Map<ServerProperty, Object> serverProperties) throws ADSContextException 331 { 332 LdapName dn = makeDNFromServerProperties(serverProperties); 333 BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties, true); 334 try 335 { 336 // This check is required because by default the server container entry 337 // does not exist. 338 if (!isExistingEntry(nameFromDN(getServerContainerDN()))) 339 { 340 createContainerEntry(getServerContainerDN()); 341 } 342 dirContext.createSubcontext(dn, attrs).close(); 343 if (serverProperties.containsKey(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)) 344 { 345 registerInstanceKeyCertificate(serverProperties, dn); 346 } 347 348 // register this server into "all" groups 349 Map<ServerGroupProperty, Object> serverGroupProperties = new HashMap<>(); 350 Set<String> memberList = getServerGroupMemberList(ALL_SERVERGROUP_NAME); 351 if (memberList == null) 352 { 353 memberList = new HashSet<>(); 354 } 355 String newMember = "cn=" + Rdn.escapeValue(serverProperties.get(ServerProperty.ID)); 356 357 memberList.add(newMember); 358 serverGroupProperties.put(ServerGroupProperty.MEMBERS, memberList); 359 360 updateServerGroup(ALL_SERVERGROUP_NAME, serverGroupProperties); 361 362 // Update the server property "GROUPS" 363 Set<?> rawGroupList = (Set<?>) serverProperties.get(ServerProperty.GROUPS); 364 Set<String> groupList = new HashSet<>(); 365 if (rawGroupList != null) 366 { 367 for (Object elm : rawGroupList) 368 { 369 groupList.add(elm.toString()); 370 } 371 } 372 groupList.add(ALL_SERVERGROUP_NAME); 373 serverProperties.put(ServerProperty.GROUPS, groupList); 374 updateServer(serverProperties, null); 375 } 376 catch (ADSContextException ace) 377 { 378 throw ace; 379 } 380 catch (NameAlreadyBoundException x) 381 { 382 throw new ADSContextException(ErrorType.ALREADY_REGISTERED); 383 } 384 catch (Exception x) 385 { 386 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 387 } 388 } 389 390 /** 391 * Method called to update the properties of a server in the ADS. 392 * 393 * @param serverProperties 394 * the new properties of the server. 395 * @param newServerId 396 * The new server Identifier, or null. 397 * @throws ADSContextException 398 * if the server could not be registered. 399 */ 400 private void updateServer(Map<ServerProperty, Object> serverProperties, String newServerId) 401 throws ADSContextException 402 { 403 LdapName dn = makeDNFromServerProperties(serverProperties); 404 405 try 406 { 407 if (newServerId != null) 408 { 409 Map<ServerProperty, Object> newServerProps = new HashMap<>(serverProperties); 410 newServerProps.put(ServerProperty.ID, newServerId); 411 LdapName newDn = makeDNFromServerProperties(newServerProps); 412 dirContext.rename(dn, newDn); 413 dn = newDn; 414 serverProperties.put(ServerProperty.ID, newServerId); 415 } 416 BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties, false); 417 dirContext.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs); 418 if (serverProperties.containsKey(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)) 419 { 420 registerInstanceKeyCertificate(serverProperties, dn); 421 } 422 } 423 catch (ADSContextException ace) 424 { 425 throw ace; 426 } 427 catch (NameNotFoundException x) 428 { 429 throw new ADSContextException(ErrorType.NOT_YET_REGISTERED); 430 } 431 catch (Exception x) 432 { 433 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 434 } 435 } 436 437 /** 438 * Method called to unregister a server in the ADS. Note that the server's 439 * instance key-pair public-key certificate entry (created in 440 * <tt>registerServer()</tt>) is left untouched. 441 * 442 * @param serverProperties 443 * the properties of the server. 444 * @throws ADSContextException 445 * if the server could not be unregistered. 446 */ 447 public void unregisterServer(Map<ServerProperty, Object> serverProperties) throws ADSContextException 448 { 449 LdapName dn = makeDNFromServerProperties(serverProperties); 450 try 451 { 452 // Unregister the server from the server groups. 453 String member = "cn=" + Rdn.escapeValue(serverProperties.get(ServerProperty.ID)); 454 Set<Map<ServerGroupProperty, Object>> serverGroups = readServerGroupRegistry(); 455 for (Map<ServerGroupProperty, Object> serverGroup : serverGroups) 456 { 457 Set<?> memberList = (Set<?>) serverGroup.get(ServerGroupProperty.MEMBERS); 458 if (memberList != null && memberList.remove(member)) 459 { 460 Map<ServerGroupProperty, Object> serverGroupProperties = new HashMap<>(); 461 serverGroupProperties.put(ServerGroupProperty.MEMBERS, memberList); 462 String groupName = (String) serverGroup.get(ServerGroupProperty.UID); 463 updateServerGroup(groupName, serverGroupProperties); 464 } 465 } 466 467 dirContext.destroySubcontext(dn); 468 } 469 catch (NameNotFoundException x) 470 { 471 throw new ADSContextException(ErrorType.NOT_YET_REGISTERED); 472 } 473 catch (NamingException x) 474 { 475 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 476 } 477 478 // Unregister the server in server groups 479 NamingEnumeration<SearchResult> ne = null; 480 try 481 { 482 SearchControls sc = new SearchControls(); 483 484 String serverID = getServerID(serverProperties); 485 if (serverID != null) 486 { 487 String memberAttrName = ServerGroupProperty.MEMBERS.getAttributeName(); 488 String filter = "(" + memberAttrName + "=cn=" + serverID + ")"; 489 sc.setSearchScope(SearchControls.ONELEVEL_SCOPE); 490 ne = dirContext.search(getServerGroupContainerDN(), filter, sc); 491 while (ne.hasMore()) 492 { 493 SearchResult sr = ne.next(); 494 String groupDn = sr.getNameInNamespace(); 495 BasicAttribute newAttr = new BasicAttribute(memberAttrName); 496 NamingEnumeration<? extends Attribute> attrs = sr.getAttributes().getAll(); 497 try 498 { 499 while (attrs.hasMore()) 500 { 501 Attribute attr = attrs.next(); 502 String attrID = attr.getID(); 503 504 if (attrID.equalsIgnoreCase(memberAttrName)) 505 { 506 NamingEnumeration<?> ae = attr.getAll(); 507 try 508 { 509 while (ae.hasMore()) 510 { 511 String value = (String) ae.next(); 512 if (!value.equalsIgnoreCase("cn=" + serverID)) 513 { 514 newAttr.add(value); 515 } 516 } 517 } 518 finally 519 { 520 handleCloseNamingEnumeration(ae); 521 } 522 } 523 } 524 } 525 finally 526 { 527 handleCloseNamingEnumeration(attrs); 528 } 529 BasicAttributes newAttrs = new BasicAttributes(); 530 newAttrs.put(newAttr); 531 if (newAttr.size() > 0) 532 { 533 dirContext.modifyAttributes(groupDn, DirContext.REPLACE_ATTRIBUTE, newAttrs); 534 } 535 else 536 { 537 dirContext.modifyAttributes(groupDn, DirContext.REMOVE_ATTRIBUTE, newAttrs); 538 } 539 } 540 } 541 } 542 catch (NameNotFoundException x) 543 { 544 throw new ADSContextException(ErrorType.BROKEN_INSTALL); 545 } 546 catch (NoPermissionException x) 547 { 548 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 549 } 550 catch (NamingException x) 551 { 552 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 553 } 554 finally 555 { 556 handleCloseNamingEnumeration(ne); 557 } 558 } 559 560 /** 561 * Returns whether a given server is already registered or not. 562 * 563 * @param serverProperties 564 * the server properties. 565 * @return <CODE>true</CODE> if the server was registered and 566 * <CODE>false</CODE> otherwise. 567 * @throws ADSContextException 568 * if something went wrong. 569 */ 570 private boolean isServerAlreadyRegistered(Map<ServerProperty, Object> serverProperties) throws ADSContextException 571 { 572 return isExistingEntry(makeDNFromServerProperties(serverProperties)); 573 } 574 575 /** 576 * Returns whether a given administrator is already registered or not. 577 * 578 * @param uid 579 * the administrator UID. 580 * @return <CODE>true</CODE> if the administrator was registered and 581 * <CODE>false</CODE> otherwise. 582 * @throws ADSContextException 583 * if something went wrong. 584 */ 585 private boolean isAdministratorAlreadyRegistered(String uid) throws ADSContextException 586 { 587 return isExistingEntry(makeDNFromAdministratorProperties(uid)); 588 } 589 590 /** 591 * A convenience method that takes some server properties as parameter and if 592 * there is no server registered associated with those properties, registers 593 * it and if it is already registered, updates it. 594 * 595 * @param serverProperties 596 * the server properties. 597 * @return 0 if the server was registered; 1 if updated (i.e., the server 598 * entry was already in ADS). 599 * @throws ADSContextException 600 * if something goes wrong. 601 */ 602 public int registerOrUpdateServer(Map<ServerProperty, Object> serverProperties) throws ADSContextException 603 { 604 try 605 { 606 registerServer(serverProperties); 607 return 0; 608 } 609 catch (ADSContextException x) 610 { 611 if (x.getError() == ErrorType.ALREADY_REGISTERED) 612 { 613 updateServer(serverProperties, null); 614 return 1; 615 } 616 617 throw x; 618 } 619 } 620 621 /** 622 * Returns the member list of a group of server. 623 * 624 * @param serverGroupId 625 * The group name. 626 * @return the member list of a group of server. 627 * @throws ADSContextException 628 * if something goes wrong. 629 */ 630 private Set<String> getServerGroupMemberList(String serverGroupId) throws ADSContextException 631 { 632 LdapName dn = nameFromDN("cn=" + Rdn.escapeValue(serverGroupId) + "," + getServerGroupContainerDN()); 633 634 Set<String> result = new HashSet<>(); 635 NamingEnumeration<SearchResult> srs = null; 636 NamingEnumeration<? extends Attribute> ne = null; 637 try 638 { 639 SearchControls sc = new SearchControls(); 640 sc.setSearchScope(SearchControls.OBJECT_SCOPE); 641 srs = getDirContext().search(dn, "(objectclass=*)", sc); 642 643 if (!srs.hasMore()) 644 { 645 return result; 646 } 647 Attributes attrs = srs.next().getAttributes(); 648 ne = attrs.getAll(); 649 while (ne.hasMore()) 650 { 651 Attribute attr = ne.next(); 652 String attrID = attr.getID(); 653 654 if (!attrID.toLowerCase().equals(ServerGroupProperty.MEMBERS.getAttributeName().toLowerCase())) 655 { 656 continue; 657 } 658 659 // We have the members list 660 NamingEnumeration<?> ae = attr.getAll(); 661 try 662 { 663 while (ae.hasMore()) 664 { 665 result.add((String) ae.next()); 666 } 667 } 668 finally 669 { 670 handleCloseNamingEnumeration(ae); 671 } 672 break; 673 } 674 } 675 catch (NameNotFoundException x) 676 { 677 result = new HashSet<>(); 678 } 679 catch (NoPermissionException x) 680 { 681 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 682 } 683 catch (NamingException x) 684 { 685 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 686 } 687 finally 688 { 689 handleCloseNamingEnumeration(srs); 690 handleCloseNamingEnumeration(ne); 691 } 692 return result; 693 } 694 695 /** 696 * Returns a set containing the servers that are registered in the ADS. 697 * 698 * @return a set containing the servers that are registered in the ADS. 699 * @throws ADSContextException 700 * if something goes wrong. 701 */ 702 public Set<Map<ServerProperty, Object>> readServerRegistry() throws ADSContextException 703 { 704 Set<Map<ServerProperty, Object>> result = new HashSet<>(); 705 NamingEnumeration<SearchResult> ne = null; 706 try 707 { 708 SearchControls sc = new SearchControls(); 709 710 sc.setSearchScope(SearchControls.ONELEVEL_SCOPE); 711 ne = dirContext.search(getServerContainerDN(), "(objectclass=*)", sc); 712 while (ne.hasMore()) 713 { 714 SearchResult sr = ne.next(); 715 Map<ServerProperty, Object> properties = makePropertiesFromServerAttrs(sr.getAttributes()); 716 Object keyId = properties.get(ServerProperty.INSTANCE_KEY_ID); 717 if (keyId != null) 718 { 719 NamingEnumeration<SearchResult> ne2 = null; 720 try 721 { 722 SearchControls sc1 = new SearchControls(); 723 sc1.setSearchScope(SearchControls.ONELEVEL_SCOPE); 724 final String attrIDs[] = { "ds-cfg-public-key-certificate;binary" }; 725 sc1.setReturningAttributes(attrIDs); 726 727 ne2 = dirContext.search(getInstanceKeysContainerDN(), "(ds-cfg-key-id=" + keyId + ")", sc); 728 boolean found = false; 729 while (ne2.hasMore()) 730 { 731 SearchResult certEntry = ne2.next(); 732 Attribute certAttr = certEntry.getAttributes().get(attrIDs[0]); 733 properties.put(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE, certAttr.get()); 734 found = true; 735 } 736 if (!found) 737 { 738 logger.warn(LocalizableMessage.raw("Could not find public key for " + properties)); 739 } 740 } 741 catch (NameNotFoundException x) 742 { 743 logger.warn(LocalizableMessage.raw("Could not find public key for " + properties)); 744 } 745 finally 746 { 747 handleCloseNamingEnumeration(ne2); 748 } 749 } 750 result.add(properties); 751 } 752 } 753 catch (NameNotFoundException x) 754 { 755 throw new ADSContextException(ErrorType.BROKEN_INSTALL); 756 } 757 catch (NoPermissionException x) 758 { 759 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 760 } 761 catch (NamingException x) 762 { 763 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 764 } 765 finally 766 { 767 handleCloseNamingEnumeration(ne); 768 } 769 770 return result; 771 } 772 773 /** 774 * Creates a Server Group in the ADS. 775 * 776 * @param serverGroupProperties 777 * the properties of the server group to be created. 778 * @throws ADSContextException 779 * if something goes wrong. 780 */ 781 private void createServerGroup(Map<ServerGroupProperty, Object> serverGroupProperties) throws ADSContextException 782 { 783 LdapName dn = makeDNFromServerGroupProperties(serverGroupProperties); 784 BasicAttributes attrs = makeAttrsFromServerGroupProperties(serverGroupProperties); 785 // Add the objectclass attribute value 786 Attribute oc = new BasicAttribute("objectclass"); 787 oc.add("top"); 788 oc.add("groupOfUniqueNames"); 789 attrs.put(oc); 790 try 791 { 792 DirContext ctx = dirContext.createSubcontext(dn, attrs); 793 ctx.close(); 794 } 795 catch (NameAlreadyBoundException x) 796 { 797 throw new ADSContextException(ErrorType.ALREADY_REGISTERED); 798 } 799 catch (NamingException x) 800 { 801 throw new ADSContextException(ErrorType.BROKEN_INSTALL, x); 802 } 803 } 804 805 /** 806 * Updates the properties of a Server Group in the ADS. 807 * 808 * @param serverGroupProperties 809 * the new properties of the server group to be updated. 810 * @param groupID 811 * The group name. 812 * @throws ADSContextException 813 * if something goes wrong. 814 */ 815 private void updateServerGroup(String groupID, Map<ServerGroupProperty, Object> serverGroupProperties) 816 throws ADSContextException 817 { 818 LdapName dn = nameFromDN("cn=" + Rdn.escapeValue(groupID) + "," + getServerGroupContainerDN()); 819 try 820 { 821 // Entry renaming ? 822 if (serverGroupProperties.containsKey(ServerGroupProperty.UID)) 823 { 824 String newGroupId = serverGroupProperties.get(ServerGroupProperty.UID).toString(); 825 if (!newGroupId.equals(groupID)) 826 { 827 // Rename to entry 828 LdapName newDN = nameFromDN("cn=" + Rdn.escapeValue(newGroupId) + "," + getServerGroupContainerDN()); 829 dirContext.rename(dn, newDN); 830 dn = newDN; 831 } 832 833 // In any case, we remove the "cn" attribute. 834 serverGroupProperties.remove(ServerGroupProperty.UID); 835 } 836 if (serverGroupProperties.isEmpty()) 837 { 838 return; 839 } 840 841 BasicAttributes attrs = makeAttrsFromServerGroupProperties(serverGroupProperties); 842 // attribute modification 843 dirContext.modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, attrs); 844 } 845 catch (NameNotFoundException x) 846 { 847 throw new ADSContextException(ErrorType.NOT_YET_REGISTERED); 848 } 849 catch (NameAlreadyBoundException x) 850 { 851 throw new ADSContextException(ErrorType.ALREADY_REGISTERED); 852 } 853 catch (NamingException x) 854 { 855 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 856 } 857 } 858 859 /** 860 * Returns a set containing the server groups that are defined in the ADS. 861 * 862 * @return a set containing the server groups that are defined in the ADS. 863 * @throws ADSContextException 864 * if something goes wrong. 865 */ 866 private Set<Map<ServerGroupProperty, Object>> readServerGroupRegistry() throws ADSContextException 867 { 868 Set<Map<ServerGroupProperty, Object>> result = new HashSet<>(); 869 NamingEnumeration<SearchResult> ne = null; 870 try 871 { 872 SearchControls sc = new SearchControls(); 873 sc.setSearchScope(SearchControls.ONELEVEL_SCOPE); 874 ne = dirContext.search(getServerGroupContainerDN(), "(objectclass=*)", sc); 875 while (ne.hasMore()) 876 { 877 SearchResult sr = ne.next(); 878 result.add(makePropertiesFromServerGroupAttrs(sr.getAttributes())); 879 } 880 } 881 catch (NameNotFoundException x) 882 { 883 throw new ADSContextException(ErrorType.BROKEN_INSTALL); 884 } 885 catch (NoPermissionException x) 886 { 887 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 888 } 889 catch (NamingException x) 890 { 891 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 892 } 893 finally 894 { 895 handleCloseNamingEnumeration(ne); 896 } 897 return result; 898 } 899 900 /** 901 * Returns a set containing the administrators that are defined in the ADS. 902 * 903 * @return a set containing the administrators that are defined in the ADS. 904 * @throws ADSContextException 905 * if something goes wrong. 906 */ 907 public Set<Map<AdministratorProperty, Object>> readAdministratorRegistry() throws ADSContextException 908 { 909 Set<Map<AdministratorProperty, Object>> result = new HashSet<>(); 910 NamingEnumeration<SearchResult> ne = null; 911 try 912 { 913 SearchControls sc = new SearchControls(); 914 sc.setSearchScope(SearchControls.ONELEVEL_SCOPE); 915 String[] attList = { "cn", "userpassword", "ds-privilege-name", "description" }; 916 sc.setReturningAttributes(attList); 917 ne = dirContext.search(getAdministratorContainerDN(), "(objectclass=*)", sc); 918 while (ne.hasMore()) 919 { 920 SearchResult sr = ne.next(); 921 result.add(makePropertiesFromAdministratorAttrs(getRdn(sr.getName()), sr.getAttributes())); 922 } 923 } 924 catch (NameNotFoundException x) 925 { 926 throw new ADSContextException(ErrorType.BROKEN_INSTALL); 927 } 928 catch (NoPermissionException x) 929 { 930 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 931 } 932 catch (NamingException x) 933 { 934 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 935 } 936 finally 937 { 938 handleCloseNamingEnumeration(ne); 939 } 940 941 return result; 942 } 943 944 /** 945 * Creates the Administration Data in the server. The call to this method 946 * assumes that OpenDJ.jar has already been loaded. 947 * 948 * @param backendName 949 * the backend name which will handle admin information. 950 * <CODE>null</CODE> to use the default backend name for the admin 951 * information. 952 * @throws ADSContextException 953 * if something goes wrong. 954 */ 955 public void createAdminData(String backendName) throws ADSContextException 956 { 957 // Add the administration suffix 958 createAdministrationSuffix(backendName); 959 createAdminDataContainers(); 960 } 961 962 /** Create container entries. */ 963 private void createAdminDataContainers() throws ADSContextException 964 { 965 // Create the DIT below the administration suffix 966 if (!isExistingEntry(nameFromDN(getAdministrationSuffixDN()))) 967 { 968 createTopContainerEntry(); 969 } 970 if (!isExistingEntry(nameFromDN(getAdministratorContainerDN()))) 971 { 972 createAdministratorContainerEntry(); 973 } 974 if (!isExistingEntry(nameFromDN(getServerContainerDN()))) 975 { 976 createContainerEntry(getServerContainerDN()); 977 } 978 if (!isExistingEntry(nameFromDN(getServerGroupContainerDN()))) 979 { 980 createContainerEntry(getServerGroupContainerDN()); 981 } 982 983 // Add the default "all-servers" group 984 if (!isExistingEntry(nameFromDN(getAllServerGroupDN()))) 985 { 986 Map<ServerGroupProperty, Object> allServersGroupsMap = new HashMap<>(); 987 allServersGroupsMap.put(ServerGroupProperty.UID, ALL_SERVERGROUP_NAME); 988 createServerGroup(allServersGroupsMap); 989 } 990 991 // Create the CryptoManager instance key DIT below the administration suffix 992 if (!isExistingEntry(nameFromDN(getInstanceKeysContainerDN()))) 993 { 994 createContainerEntry(getInstanceKeysContainerDN()); 995 } 996 997 // Create the CryptoManager secret key DIT below the administration suffix 998 if (!isExistingEntry(nameFromDN(getSecretKeysContainerDN()))) 999 { 1000 createContainerEntry(getSecretKeysContainerDN()); 1001 } 1002 } 1003 1004 /** 1005 * Removes the administration data. 1006 * 1007 * @param removeAdministrators 1008 * {@code true} if administrators should be removed. It may not be 1009 * possible to remove administrators if the operation is being 1010 * performed by one of the administrators because it will cause the 1011 * administrator to be disconnected. 1012 * @throws ADSContextException 1013 * if something goes wrong. 1014 */ 1015 public void removeAdminData(boolean removeAdministrators) throws ADSContextException 1016 { 1017 String[] dns = { getServerContainerDN(), getServerGroupContainerDN(), 1018 removeAdministrators ? getAdministratorContainerDN() : null }; 1019 try 1020 { 1021 Control[] controls = new Control[] { new SubtreeDeleteControl() }; 1022 LdapContext tmpContext = dirContext.newInstance(controls); 1023 try 1024 { 1025 for (String dn : dns) 1026 { 1027 if (dn != null) 1028 { 1029 LdapName ldapName = nameFromDN(dn); 1030 if (isExistingEntry(ldapName)) 1031 { 1032 tmpContext.destroySubcontext(dn); 1033 } 1034 } 1035 } 1036 } 1037 finally 1038 { 1039 try 1040 { 1041 tmpContext.close(); 1042 } 1043 catch (Exception ex) 1044 { 1045 logger.warn(LocalizableMessage.raw("Error while closing LDAP connection after removing admin data", ex)); 1046 } 1047 } 1048 // Recreate the container entries: 1049 createAdminDataContainers(); 1050 } 1051 catch (NamingException x) 1052 { 1053 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1054 } 1055 } 1056 1057 /** 1058 * Returns <CODE>true</CODE> if the server contains Administration Data and 1059 * <CODE>false</CODE> otherwise. 1060 * 1061 * @return <CODE>true</CODE> if the server contains Administration Data and 1062 * <CODE>false</CODE> otherwise. 1063 * @throws ADSContextException 1064 * if something goes wrong. 1065 */ 1066 public boolean hasAdminData() throws ADSContextException 1067 { 1068 String[] dns = { getAdministratorContainerDN(), getAllServerGroupDN(), getServerContainerDN(), 1069 getInstanceKeysContainerDN(), getSecretKeysContainerDN() }; 1070 boolean hasAdminData = true; 1071 for (int i = 0; i < dns.length && hasAdminData; i++) 1072 { 1073 hasAdminData = isExistingEntry(nameFromDN(dns[i])); 1074 } 1075 return hasAdminData; 1076 } 1077 1078 /** 1079 * Returns the DN of the administrator for a given UID. 1080 * 1081 * @param uid 1082 * the UID to be used to generate the DN. 1083 * @return the DN of the administrator for the given UID: 1084 */ 1085 public static String getAdministratorDN(String uid) 1086 { 1087 return "cn=" + Rdn.escapeValue(uid) + "," + getAdministratorContainerDN(); 1088 } 1089 1090 /** 1091 * Creates an Administrator in the ADS. 1092 * 1093 * @param adminProperties 1094 * the properties of the administrator to be created. 1095 * @throws ADSContextException 1096 * if something goes wrong. 1097 */ 1098 public void createAdministrator(Map<AdministratorProperty, Object> adminProperties) throws ADSContextException 1099 { 1100 LdapName dnCentralAdmin = makeDNFromAdministratorProperties(adminProperties); 1101 BasicAttributes attrs = makeAttrsFromAdministratorProperties(adminProperties, true, null); 1102 1103 try 1104 { 1105 DirContext ctx = dirContext.createSubcontext(dnCentralAdmin, attrs); 1106 ctx.close(); 1107 } 1108 catch (NameAlreadyBoundException x) 1109 { 1110 throw new ADSContextException(ErrorType.ALREADY_REGISTERED); 1111 } 1112 catch (NoPermissionException x) 1113 { 1114 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 1115 } 1116 catch (NamingException x) 1117 { 1118 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1119 } 1120 } 1121 1122 /** 1123 * Deletes the administrator in the ADS. 1124 * 1125 * @param adminProperties 1126 * the properties of the administrator to be deleted. 1127 * @throws ADSContextException 1128 * if something goes wrong. 1129 */ 1130 public void deleteAdministrator(Map<AdministratorProperty, Object> adminProperties) throws ADSContextException 1131 { 1132 LdapName dnCentralAdmin = makeDNFromAdministratorProperties(adminProperties); 1133 1134 try 1135 { 1136 dirContext.destroySubcontext(dnCentralAdmin); 1137 } 1138 catch (NameNotFoundException | NotContextException x) 1139 { 1140 throw new ADSContextException(ErrorType.NOT_YET_REGISTERED); 1141 } 1142 catch (NoPermissionException x) 1143 { 1144 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 1145 } 1146 catch (NamingException x) 1147 { 1148 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1149 } 1150 } 1151 1152 /** 1153 * Returns the DN of the suffix that contains the administration data. 1154 * 1155 * @return the DN of the suffix that contains the administration data. 1156 */ 1157 public static String getAdministrationSuffixDN() 1158 { 1159 return "cn=admin data"; 1160 } 1161 1162 /** 1163 * This method returns the DN of the entry that corresponds to the given host 1164 * name and installation path. 1165 * 1166 * @param hostname 1167 * the host name. 1168 * @param ipath 1169 * the installation path. 1170 * @return the DN of the entry that corresponds to the given host name and 1171 * installation path. 1172 * @throws ADSContextException 1173 * if something goes wrong. 1174 */ 1175 private static LdapName makeDNFromHostnameAndPath(String hostname, String ipath) throws ADSContextException 1176 { 1177 return nameFromDN("cn=" + Rdn.escapeValue(hostname + "@" + ipath) + "," + getServerContainerDN()); 1178 } 1179 1180 /** 1181 * This method returns the DN of the entry that corresponds to the given host 1182 * name port representation. 1183 * 1184 * @param serverUniqueId 1185 * the host name and port. 1186 * @return the DN of the entry that corresponds to the given host name and 1187 * port. 1188 * @throws ADSContextException 1189 * if something goes wrong. 1190 */ 1191 private static LdapName makeDNFromServerUniqueId(String serverUniqueId) throws ADSContextException 1192 { 1193 return nameFromDN("cn=" + Rdn.escapeValue(serverUniqueId) + "," + getServerContainerDN()); 1194 } 1195 1196 /** 1197 * This method returns the DN of the entry that corresponds to the given 1198 * server group properties. 1199 * 1200 * @param serverGroupProperties 1201 * the server group properties 1202 * @return the DN of the entry that corresponds to the given server group 1203 * properties. 1204 * @throws ADSContextException 1205 * if something goes wrong. 1206 */ 1207 private static LdapName makeDNFromServerGroupProperties(Map<ServerGroupProperty, Object> serverGroupProperties) 1208 throws ADSContextException 1209 { 1210 String serverGroupId = (String) serverGroupProperties.get(ServerGroupProperty.UID); 1211 if (serverGroupId == null) 1212 { 1213 throw new ADSContextException(ErrorType.MISSING_NAME); 1214 } 1215 return nameFromDN("cn=" + Rdn.escapeValue(serverGroupId) + "," + getServerGroupContainerDN()); 1216 } 1217 1218 /** 1219 * This method returns the DN of the entry that corresponds to the given 1220 * server properties. 1221 * 1222 * @param serverProperties 1223 * the server properties. 1224 * @return the DN of the entry that corresponds to the given server 1225 * properties. 1226 * @throws ADSContextException 1227 * if something goes wrong. 1228 */ 1229 private static LdapName makeDNFromServerProperties(Map<ServerProperty, Object> serverProperties) 1230 throws ADSContextException 1231 { 1232 String serverID = getServerID(serverProperties); 1233 if (serverID != null) 1234 { 1235 return makeDNFromServerUniqueId(serverID); 1236 } 1237 1238 String hostname = getHostname(serverProperties); 1239 try 1240 { 1241 String ipath = getInstallPath(serverProperties); 1242 return makeDNFromHostnameAndPath(hostname, ipath); 1243 } 1244 catch (ADSContextException ace) 1245 { 1246 ServerDescriptor s = ServerDescriptor.createStandalone(serverProperties); 1247 return makeDNFromServerUniqueId(s.getHostPort(true).toString()); 1248 } 1249 } 1250 1251 /** 1252 * This method returns the DN of the entry that corresponds to the given 1253 * administrator properties. 1254 * 1255 * @param adminProperties 1256 * the administrator properties. 1257 * @return the DN of the entry that corresponds to the given administrator 1258 * properties. 1259 * @throws ADSContextException 1260 * if something goes wrong. 1261 */ 1262 private static LdapName makeDNFromAdministratorProperties(Map<AdministratorProperty, Object> adminProperties) 1263 throws ADSContextException 1264 { 1265 return makeDNFromAdministratorProperties(getAdministratorUID(adminProperties)); 1266 } 1267 1268 /** 1269 * This method returns the DN of the entry that corresponds to the given 1270 * administrator properties. 1271 * 1272 * @param adminUid 1273 * the administrator uid. 1274 * @return the DN of the entry that corresponds to the given administrator 1275 * properties. 1276 * @throws ADSContextException 1277 * if something goes wrong. 1278 */ 1279 private static LdapName makeDNFromAdministratorProperties(String adminUid) throws ADSContextException 1280 { 1281 return nameFromDN(getAdministratorDN(adminUid)); 1282 } 1283 1284 /** 1285 * Returns the attributes for some administrator properties. 1286 * 1287 * @param adminProperties 1288 * the administrator properties. 1289 * @param passwordRequired 1290 * Indicates if the properties should include the password. 1291 * @param currentPrivileges 1292 * The current privilege list or null. 1293 * @return the attributes for the given administrator properties. 1294 * @throws ADSContextException 1295 * if something goes wrong. 1296 */ 1297 private static BasicAttributes makeAttrsFromAdministratorProperties( 1298 Map<AdministratorProperty, Object> adminProperties, boolean passwordRequired, 1299 NamingEnumeration<?> currentPrivileges) throws ADSContextException 1300 { 1301 BasicAttributes attrs = new BasicAttributes(); 1302 Attribute oc = new BasicAttribute("objectclass"); 1303 if (passwordRequired) 1304 { 1305 attrs.put("userPassword", getAdministratorPassword(adminProperties)); 1306 } 1307 oc.add("top"); 1308 oc.add("person"); 1309 attrs.put(oc); 1310 attrs.put("sn", GLOBAL_ADMIN_UID); 1311 if (adminProperties.containsKey(AdministratorProperty.DESCRIPTION)) 1312 { 1313 attrs.put("description", adminProperties.get(AdministratorProperty.DESCRIPTION)); 1314 } 1315 Attribute privilegeAtt; 1316 if (adminProperties.containsKey(AdministratorProperty.PRIVILEGE)) 1317 { 1318 // We assume that privilege strings provided in 1319 // AdministratorProperty.PRIVILEGE 1320 // are valid privileges represented as a LinkedList of string. 1321 privilegeAtt = new BasicAttribute("ds-privilege-name"); 1322 if (currentPrivileges != null) 1323 { 1324 while (currentPrivileges.hasMoreElements()) 1325 { 1326 privilegeAtt.add(currentPrivileges.nextElement().toString()); 1327 } 1328 } 1329 1330 LinkedList<?> privileges = (LinkedList<?>) adminProperties.get(AdministratorProperty.PRIVILEGE); 1331 for (Object o : privileges) 1332 { 1333 String p = o.toString(); 1334 if (p.startsWith("-")) 1335 { 1336 privilegeAtt.remove(p.substring(1)); 1337 } 1338 else 1339 { 1340 privilegeAtt.add(p); 1341 } 1342 } 1343 } 1344 else 1345 { 1346 privilegeAtt = addRootPrivileges(); 1347 } 1348 attrs.put(privilegeAtt); 1349 1350 // Add the RootDNs Password policy so the password do not expire. 1351 attrs.put("ds-pwp-password-policy-dn", "cn=Root Password Policy,cn=Password Policies,cn=config"); 1352 1353 return attrs; 1354 } 1355 1356 /** 1357 * Builds an attribute which contains 'root' privileges. 1358 * 1359 * @return The attribute which contains 'root' privileges. 1360 */ 1361 private static Attribute addRootPrivileges() 1362 { 1363 Attribute privilege = new BasicAttribute("ds-privilege-name"); 1364 privilege.add("bypass-acl"); 1365 privilege.add("modify-acl"); 1366 privilege.add("config-read"); 1367 privilege.add("config-write"); 1368 privilege.add("ldif-import"); 1369 privilege.add("ldif-export"); 1370 privilege.add("backend-backup"); 1371 privilege.add("backend-restore"); 1372 privilege.add("server-shutdown"); 1373 privilege.add("server-restart"); 1374 privilege.add("disconnect-client"); 1375 privilege.add("cancel-request"); 1376 privilege.add("password-reset"); 1377 privilege.add("update-schema"); 1378 privilege.add("privilege-change"); 1379 privilege.add("unindexed-search"); 1380 privilege.add("subentry-write"); 1381 privilege.add("changelog-read"); 1382 return privilege; 1383 } 1384 1385 /** 1386 * Returns the attributes for some server properties. 1387 * 1388 * @param serverProperties 1389 * the server properties. 1390 * @param addObjectClass 1391 * Indicates if the object class has to be added. 1392 * @return the attributes for the given server properties. 1393 */ 1394 private static BasicAttributes makeAttrsFromServerProperties(Map<ServerProperty, Object> serverProperties, 1395 boolean addObjectClass) 1396 { 1397 BasicAttributes result = new BasicAttributes(); 1398 1399 // Transform 'properties' into 'attributes' 1400 for (ServerProperty prop : serverProperties.keySet()) 1401 { 1402 Attribute attr = makeAttrFromServerProperty(prop, serverProperties.get(prop)); 1403 if (attr != null) 1404 { 1405 result.put(attr); 1406 } 1407 } 1408 if (addObjectClass) 1409 { 1410 // Add the objectclass attribute value 1411 // TODO: use another structural objectclass 1412 Attribute oc = new BasicAttribute("objectclass"); 1413 oc.add("top"); 1414 oc.add("ds-cfg-branch"); 1415 oc.add("extensibleobject"); 1416 result.put(oc); 1417 } 1418 return result; 1419 } 1420 1421 /** 1422 * Returns the attribute for a given server property. 1423 * 1424 * @param property 1425 * the server property. 1426 * @param value 1427 * the value. 1428 * @return the attribute for a given server property. 1429 */ 1430 private static Attribute makeAttrFromServerProperty(ServerProperty property, Object value) 1431 { 1432 Attribute result; 1433 1434 switch (property) 1435 { 1436 case INSTANCE_PUBLIC_KEY_CERTIFICATE: 1437 result = null; // used in separate instance key entry 1438 break; 1439 case GROUPS: 1440 result = new BasicAttribute(ServerProperty.GROUPS.getAttributeName()); 1441 for (Object o : ((Set<?>) value)) 1442 { 1443 result.add(o); 1444 } 1445 break; 1446 default: 1447 result = new BasicAttribute(property.getAttributeName(), value); 1448 } 1449 return result; 1450 } 1451 1452 /** 1453 * Returns the attributes for some server group properties. 1454 * 1455 * @param serverGroupProperties 1456 * the server group properties. 1457 * @return the attributes for the given server group properties. 1458 */ 1459 private static BasicAttributes makeAttrsFromServerGroupProperties( 1460 Map<ServerGroupProperty, Object> serverGroupProperties) 1461 { 1462 BasicAttributes result = new BasicAttributes(); 1463 1464 // Transform 'properties' into 'attributes' 1465 for (ServerGroupProperty prop : serverGroupProperties.keySet()) 1466 { 1467 Attribute attr = makeAttrFromServerGroupProperty(prop, serverGroupProperties.get(prop)); 1468 if (attr != null) 1469 { 1470 result.put(attr); 1471 } 1472 } 1473 return result; 1474 } 1475 1476 /** 1477 * Returns the attribute for a given server group property. 1478 * 1479 * @param property 1480 * the server group property. 1481 * @param value 1482 * the value. 1483 * @return the attribute for a given server group property. 1484 */ 1485 private static Attribute makeAttrFromServerGroupProperty(ServerGroupProperty property, Object value) 1486 { 1487 switch (property) 1488 { 1489 case MEMBERS: 1490 Attribute result = new BasicAttribute(ServerGroupProperty.MEMBERS.getAttributeName()); 1491 for (Object o : ((Set<?>) value)) 1492 { 1493 result.add(o); 1494 } 1495 return result; 1496 default: 1497 return new BasicAttribute(property.getAttributeName(), value); 1498 } 1499 } 1500 1501 /** 1502 * Returns the properties of a server group for some LDAP attributes. 1503 * 1504 * @param attrs 1505 * the LDAP attributes. 1506 * @return the properties of a server group for some LDAP attributes. 1507 * @throws ADSContextException 1508 * if something goes wrong. 1509 */ 1510 private Map<ServerGroupProperty, Object> makePropertiesFromServerGroupAttrs(Attributes attrs) 1511 throws ADSContextException 1512 { 1513 Map<ServerGroupProperty, Object> result = new HashMap<>(); 1514 try 1515 { 1516 for (ServerGroupProperty prop : ServerGroupProperty.values()) 1517 { 1518 Attribute attr = attrs.get(prop.getAttributeName()); 1519 if (attr == null) 1520 { 1521 continue; 1522 } 1523 Object value; 1524 1525 if (attr.size() >= 1 && MULTIVALUED_SERVER_GROUP_PROPERTIES.contains(prop)) 1526 { 1527 Set<String> set = new HashSet<>(); 1528 NamingEnumeration<?> ae = attr.getAll(); 1529 try 1530 { 1531 while (ae.hasMore()) 1532 { 1533 set.add((String) ae.next()); 1534 } 1535 } 1536 finally 1537 { 1538 ae.close(); 1539 } 1540 value = set; 1541 } 1542 else 1543 { 1544 value = attr.get(0); 1545 } 1546 1547 result.put(prop, value); 1548 } 1549 } 1550 catch (NamingException x) 1551 { 1552 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1553 } 1554 return result; 1555 } 1556 1557 /** 1558 * Returns the properties of a server for some LDAP attributes. 1559 * 1560 * @param attrs 1561 * the LDAP attributes. 1562 * @return the properties of a server for some LDAP attributes. 1563 * @throws ADSContextException 1564 * if something goes wrong. 1565 */ 1566 private Map<ServerProperty, Object> makePropertiesFromServerAttrs(Attributes attrs) throws ADSContextException 1567 { 1568 Map<ServerProperty, Object> result = new HashMap<>(); 1569 try 1570 { 1571 NamingEnumeration<? extends Attribute> ne = attrs.getAll(); 1572 while (ne.hasMore()) 1573 { 1574 Attribute attr = ne.next(); 1575 String attrID = attr.getID(); 1576 Object value; 1577 1578 if (attrID.endsWith(";binary")) 1579 { 1580 attrID = attrID.substring(0, attrID.lastIndexOf(";binary")); 1581 } 1582 1583 ServerProperty prop = null; 1584 ServerProperty[] props = ServerProperty.values(); 1585 for (int i = 0; i < props.length && prop == null; i++) 1586 { 1587 String v = props[i].getAttributeName(); 1588 if (attrID.equalsIgnoreCase(v)) 1589 { 1590 prop = props[i]; 1591 } 1592 } 1593 if (prop == null) 1594 { 1595 // Do not handle it 1596 } 1597 else 1598 { 1599 if (attr.size() >= 1 && MULTIVALUED_SERVER_PROPERTIES.contains(prop)) 1600 { 1601 Set<String> set = new HashSet<>(); 1602 NamingEnumeration<?> ae = attr.getAll(); 1603 try 1604 { 1605 while (ae.hasMore()) 1606 { 1607 set.add((String) ae.next()); 1608 } 1609 } 1610 finally 1611 { 1612 ae.close(); 1613 } 1614 value = set; 1615 } 1616 else 1617 { 1618 value = attr.get(0); 1619 } 1620 1621 result.put(prop, value); 1622 } 1623 } 1624 } 1625 catch (NamingException x) 1626 { 1627 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1628 } 1629 return result; 1630 } 1631 1632 /** 1633 * Returns the properties of an administrator for some rdn and LDAP 1634 * attributes. 1635 * 1636 * @param rdn 1637 * the RDN. 1638 * @param attrs 1639 * the LDAP attributes. 1640 * @return the properties of an administrator for the given rdn and LDAP 1641 * attributes. 1642 * @throws ADSContextException 1643 * if something goes wrong. 1644 */ 1645 private Map<AdministratorProperty, Object> makePropertiesFromAdministratorAttrs(String rdn, Attributes attrs) 1646 throws ADSContextException 1647 { 1648 Map<AdministratorProperty, Object> result = new HashMap<>(); 1649 String dn = nameFromDN(rdn) + "," + getAdministratorContainerDN(); 1650 result.put(AdministratorProperty.ADMINISTRATOR_DN, dn); 1651 NamingEnumeration<? extends Attribute> ne = null; 1652 try 1653 { 1654 ne = attrs.getAll(); 1655 while (ne.hasMore()) 1656 { 1657 Attribute attr = ne.next(); 1658 String attrID = attr.getID(); 1659 Object value; 1660 1661 if ("cn".equalsIgnoreCase(attrID)) 1662 { 1663 value = attr.get(0); 1664 result.put(AdministratorProperty.UID, value); 1665 } 1666 else if ("userpassword".equalsIgnoreCase(attrID)) 1667 { 1668 value = new String((byte[]) attr.get()); 1669 result.put(AdministratorProperty.PASSWORD, value); 1670 } 1671 else if ("description".equalsIgnoreCase(attrID)) 1672 { 1673 value = attr.get(0); 1674 result.put(AdministratorProperty.DESCRIPTION, value); 1675 } 1676 else if ("ds-privilege-name".equalsIgnoreCase(attrID)) 1677 { 1678 LinkedHashSet<String> privileges = new LinkedHashSet<>(); 1679 NamingEnumeration<?> attValueList = attr.getAll(); 1680 while (attValueList.hasMoreElements()) 1681 { 1682 privileges.add(attValueList.next().toString()); 1683 } 1684 result.put(AdministratorProperty.PRIVILEGE, privileges); 1685 } 1686 } 1687 } 1688 catch (NamingException x) 1689 { 1690 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1691 } 1692 finally 1693 { 1694 handleCloseNamingEnumeration(ne); 1695 } 1696 1697 return result; 1698 } 1699 1700 /** 1701 * Returns the parent entry of the server entries. 1702 * 1703 * @return the parent entry of the server entries. 1704 */ 1705 private static String getServerContainerDN() 1706 { 1707 return "cn=Servers," + getAdministrationSuffixDN(); 1708 } 1709 1710 /** 1711 * Returns the parent entry of the administrator entries. 1712 * 1713 * @return the parent entry of the administrator entries. 1714 */ 1715 public static String getAdministratorContainerDN() 1716 { 1717 return "cn=Administrators," + getAdministrationSuffixDN(); 1718 } 1719 1720 /** 1721 * Returns the parent entry of the server group entries. 1722 * 1723 * @return the parent entry of the server group entries. 1724 */ 1725 private static String getServerGroupContainerDN() 1726 { 1727 return "cn=Server Groups," + getAdministrationSuffixDN(); 1728 } 1729 1730 /** 1731 * Returns the all server group entry DN. 1732 * 1733 * @return the all server group entry DN. 1734 */ 1735 private static String getAllServerGroupDN() 1736 { 1737 return "cn=" + Rdn.escapeValue(ALL_SERVERGROUP_NAME) + "," + getServerGroupContainerDN(); 1738 } 1739 1740 /** 1741 * Returns the host name for the given properties. 1742 * 1743 * @param serverProperties 1744 * the server properties. 1745 * @return the host name for the given properties. 1746 * @throws ADSContextException 1747 * if the host name could not be found or its value is not valid. 1748 */ 1749 private static String getHostname(Map<ServerProperty, Object> serverProperties) throws ADSContextException 1750 { 1751 String result = (String) serverProperties.get(ServerProperty.HOST_NAME); 1752 if (result == null) 1753 { 1754 throw new ADSContextException(ErrorType.MISSING_HOSTNAME); 1755 } 1756 else if (result.length() == 0) 1757 { 1758 throw new ADSContextException(ErrorType.NOVALID_HOSTNAME); 1759 } 1760 return result; 1761 } 1762 1763 /** 1764 * Returns the Server ID for the given properties. 1765 * 1766 * @param serverProperties 1767 * the server properties. 1768 * @return the server ID for the given properties or null. 1769 */ 1770 private static String getServerID(Map<ServerProperty, Object> serverProperties) 1771 { 1772 String result = (String) serverProperties.get(ServerProperty.ID); 1773 if (result != null && result.length() == 0) 1774 { 1775 result = null; 1776 } 1777 return result; 1778 } 1779 1780 /** 1781 * Returns the install path for the given properties. 1782 * 1783 * @param serverProperties 1784 * the server properties. 1785 * @return the install path for the given properties. 1786 * @throws ADSContextException 1787 * if the install path could not be found or its value is not valid. 1788 */ 1789 private static String getInstallPath(Map<ServerProperty, Object> serverProperties) throws ADSContextException 1790 { 1791 String result = (String) serverProperties.get(ServerProperty.INSTANCE_PATH); 1792 if (result == null) 1793 { 1794 throw new ADSContextException(ErrorType.MISSING_IPATH); 1795 } 1796 else if (result.length() == 0) 1797 { 1798 throw new ADSContextException(ErrorType.NOVALID_IPATH); 1799 } 1800 return result; 1801 } 1802 1803 /** 1804 * Returns the Administrator UID for the given properties. 1805 * 1806 * @param adminProperties 1807 * the server properties. 1808 * @return the Administrator UID for the given properties. 1809 * @throws ADSContextException 1810 * if the administrator UID could not be found. 1811 */ 1812 private static String getAdministratorUID(Map<AdministratorProperty, Object> adminProperties) 1813 throws ADSContextException 1814 { 1815 String result = (String) adminProperties.get(AdministratorProperty.UID); 1816 if (result == null) 1817 { 1818 throw new ADSContextException(ErrorType.MISSING_ADMIN_UID); 1819 } 1820 return result; 1821 } 1822 1823 /** 1824 * Returns the Administrator password for the given properties. 1825 * 1826 * @param adminProperties 1827 * the server properties. 1828 * @return the Administrator password for the given properties. 1829 * @throws ADSContextException 1830 * if the administrator password could not be found. 1831 */ 1832 private static String getAdministratorPassword(Map<AdministratorProperty, Object> adminProperties) 1833 throws ADSContextException 1834 { 1835 String result = (String) adminProperties.get(AdministratorProperty.PASSWORD); 1836 if (result == null) 1837 { 1838 throw new ADSContextException(ErrorType.MISSING_ADMIN_PASSWORD); 1839 } 1840 return result; 1841 } 1842 1843 // LDAP utilities 1844 /** 1845 * Returns the LdapName object for the given dn. 1846 * 1847 * @param dn 1848 * the DN. 1849 * @return the LdapName object for the given dn. 1850 * @throws ADSContextException 1851 * if a valid LdapName could not be retrieved for the given dn. 1852 */ 1853 private static LdapName nameFromDN(String dn) throws ADSContextException 1854 { 1855 try 1856 { 1857 return new LdapName(dn); 1858 } 1859 catch (InvalidNameException x) 1860 { 1861 logger.error(LocalizableMessage.raw("Error parsing dn " + dn, x)); 1862 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1863 } 1864 } 1865 1866 /** 1867 * Returns the String rdn for the given search result name. 1868 * 1869 * @param rdnName 1870 * the search result name. 1871 * @return the String rdn for the given search result name. 1872 * @throws ADSContextException 1873 * if a valid String rdn could not be retrieved for the given result 1874 * name. 1875 */ 1876 private static String getRdn(String rdnName) throws ADSContextException 1877 { 1878 // Transform the JNDI name into a RDN string 1879 try 1880 { 1881 return new CompositeName(rdnName).get(0); 1882 } 1883 catch (InvalidNameException x) 1884 { 1885 logger.error(LocalizableMessage.raw("Error parsing rdn " + rdnName, x)); 1886 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1887 } 1888 } 1889 1890 /** 1891 * Tells whether an entry with the provided DN exists. 1892 * 1893 * @param dn 1894 * the DN to check. 1895 * @return <CODE>true</CODE> if the entry exists and <CODE>false</CODE> if it 1896 * does not. 1897 * @throws ADSContextException 1898 * if an error occurred while checking if the entry exists or not. 1899 */ 1900 private boolean isExistingEntry(LdapName dn) throws ADSContextException 1901 { 1902 try 1903 { 1904 SearchControls sc = new SearchControls(); 1905 sc.setSearchScope(SearchControls.OBJECT_SCOPE); 1906 sc.setReturningAttributes(new String[] { SchemaConstants.NO_ATTRIBUTES }); 1907 NamingEnumeration<SearchResult> sr = getDirContext().search(dn, "(objectclass=*)", sc); 1908 try 1909 { 1910 while (sr.hasMore()) 1911 { 1912 sr.next(); 1913 return true; 1914 } 1915 } 1916 finally 1917 { 1918 sr.close(); 1919 } 1920 return false; 1921 } 1922 catch (NameNotFoundException x) 1923 { 1924 return false; 1925 } 1926 catch (NoPermissionException x) 1927 { 1928 throw new ADSContextException(ErrorType.ACCESS_PERMISSION); 1929 } 1930 catch (javax.naming.NamingException x) 1931 { 1932 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 1933 } 1934 } 1935 1936 /** 1937 * Creates a container entry with the given dn. 1938 * 1939 * @param dn 1940 * the entry of the new entry to be created. 1941 * @throws ADSContextException 1942 * if the entry could not be created. 1943 */ 1944 private void createContainerEntry(String dn) throws ADSContextException 1945 { 1946 Attribute oc = new BasicAttribute("objectclass"); 1947 oc.add("top"); 1948 oc.add("ds-cfg-branch"); 1949 BasicAttributes attrs = new BasicAttributes(); 1950 attrs.put(oc); 1951 createEntry(dn, attrs); 1952 } 1953 1954 /** 1955 * Creates the administrator container entry. 1956 * 1957 * @throws ADSContextException 1958 * if the entry could not be created. 1959 */ 1960 private void createAdministratorContainerEntry() throws ADSContextException 1961 { 1962 Attribute oc = new BasicAttribute("objectclass"); 1963 oc.add("groupofurls"); 1964 BasicAttributes attrs = new BasicAttributes(); 1965 attrs.put(oc); 1966 attrs.put("memberURL", "ldap:///" + getAdministratorContainerDN() + "??one?(objectclass=*)"); 1967 attrs.put("description", "Group of identities which have full access."); 1968 createEntry(getAdministratorContainerDN(), attrs); 1969 } 1970 1971 /** 1972 * Creates the top container entry. 1973 * 1974 * @throws ADSContextException 1975 * if the entry could not be created. 1976 */ 1977 private void createTopContainerEntry() throws ADSContextException 1978 { 1979 Attribute oc = new BasicAttribute("objectclass"); 1980 oc.add("top"); 1981 oc.add("ds-cfg-branch"); 1982 BasicAttributes attrs = new BasicAttributes(); 1983 attrs.put(oc); 1984 createEntry(getAdministrationSuffixDN(), attrs); 1985 } 1986 1987 /** 1988 * Creates an entry with the provided dn and attributes. 1989 * 1990 * @param dn 1991 * the dn of the entry. 1992 * @param attrs 1993 * the attributes of the entry. 1994 * @throws ADSContextException 1995 * if the entry could not be created. 1996 */ 1997 private void createEntry(String dn, Attributes attrs) throws ADSContextException 1998 { 1999 try 2000 { 2001 DirContext ctx = getDirContext().createSubcontext(nameFromDN(dn), attrs); 2002 ctx.close(); 2003 } 2004 catch (NamingException x) 2005 { 2006 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 2007 } 2008 } 2009 2010 /** 2011 * Creates the Administration Suffix. 2012 * 2013 * @param backendName 2014 * the backend name to be used for the Administration Suffix. If this 2015 * value is null the default backendName for the Administration 2016 * Suffix will be used. 2017 * @throws ADSContextException 2018 * if something goes wrong. 2019 */ 2020 private void createAdministrationSuffix(String backendName) throws ADSContextException 2021 { 2022 ADSContextHelper helper = new ADSContextHelper(); 2023 String ben = backendName; 2024 if (backendName == null) 2025 { 2026 ben = getDefaultBackendName(); 2027 } 2028 helper.createAdministrationSuffix(connectionWrapper, ben); 2029 } 2030 2031 /** 2032 * Returns the default backend name of the administration data. 2033 * 2034 * @return the default backend name of the administration data. 2035 */ 2036 public static String getDefaultBackendName() 2037 { 2038 return "adminRoot"; 2039 } 2040 2041 /** 2042 * Returns the LDIF file of the administration data. 2043 * 2044 * @return the LDIF file of the administration data. 2045 */ 2046 static String getAdminLDIFFile() 2047 { 2048 return "config" + File.separator + "admin-backend.ldif"; 2049 } 2050 2051 /** CryptoManager related types, fields, and methods. */ 2052 2053 /** 2054 * Returns the parent entry of the server key entries in ADS. 2055 * 2056 * @return the parent entry of the server key entries in ADS. 2057 */ 2058 static String getInstanceKeysContainerDN() 2059 { 2060 return "cn=instance keys," + getAdministrationSuffixDN(); 2061 } 2062 2063 /** 2064 * Returns the parent entry of the secret key entries in ADS. 2065 * 2066 * @return the parent entry of the secret key entries in ADS. 2067 */ 2068 private static String getSecretKeysContainerDN() 2069 { 2070 return "cn=secret keys," + getAdministrationSuffixDN(); 2071 } 2072 2073 /** 2074 * Tells whether the provided server is registered in the registry. 2075 * 2076 * @param server 2077 * the server. 2078 * @param registry 2079 * the registry. 2080 * @return <CODE>true</CODE> if the server is registered in the registry and 2081 * <CODE>false</CODE> otherwise. 2082 */ 2083 public static boolean isRegistered(ServerDescriptor server, Set<Map<ADSContext.ServerProperty, Object>> registry) 2084 { 2085 for (Map<ADSContext.ServerProperty, Object> s : registry) 2086 { 2087 ServerDescriptor servInRegistry = ServerDescriptor.createStandalone(s); 2088 if (servInRegistry.getId().equals(server.getId())) 2089 { 2090 return true; 2091 } 2092 } 2093 return false; 2094 } 2095 2096 /** 2097 * Register instance key-pair public-key certificate provided in 2098 * serverProperties: generate a key-id attribute if one is not provided (as 2099 * expected); add an instance key public-key certificate entry for the key 2100 * certificate; and associate the certificate entry with the server entry via 2101 * the key ID attribute. 2102 * 2103 * @param serverProperties 2104 * Properties of the server being registered to which the instance 2105 * key entry belongs. 2106 * @param serverEntryDn 2107 * The server's ADS entry DN. 2108 * @throws ADSContextException 2109 * In case there is a problem registering the instance public key certificate ID 2110 */ 2111 private void registerInstanceKeyCertificate(Map<ServerProperty, Object> serverProperties, LdapName serverEntryDn) 2112 throws ADSContextException 2113 { 2114 ADSContextHelper helper = new ADSContextHelper(); 2115 helper.registerInstanceKeyCertificate(dirContext, serverProperties, serverEntryDn); 2116 } 2117 2118 /** 2119 * Return the set of valid (i.e., not tagged as compromised) instance key-pair 2120 * public-key certificate entries in ADS. NOTE: calling this method assumes 2121 * that all the jar files are present in the classpath. 2122 * 2123 * @return The set of valid (i.e., not tagged as compromised) instance 2124 * key-pair public-key certificate entries in ADS represented as a Map 2125 * from ds-cfg-key-id value to ds-cfg-public-key-certificate;binary 2126 * value. Note that the collection might be empty. 2127 * @throws ADSContextException 2128 * in case of problems with the entry search. 2129 * @see org.opends.server.crypto.CryptoManagerImpl#getTrustedCertificates 2130 */ 2131 public Map<String, byte[]> getTrustedCertificates() throws ADSContextException 2132 { 2133 final Map<String, byte[]> certificateMap = new HashMap<>(); 2134 final String baseDNStr = getInstanceKeysContainerDN(); 2135 try 2136 { 2137 ADSContextHelper helper = new ADSContextHelper(); 2138 final LdapName baseDN = new LdapName(baseDNStr); 2139 final String FILTER_OC_INSTANCE_KEY = "(objectclass=" + helper.getOcCryptoInstanceKey() + ")"; 2140 final String FILTER_NOT_COMPROMISED = "(!(" + helper.getAttrCryptoKeyCompromisedTime() + "=*))"; 2141 final String searchFilter = "(&" + FILTER_OC_INSTANCE_KEY + FILTER_NOT_COMPROMISED + ")"; 2142 final SearchControls searchControls = new SearchControls(); 2143 searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE); 2144 final String attrIDs[] = 2145 { ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(), 2146 ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary" }; 2147 searchControls.setReturningAttributes(attrIDs); 2148 NamingEnumeration<SearchResult> keyEntries = dirContext.search(baseDN, searchFilter, searchControls); 2149 try 2150 { 2151 while (keyEntries.hasMore()) 2152 { 2153 final SearchResult entry = keyEntries.next(); 2154 final Attributes attrs = entry.getAttributes(); 2155 final Attribute keyIDAttr = attrs.get(attrIDs[0]); 2156 final Attribute keyCertAttr = attrs.get(attrIDs[1]); 2157 if (null == keyIDAttr || null == keyCertAttr) 2158 { 2159 continue;// schema viol. 2160 } 2161 certificateMap.put((String) keyIDAttr.get(), (byte[]) keyCertAttr.get()); 2162 } 2163 } 2164 finally 2165 { 2166 try 2167 { 2168 keyEntries.close(); 2169 } 2170 catch (Exception ex) 2171 { 2172 logger.warn(LocalizableMessage.raw("Unexpected error closing enumeration on ADS key pairs", ex)); 2173 } 2174 } 2175 } 2176 catch (NamingException x) 2177 { 2178 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, x); 2179 } 2180 return certificateMap; 2181 } 2182 2183 /** 2184 * Merge the contents of this ADSContext with the contents of the provided 2185 * ADSContext. Note that only the contents of this ADSContext will be updated. 2186 * 2187 * @param adsCtx 2188 * the other ADSContext to merge the contents with. 2189 * @throws ADSContextException 2190 * if there was an error during the merge. 2191 */ 2192 public void mergeWithRegistry(ADSContext adsCtx) throws ADSContextException 2193 { 2194 try 2195 { 2196 mergeAdministrators(adsCtx); 2197 mergeServerGroups(adsCtx); 2198 mergeServers(adsCtx); 2199 } 2200 catch (ADSContextException adce) 2201 { 2202 LocalizableMessage msg = ERR_ADS_MERGE.get(getHostPort(), adsCtx.getHostPort(), adce.getMessageObject()); 2203 throw new ADSContextException(ErrorType.ERROR_MERGING, msg, adce); 2204 } 2205 } 2206 2207 /** 2208 * Merge the administrator contents of this ADSContext with the contents of 2209 * the provided ADSContext. Note that only the contents of this ADSContext 2210 * will be updated. 2211 * 2212 * @param adsCtx 2213 * the other ADSContext to merge the contents with. 2214 * @throws ADSContextException 2215 * if there was an error during the merge. 2216 */ 2217 private void mergeAdministrators(ADSContext adsCtx) throws ADSContextException 2218 { 2219 Set<Map<AdministratorProperty, Object>> admins2 = adsCtx.readAdministratorRegistry(); 2220 SortedSet<String> notDefinedAdmins = new TreeSet<>(); 2221 for (Map<AdministratorProperty, Object> admin2 : admins2) 2222 { 2223 String uid = (String) admin2.get(AdministratorProperty.UID); 2224 if (!isAdministratorAlreadyRegistered(uid)) 2225 { 2226 notDefinedAdmins.add(uid); 2227 } 2228 } 2229 if (!notDefinedAdmins.isEmpty()) 2230 { 2231 LocalizableMessage msg = ERR_ADS_ADMINISTRATOR_MERGE.get( 2232 adsCtx.getHostPort(), getHostPort(), 2233 joinAsString(Constants.LINE_SEPARATOR, notDefinedAdmins), getHostPort()); 2234 throw new ADSContextException(ErrorType.ERROR_MERGING, msg, null); 2235 } 2236 } 2237 2238 /** 2239 * Merge the groups contents of this ADSContext with the contents of the 2240 * provided ADSContext. Note that only the contents of this ADSContext will be 2241 * updated. 2242 * 2243 * @param adsCtx 2244 * the other ADSContext to merge the contents with. 2245 * @throws ADSContextException 2246 * if there was an error during the merge. 2247 */ 2248 private void mergeServerGroups(ADSContext adsCtx) throws ADSContextException 2249 { 2250 Set<Map<ServerGroupProperty, Object>> serverGroups1 = readServerGroupRegistry(); 2251 Set<Map<ServerGroupProperty, Object>> serverGroups2 = adsCtx.readServerGroupRegistry(); 2252 2253 for (Map<ServerGroupProperty, Object> group2 : serverGroups2) 2254 { 2255 Map<ServerGroupProperty, Object> group1 = null; 2256 String uid2 = (String) group2.get(ServerGroupProperty.UID); 2257 for (Map<ServerGroupProperty, Object> gr : serverGroups1) 2258 { 2259 String uid1 = (String) gr.get(ServerGroupProperty.UID); 2260 if (uid1.equalsIgnoreCase(uid2)) 2261 { 2262 group1 = gr; 2263 break; 2264 } 2265 } 2266 2267 if (group1 != null) 2268 { 2269 // Merge the members, keep the description on this ADS. 2270 Set<String> member1List = getServerGroupMemberList(uid2); 2271 if (member1List == null) 2272 { 2273 member1List = new HashSet<>(); 2274 } 2275 Set<String> member2List = adsCtx.getServerGroupMemberList(uid2); 2276 if (member2List != null && !member2List.isEmpty()) 2277 { 2278 member1List.addAll(member2List); 2279 Map<ServerGroupProperty, Object> newProperties = new HashMap<>(); 2280 newProperties.put(ServerGroupProperty.MEMBERS, member1List); 2281 updateServerGroup(uid2, newProperties); 2282 } 2283 } 2284 else 2285 { 2286 createServerGroup(group2); 2287 } 2288 } 2289 } 2290 2291 /** 2292 * Merge the server contents of this ADSContext with the contents of the 2293 * provided ADSContext. Note that only the contents of this ADSContext will be 2294 * updated. 2295 * 2296 * @param adsCtx 2297 * the other ADSContext to merge the contents with. 2298 * @throws ADSContextException 2299 * if there was an error during the merge. 2300 */ 2301 private void mergeServers(ADSContext adsCtx) throws ADSContextException 2302 { 2303 for (Map<ServerProperty, Object> server2 : adsCtx.readServerRegistry()) 2304 { 2305 if (!isServerAlreadyRegistered(server2)) 2306 { 2307 registerServer(server2); 2308 } 2309 } 2310 } 2311 2312 private void handleCloseNamingEnumeration(NamingEnumeration<?> ne) throws ADSContextException 2313 { 2314 if (ne != null) 2315 { 2316 try 2317 { 2318 ne.close(); 2319 } 2320 catch (NamingException ex) 2321 { 2322 throw new ADSContextException(ErrorType.ERROR_UNEXPECTED, ex); 2323 } 2324 } 2325 } 2326}