java.lang.Object
net.i2p.router.web.ShellService
All Implemented Interfaces:
ClientApp

public class ShellServiceextends Object implements ClientApp
Alternative to ShellCommand for plugins based on ProcessBuilder, which manages a process and keeps track of it's state by maintaining a Process object.

Keeps track of the process, and reports start/stop status correctly on configplugins. When running a ShellService from a clients.config file, the user MUST pass -shellservice.name in the args field in clients.config to override the plugin name. The name passed to -shellservice.name should be unique to avoid causing issues. (https://i2pgit.org/i2p-hackers/i2p.i2p/-/merge_requests/39#note_4234) -shellservice.displayName is optional and configures the name of the plugin which is shown on the console. In most cases, the -shellservice.name must be the same as the plugin name in order for the $PLUGIN field in clients.config to match the expected value. If this is not the case, i.e. (-shellservice.name != plugin.name), you must not use $PLUGIN in your clients.config file.

The recommended way to use this tool is to manage a single forked app/process, with a single ShellService, in a single plugin.

When you are writing your clients.config file, please take note that $PLUGIN will be derived from the `shellservice.name` field in the config file args.

Works on Windows, OSX, and Linux.

  • Field Details

    • NAME_OPTION

      private static final String NAME_OPTION
      Option naming the service internally.
      See Also:
    • DISPLAY_NAME_OPTION

      private static final String DISPLAY_NAME_OPTION
      Option naming the service for display.
      See Also:
    • PLUGIN_DIR

      private static final String PLUGIN_DIR
      Directory the command is looked up in.
      See Also:
    • EQUALS_SPLIT

      private static final Pattern EQUALS_SPLIT
      Splits a command line argument on the equals sign.
    • _log

      private final Log _log
      Logger for the shell service.
    • _pb

      private final ProcessBuilder _pb
      Builder launching the external command.
    • _context

      private final I2PAppContext _context
      The app context.
    • _cmgr

      private final ClientAppManager _cmgr
      The manager notified of the state changes.
    • _commandPath

      private final String _commandPath
      The command line being run.
    • _errorLog

      private final File _errorLog
      File the command's errors are written to.
    • _outputLog

      private final File _outputLog
      File the command's output is written to.
    • _state

      private ClientAppState _state
      Current state of the service.
    • name

      private volatile String name
      Internal name of the service.
    • displayName

      private volatile String displayName
      Name of the service shown in the console.
    • _p

      private Process _p
      The running process, while started.
  • Constructor Details

    • ShellService

      public ShellService(I2PAppContext context, ClientAppManager listener, String[] args)
      Creates a ShellService from command-line args, validating the executable and setting up log files.
      Parameters:
      context - the application context supplying the log manager
      listener - the client app manager to notify of this app's state changes
      args - the command line arguments: the executable path first, then the arguments to pass to that executable
  • Method Details

    • trimArgs

      private ArrayList<String> trimArgs(String[] args)
      Extract the app process arguments, filtering out -shellservice options.
      Parameters:
      args - raw command-line arguments
      Returns:
      filtered argument list
    • changeState

      private void changeState(ClientAppState newState, String message, Exception ex)
      Changes the app state and notifies listeners.
      Parameters:
      newState - the new state
      message - the message for the listeners
      ex - the exception, null if none
    • changeState

      private void changeState(ClientAppState newState, String message)
      Changes the app state and notifies listeners.
      Parameters:
      newState - the new state
      message - the message for the listeners
    • startup

      public void startup() throws Throwable
      Determine if a ShellService corresponding to the wrapped application has been started yet. If it hasn't, attempt to start the process and notify the router that it has been started.
      Specified by:
      startup in interface ClientApp
      Throws:
      Throwable - on startup failure
    • isProcessStopped

      public boolean isProcessStopped()
      Determine if the process running or not.
      Returns:
      true if the Process is NOT running, false if the Process is running
    • isProcessRunning

      public boolean isProcessRunning()
      Determine if the process running or not.
      Returns:
      true if the Process is running, false if the Process is not running
    • shutdown

      public void shutdown(String[] args) throws Throwable
      Shut down the process by calling Process.destroy().
      Specified by:
      shutdown in interface ClientApp
      Parameters:
      args - generally null but could be stopArgs from clients.config
      Throws:
      Throwable - on shutdown failure
    • getState

      public ClientAppState getState()
      Query the state of managed process and determine if it is running or not. Convert to corresponding ClientAppState and return the correct value.
      Specified by:
      getState in interface ClientApp
      Returns:
      non-null
    • getName

      public String getName()
      The generic name of the ClientApp, used for registration, e.g. "console". Do not translate. Has a special use in the context of ShellService, must match the plugin name.
      Specified by:
      getName in interface ClientApp
      Returns:
      non-null
    • getDisplayName

      public String getDisplayName()
      The display name of the ClientApp, used in user interfaces. The app must translate.
      Specified by:
      getDisplayName in interface ClientApp
      Returns:
      non-null