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