ClientDriver.java
/*
** Module : ClientDriver.java
** Abstract : general purpose client command line driver
**
** Copyright (c) 2005-2024, Golden Code Development Corporation.
**
** -#- -I- --Date-- --JPRM-- ----------------------------------Description-----------------------------------
** 001 NVS 20050827 @22390 Created this production level client driver.
** 002 NVS 20060110 @23849 Now the omission of the application key is allowed and causes
** StandardClient to be used.
** 003 GES 20060815 @28609 Refactored to remove duplicate code and share a common base class.
** 004 NVS 20061017 @30459 Switched to using connect() method instead of a callback approach.
** 005 GES 20061215 @31705 Changes in bootstrap config interface.
** 006 GES 20070111 @31780 Hard coded CHUI client processing here and removed some unnecessary
** processing/dead code.
** 007 GES 20070112 @31811 Removed initial debug level (it wasn't being used downstream) and
** added application args.
** 008 GES 20070115 @31826 Added support for conversation mode.
** 009 EVL 20070609 @34005 Adding explicit import of the class com.goldencode.p2j.net.Queue
** to eliminate conflict with the same class from java.util package
** to be able to compile for Java 6.
** 010 ECF 20071101 @35890 Refactored to accommodate net package mods. Eliminated
** ClientBootstrap dependencies, integrated SessionManager.
** 011 GES 20080409 @37911 Initialize remote directory access after the session is started.
** 012 GES 20090720 @43239 Better error handling for throwables.
** 013 GES 20090723 @43356 More error handling improvements and docs.
** 014 GES 20091103 @44304 Added a logging facility for detailed debugging.
** 015 GES 20110928 Moved core logic into a common class so it can be easily shared.
** 016 MAG 20140131 For web clients redirect the stderr to a file.
** 017 MAG 20140224 For batch clients redirect the stderr to a file.
** 018 MAG 20140707 Implements remote launcher (broker) a special P2J client.
** 019 GES 20141228 Rework to eliminate application arguments and to extend the client
** parameters to more use cases.
** 020 EVL 20160225 Javadoc fixes to make compatible with Oracle Java 8 for Solaris 10.
** 021 GES 20210827 Added driver name initialization and diagnostics output.
** GES 20211004 Changed log file name timestamp replacement to be a sortable date instead of millis.
** EVL 20211222 Added implementation to get client driver options from server via socket.
** HC 20220307 Added net:http_client:disable_ssl_certificate_validation to allow disabling of SSL
** certificate validation on HTTPS client connections.
** GBB 20221209 Path to the background process stderr log file to be read from configs.
** 022 GBB 20230512 Logging methods replaced by CentralLogger/ConversionStatus.
** 023 GBB 20230825 Adding an uncaught exceptions handler that logs before delegating to the
** default one.
** 024 HC 20240222 Enabled JMX on FWD Client.
** 025 GBB 20240404 Close native Win terminal on ClientCore throwing exception.
** 026 GBB 20240415 Catch IllegalStateException on console termination (in Windows).
** 027 GBB 20240709 Removing methods related to receiving client options via socket.
** 028 GBB 20240729 Initialize CentralLogger after SecurityManager is created.
** 029 GBB 20240826 Removing single client.
*/
/*
** 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.jmx.*;
import com.goldencode.p2j.ui.chui.*;
import com.goldencode.p2j.ui.client.chui.driver.console.*;
import com.goldencode.p2j.ui.client.driver.*;
import com.goldencode.p2j.util.*;
import java.io.*;
import java.net.Socket;
import java.util.*;
import com.goldencode.p2j.cfg.*;
import com.goldencode.p2j.util.logging.*;
import com.goldencode.util.*;
import javax.management.*;
/**
* General purpose command line driver to start a client process based on a bootstrap
* configuration file and/or command line parameters.
* <p>
* This driver performs a single logon to the server, invokes the application class and exits,
* when the latter is done.
* <p>
* Configuration file can be plain (unencrypted) XML file or encrypted XML. If no password is
* given with the command line, the file is assumed to be plain XML.
* <p>
* Zero, one or two configuration files can be given as parameters along with their respective
* passwords. If not specified, it will default to "standard_client.xml" in the current
* directory.
* <p>
* The two file approach is recommended as it allows for a natural way of separating common or
* related configuration information (for all users or a group of users, normally supplied in the
* first file), from the user-specific configuration information (usually supplied in the second
* file). By merely specifying a different second file, another subject can use the application
* while sharing the first configuration file.
* <p>
* All entries in the bootstrap configuration can be overridden by a command line parameter using
* the "category:group:key=value" syntax (see below).
* <p>
* The full syntax of the command line is:
* <p>
* <code>
* java ClientDriver [-?]
* [<i>config1</i>]
* [-p <i>config1_file_password</i>]
* [<i>config2</i>]
* [-p <i>config2_file_password</i>]
* [-d <i>initial_debuglevel</i>]
* [[[category:]group:]key=value]...
* </code>
* <p>
* where arguments can be specified in any order. The first password specified will be used
* with the first config file specified and likewise with the second password and config file
* respectively.
* <p>
* '-?' requests syntax help and exits.
* <p>
* Password can be given with the command line or entered interactively. One special value can
* be used: "?" (which causes an interactive password prompt to be displayed).
* <p>
* Arguments in the form "category:group:key=value" are bootstrap configuration overrides. They
* may be used to add or change values of the configuration keys in the specified category and
* group. A short form of override (one that omits the category and group) is allowed after a
* long form override and refers to the most recently specified category and group.
*/
public class ClientDriver
extends CommonDriver
{
/** Logger. Should be instantiated after setting the logger to client mode. */
private static CentralLogger LOG;
{
// initialize our protected members
driverName = "ClientDriver";
defCfg = "standard_client.xml";
maxCfg = 2;
helptxt = new String[]
{
"-----------------------P2J Client Driver-----------------------",
"",
"Syntax:",
"",
"java ClientDriver -?",
" [config1]",
" [-p config1_file_password]",
" [config2]",
" [-p config2_file_password]",
" [-d initial_debug_level]",
" [parameter_overrides]",
"",
"Where:",
"",
"-? = displays this help screen",
"config = a relative or absolute filename of a valid",
" bootstrap configuration file for this",
" client",
"config_file_password = the password to use to decrypt the config",
" file or '?' to force an interactive",
" password prompt",
"initial_debug_level = an integer value that specifies the",
" logging that should occur before server's",
" main configuration (in the directory) can",
" be read",
"parameter_overrides = configuration values that add to or",
" replace values that can be specified in",
" the bootstrap configuration; the override",
" must take one of three forms:",
" category:group:key=value",
" group:key=value",
" key=value",
" (the shorter forms will use the most",
" recently specified category and/or group",
" as needed)",
"",
"All arguments can be specified in any order except '-?' which must",
"always appear first. The first password specified will be used with ",
"the first config file specified and likewise with the second password ",
"and config file respectively."
};
}
/**
* Allows a subclass to check if the given configuration matches any
* required values. Edits may be made if needed.
*
* @param bc
* The configuration to be checked.
*/
protected void checkConfig(BootstrapConfig bc)
{
bc.setServer(false);
String convo = null;
try
{
convo = bc.getConfigItem("net", "queue", "conversation");
}
catch (ConfigurationException ce)
{
// ignore
}
// default to conversation mode if not specified
if (convo == null)
{
bc.setConfigItem("net", "queue", "conversation", "true");
}
// either way, force start thread to false (this client is going to
// use its main thread as the conversation thread so we don't need
// to start one
bc.setConfigItem("net", "queue", "start_thread", "false");
}
/**
* Runs the primary application using the preprocessed configuration and
* target object.
*
* @param config
* The configuration to use.
*/
protected void start(BootstrapConfig config)
throws Exception
{
if (config.getBoolean("net", "http_client", "disable_ssl_certificate_validation", false))
{
Utils.disableClientSSLCertificateValidation();
}
if (config.getBoolean("client", "mode", "broker", false))
{
BrokerCore.start(config);
}
else
{
try
{
ClientCore.start(config, this::printDriverDetails);
}
catch (Throwable t)
{
if (PlatformHelper.isUnderWindowsFamily() &&
ThinClient.getInstance().getOutputManager().getInstanceDriver() instanceof ConsoleDriver)
{
try
{
ConsoleHelper.terminate();
}
catch (Throwable nativeThrowable)
{
LOG.info("ConsoleHelper.terminate() execution has thrown an exception:", nativeThrowable);
}
}
throw t;
}
}
// ensure that remaining non-daemon threads don't stop us from closing
System.exit(0);
}
/**
* The command line entry point.
*
* @param args
* The array of command-line parameters.
*/
public static void main(String[] args)
{
CentralLogger.setMode(CentralLogger.Mode.CLIENT_BASE);
LOG = CentralLogger.get(ClientDriver.class);
setDefaultExceptionHandler(LOG);
FwdClientJMX.init();
ClientDriver client = new ClientDriver();
// after our parent class processes the command line arguments, if there are no errors,
// then the start() method will be called
client.process(args);
}
}