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