/* ====================================================================
* Limited Evaluation License:
*
* This software is open source, but licensed. The license with this package
* is an evaluation license, which may not be used for productive systems. If
* you want a full license, please contact us.
*
* The exclusive owner of this work is the OpenRate project.
* This work, including all associated documents and components
* is Copyright of the OpenRate project 2006-2015.
*
* The following restrictions apply unless they are expressly relaxed in a
* contractual agreement between the license holder or one of its officially
* assigned agents and you or your organisation:
*
* 1) This work may not be disclosed, either in full or in part, in any form
* electronic or physical, to any third party. This includes both in the
* form of source code and compiled modules.
* 2) This work contains trade secrets in the form of architecture, algorithms
* methods and technologies. These trade secrets may not be disclosed to
* third parties in any form, either directly or in summary or paraphrased
* form, nor may these trade secrets be used to construct products of a
* similar or competing nature either by you or third parties.
* 3) This work may not be included in full or in part in any application.
* 4) You may not remove or alter any proprietary legends or notices contained
* in or on this work.
* 5) This software may not be reverse-engineered or otherwise decompiled, if
* you received this work in a compiled form.
* 6) This work is licensed, not sold. Possession of this software does not
* imply or grant any right to you.
* 7) You agree to disclose any changes to this work to the copyright holder
* and that the copyright holder may include any such changes at its own
* discretion into the work
* 8) You agree not to derive other works from the trade secrets in this work,
* and that any such derivation may make you liable to pay damages to the
* copyright holder
* 9) You agree to use this software exclusively for evaluation purposes, and
* that you shall not use this software to derive commercial profit or
* support your business or personal activities.
*
* This software is provided "as is" and any expressed or impled warranties,
* including, but not limited to, the impled warranties of merchantability
* and fitness for a particular purpose are disclaimed. In no event shall
* The OpenRate Project or its officially assigned agents be liable to any
* direct, indirect, incidental, special, exemplary, or consequential damages
* (including but not limited to, procurement of substitute goods or services;
* Loss of use, data, or profits; or any business interruption) however caused
* and on theory of liability, whether in contract, strict liability, or tort
* (including negligence or otherwise) arising in any way out of the use of
* this software, even if advised of the possibility of such damage.
* This software contains portions by The Apache Software Foundation, Robert
* Half International.
* ====================================================================
*/
package OpenRate.configurationmanager;
import OpenRate.OpenRate;
import OpenRate.Pipeline;
import OpenRate.exception.InitializationException;
import OpenRate.logging.LogUtil;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.*;
/**
* ClientManager is used for managing the client modules available for this
* OpenRate Application. It serves as a repository of the client modules that
* can be readily executed.
*
* @author a.villena
*/
public class ClientManager {
// This is the map of the clients we know, indexed by the symbolic name
private static HashMap<String, ClientContainer> HMClientMap = new HashMap<>();
// This is the singleton instance
private static ClientManager clientManager = null;
/**
* None of MANDATORY, DYNAMIC or SYNC
*/
public static int PARAM_NONE = 0x00;
/**
* Indicates that the parameter is a mandatory parameter which must be loaded
* on startup
*/
public static int PARAM_MANDATORY = 0x01;
/**
* Indicates that this is a parameter which can be changed at run time
*/
public static int PARAM_DYNAMIC = 0x02;
/**
* Indicates that this is a parameter which will trigger a sync point
*/
public static int PARAM_SYNC = 0x04;
/**
* Mandatory and Dynamic
*/
public static int PARAM_MANDATORY_DYNAMIC = 0x03;
/**
* Dynamic and Sync
*/
public static int PARAM_DYNAMIC_SYNC = 0x06;
// module symbolic name: never changes in this module, so not set dynamically
private String SymbolicName = "ClientManager";
// -----------------------------------------------------------------------------
// --------------------- Client manager utility functions ----------------------
// -----------------------------------------------------------------------------
/**
* Returns the instance of the client manager.
*
* @return the client manager instance.
*/
public static ClientManager getClientManager() {
// Initialise the singleton if we need
if (clientManager == null) {
clientManager = new ClientManager();
}
// return the reference so we can work on it
return clientManager;
}
/**
* puts the client in the HashMap which contains all the client modules
* registered
*
* @param SymbolicName - the symbolic name of the client module that will be
* the key
* @param clientContainer - clientContainer object which holds the client
* module
*/
private void put(String SymbolicName, ClientContainer clientContainer) {
HMClientMap.put(SymbolicName, clientContainer);
}
/**
* getter method for returning the ClientContainer of a specific client module
*
* @param SymbolicName - symbolic name of the client module
* @return The client container object
*/
public ClientContainer get(String SymbolicName) {
if (HMClientMap.containsKey(SymbolicName)) {
ClientContainer clCont = HMClientMap.get(SymbolicName);
return clCont;
} else {
return null;
}
}
/**
* Clears down the map: used primarily for testing.
*/
public void clear() {
HMClientMap.clear();
}
// -----------------------------------------------------------------------------
// ------------------------- IEventInterface functions -------------------------
// -----------------------------------------------------------------------------
/**
* registerClient registers the client module to the ClientManager. This also
* caches the client module object that can be accessed and executed.
*
* @param pipelineName
* @param symbolicName - symbolic name of the client module to add
* @param objClient - instance of the client module
* @throws InitializationException
*/
public void registerClient(String pipelineName, String symbolicName, Object objClient) throws InitializationException {
if (pipelineName == null) {
throw new InitializationException("Pipeline Name cannot be empty", getSymbolicName());
}
if (symbolicName == null) {
throw new InitializationException("Symbolic Name cannot be empty", getSymbolicName());
}
ClientContainer clCont = new ClientContainer(pipelineName, symbolicName, objClient);
put(symbolicName, clCont);
LogUtil.getStaticLogger("Framework").debug("Registered Client <" + symbolicName + ">");
}
/**
* registerClientService registers the command available for the client module
*
* @param symbolicName - symbolic name of the client module to add the command
* to
* @param commandName - name of the command to register
* @param paramFlags The parameter flags for this service (Mandatory, Dynamic,
* Sync)
*
*/
public void registerClientService(String symbolicName,
String commandName,
int paramFlags) {
ClientContainer clCont = get(symbolicName);
boolean Mandatory = (paramFlags & PARAM_MANDATORY) == PARAM_MANDATORY;
boolean Dynamic = (paramFlags & PARAM_DYNAMIC) == PARAM_DYNAMIC;
boolean RequireSync = (paramFlags & PARAM_SYNC) == PARAM_SYNC;
clCont.addService(commandName, Mandatory, Dynamic, RequireSync);
OpenRate.getOpenRateFrameworkLog().debug("Registered Client Service <" + commandName + ">");
}
// -----------------------------------------------------------------------------
// ---------------- Client Manager Configuration Push Functions ----------------
// -----------------------------------------------------------------------------
/**
* Client Manager Configuration Push is an innovative feature to allow the
* Client Manager to check the configuration before trying to initialise the
* pipelines. It should work like this: 1) The Client Manager reads in the
* whole of the configuration on start up 2) The Client Manager then performs
* a first level of plausibility checks on the configuration that has been
* passed. 3) The Framework requests a list of the resources to create 4) The
* Framework creates the resources 5) The Client Manager then pushes the
* configuration to the resources 6) The Framework requests a list of the
* pipelines to create 7) The Framework creates the pipelines 8) The Client
* manager pushes the configuration to the pipeline modules
*/
/**
* This pushes the initial configuration into the plug-in with the symbolic
* name given. This passes the configuration from the client manager into the
* plug-in after the class has been instantiated to perform the initial
* configuration
*
* @param SymbolicName The name of the plug-in to initialise
*/
public void pushPlugInInit(String SymbolicName) {
// ToDo
}
/**
* Get a list of the resource modules to create
*
* @return List of the resources
*/
public ArrayList<String> getResourceList() {
// ToDo
return null;
}
/**
* Get a list of the pipelines to create
*
* @return List of the pipelines
*/
public ArrayList<Pipeline> getPipelineList() {
// ToDo
return null;
}
/**
* Get a list of the plug in modules to create for a given pipeline
*
* @param PipelineName The pipeline name we are querying
* @return List of the modules the pipeline contains
*/
public ArrayList<String> getPipelinePlugins(String PipelineName) {
// ToDo
return null;
}
// -----------------------------------------------------------------------------
// ---------------------- Start stream handling functions ----------------------
// -----------------------------------------------------------------------------
/**
* getCommandList returns a StringBuffer containing the list of commands
* accepted in the following format:
*
* SymbolicName ClassCommandName isMandatory isDynamic
*
* if parameter strSymbolicName is set to null, all commands of all Clients
* will be listed; else specify the symbolicName of a Client to get the
* specific commands of it. if isMandatory is set to true, only mandatory
* commands will only be included in the list; set to false if you want to get
* all the commands
*
* @param strSymbolicName - symbolic name to search
* @param isMandatoryOnly - flag to get only the mandatory commands or all
* commands
* @param GUIMode - Return the list in GUIMode or not (GUIMode is a machine
* readable format)
* @return StringBuffer - list of commands available
*/
public StringBuffer getCommandList(String strSymbolicName,
boolean isMandatoryOnly,
boolean GUIMode) {
StringBuffer strCmdList = new StringBuffer();
String strSymbolicKey;
String strHelper;
String strCurrentValue = "";
String strClassName;
ClientContainer clCont;
ServiceContainer svCont;
Object ClientObject;
IEventInterface ClientEvent;
String strCommandName;
String pipelineName;
if (!GUIMode) {
strCmdList.append(
"OpenRate command listing:\r\n+-----------------------------------------------------------------+---+---+---+\r\n");
strCmdList.append("| Command | M | D | S |\r\n");
strCmdList.append("+-----------------------------------------------------------------+---+---+---+\r\n");
}
// Sort the modules
List<String> clientKeys = new ArrayList<>(HMClientMap.keySet());
Collections.sort(clientKeys);
Iterator<String> iterNameList = clientKeys.iterator();
if (strSymbolicName == null) {
strSymbolicName = "*";
}
while (iterNameList.hasNext()) {
strSymbolicKey = iterNameList.next();
if ((strSymbolicName.endsWith("*"))
| (strSymbolicName.equals(strSymbolicKey))) {
clCont = HMClientMap.get(strSymbolicKey);
// get the pipe name for this container
pipelineName = clCont.getClientPipelineName();
HashMap<String, ServiceContainer> HMSvcList = clCont.getService();
// Sort the commands within the module
List<String> commandKeys = new ArrayList<>(HMSvcList.keySet());
Collections.sort(commandKeys);
// Get the interator
Iterator<String> iterSvcList = commandKeys.iterator();
// Get the current values
ClientObject = clCont.getClientObject();
strClassName = clCont.getClientClassName();
if (!GUIMode) {
strHelper = "|" + pipelineName + ":" + strSymbolicKey
+ " ";
strCmdList.append(strHelper.substring(0, 66)).append("| | | |\r\n");
} else {
strHelper = "Module;" + pipelineName + ";" + strSymbolicKey + ";" + strClassName + "\r\n";
strCmdList.append(strHelper);
}
while (iterSvcList.hasNext()) {
strCommandName = iterSvcList.next();
svCont = HMSvcList.get(strCommandName);
if (ClientObject instanceof IEventInterface) {
ClientEvent = (IEventInterface) ClientObject;
try {
strCurrentValue = ClientEvent.processControlEvent(strCommandName, false, "");
} catch (Exception e) {
System.err.println("Error processing control event <" + strCommandName + "> in module <" + strSymbolicKey + ">");
}
}
//check if we want to list mandatory commands only
if (isMandatoryOnly) {
//check if the command is mandatory; if yes add it to the command list
if (svCont.getMandatory()) {
if (!GUIMode) {
strHelper = getFormatCommand(pipelineName,
strSymbolicKey,
strCommandName,
strCurrentValue,
svCont.getMandatory(),
svCont.getDynamic(),
svCont.getRequireSync());
strCmdList.append(strHelper).append("\r\n");
} else {
strHelper = getFormatCommandGUI(pipelineName,
strSymbolicKey,
strCommandName,
strCurrentValue,
svCont.getMandatory(),
svCont.getDynamic(),
svCont.getRequireSync());
strCmdList.append("Command;").append(strHelper).append("\r\n");
}
}
} else {
if (!GUIMode) {
//add to command list whether mandatory or not
strHelper = getFormatCommand(pipelineName,
strSymbolicKey,
strCommandName,
strCurrentValue,
svCont.getMandatory(),
svCont.getDynamic(),
svCont.getRequireSync());
strCmdList.append(strHelper).append("\r\n");
} else {
strHelper = getFormatCommandGUI(pipelineName,
strSymbolicKey,
strCommandName,
strCurrentValue,
svCont.getMandatory(),
svCont.getDynamic(),
svCont.getRequireSync());
strCmdList.append("Command;").append(strHelper).append("\r\n");
}
}
}
}
}
if (!GUIMode) {
strCmdList.append(
"+-----------------------------------------------------------------+---+---+---+");
} else {
// Add the end tag
strCmdList.append("OK");
}
return strCmdList;
}
/**
* getModuleList returns all the available client modules that have been
* registered in the framework.
*
* @param GUIMode True if the list should be returned for use in the GUI
* @return StringBuffer - containing the client module symbolic names
*/
public StringBuffer getModuleList(boolean GUIMode) {
StringBuffer strModuleList = new StringBuffer();
String strSymbolicKey;
String strClassName;
String strHelper;
String pipelineName;
if (!GUIMode) {
strModuleList.append(
"OpenRate module listing:\r\n+--------------------+----------------------------------------+----------------------------------------------------+\r\n");
strModuleList.append(
"| Pipeline Name | Module Name | Class |\r\n");
strModuleList.append(
"+--------------------+----------------------------------------+----------------------------------------------------+\r\n");
}
List<String> clientKeys = new ArrayList<>(HMClientMap.keySet());
Collections.sort(clientKeys);
Iterator<String> iterNameList = clientKeys.iterator();
while (iterNameList.hasNext()) {
strSymbolicKey = iterNameList.next();
ClientContainer clCont = HMClientMap.get(strSymbolicKey);
strClassName = clCont.getClientClassName();
pipelineName = clCont.getClientPipelineName();
if (!GUIMode) {
strHelper = getFormatModule(pipelineName, strSymbolicKey, strClassName);
} else {
strHelper = getFormatModuleGUI(pipelineName, strSymbolicKey, strClassName);
}
strModuleList.append(strHelper).append("\r\n");
}
if (!GUIMode) {
strModuleList.append(
"+--------------------+----------------------------------------+----------------------------------------------------+");
} else {
// Add the end tag
strModuleList.append("OK");
}
return strModuleList;
}
/**
* getModuleList returns all the available client modules that have been
* registered in the framework.
*
* @return StringBuffer - containing the client module symbolic names
*/
public StringBuffer getThreadList() {
StringBuffer strThreadList = new StringBuffer();
long totalCpuTime = 0l;
long totalUserTime = 0l;
strThreadList.append(
"OpenRate thread listing:\r\n+--------------------+------------------------------------+\r\n");
ThreadMXBean threads = ManagementFactory.getThreadMXBean();
strThreadList.append("current-thread-count <").append(threads.getThreadCount()).append(">\r\n");
strThreadList.append("total-started-thread-count <").append(threads.getTotalStartedThreadCount()).append(">\r\n");
strThreadList.append("daemon-thread-count <").append(threads.getDaemonThreadCount()).append(">\r\n");
strThreadList.append("peak-thread-count <").append(threads.getPeakThreadCount()).append(">\r\n");
// Parse each thread
ThreadInfo[] threadInfos = threads.getThreadInfo(threads.getAllThreadIds());
for (int i = 0; i < threadInfos.length; i++) {
strThreadList.append("id <").append(Long.toString(threadInfos[i].getThreadId())).append(">\r\n");
strThreadList.append("name <").append(threadInfos[i].getThreadName()).append(">\r\n");
strThreadList.append("cpu-time-nano <").append(Long.toString(threads.getThreadCpuTime(threadInfos[i].getThreadId()))).append(">\r\n");
strThreadList.append("cpu-time-ms <").append(Long.toString(threads.getThreadCpuTime(threadInfos[i].getThreadId()) / 1000000l)).append(">\r\n");
strThreadList.append("user-time-nano <").append(Long.toString(threads.getThreadUserTime(threadInfos[i].getThreadId()))).append(">\r\n");
strThreadList.append("user-time-ms <").append(Long.toString(threads.getThreadUserTime(threadInfos[i].getThreadId()) / 1000000l)).append(">\r\n");
strThreadList.append("blocked-count <").append(Long.toString(threadInfos[i].getBlockedCount())).append(">\r\n");
strThreadList.append("blocked-time <").append(Long.toString(threadInfos[i].getBlockedTime())).append(">\r\n");
strThreadList.append("waited-count <").append(Long.toString(threadInfos[i].getWaitedCount())).append(">\r\n");
strThreadList.append("waited-time <").append(Long.toString(threadInfos[i].getWaitedTime())).append(">\r\n");
strThreadList.append("+--------------------+\r\n");
// Update our aggregate values
totalCpuTime += threads.getThreadCpuTime(threadInfos[ i].getThreadId());
totalUserTime += threads.getThreadUserTime(threadInfos[ i].getThreadId());
}
long totalCpuTimeMs = totalCpuTime / 1000000l;
long totalUserTimeMs = totalUserTime / 1000000l;
strThreadList.append("total-cpu-time-nano <").append(Long.toString(totalCpuTime)).append(">\r\n");
strThreadList.append("total-user-time-nano <").append(Long.toString(totalUserTime)).append(">\r\n");
strThreadList.append("total-cpu-time-ms <").append(Long.toString(totalCpuTimeMs)).append(">\r\n");
strThreadList.append("total-user-time-ms <").append(Long.toString(totalUserTimeMs)).append(">\r\n");
strThreadList.append(
"+--------------------+------------------------------------+");
return strThreadList;
}
/**
* Formats the command items for display
*
* @param pipelineName Name of the pipeline holding the module
* @param symbolicName Name of the module
* @param command The command name
* @param currentValue The current value
* @param mandatory True if mandatory
* @param dynamic True if dynamic
* @param requireSync True if requires sync point
* @return Formatted string
*/
public String getFormatCommand(String pipelineName,
String symbolicName,
String command,
String currentValue,
boolean mandatory,
boolean dynamic,
boolean requireSync) {
String strHelperName;
String strHelperMandatory;
String strHelperDynamic;
String strHelperReqSync;
strHelperName = "| - " + symbolicName + ":" + command
+ " ";
strHelperName = strHelperName.substring(0, 66) + "|";
if (mandatory) {
strHelperMandatory = " X |";
} else {
strHelperMandatory = " |";
}
if (dynamic) {
strHelperDynamic = " X |";
} else {
strHelperDynamic = " |";
}
if (requireSync) {
strHelperReqSync = " X |";
} else {
strHelperReqSync = " |";
}
return strHelperName + strHelperMandatory + strHelperDynamic + strHelperReqSync;
}
/**
* Formats the command items for the GUI
*
* @param pipelineName Name of the pipeline holding the module
* @param symbolicName Name of the module
* @param command The command name
* @param currentValue The current value
* @param mandatory True if mandatory
* @param dynamic True if dynamic
* @param requireSync True if requires sync point
* @return Formatted string
*/
public String getFormatCommandGUI(String pipelineName,
String symbolicName,
String command,
String currentValue,
boolean mandatory,
boolean dynamic,
boolean requireSync) {
String strHelperOutput;
String strHelperMandatory;
String strHelperDynamic;
String strHelperReqSync;
strHelperOutput = pipelineName + ";" + symbolicName + ";" + command + ";" + currentValue + ";";
if (mandatory) {
strHelperMandatory = "X;";
} else {
strHelperMandatory = " ;";
}
if (dynamic) {
strHelperDynamic = "X;";
} else {
strHelperDynamic = " ;";
}
if (requireSync) {
strHelperReqSync = "X;";
} else {
strHelperReqSync = " ;";
}
return strHelperOutput + strHelperMandatory + strHelperDynamic + strHelperReqSync;
}
/**
* Formats the module items for display
*
* @param pipelineName Name of the pipeline the module is in
* @param SymbolicName Name of the module
* @param Class Class name of the module
* @return Formatted string
*/
public String getFormatModule(String pipelineName, String SymbolicName, String Class) {
String strHelperPipe;
String strHelperName;
String strHelperClass;
strHelperPipe = "| " + pipelineName + " ";
strHelperPipe = strHelperPipe.substring(0, 21);
strHelperName = "| " + SymbolicName + " ";
strHelperName = strHelperName.substring(0, 41) + "| ";
strHelperClass = Class + " ";
strHelperClass = strHelperClass.substring(0, 51) + "| ";
return strHelperPipe + strHelperName + strHelperClass;
}
/**
* Formats the module items for GUI
*
* @param pipelineName Name of the pipeline the module is in
* @param SymbolicName Name of the module
* @param Class Class name of the module
* @return Formatted string
*/
public String getFormatModuleGUI(String pipelineName, String SymbolicName, String Class) {
String strHelper;
strHelper = "Module;" + pipelineName + ";" + SymbolicName + ";" + Class;
return strHelper;
}
/**
* @return the SymbolicName
*/
public String getSymbolicName() {
return SymbolicName;
}
/**
* @param SymbolicName the SymbolicName to set
*/
public void setSymbolicName(String SymbolicName) {
this.SymbolicName = SymbolicName;
}
}