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-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027package org.opends.guitools.controlpanel.datamodel; 028 029import static org.opends.admin.ads.util.ConnectionUtils.*; 030import static org.opends.guitools.controlpanel.util.Utilities.*; 031import static org.opends.server.tools.ConfigureWindowsService.*; 032 033import static com.forgerock.opendj.cli.Utils.*; 034import static com.forgerock.opendj.util.OperatingSystem.*; 035 036import java.io.File; 037import java.net.InetAddress; 038import java.util.Collection; 039import java.util.Collections; 040import java.util.HashSet; 041import java.util.LinkedHashSet; 042import java.util.Objects; 043import java.util.Set; 044import java.util.SortedSet; 045 046import javax.naming.NamingException; 047import javax.naming.ldap.InitialLdapContext; 048 049import org.forgerock.i18n.LocalizableMessage; 050import org.forgerock.i18n.slf4j.LocalizedLogger; 051import org.forgerock.opendj.config.ConfigurationFramework; 052import org.forgerock.opendj.config.server.ConfigException; 053import org.opends.admin.ads.util.ApplicationTrustManager; 054import org.opends.admin.ads.util.ConnectionUtils; 055import org.opends.guitools.controlpanel.browser.IconPool; 056import org.opends.guitools.controlpanel.browser.LDAPConnectionPool; 057import org.opends.guitools.controlpanel.datamodel.ServerDescriptor.ServerStatus; 058import org.opends.guitools.controlpanel.event.BackendPopulatedEvent; 059import org.opends.guitools.controlpanel.event.BackendPopulatedListener; 060import org.opends.guitools.controlpanel.event.BackupCreatedEvent; 061import org.opends.guitools.controlpanel.event.BackupCreatedListener; 062import org.opends.guitools.controlpanel.event.ConfigChangeListener; 063import org.opends.guitools.controlpanel.event.ConfigurationChangeEvent; 064import org.opends.guitools.controlpanel.event.IndexModifiedEvent; 065import org.opends.guitools.controlpanel.event.IndexModifiedListener; 066import org.opends.guitools.controlpanel.task.Task; 067import org.opends.guitools.controlpanel.task.Task.State; 068import org.opends.guitools.controlpanel.task.Task.Type; 069import org.opends.guitools.controlpanel.util.ConfigFromDirContext; 070import org.opends.guitools.controlpanel.util.ConfigFromFile; 071import org.opends.guitools.controlpanel.util.ConfigReader; 072import org.opends.guitools.controlpanel.util.Utilities; 073import org.opends.quicksetup.util.UIKeyStore; 074import org.opends.quicksetup.util.Utils; 075import org.opends.server.util.StaticUtils; 076 077import com.forgerock.opendj.cli.CliConstants; 078 079/** 080 * This is the classes that is shared among all the different places in the 081 * Control Panel. It contains information about the server status and 082 * configuration and some objects that are shared everywhere. 083 */ 084public class ControlPanelInfo 085{ 086 private long poolingPeriod = 20000; 087 088 private ServerDescriptor serverDesc; 089 private Set<Task> tasks = new HashSet<>(); 090 private InitialLdapContext ctx; 091 private InitialLdapContext userDataCtx; 092 private final LDAPConnectionPool connectionPool = new LDAPConnectionPool(); 093 /** Used by the browsers. */ 094 private final IconPool iconPool = new IconPool(); 095 private Thread poolingThread; 096 private boolean stopPooling; 097 private boolean pooling; 098 private ApplicationTrustManager trustManager; 099 private int connectTimeout = CliConstants.DEFAULT_LDAP_CONNECT_TIMEOUT; 100 private ConnectionProtocolPolicy connectionPolicy = 101 ConnectionProtocolPolicy.USE_MOST_SECURE_AVAILABLE; 102 private String ldapURL; 103 private String startTLSURL; 104 private String ldapsURL; 105 private String adminConnectorURL; 106 private String localAdminConnectorURL; 107 private String lastWorkingBindDN; 108 private String lastWorkingBindPwd; 109 private String lastRemoteHostName; 110 private String lastRemoteAdministrationURL; 111 112 private static boolean mustDeregisterConfig; 113 114 private boolean isLocal = true; 115 116 private Set<AbstractIndexDescriptor> modifiedIndexes = new HashSet<>(); 117 private LinkedHashSet<ConfigChangeListener> configListeners = new LinkedHashSet<>(); 118 private LinkedHashSet<BackupCreatedListener> backupListeners = new LinkedHashSet<>(); 119 private LinkedHashSet<BackendPopulatedListener> backendPopulatedListeners = new LinkedHashSet<>(); 120 private LinkedHashSet<IndexModifiedListener> indexListeners = new LinkedHashSet<>(); 121 122 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 123 124 private static ControlPanelInfo instance; 125 126 /** Default constructor. */ 127 protected ControlPanelInfo() 128 { 129 } 130 131 /** 132 * Returns a singleton for this instance. 133 * @return the control panel info. 134 */ 135 public static ControlPanelInfo getInstance() 136 { 137 if (instance == null) 138 { 139 instance = new ControlPanelInfo(); 140 try 141 { 142 instance.setTrustManager( 143 new ApplicationTrustManager(UIKeyStore.getInstance())); 144 } 145 catch (Throwable t) 146 { 147 logger.warn(LocalizableMessage.raw("Error retrieving UI key store: "+t, t)); 148 instance.setTrustManager(new ApplicationTrustManager(null)); 149 } 150 } 151 return instance; 152 } 153 154 /** 155 * Returns the last ServerDescriptor that has been retrieved. 156 * @return the last ServerDescriptor that has been retrieved. 157 */ 158 public ServerDescriptor getServerDescriptor() 159 { 160 return serverDesc; 161 } 162 163 /** 164 * Returns the list of tasks. 165 * @return the list of tasks. 166 */ 167 public Set<Task> getTasks() 168 { 169 return Collections.unmodifiableSet(tasks); 170 } 171 172 /** 173 * Registers a task. The Control Panel creates a task every time an operation 174 * is made and they are stored here. 175 * @param task the task to be registered. 176 */ 177 public void registerTask(Task task) 178 { 179 tasks.add(task); 180 } 181 182 /** 183 * Unregisters a task. 184 * @param task the task to be unregistered. 185 */ 186 public void unregisterTask(Task task) 187 { 188 tasks.remove(task); 189 } 190 191 /** 192 * Tells whether an index must be reindexed or not. 193 * @param index the index. 194 * @return <CODE>true</CODE> if the index must be reindexed and 195 * <CODE>false</CODE> otherwise. 196 */ 197 public boolean mustReindex(AbstractIndexDescriptor index) 198 { 199 boolean mustReindex = false; 200 for (AbstractIndexDescriptor i : modifiedIndexes) 201 { 202 if (i.getName().equals(index.getName()) && 203 i.getBackend().getBackendID().equals( 204 index.getBackend().getBackendID())) 205 { 206 mustReindex = true; 207 break; 208 } 209 } 210 return mustReindex; 211 } 212 213 /** 214 * Registers an index as modified. This is used by the panels to be able 215 * to inform the user that a rebuild of the index is required. 216 * @param index the index. 217 */ 218 public void registerModifiedIndex(AbstractIndexDescriptor index) 219 { 220 modifiedIndexes.add(index); 221 indexModified(index); 222 } 223 224 /** 225 * Unregisters a modified index. 226 * @param index the index. 227 * @return <CODE>true</CODE> if the index is found in the list of modified 228 * indexes and <CODE>false</CODE> otherwise. 229 */ 230 public boolean unregisterModifiedIndex(AbstractIndexDescriptor index) 231 { 232 // We might have stored indexes whose configuration has changed, just remove 233 // them if they have the same name, are of the same type and are defined in 234 // the same backend. 235 Set<AbstractIndexDescriptor> toRemove = new HashSet<>(); 236 for (AbstractIndexDescriptor i : modifiedIndexes) 237 { 238 if (i.getName().equalsIgnoreCase(index.getName()) && 239 i.getBackend().getBackendID().equalsIgnoreCase( 240 index.getBackend().getBackendID()) && 241 i.getClass().equals(index.getClass())) 242 { 243 toRemove.add(i); 244 } 245 } 246 247 if (!toRemove.isEmpty()) 248 { 249 boolean returnValue = modifiedIndexes.removeAll(toRemove); 250 indexModified(toRemove.iterator().next()); 251 return returnValue; 252 } 253 return false; 254 } 255 256 /** 257 * Unregisters all the modified indexes on a given backend. 258 * @param backendName the name of the backend. 259 */ 260 public void unregisterModifiedIndexesInBackend(String backendName) 261 { 262 HashSet<AbstractIndexDescriptor> toDelete = new HashSet<>(); 263 for (AbstractIndexDescriptor index : modifiedIndexes) 264 { 265 // Compare only the Backend ID, since the backend object attached to 266 // the registered index might have changed (for instance the number of 267 // entries). Relying on the backend ID to identify the backend is 268 // safe. 269 if (index.getBackend().getBackendID().equalsIgnoreCase(backendName)) 270 { 271 toDelete.add(index); 272 } 273 } 274 modifiedIndexes.removeAll(toDelete); 275 for (BackendDescriptor backend : getServerDescriptor().getBackends()) 276 { 277 if (backend.getBackendID().equals(backendName)) 278 { 279 IndexModifiedEvent ev = new IndexModifiedEvent(backend); 280 for (IndexModifiedListener listener : indexListeners) 281 { 282 listener.backendIndexesModified(ev); 283 } 284 break; 285 } 286 } 287 } 288 289 /** 290 * Returns a collection with all the modified indexes. 291 * @return a collection with all the modified indexes. 292 */ 293 public Collection<AbstractIndexDescriptor> getModifiedIndexes() 294 { 295 return Collections.unmodifiableCollection(modifiedIndexes); 296 } 297 298 /** 299 * Sets the dir context to be used by the ControlPanelInfo to retrieve 300 * monitoring and configuration information. 301 * @param ctx the connection. 302 */ 303 public void setDirContext(InitialLdapContext ctx) 304 { 305 this.ctx = ctx; 306 if (ctx != null) 307 { 308 lastWorkingBindDN = ConnectionUtils.getBindDN(ctx); 309 lastWorkingBindPwd = ConnectionUtils.getBindPassword(ctx); 310 lastRemoteHostName = ConnectionUtils.getHostName(ctx); 311 lastRemoteAdministrationURL = ConnectionUtils.getLdapUrl(ctx); 312 } 313 } 314 315 /** 316 * Returns the dir context to be used by the ControlPanelInfo to retrieve 317 * monitoring and configuration information. 318 * @return the dir context to be used by the ControlPanelInfo to retrieve 319 * monitoring and configuration information. 320 */ 321 public InitialLdapContext getDirContext() 322 { 323 return ctx; 324 } 325 326 /** 327 * Sets the dir context to be used by the ControlPanelInfo to retrieve 328 * user data. 329 * @param ctx the connection. 330 * @throws NamingException if there is a problem updating the connection pool. 331 */ 332 public void setUserDataDirContext(InitialLdapContext ctx) 333 throws NamingException 334 { 335 if (userDataCtx != null) 336 { 337 unregisterConnection(connectionPool, ctx); 338 } 339 this.userDataCtx = ctx; 340 if (ctx != null) 341 { 342 InitialLdapContext cloneLdc = 343 ConnectionUtils.cloneInitialLdapContext(userDataCtx, 344 getConnectTimeout(), 345 getTrustManager(), null); 346 connectionPool.registerConnection(cloneLdc); 347 } 348 } 349 350 /** 351 * Returns the dir context to be used by the ControlPanelInfo to retrieve 352 * user data. 353 * @return the dir context to be used by the ControlPanelInfo to retrieve 354 * user data. 355 */ 356 public InitialLdapContext getUserDataDirContext() 357 { 358 return userDataCtx; 359 } 360 361 /** 362 * Informs that a backup has been created. The method will notify to all 363 * the backup listeners that a backup has been created. 364 * @param newBackup the new created backup. 365 */ 366 public void backupCreated(BackupDescriptor newBackup) 367 { 368 BackupCreatedEvent ev = new BackupCreatedEvent(newBackup); 369 for (BackupCreatedListener listener : backupListeners) 370 { 371 listener.backupCreated(ev); 372 } 373 } 374 375 /** 376 * Informs that a set of backends have been populated. The method will notify 377 * to all the backend populated listeners. 378 * @param backends the populated backends. 379 */ 380 public void backendPopulated(Set<BackendDescriptor> backends) 381 { 382 BackendPopulatedEvent ev = new BackendPopulatedEvent(backends); 383 for (BackendPopulatedListener listener : backendPopulatedListeners) 384 { 385 listener.backendPopulated(ev); 386 } 387 } 388 389 /** 390 * Informs that an index has been modified. The method will notify to all 391 * the index listeners that an index has been modified. 392 * @param modifiedIndex the modified index. 393 */ 394 public void indexModified(AbstractIndexDescriptor modifiedIndex) 395 { 396 IndexModifiedEvent ev = new IndexModifiedEvent(modifiedIndex); 397 for (IndexModifiedListener listener : indexListeners) 398 { 399 listener.indexModified(ev); 400 } 401 } 402 403 /** 404 * Returns an empty new server descriptor instance. 405 * @return an empty new server descriptor instance. 406 */ 407 protected ServerDescriptor createNewServerDescriptorInstance() 408 { 409 return new ServerDescriptor(); 410 } 411 412 /** 413 * Returns a reader that will read the configuration from a file. 414 * @return a reader that will read the configuration from a file. 415 */ 416 protected ConfigFromFile createNewConfigFromFileReader() 417 { 418 return new ConfigFromFile(); 419 } 420 421 /** 422 * Returns a reader that will read the configuration from a dir context. 423 * @return a reader that will read the configuration from a dir context. 424 */ 425 protected ConfigFromDirContext createNewConfigFromDirContextReader() 426 { 427 ConfigFromDirContext configFromDirContext = new ConfigFromDirContext(); 428 configFromDirContext.setIsLocal(isLocal()); 429 return configFromDirContext; 430 } 431 432 /** 433 * Updates the contents of the server descriptor with the provider reader. 434 * @param reader the configuration reader. 435 * @param desc the server descriptor. 436 */ 437 protected void updateServerDescriptor(ConfigReader reader, 438 ServerDescriptor desc) 439 { 440 desc.setExceptions(reader.getExceptions()); 441 desc.setAdministrativeUsers(reader.getAdministrativeUsers()); 442 desc.setBackends(reader.getBackends()); 443 desc.setConnectionHandlers(reader.getConnectionHandlers()); 444 desc.setAdminConnector(reader.getAdminConnector()); 445 desc.setSchema(reader.getSchema()); 446 desc.setSchemaEnabled(reader.isSchemaEnabled()); 447 } 448 449 /** Regenerates the last found ServerDescriptor object. */ 450 public synchronized void regenerateDescriptor() 451 { 452 boolean isLocal = isLocal(); 453 454 ServerDescriptor desc = createNewServerDescriptorInstance(); 455 desc.setIsLocal(isLocal); 456 InitialLdapContext ctx = getDirContext(); 457 if (isLocal) 458 { 459 desc.setOpenDSVersion( 460 org.opends.server.util.DynamicConstants.FULL_VERSION_STRING); 461 String installPath = Utilities.getInstallPathFromClasspath(); 462 desc.setInstallPath(installPath); 463 desc.setInstancePath(Utils.getInstancePathFromInstallPath(installPath)); 464 desc.setWindowsServiceEnabled(isWindows() && serviceState() == SERVICE_STATE_ENABLED); 465 } 466 else if (lastRemoteHostName != null) 467 { 468 desc.setHostname(lastRemoteHostName); 469 } 470 ConfigReader reader; 471 472 ServerStatus status = getStatus(desc); 473 if (status != null) 474 { 475 desc.setStatus(status); 476 if (status == ServerStatus.STOPPING) 477 { 478 StaticUtils.close(ctx); 479 this.ctx = null; 480 if (userDataCtx != null) 481 { 482 unregisterConnection(connectionPool, ctx); 483 StaticUtils.close(userDataCtx); 484 userDataCtx = null; 485 } 486 } 487 if (isLocal) 488 { 489 reader = createNewConfigFromFileReader(); 490 ((ConfigFromFile)reader).readConfiguration(); 491 } 492 else 493 { 494 reader = null; 495 } 496 desc.setAuthenticated(false); 497 } 498 else if (!isLocal || 499 Utilities.isServerRunning(new File(desc.getInstancePath()))) 500 { 501 desc.setStatus(ServerStatus.STARTED); 502 503 if (ctx == null && lastWorkingBindDN != null) 504 { 505 // Try with previous credentials. 506 try 507 { 508 if (isLocal) 509 { 510 ctx = Utilities.getAdminDirContext(this, lastWorkingBindDN, 511 lastWorkingBindPwd); 512 } 513 else if (lastRemoteAdministrationURL != null) 514 { 515 ctx = createLdapsContext(lastRemoteAdministrationURL, 516 lastWorkingBindDN, 517 lastWorkingBindPwd, 518 getConnectTimeout(), null, 519 getTrustManager(), null); 520 } 521 } 522 catch (ConfigReadException | NamingException cre) 523 { 524 // Ignore: we will ask the user for credentials. 525 } 526 if (ctx != null) 527 { 528 this.ctx = ctx; 529 } 530 } 531 532 if (isLocal && ctx == null) 533 { 534 reader = createNewConfigFromFileReader(); 535 ((ConfigFromFile)reader).readConfiguration(); 536 } 537 else if (!isLocal && ctx == null) 538 { 539 desc.setStatus(ServerStatus.NOT_CONNECTED_TO_REMOTE); 540 reader = null; 541 } 542 else 543 { 544 Utilities.initializeLegacyConfigurationFramework(); 545 reader = createNewConfigFromDirContextReader(); 546 ((ConfigFromDirContext) reader).readConfiguration(ctx); 547 548 boolean connectionWorks = checkConnections(ctx, userDataCtx); 549 if (!connectionWorks) 550 { 551 if (isLocal) 552 { 553 // Try with off-line info 554 reader = createNewConfigFromFileReader(); 555 ((ConfigFromFile) reader).readConfiguration(); 556 } 557 else 558 { 559 desc.setStatus(ServerStatus.NOT_CONNECTED_TO_REMOTE); 560 reader = null; 561 } 562 StaticUtils.close(ctx); 563 this.ctx = null; 564 unregisterConnection(connectionPool, ctx); 565 StaticUtils.close(userDataCtx); 566 userDataCtx = null; 567 } 568 } 569 570 if (reader != null) 571 { 572 desc.setAuthenticated(reader instanceof ConfigFromDirContext); 573 desc.setJavaVersion(reader.getJavaVersion()); 574 desc.setOpenConnections(reader.getOpenConnections()); 575 desc.setTaskEntries(reader.getTaskEntries()); 576 if (reader instanceof ConfigFromDirContext) 577 { 578 ConfigFromDirContext rCtx = (ConfigFromDirContext)reader; 579 desc.setRootMonitor(rCtx.getRootMonitor()); 580 desc.setEntryCachesMonitor(rCtx.getEntryCaches()); 581 desc.setJvmMemoryUsageMonitor(rCtx.getJvmMemoryUsage()); 582 desc.setSystemInformationMonitor(rCtx.getSystemInformation()); 583 desc.setWorkQueueMonitor(rCtx.getWorkQueue()); 584 desc.setOpenDSVersion(getFirstValueAsString(rCtx.getVersionMonitor(), "fullVersion")); 585 String installPath = getFirstValueAsString(rCtx.getSystemInformation(), "installPath"); 586 if (installPath != null) 587 { 588 desc.setInstallPath(installPath); 589 } 590 String instancePath = getFirstValueAsString(rCtx.getSystemInformation(), "instancePath"); 591 if (instancePath != null) 592 { 593 desc.setInstancePath(instancePath); 594 } 595 } 596 } 597 } 598 else 599 { 600 desc.setStatus(ServerStatus.STOPPED); 601 desc.setAuthenticated(false); 602 reader = createNewConfigFromFileReader(); 603 ((ConfigFromFile)reader).readConfiguration(); 604 } 605 if (reader != null) 606 { 607 updateServerDescriptor(reader, desc); 608 } 609 610 if (serverDesc == null || !serverDesc.equals(desc)) 611 { 612 serverDesc = desc; 613 ldapURL = getURL(serverDesc, ConnectionHandlerDescriptor.Protocol.LDAP); 614 ldapsURL = getURL(serverDesc, ConnectionHandlerDescriptor.Protocol.LDAPS); 615 adminConnectorURL = getAdminConnectorURL(serverDesc); 616 if (serverDesc.isLocal()) 617 { 618 localAdminConnectorURL = adminConnectorURL; 619 } 620 startTLSURL = getURL(serverDesc, 621 ConnectionHandlerDescriptor.Protocol.LDAP_STARTTLS); 622 ConfigurationChangeEvent ev = new ConfigurationChangeEvent(this, desc); 623 for (ConfigChangeListener listener : configListeners) 624 { 625 listener.configurationChanged(ev); 626 } 627 } 628 } 629 630 private ServerStatus getStatus(ServerDescriptor desc) 631 { 632 ServerStatus status = null; 633 for (Task task : getTasks()) 634 { 635 if (task.getType() == Type.START_SERVER 636 && task.getState() == State.RUNNING 637 && isRunningOnServer(desc, task)) 638 { 639 status = ServerStatus.STARTING; 640 } 641 else if (task.getType() == Type.STOP_SERVER && task.getState() == State.RUNNING 642 && isRunningOnServer(desc, task)) 643 { 644 status = ServerStatus.STOPPING; 645 } 646 } 647 return status; 648 } 649 650 private void unregisterConnection(LDAPConnectionPool connectionPool, InitialLdapContext userDataCtx) 651 { 652 if (connectionPool.isConnectionRegistered(userDataCtx)) 653 { 654 try 655 { 656 connectionPool.unregisterConnection(userDataCtx); 657 } 658 catch (Throwable t) 659 { 660 } 661 } 662 } 663 664 /** 665 * Adds a configuration change listener. 666 * @param listener the listener. 667 */ 668 public void addConfigChangeListener(ConfigChangeListener listener) 669 { 670 configListeners.add(listener); 671 } 672 673 /** 674 * Removes a configuration change listener. 675 * @param listener the listener. 676 * @return <CODE>true</CODE> if the listener is found and <CODE>false</CODE> 677 * otherwise. 678 */ 679 public boolean removeConfigChangeListener(ConfigChangeListener listener) 680 { 681 return configListeners.remove(listener); 682 } 683 684 /** 685 * Adds a backup creation listener. 686 * @param listener the listener. 687 */ 688 public void addBackupCreatedListener(BackupCreatedListener listener) 689 { 690 backupListeners.add(listener); 691 } 692 693 /** 694 * Removes a backup creation listener. 695 * @param listener the listener. 696 * @return <CODE>true</CODE> if the listener is found and <CODE>false</CODE> 697 * otherwise. 698 */ 699 public boolean removeBackupCreatedListener(BackupCreatedListener listener) 700 { 701 return backupListeners.remove(listener); 702 } 703 704 /** 705 * Adds a backend populated listener. 706 * @param listener the listener. 707 */ 708 public void addBackendPopulatedListener(BackendPopulatedListener listener) 709 { 710 backendPopulatedListeners.add(listener); 711 } 712 713 /** 714 * Removes a backend populated listener. 715 * @param listener the listener. 716 * @return <CODE>true</CODE> if the listener is found and <CODE>false</CODE> 717 * otherwise. 718 */ 719 public boolean removeBackendPopulatedListener( 720 BackendPopulatedListener listener) 721 { 722 return backendPopulatedListeners.remove(listener); 723 } 724 725 /** 726 * Adds an index modification listener. 727 * @param listener the listener. 728 */ 729 public void addIndexModifiedListener(IndexModifiedListener listener) 730 { 731 indexListeners.add(listener); 732 } 733 734 /** 735 * Removes an index modification listener. 736 * @param listener the listener. 737 * @return <CODE>true</CODE> if the listener is found and <CODE>false</CODE> 738 * otherwise. 739 */ 740 public boolean removeIndexModifiedListener(IndexModifiedListener listener) 741 { 742 return indexListeners.remove(listener); 743 } 744 745 /** 746 * Starts pooling the server configuration. The period of the pooling is 747 * specified as a parameter. This method is asynchronous and it will start 748 * the pooling in another thread. 749 */ 750 public synchronized void startPooling() 751 { 752 if (poolingThread != null) 753 { 754 return; 755 } 756 pooling = true; 757 stopPooling = false; 758 759 poolingThread = new Thread(new Runnable() 760 { 761 @Override 762 public void run() 763 { 764 try 765 { 766 while (!stopPooling) 767 { 768 cleanupTasks(); 769 regenerateDescriptor(); 770 Thread.sleep(poolingPeriod); 771 } 772 } 773 catch (Throwable t) 774 { 775 } 776 pooling = false; 777 } 778 }); 779 poolingThread.start(); 780 } 781 782 /** 783 * Stops pooling the server. This method is synchronous, it does not return 784 * until the pooling is actually stopped. 785 */ 786 public synchronized void stopPooling() 787 { 788 stopPooling = true; 789 while (poolingThread != null && pooling) 790 { 791 try 792 { 793 poolingThread.interrupt(); 794 Thread.sleep(100); 795 } 796 catch (Throwable t) 797 { 798 // do nothing; 799 } 800 } 801 poolingThread = null; 802 pooling = false; 803 } 804 805 /** 806 * Returns the trust manager to be used by this ControlPanelInfo (and in 807 * general by the control panel). 808 * @return the trust manager to be used by this ControlPanelInfo. 809 */ 810 public ApplicationTrustManager getTrustManager() 811 { 812 return trustManager; 813 } 814 815 /** 816 * Sets the trust manager to be used by this ControlPanelInfo (and in 817 * general by the control panel). 818 * @param trustManager the trust manager to be used by this ControlPanelInfo. 819 */ 820 public void setTrustManager(ApplicationTrustManager trustManager) 821 { 822 this.trustManager = trustManager; 823 connectionPool.setTrustManager(trustManager); 824 } 825 826 /** 827 * Returns the timeout to establish the connection in milliseconds. 828 * @return the timeout to establish the connection in milliseconds. 829 */ 830 public int getConnectTimeout() 831 { 832 return connectTimeout; 833 } 834 835 /** 836 * Sets the timeout to establish the connection in milliseconds. 837 * Use {@code 0} to express no timeout. 838 * @param connectTimeout the timeout to establish the connection in 839 * milliseconds. 840 * Use {@code 0} to express no timeout. 841 */ 842 public void setConnectTimeout(int connectTimeout) 843 { 844 this.connectTimeout = connectTimeout; 845 connectionPool.setConnectTimeout(connectTimeout); 846 } 847 848 /** 849 * Returns the connection policy to be used by this ControlPanelInfo (and in 850 * general by the control panel). 851 * @return the connection policy to be used by this ControlPanelInfo. 852 */ 853 public ConnectionProtocolPolicy getConnectionPolicy() 854 { 855 return connectionPolicy; 856 } 857 858 /** 859 * Sets the connection policy to be used by this ControlPanelInfo (and in 860 * general by the control panel). 861 * @param connectionPolicy the connection policy to be used by this 862 * ControlPanelInfo. 863 */ 864 public void setConnectionPolicy(ConnectionProtocolPolicy connectionPolicy) 865 { 866 this.connectionPolicy = connectionPolicy; 867 } 868 869 /** 870 * Gets the LDAPS URL based in what is read in the configuration. It 871 * returns <CODE>null</CODE> if no LDAPS URL was found. 872 * @return the LDAPS URL to be used to connect to the server. 873 */ 874 public String getLDAPSURL() 875 { 876 return ldapsURL; 877 } 878 879 /** 880 * Gets the Administration Connector URL based in what is read in the 881 * configuration. It returns <CODE>null</CODE> if no Administration 882 * Connector URL was found. 883 * @return the Administration Connector URL to be used to connect 884 * to the server. 885 */ 886 public String getAdminConnectorURL() 887 { 888 if (isLocal) 889 { 890 // If the user set isLocal to true, we want to return the 891 // localAdminConnectorURL (in particular if regenerateDescriptor has not 892 // been called). 893 return localAdminConnectorURL; 894 } 895 return adminConnectorURL; 896 } 897 898 /** 899 * Gets the Administration Connector URL based in what is read in the local 900 * configuration. It returns <CODE>null</CODE> if no Administration 901 * Connector URL was found. 902 * @return the Administration Connector URL to be used to connect 903 * to the local server. 904 */ 905 public String getLocalAdminConnectorURL() 906 { 907 return localAdminConnectorURL; 908 } 909 910 /** 911 * Gets the LDAP URL based in what is read in the configuration. It 912 * returns <CODE>null</CODE> if no LDAP URL was found. 913 * @return the LDAP URL to be used to connect to the server. 914 */ 915 public String getLDAPURL() 916 { 917 return ldapURL; 918 } 919 920 /** 921 * Gets the Start TLS URL based in what is read in the configuration. It 922 * returns <CODE>null</CODE> if no Start TLS URL is found. 923 * @return the Start TLS URL to be used to connect to the server. 924 */ 925 public String getStartTLSURL() 926 { 927 return startTLSURL; 928 } 929 930 /** 931 * Returns the LDAP URL to be used to connect to a given ServerDescriptor 932 * using a certain protocol. It returns <CODE>null</CODE> if URL for the 933 * protocol is not found. 934 * @param server the server descriptor. 935 * @param protocol the protocol to be used. 936 * @return the LDAP URL to be used to connect to a given ServerDescriptor 937 * using a certain protocol. 938 */ 939 private static String getURL(ServerDescriptor server, 940 ConnectionHandlerDescriptor.Protocol protocol) 941 { 942 String sProtocol = toString(protocol); 943 944 String url = null; 945 for (ConnectionHandlerDescriptor desc : server.getConnectionHandlers()) 946 { 947 if (desc.getState() == ConnectionHandlerDescriptor.State.ENABLED 948 && desc.getProtocol() == protocol) 949 { 950 int port = desc.getPort(); 951 if (port > 0) 952 { 953 if (server.isLocal()) 954 { 955 SortedSet<InetAddress> addresses = desc.getAddresses(); 956 if (addresses.isEmpty()) 957 { 958 url = sProtocol +"://localhost:"+port; 959 } 960 else 961 { 962 InetAddress address = addresses.first(); 963 url = sProtocol + "://" + getHostNameForLdapUrl(address.getHostAddress()) + ":" + port; 964 } 965 } 966 else 967 { 968 url = sProtocol + "://" + getHostNameForLdapUrl(server.getHostname()) + ":" + port; 969 } 970 } 971 } 972 } 973 return url; 974 } 975 976 private static String toString(ConnectionHandlerDescriptor.Protocol protocol) 977 { 978 switch (protocol) 979 { 980 case LDAP: 981 return "ldap"; 982 case LDAPS: 983 return "ldaps"; 984 case LDAP_STARTTLS: 985 return "ldap"; 986 case JMX: 987 return "jmx"; 988 case JMXS: 989 return "jmxs"; 990 default: 991 return null; 992 } 993 } 994 995 /** 996 * Returns the Administration Connector URL. 997 * It returns <CODE>null</CODE> if URL for the 998 * protocol is not found. 999 * @param server the server descriptor. 1000 * @return the Administration Connector URL. 1001 */ 1002 private static String getAdminConnectorURL(ServerDescriptor server) { 1003 ConnectionHandlerDescriptor desc = server.getAdminConnector(); 1004 if (desc != null) 1005 { 1006 int port = desc.getPort(); 1007 if (port > 0) { 1008 SortedSet<InetAddress> addresses = desc.getAddresses(); 1009 if (!addresses.isEmpty()) 1010 { 1011 String hostAddr = addresses.first().getHostAddress(); 1012 return getLDAPUrl(hostAddr, port, true); 1013 } 1014 else 1015 { 1016 return getLDAPUrl("localhost", port, true); 1017 } 1018 } 1019 } 1020 return null; 1021 } 1022 1023 /** 1024 * Tells whether we must connect to the server using Start TLS. 1025 * @return <CODE>true</CODE> if we must connect to the server using Start TLS 1026 * and <CODE>false</CODE> otherwise. 1027 */ 1028 public boolean connectUsingStartTLS() 1029 { 1030 if (getStartTLSURL() != null) 1031 { 1032 return getStartTLSURL().equals(getURLToConnect()); 1033 } 1034 return false; 1035 } 1036 1037 /** 1038 * Tells whether we must connect to the server using LDAPS. 1039 * @return <CODE>true</CODE> if we must connect to the server using LDAPS 1040 * and <CODE>false</CODE> otherwise. 1041 */ 1042 public boolean connectUsingLDAPS() 1043 { 1044 if (getLDAPSURL() != null) 1045 { 1046 return getLDAPSURL().equals(getURLToConnect()); 1047 } 1048 return false; 1049 } 1050 1051 /** 1052 * Returns the URL that must be used to connect to the server based on the 1053 * available enabled connection handlers in the server and the connection 1054 * policy. 1055 * @return the URL that must be used to connect to the server. 1056 */ 1057 public String getURLToConnect() 1058 { 1059 String url; 1060 switch (getConnectionPolicy()) 1061 { 1062 case USE_STARTTLS: 1063 return getStartTLSURL(); 1064 case USE_LDAP: 1065 return getLDAPURL(); 1066 case USE_LDAPS: 1067 return getLDAPSURL(); 1068 case USE_ADMIN: 1069 return getAdminConnectorURL(); 1070 case USE_MOST_SECURE_AVAILABLE: 1071 url = getLDAPSURL(); 1072 if (url == null) 1073 { 1074 url = getStartTLSURL(); 1075 } 1076 if (url == null) 1077 { 1078 url = getLDAPURL(); 1079 } 1080 return url; 1081 case USE_LESS_SECURE_AVAILABLE: 1082 url = getLDAPURL(); 1083 if (url == null) 1084 { 1085 url = getStartTLSURL(); 1086 } 1087 if (url == null) 1088 { 1089 url = getLDAPSURL(); 1090 } 1091 return url; 1092 default: 1093 throw new RuntimeException("Unknown policy: "+getConnectionPolicy()); 1094 } 1095 } 1096 1097 /** 1098 * Returns <CODE>true</CODE> if the configuration must be deregistered and 1099 * <CODE>false</CODE> otherwise. 1100 * This is required when we use the ConfigFileHandler to update the 1101 * configuration, in these cases cn=config must the deregistered from the 1102 * ConfigFileHandler and after that register again. 1103 * @return <CODE>true</CODE> if the configuration must be deregistered and 1104 * <CODE>false</CODE> otherwise. 1105 */ 1106 public boolean mustDeregisterConfig() 1107 { 1108 return mustDeregisterConfig; 1109 } 1110 1111 /** 1112 * Sets whether the configuration must be deregistered or not. 1113 * @param mustDeregisterConfig whether the configuration must be deregistered 1114 * or not. 1115 */ 1116 public void setMustDeregisterConfig(boolean mustDeregisterConfig) 1117 { 1118 ControlPanelInfo.mustDeregisterConfig = mustDeregisterConfig; 1119 } 1120 1121 /** 1122 * Sets whether the server is local or not. 1123 * @param isLocal whether the server is local or not. 1124 */ 1125 public void setIsLocal(boolean isLocal) 1126 { 1127 this.isLocal = isLocal; 1128 } 1129 1130 /** 1131 * Returns <CODE>true</CODE> if we are trying to manage the local host and 1132 * <CODE>false</CODE> otherwise. 1133 * @return <CODE>true</CODE> if we are trying to manage the local host and 1134 * <CODE>false</CODE> otherwise. 1135 */ 1136 public boolean isLocal() 1137 { 1138 return isLocal; 1139 } 1140 1141 /** 1142 * Returns the connection pool to be used by the LDAP entry browsers. 1143 * @return the connection pool to be used by the LDAP entry browsers. 1144 */ 1145 public LDAPConnectionPool getConnectionPool() 1146 { 1147 return connectionPool; 1148 } 1149 1150 /** 1151 * Returns the icon pool to be used by the LDAP entry browsers. 1152 * @return the icon pool to be used by the LDAP entry browsers. 1153 */ 1154 public IconPool getIconPool() 1155 { 1156 return iconPool; 1157 } 1158 1159 /** 1160 * Returns the pooling period in miliseconds. 1161 * @return the pooling period in miliseconds. 1162 */ 1163 public long getPoolingPeriod() 1164 { 1165 return poolingPeriod; 1166 } 1167 1168 /** 1169 * Sets the pooling period in miliseconds. 1170 * @param poolingPeriod the pooling time in miliseconds. 1171 */ 1172 public void setPoolingPeriod(long poolingPeriod) 1173 { 1174 this.poolingPeriod = poolingPeriod; 1175 } 1176 1177 /** Cleans the tasks that are over. */ 1178 private void cleanupTasks() 1179 { 1180 Set<Task> toClean = new HashSet<>(); 1181 for (Task task : tasks) 1182 { 1183 if (task.getState() == Task.State.FINISHED_SUCCESSFULLY || 1184 task.getState() == Task.State.FINISHED_WITH_ERROR) 1185 { 1186 toClean.add(task); 1187 } 1188 } 1189 for (Task task : toClean) 1190 { 1191 unregisterTask(task); 1192 } 1193 } 1194 1195 /** 1196 * Returns whether the provided task is running on the provided server or not. 1197 * The code takes into account that the server object might not be fully 1198 * initialized (but at least it contains the host name and the instance 1199 * path if it is local). 1200 * @param server the server. 1201 * @param task the task to be analyzed. 1202 * @return <CODE>true</CODE> if the provided task is running on the provided 1203 * server and <CODE>false</CODE> otherwise. 1204 */ 1205 private boolean isRunningOnServer(ServerDescriptor server, Task task) 1206 { 1207 if (server.isLocal() && task.getServer().isLocal()) 1208 { 1209 return true; 1210 } 1211 1212 String host1 = server.getHostname(); 1213 String host2 = task.getServer().getHostname(); 1214 boolean isRunningOnServer = host1 != null ? host1.equalsIgnoreCase(host2) : host2 == null; 1215 if (!isRunningOnServer) 1216 { 1217 return false; 1218 } 1219 1220 if (server.isLocal()) 1221 { 1222 // Compare paths 1223 String path1 = server.getInstancePath(); 1224 String path2 = task.getServer().getInstancePath(); 1225 return Objects.equals(path1, path2); 1226 } 1227 1228 // At this point we only have connection information about the new server. 1229 // Use the dir context which corresponds to the server to compare things. 1230 1231 // Compare administration port; 1232 int adminPort1 = -1; 1233 int adminPort2 = -1; 1234 if (server.getAdminConnector() != null) 1235 { 1236 adminPort1 = server.getAdminConnector().getPort(); 1237 } 1238 1239 if (getDirContext() != null) 1240 { 1241 adminPort2 = ConnectionUtils.getPort(getDirContext()); 1242 } 1243 return adminPort1 == adminPort2; 1244 } 1245 1246 private boolean checkConnections(InitialLdapContext ctx, InitialLdapContext userCtx) 1247 { 1248 // Check the connection 1249 int nMaxErrors = 5; 1250 for (int i=0; i< nMaxErrors; i++) 1251 { 1252 try 1253 { 1254 Utilities.pingDirContext(ctx); 1255 if (userCtx != null) 1256 { 1257 Utilities.pingDirContext(userCtx); 1258 } 1259 return true; 1260 } 1261 catch (NamingException ne) 1262 { 1263 try 1264 { 1265 Thread.sleep(400); 1266 } 1267 catch (Throwable t) 1268 { 1269 } 1270 } 1271 } 1272 return false; 1273 } 1274 1275 /** 1276 * Initialize the new configuration framework if needed. 1277 * 1278 * @throws org.opends.server.config.ConfigException 1279 * If error occurred during the initialization 1280 */ 1281 public void initializeConfigurationFramework() throws org.opends.server.config.ConfigException 1282 { 1283 if (!ConfigurationFramework.getInstance().isInitialized()) 1284 { 1285 try 1286 { 1287 ConfigurationFramework.getInstance().initialize(); 1288 } 1289 catch (ConfigException ce) 1290 { 1291 throw new org.opends.server.config.ConfigException(ce.getMessageObject(), ce); 1292 } 1293 } 1294 } 1295}