WebClientBuilder.java
/*
** Module : WebClientBuilder.java
** Abstract : build and start a process for the web client
**
** Copyright (c) 2014-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- ---------------------------------Description----------------------------------
** 001 CA 20140206 First version, extracted from ClientBuilder.
** 002 MAG 20140711 Enable/Disable clipboard.
** 003 MAG 20140722 Implement remote launcher.
** 004 GES 20150312 Added support for the GUI web client.
** 005 GES 20150710 Modified/added configuration processing for GUI, clipboard flag is ChUI-only.
** 006 CA 20160205 Changed to use ServerKeyStore.getStore().
** 007 GES 20160203 Added trusted mode support.
** SBI 20160321 Added maxBinaryMessage, maxTextMessage, maxIdleTime websocket's parameters
** and set the web client embedded mode "client:web:embedded".
** 008 CA 20160428 Added command-line configuration options for web-clients.
** 009 SBI 20160427 Added graphicsCached parameter to turn off the graphics cache for testing.
** 010 HC 20201116 Added renderer web client option.
** SBI 20210331 Added client:gui:taskBarStyle.
** SBI 20210514 Added delayBetweenTriesToConnect, tryToConnectMessage and serverUnavailableMessage
** 20210516 Added pingPongInterval, maxLostPings and delayBetweenPingTries.
** 20210517 Added connectionRestoredMessage.
** 20210914 Added enableDebugLogging.
** SBI 20211003 Added http configuration settings for the web client.
** EVL 20211222 Added implementation to pass options to client driver from server via socket.
** EVL 20220105 Improvements for Windows specific options passing via socket for web client.
** TJD 20220527 Support for text-metrics cache controlled by server
** 011 SBI 20230306 Changed remoteStart by adding new parameters to perform allocation of network ports
** for spawned clients.
** 012 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
** 013 GBB 20230825 Cleanup for client:web:embedded.
** 014 GBB 20231101 Adding new option client:web:useLocalStorage from directory configs.
** 015 GBB 20231113 Cleanup for web:referrer:url. Adding new option client:web:broadcastChannelPingTimeout.
** 016 GBB 20240709 Removing fields and methods for sending options via temp socket. Instead of adding the
** options to cmd in addClientOptions create PostInitOptions wrapper and store it in map
** UUID_OPTIONS for later retrieval by the client. The logic for creating the bootstrap
** override values moved to WebClientSpawner.prepareBootstrapValues.
** 017 GBB 20240719 Null check for project token.
** 018 GBB 20240730 Get the project token from the web parameters instead of resolving each time.
** 019 CA 20250221 Added constants for the spawner modes.
*/
/*
** 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 java.util.*;
import com.goldencode.p2j.util.*;
/**
* This class is used to create and spawn a web client process using a {@link ProcessBuilder}
* instance. A special small tools are designed for Linux / Windows OS in order to spawn the
* process on the OS user account. Both tools are written in C using specific OS API and are
* build as executable using ant native target. The source code and the make file for this tools
* are available in the /src/native process directory. The password is provided vis stdin
* redirection on both platforms. The command line parameters for the spawned process are
* constructed from default parameters stored in directory and some specific parameters stored
* inside a {@link WebClientBuilderParameters} structure.
*/
public class WebClientBuilder
extends ClientBuilder
{
/** Map of client uuid and options. */
static final Map<String, PostInitOptions> UUID_OPTIONS = new HashMap<>();
/** A Java Bean containing specific parameters */
private final WebClientBuilderParameters params;
/**
* Constructor.
*
* @param params
* The specific parameters for this client.
*/
public WebClientBuilder(WebClientBuilderParameters params)
{
this.params = params;
}
/**
* Returns the {@link WebClientBuilderParameters} used for building the client.
*
* @return See above.
*/
@Override
public WebClientBuilderParameters getParams()
{
return params;
}
/**
* Prepares options to be sent to the client after a session is established. Don't use for options
* critical for initial client configuration.
*/
@Override
protected void addClientOptions()
{
WebClientBuilderOptions dirOptions = params.getDirOptions();
if (dirOptions.getProjectToken() != null)
{
command.add(ConfigItem.PROJECT_TOKEN.fullOption() + "=" + dirOptions.getProjectToken());
}
if (params.getSsoFwdUser() != null)
{
command.add(ConfigItem.SSO_SUBJECT_ID.fullOption() + "=" + params.getSsoFwdUser());
}
if (params.getStorageId() != null)
{
command.add(ConfigItem.SSO_STORAGE_ID.fullOption() + "=" + params.getStorageId());
}
UUID_OPTIONS.put(this.params.getUuid(), new PostInitOptions(dirOptions.getDriverType(),
remote,
dirOptions.getOverriddenOptions(),
params.getFirstWebOverrides(),
params.getDirWebOverrides(),
params.getRuntimeWebOverrides(),
params.getLastWebOverrides()));
}
/**
* Get the spawn arguments. Web chui clients call the {@code spawn} tool using the
* {@code spawn 0 <user> <workdir> <command> [args]} syntax.
* <p>
* As these arguments are already built into the {@link ClientBuilder#command} list, it just
* returns the already build list with a "1" prefix.
*
* @return See above.
*/
@Override
protected List<String> getSpawnArguments()
{
List<String> cmd = new ArrayList<>();
if (params.isTrusted())
{
// mode 0 (passwordless/trusted, uses the NativeSecureConnection)
initNativeSecureConnection(cmd);
}
else
{
// add mode 1 (userid/password authentication at OS level)
cmd.add(ClientSpawner.MODE_AUTH_PASSWORD);
}
// the entire command
cmd.addAll(command);
return cmd;
}
/**
* A wrapper class for all configurations applicable to the specific request for client spawn, that
* need to be applied after the client is initialized.
*/
static class PostInitOptions
{
/** The web driver type. */
private WebDriverType driverType;
/** Indicator for a remote spawn. */
private boolean remote;
/** The map of runtime derived options. */
private Map<String, String> runtimeOptions;
/** The bootstrap config overrides to be applied first. Lowest priority. */
private List<String> firstWebOverrides;
/** The bootstrap config overrides coming from directory. */
private List<String> dirWebOverrides;
/** The bootstrap config overrides compiled runtime. */
private List<String> runtimeWebOverrides;
/** The bootstrap config overrides to be applied last. Highest priority. */
private List<String> lastWebOverrides;
/**
* Constructor.
*
* @param driverType
* The web driver type.
* @param remote
* Indicator for a remote spawn.
* @param runtimeOptions
* The map of runtime derived options.
* @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.
*/
PostInitOptions(WebDriverType driverType,
boolean remote,
Map<String, String> runtimeOptions,
List<String> firstWebOverrides,
List<String> dirWebOverrides,
List<String> runtimeWebOverrides,
List<String> lastWebOverrides)
{
this.driverType = driverType;
this.remote = remote;
this.runtimeOptions = runtimeOptions;
this.firstWebOverrides = firstWebOverrides;
this.dirWebOverrides = dirWebOverrides;
this.runtimeWebOverrides = runtimeWebOverrides;
this.lastWebOverrides = lastWebOverrides;
}
/**
* Getter for {@link #driverType}.
*
* @return See above.
*/
public WebDriverType getDriverType()
{
return driverType;
}
/**
* Getter for {@link #remote}.
*
* @return See above.
*/
public boolean getRemote()
{
return remote;
}
/**
* Getter for {@link #runtimeOptions}.
*
* @return See above.
*/
public Map<String, String> getRuntimeOptions()
{
return runtimeOptions;
}
/**
* Returns all bootstrap overrides merged in the right order. Uses the directory values, stored
* on receiving the spawn request.
*
* @return See above.
*/
public List<String> getWebOverrides()
{
return getWebOverrides(dirWebOverrides);
}
/**
* Returns all bootstrap overrides merged in the right order. Uses the directory values provided as
* parameter (could be a list created after the project token is set).
*
* @param dirOverrides
* The bootstrap overrides derived from directory values to be used in the final list.
*
* @return See above.
*/
public List<String> getWebOverrides(List<String> dirOverrides)
{
List<String> allWebOverrides = new ArrayList<>();
if (firstWebOverrides != null)
{
allWebOverrides.addAll(firstWebOverrides);
}
if (dirOverrides != null)
{
allWebOverrides.addAll(dirOverrides);
}
if (runtimeWebOverrides != null)
{
allWebOverrides.addAll(runtimeWebOverrides);
}
if (lastWebOverrides != null)
{
allWebOverrides.addAll(lastWebOverrides);
}
return allWebOverrides;
}
}
}