eXept Software AG Logo

Smalltalk/X Webserver

Documentation of class 'StandaloneStartup':

Home

Documentation
www.exept.de
Everywhere
for:
[back]

Class: StandaloneStartup


Inheritance:

   Object
   |
   +--StandaloneStartup
      |
      +--StandaloneStartupHeadless
      |
      +--WebServerStartup

Package:
stx:libbasic
Category:
System-Support
Version:
rev: 1.171 date: 2024/03/18 14:34:51
user: stefan
file: StandaloneStartup.st directory: libbasic
module: stx stc-classLibrary: libbasic

Description:


When smalltalk is started as IDE (stx), the show starts in Smalltalk>>start.
In contrast, when a standAlone app is linked, 
the show starts in the startup class's start method.

This class is an abstract, subclassable template for a standalone GUI-application's startup.

For your own stand alone programs, define a subclass of this, 
and redefine the #main: method there.
(of course, the other methods can also be redefined.)

copyright

COPYRIGHT (c) 2006 by eXept Software AG All Rights Reserved This software is furnished under a license and may be used only in accordance with the terms of that license and with the inclusion of the above copyright notice. This software may not be provided or otherwise made available to, or used by, any other person. No title to or ownership of the software is hereby transferred.

howToDealWithMultipleApplicationInstances

please read the comment in the corresponding ApplicationModel class-documentation method.

whichMethodsToRedefine

main:argv that's the actual program. suppressRCFileReading false here; redefine to return true, to disable the rc-file reading. you loose the chance of configuration, but lock the user out from any access to any smalltalk (if you have a user-phobia) allowDebugOption false here; redefine to return true, to enable the --debug startup option. if disabled, you loose the chance of debugging, but lock the user out from any access to any smalltalk allowScriptingOption false here; redefine to return true, to enable the --scripting startup option. if disabled, you loose the chance of remote control, but lock the user out from any access to any smalltalk

Class protocol:

debugging support
o  dumpCoverageInformation
if the --coverage argument was given, dump that information now.
This is invoked via an exit block, when smalltalk terminates

Usage example(s):

     self dumpCoverageInformation

o  handleCoverageMeasurementOptionsFromArguments: argv
handle the coverage measurement command line argument:
--coverage
[+/-]package: <package-pattern> ... do / do not measure in package (regex match)
[+/-]class: <class-pattern> ... do / do not measure in class (regex match, including nameSpace)
[+/-]method: <className>#<methodName> ... do / do not measure in method

adds instrumentation code to all selected methods.

Usage example(s):

 self handleCoverageMeasurementOptionsFromArguments:#('foo' '--coverage' '+package:' 'expeccoNET:*' '-class:' 'ExpeccoNET::ML' 'ExpeccoNET::LicenseString'  )
 self handleCoverageMeasurementOptionsFromArguments:#('foo' '--coverage' '+package:' 'stx:*')
 self handleCoverageMeasurementOptionsFromArguments:#('foo' '--coverage' '+package:' 'stx:libtool*')
 self handleCoverageMeasurementOptionsFromArguments:#('foo' '--coverage' '+class:' 'Tools::*' '-class:' 'Tools::StringSearchTool' )
 self handleCoverageMeasurementOptionsFromArguments:#('foo' '--coverage' '+class:' 'Tools::*Browser*'  )
 self handleCoverageMeasurementOptionsFromArguments:#('foo' '--coverage' '+method:' 'String#at:put:' 'String#at:')

defaults
o  allowCoverageMeasurementOption
enable/disable the --measureCoverage startup options.
The default is false, so standAlone apps do not support coverage measurements by default.
Can be redefined in subclasses to enable it
(but will need the libcomp and possibly the programming/oom packages to be present)

o  allowDebugOption
enable/disable the --debug startup option.
Can be redefined in subclasses to enable it

o  allowScriptingOption
enable/disable the --scripting startup option.
Can be redefined in subclasses to enable it

o  suppressRCFileReading
enable/disable the rc-file reading (and also the --rcFileName option).
If suppressed, there is no chance to interfere with the startup.
Can be redefined in subclasses to disable it

helpers
o  printInfo: msg
print an informal message using the logger

o  redirectStandardStreams
redirect all output for Transcript to stderr

o  verbose
true iff the program was started with --verbose flag

o  verboseInfo: msg
output some message, but only if the program was started with --verbose

initialization
o  initialize
Verbose := true.

misc ui support
o  iconInBrowserSymbol
( an extension from the stx:libtool package )
the browser will use this as index into the toolbariconlibrary

multiple applications support
o  applicationRegistryPath
the key under which this application stores its process ID in the registry
as a collection of path-components.
i.e. if #('foo' 'bar' 'baz') is returned here, the current applications ID will be stored
in HKEY_CURRENT_USER\Software\foo\bar\baz\CurrentID.
(would also be used as a relative path for a temporary lock file under unix).
Used to detect if another instance of this application is already running.

** This method must be redefined in concrete classes (subclassResponsibility) **

o  applicationUUID
answer an application-specific unique uuid.
This is used as the name of some exclusive OS-resource, which is used to find out,
if another instance of this application is already running.
Under win32, a mutex is used; under unix, an exclusive file in the tempDir could be used.
If redefined, please return a real UUID (i.e. UUID fromString:'.....') and not a string or
similar possibly conflicting identifier.
You can paste a fresh worldwide unique id via the editor's more-misc-paste UUID menuFunction.

** This method must be redefined in concrete classes (subclassResponsibility) **

o  shouldReuseRunningApplication
answer true, if an already running application instance should be re-used

multiple applications support-helpers
o  applicationRegistryEntry
retrieve the registry entry in which (if present), any currently running application
has left its process ID

o  applicationRegistryRootKey
retrieve the registry root key
required by #applicationRegistryEntry

for e.g. some applications are user specific like expecco -> 'HKEY_CURRENT_USER'
but some are system/server specific like AIDYMO -> 'HKEY_LOCAL_MACHINE'

o  checkForAndExitIfAnotherApplicationInstanceIsRunning
if another instance of this application is running,
send it an openFile command for my file-argument, and exit.
(i.e. the already running app gets a (processOpenPathCommand:argument) message
to ask it to open up another window).

o  confirmOpenNewApplicationInstance

o  currentBinaryPathKeyInRegistry

o  currentIDKeyInRegistry

o  getCurrentBinaryPathFromRegistry
used to check if the binary of the running instance and the attaching is the same,
if not do not attach to other version or even other installation

Usage example(s):

        ExpeccoStartup writeCurrentBinaryPathIntoRegistry.
        ExpeccoStartup getCurrentBinaryPathFromRegistry.
        self assert:OperatingSystem pathOfSTXExecutable = ExpeccoStartup getCurrentBinaryPathFromRegistry.

o  getCurrentIDFromRegistry
|hWnd externalAddress|
hWnd := DapasXStartup getCurrentIDFromRegistry.
hWnd isEmptyOrNil ifTrue:[^ self halt.].
hWnd := hWnd asInteger.
externalAddress := ExternalAddress newAddress: hWnd.
Display raiseWindow:externalAddress.
Display setForegroundWindow:externalAddress

o  getIDOfRunningApplicationFromRegistryEntry

o  isAnotherApplicationInstanceRunning
answer true, if another instance of myself is currently running.
For now, it only works under win32, because it uses the underlying mutex mechanism.

o  processStartupOfASecondInstance
This is executed when I have been started as a second instance of an already running application.
If I can get the currentID (i.e. windowID) of the first one and there is a command line argument with a file,
send a message (processOpenPathCommand:argument) to the main window of the already running application, to ask it for another window.
If the currentID is unknown, ask if the user wants to open a new instance of the application anyway.
Return true if the first instance has been notified, and this second instance should exit.

o  releaseApplicationMutex

o  sendCommand: message toWindowId: aWindowId
use the event send mechanism to forward a command to the already running application

o  sendOpenPathCommand: pathName toWindowId: aWindowId
use the event send mechanism to forward an open-Path command to the already running application

o  writeCurrentBinaryPathIntoRegistry
used to check if the binary of the running instance and the attaching is the same,
if not do not attach to other version or even other installation

Usage example(s):

        ExpeccoStartup writeCurrentBinaryPathIntoRegistry.
        ExpeccoStartup getCurrentBinaryPathFromRegistry.
        self assert:OperatingSystem pathOfSTXExecutable = ExpeccoStartup getCurrentBinaryPathFromRegistry.

o  writeCurrentIDIntoRegistry: currentID
| currentID returnedCurrentID |
currentID := 999.
DapasXStartup writeCurrentIDIntoRegistry: currentID.
returnedCurrentID := DapasXStartup getCurrentIDFromRegistry.
self assert: currentID = returnedCurrentID asNumber.

queries
o  applicationName
used in verbose messages - can/should be redefined in subclasses

o  commandLineArguments

o  isAbstract
Return if this class is an abstract class.
True is returned here for myself only; false for subclasses.
Abstract subclasses must redefine this again.

o  isBrowserStartable
return true, if this is an application class,
which can be started from the browser

o  keepSplashWindowOpen
if true is returned here, the splashWindow is not closed and will be still open
when the main: method is invoked. This allows for plugin-loads etc. to be shown in the
splash screen. However, my subclass's main: has to make sure that the splashScreen is closed.
(calling hideSplashWindow)
The default is false here which means that the splashWindow will be already closed when the
subclasses main: is invoked.

o  patchesDirectory
answer a directory containing patches.
The directory needs not to be present.

o  startupFilename
used in verbose messages - can/should be redefined in subclasses.
Only return a basename here.

Usage example(s):

     ExpeccoStartup startupFilename -> 'expeccoStart.rc'

startup
o  handleRCFileOptionsFromArguments: argv
handle rc-file command line arguments:
--rcFileName ......... define a startup rc-file
(defaults to <appname>Start.rc)

o  handleScriptingOptionsFromArguments: argv
handle scripting command line argument:
--scripting portNr ... start a scripting server on port (or default, if missing)
--allowHost host ..... add host to the allowed scripting hosts

o  loadPatch: fileName

o  loadPatches
load all patches in the application's patches dir

o  loadPatchesMatching: aGlobString
load the patches in the application's patches dir.
If aGlobString is not empty or nil, only patches matching the glob
pattern are loaded. E.g. '[0-9]*.chg'

o  loadRemainingClassLibraries
Windows only.
To speedup startup, we did not load all dll's (only a subset of non-GUI dll's is present).
Now, load all skipped libs (the ones marked with '*') from modules.stx.

o  possiblyCheckForNewPatchesOnServer
to be redefined in concrete applications: check for patches on a server

o  removeDebugger

o  removeInspector

o  removeLauncher

o  setupSmalltalkFromArguments: argv
handle common command line arguments:
--help ............... print usage and exit
--verbose ............ be verbose during startup
--logLevel lvl ....... set log level (also -lV)
--logFile fn ......... set log file (also -lF)
--logColor bool ...... enable/disable log colors (also -lC)
--debug .............. enable debugger & inspector
--rcFileName ......... define a startup rc-file
(defaults to <appname>Start.rc)
--scripting portNr ... start a scripting server
--allowHost host ..... add host to the allowed scripting hosts

o  setupToolsForDebug
self verboseInfo:('debug enabled - CTRL-C brings you into a debugger.').

o  setupToolsForNoDebug

o  start
this is the default initial entry into a standalone program.
It checks for any remaining shared libraries/packages which need to be
loaded, looks for any patch-files to be applied
and then enters into main.
On systems, which allow for the same app to be started for multiple documents
(i.e. windows), when clicking on a document),
first check if there is an already running application and tell it to open
a window for the new document.

Usage example(s):

to speedup startup, we did not load all dll's (only a subset of non-GUI dll's is present).

o  startStartBlockProcess

o  stxModulesFilename
answer the Filename of modules.stx

o  usage
Stderr nextPutLine:''.

o  usageAndExitWith: exitCode
show the usage message, then exit with given exitCode

startup-to be redefined
o  additionalArgumentsFromRegistry
can be redefined to fetch and return additional arguments from the registry
(or other .ini file). These are added to the beginning of the command line arguments.

o  isHeadless
this is invoked early by Smalltalk>>mainStartup, to ask if I like to
have a Display or if I am a non-GUI headless application.

Redefine in subclass, if your application is a non-GUI application

o  main
self main
self main:#('--info')

o  main: argv
a typical main: looks like (in a subclass):

** This method must be redefined in concrete classes (subclassResponsibility) **



ST/X 7.7.0.0; WebServer 1.702 at 20f6060372b9.unknown:8081; Sat, 21 Dec 2024 15:56:18 GMT