WebClientBuilderParameters.java

/*
** Module   : WebClientBuilderParameters.java
** Abstract : store the web client process parameters
**
** Copyright (c) 2014-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- -------------------------------Description------------------------------------
** 001 CA  20140206 Created initial version, extracted from ClientBuilderParameters.
** 002 GES 20150312 Store the web client type.
** 003 GES 20160203 Added trusted mode support and removed some dead code.
** 004 CA  20160428 Added command-line configuration options for web-clients.
** 005 GBB 20230825 Adding new fields logoutPage and ssoFwdUser.
** 006 GBB 20231113 Cleanup for web:referrer:url. Adding storageId to constructor.
** 007 GBB 20240709 Splitting web overrides to 4 fields to be merged in the right order after setting a 
**                  project token. Web specific fields and methods moved here from other classes for stronger 
**                  cohesion and better typization. Fields unmodifiable.
** 008 GBB 20240718 Moving base client builder configs to a field in the respective options class.
** 009 GBB 20240821 Replacing hard-coded proxy client option names with constants.
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
** 
** Additional terms under GNU Affero GPL version 3 section 7:
** 
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
**   terms apply to the works covered under the License.  These additional terms
**   are non-permissive additional terms allowed under Section 7 of the GNU
**   Affero GPL version 3 and may not be removed by you.
** 
**   0. Attribution Requirement.
** 
**     You must preserve all legal notices or author attributions in the covered
**     work or Appropriate Legal Notices displayed by works containing the covered
**     work.  You may not remove from the covered work any author or developer
**     credit already included within the covered work.
** 
**   1. No License To Use Trademarks.
** 
**     This license does not grant any license or rights to use the trademarks
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
**     of Golden Code Development Corporation. You are not authorized to use the
**     name Golden Code, FWD, or the names of any author or contributor, for
**     publicity purposes without written authorization.
** 
**   2. No Misrepresentation of Affiliation.
** 
**     You may not represent yourself as Golden Code Development Corporation or FWD.
** 
**     You may not represent yourself for publicity purposes as associated with
**     Golden Code Development Corporation, FWD, or any author or contributor to
**     the covered work, without written authorization.
** 
**   3. No Misrepresentation of Source or Origin.
** 
**     You may not represent the covered work as solely your work.  All modified
**     versions of the covered work must be marked in a reasonable way to make it
**     clear that the modified work is not originating from Golden Code Development
**     Corporation or FWD.  All modified versions must contain the notices of
**     attribution required in this license.
*/

package com.goldencode.p2j.main;

import com.goldencode.p2j.util.*;
import com.goldencode.p2j.util.logging.*;
import com.goldencode.p2j.web.*;

import java.util.*;
import java.util.logging.*;

/**
 * This structure holds default parameters as well specific parameters used to create and spawn a 
 * process for a web client (either GUI or ChUI). 
 */
public class WebClientBuilderParameters
extends ClientBuilderParameters
{
   /** Logger. */
   private static final CentralLogger LOG = CentralLogger.get(WebClientBuilderParameters.class);
   
   /** The template for the transport part of the java debugger agent connection string */
   private static final String DEBUGGER_TRANSPORT = "dt_socket,server=y,suspend=%s,address=%d";

   /** Unmodifiable map of client config : default value pairs for the debug profile. */
   private static final Map<ConfigItem, String> DEBUG_PROFILE =
      Collections.unmodifiableMap(new HashMap<ConfigItem, String>() {
         {
            put(ConfigItem.WEB_SOCKET_TIMEOUT, String.valueOf(20 * 60 * 1000));
            put(ConfigItem.WATCHDOG_TIMEOUT, String.valueOf(40 * 60 * 1000));
            put(ConfigItem.MAX_IDLE_TIME, String.valueOf(20 * 60 * 1000));
            put(ConfigItem.MAX_HTTP_IDLE_TIME, String.valueOf(WebConfigurationConstants.INFINITE_TIMEOUT));
            put(ConfigItem.CONNECT_RETRY_DELAY,
                String.valueOf(WebConfigurationConstants.DELAY_BETWEEN_CONNECT_TRIES));
            put(ConfigItem.PING_PONG_INTERVAL, String.valueOf(20 * 60 * 1000));
            put(ConfigItem.MAX_LOST_PINGS, String.valueOf(WebConfigurationConstants.MAX_LOST_PINGS));
            put(ConfigItem.PING_DELAY, String.valueOf(WebConfigurationConstants.DELAY_BETWEEN_PING_TRIES));
            put(ConfigItem.JS_DEBUG_LOGGING, String.valueOf(true));
         }});
      
   /** Enables trusted launch mode (no password is used and the OS account is forced). */
   private final boolean trusted;
   
   /** The bootstrap config overrides to be applied first. Lowest priority. Embedded startup procedure. */
   private final List<String> firstWebOverrides;

   /** The bootstrap config overrides coming from directory, i.e. webClient/cfgOverrides. */
   private final List<String> dirWebOverrides;

   /**
    * The bootstrap config overrides compiled runtime: theme, webRoot, login/logout page url, forked 
    * session overrides.
    */
   private final List<String> runtimeWebOverrides;

   /**
    * The bootstrap config overrides to be applied last. Highest priority. Web driver type: embedded or not.
    */
   private final List<String> lastWebOverrides;
   
   /** Default options from directory */
   private final WebClientBuilderOptions dirOptions;

   /** Fwd user for SSO authentication. */
   private final String ssoFwdUser;

   /** The unique id for the client storage. <code>null</code> if SSO not enabled. */
   private final String storageId;

   /**
    * Constructor. Assign a unique UUID to this process.
    *
    * @param    osUser
    *           The OS user name.
    * @param    osPass
    *           The OS user password.
    * @param    dirOptions
    *           The client builder options.
    * @param    securePort
    *           The server's secure port.
    * @param    serverAlias
    *           The alias of the server certificate.
    * @param    trusted
    *           If this instance will be used to launch clients in trusted mode.
    * @param    ssoFwdUser
    *           Fwd user for SSO authentication.
    * @param    storageId
    *           The unique id for the client storage.
    * @param    firstWebOverrides
    *           The bootstrap config overrides to be applied first. Lowest priority.
    * @param    dirWebOverrides
    *           The bootstrap config overrides coming from directory.
    * @param    runtimeWebOverrides
    *           The bootstrap config overrides compiled runtime.
    * @param    lastWebOverrides
    *           The bootstrap config overrides to be applied last. Highest priority.
    */
   public WebClientBuilderParameters(String osUser,
                                     String osPass,
                                     WebClientBuilderOptions dirOptions,
                                     int securePort,
                                     String serverAlias,
                                     boolean trusted,
                                     String ssoFwdUser,
                                     String storageId,
                                     List<String> firstWebOverrides,
                                     List<String> dirWebOverrides,
                                     List<String> runtimeWebOverrides,
                                     List<String> lastWebOverrides)
   {
      super(osUser, osPass, securePort, serverAlias);
      
      this.ssoFwdUser = ssoFwdUser;
      this.storageId = storageId;
      this.dirOptions = dirOptions;
      this.trusted = trusted;
      this.firstWebOverrides = Collections.unmodifiableList(firstWebOverrides);
      this.dirWebOverrides = Collections.unmodifiableList(dirWebOverrides);
      this.runtimeWebOverrides = Collections.unmodifiableList(runtimeWebOverrides);
      this.lastWebOverrides = Collections.unmodifiableList(lastWebOverrides);
      
      dirOptions.reset();
   }

   /**
    * Returns the directory values for the client as {@link WebClientBuilderOptions}.
    *
    * @return   See above.
    */
   @Override
   public WebClientBuilderOptions getDirOptions()
   {
      return dirOptions;
   }

   /**
    * Get the authentication mode for this spawner.
    *
    * @return   {@code true} indicating that the user's password is required for authentication.
    */
   @Override
   public boolean isPasswordAuthentication()
   {
      return !trusted;
   }

   /**
    * Get the flag that reports which web client type is in use.
    * 
    * @return   Client type (<code>true</code> for GUI, <code>false</code> for ChUI).
    */
   public boolean isGui()
   {
      return getDirOptions().getDriverType().isGui();                  
   }

   /**
    * Get the flag that reports is spawning should use trusted mode.
    *
    * @return   Trusted mode flag.
    */
   public boolean isTrusted()
   {
      return trusted;
   }
   
   /**
    * Get the FWD user for SSO authentication.
    *
    * @return  The FWD user for SSO authentication.
    */
   public String getSsoFwdUser()
   {
      return ssoFwdUser;
   }

   /**
    * Get the unique id for the client storage.
    *
    * @return  The unique id for the client storage.
    */
   public String getStorageId()
   {
      return storageId;
   }

   /**
    * Getter for {@link #firstWebOverrides}.
    *
    * @return  See above.
    */
   public List<String> getFirstWebOverrides()
   {
      return firstWebOverrides;
   }

   /**
    * Getter for {@link #dirWebOverrides}.
    *
    * @return  See above.
    */
   public List<String> getDirWebOverrides()
   {
      return dirWebOverrides;
   }

   /**
    * Getter for {@link #runtimeWebOverrides}.
    *
    * @return  See above.
    */
   public List<String> getRuntimeWebOverrides()
   {
      return runtimeWebOverrides;
   }

   /**
    * Getter for {@link #lastWebOverrides}.
    *
    * @return  See above.
    */
   public List<String> getLastWebOverrides()
   {
      return lastWebOverrides;
   }

   /**
    * Update the command line parameters for the spawning process with the web client configuration.
    *
    * @param    allocatedResources
    *           The web client allocated resources
    */
   void updateOptions(WebAllocatedResources allocatedResources)
   {
      if (allocatedResources == null)
      {
         return;
      }
      
      // set jmx and java debugger command line options
      if (allocatedResources.getJmxAgentPort() > 0)
      {
         dirOptions.getBaseOptions().updateJvmArgument("-Dcom.sun.management.jmxremote.port",
                                                       String.valueOf(allocatedResources.getJmxAgentPort()));
      }
      if (allocatedResources.getDebugAgentPort() > 0)
      {
         dirOptions.getBaseOptions().updateJvmArgument("-Xrunjdwp:transport",
                                                       String.format(DEBUGGER_TRANSPORT,
                                                                     dirOptions.getBaseOptions().getSuspendOption(),
                                                                     allocatedResources.getDebugAgentPort()));
         for (Map.Entry<ConfigItem, String> debugConfig : DEBUG_PROFILE.entrySet())
         {
            String configName = debugConfig.getKey().name();
            dirOptions.override(configName, debugConfig.getValue());
            LOG.log(Level.WARNING, "DEBUG MODE: %s=%s", configName, debugConfig.getValue());
         }
      }
      if (allocatedResources.getPort() > 0)
      {
         dirOptions.override(ConfigItem.PORT.name(), String.valueOf(allocatedResources.getPort()));
      }
      String forwardedHost = allocatedResources.getForwardedHost();
      if (forwardedHost != null)
      {
         dirOptions.override(ConfigItem.PROXY_HOST.name(), forwardedHost);
         dirOptions.override(ConfigItem.PROXY_PROTOCOL.name(), allocatedResources.getForwardedProto());
         dirOptions.override(ConfigItem.WEB_ROOT.name(), allocatedResources.getWebRoot());
      }
   }
}