001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008-2011 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS. 026 */ 027package org.opends.guitools.controlpanel.util; 028 029import static org.opends.messages.AdminToolMessages.*; 030import static org.opends.server.backends.pluggable.SuffixContainer.*; 031 032import java.net.InetAddress; 033import java.text.DateFormat; 034import java.text.SimpleDateFormat; 035import java.util.ArrayList; 036import java.util.Collection; 037import java.util.Collections; 038import java.util.HashMap; 039import java.util.HashSet; 040import java.util.List; 041import java.util.Map; 042import java.util.Set; 043import java.util.SortedSet; 044import java.util.TimeZone; 045import java.util.TreeSet; 046 047import javax.naming.NamingEnumeration; 048import javax.naming.NamingException; 049import javax.naming.directory.SearchControls; 050import javax.naming.directory.SearchResult; 051import javax.naming.ldap.InitialLdapContext; 052import javax.naming.ldap.LdapName; 053 054import org.forgerock.i18n.LocalizableMessage; 055import org.forgerock.i18n.slf4j.LocalizedLogger; 056import org.forgerock.opendj.config.server.ConfigException; 057import org.opends.admin.ads.util.ConnectionUtils; 058import org.opends.guitools.controlpanel.datamodel.AbstractIndexDescriptor; 059import org.opends.guitools.controlpanel.datamodel.BackendDescriptor; 060import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor; 061import org.opends.guitools.controlpanel.datamodel.ConnectionHandlerDescriptor; 062import org.opends.guitools.controlpanel.datamodel.CustomSearchResult; 063import org.opends.guitools.controlpanel.datamodel.IndexDescriptor; 064import org.opends.guitools.controlpanel.datamodel.IndexTypeDescriptor; 065import org.opends.guitools.controlpanel.datamodel.VLVIndexDescriptor; 066import org.opends.guitools.controlpanel.datamodel.VLVSortOrder; 067import org.opends.guitools.controlpanel.task.OnlineUpdateException; 068import org.opends.server.admin.client.AuthorizationException; 069import org.opends.server.admin.client.CommunicationException; 070import org.opends.server.admin.client.ConcurrentModificationException; 071import org.opends.server.admin.client.ManagementContext; 072import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor; 073import org.opends.server.admin.client.ldap.LDAPManagementContext; 074import org.opends.server.admin.std.client.AdministrationConnectorCfgClient; 075import org.opends.server.admin.std.client.BackendCfgClient; 076import org.opends.server.admin.std.client.BackendIndexCfgClient; 077import org.opends.server.admin.std.client.BackendVLVIndexCfgClient; 078import org.opends.server.admin.std.client.BackupBackendCfgClient; 079import org.opends.server.admin.std.client.ConnectionHandlerCfgClient; 080import org.opends.server.admin.std.client.HTTPConnectionHandlerCfgClient; 081import org.opends.server.admin.std.client.JMXConnectionHandlerCfgClient; 082import org.opends.server.admin.std.client.LDAPConnectionHandlerCfgClient; 083import org.opends.server.admin.std.client.LDIFBackendCfgClient; 084import org.opends.server.admin.std.client.LDIFConnectionHandlerCfgClient; 085import org.opends.server.admin.std.client.LocalDBBackendCfgClient; 086import org.opends.server.admin.std.client.LocalDBIndexCfgClient; 087import org.opends.server.admin.std.client.LocalDBVLVIndexCfgClient; 088import org.opends.server.admin.std.client.MemoryBackendCfgClient; 089import org.opends.server.admin.std.client.MonitorBackendCfgClient; 090import org.opends.server.admin.std.client.PluggableBackendCfgClient; 091import org.opends.server.admin.std.client.ReplicationDomainCfgClient; 092import org.opends.server.admin.std.client.ReplicationServerCfgClient; 093import org.opends.server.admin.std.client.ReplicationSynchronizationProviderCfgClient; 094import org.opends.server.admin.std.client.RootCfgClient; 095import org.opends.server.admin.std.client.RootDNCfgClient; 096import org.opends.server.admin.std.client.RootDNUserCfgClient; 097import org.opends.server.admin.std.client.SNMPConnectionHandlerCfgClient; 098import org.opends.server.admin.std.client.TaskBackendCfgClient; 099import org.opends.server.backends.jeb.RemoveOnceLocalDBBackendIsPluggable; 100import org.opends.server.config.ConfigConstants; 101import org.opends.server.core.DirectoryServer; 102import org.opends.server.tools.tasks.TaskEntry; 103import org.opends.server.types.DN; 104import org.opends.server.types.OpenDsException; 105import org.opends.server.util.ServerConstants; 106 107/** 108 * A class that reads the configuration and monitoring information using a 109 * DirContext through LDAP. 110 */ 111public class ConfigFromDirContext extends ConfigReader 112{ 113 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 114 115 private static final String DATABASE_ENVIRONMENT_SUFFIX = " Database Environment"; 116 private static final String SYNC_PROVIDER_NAME = "Multimaster Synchronization"; 117 118 private CustomSearchResult rootMonitor; 119 private CustomSearchResult jvmMemoryUsage; 120 private CustomSearchResult systemInformation; 121 private CustomSearchResult entryCaches; 122 private CustomSearchResult workQueue; 123 private CustomSearchResult versionMonitor; 124 125 private boolean isLocal = true; 126 127 private final Map<String, CustomSearchResult> hmConnectionHandlersMonitor = new HashMap<>(); 128 129 /** The monitor root entry DN. */ 130 protected DN monitorDN = DN.rootDN(); 131 /** The JVM memory usage monitoring entry DN. */ 132 protected DN jvmMemoryUsageDN = DN.rootDN(); 133 /** The system information monitoring entry DN. */ 134 protected DN systemInformationDN = DN.rootDN(); 135 /**The entry cache monitoring entry DN. */ 136 protected DN entryCachesDN = DN.rootDN(); 137 /** The work queue monitoring entry DN. */ 138 protected DN workQueueDN = DN.rootDN(); 139 /** The version monitoring entry DN. */ 140 protected DN versionDN = DN.rootDN(); 141 142 { 143 try 144 { 145 monitorDN = DN.valueOf("cn=monitor"); 146 jvmMemoryUsageDN = DN.valueOf("cn=JVM Memory Usage,cn=monitor"); 147 systemInformationDN = DN.valueOf("cn=System Information,cn=monitor"); 148 entryCachesDN = DN.valueOf("cn=Entry Caches,cn=monitor"); 149 workQueueDN = DN.valueOf("cn=Work Queue,cn=monitor"); 150 versionDN = DN.valueOf("cn=Version,cn=monitor"); 151 } 152 catch (Throwable t) 153 { 154 throw new RuntimeException("Could not decode DNs: "+t, t); 155 } 156 } 157 158 /** The date formatter to be used to parse GMT dates. */ 159 public static final SimpleDateFormat utcParser = new SimpleDateFormat(ServerConstants.DATE_FORMAT_GMT_TIME); 160 { 161 utcParser.setTimeZone(TimeZone.getTimeZone("UTC")); 162 } 163 164 /** The date formatter to be used to format dates. */ 165 public static final DateFormat formatter = DateFormat.getDateTimeInstance(); 166 167 /** 168 * Returns the monitoring entry for the entry caches. 169 * 170 * @return the monitoring entry for the entry caches. 171 */ 172 public CustomSearchResult getEntryCaches() 173 { 174 return entryCaches; 175 } 176 177 /** 178 * Returns the monitoring entry for the JVM memory usage. 179 * 180 * @return the monitoring entry for the JVM memory usage. 181 */ 182 public CustomSearchResult getJvmMemoryUsage() 183 { 184 return jvmMemoryUsage; 185 } 186 187 /** 188 * Returns the root entry of the monitoring tree. 189 * 190 * @return the root entry of the monitoring tree. 191 */ 192 public CustomSearchResult getRootMonitor() 193 { 194 return rootMonitor; 195 } 196 197 /** 198 * Returns the version entry of the monitoring tree. 199 * 200 * @return the version entry of the monitoring tree. 201 */ 202 public CustomSearchResult getVersionMonitor() 203 { 204 return versionMonitor; 205 } 206 207 /** 208 * Returns the monitoring entry for the system information. 209 * 210 * @return the monitoring entry for the system information. 211 */ 212 public CustomSearchResult getSystemInformation() 213 { 214 return systemInformation; 215 } 216 217 /** 218 * Returns the monitoring entry for the work queue. 219 * 220 * @return the monitoring entry for the work queue. 221 */ 222 public CustomSearchResult getWorkQueue() 223 { 224 return workQueue; 225 } 226 227 /** 228 * Sets whether this server represents the local instance or a remote server. 229 * 230 * @param isLocal 231 * whether this server represents the local instance or a remote 232 * server (in another machine or in another installation on the same 233 * machine). 234 */ 235 public void setIsLocal(boolean isLocal) 236 { 237 this.isLocal = isLocal; 238 } 239 240 /** 241 * Returns <CODE>true</CODE> if we are trying to manage the local host and 242 * <CODE>false</CODE> otherwise. 243 * 244 * @return <CODE>true</CODE> if we are trying to manage the local host and 245 * <CODE>false</CODE> otherwise. 246 */ 247 public boolean isLocal() 248 { 249 return isLocal; 250 } 251 252 /** 253 * Reads configuration and monitoring information using the provided 254 * connection. 255 * 256 * @param context 257 * the connection to be used to read the information. 258 */ 259 public void readConfiguration(final InitialLdapContext context) 260 { 261 final List<OpenDsException> errors = new ArrayList<>(); 262 final Set<ConnectionHandlerDescriptor> connectionHandlers = new HashSet<>(); 263 final Set<BackendDescriptor> backendDescriptors = new HashSet<>(); 264 final Set<DN> as = new HashSet<>(); 265 final Set<TaskEntry> tasks = new HashSet<>(); 266 267 rootMonitor = null; 268 jvmMemoryUsage = null; 269 systemInformation = null; 270 entryCaches = null; 271 workQueue = null; 272 versionMonitor = null; 273 274 hmConnectionHandlersMonitor.clear(); 275 276 readSchemaIfNeeded(context, errors); 277 278 try 279 { 280 readConfig(context, connectionHandlers, backendDescriptors, as, errors); 281 } 282 catch (final Throwable t) 283 { 284 errors.add(new OnlineUpdateException(ERR_READING_CONFIG_LDAP.get(t), t)); 285 } 286 287 for (OpenDsException oe : errors) 288 { 289 logger.warn(LocalizableMessage.raw("Error reading configuration: " + oe, oe)); 290 } 291 administrativeUsers = Collections.unmodifiableSet(as); 292 listeners = Collections.unmodifiableSet(connectionHandlers); 293 backends = Collections.unmodifiableSet(backendDescriptors); 294 try 295 { 296 updateMonitorInformation(context, errors); 297 } 298 catch (Throwable t) 299 { 300 logger.warn(LocalizableMessage.raw("Error reading monitoring: " + t, t)); 301 errors.add(new OnlineUpdateException(ERR_READING_CONFIG_LDAP.get(t), t)); 302 } 303 304 try 305 { 306 updateTaskInformation(context, errors, tasks); 307 } 308 catch (Throwable t) 309 { 310 logger.warn(LocalizableMessage.raw("Error reading task information: " + t, t)); 311 errors.add(new OnlineUpdateException(ERR_READING_CONFIG_LDAP.get(t), t)); 312 } 313 314 taskEntries = Collections.unmodifiableSet(tasks); 315 for (ConnectionHandlerDescriptor ch : getConnectionHandlers()) 316 { 317 ch.setMonitoringEntries(getMonitoringEntries(ch)); 318 } 319 320 if (adminConnector != null) 321 { 322 adminConnector.setMonitoringEntries(getMonitoringEntries(adminConnector)); 323 } 324 exceptions = Collections.unmodifiableList(errors); 325 } 326 327 private void readSchemaIfNeeded(final InitialLdapContext context, final List<OpenDsException> errors) 328 { 329 if (mustReadSchema()) 330 { 331 try 332 { 333 readSchema(context); 334 if (getSchema() != null) 335 { 336 // Update the schema: so that when we call the server code the 337 // latest schema read on the server we are managing is used. 338 DirectoryServer.setSchema(getSchema()); 339 } 340 } 341 catch (OpenDsException oe) 342 { 343 errors.add(oe); 344 } 345 } 346 } 347 348 private void readConfig(final InitialLdapContext context, 349 final Set<ConnectionHandlerDescriptor> connectionHandlers, final Set<BackendDescriptor> backendDescriptors, 350 final Set<DN> alternateBindDNs, final List<OpenDsException> errors) throws Exception 351 { 352 // Get the Directory Server configuration handler and use it. 353 ManagementContext mCtx = LDAPManagementContext.createFromContext(JNDIDirContextAdaptor.adapt(context)); 354 final RootCfgClient root = mCtx.getRootConfiguration(); 355 356 readAdminConnector(root, errors); 357 readConnectionHandlers(connectionHandlers, root, errors); 358 isSchemaEnabled = root.getGlobalConfiguration().isCheckSchema(); 359 360 readBackendConfiguration(backendDescriptors, root, errors); 361 362 boolean isReplicationSecure = readIfReplicationIsSecure(root, errors); 363 364 final ReplicationSynchronizationProviderCfgClient sync = readSyncProviderIfExists(root); 365 if (sync != null) 366 { 367 readReplicationConfig(connectionHandlers, backendDescriptors, sync, isReplicationSecure, errors); 368 } 369 370 readAlternateBindDNs(alternateBindDNs, root, errors); 371 } 372 373 private void readAdminConnector(final RootCfgClient root, final List<OpenDsException> errors) 374 { 375 try 376 { 377 AdministrationConnectorCfgClient adminConnector = root.getAdministrationConnector(); 378 this.adminConnector = getConnectionHandler(adminConnector); 379 } 380 catch (OpenDsException oe) 381 { 382 errors.add(oe); 383 } 384 } 385 386 private void readConnectionHandlers(final Set<ConnectionHandlerDescriptor> connectionHandlers, 387 RootCfgClient root, final List<OpenDsException> errors) throws ConcurrentModificationException, 388 AuthorizationException, CommunicationException 389 { 390 for (String connHandler : root.listConnectionHandlers()) 391 { 392 try 393 { 394 ConnectionHandlerCfgClient connectionHandler = root.getConnectionHandler(connHandler); 395 connectionHandlers.add(getConnectionHandler(connectionHandler, connHandler)); 396 } 397 catch (OpenDsException oe) 398 { 399 errors.add(oe); 400 } 401 } 402 } 403 404 private void readBackendConfiguration(final Set<BackendDescriptor> backendDescriptors, 405 final RootCfgClient root, final List<OpenDsException> errors) throws Exception 406 { 407 for (final String backendName : root.listBackends()) 408 { 409 try 410 { 411 BackendCfgClient backend = root.getBackend(backendName); 412 Set<BaseDNDescriptor> baseDNs = new HashSet<>(); 413 for (DN dn : backend.getBaseDN()) 414 { 415 BaseDNDescriptor baseDN = new BaseDNDescriptor(BaseDNDescriptor.Type.NOT_REPLICATED, dn, null, -1, -1, -1); 416 baseDNs.add(baseDN); 417 } 418 Set<IndexDescriptor> indexes = new HashSet<>(); 419 Set<VLVIndexDescriptor> vlvIndexes = new HashSet<>(); 420 BackendDescriptor.Type type; 421 if (backend instanceof LocalDBBackendCfgClient) 422 { 423 type = BackendDescriptor.Type.LOCAL_DB; 424 refreshLocalDBBackendConfig(indexes, vlvIndexes, backend, errors); 425 } 426 else if (backend instanceof PluggableBackendCfgClient) 427 { 428 type = BackendDescriptor.Type.PLUGGABLE; 429 refreshBackendConfig(indexes, vlvIndexes, backend, errors); 430 } 431 else if (backend instanceof LDIFBackendCfgClient) 432 { 433 type = BackendDescriptor.Type.LDIF; 434 } 435 else if (backend instanceof MemoryBackendCfgClient) 436 { 437 type = BackendDescriptor.Type.MEMORY; 438 } 439 else if (backend instanceof BackupBackendCfgClient) 440 { 441 type = BackendDescriptor.Type.BACKUP; 442 } 443 else if (backend instanceof MonitorBackendCfgClient) 444 { 445 type = BackendDescriptor.Type.MONITOR; 446 } 447 else if (backend instanceof TaskBackendCfgClient) 448 { 449 type = BackendDescriptor.Type.TASK; 450 } 451 else 452 { 453 type = BackendDescriptor.Type.OTHER; 454 } 455 456 BackendDescriptor desc = new BackendDescriptor( 457 backend.getBackendId(), baseDNs, indexes, vlvIndexes, -1, backend.isEnabled(), type); 458 for (AbstractIndexDescriptor index: indexes) 459 { 460 index.setBackend(desc); 461 } 462 for (AbstractIndexDescriptor index: vlvIndexes) 463 { 464 index.setBackend(desc); 465 } 466 for (BaseDNDescriptor baseDN : baseDNs) 467 { 468 baseDN.setBackend(desc); 469 } 470 backendDescriptors.add(desc); 471 } 472 catch (OpenDsException oe) 473 { 474 errors.add(oe); 475 } 476 } 477 } 478 479 private void refreshBackendConfig(final Set<IndexDescriptor> indexes, 480 final Set<VLVIndexDescriptor> vlvIndexes, final BackendCfgClient backend, final List<OpenDsException> errors) 481 { 482 final PluggableBackendCfgClient db = (PluggableBackendCfgClient) backend; 483 readBackendIndexes(indexes, errors, db); 484 readBackendVLVIndexes(vlvIndexes, errors, db); 485 } 486 487 private void readBackendIndexes(final Set<IndexDescriptor> indexes, final List<OpenDsException> errors, 488 final PluggableBackendCfgClient db) 489 { 490 indexes.add(new IndexDescriptor(DN2ID_INDEX_NAME)); 491 indexes.add(new IndexDescriptor(ID2CHILDREN_COUNT_NAME)); 492 try 493 { 494 for (final String indexName : db.listBackendIndexes()) 495 { 496 final BackendIndexCfgClient index = db.getBackendIndex(indexName); 497 indexes.add(new IndexDescriptor( 498 index.getAttribute().getNameOrOID(), index.getAttribute(), 499 null, IndexTypeDescriptor.fromBackendIndexTypes(index.getIndexType()), index.getIndexEntryLimit())); 500 } 501 } 502 catch (OpenDsException oe) 503 { 504 errors.add(oe); 505 } 506 } 507 508 private void readBackendVLVIndexes(final Set<VLVIndexDescriptor> vlvIndexes, 509 final List<OpenDsException> errors, final PluggableBackendCfgClient db) 510 { 511 try 512 { 513 for (final String vlvIndexName : db.listBackendVLVIndexes()) 514 { 515 final BackendVLVIndexCfgClient index = db.getBackendVLVIndex(vlvIndexName); 516 final List<VLVSortOrder> sortOrder = getVLVSortOrder(index.getSortOrder()); 517 vlvIndexes.add(new VLVIndexDescriptor( 518 index.getName(), null, index.getBaseDN(), VLVIndexDescriptor.toSearchScope(index.getScope()), 519 index.getFilter(), sortOrder)); 520 } 521 } 522 catch (OpenDsException oe) 523 { 524 errors.add(oe); 525 } 526 } 527 528 @RemoveOnceLocalDBBackendIsPluggable 529 private void refreshLocalDBBackendConfig(final Set<IndexDescriptor> indexes, 530 final Set<VLVIndexDescriptor> vlvIndexes, final BackendCfgClient backend, final List<OpenDsException> errors) 531 { 532 LocalDBBackendCfgClient localDBBackend = (LocalDBBackendCfgClient)backend; 533 try 534 { 535 for (String indexName : localDBBackend.listLocalDBIndexes()) 536 { 537 LocalDBIndexCfgClient index = localDBBackend.getLocalDBIndex(indexName); 538 indexes.add(new IndexDescriptor( 539 index.getAttribute().getNameOrOID(), index.getAttribute(), 540 null, IndexTypeDescriptor.fromLocalDBIndexTypes(index.getIndexType()), index.getIndexEntryLimit())); 541 } 542 } 543 catch (OpenDsException oe) 544 { 545 errors.add(oe); 546 } 547 548 indexes.add(new IndexDescriptor(DN2ID_INDEX_NAME)); 549 if (localDBBackend.isSubordinateIndexesEnabled()) 550 { 551 indexes.add(new IndexDescriptor(ID2CHILDREN_INDEX_NAME)); 552 indexes.add(new IndexDescriptor(ID2SUBTREE_INDEX_NAME)); 553 } 554 555 try 556 { 557 for (String vlvIndexName : localDBBackend.listLocalDBVLVIndexes()) 558 { 559 LocalDBVLVIndexCfgClient index = localDBBackend.getLocalDBVLVIndex(vlvIndexName); 560 String s = index.getSortOrder(); 561 List<VLVSortOrder> sortOrder = getVLVSortOrder(s); 562 vlvIndexes.add(new VLVIndexDescriptor( 563 index.getName(), null, index.getBaseDN(), VLVIndexDescriptor.toSearchScope(index.getScope()), 564 index.getFilter(), sortOrder)); 565 } 566 } 567 catch (OpenDsException oe) 568 { 569 errors.add(oe); 570 } 571 } 572 573 private boolean readIfReplicationIsSecure(final RootCfgClient root, final List<OpenDsException> errors) 574 { 575 try 576 { 577 return root.getCryptoManager().isSSLEncryption(); 578 } 579 catch (OpenDsException oe) 580 { 581 errors.add(oe); 582 return false; 583 } 584 } 585 586 private ReplicationSynchronizationProviderCfgClient readSyncProviderIfExists(final RootCfgClient root) 587 { 588 try 589 { 590 return (ReplicationSynchronizationProviderCfgClient) root.getSynchronizationProvider(SYNC_PROVIDER_NAME); 591 } 592 catch (OpenDsException oe) 593 { 594 return null; 595 } 596 } 597 598 private void readReplicationConfig(final Set<ConnectionHandlerDescriptor> connectionHandlers, 599 final Set<BackendDescriptor> backendDescriptors, final ReplicationSynchronizationProviderCfgClient sync, 600 boolean isReplicationSecure, final List<OpenDsException> errors) 601 { 602 replicationPort = -1; 603 try 604 { 605 if (sync.isEnabled() && sync.hasReplicationServer()) 606 { 607 ReplicationServerCfgClient replicationServer = sync.getReplicationServer(); 608 if (replicationServer != null) 609 { 610 replicationPort = replicationServer.getReplicationPort(); 611 ConnectionHandlerDescriptor.Protocol protocol = 612 isReplicationSecure ? ConnectionHandlerDescriptor.Protocol.REPLICATION_SECURE 613 : ConnectionHandlerDescriptor.Protocol.REPLICATION; 614 Set<CustomSearchResult> emptySet = Collections.emptySet(); 615 ConnectionHandlerDescriptor connHandler = new ConnectionHandlerDescriptor( 616 new HashSet<InetAddress>(), replicationPort, protocol, ConnectionHandlerDescriptor.State.ENABLED, 617 SYNC_PROVIDER_NAME, emptySet); 618 connectionHandlers.add(connHandler); 619 } 620 } 621 622 String[] domains = sync.listReplicationDomains(); 623 if (domains != null) 624 { 625 for (String domain2 : domains) 626 { 627 ReplicationDomainCfgClient domain = sync.getReplicationDomain(domain2); 628 DN dn = domain.getBaseDN(); 629 for (BackendDescriptor backend : backendDescriptors) 630 { 631 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 632 { 633 if (baseDN.getDn().equals(dn)) 634 { 635 baseDN.setType(sync.isEnabled() ? BaseDNDescriptor.Type.REPLICATED 636 : BaseDNDescriptor.Type.DISABLED); 637 baseDN.setReplicaID(domain.getServerId()); 638 } 639 } 640 } 641 } 642 } 643 } 644 catch (OpenDsException oe) 645 { 646 errors.add(oe); 647 } 648 } 649 650 private void readAlternateBindDNs(final Set<DN> alternateBindDNs, final RootCfgClient root, 651 final List<OpenDsException> errors) 652 { 653 try 654 { 655 RootDNCfgClient rootDN = root.getRootDN(); 656 String[] rootUsers = rootDN.listRootDNUsers(); 657 if (rootUsers != null) 658 { 659 for (String rootUser2 : rootUsers) 660 { 661 RootDNUserCfgClient rootUser = rootDN.getRootDNUser(rootUser2); 662 alternateBindDNs.addAll(rootUser.getAlternateBindDN()); 663 } 664 } 665 } 666 catch (OpenDsException oe) 667 { 668 errors.add(oe); 669 } 670 } 671 672 /** 673 * Returns an array of monitoring attributes to be returned in the request. 674 * 675 * @return an array of monitoring attributes to be returned in the request. 676 */ 677 protected String[] getMonitoringAttributes() 678 { 679 return new String[] {"*"}; 680 } 681 682 /** 683 * Reads the schema from the files. 684 * 685 * @param ctx 686 * the connection to be used to load the schema. 687 * @throws OpenDsException 688 * if an error occurs reading the schema. 689 */ 690 private void readSchema(InitialLdapContext ctx) throws OpenDsException 691 { 692 try 693 { 694 if (isLocal) 695 { 696 super.readSchema(); 697 } 698 else 699 { 700 RemoteSchemaLoader loader = new RemoteSchemaLoader(); 701 loader.readSchema(ctx); 702 schema = loader.getSchema(); 703 } 704 } 705 catch (NamingException ne) 706 { 707 throw new OnlineUpdateException(ERR_READING_SCHEMA_LDAP.get(ne), ne); 708 } 709 catch (ConfigException ce) 710 { 711 throw new org.opends.server.config.ConfigException(ce.getMessageObject(), ce); 712 } 713 } 714 715 /** 716 * Takes the provided search result and updates the monitoring information 717 * accordingly. 718 * 719 * @param sr 720 * the search result. 721 * @param searchBaseDN 722 * the base search. 723 * @throws NamingException 724 * if there is an error retrieving the values of the search result. 725 */ 726 protected void handleMonitoringSearchResult(SearchResult sr, 727 String searchBaseDN) 728 throws NamingException 729 { 730 if (javaVersion == null) 731 { 732 javaVersion = ConnectionUtils.getFirstValue(sr, "javaVersion"); 733 } 734 735 if (numberConnections == -1) 736 { 737 String v = ConnectionUtils.getFirstValue(sr, "currentConnections"); 738 if (v != null) 739 { 740 numberConnections = Integer.parseInt(v); 741 } 742 } 743 744 String dn = ConnectionUtils.getFirstValue(sr, "domain-name"); 745 String replicaId = ConnectionUtils.getFirstValue(sr, "server-id"); 746 String missingChanges = ConnectionUtils.getFirstValue(sr, "missing-changes"); 747 748 if (dn != null && replicaId != null && missingChanges != null) 749 { 750 for (BackendDescriptor backend : backends) 751 { 752 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 753 { 754 try 755 { 756 if (baseDN.getDn().equals(DN.valueOf(dn)) && 757 Integer.toString(baseDN.getReplicaID()).equals(replicaId)) 758 { 759 try 760 { 761 baseDN.setAgeOfOldestMissingChange( 762 Long.valueOf(ConnectionUtils.getFirstValue(sr, "approx-older-change-not-synchronized-millis"))); 763 } 764 catch (Throwable t) 765 { 766 } 767 try 768 { 769 baseDN.setMissingChanges(Integer.valueOf(missingChanges)); 770 } 771 catch (Throwable t) 772 { 773 } 774 } 775 } 776 catch (Throwable t) 777 { 778 } 779 } 780 } 781 } 782 else 783 { 784 CustomSearchResult csr = new CustomSearchResult(sr, searchBaseDN); 785 String backendID = ConnectionUtils.getFirstValue(sr, "ds-backend-id"); 786 String entryCount = ConnectionUtils.getFirstValue(sr, "ds-backend-entry-count"); 787 Set<String> baseDnEntries = ConnectionUtils.getValues(sr, "ds-base-dn-entry-count"); 788 if (backendID != null && (entryCount != null || baseDnEntries != null)) 789 { 790 for (BackendDescriptor backend : backends) 791 { 792 if (backend.getBackendID().equalsIgnoreCase(backendID)) 793 { 794 if (entryCount != null) 795 { 796 backend.setEntries(Integer.parseInt(entryCount)); 797 } 798 if (baseDnEntries != null) 799 { 800 for (String s : baseDnEntries) 801 { 802 int index = s.indexOf(" "); 803 if (index != -1) 804 { 805 for (BaseDNDescriptor baseDN : backend.getBaseDns()) 806 { 807 dn = s.substring(index +1); 808 809 if (Utilities.areDnsEqual(dn, 810 baseDN.getDn().toString())) 811 { 812 try 813 { 814 baseDN.setEntries( 815 Integer.parseInt(s.substring(0, index))); 816 } 817 catch (Throwable t) 818 { 819 /* Ignore */ 820 } 821 break; 822 } 823 } 824 } 825 } 826 } 827 } 828 } 829 } 830 else 831 { 832 // Check if it is the DB monitor entry 833 String cn = ConnectionUtils.getFirstValue(sr, "cn"); 834 if (cn != null && cn.endsWith(DATABASE_ENVIRONMENT_SUFFIX)) 835 { 836 String monitorBackendID = cn.substring(0, cn.length() - DATABASE_ENVIRONMENT_SUFFIX.length()); 837 for (BackendDescriptor backend : backends) 838 { 839 if (backend.getBackendID().equalsIgnoreCase(monitorBackendID)) 840 { 841 backend.setMonitoringEntry(csr); 842 } 843 } 844 } 845 } 846 try 847 { 848 if (rootMonitor == null && isRootMonitor(csr)) 849 { 850 rootMonitor = csr; 851 } 852 else if (entryCaches == null && isEntryCaches(csr)) 853 { 854 entryCaches = csr; 855 } 856 else if (workQueue == null && isWorkQueue(csr)) 857 { 858 workQueue = csr; 859 } 860 else if (jvmMemoryUsage == null && isJvmMemoryUsage(csr)) 861 { 862 jvmMemoryUsage = csr; 863 } 864 else if (systemInformation == null && isSystemInformation(csr)) 865 { 866 systemInformation = csr; 867 } 868 else if (versionMonitor == null && isVersionMonitor(csr)) 869 { 870 versionMonitor = csr; 871 } 872 else if (isConnectionHandler(csr)) 873 { 874 String statistics = " Statistics"; 875 String cn = ConnectionUtils.getFirstValue(sr, "cn"); 876 if (cn.endsWith(statistics)) 877 { 878 // Assume it is a connection handler 879 String name = cn.substring(0, cn.length() - statistics.length()); 880 hmConnectionHandlersMonitor.put(getKey(name), csr); 881 } 882 } 883 } 884 catch (OpenDsException ode) 885 { 886 exceptions.add(ode); 887 } 888 } 889 } 890 891 /** 892 * Takes the provided search result and updates the task information 893 * accordingly. 894 * 895 * @param sr 896 * the search result. 897 * @param searchBaseDN 898 * the base search. 899 * @param taskEntries 900 * the collection of TaskEntries to be updated. 901 * @param ex 902 * the list of exceptions to be updated if an error occurs. 903 * @throws NamingException 904 * if there is an error retrieving the values of the search result. 905 */ 906 private void handleTaskSearchResult(SearchResult sr, String searchBaseDN, Collection<TaskEntry> taskEntries, 907 List<OpenDsException> ex) throws NamingException 908 { 909 CustomSearchResult csr = new CustomSearchResult(sr, searchBaseDN); 910 try 911 { 912 if (isTaskEntry(csr)) 913 { 914 taskEntries.add(new TaskEntry(csr.getEntry())); 915 } 916 } 917 catch (OpenDsException ode) 918 { 919 ex.add(ode); 920 } 921 } 922 923 private void updateMonitorInformation(InitialLdapContext ctx, 924 List<OpenDsException> ex) 925 { 926 // Read monitoring information: since it is computed, it is faster 927 // to get everything in just one request. 928 SearchControls ctls = new SearchControls(); 929 ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); 930 ctls.setReturningAttributes(getMonitoringAttributes()); 931 String filter = "(objectclass=*)"; 932 933 try 934 { 935 LdapName jndiName = new LdapName("cn=monitor"); 936 NamingEnumeration<SearchResult> monitorEntries = ctx.search(jndiName, filter, ctls); 937 javaVersion = null; 938 numberConnections = -1; 939 940 try 941 { 942 while (monitorEntries.hasMore()) 943 { 944 SearchResult sr = monitorEntries.next(); 945 handleMonitoringSearchResult(sr, "cn=monitor"); 946 } 947 } 948 finally 949 { 950 monitorEntries.close(); 951 } 952 } 953 catch (NamingException ne) 954 { 955 ex.add(new OnlineUpdateException(ERR_READING_CONFIG_LDAP.get(ne.getMessage()), ne)); 956 } 957 } 958 959 /** 960 * Updates the provided list of TaskEntry with the task entries found in a 961 * server. 962 * 963 * @param ctx 964 * the connection to the server. 965 * @param ex 966 * the list of exceptions encountered while retrieving the task 967 * entries. 968 * @param ts 969 * the list of task entries to be updated. 970 */ 971 public void updateTaskInformation(InitialLdapContext ctx, List<OpenDsException> ex, Collection<TaskEntry> ts) 972 { 973 // Read monitoring information: since it is computed, it is faster 974 // to get everything in just one request. 975 SearchControls ctls = new SearchControls(); 976 ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); 977 ctls.setReturningAttributes(getMonitoringAttributes()); 978 String filter = "(objectclass=ds-task)"; 979 980 try 981 { 982 LdapName jndiName = new LdapName(ConfigConstants.DN_TASK_ROOT); 983 NamingEnumeration<SearchResult> taskEntries = ctx.search(jndiName, filter, ctls); 984 try 985 { 986 while (taskEntries.hasMore()) 987 { 988 SearchResult sr = taskEntries.next(); 989 handleTaskSearchResult(sr, ConfigConstants.DN_TASK_ROOT, ts, ex); 990 } 991 } 992 finally 993 { 994 taskEntries.close(); 995 } 996 } 997 catch (NamingException ne) 998 { 999 ex.add(new OnlineUpdateException(ERR_READING_CONFIG_LDAP.get(ne.getMessage()), ne)); 1000 } 1001 } 1002 1003 private ConnectionHandlerDescriptor getConnectionHandler(ConnectionHandlerCfgClient connHandler, String name) 1004 throws OpenDsException 1005 { 1006 SortedSet<InetAddress> addresses = new TreeSet<>(getInetAddressComparator()); 1007 ConnectionHandlerDescriptor.State state = connHandler.isEnabled() ? ConnectionHandlerDescriptor.State.ENABLED 1008 : ConnectionHandlerDescriptor.State.DISABLED; 1009 1010 ConnectionHandlerDescriptor.Protocol protocol; 1011 int port; 1012 if (connHandler instanceof LDAPConnectionHandlerCfgClient) 1013 { 1014 LDAPConnectionHandlerCfgClient ldap = (LDAPConnectionHandlerCfgClient)connHandler; 1015 if (ldap.isUseSSL()) 1016 { 1017 protocol = ConnectionHandlerDescriptor.Protocol.LDAPS; 1018 } 1019 else if (ldap.isAllowStartTLS()) 1020 { 1021 protocol = ConnectionHandlerDescriptor.Protocol.LDAP_STARTTLS; 1022 } 1023 else 1024 { 1025 protocol = ConnectionHandlerDescriptor.Protocol.LDAP; 1026 } 1027 addAll(addresses, ldap.getListenAddress()); 1028 port = ldap.getListenPort(); 1029 } 1030 else if (connHandler instanceof HTTPConnectionHandlerCfgClient) 1031 { 1032 HTTPConnectionHandlerCfgClient http = (HTTPConnectionHandlerCfgClient) connHandler; 1033 if (http.isUseSSL()) 1034 { 1035 protocol = ConnectionHandlerDescriptor.Protocol.HTTPS; 1036 } 1037 else 1038 { 1039 protocol = ConnectionHandlerDescriptor.Protocol.HTTP; 1040 } 1041 addAll(addresses, http.getListenAddress()); 1042 port = http.getListenPort(); 1043 } 1044 else if (connHandler instanceof JMXConnectionHandlerCfgClient) 1045 { 1046 JMXConnectionHandlerCfgClient jmx = (JMXConnectionHandlerCfgClient)connHandler; 1047 if (jmx.isUseSSL()) 1048 { 1049 protocol = ConnectionHandlerDescriptor.Protocol.JMXS; 1050 } 1051 else 1052 { 1053 protocol = ConnectionHandlerDescriptor.Protocol.JMX; 1054 } 1055 addresses.add(jmx.getListenAddress()); 1056 port = jmx.getListenPort(); 1057 } 1058 else if (connHandler instanceof LDIFConnectionHandlerCfgClient) 1059 { 1060 protocol = ConnectionHandlerDescriptor.Protocol.LDIF; 1061 port = -1; 1062 } 1063 else if (connHandler instanceof SNMPConnectionHandlerCfgClient) 1064 { 1065 protocol = ConnectionHandlerDescriptor.Protocol.SNMP; 1066 SNMPConnectionHandlerCfgClient snmp = (SNMPConnectionHandlerCfgClient)connHandler; 1067 addAll(addresses, snmp.getListenAddress()); 1068 port = snmp.getListenPort(); 1069 } 1070 else 1071 { 1072 protocol = ConnectionHandlerDescriptor.Protocol.OTHER; 1073 port = -1; 1074 } 1075 Set<CustomSearchResult> emptySet = Collections.emptySet(); 1076 return new ConnectionHandlerDescriptor(addresses, port, protocol, state, name, emptySet); 1077 } 1078 1079 private <T> void addAll(Collection<T> target, Collection<T> source) 1080 { 1081 if (source != null) 1082 { 1083 target.addAll(source); 1084 } 1085 } 1086 1087 private ConnectionHandlerDescriptor getConnectionHandler(AdministrationConnectorCfgClient adminConnector) 1088 throws OpenDsException 1089 { 1090 SortedSet<InetAddress> addresses = new TreeSet<>(getInetAddressComparator()); 1091 1092 ConnectionHandlerDescriptor.Protocol protocol = ConnectionHandlerDescriptor.Protocol.ADMINISTRATION_CONNECTOR; 1093 ConnectionHandlerDescriptor.State state = ConnectionHandlerDescriptor.State.ENABLED; 1094 1095 addAll(addresses, adminConnector.getListenAddress()); 1096 int port = adminConnector.getListenPort(); 1097 1098 Set<CustomSearchResult> emptySet = Collections.emptySet(); 1099 return new ConnectionHandlerDescriptor( 1100 addresses, port, protocol, state, INFO_CTRL_PANEL_CONN_HANDLER_ADMINISTRATION.get().toString(), emptySet); 1101 } 1102 1103 private boolean isRootMonitor(CustomSearchResult csr) throws OpenDsException 1104 { 1105 return monitorDN.equals(DN.valueOf(csr.getDN())); 1106 } 1107 1108 private boolean isVersionMonitor(CustomSearchResult csr) throws OpenDsException 1109 { 1110 return versionDN.equals(DN.valueOf(csr.getDN())); 1111 } 1112 1113 private boolean isSystemInformation(CustomSearchResult csr) throws OpenDsException 1114 { 1115 return systemInformationDN.equals(DN.valueOf(csr.getDN())); 1116 } 1117 1118 private boolean isJvmMemoryUsage(CustomSearchResult csr) throws OpenDsException 1119 { 1120 return jvmMemoryUsageDN.equals(DN.valueOf(csr.getDN())); 1121 } 1122 1123 private boolean isWorkQueue(CustomSearchResult csr) throws OpenDsException 1124 { 1125 return workQueueDN.equals(DN.valueOf(csr.getDN())); 1126 } 1127 1128 private boolean isEntryCaches(CustomSearchResult csr) throws OpenDsException 1129 { 1130 return entryCachesDN.equals(DN.valueOf(csr.getDN())); 1131 } 1132 1133 private boolean isConnectionHandler(CustomSearchResult csr) throws OpenDsException 1134 { 1135 DN dn = DN.valueOf(csr.getDN()); 1136 DN parent = dn.parent(); 1137 if (parent != null && parent.equals(monitorDN)) 1138 { 1139 List<?> vs = csr.getAttributeValues("cn"); 1140 if (vs != null && !vs.isEmpty()) 1141 { 1142 String cn = (String) vs.iterator().next(); 1143 String statistics = " Statistics"; 1144 if (cn.endsWith(statistics)) 1145 { 1146 return true; 1147 } 1148 } 1149 } 1150 return false; 1151 } 1152 1153 private static boolean isTaskEntry(CustomSearchResult csr) throws OpenDsException 1154 { 1155 List<Object> vs = csr.getAttributeValues("objectclass"); 1156 if (vs != null && !vs.isEmpty()) 1157 { 1158 for (Object oc : vs) 1159 { 1160 if (oc.toString().equalsIgnoreCase("ds-task")) 1161 { 1162 return true; 1163 } 1164 } 1165 } 1166 return false; 1167 } 1168 1169 /** 1170 * Commodity method to get the string representation to be used in the hash 1171 * maps as key. 1172 * 1173 * @param value 1174 * the value to be transformed into a key for a hash map. 1175 * @return the string representation to be used in the hash maps as key. 1176 */ 1177 private String getKey(String value) 1178 { 1179 return value.toLowerCase(); 1180 } 1181 1182 private Set<CustomSearchResult>getMonitoringEntries(ConnectionHandlerDescriptor ch) 1183 { 1184 Set<CustomSearchResult> monitorEntries = new HashSet<>(); 1185 if (ch.getState() == ConnectionHandlerDescriptor.State.ENABLED) 1186 { 1187 for (String key : hmConnectionHandlersMonitor.keySet()) 1188 { 1189 // The name of the connection handler does not appear necessarily in the 1190 // key (which is based on the DN of the monitoring entry). In general 1191 // the DN contains the String specified in 1192 // LDAPConnectionHandler.DEFAULT_FRIENDLY_NAME, so we have to check that 1193 // this connection handler is the right one. 1194 // See org.opends.server.protocols.ldap.LDAPConnectionHandler to see 1195 // how the DN of the monitoring entry is generated. 1196 if (key.contains(getKey("port " + ch.getPort())) 1197 && hasAllAddresses(ch, key)) 1198 { 1199 monitorEntries.add(hmConnectionHandlersMonitor.get(key)); 1200 } 1201 } 1202 } 1203 1204 return monitorEntries; 1205 } 1206 1207 private boolean hasAllAddresses(ConnectionHandlerDescriptor ch, String key) 1208 { 1209 for (InetAddress a : ch.getAddresses()) 1210 { 1211 if (!key.contains(getKey(a.getHostAddress()))) 1212 { 1213 return false; 1214 } 1215 } 1216 return true; 1217 } 1218}