docs: @FFDCIgnore({ ChannelException.class, ChainException.class })
      public synchronized void update() {
          if (TraceComponent.isAnyTracingEnabled() && tc.isEventEnabled()) {
              Tr.event(this, tc, "update chain " + this);
          }
  
          // Don't update or start the chain if it is disabled or the framework is stopping.. 
          if (!enabled || !configured || FrameworkState.isStopping())
              return;
  
          final ActiveConfiguration oldConfig = currentConfig;
  
          // The old configuration was "valid" if it existed, and if it was correctly configured
          final boolean validOldConfig = oldConfig == null ? false : oldConfig.validConfiguration;
  
          Map<String, Object> tcpOptions = owner.getTcpOptions();
          Map<String, Object> sslOptions = (isHttps) ? owner.getSslOptions() : null;
          Map<String, Object> httpOptions = owner.getHttpOptions();
  
          final ActiveConfiguration newConfig = new ActiveConfiguration(isHttps, tcpOptions, sslOptions, httpOptions);
  
          if (!newConfig.complete()) {
  
              // save the new/changed configuration before we start setting up the new chain
              currentConfig = newConfig;
  
              // Stop the chain-- will have to be recreated when port is updated
              // notification/follow-on of stop operation is in the chainStopped listener method
              try {
                  ChainData cd = cfw.getChain(chainName);
                  if (cd != null) {
                      cfw.removeChain(cd);
                  }
  
              } catch (ChainException e) {
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "Error stopping chain " + chainName, oldConfig, e);
                  }
              }
          } else {
  
              boolean sameConfig = newConfig.unchanged(oldConfig);
              if (validOldConfig) {
                  if (sameConfig) {
                      return;
                  }
              }
  
              try {
                  ChainData cd = cfw.getChain(chainName);
                  if (cd != null) {
                      cfw.removeChain(cd);
                  }
  
                  // Remove any channels that have to be rebuilt.. 
                  if (newConfig.tcpChanged(oldConfig)) {
                      removeChannel(tcpName);
                  }
  
                  if (newConfig.sslChanged(oldConfig)) {
                      removeChannel(sslName);
                  }
  
                  if (newConfig.httpChanged(oldConfig)) {
                      removeChannel(httpName);
                  }
  
              } catch (ChainException e) {
                  e.printStackTrace();
                  if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                      Tr.debug(this, tc, "Error stopping chain " + chainName, oldConfig, e);
                  }
              }
  
              // save the new/changed configuration before we start setting up the new chain
              currentConfig = newConfig;
              try {
                  Map<Object, Object> chanProps;
  
                  // TCP Channel
                  ChannelData tcpChannel = cfw.getChannel(tcpName);
                  if (tcpChannel == null) {
                      String typeName = (String) tcpOptions.get("type");
                      chanProps = new HashMap<Object, Object>(tcpOptions);
  
                      tcpChannel = cfw.addChannel(tcpName, cfw.lookupFactory(typeName), chanProps);
                  }
  
                  // SSL Channel
                  if (isHttps) {
                      ChannelData sslChannel = cfw.getChannel(sslName);
                      if (sslChannel == null) {
                          sslChannel = cfw.addChannel(sslName, cfw.lookupFactory("SSLChannel"), new HashMap<Object, Object>(sslOptions));
                      }
                  }
  
                  // HTTP Channel
                  ChannelData httpChannel = cfw.getChannel(httpName);
                  if (httpChannel == null) {
                      chanProps = new HashMap<Object, Object>(httpOptions);
                      // Put the endpoint id, which allows us to find the registered access log
                      // dynamically
                      httpChannel = cfw.addChannel(httpName, cfw.lookupFactory("HTTPOutboundChannel"), chanProps);
                  }
  
                  // Add chain
                  ChainData cd = cfw.getChain(chainName);
                  if (null == cd) {
                      final String[] chanList;
                      if (isHttps)
                          chanList = new String[] { httpName, sslName, tcpName };
                      else
                          chanList = new String[] { httpName, tcpName };
  
                      cd = cfw.addChain(chainName, FlowType.OUTBOUND, chanList);
                      cd.setEnabled(enabled);
  
                  }
  
                  // We configured the chain successfully
                  newConfig.validConfiguration = true;
  
              } catch (ChannelException e) {
                  // handleStartupError(e, newConfig); // FFDCIgnore: CFW will have logged and FFDCd already
              } catch (ChainException e) {
                  // handleStartupError(e, newConfig); // FFDCIgnore: CFW will have logged and FFDCd already
              } catch (Exception e) {
                  // The exception stack for this is all internals and does not belong in messages.log.
                  //  Question: need error message here?
                  //  Tr.error(tc, "config.httpChain.error", tcpName, e.toString());
                  //  handleStartupError(e, newConfig);
              }
          }
  
      }