blob: d11954c3a28e9590df54abb33e93e3573e08eda5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.uima.ducc.cli;
import java.util.ArrayList;
import java.util.List;
import org.apache.uima.ducc.common.Pair;
import org.apache.uima.ducc.common.utils.DuccProperties;
import org.apache.uima.ducc.common.utils.DuccPropertiesResolver;
import org.apache.uima.ducc.common.utils.DuccSchedulerClasses;
import org.apache.uima.ducc.common.utils.IllegalConfigurationException;
import org.apache.uima.ducc.transport.event.ServiceDisableEvent;
import org.apache.uima.ducc.transport.event.ServiceEnableEvent;
import org.apache.uima.ducc.transport.event.ServiceIgnoreEvent;
import org.apache.uima.ducc.transport.event.ServiceModifyEvent;
import org.apache.uima.ducc.transport.event.ServiceObserveEvent;
import org.apache.uima.ducc.transport.event.ServiceQueryEvent;
import org.apache.uima.ducc.transport.event.ServiceRegisterEvent;
import org.apache.uima.ducc.transport.event.ServiceStartEvent;
import org.apache.uima.ducc.transport.event.ServiceStopEvent;
import org.apache.uima.ducc.transport.event.ServiceUnregisterEvent;
import org.apache.uima.ducc.transport.event.cli.SpecificationProperties;
import org.apache.uima.ducc.transport.event.sm.IService.ServiceType;
import org.apache.uima.ducc.transport.event.sm.IService.Trinary;
import org.apache.uima.ducc.transport.event.sm.IServiceReply;
/**
* Handle registered services. This class is also the implementation of the
* DUCC service CLI which internally uses its API to implement itself. Details on the
* DUCC service CLI are found in the<a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
*/
public class DuccServiceApi
extends CliBase
{
String endpoint = null;
IDuccCallback callback = null;
UiOption[] registration_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Description,
UiOption.Administrators,
UiOption.SchedulingClass,
UiOption.LogDirectory,
UiOption.WorkingDirectory,
UiOption.Jvm,
UiOption.ProcessJvmArgs,
UiOption.Classpath,
UiOption.Environment,
UiOption.ProcessMemorySize,
UiOption.ProcessDD,
UiOption.ProcessExecutable,
UiOption.ProcessExecutableArgs,
UiOption.ProcessInitializationTimeMax,
UiOption.ProcessDebug,
// UiOption.Specification // not used for registration
UiOption.ServiceDependency,
UiOption.ServiceRequestEndpoint,
UiOption.ServiceLinger,
UiOption.ServicePingArguments,
UiOption.ServicePingClass,
UiOption.ServicePingClasspath,
UiOption.ServicePingJvmArgs,
UiOption.ServicePingTimeout,
UiOption.ServicePingDoLog,
UiOption.InstanceFailureWindow,
UiOption.InstanceFailureLimit,
UiOption.InstanceInitFailureLimit,
UiOption.Register,
UiOption.Autostart,
UiOption.Instances,
};
UiOption[] unregister_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Unregister,
UiOption.RoleAdministrator,
};
/**
* Service start arguments.
*/
UiOption[] start_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Start,
UiOption.Instances,
UiOption.RoleAdministrator,
};
UiOption[] stop_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Stop,
UiOption.Instances,
UiOption.RoleAdministrator,
};
UiOption[] enable_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Enable,
UiOption.RoleAdministrator,
};
UiOption[] disable_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Disable,
UiOption.RoleAdministrator,
};
UiOption[] observe_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Observe,
UiOption.RoleAdministrator,
};
UiOption[] ignore_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Ignore,
UiOption.RoleAdministrator,
};
// This gets generated from the registratoin_options.
UiOption[] modify_options;
UiOption[] query_options = {
UiOption.Help,
UiOption.Debug,
UiOption.Query,
};
// These options are only valid for CUSTOM services
UiOption[] custom_only_options = {
UiOption.ProcessExecutable,
UiOption.ProcessExecutableArgs,
};
// These options are only valid for UIMA-AS services
UiOption[] uimaas_only_options = {
UiOption.ProcessDD,
UiOption.Jvm,
UiOption.ProcessJvmArgs,
UiOption.ProcessDebug,
UiOption.Classpath,
};
// These options are only valid for services with an explicit pinger
// Note: Only ServicePingArguments is used for an internal pinger ... others are quietly ignored
UiOption[] pinger_only_options = {
UiOption.ServicePingClasspath,
UiOption.ServicePingJvmArgs,
UiOption.ServicePingTimeout,
UiOption.ServicePingDoLog,
};
public DuccServiceApi(IDuccCallback cb)
{
this.callback = cb;
//
// generate modify options, same as registration options, only with the verb
// Modify insteady of Register, and on extra option, Activate.
// The length here, based on registration options:
// minus 1 for ProcessDD
// minus 1 for ServiceRequestEndpoint
// plus 1 for RoleAdministrator
// ==> -1 length
//
modify_options = new UiOption[registration_options.length - 1];
int i = 0;
for ( UiOption o : registration_options ) {
if ( o == UiOption.ProcessDD ) continue; // disallowed for modify
if ( o == UiOption.ServiceRequestEndpoint) continue; // disallowed for modify
if ( o == UiOption.Register ) o = UiOption.Modify;
modify_options[i++] = o;
}
modify_options[i++] = UiOption.RoleAdministrator;
// modify_options[i++] = UiOption.Activate;
}
private Pair<Integer, String> getId(UiOption opt)
{
String sid = cli_props.getProperty(opt.pname());
if ( sid == null ) {
throw new IllegalArgumentException("Missing service id: --id <id or endpoint>");
}
int id = -1;
try {
id = Integer.parseInt(sid);
return new Pair<Integer, String>(id, null);
} catch ( NumberFormatException e ) {
// nothing
}
if ( sid.startsWith(ServiceType.UimaAs.decode()) || sid.startsWith(ServiceType.Custom.decode()) ) {
return new Pair<Integer, String>(-1, sid);
}
throw new IllegalArgumentException("Invalid id; must be numeric or start with " + ServiceType.UimaAs.decode() + " or " + ServiceType.Custom.decode() + ".");
}
private Trinary getAutostart()
{
String auto = cli_props.getStringProperty(UiOption.Autostart.pname(), null);
if ( auto == null ) {
return Trinary.Unset;
}
boolean val = Boolean.parseBoolean(auto);
Trinary answer = Trinary.encode(val ? "true" : "false");
if ( answer == Trinary.Unset ) {
throw new IllegalArgumentException("--" + UiOption.Autostart.pname() + " " + auto + " is not 'true' or 'false'");
}
return answer;
}
private int getInstances(int dflt)
{
String inst = cli_props.getProperty(UiOption.Instances.pname());
if ( inst == null ) return dflt;
int instances;
try {
instances = Integer.parseInt(inst);
} catch ( NumberFormatException e ) {
throw new IllegalArgumentException(UiOption.Instances.pname() + " " + inst + " is not numeric.");
}
if ( instances <= 0 ) {
throw new IllegalArgumentException(UiOption.Instances.pname() + " " + inst + " must be > 0");
}
return instances;
}
// private boolean getActivate()
// {
// return cli_props.containsKey(UiOption.Activate.pname());
// }
// private boolean getUpdate()
// {
// return cli_props.containsKey(UiOption.Update.pname());
// }
private void setLinger()
{
String default_linger = DuccPropertiesResolver.get("ducc.sm.default.linger", "5000");
String linger = cli_props.getStringProperty(UiOption.ServiceLinger.pname(), default_linger);
try {
Long.parseLong(linger); // make sure it's a long, don't care about the value
} catch ( NumberFormatException e ) {
throw new IllegalArgumentException(UiOption.ServiceLinger.pname() + " is not numeric: " + linger);
}
}
/**
* Attempt a fast-fail if a bad debug port is specified. Fill in the host if not supplied.
*/
private void enrichPropertiesForDebug(UiOption verb)
{
String debug_port = cli_props.getProperty(UiOption.ProcessDebug.pname());
String debug_host = host_address;
if ( debug_port == null ) return;
if ( debug_port.equals("off") ) {
switch (verb ) {
case Register:
System.out.println("Note: 'process_debug = off' removed; 'off' is valid only for --modify");
cli_props.remove(UiOption.ProcessDebug.pname()); // 'off' invalid for registration
return;
case Modify:
return;
}
}
if ( debug_port.contains(":") ) {
String[] parts = debug_port.split(":");
if ( parts.length != 2 ) {
throw new IllegalArgumentException("Error: " +
UiOption.ProcessDebug.pname() +
" process_debug must be a single numeric port, or else of the form 'host:port'");
}
debug_host = parts[0];
debug_port = parts[1];
}
try {
Integer.parseInt(debug_port);
} catch ( NumberFormatException e ) {
throw new IllegalArgumentException("Invalid debug port specified, not numeric: " + debug_port);
}
cli_props.setProperty(UiOption.ProcessDebug.pname(), debug_host + ":" + debug_port);
}
private String extractEndpoint(String jvmargs)
{
String dd = cli_props.getStringProperty(UiOption.ProcessDD.pname()); // will throw if can't find the prop
String working_dir = cli_props.getStringProperty(UiOption.WorkingDirectory.pname());
endpoint = DuccUiUtilities.getEndpoint(working_dir, dd, jvmargs);
if ( debug ) {
System.out.println("DD service endpoint resolves to " + endpoint);
}
return endpoint;
}
private void discardOptions(UiOption[] ignored_options, String type) {
for (UiOption opt : ignored_options) {
if (cli_props.containsKey(opt.pname())) {
message("WARNING - Option --" + opt.pname() + " is ignored for " + type + " services");
cli_props.remove(opt.pname());
}
}
}
public UiOption[] getModifyOptions()
{
return modify_options;
}
/**
* The register API is used to register a service with the service manager.
*
* @param args String rray of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with register status.
*/
public IServiceReply register(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init (this.getClass().getName(), registration_options, args, null, dp, callback, "sm");
// Note: dp & cli_props are identical ... use only the class variable here for consistency
setLinger();
// Determine service type based on the endpoint (default is UIMA-AS)
// For each type check for required options; also warn and drop any inappropriate options
String endpoint = cli_props.getStringProperty(UiOption.ServiceRequestEndpoint.pname(), null);
if ( endpoint == null || endpoint.startsWith(ServiceType.UimaAs.decode()) ) {
String uimaDD = cli_props.getStringProperty(UiOption.ProcessDD.pname(), null);
if (uimaDD == null) {
throw new IllegalArgumentException("Option --" + UiOption.ProcessDD.pname() + " is required for UIMA-AS services");
}
discardOptions(custom_only_options, ServiceType.UimaAs.decode());
if ( ! cli_props.containsKey(UiOption.ServicePingClass.pname()) ) {
discardOptions(pinger_only_options, "pinger-less UIMA-AS");
}
// Set default classpath if not specified - only used for UIMA-AS services
String key_cp = UiOption.Classpath.pname();
if (!cli_props.containsKey(key_cp)) {
cli_props.setProperty(key_cp, System.getProperty("java.class.path"));
}
// Given ep must match inferred ep. Use case: an application is wrapping DuccServiceApi and has to construct
// the endpoint as well. The app passes it in and we insure that the constructed endpoint matches the one
// we extract from the DD - the job will fail otherwise, so we catch this early.
String jvmarg_string = cli_props.getProperty(UiOption.ProcessJvmArgs.pname());
String inferred_endpoint = extractEndpoint(jvmarg_string);
if (endpoint == null) {
endpoint = inferred_endpoint;
} else {
// Check & strip any broker URL decorations on the endpoint
endpoint = DuccUiUtilities.check_service_dependencies(null, endpoint);
cli_props.setProperty(UiOption.ServiceRequestEndpoint.pname(), endpoint); // SM uses both endpoint definitions !!!
if ( !inferred_endpoint.equals(endpoint) ) {
throw new IllegalArgumentException("Specified endpoint does not match endpoint extracted from UIMA DD"
+ "\n --service_request_endpoint: " + endpoint
+ "\n extracted: " + inferred_endpoint );
}
}
enrichPropertiesForDebug(UiOption.Register);
check_heap_size(UiOption.ProcessJvmArgs.pname());
} else if (endpoint.startsWith(ServiceType.Custom.decode())) {
// Custom services must have a pinger, but the process_executable (& args)
// options may be omitted for a ping-only service.
// When omitted other options such as autostart are irrelevant.
if ( ! cli_props.containsKey(UiOption.ServicePingClass.pname()) ) {
throw new IllegalArgumentException("Option --service_ping_class is required for CUSTOM services");
}
discardOptions(uimaas_only_options, ServiceType.Custom.decode());
String key_cp = UiOption.ServicePingClasspath.pname();
if (!cli_props.containsKey(key_cp)) {
cli_props.setProperty(key_cp, System.getProperty("java.class.path"));
}
check_heap_size(UiOption.ProcessExecutableArgs.pname());
} else {
throw new IllegalArgumentException("Invalid service endpoint: " + endpoint);
}
// Check if falsely using a fair-share class; set the default if missing
String scheduling_class = cli_props.getProperty(UiOption.SchedulingClass.pname());
boolean isPreemptableClass = false;
try {
DuccSchedulerClasses duccSchedulerClasses = DuccSchedulerClasses.getInstance();
if (scheduling_class != null) {
isPreemptableClass = duccSchedulerClasses.isPreemptable(scheduling_class);
} else {
cli_props.setProperty(UiOption.SchedulingClass.pname(), duccSchedulerClasses.getDebugClassDefaultName());
}
} catch (Exception e) {
throw new IllegalConfigurationException("Error in DUCC configuration files - see administrator", e);
}
if (isPreemptableClass) {
throw new IllegalArgumentException("Invalid pre-emptable scheduling class: " + scheduling_class);
}
// work out stuff I'm dependent upon
if ( !check_service_dependencies(endpoint) ) {
throw new IllegalArgumentException("Invalid service dependencies");
}
int instances = cli_props.getIntProperty(UiOption.Instances.pname(), 1);
Trinary autostart = getAutostart();
String user = (String) cli_props.remove(UiOption.User.pname());
byte[] auth_block = (byte[]) cli_props.remove(UiOption.Signature.pname());
// A few spurious properties are set as an artifact of parsing the overly-complex command line, and need removal
cli_props.remove(UiOption.SubmitPid.pname());
cli_props.remove(UiOption.Register.pname());
cli_props.remove(UiOption.Instances.pname());
cli_props.remove(UiOption.Autostart.pname());
ServiceRegisterEvent ev = new ServiceRegisterEvent(user, instances, autostart, endpoint, cli_props, auth_block, CliVersion.getVersion());
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
/**
* The unregister API is used to unregister a service. The service manager will stop all instances and
* remove the service registration.
*
* @param args String array of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with unregister reply status.
*/
public IServiceReply unregister(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), unregister_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Unregister);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceUnregisterEvent ev = new ServiceUnregisterEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
/**
* The start API is used to start one or more instances of a registered service.
*
* @param args String array of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with start reply status.
*/
public IServiceReply start(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), start_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Start);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceStartEvent ev = new ServiceStartEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
int instances = getInstances(-1);
//boolean update = getUpdate();
ev.setInstances(instances);
//ev.setUpdate(update);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
/**
* The stop API is used to stop one or more service instances.
*
* @param args String array of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with stop status.
*/
public IServiceReply stop(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), stop_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Stop);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceStopEvent ev = new ServiceStopEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
int instances = getInstances(-1);
//boolean update = getUpdate();
ev.setInstances(instances);
//ev.setUpdate(update);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
/**
* The service 'modify' command is used to change various aspects of a registered service
* without the need to reregister it.
*
* @param args String array of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with modify status.
*/
public IServiceReply modify(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
inhibitDefaults();
init (this.getClass().getName(), modify_options, args, null, dp, callback, "sm");
enrichPropertiesForDebug(UiOption.Modify);
Pair<Integer, String> id = getId(UiOption.Modify);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
dp.remove(UiOption.RoleAdministrator.pname());
ServiceModifyEvent ev = new ServiceModifyEvent(user, id.first(), id.second(), dp, auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
/**
* The service 'modify' command is used to change various aspects of a registered service
* without the need to reregister it.
*
* @param args String array of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with modify status.
*/
public IServiceReply modifyX(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init (this.getClass().getName(), modify_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Modify);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
DuccProperties mods = new SpecificationProperties();
ServiceModifyEvent ev = new ServiceModifyEvent(user, id.first(), id.second(), mods, auth_block, CliVersion.getVersion());
int instances = getInstances(-1);
Trinary autostart = getAutostart();
// boolean activate = getActivate();
String pingArguments = cli_props.getProperty(UiOption.ServicePingArguments.pname());
String pingClass = cli_props.getProperty(UiOption.ServicePingClass.pname());
String pingClasspath = cli_props.getProperty(UiOption.ServicePingClasspath.pname());
String pingJvmArgs = cli_props.getProperty(UiOption.ServicePingJvmArgs.pname());
String pingTimeout = cli_props.getProperty(UiOption.ServicePingTimeout.pname());
String pingDoLog = cli_props.getProperty(UiOption.ServicePingDoLog.pname());
// modify: if something is modified, indicate the new value. if no value, then it's not modified.
if ( instances > 0 ) mods.setProperty("instances", Integer.toString(instances));
switch ( autostart ) {
case True: mods.setProperty("autostart", "true"); break;
case False: mods.setProperty("autostart", "false"); break;
default:
break;
}
// if ( activate ) mods.setProperty("activate", "true");
// else mods.setProperty("activate", "false");
if ( pingArguments != null ) mods.setProperty("service_ping_arguments", pingArguments);
if ( pingClass != null ) mods.setProperty("service_ping_class" , pingClass);
if ( pingClasspath != null ) mods.setProperty("service_ping_classpath", pingClasspath);
if ( pingJvmArgs != null ) mods.setProperty("service_ping_jvm_args" , pingJvmArgs);
if ( pingTimeout != null ) mods.setProperty("service_ping_timeout" , pingTimeout);
if ( pingDoLog != null ) mods.setProperty("service_ping_dolog" , pingDoLog);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
/**
* The query API is used to query the status of services known to the service manager.
*
* @param args String array of arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
* @return {@link IServiceReply IServiceReply} object with query results status.
*/
public IServiceReply query(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), query_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = null;
String sid = cli_props.getProperty(UiOption.Query.pname()).trim();
if ( sid == null || sid.equals("") ) {
id = new Pair<Integer, String>(-1, null);
} else {
id = getId(UiOption.Query);
}
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
ServiceQueryEvent ev = new ServiceQueryEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
public IServiceReply observeReferences(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), observe_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Observe);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceObserveEvent ev = new ServiceObserveEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
public IServiceReply ignoreReferences(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), ignore_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Ignore);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceIgnoreEvent ev = new ServiceIgnoreEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
public IServiceReply enable(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), enable_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Enable);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceEnableEvent ev = new ServiceEnableEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
public IServiceReply disable(String[] args)
throws Exception
{
DuccProperties dp = new SpecificationProperties();
init(this.getClass().getName(), disable_options, args, null, dp, callback, "sm");
Pair<Integer, String> id = getId(UiOption.Disable);
String user = dp.getProperty(UiOption.User.pname());
byte[] auth_block = (byte[]) dp.get(UiOption.Signature.pname());
boolean asAdministrator = dp.containsKey(UiOption.RoleAdministrator.pname());
ServiceDisableEvent ev = new ServiceDisableEvent(user, id.first(), id.second(), auth_block, CliVersion.getVersion());
ev.setAdministrative(asAdministrator);
try {
return (IServiceReply) dispatcher.dispatchAndWaitForDuccReply(ev);
} finally {
dispatcher.close();
}
}
void help()
{
CommandLine cl;
cl = new CommandLine(null, registration_options);
System.out.println(cl.formatHelp("--------------- Register Options -------------"));
cl = new CommandLine(null, unregister_options);
System.out.println(cl.formatHelp("\n\n------------- Unregister Options ------------------"));
cl = new CommandLine(null, start_options);
System.out.println(cl.formatHelp("\n\n------------- Start Options ------------------"));
cl = new CommandLine(null, stop_options);
System.out.println(cl.formatHelp("\n\n------------- Stop Options ------------------"));
cl = new CommandLine(null, modify_options);
System.out.println(cl.formatHelp("\n\n------------- Modify Options ------------------"));
cl = new CommandLine(null, query_options);
System.out.println(cl.formatHelp("\n\n------------- Query Options ------------------"));
System.exit(1);
}
public boolean execute() { return false; }
static boolean format_reply(UiOption verb, IServiceReply reply)
{
//String ep = reply.getEndpoint()!=null ? reply.getEndpoint() : "";
//String id = reply.getId()!=-1 ? " ID["+String.valueOf(reply.getId())+"]" : "";
//String result = (reply.getReturnCode()) ? " succeeded - " : " failed - ";
//String msg = "Service " + verb + result + reply.getMessage() + " - " + ep + id;
// UIMA-4336 Slight rework because different JREs return different results.
String ep = (reply.getEndpoint() == null) ? "N/A" : reply.getEndpoint();
String id = reply.getId()!=-1 ? " ID["+String.valueOf(reply.getId())+"]" : "";
boolean rc = reply.getReturnCode();
String result = rc ? " succeeded - " : " failed - ";
String msg = "Service " + verb + result + reply.getMessage() + " - " + ep + id;
switch ( verb ) {
case Register:
case Unregister:
case Start:
case Stop:
case Modify:
case Disable:
case Enable:
case Ignore:
case Observe:
System.out.println(msg);
break;
case Query:
if (rc) {
System.out.println(reply.toString());
} else {
System.out.println(msg);
}
break;
}
return rc;
}
static boolean Register(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.register(args);
return format_reply(UiOption.Register, reply);
}
static boolean Unregister(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.unregister(args);
return format_reply(UiOption.Unregister, reply);
}
static boolean Start(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.start(args);
return format_reply(UiOption.Start, reply);
}
static boolean Stop(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.stop(args);
return format_reply(UiOption.Stop, reply);
}
static boolean Modify(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.modify(args);
return format_reply(UiOption.Modify, reply);
}
static boolean Enable(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.enable(args);
return format_reply(UiOption.Enable, reply);
}
static boolean Disable(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.disable(args);
return format_reply(UiOption.Disable, reply);
}
static boolean ObserveReferences(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.observeReferences(args);
return format_reply(UiOption.Observe, reply);
}
static boolean IgnoreReferences(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.ignoreReferences(args);
return format_reply(UiOption.Ignore, reply);
}
static boolean Query(String[] args)
throws Exception
{
DuccServiceApi api = new DuccServiceApi(null);
IServiceReply reply = api.query(args);
return format_reply(UiOption.Query, reply);
}
static void Help()
{
DuccServiceApi api = new DuccServiceApi(null);
api.help();
System.exit(1);
}
static UiOption getVerb(String[] args)
{
// need to scan args for the verb, and insure only one verb
UiOption[] verbs = {
UiOption.Register,
UiOption.Modify,
UiOption.Start,
UiOption.Stop,
UiOption.Query,
UiOption.Unregister,
UiOption.Observe,
UiOption.Ignore,
UiOption.Enable,
UiOption.Disable
};
List<UiOption> check = new ArrayList<UiOption>();
UiOption reply = UiOption.Help;
for ( String s : args ) {
if ( ! s.startsWith("--") ) continue;
s = s.substring(2);
if ( s.equals("help") ) Help();
for ( UiOption v : verbs ) {
if ( s.equals(v.pname() ) ) {
reply = v;
check.add(v);
}
}
}
if ( check.size() > 1 ) {
String msg = "";
for ( UiOption o : check ) {
msg = msg + " " + o;
}
throw new IllegalArgumentException("Duplicate service actions: " + msg );
}
return reply;
}
/*
* DuccServiceApi <options>
* Where options:
* -r --register <properties>
* -u --unregister <id>
* -q --query <id>
* --start <id>
* --stop <id>
* -m --modify <properties>
* -f --fetch <id>
*
* Properties file:
* type = UIMA-AS | Custom
* endpoint = <amq endoint> # if UIMA-AS
* broker = <broker url> # if UIMA-AS
* user = userid
*
* Service is identified as:
* type:endpoint:broker
* e.g. UIMA-AS@FixedSleepAE@tcp://node1
*/
/**
* This is the main entrypoint, used by the executable jars and callable directly from the command line.
*
* If the invocation is successful, the process exits with return code 0. Otherwise, it exit
* with return code 1.
*
* @param args arguments as described in the <a href="/doc/duccbook.html#DUCC_CLI_SERVICES">DUCC CLI reference.</a>
*/
public static void main(String[] args)
{
boolean rc = false;
try {
switch ( getVerb(args) ) {
case Register:
rc = Register(args);
break;
case Unregister:
rc = Unregister(args);
break;
case Start:
rc = Start(args);
break;
case Stop:
rc = Stop(args);
break;
case Observe:
rc = ObserveReferences(args);
break;
case Ignore:
rc = IgnoreReferences(args);
break;
case Enable:
rc = Enable(args);
break;
case Disable:
rc = Disable(args);
break;
case Modify:
rc = Modify(args);
break;
case Query:
rc = Query(args);
break;
default:
System.out.println("Missing service action (register, unregister, start, stop, modify, observe_refrences, ignore_references, enable, disable, or query)");
System.exit(1);
}
} catch (Throwable e) {
System.out.println("Service call failed: " + e);
Throwable t = e;
while ((t = t.getCause()) != null) {
System.out.println(" ... " + t);
}
for (String arg : args) {
if (arg.equals("--debug")) {
e.printStackTrace();
break;
}
}
System.exit(1);
}
System.exit(rc ? 0 : 1);
}
}