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