0% found this document useful (0 votes)
21 views549 pages

SDK 2017 Doc User

Software development Kit for MSC 2017

Uploaded by

Gareth Vio
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views549 pages

SDK 2017 Doc User

Software development Kit for MSC 2017

Uploaded by

Gareth Vio
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

MSC Software Development Kit 2017

User's Guide
Corporate Europe, Middle East, Africa
MSC Software Corporation MSC Software GmbH
4675 MacArthur Court, Suite 900 Am Moosfeld 13
Newport Beach, CA 92660 81829 Munich, Germany
Telephone: (714) 540-8900 Telephone: (49) 89 431 98 70
Email: [Link]@[Link] Email: europe@[Link]

Japan Asia-Pacific
MSC Software Japan Ltd. MSC Software (S) Pte. Ltd.
Shinjuku First West 8F 100 Beach Road
23-7 Nishi Shinjuku #16-05 Shaw Tower
1-Chome, Shinjuku-Ku Singapore 189702
Tokyo 160-0023, JAPAN Telephone: 65-6272-0082
Telephone: (81) (3)-6911-1200 Email: [Link]@[Link]
Email: [Link]@[Link]

Worldwide Web
[Link]

Disclaimer
MSC Software Corporation reserves the right to make changes in specifications and other information contained in this document
without prior notice.
The concepts, methods, and examples presented in this text are for illustrative and educational purposes only, and are not intended
to be exhaustive or to apply to any particular engineering problem or design. MSC Software Corporation assumes no liability or
responsibility to any person or company for direct or indirect damages resulting from the use of any information contained herein.
User Documentation: Copyright  2016 MSC Software Corporation. All Rights Reserved.
This notice shall be marked on any reproduction of this documentation, in whole or in part. Any reproduction or distribution of this
document, in whole or in part, without the prior written consent of MSC Software Corporation is prohibited.
This software may contain certain third-party software that is protected by copyright and licensed from MSC Software suppliers.
Additional terms and conditions and/or notices may apply for certain third party software. Such additional third party software terms
and conditions and/or notices may be set forth in documentation and/or at [Link] (or
successor website designated by MSC from time to time).
MSC, Dytran, Marc, MSC Nastran, Patran, the MSC Software corporate logo, e-Xstream, Digimat, SimManager and Simulating
Reality are trademarks or registered trademarks of the MSC Software Corporation and/or its subsidiaries in the United States and/or
other countries.
NASTRAN is a registered trademark of NASA. LS-DYNA is a trademark or registered trademark of Livermore Software Technology
Corporation. FLEXlm and FlexNet Publisher are trademarks or registered trademarks of Flexera Software. All other trademarks are
the property of their respective owners.

Revision 0. June 6, 2016


SDK:2017:Z:Z:Z:DC-USR-PDF
SCA Framework SDK Introduction

Contents
1. Introduction ..................................................................................................................... 2
1.1. Organization of this manual .................................... 2
1.2. Source Code Examples ........................................... 2
2. SCA Architecture Overview ........................................................................................... 2
2.1. Interface Based Programming .................................... 3
2.2. SCA Interfaces and the IDL language ............................ 6
2.3. SCA Services ................................................... 6
2.4. SCA Components ................................................. 7
2.5. What is the SCA Kernel ......................................... 7
2.6. The SCA Framework .............................................. 8
2.7. Language support ............................................... 8
2.8. Platform support ............................................... 9
2.9. Summary ........................................................ 9
3. A SCA Hello World Application .................................................................................. 13
3.1. Introduction .................................................. 13
3.2. Define the Interfaces ......................................... 13
Include Guard .................................................... 14
Include Declarations ............................................. 14
Module Declarations .............................................. 15
Interface Declarations ........................................... 15
3.3. Define the Service ............................................ 15
Include Guard .................................................... 16
Include Declarations ............................................. 16
Module Declarations .............................................. 16
Service Declaration .............................................. 17
3.4. Define the Component .......................................... 17
Include Guard .................................................... 18
Include Declarations ............................................. 18
Component Declaration ............................................ 18
3.5. Generate the Implementation Files for the Service ............. 18
The genskeleton Command .......................................... 18
Adding the Required Functionality to the Skeletons ............... 19
Implementing the Service in C++ .................................. 19
Implementing the Service in JAVA ................................. 21
Implementing the Service in C# ................................... 21
Implementing the Service in Visual Basic ......................... 22
3.6. Building the component ........................................ 23
3.7. Creating a Client for the Service ............................. 24
Creating a C++ Client for the Service ............................ 24
Creating a JAVA Driver for the Service ........................... 26
Creating a C# Driver for the Service ............................. 27
Creating a Visual Basic Client for the Service ................... 29
Creating a Python Client for the Service ......................... 30
3.8. Summary ....................................................... 31
4. The IDL Language ........................................................................................................ 36
4.1. IDL Language Overview ......................................... 36
4.2. Source Files .................................................. 36
4.3. Lexical Conventions ........................................... 37
Comments ......................................................... 37
Identifiers ...................................................... 38
Keywords ......................................................... 38

1
SCA Framework SDK Introduction

Escaped Identifiers .............................................. 38


Constant Expressions ............................................. 41
4.4. Preprocessing ................................................. 42
4.5. SCA IDL Specification ......................................... 42
Grammar Notation ................................................. 42
IDL Specification ................................................ 43
4.6. Type Declaration .............................................. 43
Basic Types ...................................................... 45
User Constructed Types ........................................... 47
Template Types ................................................... 51
Aliases to Other Types ........................................... 53
Sequences versus Arrays .......................................... 54
4.7. Constant Declaration .......................................... 55
4.8. Modules, Name Lookup and Scoping .............................. 59
Module Declaration ............................................... 59
Name Lookup Rules ................................................ 60
Qualified Names .................................................. 60
Scoping Rules .................................................... 61
4.9. SCA Interface Declaration ..................................... 62
Interface Header ................................................. 63
Interface Inheritance Specification .............................. 63
Interface Body ................................................... 63
Operation Declaration ............................................ 64
Forward Declarations ............................................. 65
Interface Inheritance ............................................ 66
SCAIService Interface ............................................ 67
4.10. SCA Exception Declaration .................................... 68
4.11. Special SCA Framework Provided Types ......................... 69
4.12. SCA Services Declaration ..................................... 71
Service Options .................................................. 75
4.13. SCA Component Declaration .................................... 75
Component Options ................................................ 77
4.14. Running the IDL Compiler ..................................... 77
The IDL Compiler Command ......................................... 77
Compiler Processing Modes ........................................ 78
Location for Compiler Generated Files ............................ 78
The genskeleton command .......................................... 79
Appendix A: OMG IDL Specifications ............................................................................ 81
5. IDL to C++ Language Mapping ................................................................................... 88
5.1. Introduction .................................................. 88
5.2. Mapping for Identifiers ....................................... 89
5.3. Mapping for Modules ........................................... 89
5.4. Mapping for Basic Types ....................................... 90
5.5. Mapping for String Types ...................................... 90
5.6. Mapping for Enumerated Types .................................. 91
5.7. Mapping for Structures ........................................ 91
5.8. Mapping for Array Types ....................................... 92
Summary of array types ........................................... 92
Fixed size arrays ................................................ 92
Dynamic Arrays ................................................... 95
Mapping for Sequences ........................................... 105
Mapping for Vectors ............................................. 108
SCAVector Compared to SCASequence ............................... 109
5.9. Mapping for Maps ............................................. 109
5.10. Mapping for Type Aliases .................................... 110
5.11. Mapping for SCATypeCode ..................................... 111

2
SCA Framework SDK Introduction

5.12. Mapping for SCAAny .......................................... 112


The SCAAny class definition ..................................... 112
Creating new SCAAny values ...................................... 114
Inserting values into exiting SCAAny values ..................... 114
Extracting the value contained in a SCAAny ...................... 115
Assigning SCAAny values ......................................... 115
Interrogating the value contained in a SCAAny ................... 115
Miscellaneous SCAAny methods .................................... 116
Special SCAAny methods for Dynamic Arrays ....................... 116
Limitations in the SCAAny ....................................... 116
5.13. Mapping for SCAResult ....................................... 117
SCAResult class definition ...................................... 117
Creating new SCAResult values ................................... 118
Resetting the error code in a SCAResult value ................... 118
Adding parameters to a SCAResult value .......................... 119
Interrogating the contents of a SCAResult ....................... 119
Format a SCAResult Value ........................................ 119
SCAResult Logging ............................................... 120
Setting Inner SCAResult ......................................... 120
Apply Error Policy to SCAResult ................................. 121
Miscellaneous SCAResult methods ................................. 121
5.14. Mapping for Constants ....................................... 121
5.15. Mapping for Interfaces ...................................... 122
Mapping for Interface Smart Pointer Definition .................. 123
Mapping for Interface Abstract Base Class Definition ............ 124
Mapping for Interface Operations ................................ 124
Mapping Interface Operation Parameters .......................... 124
Using Smart Pointers ............................................ 126
5.16. Mapping for Exceptions ...................................... 127
SCAException class .............................................. 127
SCAUserException class .......................................... 128
SCASystemException class ........................................ 129
Mapping for IDL defined user exceptions ......................... 129
Special Rules for using SCA Exceptions in C++ ................... 130
5.17. Mapping for SCA Services .................................... 131
The inheritance form of implementation .......................... 132
The ServiceAccess interface ..................................... 135
The delegation form of implementation ........................... 137
Singleton Services .............................................. 138
Aggregation ..................................................... 139
5.18. Mapping for SCA Components .................................. 139
Embedded Components ............................................. 139
6.1. Introduction ................................................. 145
6.2. Mapping for Identifiers ...................................... 146
6.3. Mapping for Modules .......................................... 146
6.4. Mapping for Basic Types ...................................... 146
6.5. Mapping for Unsigned Data Types .............................. 147
6.6. Mapping for String Types ..................................... 148
6.7. Mapping for Enumerated Types ................................. 149
6.8. Mapping for Structures ....................................... 149
6.9. Mapping for Arrays ........................................... 149
Fixed size arrays ............................................... 149
Dynamic Arrays .................................................. 151
6.10. Mapping for Sequences ....................................... 152
6.11. Mapping for Vectors ......................................... 153
6.12. Mapping for Maps ............................................ 153
6.13. Mapping for Type Aliases .................................... 154

3
SCA Framework SDK Introduction

6.14. Mapping for SCATypeCode ..................................... 155


6.15. Mapping for SCAAny .......................................... 155
The SCAAny class definition ..................................... 156
Creating new SCAAny values ...................................... 157
Inserting values into exiting SCAAny values ..................... 158
Extracting the value contained in a SCAAny ...................... 159
Miscellaneous SCAAny methods .................................... 160
6.16. Mapping for SCAResult ....................................... 160
SCAResult class definition ...................................... 160
Creating new SCAResult values ................................... 162
Resetting the error code in a SCAResult value ................... 162
Adding parameters to a SCAResult value .......................... 162
Interrogating the contents of a SCAResult ....................... 162
Miscellaneous SCAResult methods ................................. 163
6.17. Mapping for Constants ....................................... 163
6.18. Mapping for Interfaces ...................................... 163
Mapping for Interface Operations ................................ 164
Mapping for Interface Parameters ................................ 164
6.19. Mapping for Exceptions ...................................... 165
SCAException interface .......................................... 165
SCAUserException class .......................................... 166
SCASystemException class ........................................ 166
Mapping for IDL defined user exceptions ......................... 167
The IDL raises clause ........................................... 168
6.20. Mapping for SCA Services .................................... 168
The inheritance form of implementation .......................... 170
The ServiceAccess interface ..................................... 172
The delegation form of implementation ........................... 173
Singleton Services .............................................. 173
Aggregation ..................................................... 173
6.21. Mapping for SCA Components .................................. 173
Embedded Components ............................................. 173
6.22. SCA Framework / JVM Interaction ............................. 173
Java Virtual Machine Initialization ............................. 173
The [Link] archive ........................................ 174
7. IDL to .NET Language Mapping ................................................................................ 176
7.1. Introduction ................................................. 176
7.2. Mapping for Identifiers ...................................... 177
7.3. Mapping for Modules .......................................... 177
7.4. Mapping for Basic Types ...................................... 178
7.5. Mapping for String Types ..................................... 179
7.6. Mapping for Enumerated Types ................................. 179
7.7. Mapping for Structures ....................................... 179
7.8. Mapping for Arrays ........................................... 180
Fixed size arrays ............................................... 180
Dynamic Arrays .................................................. 181
7.9. Mapping for Sequences ........................................ 181
7.10. Mapping for Vectors ......................................... 182
7.11. Mapping for Maps ............................................ 182
7.12. Mapping for Type Aliases .................................... 183
7.13. Mapping for SCATypeCode ..................................... 184
7.14. Mapping for SCAAny .......................................... 184
The SCAAny class definition ..................................... 185
Creating new SCAAny values ...................................... 186
Inserting values into existing SCAAny value ..................... 187
Extracting the value contained in a SCAAny ...................... 187

4
SCA Framework SDK Introduction

Miscellaneous SCAAny methods .................................... 188


7.15. Mapping for SCAResult ....................................... 189
SCAResult class definition ...................................... 189
Creating new SCAResult values ................................... 190
Resetting the error code in a SCAResult value ................... 191
Adding parameters to a SCAResult value .......................... 191
Interrogating the contents of a SCAResult ....................... 191
Format a SCAResult Value ........................................ 192
SCAResult Logging ............................................... 192
Setting Inner SCAResult ......................................... 192
Apply Error Policy to SCAResult ................................. 192
Miscellaneous SCAResult methods ................................. 193
7.16. Mapping for Constants ....................................... 193
7.17. Mapping for Interfaces ...................................... 193
Mapping for Interface Operations ................................ 194
Mapping for Interface Parameters ................................ 194
7.18. Mapping for Exceptions ...................................... 194
SCAException interface .......................................... 194
SCAUserException class .......................................... 195
SCASystemException class ........................................ 195
Mapping for IDL defined user exceptions ......................... 196
The IDL raises clause ........................................... 196
7.19. Mapping for SCA Services .................................... 197
The inheritance form of implementation .......................... 198
Implementation for subservice classes ........................... 200
Creating instances of subservice classes ........................ 201
The ServiceAccess interface ..................................... 201
The delegation form of implementation ........................... 202
Singleton Services .............................................. 203
Aggregation ..................................................... 203
7.20. Mapping for SCA Components .................................. 203
Embedded Components ............................................. 203
8. IDL to Python Language Mapping ............................................................................. 205
8.1. Introduction ................................................. 205
8.2. Mapping for Identifiers ...................................... 206
8.3. Mapping for Modules .......................................... 206
8.4. Mapping for Basic Types ...................................... 207
8.5. Mapping for Enumerated Types ................................. 208
8.6. Mapping for Structures ....................................... 209
8.7. Mapping for Arrays ........................................... 211
Fixed size arrays ............................................... 211
Dynamic Arrays .................................................. 212
8.8. Mapping for Sequences ........................................ 212
8.9. Mapping for Vectors .......................................... 212
8.10. Mapping for Maps ............................................ 212
8.11. Mapping for Type Aliases .................................... 213
8.12. Mapping for TypeCode ........................................ 213
8.13. Mapping for SCAAny .......................................... 214
The SCAAny class definition ..................................... 214
Creating new SCAAny values ...................................... 215
Inserting values into existing SCAAny values .................... 216
Extracting the value contained in a SCAAny ...................... 217
Miscellaneous SCAAny methods .................................... 217
8.14. Mapping for SCAResult ....................................... 218
SCAResult class definition ...................................... 218
Creating new SCAResult values ................................... 219

5
SCA Framework SDK Introduction

Resetting the error code in a SCAResult value ................... 219


Adding parameters to a SCAResult value .......................... 220
Interrogating the contents of a SCAResult ....................... 220
Miscellaneous SCAResult methods ................................. 221
8.15. Mapping for Constants ....................................... 221
8.16. Mapping for Interfaces ...................................... 221
Mapping for Interface Operations ................................ 222
Special Interface Attributes .................................... 222
Mapping for Interface Parameters ................................ 222
Use of getInterface in Python ................................... 224
Implementing SCA Interfaces ..................................... 224
8.17. Mapping for Exceptions ...................................... 225
SCAException exception .......................................... 226
Mapping for other exception types ............................... 226
The IDL raises clause ........................................... 227
8.18. Mapping for SCA Services .................................... 228
8.19. Mapping for SCA Components .................................. 228
8.20. The SCA Module .............................................. 228
8.21. Accessing IDL Type Definitions from Python .................. 228
8.22. Running Python Scripts ...................................... 231
Running Scripts with the ScriptBroker ........................... 231
Running Scripts from the command line ........................... 232
9. Messages and Internationalization .............................................................................. 234
9.1. Introduction ................................................. 234
9.2. Message Files ................................................ 234
Locale String ................................................... 234
Message File Naming Convention .................................. 234
File Search Order ............................................... 235
Message File Format ............................................. 235
Text Formatting ................................................. 236
Sample1: English Message File .................................. 239
Sample2: German Message File ................................... 240
9.3. Text Translation Service ..................................... 240
SCA::Framework::SCAITextTranslationFactory Interface ............ 240
SCA::Framework::SCAITextTranslationSettings Interface ........... 241
Using the Text Translation Service .............................. 249
Language Support Files .......................................... 250
10. Error Handling .......................................................................................................... 254
10.1. Introduction ................................................ 254
10.2. Using SCA Exceptions for Error Handling ..................... 255
SCA Exception Hierarchy ......................................... 257
SCA Framework provided Exceptions ............................... 257
Exception API ................................................... 260
Exception Propagation Rules ..................................... 260
Recommended usage of SCA Exceptions ............................. 262
Complete Exception Error Handling Example for a SCA Service ..... 262
10.3. Using SCAResult for Error Handling .......................... 265
Introduction .................................................... 265
The SCAResult data contents ..................................... 266
Overview of using the SCAResult for Error Handling .............. 267
Registering Message Tables ...................................... 268
Formatting a SCAResult value .................................... 269
Complete SCAResult Error Handling Example for a SCA Service ..... 270
Use of SCAResult values in the client ........................... 273
10.4. MessageDispatcher Service ................................... 275
SCA::Framework::SCAIMsgTableManager Interface ................... 276

6
SCA Framework SDK Introduction

SCA::Framework::SCAIMsgListenerManager Interface ................ 278


SCA::Framework::SCAIMessageDispatcher Interface ................. 279
SCA::Framework::SCAIMessageListener Interface ................... 281
Message Listener example using SCAServiceObjectImpl template .... 282
Message Listener example using a Logger Service Example ......... 284
10.5. SCA Error Manager ........................................... 289
Error Manager Settings in SCA Kernel Configuration File ......... 289
10.6. Error Policy Manager Service ................................ 290
SCA::Framework::SCAIErrorPolicyManager Interface ................ 291
10.7. Signal Catchers in SCA Framework ............................ 292
C++ Signal Action Handlers ...................................... 292
.NET Exception Handlers ......................................... 293
10.8. SCAException throwit() Method ............................... 294
10.9. Wrapping of SCAResult and SCAException ...................... 294
C++ API for Wrapping ............................................ 295
.NET API for Wrapping ........................................... 295
10.10. SCAException and SCAResult Logging ......................... 295
10.11. Call Tracing ............................................... 295
10.12. C++ Error Manager API Reference ............................ 296
SCA::IErrorManager Interface .................................... 296
SCA::ISignalAction Interface .................................... 300
SCA::ErrorManagerFactory Class .................................. 301
10.13. .NET Error Manager API Reference ........................... 301
[Link] Interface ..................................... 301
[Link] Interface .................................. 305
[Link] Class ................................... 306
11. Multi-Threaded Applications .................................................................................... 308
11.1. Introduction ................................................ 308
11.2. Thread Safety ............................................... 308
SCA Framework Synchronization Primitives ........................ 308
Kernel Thread Safety Configuration Options ...................... 312
11.3. Threading Infrastructure .................................... 312
11.4. Testing Multi-Threaded Services ............................. 312
SCA::Framework::SCAIMultiThreadBatchTest Interface Reference .... 313
11.5. Sample Multi-Threaded Application ........................... 314
12. Library Metadata and Versioning ............................................................................. 322
12.1. Introduction ................................................ 322
Default Metadata Provided by the Build System ................... 322
User Provided Metadata with BUILDINFO_xxx Construction Variables 323
12.2. Versioning of SCA Components ................................ 324
Mechanism for Specifying the Version Numbers .................... 324
Service Version Table ........................................... 326
Runtime Service Version Checking ................................ 328
Managing the XML Service Version Tables ......................... 329
12.3. Versioning of Normal Shared Libraries ....................... 331
Versioning of Exported Symbols in the Shared Libraries .......... 331
Example: ........................................................ 332
LIBS and LIBS2 Construction Variable Processing ................. 335
12.4. Extracting Library Metadata Information ..................... 336
Using scautil ................................................... 336
Programmatically within the component ........................... 337
Using SCAIServiceInfo interface ................................. 338
Using SCAIComponentInfo Interface ............................... 340
Using External Manifest Utility (versioninfo) ................... 341
13. Configuring and Using the SCA Kernel ................................................................... 343

7
SCA Framework SDK Introduction

13.1. Introduction ................................................ 343


13.2. Initializing and Terminating the Kernel ..................... 343
SCA Kernel Initialization API ................................... 343
SCA Kernel Termination API ...................................... 344
Examples of Configuring the SCA Kernel .......................... 345
13.3. Kernel Configuration Variables .............................. 347
13.4. Kernel Configuration File ................................... 349
Default Configuration File Location ............................. 351
13.5. Runtime Access to Configuration Variables ................... 351
13.6. Changing the Prefix for Environement Variable Names ........ 352
13.7. Building Applications using the SCA Kernel .................. 352
13.8. Running Applications using the SCA Kernel ................... 353
13.9. The SCA Services Catalog .................................... 355
SCASCons Build options for catalog processing ................... 355
Catalog Configuration Options ................................... 355
Service Catalog Precedence Rule for Duplicate Entries ........... 355
Sample Service Catalog File ..................................... 356
13.10. Other Configuration Files .................................. 356
IDL Type Definitions Files ...................................... 356
Message Files ................................................... 356
Language Support Files .......................................... 356
13.11. Service Manager ............................................ 357
SCA::Framework::SCAIServiceProvider Interface Reference ......... 357
SCA::Framework::SCAIKernelInfo Interface ........................ 357
SCA::Framework::SCAIServiceCatalog Interface .................... 359
13.12. Shared Library Manager ..................................... 360
SCA::Framework::SCAISharedLibraryManager Interface Reference .... 360
Library loading logic ........................................... 362
Library Release Queue ........................................... 363
SharedLibraryManager example .................................... 364
13.13. Introduction ............................................... 367
13.14. XML Parser ................................................. 367
DOM Parser Interfaces ........................................... 368
DOM Parser Example .............................................. 372
SAX Parser Interfaces ........................................... 374
SAX Parser Example .............................................. 378
XSLT Processor Interfaces ....................................... 380
13.15. Regular Expression Facility ................................ 382
SCA::RegExp::SCAIRegExp Interface ............................... 382
SCA::RegExp::SCAIRegExpFactory Interface ........................ 385
Regular Expression Example ...................................... 386
13.16. System Utilities ........................................... 388
SCA::SystemUtils::SCAIFileUtils Interface ....................... 388
SCA::SystemUtils::SCAIOSUtils Interface ......................... 395
SCA::Util::SystemUtils::SCAIPaths Interface ..................... 398
SCA::Util::SystemUtils::SCAIPathUtils Interface ................. 402
System Utils example ............................................ 407
13.17. Stream I/O Facility ........................................ 409
SCA::Framework::SCAIStream Interface ............................ 409
SCA::Framework::SCAIInStream Interface .......................... 409
SCA::Framework::SCAIOutStream Interface ......................... 410
SCA::Framework::SCAIStreamIOFactory Interface ................... 410
13.18. Timer Service .............................................. 411
SCA::Util::Timer::SCAITimerFactory Interface .................... 411
SCA::Util::Timer::SCAITimer Interface Reference ................. 411
Public Member Functions ......................................... 411
Detailed Description ............................................ 412

8
SCA Framework SDK Introduction

Member Function Documentation ................................... 412


Timer Service Example ........................................... 413
14. SCA Utility Program and Testing Components........................................................ 416
14.1. Introduction ................................................ 416
14.2. The SCA Utility Program ..................................... 416
Print the help message .......................................... 417
Testing Kernel Initialization ................................... 417
Running a Batch Test ............................................ 417
Run a Script .................................................... 417
Test Loading of a Shared Library ................................ 417
Query SCA Kernel Information .................................... 418
Query Shared Library Build Information .......................... 418
14.3. Testing of SCA components ................................... 419
SCA::Framework::SCAIBatchTest Interface Reference ............... 419
Running Tests Manual ............................................ 419
Running Tests with the Build System ............................. 420
Setting up Test Aliases ......................................... 421
Specifying when Tests run by Default ............................ 421
Running Test Using a SCA Test Component ......................... 422
Testing Using a Program ......................................... 422
Testing Using Python Script ..................................... 422
Using a fixup Routine ........................................... 423
Using the Preprocessor on the Baseline Text ..................... 424
Performing Setup and Clean Operations ........................... 425
Special Construction Variables used by the TestRun Command ...... 426
15. SCASCons Build System.......................................................................................... 428
15.1. Configuring the Build System ................................ 428
Construction Variables .......................................... 428
Directory Trees Processed by the Build System ................... 429
Configuration files ............................................. 432
Setting up the Build System in a New Source Tree ................ 435
Setting up your Runtime Environment for the Build System ........ 436
The SCons Construction Environment .............................. 436
Modifying Construction Variables in the SConscript File ......... 437
Commonly Used Environment Routines .............................. 439
Microsoft Visual Studio Projects ................................ 440
15.2. Running the Build ........................................... 441
Build Tasks ..................................................... 441
SCons Command ................................................... 441
Running SCons from a Subdirectory ............................... 441
Phases of the Build Process ..................................... 442
Removing Files Created by the Build ............................. 443
SCons Debugging Options ......................................... 443
Selecting Debug and Optimize builds ............................. 443
17. Introduction............................................... 446
17.2 Logging Filters .............................................. 446
17.3 SCA Framework Provided Logging Listeners................... 446
StdoutListener .................................................. 446
FileLogListener ................................................. 447
SysLogListener .................................................. 447
17.4. Examples of Listener Settings in SCA Kernel Configuration File
448
17.5. Logger Service API .......................................... 448
SCA::Framework::Logger::SCAILogger Interface .................... 448
SCA::Framework::Logger::SCAILogListener Interface ............... 453
Example of Adding a Custom Log Listener ......................... 454

9
SCA Framework SDK Introduction

17.6. Example of Logging Using the Logger Service ................. 457


17.7. C++ Logging Macros .......................................... 457
18. Event Manager Service ............................................................................................. 460
18.1. Introduction ................................................ 460
18.2. Event Manager Features ...................................... 461
Multiple Thread Support ......................................... 461
Logging ......................................................... 461
Domains ......................................................... 461
Channels ........................................................ 461
Events .......................................................... 462
Listeners ....................................................... 462
18.3. Registering Listeners ....................................... 462
18.4. Publishing/Posting Events ................................... 464
Publishing a Synchronous Event .................................. 464
Posting an Asynchronous Event (default mode) .................... 465
Posting an Asynchronous Event in the Dedicated Asynchronous Event
Thread .......................................................... 466
18.5. Event Manager Domain [Link] .................... 467
18.6. Miscellaneous Event Manager Data Structures ................. 468
18.7. SCA::Framework::ListenerFilter Struct Reference ............. 469
18.8. SCA::Framework::SCAEvent Struct Reference ................... 470
18.9. SCA::Framework::SCAIEventListener Interface Reference ....... 470
18.10. SCA::Framework::SCAIEventManager Interface Reference ....... 471
19. SCA Plug-in for Visual Studio ................................................................................. 482
19.1. Setup Requirements......................................... 482
Installing the plug-in .......................................... 482
The SCA_TOOLS environment variable .............................. 482
Merge Tool ...................................................... 482
Configuration errors ............................................ 483
19.2. New Project Dialog Box..................................... 484
19.3. The Source Tree and its relationship to the Visual Studio
project 485
19.4. SCA Component.............................................. 487
19.5. SCA Application............................................ 489
19.6. The rewriting of the vcproj and [Link] files...... 489
19.7. 64-bit Windows issues...................................... 491
19.8. Visual Studio IDE Enhancements............................. 491
Running genskeleton ............................................. 491
Automating the additions of code in CDL, SDL and IDL files ...... 492
CDL snippet ..................................................... 493
SDL snippets .................................................... 493
IDL snippets .................................................... 494
20. Configuration Manager Service ................................................................................ 497
20.1. Introduction ................................................ 497
20.2. Configuration XML File ...................................... 497
20.3. Configuration Variables ..................................... 498
Naming Convention ............................................... 498
Supported Data Types ............................................ 499
Variable Attributes ............................................. 499
Variable Substitution ........................................... 499
20.4. Support for Named Configurations ............................ 499
20.5. Creating OS Environment Variables from Configuration Variables
499
20.6. Configuration Manager Service API ........................... 501
SCA::Framework::SCAIConfigurationManager Interface .............. 501

10
SCA Framework SDK Introduction

SCA::Framework::SCAIConfiguration Interface ..................... 502


SCAResult Errors ................................................ 512
Explanation of Configuration Merge Options (ConfigMergeType) .... 513
20.7. Multi Thread/Process Safety ................................. 513
Write Counter ................................................... 513
File Locking .................................................... 514
Lock File Cleanup ............................................... 514
Usage Example ................................................... 514
21. Task Manger ............................................................................................................. 522
21.1. Introduction ................................................ 522
21.2. Creating task objects ....................................... 522
SCAITask interface .............................................. 522
SCAIBaseTask interface .......................................... 523
TaskStatus enum ................................................. 529
SchedulePriority enum ........................................... 529
ExecutePriority enum ............................................ 529
LoggingLevel enum ............................................... 530
EventIds enum ................................................... 530
ProgressEvent structure ......................................... 530
StatusEvent structure ........................................... 530
21.3. Implementing user tasks in C++ .............................. 531
21.4. Implementing user tasks in C# ............................... 532
21.5. TaskManager Service ......................................... 532
SCAITaskManager interface ....................................... 533
21.6. Scheduling tasks to run ..................................... 536
Task scheduling priority ........................................ 536
Task execution priority ......................................... 536
Executing tasks using the thread pool ........................... 537
Controlling the size of the thread pool ......................... 537
Executing tasks using dedicated threads ......................... 538
TBB compatibility ............................................... 538
21.7. Task status ................................................. 539
21.8. Life-cycle for task objects ................................. 540
Reusing task objects ............................................ 540
21.9. Detecting when tasks have finished .......................... 540
Explicitly waiting for tasks to finish .......................... 541
Using TaskManager status events ................................. 541
21.10. Cancelling tasks ........................................... 541
Cancelling a task while still in queue .......................... 541
Cancelling a task while executing ............................... 542
21.11. Event publishing for TaskManager ........................... 542
Using status events ............................................. 542
Using progress events ........................................... 544
Using cancel events ............................................. 545
21.12. Logging from the TaskManager ............................... 545

11
SCA Framework User Guide

Word SCA Framework User


Document

Chapter 1

Introduction

1
SCA Framework User Guide

1. Introduction
The Simulation Component Architecture, or SCA, is designed to enable the delivery of
MSC’s simulation technology as reusable software components. With this framework,
engineers can develop integrated high-performance computing (HPC) applications more
quickly and efficiently, while also making the technology more accessible to MSC clients’
applications. It also provides a framework that allows clients to build extensions or
customizations that can easily be plugged into MSC applications or reuse components that are
delivered my MSC.
1.1. Organization of this manual
This manual contains a lot of detailed information on the SCA Framework. Much of it is not
required to get started using SCA. To begin building and using simple SCA components it is
recommended that you review the following chapters first.

SCA Architecture Overview


A SCA Hello World Application
The IDL Language
The IDL mapping chapter for the language you will be using
Configuring and Using the SCA Kernel
The SCASCons Build System

The rest of the chapters in this manual provide details on more specialized topics that can be
reviewed when needed to use the features they cover.
1.2. Source Code Examples
There are a lot of snippets of example code in the various chapters in this manual. Most of this
code is delivered with the SCA Software Development Kit so you can run and play with them
as desired. See the SCA SDK chapter in the manual for more details.

2. SCA Architecture Overview


A central principle of the SCA architecture is the concept of interface-based programming
which is sometimes called component-based programming. Interfaces provide a separation of
the API, the clients see, from their actual implementation. When a developer separates an
interface from its implementation, the client code is developed around an abstraction of the
implementation or the interface.

When developing SCA based components, you will be working with three levels of
abstractions.

SCA Interfaces define the API that your clients will be exposed to.
SCA Services provide the actual implementation of the interfaces.
SCA Components provide the packages that are used to deliver the services to your
clients.

2
SCA Framework User Guide

2.1. Interface Based Programming


To better understand interface based programming, consider the following typical C++ class
definition.

MyImplementation.h
class MyImplementation
{
public:
void doSomething();
void doSomethingElse();
};

[Link]
void MyImplementation::doSomething()
{ …… }
void MyImplementation::doSomethingElse()
{ …… }

We can then write a client application that uses the simple class.

[Link]
#include “MyImplementation.h”
main()
{
MyImplementation* impl;
impl = new MyImplementation();
impl->doSomething();
impl->doSomethingElse();
}

There are a number of disadvantages to this type of implementation and most of these are
because the client code is directly linked to the class implementation. This means that any
changes in the internal implementation of the MyImplementation class will require the client
application to be recompiled and relinked. Some of these changes include the following.
Size of class
Method layout of class
Class inheritance structure

This type of inter dependency is unacceptable in a large software development environment.


In such environments it is desired to hide internal changes to the private portion of a class
from the users of the class. For example, why should the client have to be recompiled because
the implementation adds a new private data member or method? Only changes to public
methods should have an effect on them.

What we really need is a way of separating the API that the client uses from the code that
actually implements it. To do this we introduce the concept of an interface. The following is a
definition of an interface class, MyInterface, for our sample class.

3
SCA Framework User Guide

MyInterface.h
class MyInterface
{
public:
virtual void doSomething() = 0;
virtual void doSomethingElse() = 0;
};

The interface definition is a normal C++ class where every method is a pure virtual method. In
C++, a pure virtual function declaration provides only the prototype of the method and no
implementation. The actual implementation for the methods remains in the same C++ class,
MyImplementation, we had before. The only difference is now our implementation class must
inherit from the interface class.

MyImplementation.h
class MyImplementation : public MyInterface
{
public:
void doSomething();
void doSomethingElse();
};

[Link]
void MyImplementation::doSomething()
{ …… };
void MyImplementation::doSomethingElse()
{ …… };

When using interfaces, there is one other issue that needs to be resolved. The desire is for the
client to only reference the interface class and have no knowledge of the actual
implementation. But, how does the client get an instance of the class. They cannot do a C++
new operation on the interface class because it is abstract meaning it does not contain all of the
implementation for the methods it contains. C++ does not allow you to instantiate an abstract
class. To fix this problem we introduce the concept of a factory. Each class that implements an
interface that you want to expose to your clients must provide a factory function. The factory
function is responsible for getting new instances of the class. Since the factory function is part
of the class's implementation, it has access to the header files for the implementation which are
required for the C++ new operation. The following is the definition of the factory for our
example class.

MyFactory.h
MyInterface* MyFactory();

[Link]
MyInterface* MyFactory()
{
return new MyImplementation();
};

4
SCA Framework User Guide

Notice that this function returns a pointer to the interface class, MyInterface, and not the
implementation class. We now have all of the pieces to recode our client application to use the
interface version of our example class.

[Link]
#include “MyInterface.h”
#include “MyFactory.h”
main()
{
MyInterface* inf;
inf = MyFactory();
inf->doSomething();
inf->doSomethingElse();
}

The client gets an instance of the MyImplementation class using its factory function,
MyFactory. But it knows nothing about the implementation class because it is returned a
pointer to the interface class. Once the interface pointer is obtained, any of the methods it
contains may be called.

When you package this class for delivery to your clients, you would only need to deliver the
header file for the interface class and the object for the implementation class and its factory.
There is no need to delivery any of the header or implementation files from the
MyImplementation class. Because of this, the client has no knowledge of the implementation
other then the API exposed to them through its interface.

Another advantage of interface-based programming is that one version of the implementation


can replace a different version without requiring the client code to change. This new
implementation could correct errors in the previous version or it could provide different
internal algorithms. In the example, you could write a different implementation class called
MyImplementation2, and as long as it inherits from the same MyInterface interface class and
implements all of the methods, it can be used interchangeably with the first version. The
client’s code would be able to use this updated code without any changes except to link with
the object file for MyImplementation2.

It is also possible to deliver the implementation in a shared library instead of an object library.
By using this method, the client’s code would not have to be modified in any way, including
linking, to use the new implementation.

This illustrates another important feature of an interface: once an interface is delivered to a


client, it should not change. This insures that the client code will continue to function
correctly even if the underlying implementation is changed. If the new implementation needs
to change the interface, then it should provide a different interface for the new functionality
and continue to support the old interface, if possible. The client code can then determine at
run time if the implementation they are using provides the new or old interface and follow the
appropriate procedure. This allows old clients to work with new implementations and new
clients to work with old implementations.

5
SCA Framework User Guide

In summary, the use of interfaces provides the following advantages.


Client code is separated from class implementation code.
As long as the interface does not change, then class implementation changes do not affect
the client.
One version of implementation can be replaced with another without requiring the client
to be recompiled but it may have to be relinked.
If implementation is in a shared library then even the relink is not required.
The implementation of the class can be shared by more than one client.
Applications can be built on a component-by-component basis.

2.2. SCA Interfaces and the IDL language


The SCA Framework uses interface-based programming as a fundamental design premise.
Access to all exposed functionality is indirectly through interfaces. In SCA, all interface
definitions are defined in the interface definition language (IDL). These definitions completely
define the interface. This includes its methods, each of their parameters and any user
constructed data types required. The IDL definitions of the interfaces provide the information
needed to develop clients that use the interface’s operations.

The IDL language is a purely descriptive language. This means that the implementation of the
interfaces are not written in IDL, but in normal programming languages for which mappings
from the IDL concepts have been defined. The SCA IDL compiler will process the IDL
language and generate the required source files needed to access the functionality of the
interfaces in the requested language. Currently the SCA Framework supports mappings for
the C++, Java, C#, Visual Basic and Python languages.

In addition to the benefits of using interfaces, the use of IDL offers a number of additional
benefits.
The success of any large scale system may be strongly influenced by the design of its
interfaces. The use of an IDL promotes good software engineering practice by reinforcing
the idea of good interface design by forcing the developer to consider the interfaces to the
system before the implementation details are coded.
Because the IDL language is different from the various implementation languages, it
enables cross language applications development. You can use any of the supported
implementation languages to implement the API defined in an interface.
The use of an IDL compiler can greatly enhance productivity by automating the
generation of much of the code required to implement the many low-level details. This
frees the developer from performing these mundane tasks.
Similar to multi-language support, the use of IDL also allows for the transparent access
between SCA services and clients running on different computers.

2.3. SCA Services


SCA services provide the implementation for the interfaces. One or more classes may be used
to implement each service. These classes inherit from one or more interface classes and
provide the implementation for their methods. The service is the level of functionality that a

6
SCA Framework User Guide

client requests. They do not request an interface because several different implementations for
the same interface may reside in difference services. By requesting the service, the client can
easily select from the available implementations that they require.

Instances of the classes that make up a SCA service are called SCA service objects. The
lifecycle of SCA service objects is automatically handled by the SCA Kernel. The technique
used to manage the lifecycle depends on the language being used.

In C++, smart pointers are used to automate the destruction of service objects when all
references to them have been removed.
In Java, .NET and Python the normal garbage collection facilities in the languages are
used.

2.4. SCA Components


A SCA component is the container that is used to deliver one or more services. Depending on
the language, physically it may be a dynamically linked shared library or a Java JAR file.

Client code is not aware of components. When a client requests an instance of a SCA service,
the SCA Kernel will look in the SCA Service Catalog to determine which component
contains the requested service. It will then load the appropriate shared library or JAR file and
request an instance of the service from its factory. The lifecycle of components is also
automatically handled. When all instances of services in a component are released, the shared
library will be unloaded.
2.5. What is the SCA Kernel
The SCA Kernel is a collection of common services that reside in the SCAKernel and
SCAKernelUtil shared libraries.

One of the main functions the kernel provides is the lifecycle management of services. The
process of getting instances of service objects, tracking their use and deleting them when they
are no longer required is referred to as the lifecycle management. The SCA Kernel performs
the following function to help control lifecycle.
Maintains a catalog of services and the shared libraries that contain them.
Loads the required shared libraries for services when they are requested.
Initializes the shared libraries which makes available to the application all of the services
they contain.
Gets instances of the class for a service by calling its factory method.
Unloads the shared library when it is no longer required.

The SCA Kernel is composed of the following services.


ServiceManager which is responsible for the lifecycle management of services.
SharedLibraryManager which is responsible for loading and unloading of shared libraries.
TextTranslation which provides the core message processing functions.
EventManager which provides facilities for event processing.

7
SCA Framework User Guide

2.6. The SCA Framework


The SCA Framework is composed of the SCA Kernel, utility services, and supporting
infrastructure. It is delivered as a collection of shared libraries, Python files, Java files, XML
files, and other configuration files. The framework facilitates the designing, coding, and
building of applications through several facilities. These facilities are accessed though a set of
common services using interfaces provided by the SCA Framework. They currently include
the following:

Loading and lifecycle management of services


Error and exception management
Event support
Implementation reuse support
Memory management
Messaging support
Scripting support
Multithreading support
Regular expression searching
Remoting support
I/O
System Utilities
XML parsing
Some of the infrastructure related utilities provided by the SCA Framework include the
following:
Build system based on the SCons software
IDL compiler

2.7. Language support


The SCA Framework language support differs from language to language. The level of
support for a given language can be described by the following capabilities.
Can you call SCA interfaces implemented in the same language or in other languages?
Can you implement a SCA interface in the language?
Can you implement a SCA service in the language?

The following is the supports matrix for the languages currently supported.

Call Implement Implement


Language
Interface Interfaces Services
C++ Yes Yes Yes
Java Yes Yes Yes
C# Yes Yes Yes
Visual Basic Yes Yes Yes
Other .NET Languages Yes No No

8
SCA Framework User Guide

Python Yes Yes No

2.8. Platform support


The SCA Framework is currently supported on the following Windows, and Linux platforms.

Identifier Description
Linux on Intel x86_64 or AMD Opteron hardware,
linux64
64 bit (RHEL 6.7, RHEL 7.1, SuSE ES 11 SP3)
Linux on Intel x86_64 or AMD Opteron hardware,
linux64i8
ILP64 bit (RHEL 6.7, RHEL 7.1, SuSE ES11SP3)
Windows on Intel x86_64 or AMD Opteron
win64
hardware, 64 bit
Windows on Intel x86_64 or AMD Opteron
win64i8
hardware, ILP64 bit
win32 Windows on x86 or similar AMD hardware, 32 bit

Note that not all of the advanced features of the Framework are supported on all platforms.
2.9. Summary
An important thing to remember about the SCA Architecture is that it is not anything entirely
new or radical.

SCA interfaces are just C++ pure virtual classes or Java or .NET interface classes
Services are made up of one or more normal language classes.
Components are just shared libraries or JAR files

The development of SCA component is not that different from the development of a normal
C++ application.

What SCA provides is a formalization of the processes that govern normal object based
programming practices. In addition to this, the SCA Framework provides a set of tools that
automates much of the mundane aspects of building and deploying SCA components. These
include benefits at both build time and run time. For example the build time benefits include
the automatic generation of much of the infrastructural code required by SCA service like the
service factories. At runtime the SCA Kernel provides the automatic lifecycle management of
SCA components.

The benefits provided by SCA do not come completely free. In order to provide them it is
necessary to impose some restrictions on what you are allowed to do. An example of this is
the restriction on the type of interface arguments and return values that are allowed. Because
of the requirement that the API defined by the IDL language must be implemented in a
number of different languages and you must be able to marshal the data from one language to
the other at run time, you are only allowed to use types that are fully defined. This means that

9
SCA Framework User Guide

indescript types like pointers are not allowed. Full details on all of these restrictions are
presented in the appropriate chapters of this manual.

In summary, the use of interface-based programming and the SCA Framework provide a
number of benefits to the developers:

The success of any large scale system may be strongly influenced by the design of its
interfaces. The use of an IDL promotes good software engineering practice by
reinforcing the idea of good interface design by forcing the developer to consider the
interfaces to the system before the implementation details are coded.
Because the IDL language is different from the various implementation languages, it
enables cross language applications development. You can use any of the supported
implementation languages to implement the API defined in an interface.
The use of an IDL compiler can greatly enhance productivity by automating the
generation of much of the code required to implement the many low-level details. This
frees the developer from performing these mundane tasks.
Similar to multi-language support, the use of IDL also allows for the transparent
access between SCA services and clients running on different computers.
Clients and services can be implemented in any of the supported programming
languages and do not have to be implemented in the same language.
Inter-process communication is automatically provided by the Framework.
A service’s implementation can change without affecting the client, as long as the
interface does not change. Developers can replace an existing version of a service
with a new version without requiring any changes to the client.
Applications can be built on a component-by-component basis.
A service can be used by all applications that use the SCA Framework.

10
SCA Framework Template

Chapter 3
A SCA Hello World Application

12
A SCA Hello World Application A SCA Hello World Application

3. A SCA Hello World Application


3.1. Introduction
The Simulation Component Architecture (SCA) Framework is designed to enable the
development of reusable software components quickly and efficiently. In this chapter we will
show the actual steps involved in implementing a SCA component by creating a simple
component that contains one service named HelloWorld. This service will implement the
SCAIHello interface. We will then show an example client application that uses this service.
Each of these examples will be done in the following languages which are currently supported
by the SCA Framework.
C++
C#
Java
Visual Basic
Python
Currently you cannot implement SCA components in Python so for this language we will only
show a sample client application.
The following are the basic steps that you must follow to create a SCA component. The steps
are the same regardless of which implementation language you choose.
1. Define the interfaces
2. Define the services
3. Define the component
4. Generating code stubs for the language of your choice
5. Add the required functionality to the generated stubs
All of the code for the examples created in this chapter is delivered with the SCA Software
Development Kit. The actual building of the components and client applications will not be
discussed in this chapter. If you wish to actual build and run the samples please consult the
instructions delivered with the examples.
3.2. Define the Interfaces
The first step in creating a service is to define the interfaces that the service will support.
These interfaces form the API that the service’s clients will use, and they should not change
once they are delivered to the client. Because of this, it is important that the appropriate
thought is given to develop consistent and well-designed interfaces.
Interfaces are defined by using the SCA interface definition language (IDL). The SCA IDL
compiler processes the IDL and generates the required source files needed to access the
functionality defined by the interfaces in each of the supported languages. The SCA IDL is
based on the OMG IDL and is described in detail in the IDL Language chapter of this manual

13
A SCA Hello World Application A SCA Hello World Application

IDL files have the extension .idl and may contain as many interface and type definitions as
you need.
Our HelloWorld service will implement one interface which is called SCAIHello. This
interface has one method named printHello which requires a single string argument which is
the implementation language of the client calling the service. The printHello method for our
simple service will just print the language that it was called from and the language that it is
implemented in.
The following is the IDL definition for the SCAIHello interface.

#ifndef SCA_HELLOWORLD_EXAMPLE_HELLOWORLD_IDL_INCLUDED
#define SCA_HELLOWORLD_EXAMPLE_HELLOWORLD_IDL_INCLUDED

#include "SCA/[Link]"

module SCA { module HelloWorld { module Example {

interface SCAIHello : SCAIService


{
SCAResult printHello (in SCAString sName );
};

}; }; };

#endif

The IDL definition contains the following sections.


Include Guard
The first two lines of the IDL definition contain the standard include guard definitions that
keep the file from being expanded more than once during each compilation. This may happen
if the IDL file is included by more than one file that is part of the current compilation. To
make sure the guard name is unique, the convention is use the full relative path to the file
being guarded followed by _INCLUDED. In this case we have used
SCA_HELLOWORLD_EXAMPLE_HELLOWORLD_IDL_INCLUDED for the guard
name.
Include Declarations
The next section of the IDL file is for the include statements for any other IDL files that are
required by the interface definitions. If the SCA Framework or some other service has
previously defined an interface that is being implemented, the IDL file where it is defined
should be included, instead of redefining the interface in your file.
It is important to remember that the file names used in these include statements must include
the correct relative directory location in the delivery tree for the IDL files. You should not use
the directory names in the source tree. This is because the IDL you create must be delivered to
the users of your service. When they use the IDL files, they will be using them from the
delivery tree. They should have no knowledge of the structure of your source tree. To enforce
this, The IDL compiler will not look in the source tree for the files that are included.
The build system will automatically copy the IDL files from the source tree into the correct
location in your delivery tree before it runs the IDL compiler. However, if the IDL compiler

14
A SCA Hello World Application A SCA Hello World Application

is manually run, you may need to copy the files and add appropriate include paths on the
command.
In our IDL file we have included the IDL file SCA/[Link] because the SCAIHello
interface inherits from the SCAIService interface which is defined in this file.
Module Declarations
The IDL file’s module statements are used to define the namespace and the locations in the
delivery tree where the IDL and header files are stored.
A namespace should always be used for interface definitions to minimize naming collisions
with other definitions. The fully qualified name of an interface is determined by combining
the module names and the interface name. The fully qualified interface name in this example
is [Link].
The implementation language’s namespace for the interface is also taken directly from the
module statements as well. For example in C++ the namespace in this example would be
SCA::HelloWorld::Example and in Python it would be [Link].
The installation subdirectories for the IDL in the delivery tree are also taken from the module
statements. In this example, the IDL files will be stored in the idl/SCA/HelloWorld/Example
directory in the delivery tree. This is the relative location that should be used by all users of
the SCAIHello interface.
In a similar manner, any language specific support files that are generated by the IDL
compiler and are required for the clients to use your interface will also be stored in the
delivery tree. The installation subdirectories for these files are also taken from the module
statements. In this example, the C++ include file for this interface will be stored in the
include/SCA/HelloWorld/Example directory in the delivery tree.
Interface Declarations
Each interface is declared with an interface statement that contains the definitions of the
methods it implements. The syntax for interface definition is similar to C++ class
declarations. The main difference is that each parameter in the method definitions must
contain a direction parameter. This parameter can be in, out, or inout and is used to define
whether the parameter is input only, output only, or both input and output. It is used to
determine how the parameters are declared and passed. It also determines the data transfer
direction for marshalling the parameters between different languages or different address
spaces.
A SCA Framework requires that each interface inherits from the SCAIService interface. This
inheritance may be direct, as in this example, or indirectly through another interface from
which it inherits. The SCAIService interface defines the methods used to support interface
navigation, reference counting, and runtime introspection. You need to include the file that
defines this interface, SCA/[Link], in the IDL file unless it is already included in another
file that you have included. Since every interface must inherit from the SCAIService
interface, the IDL compiler will generate all the code that is required to implement the
methods it contains.
3.3. Define the Service
After defining the interfaces in the IDL file, you must define the service itself. A service
definition language (SDL) file is used to define which interfaces a service supports. It also
defines the structure of the classes that will implement the interfaces. The IDL compiler uses

15
A SCA Hello World Application A SCA Hello World Application

this information to generate a set of skeleton implementation classes to which the developer
adds the required functionality. When the build system compiles your service, it will also run
the IDL compiler to generate the implementation for the required base classes.
SDL files have the extension .sdl and only one service definition is allowed in each SDL file.
We have defined the HelloWorld service which implements the SCAIHello interface with
the SDL file [Link], which is listed below.

#ifndef HELLOWORLDCPP_HELLOWORLD_SDL_INCLUDED
#define HELLOWORLDCPP_HELLOWORLD_SDL_INCLUDED

#include "SCA/HelloWorld/Example/[Link]"

module Samples { module HelloWorld { module Example {

service [Link] {
interface SCA::HelloWorld::Example::SCAIHello;
};

}; }; };

#endif

Note that this is the SDL file for the C++ implementation of the HelloWorld service. The
only difference for the implementation in the other languages is the include guard and the
actual name of the service.
Most of the SDL file is similar to the IDL file. It contains the include guard, include
statements, module statements and service statements.
Include Guard
The first two lines of the SDL definition contain the standard include guard that keep the file
from being expanded more than once during each compilation. To make sure the guard name
is unique, the convention is use the full relative path to the file being guarded followed by
_INCLUDED. In this case we have used
HELLOWORLDCPP_HELLOWORLD_SDL_INCLUDED for the guard name.

Include Declarations
The next section of the SDL file is for the include statements. You should include all the IDL
files that define the interfaces implemented by the service. Once again remember that when
including IDL files you need to use the correct relative directory location in the deliver tree
and not the directory names from the source tree.
Module Declarations
The SDL file’s module statements are used to define the implementation code’s namespace.
For example, in C++, the namespace for the service’s implementation class would be
Samples::HelloWorld::Example. The general policy for SDL files is that each service is put
in its own separate implementation code namespace to minimize the change of symbol
collisions.

16
A SCA Hello World Application A SCA Hello World Application

The SDL namespace is not related to the IDL namespace and will normally be different.
Remember that the interface namespace is exposed to clients and has different requirements
than the implementation code’s namespace. The IDL namespace needs to coexist with all of
the other interfaces defined by all of the components in your application. It therefore should
follow some application determined convention. The SDL namespace is unique to your
implementation and you can choose any appropriate value you like. One common convention
is to use the directory structure of the source tree for you namespace. There is no installation
information needed for services because they are delivered in components and not installed by
themselves. As a result, the SDL namespace has no affect on any installation decisions.
Service Declaration
The definition of the service starts with the service statement in the SDL file. The fully
qualified service name is the name clients will use to request instances of this service and is
defined by the name following the service statement. It must be a fully qualified name to
make sure the service name is unique from all other service names in the system. The service
name in the example is [Link].
The fully qualified service name is not based on the namespace defined by the SDL file’s
module statements. The service name is also not related to the IDL namespace, even though it
may be similar to it. The last part of the service name, HelloWorld, is used as the name of the
top level class that will be generated to implement the service.
3.4. Define the Component
Once the service has been defined, a component must be defined to contain it. The exact
format of the component generated by the build system depends on the language it is
implemented in. If you are using C++, C# or Visual Basic, the component is a dynamically
linked shared library and for Java it will be a jar file.
CDL files have the extension .cdl and only one component definition is allowed in each CDL
file.
In our example, the CPPGreeting component contains one service, HelloWorld. The
following is the CDL file for the component.

#ifndef HELLOWORLDCPP_HELLOWORLD_CDL_INCLUDED
#define HELLOWORLDCPP_HELLOWORLD_CDL_INCLUDED

#include "[Link]"

component [Link]
{
service HelloWorld;
};

#endif

Once again, note that this is the CDL file for the C++ implementation of the HelloWorld
service. The only difference for the implementation in the other languages is the include guard
and the actual name of the component.
The component definition does not require a namespace or module declarations. If you
include one it will have no affect on the build.

17
A SCA Hello World Application A SCA Hello World Application

Include Guard
The first two lines of the CDL definition contain the standard include guard that keep the file
from being expanded more than once during each compilation. To make sure the guard name
is unique, the convention is use the full relative path to the file being guarded followed by
_INCLUDED. In this case we have used
HELLOWORLDCPP_HELLOWORLD_CDL_INCLUDED for the guard name.
Include Declarations
The next section of the CDL file is for the include statements. You should include all the SDL
files that define the services that the component will contain. Because the SDL files are never
delivered to the clients of your services, they are never installed in the delivery tree. As a
result, the directory structure for including SDL files should be relative to the source tree and
not the delivery tree.
Component Declaration
The fully qualified component name is determined directly from the name following the
component statement, which is [Link] in the example. It is not
related to the IDL namespace, SDL namespace, or service name, though it may look similar to
any of them. The short name is CPPGreeting, and it is used for the name of the generated
library file.
The fully qualified component defines the relative path where the build system stores the
shared library. The delivery locations for the example components in each of the supported
languages are show below.

Language Platform File


C++ Windows WINNT/bin/SCA/HelloWorld/[Link]
Linux LX86/lib/SCA /HelloWorld/[Link]
Java All lib/java/SCA/HelloWorld/[Link]
C# Windows WINNT/bin/SCA/HelloWorld/[Link]
Visual Basic Windows WINNT/bin/SCA/HelloWorld/[Link]

3.5. Generate the Implementation Files for the Service


Once the IDL and SDL files have been created, the IDL compiler can be used to generate the
skeleton code for the implementation of the service. This code will only include the methods
that are defined in the interfaces that the service will implement. The exception is the
SCAIService interface; its methods are implemented in a base class that the HelloWorld
service implementation needs to inherit from. The code for the base class will be generated as
part of the build process.
The genskeleton Command
A special command called genskeleton is provided with the SDK. It is used to run the IDL
compiler and create these code file skeletons. The genskeleton command takes an option to

18
A SCA Hello World Application A SCA Hello World Application

indicate which language the services will be implemented in. The default is to generate the
implementation in C++. The genskeleton command is located in the SCA tools directory.
Using the definitions in the SDL files, the IDL compiler will generate a number of language
specific skeleton code files in the current directory. For example, when running the
genskeleton command for C++, it will create a .h header and a .cpp implementation file.
If there are existing versions of any of the files to be generated, then all of the new files will be
generated with the additional extension of .new. If you add the –r option to the genskeleton
command, then the existing files will be renamed by adding an extension of .old and the newly
generated files will not nave the .new extension.
These files can now be used as a base to implement the service.
The genskeleton command will only work correctly if you are running from a directory inside
of a properly formatted SCA source tree. This means the directory needs to contain a
SConscript file and the source tree must contain a SConstruct in its root directory. These are
required because a short build step, which uses them, is initially run to install any IDL files
from the current directory in the source tree into the delivery tree so the IDL compiler can
access them.
The IDL compiler does not need to be manually run on the IDL or CDL files. That will be
done as part of the normal build process when required.
Adding the Required Functionality to the Skeletons
Once you have generated the skeleton files, you can modify them to add whatever details are
required to implement the desired functionality. You are free to add any new methods or data
that you require. There are a couple of things that you cannot change.
The implementation class must inherit from the IDL generated base class. You may
add to the inheritance structure but you may not remove the generated one.
You cannot change the signature of the constructor for the implementation class. The
IDL compiler will also generate factory code that is used to instantiate instances of the
service and it requires the signature of the constructor as generated.
In the HelloWorld example, the only implementation that is required is a simple write
statement in the printHello method.
In the following sections we show the formats for the generated skeleton file for the
implementation in each of the supported languages. In the example code, the light gray
background shows the code generated by the genskeleton command. The lines of code that
have the darker gray background represent the lines of code that were changed to add the
required functionality to the generated skeletons.
Implementing the Service in C++
The following genskeleton command will generate the implementation stubs in C++.
/Tools/genskeleton [Link]
Or
/Tools/genskeleton –cxx [Link]
From the SDL, the compiler will generate the following C++ skeleton code files in the current
directory.

HelloWorld.h C++ header file for the top level service class

19
A SCA Hello World Application A SCA Hello World Application

[Link] C++ implementation file for the top level service class

The following is the content of the C++ header file HelloWorld.h that is generated.

#ifndef SAMPLES_HELLOWORLD_EXAMPLE_HELLOWORLD_H_INCLUDED
#define SAMPLES_HELLOWORLD_EXAMPLE_HELLOWORLD_H_INCLUDED

#include "HelloWorldBase.h"

namespace Samples { namespace HelloWorld { namespace Example {

class HelloWorld : public HelloWorldBase


{
public:

// Constructor and Destructor


HelloWorld(SCAIHelloWorldFactoryAccess* factoryAccess);
virtual ~HelloWorld();

// Methods for interface [Link]


virtual SCA::SCAResult printHello(const SCA::SCAString sName);
};

} } }

#endif

The following is the content of the C++ implementation file [Link] that is generated.

#include "HelloWorld.h"
#include <iostream>

namespace Samples { namespace HelloWorld { namespace Example {

// Constructor
HelloWorld::HelloWorld(SCAIHelloWorldFactoryAccess* factoryAccess)
: HelloWorldBase(factoryAccess)
{
}

// Destructor
HelloWorld::~HelloWorld()
{
}

SCA::SCAResult HelloWorld::printHello(const SCA::SCAString sName)


{
std::cout << sName << " client calling HelloWorld "
<< "implemented in C++" << std::endl;
return SCA::SCASuccess;
}

} } }

20
A SCA Hello World Application A SCA Hello World Application

Next we just need to add the actual functionality to the stubs. In our simple case, there were no
changes required to the header file. The only change required to the implementation file was
to add an include statement and an output statement in the printHello method.
We now have a complete SCA service implemented in C++ that is ready to be built.
Implementing the Service in JAVA
The following genskeleton command will generate the implementation stubs in Java.
/Tools/genskeleton –java [Link]
From the SDL, the compiler will generate the following Java skeleton code file.

[Link] Java implementation file for the top level service class

For Java, the generated implementation files will not be in the current directory. This is
because the Java compiler uses the relative directory structure to determine the name of the
Java package that is created. The SDL namespace is used to determine this package name. In
our example, the generated Java implementation files will actually be in the directory
Samples/HelloWorld/Example relative to the current directory.
The following is the content of the Java implementation file
Samples/HelloWorld/Example/[Link] that is generated.

package [Link];

public class HelloWorld extends HelloWorld_base


{
// Constructor
public HelloWorld ([Link] provider)
{
super();
setServiceProvider(provider);
}

// Methods for interface [Link]


public final [Link] printHello (String sName)
{
[Link](sName+" client calling HelloWorld "+
"implemented in Java");
return [Link];
}
}

Next we just need to add the actual functionality to the stubs. In our simple case, the only
changed required to the implementation file was to add a print statement in the printHello
method and to return the appropriate value.
We now have a complete SCA service implemented in Java that is ready to be built.
Implementing the Service in C#
The following genskeleton command will generate the implementation stubs in C#.
/Tools/genskeleton –csharp [Link]
From the SDL, the compiler will generate the following C# skeleton code file in the current
directory.

21
A SCA Hello World Application A SCA Hello World Application

[Link] C# implementation file for the top level service class

The following is the content of the C# implementation file [Link] that is generated.

using [Link];
using SCA;

namespace Samples { namespace HelloWorld { namespace Example {

public class HelloWorld: HelloWorld_base ,


[Link]
{
// Constructor
public HelloWorld ([Link] provider)
{
setServiceProvider(provider);
}

// Methods for interface [Link]


[Link] [Link] (string
sName)
{
[Link](sName+" client calling HelloWorld "+
"implemented in C#");
return [Link];
}

} } }

Next we just need to add the actual functionality to the stubs. In our simple case, the only
changed required to the implementation file was to add a write statement in the printHello
method and to return the appropriate value.
We now have a complete SCA service implemented in C# that is ready to be built.
Implementing the Service in Visual Basic
The following genskeleton command will generate the implementation stubs in Visual Basic.
/Tools/genskeleton –vb [Link]
From the SDL, the compiler will generate the following Visual Basic skeleton code file in the
current directory.

[Link] VB implementation file for the top level service class

The following is the content of the Visual Basic implementation file [Link] that is
generated.

Imports [Link]

22
A SCA Hello World Application A SCA Hello World Application

Namespace Samples
Namespace HelloWorld
Namespace Example

Public Class HelloWorld


Inherits HelloWorld_base
Implements [Link]

' Constructor
Public Sub New(ByVal provider As [Link])
setServiceProvider(provider)
End Sub

' Methods for interface [Link]


Public Function printHello (ByVal sName As String) As [Link] _
Implements [Link]
[Link](sName & " client calling HelloWorld " & _
"implemented in VB")
Return [Link]
End Function

End Class

End Namespace
End Namespace
End Namespace

Next we just need to add the actual functionality to the stubs. In our simple case, the only
change required to the implementation file was to add a write statement in the printHello
method and to return the appropriate value.
We now have a complete SCA service implemented in Visual Basic that is ready to be built.
3.6. Building the component
Once we have created the implementation files for our service, we can now build the
component. We will not go into details on how this is done in this chapter because it will be
discussed in detail latter in the manual.
All of the code for the examples created in this chapter is delivered with the SCA Software
Development Kit. If you wish to actually build and run the samples please consult the
instructions delivered with the examples.
In this section what we will discuss is some of the processing that the build system will take
care of to build a SCA component. All of these steps are automatic and require no actions by
the developer.
As part of building a SCA component, the SCA build system will perform the following
general steps. The exact details of these and what each generates is a function of the
implementation language being used and the platform you are building on.
Run the IDL compiler on the IDL file to generate the appropriate language support
files. For C++ these include header files that are stored in the delivery tree. For the
other language they include implementation files that will be stored in the object
directory which will be compiled and linked as required by the language.

23
A SCA Hello World Application A SCA Hello World Application

Run the IDL compiler on the SDL file to generate the required base class
implementation files for the service. These will be stored in the object directory and be
compiled and linked in with your component.
Run the IDL compiler on the CDL file to generate the required initialization function
for the component. These will be stored in the object directory and be compiled and
linked in with your component. Not all languages require this step.
Compile and link your code for the implementation of the service.
3.7. Creating a Client for the Service
Now that we have a working SCA component, the next sections will show how we can create
a simple client application that will use our component in each of the supported languages.
The basic steps for the client application are as follows.
1. Initialize the SCA Kernel
2. Get an instance of the HelloWorld service which returns a SCAIService interface on
it.
3. Obtain a SCAIHello interface on the service instance. This usually involves calling
the getInterface method in the SCAIService interface.
4. Call the printHello method in the interface
5. Terminate the SCA Kernel
The client applications that we will create in these sections are all stand-alone programs. It is
also possible to use SCA services from code that that is part of the implementation of another
SCA service. When doing this, it is not necessary to initialize or terminate the SCA Kernel
because it will already be active. Also, the process of getting an instance of a SCA service is
usually different when you are inside the implementation of another SCA service. Consult the
language mapping chapter for your implementation language for the complete details.
Creating a C++ Client for the Service
The following is a sample C++ application that will exercise our HelloWorld service.

#include <iostream>
#include <SCA/HelloWorld/Example/SCAIHello.h>
#include <SCA/SCAKernel.h>

using namespace std;


using namespace SCA;
using namespace SCA::HelloWorld::Example;

int main()
{
try {
initializeSCAKernel(1);
} catch (SCAException& e) {
cout << "Initialization of SCAKernel failed" << endl << [Link]()
<< endl;
return 0;
}

24
A SCA Hello World Application A SCA Hello World Application

SCAIService spService;
SCAIHello hwInf;

try {
spService = getSCAService("[Link]");
hwInf = static_cast<SCAIHello>(spService);
spService = NULLSP;
hwInf->printHello("C++");
hwInf = NULLSP;
} catch (SCAException& e) {
cout << "Load of HelloWorld service failed" << endl << [Link]()
<< endl;
}

try {
terminateSCAKernel();
} catch (SCAException& e) {
cout << "Termination of the SCAKernel failed" << endl
<< [Link]() << endl;
}
return 0;
}

The basic SCA Kernel operations are provided in the SCA/SCAKernel.h header file. These
include the following functions that are used in this example.
void initializeSCAKernel( SCA::SCAInt32 verbose=0,
const SCA::SCAString& configPath="" );

SCA::SCAIService getSCAService( const SCA::SCAString name );

SCA::SCAInt32 terminateSCAKernel();

All of these will throw an exception if they encounter an error so they have been included in
try/catch blocks in the sample application.
The first thing our application must do is initialize the SCA kernel.
initializeSCAKernel(1);

Since this call may throw an exception, in the actual application we have enclosed it in a
try/catch block. This is the case for all of the functions defined in the SCA/SCAKernel.h
header file that we will be using.
Once we have initialized the SCA Kernel, we need to get an instance of the HelloWorld
service. In this example we are getting an instance of the version of the service that is
implemented in C++ but it could have been one of the versions implemented in any of the
other languages by just changing the service name. To do this we use the following lines of
code.
SCAIService spService;
spService = getSCAService("[Link]");

The getSCAService function will always return a SCAIService interface pointer on the
service. This is possible because every SCA interface must inherit from the SCAIService
interface. But what we really want is a SCAIHello interface pointer. In the C++ language

25
A SCA Hello World Application A SCA Hello World Application

mapping, SCA interface pointers are special C++ classes know as smart pointers. These smart
pointers can automate many of the details of using the interfaces. This includes the automatic
handling of reference counting and providing a simplified method of interface navigation
using normal C++ casting syntax. The following lines of code will get a SCAIHello interface
pointer from the SCAIService pointer that was returned when we got an instance of the
service.
SCAIHello hwInf;
hwInf = static_cast<SCAIHello>(spService);

Once we have the SCAIHello interface pointer we can then call the printHello method that it
contains.
hwInf->printHello("C++");

The final thing our application should do is terminate the SCA kernel.
terminateSCAKernel();
Creating a JAVA Driver for the Service
The following is a sample Java application that will exercise our HelloWorld service.

import SCA.*;
import [Link].*;
import [Link].*;

public class Driver{


public static void main (String args[]) {

try{
[Link]();
} catch (SCASystemException e) {
[Link]("Initialization of SCAKernel failed\n" +
[Link]());
}

SCAIService spService;
SCAIHello hwInf;

try{
spService = [Link](
"[Link]");
hwInf = (SCAIHello)[Link](
"[Link]");
[Link]("Java");
} catch (SCASystemException e) {
[Link]("Failed to get HelloWorld\n" + [Link]());
}

try{
[Link]();
} catch (SCASystemException e) {
[Link]("Termination of the SCAKernel failed\n" +
[Link]());
}

26
A SCA Hello World Application A SCA Hello World Application

In Java, the [Link] interface provided by the SCA Kernel is used to access the
basic SCA Kernel operations. All of the method of this interface will throw exceptions if they
encounter errors, so be sure to enclose these calls in a try/catch block.
The first thing our application must do is initialize the SCA kernel utilizing this interface.
import [Link].*;
[Link]();

Once we have initialized the SCA Kernel, we need to get an instance of the HelloWorld
service. In this example we are getting an instance of the version of the service that is
implemented in Java but it could have been one of the versions implemented in any of the
other languages by just changing the service name. To do this we use the following lines of
code.
SCAIService spService;
spService = [Link](
"[Link]");

The getService function will always return a SCAIService interface pointer on the service.
This is possible because every SCA interface must inherit from the SCAIService interface.
But what we really want is a SCAIHello interface pointer. In the Java language mapping it is
only possible to navigate from one interface to anther using the normal JAVA casting syntax
if the interface is pointing to a service implemented in Java. If the service is implemented in
any other language you must make an explicit getInterface call to do the navigation. Since you
never know for sure what language the service you are using is written in, it is a good practice
to always use this syntax. The following lines of code will get a SCAIHello interface pointer
from the SCAIService pointer that was returned when we got an instance of the service.
SCAIHello hwInf;
hwInf = (SCAIHello)[Link](
"[Link]");

Once we have the SCAIHello interface pointer we can then call the printHello method that it
contains.
[Link]("Java");

The final thing our application should do is terminate the SCA kernel.
[Link]();
Creating a C# Driver for the Service
The following is a sample C# application that will exercise our HelloWorld service.

using System;
using SCA;
using [Link];

class CSDriver
{
static void Main(string[] args)
{
try {

27
A SCA Hello World Application A SCA Hello World Application

[Link]();
} catch (SCAException e) {
[Link]("Initialization of SCAKernel failed\n" +
[Link]());
}

SCAIService spService;
SCAIHello hwInf;

try {
spService = [Link](
"[Link]");
hwInf = (SCAIHello)[Link](
"[Link]");
spService = null;
[Link]("C#");
} catch (SCAException e) {
[Link]("Load of HelloWorld service failed\n" +
[Link]());
} finally {
hwInf = null;
}

try {
[Link]();
} catch (SCAException e) {
[Link]("Termination of the kernel failed\n" +
[Link]());
}

}
}

In C#, the [Link] interface provided by the SCA Kernel is used to access the
basic SCA Kernel operations. All of the method of this interface will throw exceptions if they
encounter errors, so be sure to enclose these calls in a try/catch block.
The first thing our application must do is initialize the SCA kernel utilizing this interface.
using SCA;
[Link]();

Once we have initialized the SCA Kernel, we need to get an instance of the HelloWorld
service. In this example we are getting an instance of the version of the service that is
implemented in C# but it could have been one of the versions implemented in any of the other
languages by just changing the service name. To do this we use the following lines of code.
SCAIService spService;
spService = [Link](
"[Link]");

The getService function will always return a SCAIService interface pointer on the service.
This is possible because every SCA interface must inherit from the SCAIService interface.
But what we really want is a SCAIHello interface pointer. In the C# language mapping it is
only possible to navigate from one interface to anther using the normal C# casting syntax if
the interface is pointing to a service implemented in one of the .Net languages which include

28
A SCA Hello World Application A SCA Hello World Application

C# and VB. If the service is implemented in any other language you must make an explicit
getInterface call to do the navigation. Since you never know for sure what language the
service you are using is written in, it is a good practice to always use this syntax. The
following lines of code will get a SCAIHello interface pointer from the SCAIService pointer
that was returned when we got an instance of the service.
SCAIHello hwInf;
hwInf = (SCAIHello)[Link](
"[Link]");

Once we have the SCAIHello interface pointer we can then call the printHello method that it
contains.
[Link]("C#");

The final thing our application should do is terminate the SCA kernel.
[Link]();
Creating a Visual Basic Client for the Service
The following is a sample Visual Basic application that will exercise our HelloWorld service.

Imports SCA
Imports System
Imports [Link]

Module ModuleMain

Sub Main(ByVal args As String())

Try
[Link]()
Catch e As SCASystemException
[Link]("Initialization of SCAKernel failed\n" + _
[Link]())
End Try

Try
Dim spService As [Link] = [Link]( _
"[Link]")
Dim hwInf As SCAIHello = CType([Link]( _
"[Link]"), SCAIHello)
[Link]("Visual Basic")
Catch e As SCASystemException
[Link]("Load of HelloWorld service failed\n" + _
[Link]())
End Try

Try
[Link]()
Catch e As SCASystemException
[Link]("Termination of SCAKernel failed\n" + _
[Link]())
End Try

End Sub

29
A SCA Hello World Application A SCA Hello World Application

End Module

In Visual Basic, the [Link] interface provided by the SCA Kernel is used to
access the basic SCA Kernel operations. All of the method of this interface will throw
exceptions if they encounter errors, so be sure to enclose these calls in a try/catch block.
The first thing our application must do is initialize the SCA kernel utilizing this interface.
Imports SCA
[Link]()

Once we have initialized the SCA Kernel, we need to get an instance of the HelloWorld
service. In this example we are getting an instance of the version of the service that is
implemented in Visual Basic but it could have been one of the versions implemented in any of
the other languages by just changing the service name. To do this we use the following line of
code.
Dim spService As [Link] = [Link]( _
"[Link]")

The getService function will always return a SCAIService interface pointer on the service.
This is possible because every SCA interface must inherit from the SCAIService interface.
But what we really want is a SCAIHello interface pointer. In the Visual Basic language
mapping it is only possible to navigate from one interface to anther using the Visual Basic
DirectCast keyword if the interface is pointing to a service implemented in one of the .Net
languages which include C# and VB. If the service is implemented in any other language you
must make an explicit getInterface call to do the navigation. Since you never know for sure
what language the service you are using is written in, it is a good practice to always use this
syntax. The following lines of code will get a SCAIHello interface pointer from the
SCAIService pointer that was returned when we got an instance of the service.
Dim hwInf As SCAIHello = CType([Link]( _
"[Link]"), SCAIHello)

Once we have the SCAIHello interface pointer we can then call the printHello method that it
contains.
[Link]("Visual Basic")

The final thing our application should do is terminate the SCA kernel.
[Link]()
Creating a Python Client for the Service
We have not discussed using Python yet because currently you cannot implement a SCA
component in Python. But you can easily use SCA services written in any of the other support
languages from Python. The following is a sample Python application or script that will
exercise our HelloWorld service.

try:
import SCA
svc = [Link]("[Link]")
(ret,hwinf) = [Link]("[Link]")
[Link]("Python")

30
A SCA Hello World Application A SCA Hello World Application

except [Link], exc:


print "SCAException:",[Link]()

In Python, the SCA module provided by the SCA Kernel is used to access the basic SCA
Kernel operations. All of the method of this interface will throw exceptions if they encounter
errors, so be sure to enclose these calls in a try/except block.
The first thing our application must do is initialize the SCA kernel utilizing this interface. This
is done by importing the SCA module. In Python there is no explicit call required to initialize
the SCA Kernel. It is done automatically when it is required.
import SCA

Once we have initialized the SCA Kernel, we need to get an instance of the HelloWorld
service. In this example we are getting an instance of the version of the service that is
implemented in C++ but it could have been one of the versions implemented in any of the
other languages by just changing the service name. To do this we use the following line of
code.
svc = [Link]("[Link]")

The getService function will always return a SCAIService interface pointer on the service.
This is possible because every SCA interface must inherit from the SCAIService interface.
But what we really want is a SCAIHello interface pointer. Since Python is a type less
language, it is only possible to navigate from one interface to anther using an explicit
getInterface call to do the navigation. The following line of code will get a SCAIHello
interface pointer from the SCAIService pointer that was returned when we got an instance of
the service.
(ret,hwinf) = [Link]("[Link]")

Once we have the SCAIHello interface pointer we can then call the printHello method that it
contains.
[Link]("Python")

In Python there is no requirement to terminate the SCA kernel.


3.8. Summary
In this chapter we have shown how to develop a simple SCA HelloWorld service in each of
the supported languages. Let’s review the basic steps that are required.
Design the interfaces the service will support and code them in IDL
Create the SDL file for the service.
Create the CDL file for the component.
Run the IDL compiler to generated skeleton implementation code for the service.
Add code to skeletons to implement the desired behavior for each interface method.
Build the component using the SCA build system.
We then showed how to implement a simple client application in each of the supported
languages that exercised our HelloWorld service.

31
SCA Framework User Documentation

Chapter 4

IDL Language

35
A SCA Hello World Application The IDL Language

4. The IDL Language


4.1. IDL Language Overview
The Object Management Group (OMG) Interface Definition Language, or IDL, is the
language used to describe SCA interfaces. The OMG is an open membership, not-for-profit
consortium that produces and maintains computer industry specifications for interoperable
enterprise applications. Some of these specifications include the Unified Modeling
Language, or UML and the CORBA middleware platform.

An interface definition written in the IDL language completely defines the interface. This
includes its methods, each of their parameters and any user constructed data types required.
The IDL definitions of the interfaces provide the information needed to develop clients that
use the interface’s operations.

Extensions to the OMG IDL language have been added to allow for the description of SCA
services and components.

The IDL language is a purely descriptive language. This means that services are not written in
IDL, but in languages for which mappings from the IDL concepts have been defined.
Currently the SCA Framework supports mapping for the C++, Java, C#, Visual Basic and
Python languages.

4.2. Source Files


The SCA IDL compiler processes three types of source files. All of these files use the same
IDL language but each is restricted to different types of definitions.

IDL files: These source files contain definitions of interfaces and user constructed data
types. These files must have an extension of “.idl”. These definitions declare the exposed
API for a service that is available to its users. No implementation details are contained in
the IDL files.
SDL files: These source files contain service definitions and must have an extension of
“.sdl”. Service definitions specify the implementation details that the IDL compiler needs
to generate the appropriate code to link a service to the SCA Framework. This information
includes which interfaces the service will implement and how these interfaces are mapped
to language specific class definitions which will be used in the implementation.
CDL files: These source files contain component definitions and must have an extension
of “.cdl”. Component definitions specify which services a component will contain.

The separation of the different types of definitions into different files has been done for several
reasons.
Because IDL files contain the definitions of the published interfaces and their supporting
types, these are generally delivered with their components. Since service and component
definitions contain implementation specific information you do not want to deliver these.
By separating these definitions from the interface and type definitions, they do not need to
be delivered.

36
A SCA Hello World Application The IDL Language

Separating the definitions into separate files allow them to be placed in the appropriate
locations in the source tree. For example a component may include several services and
each is implemented in a different directory in the source tree. This way the SDL files can
be places with their service definition and the CDL file place where the component is
built.
The separate files allow developers and the SCA Build system to easily determine the
types of objects that are being built in the various source tree directories without having to
examine the contents of the files. For example, if a directory contains a CDL file, then it is
immediately known that an appropriate package file must for a SCA component needs be
built in that directory.

The SCA IDL compiler processes the IDL definitions and generates the appropriate code in
the chosen implementation language. In general, the following types of source code are
generated.

Interface definitions: For each interface, appropriate source files are generated that defines
the interface and the operations it contains. Additional files may also be generated for any
user constructed IDL types defined.
Service definitions: Two types of code are generated for SCA service definitions. During
the build process, various source files are generated which are used to link the developer’s
implementation code to the SCA Framework. This is done to reduce as much as possible
the amount of code that must be written by the developer. This support code also provides
a level of isolation between the service’s implementation code and the SCA Framework.
This allows framework changes to be made with less impact on the existing service
implementation code. The developer can also run the IDL compiler to generate skeleton
implementation code for their service. This is usually done once at the beginning of the
development cycle. The generated skeletons can then be expanded with the code to
implement the desired behavior for each interface method. You can also run the IDL
compiler at a later time if any interface changes are made and you want to see how these
affect the skeletons.
Component definitions: During the build process, the IDL compiler may be run to
generate support code used to initialize the services it implements. This is not required for
all support languages. The developer never required to generate any code for the
implementation of a SCA component.

See the sections on the IDL mappings for the language you will be using for additional
information on the generated code.

4.3. Lexical Conventions


The IDL language obeys the same lexical rules as C++ with a few exceptions.
Comments
Both C and C++ style comments are supported. C style comments start with the characters
“/*” and terminate with the characters “*/”. These comments do not nest. C++ style
comments start with the characters “//” and terminate at the end of the line on which they
occur. The comment characters “//”, “/*”, and “*/” have no special meaning within a C++

37
A SCA Hello World Application The IDL Language

style comment and are treated just like other characters. Similarly, the comment characters
“//” and “/*” have no special meaning within a C style comment. Comments may contain
alphabetic, digit, graphic, space, horizontal tab, vertical tab, form feed, and new line
characters.
Identifiers
An identifier is an arbitrarily long sequence of ASCII alphabetic, digits, and underscores
characters. The first character of an identifier must be an ASCII alphabetic character. All
characters in the sequence are significant.

When comparing two identifiers, upper and lower case letters are treated as the same letter.
Identifiers that differ only in case of the letters are treated as the same identifier and can cause
compilation errors if used improperly. This rule is used to allow mapping to implementation
languages that are not case sensitive.
Keywords
The identifiers listed in the following table are reserved by the OMG IDL specification for
use as keywords and may not be used otherwise unless they are properly escaped. Keywords
must be written exactly as shown in the table. Identifier names that collide with keywords are
illegal. For example, since boolean is a valid keyword, Boolean and BOOLEAN would be
illegal identifiers.

any double interface readonly unsigned


attribute enum long sequence union
boolean exception module short void
case FALSE object string wchar
char fixed octet struct wstring
const float oneway switch
context in out TRUE
default inout raises typedef

The SCA Framework does not support all of the capabilities of the OMG IDL language, but
since it uses a modified OMG IDL compiler, all of the OMG keywords are still restricted.

Escaped Identifiers
As described in the previous section, the IDL language contains a set of reserved keywords
that may not be used as identifiers. As the language evolves, new keywords that are added
may inadvertently collide with identifiers used in existing IDL definitions and implementation
code. Fixing these collisions could require not only the modification to the IDL definitions,
but also to the implementation coded that uses them. To minimize this effect, the language
allows you to lexically escape identifiers by prefixing an underscore “_” to an identifier. This
is purely a lexical convention that turns off keyword checking. The resulting identifier follows
all of the other rules for identifier processing except the underscore is not considered part of its
name. For example, the identifier _attribute is treated the same as if it were attribute but it
will not clash with the IDL reserved attribute keyword. The implementation code should still
38
A SCA Hello World Application The IDL Language

use the identifier name without the prefix. This way only the IDL definitions and not the
implementation code need to be changed to fix any conflicts.
Literals
The IDL language supports the same literals as C++.
Integer Literals
An integer literal consists of an optional “+” or “-” sign character followed by a sequence of
digits that is treated as a decimal (base ten) value. If the sequence of digits starts with the digit
zero, then they are treated as an octal (base eight) value. If the characters “0x” or “0X”
precedes the sequence of digits, then they are treated as a hexadecimal (base sixteen) value.
The hexadecimal digits also include the letters “A” through “F” which represent the decimal
values of ten through fifteen, respectively. Hexadecimal digits can be either upper or lower
case. Here are some examples for integer literals.

const SCAInt32 i1 = -123; // decimal value -123


const SCAInt32 i2 = 0123; // octal value 123
const SCAInt32 i3 = 0X1A2B3C; // hexidimal value 1A2B3C

Floating-point Literals
A floating-point literal consists of an optional sign character, an integer part, a decimal point, a
fraction part, and optionally a signed integer exponent proceeded by the character “e” or “E”.
The integer and fraction parts both consist of a sequence of decimal (base ten) digits. Either
the integer part or the fraction part, but not both, may be missing; either the decimal point or
the exponent part, but not both, may be missing. The following are some examples for floating
point literals.

const SCAReal64 D1 = 1.23e-10; // integer, fraction and exponent


const SCAReal64 D2 = -1.23; // integer and fraction
const SCAReal64 D3 = .23; // fraction only
const SCAReal64 D4 = 1.; // integer only
const SCAReal64 D5 = 1e10; // integer and exponent
const SCAReal64 D6 = .23e-1 // fraction and exponent

Character Literals
A character literal is one or more character enclosed in single quotes. A character is an 8-bit
quantity defined by the ISO Latin-1 character set which supports a superset of the ASCII
character set. The following escape sequences are supported.

Newline \n
Horizontal tab \t
Vertical tab \v
Backspace \b
Carriage return \r

39
A SCA Hello World Application The IDL Language

Form feed \f
Alert \a
Backslash \\
Question mark \?
Single quote \'
Double quote \"
Octal byte value \ooo
Hexadecimal byte value \xhh

Each escape sequence specifies a single character. The escape “\ooo” consists of the backslash
followed by one, two, or three octal digits that are taken to specify the value of the desired
character. The escape “\xhh” consists of the backslash followed by the character “x” followed
by one or two hexadecimal digits that are taken to specify the value of the desired character. A
sequence of octal or hexadecimal digits is terminated by the first character that is not an octal
or a hexadecimal digit, respectively. The following are some examples for character literals.

const SCAChar C1 = ‘c’; // character c


const SCAChar C2 = ‘\123’; // character with value of octal 123
const SCAChar C3 = ‘\t’; // horizontal tab character
const SCAChar C4 = ‘\XAB’; // character with a value of hex AB

Unicode character literals have an L prefix, for example.

const SCAUChar UC1 = L’c’ // unicode character c

Attempts to assign a wide character literal to a non-wide character constant or to assign a non-
wide character literal to a wide character constant will result in a compile time diagnostic.
String Literals
A string literal is a sequence of characters surrounded by double quotes. Adjacent string
literals are concatenated. Characters in concatenated strings are kept distinct. For example, the
following string contains the two characters “\xA” and “B” after concatenation and not the
single hexadecimal character “xAB”
"\xA" "B"

The size of a string literal is the number of character literals enclosed by the quotes after
concatenation. Within a string, the double quote character " must be preceded (escaped) by a
“\”. A string literal may not contain the null character “\0”. The following are some examples
of string literals.

const SCAString S1 = “this is a string”; // simple string


const SCAString S2 = “\”quoation\””; // embeded double quotes
40
A SCA Hello World Application The IDL Language

const SCAString S3 = “one” “string”; // concatenated string


// = “onestring”
const SCAString S4 = “this is a ” “string”; // concatenated string
// = “this is a string”
const SCAString S3 = “ap” “pear”; // concatenated string
// = “appear”

Unicode string literals have an L prefix, for example:

const SCAUString US1 = L“this is a string”; // unicode string

A unicode string literal may not contain a unicode character with a value of zero.

Attempts to assign a unicode string literal to a non-unicode string constant or to assign a non-
unicode string literal to a unicode string constant will result in a compile time diagnostic.
Constant Expressions
The IDL language offers the arithmetic and bitwise binary operators shown in the following
table.

Operator Meaning
+ Arithmetic addition
- Arithmetic subtraction
* Arithmetic multiplication
/ Arithmetic division
% Arithmetic modulo
| Bitwise OR
& Bitwise AND
^ Bitwise exclusive OR
<< Bitwise left shift
>> Bitwise right shift
~ Bitwise complement

The arithmetic operators apply to both floating-point and integer expressions with the
exception of “%” which must have integer operands. Bitwise operators only apply to integer
expressions. The semantics of these operators are the same as their C++ counterparts with the
following exceptions.

The arithmetic operators do not support mixed-mode expressions. You may not mix
integer and floating-point constants in the same expression. There is no automatic
promotion.
The bitwise shifting operators always perform logical shifts.

41
A SCA Hello World Application The IDL Language

See section Constant Declaration the detailed syntax and semantics of constant expressions.
4.4. Preprocessing
IDL source files are preprocessed to perform file inclusion and macro substitution before
being compiled. Preprocessing is controlled by directives introduced by lines having “#” as
the first non white space character. The preprocessing rules for IDL are the same as defined
for the C and C++ languages.

When coding IDL files, make sure you include the appropriate preprocessor guard definitions
just as you would in a C or C++ header file. These are required to make sure the file will not
get expanded more than once in the same compilation, which can cause compilation errors
due to duplicate definitions of the symbols.

#ifndef TEST_KERNEL_BASEIMPL_IDL_INCLUDED
#define TEST_KERNEL_BASEIMPL_IDL_INCLUDED

#include "SCA/[Link]"

module Test { module Kernel {

interface SCAIBaseImpl : SCAIService


{

};

}; };

#endif

The preprocessor used by the IDL compiler also supports the


normal conditional compilation directives. But you are
strongly discouraged from using them because they may cause
some confusion to the build system.

4.5. SCA IDL Specification


Grammar Notation
The description of OMG IDL grammar in this document uses a syntax notation that is similar
to Extended Backus-Naur Format (EBNF). The following table lists the symbols used in this
format and their meaning.

Symbol Meaning
::= Is defined to be
| Alternatively
<text> Non-terminal
“text” Literal

42
A SCA Hello World Application The IDL Language

* The preceding syntactic unit can be repeated zero or more times


+ The preceding syntactic unit can be repeated one or more times
{} The enclosed syntactic units are grouped as a single syntactic unit
[] The enclosed syntactic unit is optional—may occur zero or one time
IDL Specification
An OMG IDL specification consists of one or more type, constant, exception, interface,
module, service and component definitions. The grammar is:

<specification> ::= <definition>+


<definition> ::= <type_dcl> “;”
| <const_dcl> “;”
| <except_dcl> “;”
| <interface> “;”
| <module> “;”
| <service> “;”
| <component> “;”

See section Type Declaration for the specification of <type_dcl>.

See section Constant Declaration for the specification of <const_dcl>.

See section SCA Exception Declaration the specification of <except_decl>.

See section SCA Interface Declaration for the specification of <interface>.

See section Module Declaration for the specification of <module>.

See section SCA Services Declaration for the specification of <service>.

See section SCA Component Declaration for the specification of <component>.

4.6. Type Declaration


The IDL language provides constructs for naming data types; that is, it provides C language
like declarations that associate an identifier with a type. IDL supports both basic and user
constructed types. The complete grammar for type declarations is:
<type_dcl> ::= “typedef” <type_declarator>
| <struct_type>
| <enum_type>
<type_declarator> ::= <type_spec> <declarators>
<type_spec> ::= <simple_type_spec>
| <constr_type_spec>
<simple_type_spec> ::= <base_type_spec>
| <template_type_spec>
| <scoped_name>
<base_type_spec> ::= <floating_pt_type>
| <integer_type>

43
A SCA Hello World Application The IDL Language

| <char_type>
| <wide_char_type>
| <boolean_type>
| <any_type>
<template_type_spec> ::= <sequence_type>
| <string_type>
| <wide_string_type>
<constr_type_spec> ::= <struct_type>
| <enum_type>
<declarators> ::= <declarator> { “,” <declarator> }
<declarator> ::= <simple_declarator>
| <complex_declarator>
<simple_declarator> ::= <identifier>
<complex_declarator> ::= <array_declarator>
| <dynarray_declarator>
<floating_pt_type> ::= “SCAReal32”
| “SCAReal64”
<integer_type> ::= <signed_int>
| <unsigned_int>
<signed_int> ::= <signed_byte_int>
| <signed_short_int>
| <signed_long_int>
| <signed_llong_int>
<signed_byte_int> ::= “SCAInt8”
<signed_short_int> ::= “SCAInt16”
<signed_long_int> ::= “SCAInt32”
<signed_llong_int> ::= “SCAInt64”
<unsigned_int> ::= <unsigned_byte_int>
| <unsigned_short_int>
| <unsigned_long_int>
| <unsigned_llong_int>
<unsigned_byte_int> ::= “SCAUInt8”
<unsigned_short_int> ::= “SCAUInt16”
<unsigned_long_int> ::= “SCAUInt32”
<unsigned_llong_int> ::= “SCAUInt64”
<char_type> ::= “SCAChar”
<wide_char_type> ::= “SCAWChar”
<boolean_type> ::= “SCABool”
<any_type> ::= “SCAAny”
<struct_type> ::= “struct” <identifier> “{”
<member_list> “}”
<member_list> ::= <member>+
<member> ::= <type_spec> <declarators> “;”
<enum_type> ::= “enum” <identifier> “{”
<enumerator> { “,” <enumerator> } “}”
<enumerator> ::= <identifier>
<sequence_type> ::= “SCASequence”
“<” <simple_type_spec> “>”
<string_type> ::= “SCAString”
<wide_string_type> ::= “SCAWString”
| “SCAUString”
<array_declarator> ::= <identifier> <array_size>
| <identifier> <array_size> <array_size>

44
A SCA Hello World Application The IDL Language

<array_size> ::= “[” <positive_int_const> “]”


<dynarray_declarator> ::= <identifier> “[“ “]”
| <identifier> “[“ “]” “[“ “]”
<scoped_name> ::= <identifier>
| “::” <identifier>
| <scoped_name> “::” <identifier>
<positive_int_const> ::= <const_exp>

The <scoped_name> in <simple_type_spec> must be a previously defined type


introduced by an interface declaration <interface_dcl>, see section SCA Interface
Declaration, or a type declaration <type_dcl>, see section Type Declaration.

An IDL <type_spec>, which can consist of a basic or constructed type, can be used in
operation declarations to assign data types to parameters and in the construction of user
defined data types. The next sections describe the basic and constructed types.
Basic Types
The IDL language supports a number of different basic data types. When specifying the size
of the basic data types, the OMG IDL requirements only specify a lower bound. Since not all
CPU architectures or languages provide the ability to implement exact size definitions, the
range requirements for the IDL types have been left loose. When passing IDL data types
between machines or languages, you are only guaranteed of maintaining the documented data
ranges. For example, you may have code running on a CPU architecture or language that
allows values larger than 16 bits in a SCAInt16 value, but when the data is marshaled to
another CPU type or a different language, which restricts the size to 16 bits, then the data will
be truncated.

All basic data types are subject to changes in representation if they are transmitted between
different CPU architectures. For example, a SCAInt32 value undergoes byte swapping when
sent from a big-endian to a little-endian machine.

The grammar for the basic type declarations is as follows:

<base_type_spec> ::= <floating_pt_type>


| <integer_type>
| <char_type>
| <wide_char_type>
| <boolean_type>
| <any_type>
<floating_pt_type> ::= “SCAReal32”
| “SCAReal64”
<integer_type> ::= <signed_int>
| <unsigned_int>
<signed_int> ::= <signed_byte_int>
| <signed_short_int>
| <signed_long_int>
| <signed_llong_int>
<signed_byte_int> ::= “SCAInt8”
<signed_short_int> ::= “SCAInt16”
<signed_long_int> ::= “SCAInt32”

45
A SCA Hello World Application The IDL Language

<signed_llong_int> ::= “SCAInt64”


<unsigned_int> ::= <unsigned_byte_int>
| <unsigned_short_int>
| <unsigned_long_int>
| <unsigned_llong_int>
<unsigned_byte_int> ::= “SCAUInt8”
<unsigned_short_int> ::= “SCAUInt16”
<unsigned_long_int> ::= “SCAUInt32”
<unsigned_llong_int> ::= “SCAUInt64”
<char_type> ::= “SCAChar”
<wide_char_type> ::= “SCAWChar”
| “SCAUChar”
<boolean_type> ::= “SCABool”
<any_type> ::= “SCAAny”
Integer
The following basic types represent integer values in the ranges indicated.

SCAInt8 -27 to 27 – 1 ≥ 8 bits

SCAInt16 -215 to 215 – 1 ≥ 16 bits


31 31
SCAInt32 -2 to 2 – 1 ≥ 32 bits
SCAInt64 -263 to 263 – 1 ≥ 64 bits
8
SCAUInt8 0 to 2 - 1 ≥ 8 bits
SCAUInt16 0 to 216 - 1 ≥ 16 bits
SCAUInt32 0 to 232 - 1 ≥ 32 bits
64
SCAUInt64 0 to 2 - 1 ≥ 64 bits

Floating-point
A number of different floating-point types are supported. See the IEEE Standard for Binary
Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985, for complete details.

SCAReal32 IEEE single ≥ 32 bits

SCAReal64 IEEE double ≥ 64 bits

Note: The number of bits includes the sign, the mantissa and the exponent. The actual number
of bits in each field is defined in the IEEE standard.
Character
The SCAChar data type is defined as an 8-bit quantity. The ISO Latin-1 character set, which
supports a superset of the ASCII character set, is used. The bottom 128-character positions are
identical to ASCII. The upper 128 character positions are extensions to ASCII that allow most
European languages to be used with an 8-bit character set.

SCAChar -27 to 27 – 1 ≥ 8 bits

46
A SCA Hello World Application The IDL Language

Wide character
The SCAWChar data type that encodes wide characters from any character set. As with
character data, an implementation is free to use any code set internally for encoding wide
characters. The size of a SCAWChar is implementation dependent.

SCAWChar

Booleans
The SCABool data type is used to denote a data item that can only take a value of TRUE or
FALSE. The IDL specification has no requirements on how these values are represented or
about their size.

SCABool TRUE or FALSE ≥ 1 bit

SCAAny
The SCAAny data type is a universal container type that can hold a value of any arbitrary
IDL type with the exception of an exception type. This includes all basic types, user
constructed types and interface types. This allows for interface operations to pass a value
when the actual type is not known before run time. A SCAAny contains a pair of values that
includes a type code value, which describes what type of data is contained, and the actual
value of the data. The language mappings for each IDL data type provide operations that
allow you to insert and extract the type code and data value from a SCAAny.

SCAAny Any IDL type

The SCAAny type can be compared to a void* in C. Like a pointer to a void, a SCAAny
value can denote a value of any type. However, there is an important difference. The void*
denotes a completely type less value that can be interpreted only with advance knowledge of
its contents. In contrast, values of type SCAAny maintain type safety. For example, if the
caller places a string value in a SCAAny, the receiver cannot extract the string as a value of
the wrong type. Attempts to treat the contents of the SCAAny as the wrong type will cause a
run-time error. This is possible because the SCAAny contains a type code value, defining the
type of data stored, which can be used by the language mappings to enforce type safety.

Type codes not only serve to enforce type safety but also provide an introspection capability.
The receiver of the SCAAny value can access the type code to find out what type of value it
contains. This capability is useful because it makes SCAAny values stand-alone data items.
The receiver of the SCAAny can always interpret the value inside it without requiring
additional contextual information.
User Constructed Types
In addition to the basic data types, The IDL language allows you to construct more complex
types like enumerations, structures and arrays.
Enumeration
Enumerated types consist of ordered lists of identifiers. The grammar for an enum is:
<enum_type> ::= “enum” <identifier> “{”

47
A SCA Hello World Application The IDL Language

<enumerator> { “,” <enumerator> }* “}”


<enumerator> ::= <identifier>

The <identifier> in the <enum_type> specification introduces the name of


the new legal data type.

The IDL enumeration is similar to the C++ version except IDL does not allow you to control
the ordinal values of the enumerator values.

enum Grade { A, B, C, D, F };

A maximum of 232 identifiers may be specified in an enumeration. Therefore, the enumerated


names are mapped to a data type capable of representing a 32-bit value.

Enum definitions do not introduce a new namespace. Enumeration value names are
introduced into the enclosing scope and then are treated like any other declaration in that
scope. See section on Scoping Rules for further details.

Enumerated types may also be defined using a typedef declaration, which will introduce an
additional alias for the type.

typedef enum Grade { A, B, C, D, F } MyGrade;

In this example, Grade and MyGrade are now valid IDL type names that can be used to
reference the newly defined enum.
Structure
The IDL language supports structures containing one or more named
members of arbitrary type, including user constructed complex types.
The grammar for the struct type is

<struct_type> ::= “struct” <identifier> “{”


<member_list> “}”
<member_list> ::= <member>+
<member> ::= <type_spec> <declarators> “;”
<declarators> ::= <declarator> { “,” <declarator> }
<declarator> ::= <simple_declarator>
| <complex_declarator>
<simple_declarator> ::= <identifier>
<complex_declarator> ::= <array_declarator>
| <dynarray_declarator>

The <identifier> in the <struct_type> specification introduces the name


of the new legal data type.

The following is an example of a simple structure definition.

struct TimeOfDay

48
A SCA Hello World Application The IDL Language

{
SCAInt8 hour;
SCAInt8 minute;
SCAInt8 second;
};

These definitions can be more complicated by using other constructed types as members.

typedef SCAInt16 MeetingDate[3];


struct MeetingTime
{
SCAInt8 Hour,Minute;
MeetingDate Date;
};
enum MeetingType { REQUIRED, OPTIONAL };
typedef SCASequence<SCAString> MeetingComments;
struct Meeting
{
SCAString Subject;
MeetingTime StartTime,EndTime;
MeetingType Type;
MeetingComments Comments;
};

Structure definitions form a new namespace, so the names of the structure members need to be
unique only within their enclosing structure. The following demonstrates this.

struct FirstStructure { SCAInt32 first; SCAInt32 second; };


struct SecondStructure { SCAInt32 first; SCAInt32 second; };

While this type of definition is legal, it should be considered a bad practice to reuse the same
identifiers for two different purposes.

Structure types may also be defined using a typedef declaration, which will introduce an additional alias for
the type.

Typedef struct TimeOfDay


{
SCAInt8 hour;
SCAInt8 minute;
SCAInt8 second;
} CurrentTime;

In this example, TimeOfDay and CurrentTime are now valid IDL type names that can be
used to reference the newly defined struct.

49
A SCA Hello World Application The IDL Language

The IDL grammar allows for the generation of recursive structures for members that have a
sequence type. For example, the following is a valid IDL definition:

struct Node
{
SCAInt32 value;
sequence<Node> children;
};

This example defines a structure for a Node, which contains a SCAInt32 value and list of
children Nodes.
Fixed-size Array
The IDL language supports multidimensional arrays with fixed-sized
dimensions. A fixed-size array definition must include explicit sizes
for each dimension. Only arrays of rank 1 or 2 are allowed. Arrays of
arbitrary element types are supported in IDL.

The grammar for arrays is:

<array_declarator> ::= <identifier> <array_size>


| <identifier> <array_size> <array_size>
<array_size> ::= “[” <positive_int_const> “]”
<positive_int_const> ::= <const_exp>

The array size, <const_exp>, for each dimension is fixed at compile time and must be a
positive constant integer expression.

When an array is passed as a parameter in an operation invocation, all elements of the array
are transmitted. The implementation of array indices is language mapping specific. Some
language mappings may define the first element in the array as having an index value of zero
and others may use a value of one. As a result, passing of array indices as parameters may
yield incorrect results unless they are correctly handled.

typedef SCAInt32 ArrayOfLongs[100];


typedef TimeOfDay ArrayOfTimes[100];
typedef SCAInt32 MultiDimensionalArray[10][100];

The use a typedef construct to declare an array is required. The


following array definition is invalid.

SCAInt32 ArrayOfLongs[100]; // Error: typedef missing

All array dimensions must be specified in the IDL. Open-ended arrays are not supported
because IDL does not support pointers. The complete size for each data type must be known
at compilation time. Because of this rule, the following definition is invalid.

50
A SCA Hello World Application The IDL Language

typedef SCAString StringTable[][10]; // Error: missing dimension

Dynamic Array
The IDL language also supports multidimensional arrays with dynamic
dimensions which are not set until run time. Only arrays of rank 1 or 2
are allowed. Dynamic arrays differ from fixed-size arrays in that the
actual array dimensions are not determined until run time. Arrays of
arbitrary element types are supported in IDL.

The grammar for arrays is:

<dynarray_declarator> ::= <identifier> “[“ “]”


| <identifier> “[“ “]” “[“ “]”

The array size for each dimension must be left blank and is specified when the array is
allocated at run time.

When a dynamic array is passed as a parameter in an operation invocation, all elements of the
array are transmitted. The implementation of dynamic array indices is language mapping
specific. Some language mappings may define the first element in the array as having an index
value of zero and others may use a value of one. As a result, passing of array indices as
parameters may yield incorrect results unless they are correctly handled.

typedef SCAInt32 ArrayOfLongs[];


typedef TimeOfDay ArrayOfTimes[];
typedef SCAInt32 MultiDimensionalArray[][];

The use a typedef construct to declare an array as is required. The


following array definition is invalid.

SCAInt32 ArrayOfLongs[]; // Error: typedef missing

For convenience, the SCA Framework provides predefined dynamic arrays types for each
basic SCA type. These are described in the section Special SCA Framework Provided Types.
Template Types
SCASequence
The IDL language provides the sequence type that is a one-dimensional array with a length
that is determined at run time.

The grammar for a sequence is:

<sequence_type> ::= “SCASequence”


“<” <simple_type_spec> “>”
<simple_type_spec> ::= <base_type_spec>
| <template_type_spec>
51
A SCA Hello World Application The IDL Language

| <scoped_name>

Variable length arrays of arbitrary element types are supported in IDL


with the sequences type. You must use a typedef construct to declare a
sequence.

typedef SCASequence<SCAInt32> SCAInt32Sequence;


typedef SCASequence<Grade> Grades;
typedef SCASequence<TimeOfDay> Times;

The SCASequence only supports one-dimensional arrays, but defining a sequence of


sequences can approximate a multi-dimensional array.

typedef SCASequence<SCAInt32> SCAInt32Sequence;


typedef SCASequence<SCAInt32Sequence> SequenceOfSequence;

typedef SCASequence< SCASequence<SCAInt32> > SequenceOfSequence;

Notice that in the nested sequence declaration a white space must be used to separate the two
tokens of “>” at the end of the declaration. This is required to keep the two characters from
being parsed as a single token of “>>”.

The SCA Framework does not support bounded sequences as defined by the OMG IDL
specification.

For convenience, the SCA Framework provides predefined sequence types for each basic
SCA type. These are described in the section Special SCA Framework Provided Types.
SCAString
The IDL language provides a string type of SCAString that is a sequence of character values.
ASCII null values of ‘\0’ are not allowed inside IDL strings. Strings are singled out as a
separate data type because many languages have special built-in or standard library functions
for string manipulation. A separate string type may permit substantial optimization in the
handling of strings compared to what can be done with sequences of characters.

The grammar for a string declaration is:

<string_type> ::= “SCAString”

The SCA Framework does not support bounded string types as defined by the OMG IDL
specification.
SCAUString
The SCA Kernel provides a unicode string type of SCAUString that is a sequence of unicode
character values. Unicode strings are singled out as a separate data type because many
languages have special built-in or standard library functions for unicode string manipulation.

52
A SCA Hello World Application The IDL Language

A unicode separate string type may permit substantial optimization in the handling of strings
compared to what can be done with sequences of characters.

The grammar for a string declaration is:

<wide_string_type> ::= “SCAUString”


| “SCAWString”
The SCA Framework does not support bounded string types as defined by the OMG IDL
specification.

SCAWString (deprecated)
The IDL language provides a wide string type of SCAWString that is a sequence of wide
character values. Wide character null values of L’\0’ are not allowed inside IDL wide strings.
Wide strings are singled out as a separate data type because many languages have special
built-in or standard library functions for wide string manipulation. A wide separate string type
may permit substantial optimization in the handling of strings compared to what can be done
with sequences of characters.

The grammar for a string declaration is:

<wide_string_type> ::= “SCAWString”


| “SCAUString”

The SCA Framework does not support bounded string types as defined by the OMG IDL
specification.

The SCA Framework is migrating away from supporting wstring and wchar in favor of their
Unicode equivalent types: SCAUString and SCAUChar. Existing interfaces will continue to
support wstring and wchar types to give applications some time to convert but these types will
eventually be deprecated. All new SCA interfaces will support SCAUString and SCAUChar
only.

Aliases to Other Types


The typedef construct can be used to create a new type name or alias for any other valid IDL
type. The grammar for a typedef declaration is as follows:

<type_dcl>
::= “typedef” <type_declarator>
<type_declarator>
::= <type_spec> <declarators>
<declarators>
::= <declarator> { “,” <declarator> }
<declarator>
::= <simple_declarator>
| <complex_declarator>
<simple_declarator> ::= <identifier>
<complex_declarator> ::= <array_declarator>

Some simple examples of typedef declarations follow:

typedef SCAInt16 YearType;

53
A SCA Hello World Application The IDL Language

typedef SCAInt16 MonthType;

These types of specifications can make the IDL file more readable and self-documenting. This
example would indicate to the reader that the values represent a year or month, rather than the
more generic SCAInt16 type.

For more complex data types, the typedef construct can be used to define the data type and
create an alias for it in the same statement.

typedef sequence <SCAInt32> SCAInt32Sequence;

typedef struct Time


{
SCAInt8 hour;
SCAInt8 minute;
SCAInt8 second;
} CurrentType;

typedef enum Color { RED, BLUE, GREEN } CurrentColor;

typedef SCAInt32 ArrayOfLongs[100];

Sequences versus Arrays


Sequences and the two arrays types are similar because they all provide a vector of elements
of the same type. The three types of vectors are provided to allow more efficient mappings in
the various languages. In some languages, the mappings for some of the vector types may be
the same and in others they may all be different. The language dependent mappings have been
chosen to optimize performance and to provide various memory management models where
appropriate. You should consult the IDL mapping section for your language for complete
details.

Here are some general guidelines to help you decide whether a sequence or an array is the
more appropriate type.

If the length of the list is not known at compilation time, either a dynamic array or a
sequence must be used.
If you have a fixed length list and all of the elements exist all of the time, use either the
fixed-size array or the dynamic array.
If you have a variable length list, even if the upper bound on the size is known at compile
time, it may be more efficient to use a sequence rather than an array.

Consider the following IDL example for the definition of a matrix.

typedef SCAReal32 Matrix[100][100];

54
A SCA Hello World Application The IDL Language

This definition defines a square matrix of dimension 100. It also will cause the allocation of
10,000 storage locations, which could be very inefficient if the matrix is sparse. If this matrix
is passed out-of-proc, it is even more inefficient because all 10,000 values will be transmitted,
even if only a few are used. In contrast, consider the following IDL definition which could be
used to define a sparse matrix storage scheme.

struct MatrixElement
{
SCAUInt32 row;
SCAUInt32 col;
SCAReal32 value;
};
typedef sequence<MatrixElement> Matrix;

This definition is more efficient in both storage and transmission time because only the
meaningful matrix elements will be stored and processed.

4.7. Constant Declaration


The grammar for a constant declaration in the IDL language is:

<const_dcl> ::= “const” <const_type>


<identifier> “=” <const_exp>
<const_type> ::= <integer_type>
| <char_type>
| <wide_char_type>
| <boolean_type>
| <floating_pt_type>
| <string_type>
| <wide_string_type>
| <scoped_name>
<const_exp> ::= <or_expr>
<or_expr> ::= <xor_expr>
| <or_expr> “|” <xor_expr>
<xor_expr> ::= <and_expr>
| <xor_expr> “^” <and_expr>
<and_expr> ::= <shift_expr>
| <and_expr> “&” <shift_expr>
<shift_expr> ::= <add_expr>
| <shift_expr> “>>” <add_expr>
| <shift_expr> “<<” <add_expr>
<add_expr> ::= <mult_expr>
| <add_expr> “+” <mult_expr>
| <add_expr> “-” <mult_expr>
<mult_expr> ::= <unary_expr>
| <mult_expr> “*” <unary_expr>
| <mult_expr> “/” <unary_expr>
| <mult_expr> “%” <unary_expr>
<unary_expr> ::= <unary_operator> <primary_expr>
| <primary_expr>

55
A SCA Hello World Application The IDL Language

<unary_operator> ::= “-”


| “+”
| “~”
<primary_expr> ::= <scoped_name>
| <literal>
| “(” <const_exp> “)”
<literal> ::= <integer_literal>
| <string_literal>
| <character_literal>
| <floating_pt_literal>
| <boolean_literal>
<boolean_literal> ::= “TRUE”
| “FALSE”
<positive_int_const> ::= <const_exp>
<scoped_name> ::= <identifier>
| “::” <identifier>
| <scoped_name> “::” <identifier>

The <scoped_name> in the <const_type> definition must be a previously defined


name of an <integer_type>, <char_type>, <wide_char_type>,
<string_type>, <wide_string_type>, <enum_type> <boolean_type>
or <floating_pt_type> constant. The value of a <positive_int_const>
expression must evaluate to a positive integer constant.
One side effect of a constant type definition is the <identifier> in the
<const_dcl> specification introduces the name of the new legal data type
with the same type as <const_type>. This can be confusing if you use
this type for any other purposes in the IDL definitions. Consider the
following example.

const SCAInt32 ConstType = 123;

interface Inf
{
SCAVoid meth1 ( in ConstType inval );
SCAVoid meth2 ( in SCAInt32 inval );
};

In this example the signature for both methods in the interface definition will be identical. This
is because the first method is just defining a parameter of type ConstType which is the same
as SCAInt32. It is not defining parameter with a value of “123”. To avoid this confusion you
should not use the type names introduced by constant definitions in any other places in the
IDL. They should only used by the implementation code where normal constant can appear.
For example it is perfectly fine to use the constant value as a parameter value in a call to an
interface method, but it is not appropriate to use in the declaration of a method.

Only integer values can be assigned to integer (SCAInt8, SCAInt16, SCAInt32 and
SCAInt64) constants. Only positive integer values can be assigned to unsigned integer
(SCAUInt8, SCAUInt16, SCAUInt32 and SCAUInt64) constants. If the value of the right
hand side of an integer constant declaration is too large to fit in the actual type of the constant,

56
A SCA Hello World Application The IDL Language

or the value is inappropriate for the actual type of the left hand side, it is flagged as a compile
time error.

const SCAInt16 s = 655592; // Error: value to large


const SCAUInt16 o = -54; // Error: negative value in unsigned type

Only floating-point values can be assigned to floating point (SCAReal32 and SCAReal64)
constants. If the value of the right hand side is too large to fit in the actual type of the constant
to which it is being assigned it is flagged as a compile time error.

A binary operator can combine two integers or two floats, but not mixtures of these. Binary
operators are applicable only to integer and float-point types.

If the type of an integer constant is a SCAInt8, SCAUInt8, SCAInt16, SCAUInt16,


SCAInt32 or SCAUInt32, then each sub expression of the associated constant expression is
treated as a signed SCAInt32 or unsigned SCAUInt32 value accordingly. It is an error if any
sub expression values exceed the precision of the SCAInt32 or SCAUInt32 type, or if a final
expression value exceeds the precision of the target type. A similar rule applies to SCAInt64
and SCAUInt64 constants.

If the type of a floating-point constant is SCAReal64, then each sub expression of the
associated constant expression is treated as a SCAReal64. It is an error if any sub expression
value exceeds the precision of SCAReal64.

Unary (+ -) and binary (* / + -) operators are applicable in floating-point expressions. Unary


(+ - ~) and binary (* / % + - << >> & | ^) operators are only applicable in integer
expressions.

The “~” unary operator indicates that the bit-complement of the expression to which it is
applied should be generated. For the purposes of such expressions, the values are 2’s
complement numbers. As such, the complement can be generated as follows:

Integer Expression Type Generated 2’s Complement Numbers


SCAInt32 SCAInt32 -(value+1)
SCAUInt32 SCAUInt32 (2**32-1) - value
SCAInt64 SCAInt64 -(value+1)
SCAUInt64 SCAUInt64 (2**64-1) - value

The “%” binary operator yields the remainder from the division of the first expression by the
second. If the second operand is zero, the result is undefined. If both operands are
nonnegative, then the remainder is nonnegative; if not, the sign of the remainder is
implementation dependent.

The “<<” binary operator indicates that the value of the left operand should be shifted left the
number of bits specified by the right operand with zero fill for the vacated bits. The right
operand must be in the range 0 <= right operand < 64.

57
A SCA Hello World Application The IDL Language

The “>>” binary operator indicates that the value of the left operand should be shifted right
the number of bits specified by the right operand with zero fill for the vacated bits. The right
operand must be in the range 0 <= right operand < 64.

The “&” binary operator indicates that the logical, bitwise AND of the left and right operands
should be generated.

The “|” binary operator indicates that the logical, bitwise OR of the left and right operands
should be generated.

The “^” binary operator indicates that the logical, bitwise EXCLUSIVE-OR of the left and
right operands should be generated.

An enum constant can only be defined using a correctly scoped name for the enumerator. The
scoped name is resolved using the normal scope resolution rules described in section Scoping
Rules. For example:

enum Color { red, green, blue };


const Color FAVORITE_COLOR = red;

module M {
enum Size { small, medium, large };
};
const M::Size MYSIZE = M::medium;

The constant name for the right hand size of an enumerated constant definition must denote
one of the enumerators defined for the enumerated type of the constant. For example:

const Color col = red; // OK


const Color another = M::medium; // Error: medium is not a Color

Constant definitions in IDL are not permitted for user constructed complex types of structures
or arrays.

The following are some examples of constant definitions.

const SCAString Version = “Version 10.3”;


const SCAUString ustr = L“Test wide string”;
const SCAReal32 Pi = 3.14159;
const SCAChar Null = ‘\0’;
const SCAWChar wchr = ‘A’;
const SCABool myTrue = TRUE;
enum Color { RED, GREEN, BLUE };
const Color Favorite_Color = RED;
const SCAReal32 Test1 = (1.0+4.0-2.0)*20.0/2.0;
const SCAInt32 Test2 = (1+4-2)*20/2;

58
A SCA Hello World Application The IDL Language

const SCAUInt32 Test3 = ~2;


const SCAInt32 Test4 = 100 % 12;
const SCAInt32 Test5 = 2 << 4;
const SCAInt32 Test6 = 32 >> 4;
const SCAInt32 Test7 = 1 | (1<<4) | (1<<8);
const SCAInt32 Test8 = 0x1234 & 0xF;
const SCAInt32 Test9 = 0xF ^ 0x5;

4.8. Modules, Name Lookup and Scoping


Module Declaration
The IDL language uses the module construct to create a namespace. Namespaces combine
related definitions into a logical group and prevent the pollution of the global namespace. A
module definition satisfies the following grammar:

<module> ::= “module” <identifier> “{“


<definition>+ “}”

A <definition> is any valid IDL specification as shown in section SCA IDL


Specification. Nested module definitions are supported as the following example illustrates.

module SCA
{
module FileReader
{
// Some definitions here
};
};

Modules are similar to C++ namespaces in that they can be reopened to add additional
definitions.

module A
{
// Some definitions here
};

module B
{
// Some definitions here
};

module A
{
// Reopen module A and add some definitions to it
};

59
A SCA Hello World Application The IDL Language

Name Lookup Rules


IDL identifiers are case insensitive; that is, two identifiers that differ only in the case of their
characters are considered redefinitions of one another. However, all references to a definition
must use the same case as the defining occurrence. This allows natural mappings to case-
sensitive languages. For example:

module M
{
typedef SCAInt32 Long; // Error: Long clashes with keyword long
typedef SCABool MyBool;
interface I {
typedef SCAInt32 MyLong;
SCAResult meth1(
in myLong val; // Error: inconsistent capitalization
in MyBool mybool; // Error: MyBool clashes with mybool
);
};
};

Qualified Names
A qualified name, of the form scope::identifier, is resolved by first resolving the qualifier
scope in scope S, where S is the current scope, and then locating the definition of identifier
within S::scope. If the qualified name is not found in S, then each of S’s enclosing scopes will
be checked. The identifier must exist in the namespace scope; it is not searched for directly in
the enclosing scopes of S. Consider the following example

module A { module B {
typedef C::X mytype;
}; };

The following fully qualified names will be tried to find X


::A::B::C::X
::A::C::X
::C::X

The following fully qualified names will NOT be tried to find X


::A::B::X
::A::X
::X

When a qualified name begins with “::”, the resolution process will only look in the file or
global scope and not look in any intermediate enclosing scopes. For example:

module A { module B {
typedef ::C::X mytype;
}; };

The only fully qualified name that will be tried to find X


::C::X

60
A SCA Hello World Application The IDL Language

Inheritance causes all of the identifiers defined in the base interfaces, both direct and indirect,
to be visible in the derived interfaces. Such identifiers are considered to be semantically the
same as the original definitions.

interface CBase
{
typedef long X;
};
interface C : CBase
}
};

Either of the following references are identical


typedef CBase::X mytype1;
typedef C::X mytype2;

Scoping Rules
The scoping rules used in IDL are the same as in C++. The IDL compiler searches for the
definition of an identifier from the innermost scope outward toward the outermost scope.

The entire contents of an IDL file, together with the contents of any files referenced by
#include statements, forms a naming scope. Definitions that do not appear inside a scope are
part of the global scope. There is only a single global scope, irrespective of the number of
source files that form a specification. The following IDL definitions form new naming scopes:

module
struct
interface
interface operation

The appearance of a declaration for any of these in any scope opens a nested scope associated
with that declaration. An identifier can only be defined once in a scope. However, identifiers
can be redefined in nested scopes. An identifier declaring a module is defined by its first
occurrence in a scope. Subsequent occurrences of a module declaration with the same
identifier within the same scope reopens the module and hence its scope, allowing additional
definitions to be added to it.

The name of an interface, struct, or a module may not be redefined within the immediate
scope of the interface, struct, or the module. For example:

module Test
{
typedef SCAInt16 Test; // Error: Test is the name of the module
interface Inf
{
SCAResult inf ( ); // Error: inf clashes with interface Inf

61
A SCA Hello World Application The IDL Language

};
};

Enum definitions do not introduce a new scope. Enumeration value names are introduced into
the enclosing scope and then are treated like any other declaration in that scope. For example:

module Test
{
enum VAL { E1, E2, E3 };
enum BAD { E3, E4, E5 }; // Error: Test::E3 is already defined
};

4.9. SCA Interface Declaration


An interface definition satisfies the following grammar:
<interface> ::= <interface_dcl>
| <forward_dcl>
<interface_dcl> ::= <interface_hdr> “{”
<interface_body> “}”
<forward_dcl> ::= “interface” <identifier>
<interface_hdr> ::= “interface” <identifier>
[ <inheritance_spec> ]
<interface_body> ::= <export>*
<export> ::= <type_dcl> “;”
| <const_dcl> “;”
| <op_dcl> “;”
<inheritance_spec> ::= “:” <inferface_name> { “,”
<interface_name> }*
<interface_name> ::= <scoped_name>
<scoped_name> ::= <identifier>
| “::” <identifier>
| <scoped_name> “::” <identifier>
<op_dcl> ::= <op_type_spec> <identifier>
<parameter_dcls> [ <raises_expr> ]
<op_type_spec> ::= “SCAResult”
<parameter_dcls> ::= “(” <param_dcl>
{ “,” <param_dcl> }* “)”
| “(” “)”
<param_dcl> ::= <param_attribute> <param_type_spec>
<simple_declarator>
<param_attribute> ::= “in”
| “out”
| “inout”
<raises_expr> ::= "raises" "(" <scoped_name>
{"," <scoped_name> }* ")"
<param_type_spec> ::= <base_type_spec>
| <string_type>
| <wide_string_type>
| <scoped_name>

62
A SCA Hello World Application The IDL Language

Interface Header
The interface header consists of these elements:

The keyword interface.


The interface name consists of an <identifier> that names the interface. The SCA
Framework uses the convention that all interface names should begin with the prefix
SCAI but this is not enforced by the IDL compiler.
An optional inheritance specification, which consists of, a colon followed by a comma-
separated list of interfaces that are inherited from.
Definition of the interface body enclosed by the characters “{“ and “}”.

interface A {};
interface B : A {};
interface C : A, B {};

The <identifier> that names an interface introduces a new legal type name. Such a type
name may be used anywhere an <identifier> is legal in the grammar.
Interface Inheritance Specification
The grammar for interface inheritance is as follows:

<inheritance_spec> ::= “:” <inferface_name> { “,”


<interface_name> }*
<interface_name> ::= <scoped_name>

Each <scoped_name> in an <inheritance_spec> must denote a previously defined


interface. See section Interface Inheritance for the description of how interface inheritance is
use in the SCA Framework.
Interface Body
The interface body can contain the following kinds of declarations:

Type declarations, which specify the type definitions that the interface exports as
described in section Type Declaration.
Constant declarations, which specify the constants that the interface exports as described
in section Constant Declaration.
Operation declarations, which specify the operations that the interface exports and the
format of each, including operation name, the type of data returned and the types of all
parameters for the operation. Operation declarations are described in section Operation
Declaration.

Although it is legal to include type and constant definitions inside an interface body, it is a
discouraged practice. This is because the required language mapping for these types is not
always obvious and can lead to undesirable implementation code.

63
A SCA Hello World Application The IDL Language

Empty interfaces, that contain no declarations, are permitted.


Operation Declaration
Operation declarations in the IDL language are similar to C++ method declarations. The
grammar is:

<op_dcl> ::= <op_type_spec> <identifier>


<parameter_dcls> [ <raises_expr> ]
<op_type_spec> ::= “SCAResult”
<parameter_dcls> ::= “(” <param_dcl>
{ “,” <param_dcl> }* “)”
| “(” “)”
<param_dcl> ::= <param_attribute> <param_type_spec>
<simple_declarator>
<param_attribute> ::= “in”
| “out”
| “inout”
<raises_expr> ::= "raises" "(" <scoped_name>
{"," <scoped_name> }* ")"
<param_type_spec> ::= <base_type_spec>
| <string_type>
| <wide_string_type>
| <scoped_name>

An operation declaration consists of:

The type of the operation’s return result.


An identifier that names the operation in the scope of the interface
in which it is defined.
A parenthesized, comma separated parameter list that specifies zero
or more parameter declarations for the operation.
An optional raises clause that identifies which exceptions the
operation may throw.

Each parameter declaration consists of three parts.

A directional attribute for the parameter.


The type of the parameter that may be any type that is defined in IDL.
An identifier that names the parameter. Since the parameter list for
each operation opens a new naming scope, the names only need to be
unique in the same list.

Each parameter declaration must have a directional attribute that


informs the framework the direction in which the parameter is to be
passed. This is different than a parameter definition in a C++ method.
The directional attributes are as follows:

in The parameter is passed from caller


to callee.
out The parameter is passed from callee
to caller.

64
A SCA Hello World Application The IDL Language

inout The parameter is passed in both


directions.

It is expected that an implementation will not attempt to modify an in parameter. The ability to
even attempt to do so is language-mapping specific. The effect of such an action is undefined.

The following are valid operation definitions.

interface A
{
SCAResult meth1 ( );
SCAResult meth2 ( out SCAInt32 val );
SCAResult meth3 ( in SCABool ival, out SCAInt32 oval,
inout SCAString ioval );
};

An IDL operation may have an optional raises clause. The raises clause defines what type
of exceptions the method may throw. The syntax is defined as follows:

<raises_expr> ::= "raises" "(" <scoped_name>


{"," <scoped_name> }* ")"

Where <scoped_name> is any valid IDL exception specification as show in


section SCA Exception Declaration.

You may also specify one of the built-in exceptions, SCASystemException,


SCAUserException or SCAException, in the raises clause. The following shows an
example of the raises clause.

interface A
{
SCAResult meth1 ( )raises (Exception1, Exception2);
SCAResult meth2 ( )raises (SCAException);
};

Forward Declarations
It is valid for interface-defined types to be passed as parameters to operations. Occasionally,
interfaces are mutually dependent to each other; each one is expecting a parameter of the
other’s type. This can present a problem because the IDL compiler is a one-pass compiler
and all types must be defined before being used. In this case a forward declaration can be
used to resolve the problem.

A forward declaration declares the name of an interface without defining it. This interface can
then be used as a parameter in another interface definition. Multiple forward declarations of
the same interface name are legal. It is illegal to inherit from a forward-declared interface that
has not yet been defined.

65
A SCA Hello World Application The IDL Language

module Example
{
interface A; // Forward declaration of A
interface B // Full declaration of B
{
SCAResult meth ( in A inf ); // Use forward declared A
};
interface A // Full declaration of A
{
SCAResult meth ( in B inf ); // Use fully declared B
};
};

Interface Inheritance
An interface can be derived from another interface, which is then called a base interface of the
derived interface. A derived interface, like all interfaces, may declare new constants, types,
and operations. In addition, unless redefined in the derived interface, the elements of a base
interface can be referred to as if they were elements of the derived interface. The name
resolution operator “::” may be used to refer to a base element explicitly. This permits
reference to a name that has been redefined in the derived interface. A derived interface may
redefine any of the types or constants that have been inherited. A derived interface may not
redefine operations that have been inherited.

An interface is called a direct base if it is mentioned on the interface definition and an indirect
base if it is not a direct base but is a base interface of one of the interfaces that is inherited
from. An interface may be derived from any number of base interfaces, which is often referred
to as multiple inheritance. The order of derivation is not significant except that is should never
be changed once it has been set. An interface may not be specified as a direct base interface of
a derived interface more than once, but it may be an indirect base interface more than once.
Consider the following valid examples:

interface A { ... };
interface B: A { ... }; // Direct base of A
interface C: A { ... }; // Direct base of A
interface D: B, C { ... }; // Multiple indirect bases of A
interface E: A, B { ... }; // A is both a direct and indirect base

References to base interface elements must be unambiguous. A reference to a base interface


element is ambiguous if the name is declared as a constant or type in more than one base
interface. Ambiguities can be resolved by qualifying a name with its interface name. Consider
the following examples:

interface A
{
typedef SCAInt32 L1;
SCAResult meth1(in L1 l_1);
};
interface B

66
A SCA Hello World Application The IDL Language

{
typedef SCAInt16 L1;
SCAResult meth2(in SCAInt32 l);
};
interface C: B, A
{
typedef L1 L2; // Error: L1 ambiguous
typedef A::L1 L3; // OK: A::L1 is not ambiguous
SCAResult meth1
(
in L3 val1, // OK: L3 is not ambiguous
in B::L1 val2 // OK: B::L1 is not ambiguous
);
};

Overloading of operation definitions is not allowed. This means it is illegal to inherit from two
interfaces containing the same operation name, or to redefine an operation in the derived
interface. This is required because operation names are used at run-time with dynamic
interfaces and in scripting and must be unique. Also, not all implementation languages support
operation overloading.

interface A
{
SCAResult meth1();
};
interface B: A
{
SCAResult meth1(in long times); // Error: redefinition of meth1
};

SCAIService Interface
The SCA Framework requires that all interfaces inherit, either directly
or indirectly form the SCAIService interface. The SCAIService interface
defines the methods used to support interface navigation, reference
counting and runtime introspection. You need to include the file that
defines this interface, “SCA/[Link]”, in your IDL file unless it
is already included in another include file that you are using. The
following is the definition of the SCAIService interface.

Module SCA {
interface SCAIService
{
SCAVoid addReference();
SCAVoid releaseReference( out SCAVoidPtr pPublisher );
SCAResult getInterface( in SCAString sName,
out SCAVoidPtr pIface );
SCAString getImplName();
SCAInt32 getInstanceID();
};
};

67
A SCA Hello World Application The IDL Language

The following example shows two valid SCA interface definitions. The first interface directly
inherits from the SCAIService interface and the second one indirectly inherits from it.

#include “SCA/[Link]”

module Test {

interface SCAITest1 : SCA::SCAIService


{
SCAResult meth1();
};

interface SCAITest2: SCAITest1


{
SCAResult meth2();

};

Since every interface must inherit from the SCAIService interface, the IDL compiler will
generate all the code that is normally required to implement its methods.

4.10. SCA Exception Declaration


The IDL language supports exception declarations containing zero or
more named members of arbitrary type, including user constructed
complex types. The grammar for the exception is similar to the struct
type with several differences. Exceptions are allowed to inherit from
other exceptions but inheritance is not supported on structures. Also
it is possible to define an exception type with zero members. The
following is the grammar for the exception type.

<except_dcl> ::= "exception" <identifier>


[ <except_inherit> ] "{" <member>* "}"
<except_inherit> ::= ":" <scoped_name>
<member> ::= <type_spec> <declarators> “;”
<declarators> ::= <declarator> { “,” <declarator> }
<declarator> ::= <simple_declarator>
| <complex_declarator>
<simple_declarator> ::= <identifier>
<complex_declarator> ::= <array_declarator>
| <dynarray_declarator>
[ <except_inherit> ] "{" <member>* "}"

The <identifier> in the <except_dcl> specification introduces the name of


the new legal data type. These identifiers may appear only in an
exception inheritance <except_inherit> clause or a raises clause in an
interface operation definition described in section Operation
Declaration. Exception identifiers are not allowed to be used for any
other purpose.

The following is an example of SCA IDL exception definition.

68
A SCA Hello World Application The IDL Language

exception MyException : SCAUserException {


SCAInt32 id;
SCAString value;
};

exception MyException2 : MyException {


SCAString extradata;
};

4.11. Special SCA Framework Provided Types


The SCA Framework SDK delivery includes many IDL files which define types supported by
the framework. But, most of these types are no different than the types you define in the
components you deliver. There are a few exceptions to this. The framework also provides a
number of special types, described in this section, that are treated differently for the following
reasons.

Some types are provided for convenience because they tend to be useful to all developers.
In this case it is better to use the framework provided types rather than defining your own
for the purpose of consistency.
Some of these types are provided because they utilize special language specific mappings
to provide the required functionality. In many of these cases the framework provided
special implementation classes for these types in each supported language.

The following special types can be thought of as new basic types provided by the SCA
Framework. The IDL compiler treats them the same as any other IDL provided type but they
are so fundamental to the workings of the framework that it provides special implementations
for each.

module SCA {

// Type for holding return values and error messages


struct SCAResult
{
SCAInt32 errorCode;
SCAInt32 messageTable;
SCAInt32 messageID;
SCAAnySequence params;
};

// UUID definition for SCA Types


struct SCAUUID {
SCA::SCAUInt64 part1;
SCA::SCAUInt64 part2;
};

};

69
A SCA Hello World Application The IDL Language

The following exception types are predefined by the SCA framework.

module SCA {

// Base for all SCA exceptions


exception SCAException{};

// Base for all User defined exceptions


exception SCAUserException: SCAException{};

// Base for all System defined exception


exception SCASystemException: SCAException {
SCAInt32 id;
};

};

The following sequence and dynamic array types are provided by the framework. These are
provided for convenience and to since many components required similar definitions it is
more consistent if everyone uses the same ones.

module SCA {

// Standard sequence types


typedef sequence<SCAInt8> SCAInt8Sequence;
typedef sequence<SCAUInt8> SCAUInt8Sequence;
typedef sequence<SCAInt16> SCAInt16Sequence;
typedef sequence<SCAUInt16> SCAUInt16Sequence;
typedef sequence<SCAInt32> SCAInt32Sequence;
typedef sequence<SCAUInt32> SCAUInt32Sequence;
typedef sequence<SCAInt64> SCAInt64Sequence;
typedef sequence<SCAUInt64> SCAUInt64Sequence;
typedef sequence<SCAReal32> SCAReal32Sequence;
typedef sequence<SCAReal64> SCAReal64Sequence;
typedef sequence<SCAChar> SCACharSequence;
typedef sequence<SCAWChar> SCAWCharSequence;
typedef sequence<SCAString> SCAStringSequence;
typedef sequence<SCAUString> SCAUStringSequence;
typedef sequence<SCABool> SCABoolSequence;
typedef sequence<SCAAny> SCAAnySequence;
typedef sequence<SCATypeCode> SCATypeCodeSequence;

// Define some standard dynamic array types


typedef SCAInt8 SCAInt8DynamicArray[];
typedef SCAUInt8 SCAUInt8DynamicArray[];
typedef SCAInt16 SCAInt16DynamicArray[];
typedef SCAUInt16 SCAUInt16DynamicArray[];
typedef SCAInt32 SCAInt32DynamicArray[];
typedef SCAUInt32 SCAUInt32DynamicArray[];
typedef SCAInt64 SCAInt64DynamicArray[];
typedef SCAUInt64 SCAUInt64DynamicArray[];
typedef SCAReal32 SCAReal32DynamicArray[];
typedef SCAReal64 SCAReal64DynamicArray[];

70
A SCA Hello World Application The IDL Language

typedef SCAChar SCACharDynamicArray[];


typedef SCAWChar SCAWCharDynamicArray[];
typedef SCAString SCAStringDynamicArray[];
typedef SCAUString SCAUStringDynamicArray[];
typedef SCABool SCABoolDynamicArray[];
typedef SCAAny SCAAnyDynamicArray[];
typedef SCATypeCode SCATypeCodeDynamicArray[];

};

4.12. SCA Services Declaration


The SCA IDL language allows for the definition of SCA services. The definition of services
should always be placed in source files with the extension of “.sdl” and these SDL files
should only contain service definitions. Only one service definition is allowed in each SDL
file.

The IDL compiler uses the service definitions in SDL files to generate sample implementation
code skeletons for a service in one of the supported languages. See the IDL mapping section
for your language for the complete details.

The IDL compiler also uses the service definitions to generate support code that links the
developer’s implementation code to the SCA Framework. This code is automatically
generated, compiled and linked with the SCA services you build.

When designing the implementation for a SCA service, the developer is free to structure the
code any way they wish. Usually the implementation of a service will be split among several
different classes. In some cases the IDL compiler needs to understand this structure. In
general, the following types of classes might be used.

The Top-Level class that is instantiated when an instance of the service is requested. This
class must implement at least one SCA interface. This class is referred to as the Top-Level
service class.
Additional classes may be instantiated that also implement SCA interfaces. Pointers to
instances of these classes, in the form of interface references, may then be passed outside
of the service to other SCA services. These classes are referred to as Sub-Service classes.
Additional classes may be instantiated that do not implement SCA interfaces. Because
these classes do not implement any SCA interfaces, pointers to them cannot be passed
outside of the service. They can only be used internally as part of the implementation of
the service.

Of these three types of classes, the IDL compiler only needs to be aware of the first two
because they each implement SCA interfaces. Since interface references to any instance of
these classes may be passed outside of the service, appropriate support code is generated to
control the life cycle of these instances to insure that they will be deleted when no longer
referenced.

71
A SCA Hello World Application The IDL Language

When coding SDL definitions, the general rule is that any class in the implementation of a
service that implements a SCA interface must be declared in the SDL file. The declaration
must also include, either directly or indirectly, all of interfaces that each class implements.
Because interfaces can inherit from other interfaces, if the SDL specifies that a class
implements a specific interface, then the class must also implement all interfaces that it is
derived from. Because of this it is not required that you specify every base interface in your
SDL definitions. It is only required that you include the most derived interfaces.

The structure of the Top-Level service class and Sub-Service classes is very similar but do
differ because of the way instances of them are created. An instance of the Top-Level class is
only triggered when a SCA Framework request is made for a new instance of the service.
There is no provision for this type of request to include any parameters that can be passed to
the service instance when it is constructed. Sub-Service classes, however, can only be
instantiated from within the implementation code of a service. It is reasonable to assume that
there will be a need to initialize these classes so this information can also be provided in the
definition of Sub-Service classes.

The grammar of a SCA service definition is as follows:

<service> ::= <service_dcl> “{“ <service_body> “}”


<service_dcl> ::= “service” <service_name>
< service_name > ::= <identifier>
| < service_name > “.” <identifier>
<service_body> ::= <service_entry>+
<service_entry> ::= <option_dcl> “;”
| <interface_ref> “;”
| <sub_service> “;”
<option_dcl> ::= <option>+
<option> ::= “singleton”
| “delegate”
| “inherit”
| “aggregates”
| “aggregated”
<interface_ref> ::= “interface” <scoped_name>
<scoped_name> ::= <identifier>
| “::” <identifier>
| <scoped_name> “::” <identifier>
<sub_service> ::= <subservice_dcl>
“{“ <sub_service_body> “}”
<sub_service_dcl> ::= “subservice” <identifier>
[ <parameter_dcls> ]
<parameter_dcls> ::= “(” <param_dcl>
{ “,” <param_dcl> }* “)”
| “(” “)”
<sub_service_body> ::= <sub_service_entry>+
<sub_service_entry> ::= <interface_ref> “;”

A service definition consists of these elements:

The keyword service

72
A SCA Hello World Application The IDL Language

The fully qualified dotted service name


Definition of the service body enclosed by the characters “{“ and “}”

service [Link] {};

The fully qualified dotted service name serves several purposes. For complete details on these
see section IDL/SDL/CDL Names, Namespaces and Directories.

The body of a service definition consists of the following elements in any order.

Zero or more service option specifications.


One or more interface references for the interfaces that the Top-Level service class
will implement. The interface names must be normally scoped names that resolve
to previously defined interfaces.
Zero or more Sub-Service definitions.

The following example shows a service that implements one interface.

service A.B.C.MyService1
{
interface Inf1;
};

Since the service class must also implement all base classes of the specified interface, in
reality this service class will implement a minimum of two interfaces. The second interface is
SCA::SCAIService which is the common base class for all SCA interfaces. It may also
implement additional interfaces depending on the actual definition of the Inf1.

You may also specify more the one interface for the service class.

service A.B.C.MyService2
{
interface Inf1;
interface Inf2;
};

You may need to also specify some options for the service.

service A.B.C.MyService3
{
singleton;
delegate;
interface Inf1;

73
A SCA Hello World Application The IDL Language

};

A Sub-Service definition consists of these elements.

The keyword subservice.


An optional parenthesized initialization parameter list for the Sub-Service class that is
passed to the class when it is instantiated.
Definition of the Sub-Service body enclosed by the characters “{“ and “}”

The grammar for the optional parameter list for a Sub-Service is the same as for an interface
operation and is described in section Operation Declaration. Generally, the only parameter
types that are allowed in the parameter list are those that can be defined in the IDL. But, in
some languages it is possible to pass non-IDL pointer types using the special SCAVoidPtr
type.

The Sub-Service body contains one or more interface references for the interfaces this Sub-
Service class will implement. The interface names must be normally scoped names that
resolve to previously defined interfaces.

service A.B.C.MyService1
{
interface Inf1;
subservice MySub1
{
interface Inf2;
};
};

The following example shows a second subservice class which includes optional parameters.

service A.B.C.MyService2
{
interface Inf1;
subservice MySub1
{
interface Inf2;
};
subservice MySub2( in SCAInt32 value, in SCAVoidPtr ptr )
{
interface Inf3;
interface Inf4;
};
};

74
A SCA Hello World Application The IDL Language

Service Options
In the definition of a SCA service there are several options that can be specified which will
affect the type of code generated by the IDL compiler.

singleton: Only one instance of a singleton service may exist at any given time. Once an
instance of the service has been created, additional calls to get a copy of the service will
return the same instance. For normal non-singleton services, each call to get a copy of the
service will return a new instance of the service.
delegate or inherit: The default code generated for a SCA service will use an
implementation that inherits from a base class generated by the IDL compiler. This base
class will then inherit from the interface class and also provide all the necessary links to
the SCA Framework. There may be situations where this form of implementation is
inconvenient because of other requirements in your classes. To resolve this, the delegation
form of implementation can be used. With delegation, the skeleton classes generated by
the IDL compiler do not inherit from a base or interface classes. Instead the base class is
replaced with a separate or tie class which inherits from the interface class and provides all
the necessary links to the SCA Framework. When a new instance of the service is
requested, an instance of the tie class is constructed and returned. The tie class will
internally construct a separate instance of your implementation class when it is initialized.
Interface calls to the methods in the tie class are then delegated to the methods in the
implementation class.
aggregates: Interface aggregation is one method in interface based programming to
extend a service by reusing implementation from another service. The aggregates option
specifies that this service class will use aggregation. The services that implement the
interfaces that will be aggregated must be defined with the aggregated option. For
complete details on aggregation see the section on implementation reuse.
aggregated: This option specifies that the interfaces implemented by this service class
may be aggregated by another service which is defined with the aggregates option.

Not all languages support all of these options. See the sections on the IDL mappings for the
language you will be using for the complete details on which options are supported.

4.13. SCA Component Declaration


The SCA IDL language allows for the definition of SCA components. A SCA component is
the container that is used to deliver one or more services. The definition of components should
always be placed in files with the extension of “.cdl” and these CDL files should only contain
component definitions. Only one component definition is allowed in each CDL file.

The IDL compiler uses the component definitions to generate support code that makes the
services in the component available to the SCA Framework. This code is automatically
generated, compiled and linked with the SCA component you build.

Since SCA components are nothing more than a container for one or more SCA services, their
definitions consists of a list of these services.

The grammar of a SCA component definition is as follows:

75
A SCA Hello World Application The IDL Language

<component> ::= <component_dcl>


“{“ <component_body> “}”
<component_dcl> ::= “component” <component_name>
< component_name > ::= <identifier>
| < component_name > “.” <identifier>
<component_body> ::= <component_entry>+
<component_entry> ::= <option_dcl> “;”
| <service_ref> “;”
<option_dcl> ::= <option>+
<option> ::= “embedded”
<service_ref> ::= “service” <service_name>
< service_name > ::= <identifier>
| < service_name > “.” <identifier>

A component definition consists of these elements:

The keyword component


The fully qualified dotted component name
Definition of the component body enclosed by the characters “{“ and “}”

The body of a component definition consists of the following elements in any order.

Zero or more component option specifications.


One or more service references for the services that the component will contain.

component A.B.C.MyComponent1
{
service Service1;
service [Link].Service2;
};

You may need to also specify some options for a component.

component A.B.C.MyComponent2
{
embedded;
service Service2;

};

The fully qualified dotted component name serves several purposes. For complete details on
these see section IDL/SDL/CDL Names, Namespaces and Directories.

The service names used may be either a short name or the fully qualified dotted name. If a
short name is used there must be no ambiguities when resolving it to a service definition based
on the following rules.
76
A SCA Hello World Application The IDL Language

If there is only one service in the entire source tree with the same short name, that that
service definition is used.
If there is more than one service in the entire source tree with the same short name, there
must be only one in the sub-tree of the source tree that is rooted in the directory that
contains the CDL file for the component.
Component Options
In the definition of a SCA component there are several options that can be specified which
will affect the type of code generated by the IDL compiler.

embedded: Normally, each SCA component will be packaged by the build system into a
separate package that is appropriate for the language it is implemented in. For example a
component implemented in C++ is linked into a shared library and a Java component is
packaged in a jar file. Under some conditions it may be desirable to not do this packaging.
This allows you to manually package the files with other parts of your program as
required. See the section on Embedded Components for examples of when this may be
useful.

Not all languages support all of these options. See the sections on the IDL mappings for the
language you will be using for the complete details on which options it supports.

4.14. Running the IDL Compiler


The SCA Framework provides an IDL compiler that is used to process the “.idl”, “.sdl” and
“.cdl” files. Using the definitions in these files, the compiler generates a set of source files that
are appropriate for the implementation language being used.
The IDL Compiler Command
The following is the syntax for the command to run the SCA IDL compiler command.

Run the SCA/IDL compiler.

Usage: idl [options] file, [file, file, ...]

One of the following options must be given:

-w : Generates glue part of interfaces, services and components


-s : Generates skeleton for user's part of a service
-h : Print this message

Additional Options:

-b backend :
Name of back-end module to run
-c :
Keep comments from IDL files in interface headers
-e :
An error is generated if any of the files already exist
-f :
List the files that will be generated, do not generate them
-Dxxx :
Add pre-preprocessor define
-i path :
Add path to the list of search directories for includes
-nf :
Do not warn about unresolved forward declarations
-o path :
Base directory where output files are written
Default is the current working directory
-xmlo path : Base directory where XML output files are written
Default is the same as specified with the "-O" parameter

77
A SCA Hello World Application The IDL Language

-nrd : Do not put interface header files in relative sub-directories


specified by IDL module statements. Instead they will be put
directly in the current working directory or the directory
specified with the "-o" option.
-q : Do not print the IDL compiler version number on stdout
-t : Generate tie or delegated service implementation
-wbxxx : Pass option "xxx" directly to the back-end module
-tc : Generate TypeCode information for IDL defined types
-ntc : Do not generate TypeCode information for IDL defined types
-xmltc : If "-tc" set, generate XML TypeCode information
-nxmltc : If "-tc" set, generate embedded TypeCode information

Debug options:

-dump : Dump the parsed IDL then exit, without running back-end
-p : Only run the pre-processor, sending its output to stdout
-v : Verbose output to trace compilation stages

The extension of the input file is used to determine the type of files that
will be generated:

.cdl -> Generate component implementation (-w)


.sdl -> Generate service implementation (-w) or skeletons (-s)
.idl -> Generate interface headers (-w)

Compiler Processing Modes


When running the IDL compiler, one of the two following modes must be selected.

The “-s” option is used when you want the IDL compiler to generate skeleton code for the
implementation of a SCA service. This option only has affect when processing SDL files.
The files generated will always have an extension of “.new” appended to their name so
they will not accidentally overwrite any existing implementation files. This option is
normally used when you are first starting to develop a SCA service. You first write the
IDL and SDL definitions for the service and then use the IDL compiler to generate the
skeleton code. You may also want to rerun the compiler at a latter time if you make
significant changes to your IDL and/or SDL files and need to update your existing
implementation. Normally you do not directly run the IDL compiler with this option.
Instead you will use the genskeleton command which provides additional features for
generate your skeletons.
The “-w” option is used when you want the IDL compiler to generate the code that is
required to link the developer’s implementation code to the SCA Framework. This option
is normally only used by the SCA Build System and applies to all three IDL file types.
Location for Compiler Generated Files
The files generated by the IDL compiler will be stored in several different locations
depending on the compiler options provided and the type of files being generated.

The default location for files generated from SDL and CDL inputs, regardless of whether the
”-s” or “-w” mode is selected, is always the current directory where the command was run
from. The “-o” compiler option can be used to change this location.

78
A SCA Hello World Application The IDL Language

For IDL files, which are only processed when the “-w” mode is selected, the generated files
are normally stored in a relative sub-directory that is determined from the module commands
in the IDL file. Consider the following example IDL file.

module SCA { module FileReaders { module Nastran {

interface SCAIReader : SCAIService


{
SCAResult importBDF( in SCAString sFileName );
};

}; }; };

In this example, the file generated for the “SCAIReader” interface would be stored in the
relative sub-directory “SCA/FileReaders/Nastran”. The base for the relative sub-directory
will be the current directory where the command was run from. The “-o” compiler option can
be used to change this base location. If the “-nrd” compiler option is specified, then the files
will not be stored in a relative sub-directory. Instead they will be stored directly in the current
directory or in the directory specified with the “-o” option.
The genskeleton command
The genskeleton command is used to generate skeletons for the implementation code, in the
language of your choice, for the service definitions provide in “.sdl” files.

The following is the syntax for the command to run the SCA genskeleton command.

Generate skeleton code for a service implementation from the definitions in a


SDL file.

Usage: genskeleton [options] file [files, file, ...]

The following options are available:

-h : Print usage information


-cxx : For C++ implmentation (default)
-java : For Java implmentation
-csharp : For C# implmentation
-vb : For Visual Basic .NET implmentation
-r : If versions of the output files already exist, they will be
renamed by appending an extension of ".old". The new files
will then have their ".new" extension removed.
-v : Show the actual commands as they are executed.

The generation of skeleton files is a two step process.

The SCons build system is run to install any IDL files in the current directory into your
APPS_LOCAL directory. This is required because the IDL compiler cannot use the IDL
files located in your source directory. This is because the relative paths for the IDL files
that must be included must use the directory structure in the APPS_LOCAL tree and not
the directory structure used in the source tree.

79
A SCA Hello World Application The IDL Language

The IDL compiler is run to build the skeletons from the SDL file.

Since the build system must be run first, this script will only work if you are located in a
properly configured source tree. This means there must be a SConscript file in the current
directory and there must be a SConstruct file in either the the current directory or one of its
parents.

The skeleton files generated by the IDL compiler normally have an extension of “.new”
appended to the files names so they will not overwrite any existing versions. If none of the
files currently exist, then the new versions will have the “.new” extension removed. If any of
the files do exist, the newly generated files will keep their “.new” extension unless “-r” option
is provided. In this case, the existing versions of the files will be saved by adding an extension
of “.old”, and the new versions will then replace them.

80
A SCA Hello World Application Appendix A: OMG IDL Specifications

Appendix A: OMG IDL Specifications

Portions of this document have been taken from the OMG IDL specifications. These
documents can be found on the CORBA download page at [Link]
Copyright © 1998, 1999, Alcatel
Copyright © 1997, 1998, 1999 BEA Systems, Inc.
Copyright © 1995, 1996 BNR Europe Ltd.
Copyright © 1998, Borland International
Copyright © 1998, Cooperative Research Centre for Distributed Systems Technology (DSTC Pty Ltd)
Copyright © 2001, Concept Five Technologies
Copyright © 1991, 1992, 1995, 1996, Digital Equipment Corporation
Copyright © 2001, Eternal Systems, Inc.
Copyright © 1995, 1996, 1998, Expersoft Corporation
Copyright © 1996, 1997 FUJITSU LIMITED
Copyright © 1996, Genesis Development Corporation
Copyright © 1989- 2001, Hewlett-Packard Company
Copyright © 2001, HighComm
Copyright © 1998, 1999, Highlander Communications, L.C.
Copyright © 1991, 1992, 1995, 1996 HyperDesk Corporation
Copyright © 1998, 1999, Inprise Corporation
Copyright © 1996 - 2001, International Business Machines Corporation
Copyright © 1995, 1996 ICL, plc
Copyright © 1998 - 2001, Inprise Corporation
Copyright © 1998, International Computers, Ltd.
Copyright © 1995 - 2001, IONA Technologies, Ltd.
Copyright © 1998 - 2001, Lockheed Martin Federal Systems, Inc.
Copyright © 1998, 1999, 2001, Lucent Technologies, Inc.
Copyright © 1996, 1997 Micro Focus Limited
Copyright © 1991, 1992, 1995, 1996 NCR Corporation
Copyright © 1998, NEC Corporation
Copyright © 1998, Netscape Communications Corporation
Copyright © 1998, 1999, Nortel Networks
Copyright © 1998, 1999, Northern Telecom Corporation
Copyright © 1995, 1996, 1998, Novell USG
Copyright © 1991, 1992, 1995, 1996 by Object Design, Inc.
Copyright © 1991- 2001 Object Management Group, Inc.
Copyright © 1998, 1999, 2001, Objective Interface Systems, Inc.
Copyright © 1998, 1999, Object-Oriented Concepts, Inc.
Copyright © 1998, 2001, Oracle Corporation
Copyright © 1998, PeerLogic, Inc.
Copyright © 1996, Siemens Nixdorf Informationssysteme AG
Copyright © 1991 - 2001, Sun Microsystems, Inc.
Copyright © 1995, 1996, SunSoft, Inc.
Copyright © 1996, Sybase, Inc.
Copyright © 1998, Telefónica Investigación y Desarrollo S.A. Unipersonal
Copyright © 1998, TIBCO, Inc.
Copyright © 1998, 1999, Tri-Pacific Software, Inc.
Copyright © 1996, Visual Edge Software, Ltd.

USE OF SPECIFICATION - TERMS, CONDITIONS & NOTICES

The material in this document details an Object Management Group specification in accordance with the
terms, conditions and notices set forth below. This document does not represent a commitment to

81
A SCA Hello World Application Appendix A: OMG IDL Specifications

implement any portion of this specification in any company's products. The information contained in this
document is subject to change without notice.

LICENSES

The companies listed above have granted to the Object Management Group, Inc. (OMG) a nonexclusive,
royalty-free, paid up, worldwide license to copy and distribute this document and to modify this document
and distribute copies of the modified version. Each of the copyright holders listed above has agreed that no
person shall be deemed to have infringed the copyright in the included material of any such copyright
holder by reason of having used the specification set forth herein or having conformed any computer
software to the specification. Subject to all of the terms and conditions below, the owners of the copyright
in this specification hereby grant you a fully-paid up, non-exclusive, nontransferable, perpetual, worldwide
license (without the right to sublicense), to use this specification to create and distribute software and
special purpose specifications that are based upon this specification, and to use, copy, and distribute this
specification as provided under the Copyright Act; provided that: (1) both the copyright notice identified
above and this permission notice appear on any copies of this specification; (2) the use of the specifications
is for informational purposes and will not be copied or posted on any network computer or broadcast in any
media and will not be otherwise resold or transferred for commercial purposes; and (3) no modifications
are made to this specification. This limited permission automatically terminates without notice if you
breach any of these terms or conditions. Upon termination, you will destroy immediately any copies of the
specifications in your possession or control.

PATENTS

The attention of adopters is directed to the possibility that compliance with or adoption of OMG
specifications may require use of an invention covered by patent rights. OMG shall not be responsible for
identifying patents for which a license may be required by any OMG specification, or for conducting legal
inquiries into the legal validity or scope of those patents that are brought to its attention. OMG
specifications are prospective and advisory only. Prospective users are responsible for protecting
themselves against liability for infringement of patents.

GENERAL USE RESTRICTIONS

Any unauthorized use of this specification may violate copyright laws, trademark laws, and
communications regulations and statutes. This document contains information which is protected by
copyright. All Rights Reserved. No part of this work covered by copyright herein may be reproduced or
used in any form or by any means--graphic, electronic, or mechanical, including photocopying, recording,
taping, or information storage and retrieval systems--without permission of the copyright owner.

DISCLAIMER OF WARRANTY

WHILE THIS PUBLICATION IS BELIEVED TO BE ACCURATE, IT IS PROVIDED "AS IS" AND


MAY CONTAIN ERRORS OR MISPRINTS. THE OBJECT MANAGEMENT GROUP AND THE
COMPANIES LISTED ABOVE MAKE NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
WITH REGARD TO THIS PUBLICATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTY
OF TITLE OR OWNERSHIP, IMPLIED WARRANTY OF MERCHANTABILITY OR WARRANTY OF
FITNESS FOR A PARTICULAR PURPOSE OR USE. IN NO EVENT SHALL THE OBJECT
MANAGEMENT GROUP OR ANY OF THE COMPANIES LISTED ABOVE BE LIABLE FOR
ERRORS CONTAINED HEREIN OR FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
CONSEQUENTIAL, RELIANCE OR COVER DAMAGES, INCLUDING LOSS OF PROFITS,
REVENUE, DATA OR USE, INCURRED BY ANY USER OR ANY THIRD PARTY IN CONNECTION
WITH THE FURNISHING, PERFORMANCE, OR USE OF THIS MATERIAL, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGES.

The entire risk as to the quality and performance of software developed using this specification is borne by
you. This disclaimer of warranty constitutes an essential part of the license granted to you to use this
specification.

82
A SCA Hello World Application Appendix A: OMG IDL Specifications

RESTRICTED RIGHTS LEGEND

Use, duplication or disclosure by the U.S. Government is subject to the restrictions set forth in
subparagraph (c) (1) (ii) of The Rights in Technical Data and Computer Software Clause at DFARS
252.227-7013 or in subparagraph (c)(1) and (2) of the Commercial Computer Software - Restricted Rights
clauses at 48 C.F.R. 52.227-19 or as specified in 48 C.F.R. 227-7202-2 of the DoD F.A.R. Supplement and
its successors, or as specified in 48 C.F.R. 12.212 of the Federal Acquisition Regulations and its
successors, as applicable. The specification copyright owners are as indicated above and may be contacted
through the Object Management Group, 250 First Avenue, Needham, MA 02494, U.S.A.

TRADEMARKS

The OMG Object Management Group Logo®, CORBA®, CORBA Academy®, The Information
Brokerage®, XMI® and IIOP® are registered trademarks of the Object Management Group. OMG™,
Object Management Group™, CORBA logos™, OMG Interface Definition Language (IDL)™, The
Architecture of Choice for a Changing World™, CORBAservices™, CORBAfacilities™, CORBAmed™,
CORBAnet™, Integrate 2002™, Middleware That's Everywhere™, UML™, Unified Modeling
Language™, The UML Cube logo™, MOF™, CWM™, The CWM Logo™, Model Driven
Architecture™, Model Driven Architecture Logos™, MDA™, OMG Model Driven Architecture™, OMG
MDA™ and the XMI Logo™ are trademarks of the Object Management Group. All other products or
company names mentioned are used for identification purposes only, and may be trademarks of their
respective owners.

COMPLIANCE

The copyright holders listed above acknowledge that the Object Management Group (acting itself or
through its designees) is and shall at all times be the sole entity that may authorize developers, suppliers
and sellers of computer software to use certification marks, trademarks or other special designations to
indicate compliance with these materials. Software developed under the terms of this license may claim
compliance or conformance with this specification if and only if the software compliance is of a nature
fully matching the applicable compliance points as stated in the specification. Software
developed only partially matching the applicable compliance points may claim only that the software was
based on this specification, but may not claim compliance or conformance with this specification. In the
event that testing suites are implemented or approved by Object Management Group, Inc., software
developed using this specification may claim compliance or conformance with the specification only if the
software satisfactorily completes the testing suites.

ISSUE REPORTING

All OMG specifications are subject to continuous review and improvement. As part of this process we
encourage readers to report any ambiguities, inconsistencies, or inaccuracies they may find by completing
the Issue Reporting Form listed on the main web page [Link] under Documents &
Specifications, Report a Bug/Issue.

83
SCA Framework User Documentation

Chapter 5

IDL to C++ Language Mapping

87
SCA IDL Language and C++ Language Mappings

5. IDL to C++ Language Mapping


5.1. Introduction
The IDL language provides a language independent definition of SCA interfaces and data
types. In order to actually use these definitions, there must be a set of rules, commonly known
as a mapping; that describes how these types are represented in a particular language. This
chapter explains the mapping that SCA uses for the C++ language.

For every type defined in IDL, the IDL compiler will generate the code required to expose the
proper C++ definition of the type. In addition to the actual C++ definition of the type, there is
also some support code generated which is used by the SCA Framework to manage instances
of each type. An example of this is the bridging of instances of the type between C++ and the
other languages supported by the SCA Framework.

The SCA C++ mapping uses a set of overloaded bi-directional marshalling operators to
manipulate data in instances of the SCAAny type and for some bridging operations. For
each user defined type the IDL compiler will generate these required operator definitions.
The format for these is different for each different type and will be shown in the various
mapping sections below. For the basic and predefined types that are delivered with the
SCA Framework, these operators are predefined in the delivered header files.

For each type the IDL compiler will generate some support code for accessing the
SCATypeCode created at runtime by the SCA Framework. This code will be described in
the SCATypeCode mapping section latter in this chapter.

The code that is generated by the IDL compiler is stored in one of several files depending on
whether it is an interface or a user defined type definition.

All of the user defined types, defined outside of interfaces, in the same .idl file will be
store in a single header file. The name of the file will be xxxTypes.h for the IDL file named
[Link]. The relative directory under the include directory in the delivery tree where the
generated file is stored is taken from the namespace of the first type defined in the file.

For each interface defined in the IDL file, two header files will be generated, one for the
smart pointer definition and one for the full definition of the abstract interface class. The
relative directory under the include directory in the delivery tree where the generated files
are stored is taken from the namespace that the interface is defined in.

Consider the following simple IDL file to demonstrate these rules.

IDL file “[Link]”


module SCA { module Test {

enum MyENUM { VALUE1, VALUE2 };

Module Test2 {

Struct MyStruct { SCAInt32 data; } ;

88
SCA IDL Language and C++ Language Mappings

Interface SCAITest1 : SCAIService { };

};

Interface SCAITest2 : SCAIService { };

}; };

The IDL compiler will generate the following type file for this definition.

SCA/Test/mytestTypes.h - contains MyEnum and MyStruct


SCA/Test/Test2/SCAITest1SPtr.h - contains smart pointer for SCAITest1
SCA/Test/Test2/SCAITest1.h - contains interface for SCAITest1
SCA/Test/SCAITest2SPtr.h - contains smart pointer for SCAITest2
SCA/Test/SCAITest2.h - contains interface for SCAITest2

Although it is legal to include type and constant definitions inside an interface body, it is a
discouraged practice. As a result the affect on the mappings described in this section will not
be discussed.
5.2. Mapping for Identifiers
IDL identifiers are mapped to C++ with no change. For example:

IDL
enum Color { RED, GREEN, BLUE };

C++
enum Color { RED, GREEN, BLUE };

There is one potential problem to be aware of. If the IDL contains an identifier that is also a
C++ reserved keyword, then the resulting C++ code will not compile. The OMG IDL
specification dictates that in this case the identifier should be automatically prefixed with the
string “_cxx_”. Since this leads to ugly and non-intuitive code, the SCA IDL compiler does
not implement this feature. Therefore, the use of C++ reserved words for identifiers is not
allowed.
5.3. Mapping for Modules
The IDL module construct is mapped directly to a C++ namespace with the same name.

IDL
module SCA { module Test {
// definitions
}; };

C++
namespace SCA { namespace Test {
// definitions
} }

The IDL module constructs also affect other aspects of the SCA mapping. See the IDL
Compiler chapter for detailed information on how the IDL module statements are used.
89
SCA IDL Language and C++ Language Mappings

5.4. Mapping for Basic Types


Each basic IDL data type is mapped to a C++ typedef in the SCA namespace with the same
name. This is done because some types, like SCAInt16 and SCAInt32, may have different
representations on different platforms, and the SCA definitions will reflect the appropriate
representation for that platform. It is therefore important to use the appropriate SCA types and
not the native C++ types when dealing with interface parameters and results to insure
compatibility across platforms.

SCA IDL Type C++ Type


SCA::SCAInt8 SCA::SCAInt8
SCA::SCAInt16 SCA::SCAInt16
SCA::SCAInt32 SCA::SCAInt32
SCA::SCAInt64 SCA::SCAInt64
SCA::SCAUInt8 SCA::SCAUInt8
SCA::SCAUInt16 SCA::SCAUInt16
SCA::SCAUInt32 SCA::SCAUInt32
SCA::SCAUInt64 SCA::SCAUInt64
SCA::SCAReal32 SCA::SCAReal32
SCA::SCAReal64 SCA::SCAReal64
SCA::SCAChar SCA::SCAChar
SCA::SCAUChar SCA::SCAUChar
SCA::SCABool SCA::SCABool

All of the mappings for the basic types are distinguishable and unique with respect to
overloading. That is, one can safely write overloaded C++ functions for SCAInt8,
SCAUInt8, SCAInt16, SCAUInt16, SCAInt32, SCAUInt32, SCAInt64, SCAUInt64,
SCAReal32, SCAReal64, SCAChar, SCAUChar and SCABool types and each of these
will be unique. Remember that overloading is not permitted in interface operations in IDL but
it can be used in service implementation code. This is also a requirement to allow type-safe
processing of data in a SCAAny type.
5.5. Mapping for String Types
The IDL SCAString type is directly mapped to the C++ STL string class and the
SCAUString type is directly mapped to the ICU UnicodeString class.

namespace SCA {
typedef std::string SCAString;
typedef UnicodeString SCAUString;
}

The SCA Kernel has transitioned from using wide strings to Unicode
strings. The SCAWString (typedef to std::wstring) and SCAWChar
(typedef to wchar_t) types will be supported for a limited time to
allow applications to migrate to Unicode strings and characters.

90
SCA IDL Language and C++ Language Mappings

The SCA Framework also provides the C++ SCA::StringUtility class which
has a large number of members for manipulating strings. It provides
functionality not provided by the native string implementations and
provides methods to convert between the various string formats.

5.6. Mapping for Enumerated Types


An IDL enum maps directly to the corresponding C++ enum type definition.

IDL
enum Color { RED, GREEN, BLUE };

C++
enum Color { RED, GREEN, BLUE };

inline SCAMarshaller& operator >>= (const Color& val,


SCAMarshaller& stream){
SCAInt32 ival = static_cast< SCAInt32 >(val);
ival >>= stream;
return stream;
}

inline SCAMarshaller& operator <<= (Color& val,


SCAMarshaller& stream){
SCAInt32 ival;
ival <<= stream;
val = static_cast< Color >(ival);
return stream;
}

5.7. Mapping for Structures


An IDL structure maps to a C++ struct, with each IDL structure member mapped to a
corresponding member of the C++ structure. The C++ structure members appear in the same
order as the corresponding IDL structure members. For example:

IDL
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

C++
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

inline SCAMarshaller& operator >>= (const Node& val


SCAMarshaller& stream){
[Link](TypeCodeForType< Node >::get());

91
SCA IDL Language and C++ Language Mappings

[Link] >>= stream;


val.x >>= stream;
val.y >>= stream;
val.z >>= stream;
return stream;
}

inline SCAMarshaller& operator <<= (Node& val,


SCAMarshaller& stream){
[Link] <<= stream;
val.x <<= stream;
val.y <<= stream;
val.z <<= stream;
return stream;
}

5.8. Mapping for Array Types


The SCA Framework supports four types of arrays that can be defined in
IDL. The four array types differ in the way memory is managed, when
the array size is determined and when the size can change. Each of the
array types may hold any type of data that is defined in IDL.

Summary of array types


The following table gives a summary of the differences between the
various types of IDL defined arrays.

When Can size Referen Memory


size change? ce Manager
declare Counted
d
Fixed Array IDL No No Compiler
Dynamic Runtime When created Yes Programmer
Array only
Sequence Runtime Dynamically Yes SCASequence
class
Vector Runtime Dynamically No std::vector
class

Fixed size arrays


Fixed size arrays must have their size defined in the IDL and can never change. Only arrays of
rank 1 or 2 are supported.

The C++ compiler represents a standard array reference as a simple pointer to values of their
data type. As a result, two different IDL defined arrays which contain data of the same type
will be treated as the same type when distinguishing operator overloads. This would make it
difficult to support the insertion of these arrays into a SCAAny value in a type-safe manner.
To allow for the type-safe handling of arrays, each IDL defined array is mapped to a light
weight C++ class which acts like a normal C++ array.

92
SCA IDL Language and C++ Language Mappings

IDL
typedef SCAInt32 Date[3];

C++
class Date
{
public:
typedef SCAInt32 value_type;
typedef size_t size_type;
Date() { }
size_type size() const { return 3; }
value_type& operator[](size_type idx) { return data[idx]; }
const value_type& operator[](size_type idx)const {
return data[idx];
}
private:
value_type data[3];
};

inline SCAMarshaller& operator >>= (const Date& val,


SCAMarshaller& stream){
[Link](TypeCodeForType< Date >::get());
for(Date::size_type i=0; i<3; i++) val[i] >>= stream;
return stream;
}

inline SCAMarshaller& operator <<= (Date& val,


SCAMarshaller& stream){
for(Date::size_type i=0; i<3; i++) val[i] <<= stream;
return stream;
}

Two dimensional arrays are handled in a similar manner.

IDL
typedef SCAInt32 Matrix[5][5];

C++
class Matrix
{
public:
typedef SCAInt32 value_type;
typedef size_t size_type;
Matrix() {}
size_type size1() const { return 5; }
size_type size2() const { return 5; }
value_type* operator[](size_type idx) { return data[idx]; }
const value_type* operator[](size_type idx) const {
return data[idx];
}
private:
value_type data[5][5];
};

inline SCAMarshaller& operator >>= (const Matrix& val,


SCAMarshaller& stream){

93
SCA IDL Language and C++ Language Mappings

[Link](SCA::TypeCodeForType< Matrix >::get());


for(Matrix::size_type i=0; i<5; i++)
for(Matrix::size_type j=0; j<5; j++)
val[i][j] >>= stream;
return stream;
}

inline SCAMarshaller& operator <<= (Matrix& val,


SCAMarshaller& stream){
for(Matrix::size_type i=0; i<5; i++)
for(Matrix::size_type j=0; j<5; j++)
val[i][j] <<= stream;
return stream;
}

Only one and two dimensional arrays are support by the C++ mapping.
Fixed size arrays are used in C++ the same way C arrays are used. The
following are some simple IDL array definitions.

IDL
// Define fixed size array types
typedef SCA::SCAInt32 Array1[2];
typedef SCA::SCAInt32 Array2[2][2];

// Define structure that contains fixed size arrays defined


// both within the structure and externally to it
struct MyStruct {
SCA::SCAInt32 data1[2];
Array1 data2;
SCA::SCAInt32 data2[2][2];
Array2 data4;
};

The following examples show how they can be used.

C++
// Using rank 1 array
Array1 val1;
val1[0] = 1;

// Using rank 2 array


Array2 val2;
val2[0][0] = 1;

// Using arrays in structure


MyStruct struct;
struct.data1[0] = 1;
struct.data2[0] = 1;
struct.data3[0][0] = 1;
struct.data4[0][0] = 1;

In addition to the standard C array operations, fixed size IDL arrays


also have a size method which allows you to determine the size of the
array.

// Using size member for rank 1 array


for(int i=0,i<[Link]();i++)
val1[i] = i;

94
SCA IDL Language and C++ Language Mappings

// Using size members for rank 2 array


for(int i=0,i<val2.size1();i++)
for(int j=0,j<val2.size2();j++)
val2[i][j] = i;

Dynamic Arrays
Dynamic arrays are similar to fixed size arrays except the size of the
array is not defined in IDL. Instead you specify the size at runtime
when the array instance is created. Also for dynamic arrays, the
programmer instead of the compiler is responsible for managing the
memory they use.

Because dynamic arrays perform no internal memory management,


operations that would result in an expansion or contraction are not
supported. Only simple operations like those available with fixed size
arrays are available.

Because the programmer is providing the memory for the array, it is


possible to initialize a dynamic array on top of existing data. In this
case the dynamic array is used as a wrapper on existing data allowing
it to be passed across interface boundaries without making any copies
of the data. This can be very important in legacy applications where
large amounts of data need to be passed. If either fixed size arrays or
sequences are used for this purpose, then at least one copy of the data
must be made.

Like other types of arrays supported in the SCA Framework, dynamic


arrays may hold any type of data that can be defined in IDL.

IDL definitions for Dynamic arrays


Dynamic arrays are defined in IDL in a similar manner to fixed size
arrays except the actual array sizes are left blank. Dynamic arrays may
be defined in the IDL as separate data types or as members in a
structure definition. Only arrays of rank 1 or rank 2 are currently
supported.

IDL
// Define dynamic array types
typedef SCA::SCAInt32 Array1[];
typedef SCA::SCAInt32 Array2[][];

// Define structure that contains dynamic arrays


struct MyStruct {
SCA::SCAInt32 data1[];
Array1 data2;
SCA::SCAInt32 data2[][];
Array2 data4;
};

Dynamic array class definitions


For each dynamic array defined in IDL, the SCA IDL compiler creates a
type definition which is an instantiation of either the ArrayPtr1 or
ArrayPtr2 template classes. These templates are defined as follows. The

95
SCA IDL Language and C++ Language Mappings

actual definitions include implementation for each of the methods but


that part of the code is not show here.

namespace SCA { namespace DynamicArray {

template<typename T> class ArrayPtr1;


template<typename T> class ArrayPtr2;
typedef SCAVoid (*DestroyFunc)( SCAVoid*,SCATypeCode,SCASizeType );

//
// ArrayPtr1 is a class for a one dimensional dynamic array.
//
template<typename T>
class ArrayPtr1
{
public:
typedef T value_type;
typedef ::SCA::DynamicArray::ArrayData<value_type> arraydata;
typedef typename arraydata::size_type size_type;
typedef typename arraydata::reference reference;
typedef typename arraydata::const_reference const_reference;
typedef typename arraydata::pointer pointer;
typedef typename arraydata::const_pointer const_pointer;
ArrayPtr1();
ArrayPtr1(value_type* data,
size_type size,
DestroyFunc destroyFunc=NULL,
SCATypeCode contTC=SCATypeCode());
ArrayPtr1(const ArrayPtr1& val);
~ArrayPtr1()
void set(pointer data,
size_type size,
DestroyFunc destroyFunc=NULL,
SCATypeCode contTC=SCATypeCode());
void setTypeCode(SCATypeCode contTC) ;
void clear();
size_t size() const;
bool empty() const;
bool shared() const;
pointer data() const;
ArrayPtr1<value_type>& operator=(const ArrayPtr1& val);
const_reference operator[](size_type index) const;
reference operator[](size_type index);
};

//
// ArrayPtr2 is a class for a two dimensional dynamic array.
//
template<typename T>
class ArrayPtr2
{
public:
typedef T value_type;
typedef ::SCA::DynamicArray::ArrayData<value_type> arraydata;
typedef typename arraydata::size_type size_type;
typedef typename arraydata::reference reference;
typedef typename arraydata::const_reference const_reference;
typedef typename arraydata::pointer pointer;

96
SCA IDL Language and C++ Language Mappings

typedef typename arraydata::const_pointer const_pointer;


ArrayPtr2();
ArrayPtr2(value_type* data,
size_type size1,
size_type size2,
DestroyFunc destroyFunc=NULL,
SCATypeCode contTC=SCATypeCode());
ArrayPtr2(const ArrayPtr2& val);
~ArrayPtr2();
void set(pointer data,
size_type size1,
size_type size2,
DestroyFunc destroyFunc=NULL,
SCATypeCode contTC=SCATypeCode());
void setTypeCode(SCATypeCode contTC);
void clear();
size_t size1() const;
size_t size2() const;
bool empty() const;
bool shared() const;
pointer data() const;
ArrayPtr2<value_type>& operator=(const ArrayPtr2& val);
const_pointer operator[](size_type index) const;
pointer operator[](size_type index);
};

} }

IDL Generated Code


The IDL generated code for dynamic array types must be handled differently because the C++
compiler treats two different instantiation of a template with the same parameter type the same
when distinguishing operator overloads. This would make it difficult to support the insertion
of the dynamic arrays into a SCAAny value in a type-safe manner. To allow for the type-safe
handling of dynamic arrays, each IDL defined array is mapped to a light weight C++ class that
inherits from the template class.

The following shows an example of the generated code for a one dimensional dynamic array
type.

IDL
typedef SCAInt32 DynDate[];

C++
class DynDate : public DynamicArray::ArrayPtr1< SCAInt32 >
{
public:
typedef SCAInt32 value_type;
typedef DynamicArray::ArrayPtr1<value_type> base;
typedef base::size_type size_type;
DynDate() : base() {}
DynDate(value_type* data, size_type size,
DynamicArray::DestroyFunc desfunc=0) :
base(data,size,desfunc) {};
};

97
SCA IDL Language and C++ Language Mappings

inline SCAMarshaller& operator >>= (const DynDate& val,


SCAMarshaller& stream)
{
[Link](&val);
return stream;
}

inline SCAMarshaller& operator <<= (DynDate& val,


SCAMarshaller& stream)
{
[Link](&val);
return stream;
}

The following shows an example of the generated code for a two dimensional dynamic array
type.

IDL
typedef SCAInt32 DynMatrix[][];

C++
class DynMatrix : public DynamicArray::ArrayPtr2< SCAInt32 >
{
public:
typedef SCAInt32 value_type;
typedef DynamicArray::ArrayPtr2<value_type> base;
typedef base::size_type size_type;
DynMatrix() : base() {}
DynMatrix(value_type* data, size_type size1, size_type size2,
DynamicArray::DestroyFunc desfunc=0) :
base(data,size1,size2,desfunc) {};
};

inline SCAMarshaller& operator >>= (const DynMatrix& val,


SCAMarshaller& stream)
{
[Link](&val);
return stream;
}

inline SCAMarshaller& operator <<= (DynMatrix& val,


SCAMarshaller& stream)
{
[Link](&val);
return stream;
}

Simplified usage of a dynamic array


Dynamic arrays are used in C++ the same way C arrays are used except
the programmer must provide and manage the memory used by the array.
You therefore need provide a pointer to the memory and the number of
entries in the array when you construct a new dynamic array.

// Using rank 1 array


SCAInt32* mem1 = new SCAInt32[10];

98
SCA IDL Language and C++ Language Mappings

Array1 val1(mem1,10);
for(int i=0,i<10;i++)
val1[i] = i;

// Using rank 2 array


SCAInt32* mem2 = new SCAInt32[10];
Array2 val2(mem2,2,5);
for(int i=0,i<2;i++)
for(int j=0,j<5;j++)
val2[i][j] = i;

No checking can be done to insure that the memory provided is large


enough to hold the number of entries specified. It is up to the user to
ensure this is correct. It is also possible to provide a larger chunk
of memory then required when allocating the array which allows you to
add more entries to the array at a later time without having to
reallocate and copy the data.

The dynamic array also provides size methods similar to fixed size
arrays which return the current size of the array.

// Using rank 1 array


SCAInt32* mem1 = new SCAInt32[10];
Array1 val1(mem1,10);
for(int i=0,i<[Link]();i++)
val1[i] = i;

// Using rank 2 array


SCAInt32* mem2 = new SCAInt32[10];
Array2 val2(mem2,2,5);
for(int i=0,i<val2.size1();i++)
for(int j=0,j<val2.size2();j++)
val2[i][j] = i;

The clear method is used to set the array instance to empty.

// Clear dynamic array


[Link]();

And the empty method can be used to test if the dynamic array instance
currently holds any data.

Array1 val1;
if ( [Link]() )
cout << "Array is empty” << endl;
else
cout << "Array contains” << [Link]() << “ entires” << endl;

Dynamic arrays can also be stored in SCAAny values. When a dynamic


array is stored in a SCAAny, the data is not copied. Instead the SCAAny
value just contains a reference to the data in the same manner a normal
instance of the dynamic array contains a reference to the data.

// Initialize rank 1 array


SCAInt32* mem1 = new SCAInt32[10];
Array1 val1(mem1,10);
for(int i=0,i<[Link]();i++)
val1[i] = i;

99
SCA IDL Language and C++ Language Mappings

cout << "Shared=" << [Link]() << endl; (Not shared: "false")

// Store array in a SCAAny


SCAAny any;
any <<= val1;
cout << "Shared=" << [Link]() << endl; (Shared: "true")

// Flush the data in the SCAAny


[Link]();
cout << "Shared=" << [Link]() << endl; (Not shared: "false")

Resetting the contents of a dynamic array


It is also possible to instantiate an empty dynamic array using the
default constructor. In this case the set method can then used to
initialize the array at a later time. To determine if an instance of an
array has been initialized or not, the empty method can be used.

// Using rank 1 array


Array1 val1;
SCAInt32* mem1 = new SCAInt32[10];
[Link](mem1,10);

// Using rank 2 array


Array2 val2;
SCAInt32* mem2 = new SCAInt32[10];
[Link](mem2,2,5);

If you use the set method on a dynamic array that already contains
data, it reference to the old data is removed and the new data is
added. Since the dynamic array does no memory management, the old data
is not deleted. It is the responsibility of the programmer to make sure
the data gets deleted.

The initializing of a dynamic array at a later time is very useful if


the array is a member of a structure. This is because it is difficult
to provide initial values in a structure for complex member types.

// Using dynamic array in structure


MyStruct struct;
SCAInt32* mems1 = new SCAInt32[10];
[Link](mems1,10);
struct.data1[0] = 1;
SCAInt32* mems2 = new SCAInt32[10];
[Link](mems2,10);
struct.data2[0] = 1;
SCAInt32* mems3 = new SCAInt32[10];
[Link](mems3,10);
struct.data3[0][0] = 1;
SCAInt32* mems4 = new SCAInt32[10];
[Link](mems4,10);
struct.data4[0][0] = 1;

Memory management for dynamic array


The actual array data in dynamic arrays is referenced counted and the
ArrayPtr1 and Arrayptr2 class act as smart pointers to this data. This
allows dynamic arrays instances to be copied using the assignment

100
SCA IDL Language and C++ Language Mappings

operator or the copy constructor without actually having to copy the


data. Only a pointer to the underlying data is copied and the reference
count is increased. The dynamic array provides a shared method which
indicates if the data is shared or not. The following example shows
behavior of the shared method when several different dynamic array
instance point to the same data.

// Allocate a dynamic array


SCAInt32* mem1 = new SCAInt32[10];
Array1 val1(mem1,10);
for(int i=0,i<[Link]();i++) val1[i] = i;
if ( [Link]() )
cout << “Error: Array should not shared at this point” << endl;

// Assign a second dynamic array using the same data


// This operation does not make a copy of the data but simply
// increase the reference count to the original data
Array1 val2 = val1;
if ( ![Link]() )
cout << “Error: Array should be shared at this point” << endl;

// Clear one of the instances so the data is no longer shared


[Link]();
if ( [Link]() )
cout << “Error: Array should not shared at this point” << endl;

// Allocate a second dynamic array using the copy constructor


// This operation does not make a copy of the data but simply
// increase the reference count to the original data
Array1 val2(val1);
if ( ![Link]() )
cout << “Error: Array should be shared at this point” << endl;

Since the programmer is responsible for the management of memory in a


dynamic array instance, reference counting introduces a degree of
difficulty to properly handle the memory. This is because the data in
the dynamic array may be shared between several different instances of
the array which means the programmer must make sure the data is not
being shared when it need to be deleted. The shared method can be used
to determine if the data in a dynamic array instance can safely be
deleted.

// Allocate a dynamic array


SCAInt32* mem1 = new SCAInt32[10];
Array1 val1(mem1,10);
for(int i=0,i<[Link]();i++) val1[i] = i;

// Pass the dynamic array in an interface method


sp->someMethod(val1);

// Delete the data if it is not shared


if ( ![Link]() ) {
[Link]();
delete [] mem1;
}

To correctly deal with the dynamic arrays data, there needs to be


coordination between the caller and the callee of services using them.

101
SCA IDL Language and C++ Language Mappings

In the above example, the memory in the array is not deleted if it is


shared. This would be the case if the code in the interface method
called made a copy of the array. In this case the callee now becomes
responsible for making sure the data is properly destroyed when no
other references to it exist.

As this example show, the use of the shared method to determine if the
data stored in a dynamic array should be deleted is a bit cumbersome
and prone to error. To help make the memory manage easier, the dynamic
array allows you to provide a destroy function when you create a
dynamic array instance. The programmer defines the destroy function
because they are the one who knows the correct way to destroy this
memory. The advantage of providing a destroy function is the dynamic
array classes will automatically call this function when the reference
count on the data goes to zero. This relieves the code in both the
caller and the callee from having checking if the data is shared and
deleting the data when they are finished with it. This task will be
handled automatically by the dynamic array instances when they go out
of scope.

The following is the signature of the destroy function that you may
provide.

typedef SCAVoid (*DestroyFunc)(SCAVoid*,SCATypeCode,SCASizeType);

The SCASizeType value in the above definition contains the total number
of elements in the array regardless of whether the array has a rank 1
or 2.

The following examples show how the destroy function can be used to
automatically delete the data when it is no longer needed.

// Implemement of a destroy function


SCAVoid destroyData(SCAVoid* mem,SCATypeCode tc,SCASizeType size) {
delete [] (SCAInt32*)mem1;
}

// Allocate dynamic array with a destroy function


SCAInt32* mem1 = new SCAInt32[10];
Array1 val1(mem1,10,destroyData);
for(int i=0,i<[Link]();i++) val1[i] = i;

// Pass the dynamic array in an interface method


sp->someMethod(val1);

// If the data is not shared, the clear should trigger the


// destruction of the data in the dynamic array
[Link]();

Using dynamic arrays not defined in IDL


In the previous discussions of dynamic arrays, only the memory and the
size of the array were dynamic. The actual array definitions are static
and done in IDL and the code used the C++ classes generated by the SCA
IDL compiler. It is also possible to process dynamic arrays that were
never defined in IDL. Since the array types were not defined in IDL,
they obviously cannot be used as arguments in interface methods calls.
But these arrays can be inserted in SCAAny values and these then be

102
SCA IDL Language and C++ Language Mappings

passed as arguments. Using these features of the dynamic array it is


possible to pass arrays of data through interface calls that are
completely dynamic both in size and type.

SCAAny instances normally use the marshalling operators generated by


SCA IDL compiler to insert and extract data. In this case of dynamic
arrays not defined in IDL these operators do not exist. To handle this,
the SCAAny class provides the special insertArray and extractArray
methods to insert and extract these arrays. These are the definitions
for the methods.

// Routines to directly process dynamic arrays in a Any


SCAAny& insertArray(const SCATypeCode tc,
SCAVoid* values,
SCAUInt32 numEnt1,
SCAUInt32 numEnt2
const SCATypeCode tcArray=SCATypeCode(),
const DestroyFunc destroyFunc=NULL);
SCABool extractArray(SCATypeCode& tc,
SCAVoid** values,
SCAUInt32& numEnt1,
SCAUInt32& numEnt2) const;

You will notice that much of the data needed for these calls is similar
to the data used to construct a normal IDL defined dynamic array which
includes the pointer to the array memory, the number of elements in the
array and an optional destroy function. But in this case you also need
to pass one or two additional SCATypeCode values to define the dynamic
array.

To completely define a dynamic array; you need two different


SCATypeCode values. One of these values is for the dynamic array itself
and the second one is for the data that the array contains. At a
minimum you need to pass in the insertArray call the SCATypeCode value
for the data that the array contains. You can optionally pass the
SCATypeCode value for the dynamic array itself or you can let the
SCAAny processing create it internally. If you are only making a few
calls to the insertArray method with the same array type, then it is
fine to let the SCAAny processing create the dynamic array type code
for you. But, if you plan to make many calls, it is more efficient if
you create this type code once and provide it on each of the
insertArray calls.

Since the main purpose of this feature is to handle arrays that are
completely dynamic, it is most likely that you will not know a compile
time what the actual format of data in the array is. In this case it is
not possible to define the types for this data in IDL so you will need
to create the actual SCATypeCode definitions yourself at runtime. The
following example shows how a SCATypeCode is created for a structure
which contains a SCAReal32 and a SCAReal64 value. An array of 50 of
these values is then initialized and then inserted into a SCAAny.

The first step in the process is to create the SCATypeCode for the
contents of the array. When you create this type code it must be
registered in the kernels type code cache. This is done by adding the
optional true argument in the call to define the type code.

// Create SCATypeCode describing data contained in the array

103
SCA IDL Language and C++ Language Mappings

TypeCodes::SCAStructMemberSeq memberss;
TypeCodes::SCAStructMember mem;
[Link] = "mem1";
[Link] = "SCA.SCAReal32";
members.push_back(mem);
[Link] = "mem2";
[Link] = "SCA.SCAReal64";
members.push_back(mem);
SCATypeCode tcval = defineStructTypeCode("[Link]",members,true);

The next step is to allocate and initialize the data to be put in the
array. In a real application this data will probably already exist and
you wish to use the dynamic array to wrap it.

// Create array of data


char* data = new char[50*sizeof(SCAReal32)+50*sizeof(SCAReal64)];
char* tmpptr = data;
for ( int j=0; j<50; j++ ) {
SCAReal32 rval = 10.0f*j + j;
memcpy(tmpptr,&rval,sizeof(SCAReal32));
tmpptr += sizeof(SCAReal32);
SCAReal64 dval = 100.0*j + j;
memcpy(tmpptr,&dval,sizeof(SCAReal64));
tmpptr += sizeof(SCAReal64);
}

You can now insert the dynamic array into a SCAAny value.

// Insert data into SCAAny


SCAAny anyval;
[Link](tcval,data,50,0);

Once the data has been inserted in the SCAAny, the value can be passed
through any normal interface call.

sp->myMeethod(anyval);

The callee can then extract and process the data. When the data is
truly dynamic, the callee may not know the format of the data. In this
case they can interrogate the SCATypeCode value to determine its
format. For simplicity, this example assumes the routine knows the
format of the data.

SCAResult MyService:myMethod(SCAAny& anyval)


{
SCAVoid* ptr;
SCAUInt32 size1,size2;
SCATypeCode tcval;
if ( [Link](tcval,&ptr,size1,size2) ) {
// Memory pointed to by ptr contains the array data
// Values size1 and size2 contain the array dimentisons
// SCATypeCode tcval describes the format of each array entry
} else {
cout << "Error: SCAAny does not contain a dynamic array" << endl;
}
}

104
SCA IDL Language and C++ Language Mappings

Notice that the extractArray call returns a logical value just like the
normal >>= extraction operator which tells you if the operation was
successful or not.

Just like the normal insertion and extraction operators, the


insertArray and extractArray will not make any copies of the data. The
SCAAny only contains a reference to the data and the user is
responsible for managing this memory.

The following example expands the previous one showing how the optional
dynamic array SCATypeCode value and destroy function can also be used.
Only the new and changed portions of the code are shown.

// Implemement of a destroy function


SCAVoid destroyData(SCAVoid* mem,SCATypeCode tc,SCASizeType size) {
delete [] (char*)mem1;
}

// Define SCATypeCode for the dynamic array itself


SCAUInt32Sequence sizes;
sizes.push_back(0);
SCATypeCode tcvalda = defineArrayTypeCode(“[Link]”,
sizes,
“[Link]”,
false);

// Insert data into SCAAny


SCAAny anyval;
[Link](tcval,data,50,0,tcvalda,destroyData);

Mapping for Sequences


Sequences are defined in IDL without a size. The memory for the
sequence is entirely managed by the sequence itself and can expand or
contract as required. Only sequences of rank 1 are supported but you
can store a sequence in a sequence to simulate a rank 2 object.

The IDL SCASequence type is implemented in C++ as a template class type that extends the
standard C++ STL vector class. The SCASequence template class adds the following new
behavior to the standard STL vector class.

The actual sequence data is reference counted to reduce to a minimum the times when
the actual data will be copied.
The SCASequence implements the copy on write semantics so multiple readers can
share the same copy of the data and only when one copy is changed is a copy of the
actual data made
Sequences contain a large number of methods for accessing and
manipulating their contents. Consult the normal std::vector
documentation for details.

Sequences may be defined in the IDL as separate data types or as


members in a structure definition.

IDL
// Define sequence data types

105
SCA IDL Language and C++ Language Mappings

typedef sequence<SCA::SCAInt32> SeqInt32;

// Define structure that contains sequences


struct MyStruct {
sequence<SCA::SCAInt32> data1;
SeqInt32 data2;
};

And used in a manner similar to the standard std::vector type.

C++
// Using sequence
SeqInt32 val1;
val1.push_back(1);

// Using sequence in structure


MyStruct struct;
struct.data1.push_back(1);
struct.data2.push_back(1);

The following example uses the framework provided SCAInt32Sequence to show how the
copy on write semantics works. First the code declares an instance of the sequence, values1,
and fills it with data.

SCAInt32Sequence values1;
for ( int i=0; i<1000; i++ )
values1.push_back(i);

Then a new instance of the sequence, values2, is allocated and set equal to the first instance.
This operation will not cause a new copy of the data in the sequence to be made. Instead both
instances, values1 and values2, will be referencing the same data.

vector<int> values2 = values1;


for ( int i=0; i<1000; i++ )
cout << values2.r_at(i) << endl;

Then an entry in the sequence is changed using the values2 instance. At this time a copy of the
data will be made and only the value in the second copy will be changed. Now when the
sequence instance values1 is printed it will contain the original values but the values2 instance
will contain the modified data.

values2[5] = 10;
for ( int i=0; i<1000; i++ )
cout << values1.r_at(i) << endl;
for ( int i=0; i<1000; i++ )
cout << values2.r_at(i) << endl;

In order for the copy on write behavior to work correctly, the various methods in the
SCASequence class must know when the data in the sequence is being read or when it is
being written. The standard C++ vector class does not provide this ability because certain
methods can be used for both purposes as shows by the following example.

vector<int> values(10);
[Link](5) = 10;

106
SCA IDL Language and C++ Language Mappings

int ival = [Link](5);

To solve this problem, the SCASequence provides two different versions of these methods,
one for reading and one for writing. The version for reading uses the standard std::vector
name with an r_ prefix and the writing version uses a w_ prefix.

SCAInt32Sequence values(10);
values.w_at(5) = 10;
int ival = values.r_at(5);

The following table shows the standard methods in the STL vector class and their
corresponding methods in the SCASequence class which are different. All of the other
methods are the same.

std::vector SCASequence – read SCASequence - write


begin r_begin w_begin
end r_end w_end
rbegin r_rbegin w_rbegin
rend r_rend w_rend
address r_address w_address
at r_at w_at
front r_front w_front
back r_back w_back

The mapping for sequences types must be handled differently because the C++ compiler treats
two different instantiation of a template with the same parameter type the same when
distinguishing operator overloads. This would make it difficult to support the insertion of these
sequences into a SCAAny value in a type-safe manner. To allow for the type-safe handling of
sequences, each IDL defined sequence is mapped to a light weight C++ class that inherits
from the template class.

IDL
typedef SCASequence<Node> NodeSequence;

C++
class NodeSequence : public SCA::SCASequence< Node >
{
public:
NodeSequence(size_type n, const Node& value = Node())
: SCA::SCASequence< Node >(n,value) { }
NodeSequence()
: SCA::SCASequence< Node >() { }
template <class InputIterator>
NodeSequence(InputIterator first, InputIterator last)
: SCA::SCASequence< Node >(first,last) { }
};
inline void swap(NodeSequence& x, NodeSequence& y)
{
[Link](y);
}

inline SCAMarshaller& operator >>= (const NodeSequence& val,


SCAMarshaller& stream){

107
SCA IDL Language and C++ Language Mappings

SCAUInt32 len = static_cast< SCAUInt32 >([Link]());


len >>= stream;
for(SCAUInt32 i=0; i<len; i++) val.r_at(i) >>= stream;
return stream;
}

inline SCAMarshaller& operator <<= (NodeSequence& val,


SCAMarshaller& stream){
SCAUInt32 len;
len <<= stream;
[Link](len);
for(SCAUInt32 i=0; i<len; i++) val.w_at(i) <<= stream;
return stream;
}

Mapping for Vectors


Vectors are defined in IDL without a size. The memory for the vector
is entirely managed by the vector itself and can expand or contract as
required. Only vectors of rank 1 are supported but you can store a
vector in a vector to simulate a rank 2 object.

The IDL defined vectors inherit directly from the standard C++ STL
vector class.
The std::vector class is not reference counted and does not have any
copy on write semantics.

Unlike the SCASequence, the vectors can only be defined in the IDL as
separate data types. Once defined, they can be used as members in a
structure definition.

// Define vector data types


typedef vector<SCA::SCAInt32> VecInt32;

// Define structure that contains vectors


struct MyStruct {
VecInt32 data1;
VecInt32 data2;
};

// Using vector
VecInt32 val1;
val1.push_back(1);

// Using vector in structure


MyStruct struct;
struct.data1.push_back(1);
struct.data2.push_back(1);

Vectors contain a large number of methods for accessing and


manipulating their contents. Consult the normal std::vector
documentation for details.

IDL
typedef vector<Node> NodeVector;

C++
class NodeVector: public std::vector< Node>

108
SCA IDL Language and C++ Language Mappings

{
public:
NodeVector(size_type n, const Node& value = Node ())
: std::vector<Node>(n,value) { }
NodeVector()
: std::vector<Node>() { }
template <class InputIterator>
NodeVector (InputIterator first, InputIterator last)
: std::vector<Node>(first,last) { }
};

inline void swap(Node& x, Node& y)


{
[Link](y);
}

namespace Test { namespace TypeTest {

inline SCAMarshaller& operator >>= (const NodeVector& val,


SCAMarshaller& stream)
{
SCAUInt32 len = static_cast< SCAUInt32 >([Link]());
len >>= stream;
for(SCAUInt32 i=0; i<len; i++) [Link](i) >>= stream;
return stream;
}

inline SCAMarshaller& operator <<= NodeVector& val,


SCAMarshaller& stream)
{
SCAUInt32 len;
len <<= stream;
[Link](len);
for(SCAUInt32 i=0; i<len; i++) [Link](i) <<= stream;
return stream;
}

SCAVector Compared to SCASequence


The C++ implementation of the SCASequence type carries some additional
overhead such as reference counting, copy on write logic and slightly
larger storage requirements. This makes the type binary incompatible
with the std::vector which can lead to additional overhead of
converting between these types in legacy code. The SCAVector type
solves these problems by mapping directly to the native STL std::vector
type.

For most cases, the SCAVector performance is better than SCASequence.


The primary case where there is a significant performance hit is when
you are making a lot of copies of the type instances. Since the C++
implementation of SCAVector is a std::vector, which is not reference-
counted, it is always deep copied on assignment. The users can avoid
unnecessary copying in these cases by using the SCASequence instead

5.9. Mapping for Maps


The map type provides the ability to store name/value pairs. IDL
defined maps inherit directly from the standard C++ STL map class.
109
SCA IDL Language and C++ Language Mappings

IDL
typedef map<KeyNode, ValueNode> NodeMap;

C++
class NodeMap : public std::map<KeyNode,ValueNode >
{
public:
NodeMap()
: std::map<KeyNode,ValueNode >() { }
template <class InputIterator>
NodeMap(InputIterator first, InputIterator last)
: std::map<KeyNode,ValueNode >(first,last) { }
};

inline void swap(NodeMap& x, NodeMap& y)


{
[Link](y);
}

inlineSCAMarshaller& operator >>= (const NodeMap& val,


SCAMarshaller& stream)
{
SCAUInt32 len = static_cast<SCAUInt32 >([Link]());
len >>= stream;
typedef std::map<KeyNode,ValueNode > StdMap;
StdMap& stdMap= (StdMap&) val;
std::map<KeyNode,ValueNode >::iterator it;
for ( it=[Link]() ; it != [Link](); it++ ) {
(*it).first >>= stream;
(*it).second >>= stream;
}
return stream;
}

inlineSCAMarshaller& operator <<= (NodeMap& val,SCAMarshaller& stream)


{
SCAUInt32 len;
len <<= stream;
std::map<KeyNode,ValueNode >::iterator it;
for(SCAUInt32 i=0; i<len; i++) {
KeyNode first;
first <<= stream;
ValueNode second;
second <<= stream;
val[first] = second;
}
return stream;
}

5.10. Mapping for Type Aliases


An IDL typedef creates an alias for a type and is mapped to the corresponding C++ typedef.
The examples below illustrate this mapping.

IDL
typedef SCAInt32 Hour;

110
SCA IDL Language and C++ Language Mappings

typedef SCAInt32 Minute;


typedef SCAInt32 Second;

C++
typedef SCAInt32 Hour;
typedef SCAInt32 Minute;
typedef SCAInt32 Second;

5.11. Mapping for SCATypeCode


The SCATypeCode type is a special type used by the SCA Framework to describe the details
about each IDL defined type. The SCA Framework creates instances of the SCATypeCode
using XML data generated by the IDL compiler. Each instance of the SCATypeCode
contains the complete description of one IDL defined type. For example, the description of a
structure would include the name and type for each of its members.

The SCATypeCode type is treated in IDL as a basic type and it can appear anywhere in the
IDL where a basic type can appear. For example it could be the member of a structure or one
of the arguments in an interface method.

In C++ a type code is represented by an instance of the SCA::SCATypeCode class. The


definition of a SCATypeCode contains a pair of values. These include a SCATypeCodeID
value that indicates the type of data and a description of the type. The contents of the
description depend on the value of the SCATypeCodeID. The SCATypeCode class is fairly
complex and will not be discussed in detail here. The data contained in this class is mostly
used internally within the SCA Framework. If you need to access these detailed type
definitions you are encouraged to use the [Link] service that is
describe in detail in the Dynamic SCA chapter of the Advanced SDK manual.

Besides generating the XML type definition for every type defined, the IDL compiler also
generates a small bit of code for every IDL defined type which is used to obtain the
SCATypeCode instance for a given type. The following is the format of this code which is
the same for all IDL types.

static SCATypeCode TC_SCA_Test_Color;


template<> struct TypeCodeForType< Color >
{
static const SCATypeCode get() {
if ( !TC_SCA_Test_Color.m_ptc )
getCachedTypeCodeInit("[Link]",TC_SCA_Test_Color);
return TC_SCA_Test_Color;
}
};

The usage of these template specializations as well as other methods for accessing
SCATypeCode values is also described in the Dynamic SCA chapter of the Advanced SDK
manual

111
SCA IDL Language and C++ Language Mappings

5.12. Mapping for SCAAny


The SCAAny is a container data type which can hold a single value of any other arbitrary IDL
data type. Only values for types that are defined in IDL can be stored in a SCAAny. This is
because the SCAAny design requires a SCATypeCode value to describe the data it holds and
marshalling operators to insert and extract the actual value. Both of these are generated by the
IDL compiler and will not exist for types that are not defined in IDL.

The C++ mapping for the IDL type SCAAny fulfills two important requirements:

It must handle the C++ types in a type-safe manner.


It must handle values for complex types that are not known at compile time.

The first requirement covers the typical usage of the SCAAny type, the insertion of typed
values into the SCAAny and the type-safe extraction of the values. The second requirement
covers situations like a requirement to process a SCAAny value that holds data of a type that
is unknown when the service was built. In this case the receiver must be able to determine
information about what type of data the SCAAny contains so it can be processed correctly.

To achieve these requirements, the definition of a SCAAny contains a pair of values that
includes a SCATypeCode value, which describes what type of data is contained, and the
actual value of the data. Using the type code value, the C++ mapping of the SCAAny can
enforce type safety and also allow for the handling of types not known at compile time.

If the value stored in a SCAAny instance is a type that is referenced counted, like an interface
pointer or a SCASequence, the reference count will be correctly incremented when the value
is inserted into the instance and decremented when the SCAAny instance is destroyed or
overwritten. It is therefore safe for the SCAAny to hold only a reference to value and not a
copy of it.

To decrease the chances of creating a SCAAny with a mismatched SCATypeCode and value,
the C++ operator overloading facility is utilized. Specifically, for each distinct type in an IDL
specification, overloaded operators to insert and extract values of that type are used.
Overloaded operators are used instead of functions definitions to avoid namespace pollution.
The usage of these insertion and extraction operators is described below.
The SCAAny class definition
In C++ the SCAAny type is implemented by the SCA::SCAAny class. The public methods
for the class are shown below.

namespace SCA {
class SCAAny
{
public:

// Default constructor
SCAAny();

// Templated constructor to intialize SCAAny with a value


template<typename t_type>

112
SCA IDL Language and C++ Language Mappings

explicit SCAAny(const t_type& val);

// Destructor
~SCAAny();

// Copy constructor
SCAAny(const SCAAny& val);

// Assignment operator
SCAAny& operator = (const SCAAny& val);

// Special insertion operator for a SCAAny iself


SCAVoid operator <<= (const SCAAny& val);

// Templated insertion operator for all other values.


template<typename t_type>
SCAAny& operator <<= (const t_type& val);

// Special extraction operator for a SCAAny iself. True is


// returned if and only if the extraction is successful
SCABool operator >>= (SCAAny& val) const;

// Templated extraction operator for all other values. True is


// returned if and only if the extraction is successful
template<typename t_type>
SCABool operator >>= (t_type& val) const;

// Routines to directly process dynamic arrays in a Any


SCAAny& insertArray(const SCATypeCode tcval,
SCAVoid* values,
SCAUInt32 numEnt1,
SCAUInt32 numEnt2,
const SCATypeCode tcArray=SCATypeCode(),
const DynamicArray::DestroyFunc destroyFunc=NULL);
SCABool extractArray(SCATypeCode& tcval,
SCAVoid** values,
SCAUInt32& numEnt1,
SCAUInt32& numEnt2) const;

// Data extraction and testing


SCAVoid dump() const;
SCATypeCode getType() const;
SCATypeCodeID getTypeID() const;
SCAString getTypeDesc() const;
SCAUInt32 getLength() const;
SCABool sameTypeCode(const SCATypeCode& tcval) const;
SCABool empty() const;
SCAVoid flush();
};
}

The class provides the following capabilities:


Default constructor to create an empty SCAAny instance
Copy constructor
Destructor to release all resource held by the SCAAny instance
Assignment operator

113
SCA IDL Language and C++ Language Mappings

Templated constructors to create a SCAAny instance from the given value


Utility members for accessing and testing type of data stored in the SCAAny
Templated insertion operator <<= for inserting a value into SCAAny
Templated extraction operator >>= for extracting the contents of a SCAAny

Examples of the usages of these are show in the following sections.


Creating new SCAAny values
The following example creates an empty SCAAny value.

// Create an empty SCAAny instance


SCAAny anyval;

To create a new SCAAny value that contains a value you can use the templated constructor.
Note that if the value is a constant that could be converted to any one of several SCA types,
you will have to explicitly tell the compiler which one you wish to use.

// Create a SCAAny instance which contains a SCAInt32 value


SCAAny anyval(SCAInt32(100));

Inserting values into exiting SCAAny values


The insertion operator is used to insert a value into an existing SCAAny instance. If the
SCAAny already holds a value it will be replaced with the existing value and any resources
used by the old value will be released. Remember that the SCAAny can only hold a single
instance at a time.

// Insert an SCAInt32 value to SCAAny instance


SCAInt32 int32val = 100;
anyval <<= int32val;

Or for a simpler version of the same operation you could use the following.

// Insert an SCAInt32 value to SCAAny instance


anyval <<= SCAInt32(100);

Remember that a SCAAny can hold any IDL defined type, not just the basic types used in the
previous example. Here is an example of inserting a sequence into a SCAAny.

// Insert an SCAReal32Sequence value to SCAAny instance


SCAReal32Sequence seqval;
seqval.push_back(1.2);
seqval.push_back(2.3);
anyval <<= seqval;

A SCAAny can even hold another SCAAny instance.

// Insert an SCAAny value to SCAAny instance


SCAAny anyval1(SCAInt32(100));
anyval <<= anyval1;

114
SCA IDL Language and C++ Language Mappings

Extracting the value contained in a SCAAny


The extraction operator is used to extract the value from a SCAAny instance. The SCAAny
remains unchanged after the extraction.

// Extract the value from a SCAAny instance


SCAInt32 int32val
anyval >>= int32val;

The C++ implementation of the SCAAny is type safe. This means you can only extract the
value from the SCAAny if the type of the value it contains is the same as the type of the value
you are trying to extract it into. Since the compiler has no way of knowing what type of value
it may contain, this decision must be made at runtime. To handle this, the extraction operator
returns a logical flag indicating if the extraction was successful or if it failed. If the extraction
was successful, the operation returns true, otherwise it returns false. The following example
shows how several extractions can be used to handle different possible types of values that
may be in the SCAAny instance.

// Extract the value from the SCAAny instance


SCAInt32 int32val;
SCAReal32 real32val;
if ( anyval >>= int32val ){
// Value in SCAAny was a SCAInt32 value and stored in “int32val”
} else if( anyval >>= real32val ){
// Value in SCAAny was a SCAReal32 value and stored in “real32val”
} else {
// Unsupported type
}

Assigning SCAAny values


The SCAAny provides an assignment operator and copy constructor that allows you to copy
the value of one SCAAny value into another. The actual data stored in the SCAAny is
referenced counted so this operation does not result in the coping of any actual data. It only
needs to copy the pointer to the data and increase its reference count.

// Assign a SCAAny value to another SCAAny instance


SCAAny anyval2;
anyval2 = anyval;

Interrogating the value contained in a SCAAny


In addition to using the return value from the extraction operator, you can also directly
interrogate the SCAAny value to see what type of data it contains. This is done by using the
information in the SCATypeCode value contained in the SCAAny instance. The following
shows an example of using this information to determine what type of value should be
extracted instead of using the return value from the extraction operator.

// Extract the value from the SCAAny instance


SCAInt32 int32val;
SCAReal32 real32val;
if ( [Link]() == TCID_Int32 ){

115
SCA IDL Language and C++ Language Mappings

anyval >>= int32val


} else if([Link]() == TCID_Real32 ){
anyval >>= real32val
} else {
// Unsupported type
}

Other methods are also available for accessing the type information.

// Get the SCATypeCode for the value in the SCAAny


SCATypeCode tcval = [Link]();

// Get the ID from the SCATypeCode for the value in the SCAAny
SCATypeCodeID tcid = [Link]();

// Get the type description from the SCATypeCode for the value
SCAString tcdesc = [Link]();

// Check if value of the type in the SCAAny is the same as


// the given SCATypeCode value
If ( [Link](tcval) ) {
// Value in SCAAny is the same as SCATypeCode tcval
}

Miscellaneous SCAAny methods


The SCAAny provides several miscellaneous methods that can be used to check if the
SCAAny contains any data or to flush its contents.

// Check if SCAAny is empty


If ( [Link]() ){
// SCAAny value is empty
}
// Flush the contents of the SCAAny which will now be empty
[Link]();

Special SCAAny methods for Dynamic Arrays


Two special methods, insertArray and extractArray, are also provided by the SCAAny. These
are used for the processing of dynamic arrays and are discussed in detail in the Dynamic SCA
chapter of the Advanced SDK manual.
Limitations in the SCAAny
The current mapping for SCAAny does not allow you to control the precise type code if an
IDL typedef definition is used. Consider the following IDL.

IDL
typedef SCAInt16 YearType;
typedef SCAInt16 MonthType;

The problem is that any of the types SCAInt16, YearType or MonthType can be used for
insertion and extraction into the same SCAAny. This is because C++ does not permit
overloading on types that are aliased to the same underlying type.

116
SCA IDL Language and C++ Language Mappings

5.13. Mapping for SCAResult


The SCAResult type is used to return error information from calls to interface methods. It
contains the following information.

Error code
Message table ID
Message number
Message parameters

The values in a SCAResult instance can be used by the SCA Framework to format and
dispatch messages in the language appropriate for the current user. For more information on
using SCAResult for error processing see the Error Handling chapter of this manual.
SCAResult class definition
The SCAResult type is directly mapped to the C++ SCA::SCAResult class. It provides
methods to construct instances of the class, add parameters, interrogate it contents, log values,
format messages, set inner SCAResult value and apply error policies.

namespace SCA {
class SCA_EXPORT SCAResult
{
public:

// Constructors
SCAResult( SCAInt32 eid=0)
SCAResult( SCAInt32 eid, SCAInt32 msgTableId, SCAInt32 mid);
SCAResult( const SCAResult &sr )
~SCAResult();

// Add an error parameter to SCAResult


void addParam( SCAInt8 );
void addParam( SCAUInt8 );
void addParam( SCAInt16 );
void addParam( SCAUInt16 );
void addParam( SCAInt32 );
void addParam( SCAUInt32 );
void addParam( SCAInt64 );
void addParam( SCAUInt64 );
void addParam( SCAReal32 );
void addParam( SCAReal64 );
void addParam( SCAChar );
void addParam( SCAString );
void addParam( SCAUString );
void addParam( SCABool );

// Conversion operator which returns error code value


operator SCAInt32() const;

// Comparison operator
bool equals(const SCAResult& );

// Assignment operators
SCAResult & operator=( const SCAResult& );
SCAResult & operator=( const SCAInt32 eid );

117
SCA IDL Language and C++ Language Mappings

// Return the information of error


SCAInt32 getTableID() const;
SCAInt32 getMessageID() const;
SCAInt32 getErrorCode() const;
SCAAnySequence getParams() const;
SCABool hasParams() const;
SCABool isOk() const;
SCABool isSystemError() const;

// Marshalling insertion and extraction operators


SCAMarshaller& operator >>= (SCAMarshaller& stream) const;
SCAMarshaller& operator <<= (SCAMarshaller& stream);

// Method to format a SCAResult value


SCAString toString(SCAInt32 raw=0) const;

//Logs this SCAResult


SCAResult log(bool logTraceback=false,int numFrames2Skip=3) const;

// Wrapping methods to set and get the inner SCAResult


void setInnerSCAResult(const SCAResult& result);
bool getInnerSCAResult(SCAResult& result) const;

// Apply error policy to SCAResult.


SCAResult applyErrorPolicy(const SCAString& policyName="") const;

// Debug method to print error information


void dump() const;
};
}

Two predefined SCAResult values are provided when you do not need to return more
detailed information to the caller.

namespace SCA {
const SCAResult SCASuccess(0);
const SCAResult SCAError(0XFFFFFFFF);
}

Examples of the usages of these are shown in the following sections.


Creating new SCAResult values
The following example creates SCAResult values with different levels of initialization.

// Create SCAResult with all zero values


[Link] rstat = new [Link]();
// Create SCAResult with only an error value
[Link] rstat = new [Link](1);
// Create SCAResult with error, tableID and messageID
[Link] rstat = new [Link](1,4,301);}
Resetting the error code in a SCAResult value
The error code in an existing SCAResult value can be reset using the normal assignment
operator.

118
SCA IDL Language and C++ Language Mappings

// Reset error code in SCAResult


rstat = 201;
Adding parameters to a SCAResult value
You use one of the overloaded addParam methods to add a parameter to a SCAResult value.

// Add parameters to SCAResult value


[Link](SCAInt8(1));
[Link](SCAInt16(12));
[Link](SCAInt32(123));
[Link](SCAInt64(1234));
[Link](SCAUInt8(2));
[Link](SCAUInt16(23));
[Link](SCAUInt32(234));
[Link](SCAUInt64(2345));
[Link](SCAReal32(12.34));
[Link](SCAReal64(123.456));
[Link]('A');
[Link]("TestString");
[Link](SCAUString("TestUnicodeString"));
[Link](true);

Interrogating the contents of a SCAResult


The isOk method provides a simple way to test if the SCAResult value has an error.

// Test if SCAResult has a non-zero error


if ( ![Link]() )
// Process error

The get methods can be used to extract the error, table and message values.

// Extract the error, tableID and messageID values


int error = [Link]();
int tableid = [Link]();
int messageid = [Link]();

The hasParams and getParams methods can be used to determine if the SCAResult has
parameters and to process them. The parameter values are returned in a SCAAnySequence.

// If the SCAResult has parameters, print them


if ( [Link]() ) {
SCAAnySequence params = [Link]();
for ( int i=0; i<[Link](); i++ ) {
[Link] param = [Link](i);
[Link]("Param " + i + " = " + [Link]());
}
}
Format a SCAResult Value
The toString method is used to format a SCAResult value to a SCAString.
If the raw parameter is non zero only the raw contents are output. The
following shows an example of formatting a SCAResult value.

119
SCA IDL Language and C++ Language Mappings

// Format a SCAResult value


SCAResult rstat = SCAResult( MSG_SERVICE_COMP_NOT_FOUND,
SCA_KERNEL_MSG_TABLE_ID,
MSG_SERVICE_COMP_NOT_FOUND);
[Link]("[Link]");
SCAString message = [Link]();
std::cout<<"Error Message:"<<std::endl<<message<<std::endl;
SCAString rawMessage = [Link](1);
std::cout << "Raw ErrorMessage:" << std::endl << rawMessage
<< std::endl;

This code will generate the following output.

Error Message
The component for service “[Link]” was not found
in the catalog.

Raw ErrorMessage:
errorCode = 401
msgTableID = 268435455
messageID = 401
Parameters values:
SCAString Value: [Link]

SCAResult Logging
The log methods can be used to manually log the SCAResult error message using the logger
service. The inner wrapped objects are also logged recursively. See the “Logger Service”
chapter of this manual for details on the Logger Service. If the optional logTraceback
parameter is true, the call stack traceback is also logged.
// Log SCAResult only
[Link]();

// Log SCAResult and traceback. By default skip 3 traceback frames


[Link](true);

// Log SCAResult and traceback. Skip 2 traceback frames.


[Link](true, 2);

Setting Inner SCAResult


A SCAResult value may also wrap an inner SCAResult value. This can be used when you
want to change the error value to something more appropriate for the current method but do
not want to lose the original error information. The wrapping may be recursive to any desired
level. The following shows an example of setting an inner SCAResult value.
SCAResult outerSCAResult = SCAResult(MSG_ERROR_UNKNOWN_SIGNAL,
SCA_KERNEL_MSG_TABLE_ID,
MSG_ERROR_UNKNOWN_SIGNAL);
[Link](256);
SCAResult innerSCAResult(MSG_SERVICE_COMP_NOT_FOUND,
SCA_KERNEL_MSG_TABLE_ID,
MSG_SERVICE_COMP_NOT_FOUND);
[Link]("[Link]");
[Link](innerSCAResult);

120
SCA IDL Language and C++ Language Mappings

Apply Error Policy to SCAResult


An Error Policy defines a set of associated actions (such as Log,
Replace, Traceback, Terminate and Minidump), to be taken when handling
errors. The policies are specified in the table
[Link], which is installed as part of the Kernel
in the Resource directory. See the “Error Handling” chapter for more
details.

// Apply error policy to SCAResult.


[Link]("SCAResult");

Miscellaneous SCAResult methods


The SCAResult also implements a dump method which allows you to print the raw contents.

// Print contents using the dump method


[Link]();

5.14. Mapping for Constants


IDL constants are mapped directly to C++ constant definitions.

IDL
const SCAString name1 = "testing1";
const SCAUString name1 = "testing2";

C++
const SCA::SCAString name1 = "testing1";
const SCA::SCAUString name1 = "testing2";

In certain situations, use of a constant in IDL might generate the constant’s value instead of
the constant’s name. This is shown in the following array definition which uses a constant
definition for its size.

IDL
const SCAInt32 n = 10;
typedef SCAInt32 Vec[n];

C++
const SCAInt32 n = 10;
class Vec
{
public:
typedef SCAInt32 value_type;
typedef size_t size_type;
Vec() { }
size_type size() const { return 10; }
value_type& operator[](size_type idx) { return data[idx]; }
const value_type& operator[](size_type idx)const
{ return data[idx]; }
private:
value_type data[10];
};

121
SCA IDL Language and C++ Language Mappings

5.15. Mapping for Interfaces


SCA interfaces are mapped to abstract C++ base classes that contain only pure virtual
functions with no implementation. The mapping for each interface will also contain a smart
pointer definition that is used by the client code to access the interface.

The following is a simple interface definition. This example is missing the definitions of all
the required types but they have no affect on actual interface mapping so they have been left
out to simplify the example.

IDL
#include "SCA/[Link]"

module SCA { module Test {

interface SCAIReader : SCA::SCAIService


{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
SCAINode getNode( in SCAInt32 id ) raises(ReaderException);
};

}; };

Each IDL defined interface will generate two different C++ definitions. Each of these
definitions will be put in a separate header file

A smart pointer definition for the interface with the same name as the interface. In this
example the smart pointer name will be SCAIReader and it will be stored in a header
file with the name SCAIReaderSPtr.h.

An abstract class with the name composed of the interface name followed by the string
Interface. In this example the name of the C++ class will be SCAIReaderInterface
and it will be stored in a header file with the name SCAIReader.h. This file will always
include the file containing the smart pointer definition so you do not need to explicitly
include both.

Each of the generated header files is completely defined. This means they will include any
required header files to allow a successful compile whenever it is used.

The definitions are split between different header files because the smart pointer definition can
act very similar to the forward definition of a C++ class. When you do not need the detailed
information about the methods in an interface you can include the header file for the smart
pointer, SCAIReaderSPtr.h, instead of the header file with the full interface class definition,
SCAIReader.h. This can result in a substantial reduction in the size of the expanded source
files because they do not need to include the definitions of all the types that are used as
parameters in the interface methods. The IDL compiler makes extensive use of the behavior to
keep down the size of the expanded skeleton files it generates. This means that the generated
header files for the full interface definition will only include the smart pointer definitions for
any other interfaces that appear only as parameter values.

122
SCA IDL Language and C++ Language Mappings

There is a side effect when only including the smart pointer definition that needs to be
understood. The stub files for your implementation class will compile correctly as generated
by the IDL compiler. But, as soon as you add a call to a method on an interface that is passed
in as a parameter, you may get a compiler error. Unfortunately these errors tend to be very
cryptic and difficult to understand because they are related to template expansions. If you get
one of these cryptic errors, just include the header file with the full definition of the interface
appearing in the error and it will usually fix the problem.

To illustrate this problem consider the following portion of a simple interface definition.

interface SCAITest1 : SCA::SCAIService


{
SCAVoid test1( in SCAITest2 inf );
};

The code for the test1 method in the generated implementation stub would look something
like this. This code will compile as generated with no errors.

SCA::SCAVoid TestService::test1(const SCAITest2 inf)


{
}

But if you then add a call to a method in the SCAITest2 interface a compilation error may
occur.

SCA::SCAVoid TestService::test1(const SCAITest2 inf)


{
inf->test2();
}

To fix the error, just add an include statement for the SCAITest2.h header file.
Mapping for Interface Smart Pointer Definition
The generated code for the header file containing the definition of the smart pointer for the
SCAIReader interface is shown below.

// Definition of SmartPointer for SCAIReader

#ifndef SCA_TEST_SCAIREADERSPTR_H_INCLUDED
#define SCA_TEST_SCAIREADERSPTR_H_INCLUDED

namespace SCA { namespace Test {


struct SCAIReaderInterface;
typedef SCASmartPointer< SCAIReaderInterface > SCAIReader;
} }

namespace SCA {

template <>
const SCAString SCASmartPointer< SCAIReaderInterface >::getInfName() {
static SCAString infName = "[Link]";
return infName;
}

123
SCA IDL Language and C++ Language Mappings

template <>
const SCAUUID& SCASmartPointer< SCAIReaderInterface >::getUUID(){
static SCAUUID uuid = {0x0d291f4bfd5331e3,0xa1fcefd01e371d1f};
return uuid;
}

#endif

The smart pointer definition contains the following pieces of information.

The expansion of the SCASmartPointer template for the SCAIReaderInterface abstract


class which has the name SCAIReader. The smart pointer is used by the client to access
the methods in the interface.
A template specialization of the getInfName method of the SCASmartPointer class which
contains the name of the interface.
A template specialization of the getUUID method of the SCASmartPointer class which
contains the UUID value for the interface.

Mapping for Interface Abstract Base Class Definition


The generated code for the header file containing the full definition of the
SCAIReaderInterface abstract base class is shown below.

#ifndef SCA_TEST_SCAIREADER_H_INCLUDED
#define SCA_TEST_SCAIREADER_H_INCLUDED

#include "SCAIReaderSPtr.h"
#include "FileReaderTypes.h"
#include "SCAINodeSPtr.h"

// Definition of Interface SCAIReader

namespace SCA { namespace Test {

struct SCAIReaderInterface : public SCAIServiceInterface


{
virtual SCAVoid readModel(const SCAString name) = 0;
virtual SCAINode getNode(const SCAInt32 id) = 0;
};

} }

#endif
Mapping for Interface Operations
Each interface operation maps to a C++ member function with the same name as the
operation.
Mapping Interface Operation Parameters
The following table shows details on how each IDL type is passed when it is use as an in, out
or inout parameter in an interface method or as a return value from a method.

Type in inout out return

124
SCA IDL Language and C++ Language Mappings

SCAInt8 const SCAInt8 SCAInt8& SCAInt8& SCAInt8


SCAInt16 const SCAInt16 SCAInt16& SCAInt16& SCAInt16
SCAInt32 const SCAInt32 SCAInt32& SCAInt32& SCAInt32
SCAInt64 const SCAInt64 SCAInt64& SCAInt64& SCAInt64
SCAUInt8 const SCAUInt8 SCAUInt8& SCAUInt8& SCAUInt8
SCAUInt16 const SCAUInt16 SCAUInt16& SCAUInt16& SCAUInt16
SCAUInt32 const SCAUInt32 SCAUInt32& SCAUInt32& SCAUInt32
SCAUInt64 const SCAUInt64 SCAUInt64& SCAUInt64& SCAUInt64
SCAReal32 const SCAReal32 SCAReal32& SCAReal32& SCAReal32
SCAReal64 const SCAReal64 SCAReal64& SCAReal64& SCAReal64
SCAChar const SCAChar SCAChar& SCAChar& SCAChar
SCAUChar const SCAUChar& SCAUChar& SCAUChar& SCAUChar
SCABool const SCABool SCABool& SCABool& SCABool
SCAResult const SCAResult& SCAResult& SCAResult& SCAResult
enum const enum enum& eum& eum
interface interface& interface& interface& interface
struct const struct& struct& struct& struct
(1)
SCAString const SCAString SCAString& SCAString& SCAString
SCAUString const SCAUString& SCAUString& SCAUString& SCAUString
SCASequence const sequence& sequence& sequence& sequence
array const array& array& array& array
SCAAny const SCAAny& SCAAny& SCAAny& SCAAny
SCATypeCode const SCATypeCode& SCATypeCode& SCATypeCode& SCATypeCode

Note (1) The default passing of input SCAString and SCAWString values is by value
and not by reference. This will normally not be a problem if the size of the strings is
small. But it can lead to performance issues if very large strings are being passed because
a copy of them will be made. You can change the mapping to pass input strings by
reference by adding the following pragma definition in you IDL file.

interface SCAITest : SCA::SCAIService


{
#pragma pass_strings_by_ref
SCAResult testStringRef(in SCA::SCAString val1);
SCAResult testWStringRef(in SCA::SCAWString val1);
};

If the pragma is defined outside of the interface definition, it will apply to all interfaces
defined in the IDL file.

125
SCA IDL Language and C++ Language Mappings

Using Smart Pointers


In the SCA Framework, all access to interfaces is through smart pointers generated by the
SCA IDL compiler. The smart pointers are used to automatically manage the lifecycle control
of the objects that implement the interfaces.

A smart pointer is a C++ class that implements all the required methods and operator
overloads to allow it to behave like a normal C pointer. Since the smart pointer is really a class
object, it can act as an intelligent pointer to objects and hide the complications of dealing with
the objects they point to. Some of the functionality that the SCA smart pointers provide is as
follows.

Every time a smart pointer is created, destroyed, copied or assigned to another smart
point, the appropriate reference counting calls are made to automatically manage the
lifecycle of the objects pointed to.
Navigating or switching between interfaces implemented by the same service object
can be made using standard C++ assignment or casting operators instead of requiring
special framework calls.
Allows you to determine if two different interface references point to the same
underlying implementation object using standard C++ comparison tests.

The following shows some examples of how using smart pointers simplify the handling of
interfaces.

Declarations of smart pointer instances are the same as instances of any C++ class. Note that
no * is used as would be the case with a normal C pointer.

SCAITest1 spTest1;
SCAITest2 spTest2;

The conversion of one smart pointer type to another smart point type is also referred to as
interface navigation. With smart pointers, the syntax for interface navigation is the same as
normal C++ casts or conversions.

try {
spTest2 = static_cast<SCAITest2>(spTest1);
spTest2 = (SCAITest2)spTest1;
spTest2 = spTest1;
} catch(SCAIException ex) {
cout << “Interface cast failed = “ << [Link]() << endl;
}

It is important to remember that you can only navigate from one interface to another interface
if the underlying implementation object supports both interfaces. If the underlying object does
not implement the interface that you wish to navigate to, a SCAException will be thrown. As
a result you should always include interface casts in a try/catch block to catch any errors.

The smart pointer implementation provides a number of different operator overloads that can
be used. Two smart pointers are defined to be equal if they point to the same underlying

126
SCA IDL Language and C++ Language Mappings

implementation object. The normal C++ equality operators can be used for this test. Less then
and greater then operators have no meaning and are not defined.

if ( spTest1 == spTest2 ) ...;


if ( spTest1 != spTest2 ) ...;

The C++ pointer-to-member operator is used to make a call to a method in the interface.

spTest1->doSomething();

A special value, SCA::NULLSP, is provided which is a used to represent a null interface


pointer. The use of the normal C++ NULL value or a 0 value will not work and will generate a
compilation error. The following shows how a smart pointer instance can be reset. If the
instance currently contains a pointer to an implementation object, then the reference count on
that object will be decremented before the pointer is set to null.

spTest1 = NULLSP;

The NULLSP value can also be used to test for an unassigned smart pointer or you can just
test its value.

if ( spTest1 == NULLSP ) ...;


if ( spTest1 != NULLSP ) ...;
if ( !spTest1 ) ...;
if ( spTest1 ) ...;

Several methods are provided which allow you to interrogate information about the contents
of the smart pointer.

// Get the name of the interface the smart pointer is for


cout << “Interface name is “ << [Link]() << endl;

// Get the UUID for the interface the smart pointer is for
SCAUUID uuid = [Link]();

// Get the raw pointer that is held by the smart pointer


void* ptr = [Link]();

5.16. Mapping for Exceptions


The SCA Framework predefines three exception types, SCA::SCAException,
SCA::SCAUserException and SCA::SCASystemException. All user defined exceptions in
IDL must inherit either SCA::SCAUserException or another user-defined exception. Only
single inheritance is allowed.

SCAException class
The base for all IDL defined exceptions is SCA::SCAException. It is mapped to the
following C++ class. Only those methods intended for external use have been shown here.
Other methods required by the framework to manage exceptions and marshal them between
different languages have not been shown.

127
SCA IDL Language and C++ Language Mappings

namespace SCA {
struct SCA_EXPORT SCAException
{
//Constructors and destructors
SCAException(SCABool deleteOnThrow=false);
SCAException(const SCAException &copy);
virtual ~SCAException() throw();

//Method to print out description of exception


SCAString what() const throw();

//Method to get SCATypeCode for this exception


virtual SCATypeCode getTypeCode() const throw();

//Method to get raw text string for this exception


SCAString getText() const throw();

//Method to set raw text string for this exception


SCAVoid setText(const SCAString text) throw();

//Creates an SCAException object


static SCAException* create();

//Throws this exception


virtual void throwit(const SCAString& policyName="SCAException");

//Logs this exception


virtual SCAResult log( bool logTraceback=false,
int numFrames2Skip=3 ) const;

// Wrapping methods to set and get the inner exception


void setInnerSCAException( SCAException * exPtr,
bool makeCopy=true);
SCAException* getInnerSCAException() const;

// Apply the error policy to the Exception.


SCAResult applyErrorPolicy(const SCAString&
policyName="SCAException") const;

// Clones this SCAException


virtual SCAException* clone() const;

//Optional exception description


SCAString m_text;
};
}

SCAUserException class
The SCA::SCAUserException class adds no new data or method. It is provided as a base for
all user defined exceptions.

namespace SCA {
struct SCA_EXPORT SCAUserException: public SCAException
{
//Constructors and destructors
SCAUserException(SCABool deleteOnThrow=false);

128
SCA IDL Language and C++ Language Mappings

SCAUserException(SCAString text, SCABool deleteOnThrow=false);


virtual ~SCAUserException() throw();

//Method to get SCATypeCode for this exception


virtual SCATypeCode getTypeCode() const throw();

//Creates an SCAUserException object


static SCAException* create();

//Throws this exception


virtual void throwit(const SCAString& policyName="SCAException");

// Clones this SCAUserException


virtual SCAUserException* clone() const;
};
}

SCASystemException class
The SCA::SCASystemException class should only be used internally by the SCA
Framework. It adds an error ID to the base SCAException.

namespace SCA {
struct SCA_EXPORT SCASystemException: public SCAException
{
//Constructors and destructors
SCASystemException(SCABool deleteOnThrow=false);
SCASystemException(SCAInt32 id, SCAString text,
SCABool deleteOnThrow=false);
virtual ~SCASystemException() throw();

//Method to get SCATypeCode for this exception


virtual SCATypeCode getTypeCode() const throw();

//Creates an SCASystemException object


static SCAException* create();

//Throws this exception


virtual void throwit(const SCAString& policyName="SCAException");

// Clones this SCASystemException


virtual SCASystemException* clone() const;

//System exception ID
SCAInt32 id;
};
}

Mapping for IDL defined user exceptions


All exceptions defined in IDL should inherit either directly or indirectly from the
SCAUserException type.

IDL
exception ReaderException : SCAUserException
{

129
SCA IDL Language and C++ Language Mappings

SCAString name;
SCAString error;
};

C++
struct ReaderException : public SCAUserException
{
ReaderException(SCABool deleteOnThrow=false) :
SCAUserException(deleteOnThrow) {}
virtual ~ReaderException() throw() {}
static SCAException* create() {
return new ReaderException(true);
}
virtual ReaderException* clone(){
ReaderException* clonePtr = new ReaderException(*this);
clonePtr->copyData(*this);
return clonePtr;
}
virtual void throwit( const SCAString& policyName ) {
// Apply Error policy before throwing the exception.
applyErrorPolicy(policyName);

if ( m_deleteOnThrow ) {
ReaderException exc = *this;
delete this;
[Link]();
throw exc;
} else {
this->setThrow();
throw *this;
}
}
virtual SCATypeCode getTypeCode() const throw() {
return getCachedTypeCode("[Link]");
}

SCAString name;
SCAString error;
};

Special Rules for using SCA Exceptions in C++


The using of SCA exceptions in the C++ language is the same as normal C++ exception usage
with one exception. You should not use the normal C++ throw statement to throw SCA
exceptions. Instead you should use the throwit method provided in the base SCAException
class. The following code shows how this should be done.

ReaderException ex;
[Link] = “[Link]”;
[Link] = “The file does not exist”;
[Link]();

To understand why this is important, consider the following simple example which loads a
service and calls a method which throws an exception.

try {

130
SCA IDL Language and C++ Language Mappings

SCAIReader spReader = getSCAService("[Link]");


SCAINode spNode = spReader->getNode(123);
} catch (SCAException& e) {
cout << "Exception: " << [Link]() << endl;
}

In this example, if the getNode method throws an exception there is a potential problem.
Notice that the getSCAService call to load the service and the only references to it, spReader
and spNode, are all inside the try block. This means that when the method throws an
exception, and the execution flow leaves the try block to enter the catch block, the destructors
for the smart pointers spReader and spNode will be called. Since these are the only references
to the service, the shared library for the service may be unloaded by the SCA Kernel at this
point. This is a problem because the code in the catch block requires access to the
implementation of the exception object which would be no longer available. This can trigger a
crash in the catch block. To keep this from happening you should always throw the exception
using the throwit method. This will trigger some additional logic in the SCA Kernel that will
insure that no shared libraries are unloaded until all of the SCA exception objects that have
been thrown have been deleted.

For a complete discussion of how exceptions are used in the SCA Framework see the Error
Processing chapter of this manual.
5.17. Mapping for SCA Services
Two types of code are generated for SCA service definitions.

The genskeleton command is used to generate the initial implementation skeletons for a
service. The generated skeletons can then be expanded with the code required to
implement the desired behavior for the various interface operations.

During the build process, various C++ base, tie and factory classes are generated by the
IDL compiler. This code is used to link the developer generated implementation code to
the SCA Framework. This is done to reduce as much as possible the amount of code that
must be written by the developer to implement a service. This support code also provides
a level of isolation between the service’s implementation code and the SCA Framework.
This allows for future changes to be made in the interaction between the base or tie classes
and the SCA Framework without affecting the developer’s implementation code. The low
level details of this support code will not be discussed in this section. The only things
about the support code that will be shown are the methods that it exposes for use by the
component developer.

The following is the IDL for an example interface definition that will be used in this section.
#ifndef SCA_FILEREADER_FILEREADER_IDL_INCLUDED
#define SCA_FILEREADER_FILEREADER_IDL_INCLUDED

#include "SCA/[Link]"

module SCA { module FileReader {

struct Node

131
SCA IDL Language and C++ Language Mappings

{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

exception ReaderException : SCAUserException


{
SCAString name;
SCAString error;
};

interface SCAINode;

interface SCAIReader : SCA::SCAIService


{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
SCAINode getNode( in SCAInt32 id ) raises(ReaderException);
};

interface SCAINode : SCA::SCAIService


{
SCAInt32 getID();
SCAReal32 getX();
SCAReal32 getY();
SCAReal32 getZ();
};

}; };

#endif

The following is the SDL for an example service that will implement these interfaces.
#ifndef FILEREADER_SDL_INCLUDED
#define FILEREADER_SDL_INCLUDED

#include "SCA/FileReader/[Link]"

module SCA { module FileReader { module Impl {

service [Link] {
interface SCA::SCAIReader;
subservice NodeImpl ( in SCA::Node node ) {
interface SCA::SCAINode;
};
};

}; }; };

#endif

The inheritance form of implementation


The C++ mapping for SCA services supports two styles of implementation. The default code
generated will use an implementation form where the implementation classes generated by

132
SCA IDL Language and C++ Language Mappings

genskeleton will inherit from base classes that the IDL compiler will generate at build time.
These base classes then inherit from the interface classes and also provide all the necessary
links to the SCA Framework.

When the genskeleton command is run on the above SDL file to generate the skeleton code for
the service, it will generate two C++ classes, FileReader which implements the SCAIReader
interface and NodeImpl which implements the SCAINode interface. The FileReader class is
referred to as the top-level class for the service because it has the same name as the service. A
service implemented in C++ will always have a top-level class. The NodeImpl class is
referred to as a subservice class because it is defined using the subservice construct in the SDL
definition for the service. Subservice classes are optional and will only be generated if
requested in the SDL.
Implementation for top-level class
The following is the header file FileReader.h that is generated for the top-level service class.
#ifndef SCA_FILEREADER_IMPL_FILEREADER_H_INCLUDED
#define SCA_FILEREADER_IMPL_FILEREADER_H_INCLUDED

#include "FileReaderBase.h"

namespace SCA { namespace FileReader { namespace Impl {

class FileReader : public FileReaderBase


{
public:

// Constructor and Destructor


FileReader(SCAIFileReaderFactoryAccess* factoryAccess);
virtual ~FileReader();

// Methods for interface [Link]


virtual SCAVoid readModel(const SCAString name);
virtual SCAINode getNode(const SCAInt32 id);
};

} } }

#endif

The following is the implementation file [Link] that is generated.

#include "FileReader.h"

namespace SCA { namespace FileReader { namespace Impl {

// Constructor
FileReader::FileReader(SCAIFileReaderFactoryAccess* factoryAccess)
: FileReaderBase(factoryAccess)
{
}

// Destructor
FileReader::~FileReader()
{

133
SCA IDL Language and C++ Language Mappings

SCAVoid FileReader::readModel(const SCAString name)


{
}

SCAINode FileReader::getNode(const SCAInt32 id)


{
}

} } }

The C++ implementation will be put in a namespace that is defined by the SDL module
statements. In this example it will be SCA::FileReader::Impl.

The implementation classes generated are fairly simple, but there are a couple of requirements
for these that are imposed by the SCA Framework. These are the requirements when using the
default or inheritance form of implementation.

The class must inherit from the base class generated by the IDL compiler. The name of the
base class will be xxxBase where xxx is the name of the service class.
The class can have only one constructor and it must have a single argument of
SCAIxxxFactoryAccess* where xxx is the name of the top-level service class. This
pointer is used by the base class to access the SCA Framework.
The base class constructor must be explicitly called from the class constructor.
The class must implement each of the operations defined in the interfaces it supports and
any interfaces that inherit from them. The exception to this rule is the methods in the
SCAIService interface do not need to be implemented.

As long as these requirements are followed, the developer is free to make any desired
modifications to these implementation classes.

The base class, FileReaderBase, generated by the IDL compiler during the build process,
does the following.

Inherits from the abstract base class for each interface implemented by the service object.
In this example it will be the SCAIReaderInterface class.
Provides the implementation for all of the required reference counting, interface
navigation and introspection methods in the SCAIService interface that every SCA
service must implement.
Provides complete access to the SCA Framework facilities through the service access
interface.
Provides helper functions for creating new instances of subservice objects using any
initialization parameters defined in the SDL through the service access interface.

If the FileReader service used in this example implemented additional interfaces, the only
changes to the generated code would be the addition of the method definitions for the
operations in the new interfaces.

134
SCA IDL Language and C++ Language Mappings

Implementation for subservice class


The SDL for the FileReader service also includes the definition of a subservice NodeImpl
which takes a Node constructor argument. A separate C++ class, NodeImpl, will be
generated for the subservice class. The format of this class is identical to the FileReader class
except for the addition of an extra argument on the class constructor and the interface methods
it implements. The following is the header file generated for this class.

#ifndef SCA_FILEREADER_IMPL_NODEIMPL_H_INCLUDED
#define SCA_FILEREADER_IMPL_NODEIMPL_H_INCLUDED

#include "NodeImplBase.h"

namespace SCA { namespace FileReader { namespace Impl {

class NodeImpl : public NodeImplBase


{
public:

// Constructor and Destructor


NodeImpl(SCAIFileReaderFactoryAccess* factoryAccess,
const Node& node);
virtual ~NodeImpl();

// Methods for interface [Link]


virtual SCAInt32 getID();
virtual SCAReal32 getX();
virtual SCAReal32 getY();
virtual SCAReal32 getZ();
};

} } }

#endif

Subservice classes have the same requirements imposed by the SCA Framework as top-level
classes except the restrictions on its constructor are relaxed. Subservice classes may still only
have one constructor defined but it is possible for it to have additional user defined arguments.

Only subservice classes can have user defined constructor arguments. This is because
instances of the top-level FileReader class are instantiated by the IDL generated factory class
in response to getService calls made by the clients of the service. There is currently no way for
clients to passes constructor arguments through the getService call. On the other hand,
instances of subservice objects can only be generated by the implementation code in the
service. In this case the implementation is free to pass any desired arguments to the
constructors. It is even possible to pass argument types that are not supported in IDL by using
the SCAVoidPtr IDL type in the SDL definition.
The ServiceAccess interface
In addition to the supporting base classes, the IDL compiler will always generate a unique
ServiceAccess interface for each service. This interface is the link between the
implementation of the service and the SCA Framework. The name of this interface will

135
SCA IDL Language and C++ Language Mappings

always be SCAIxxxServiceAccess where xxx is the name of the top-level service class. The
following is the generated interface for the FileReader service.

#ifndef SCA_FILEREADER_IMPL_SCAIFILEREADERSERVICEACCESS_H_INCLUDED
#define SCA_FILEREADER_IMPL_SCAIFILEREADERSERVICEACCESS_H_INCLUDED

#include "SCA/SCAIServiceAccess.h"
#include "FileReaderTypes.h"

namespace SCA { namespace FileReader { namespace Impl {

SCAINTERFACE SCAIFileReaderServiceAccess : public SCAIServiceAccess


{
// Ask the Service Manager for a service instance
virtual SCAIService getService(const SCAString name,
const SCAString attributes="");
virtual SCAIService getService(const SCAString name,
const SCAString attributes,
SCAResult& rstatus);
virtual SCAIService getService(const SCAString name,
SCAResult& rstatus);

// Get interface on this service object - required for tie impl


::SCA::SCAIService getSCAIService();

// Get system interfaces


virtual SCAIServiceProvider getSCAIServiceProvider();
virtual SCAIServicePublisher getSCAIServicePublisher();
virtual SCAIServiceFactory getSCAIServiceFactory();

// Get a subservice object


virtual SCAIService getNodeImpl(const Node& node);
};

} } }

#endif

The ServiceAccess interface is made available to the implementation classes using the
m_serviceAccess variable defined in the base class.

The ServiceAccess interface provides three overloaded getService methods that should be
used by the implementation code if it needs to load other SCA services. Here is an example of
using these.

SCAIService spSvc;
SCAResult rStat;

spSvc = m_serviceAccess->getService(“[Link]”);

spSvc = m_serviceAccess->getService(“[Link]”,rStat)
if ( rStat ) return rStat;

For each subservice class defined in the SDL, the ServiceAccess interface will also include a
helper method that can be used to create instances of it. The arguments to the method will

136
SCA IDL Language and C++ Language Mappings

match the constructor arguments specified in the SDL for the class. These simplify the task of
creating subservice object instances because the implementation code does not need to worry
about the Factory Access interface that is always required as a constructor argument. The
name of each helper method will be getXxx where Xxx is the name of the subservice class.
The following shows how we can use this helper method in a sample implementation of the
getNode method in the SCAIReader interface. This interface is implemented by the
FileReader class.

SCAINode FileReader::getNode(const SCAInt32 id)


{
// Find and initialize the node with the requested ID
Node node = …

// Return a new subservice object for this node


SCAINode spNode = m_serviceAccess->getNodeImpl(node);
return spNode;
}

The delegation form of implementation


There may be situations where the inheritance form of implementation is inconvenient
because of other requirements in your classes. An example of this is if you wish to use a base
class to provide the implementation for some of the interface methods. The C++ compiler will
not allow the implementation of method in one branch of the inheritance tree to satisfy a pure
virtual method in another branch of the inheritance tree. To resolve this, the delegation form of
implementation can be used. With delegation, the skeleton classes generated by the IDL
compiler do not inherit from a base or interface classes. Instead the base class is replaced with
a separate tie class which inherits from the interface class and provides all the necessary links
to the SCA Framework. When a new instance of the service is requested, an instance of the tie
class is constructed and returned. The tie class will internally construct a separate instance of
your implementation class when it is initialized. Interface calls to the methods in the tie class
are then delegated to the methods in the implementation class that it wraps.

You use the delegate keyword in the SDL file to select the delegation form of implementation.
The following is the header file FileReader.h that is generated for the top-level service class
when delegation is used. The lines in a darker shade of gray are the lines that are different
from the format of this header when the inheritance form of implementation is used.

#ifndef SCA_FILEREADER_IMPL_FILEREADER_H_INCLUDED
#define SCA_FILEREADER_IMPL_FILEREADER_H_INCLUDED

#include "SCA/Framework/Scripting/SCAITypeProvider.h"
#include "SCA/FileReader/SCAIReader.h"
#include "SCAIFileReaderServiceAccess.h"

namespace SCA { namespace FileReader { namespace Impl {

class FileReader
{
public:

// Constructor and Destructor

137
SCA IDL Language and C++ Language Mappings

FileReader(SCAIFileReaderServiceAccess* serviceAccess);
virtual ~FileReader();

// Methods for interface [Link]


SCAVoid readModel(const SCAString name);
SCAINode getNode(const SCAInt32 id);

private:
SCAIFileReaderServiceAccess* m_serviceAccess;
};

} } }

#endif

Notice that class no longer inherits from a base class and as a result the interface methods are
no longer declared virtual. Because there is no requirement that the implementation inherit
from an IDL generated base class, you are free to use any inheritance structure you require.
Also note that the m_serviceAccess variable must now be a member of the implementation
class because there is no longer a base class for it to reside in.

The following is the implementation file [Link] that is generated for the delegation
form of implementation.

#include "FileReader.h"

namespace SCA { namespace FileReader { namespace Impl {

// Constructor
FileReader::FileReader(SCAIFileReaderServiceAccess* serviceAccess)
{
m_serviceAccess = serviceAccess;
}

// Destructor
FileReader::~FileReader()
{
}

SCAVoid FileReader::readModel(const SCAString name)


{
}

SCAINode FileReader::getNode(const SCAInt32 id)


{
}

} } }

Singleton Services
It is also possible to indicate that the service is a singleton in the SDL. The use of this keyword
has no affect on any of the C++ implementation skeletons generated for a service. The
processing of singleton services is handled entirely in the factory support code that is
generated when the service is built. It is important to remember that even so the generated

138
SCA IDL Language and C++ Language Mappings

skeletons are the same; the implementation code for a singleton service may need to be
different. Because multiple clients may be sharing the same instance of the service, the code
needs to make sure this is done in a safe manner.
Aggregation
The C++ mapping also supports the aggregates and aggregated keywords in the SDL. The
affect of these on the mapping for service objects is an advanced topic that is covered later in
this manual.
5.18. Mapping for SCA Components
The C++ mapping uses a normal shared library for SCA components. The only code required
for SCA components is support code generated by the IDL compiler during the build process.
This code is used by the SCA Framework to initialize the component and expose the services
it provides when the component is loaded at runtime. There is no code that the developer
needs to create for a component.
Embedded Components
The C++ mapping supports the embedded option in the CDL. When this option is specified,
the build system compiles the source for the component in normal fashion but it will not link
the object files into a separate shared library. Instead you are allowed to include the generated
object files where ever you would like in the application. Also since the SCA framework will
no longer be loading the share library, a different initialization scheme is required. See section
on embedded components in the Advanced SDK manual for complete details.

139
C++ Language Mappings

SCA Framework User Document

Chapter 6

IDL to Java Language Mapping

2/21/2013 144
C++ Language Mappings

IDL to Java Language Mapping


6.1. Introduction
The IDL language provides a language independent definition of SCA interfaces and data
types. In order to actually use these definitions, there must be a set of rules, commonly known
as a mapping that describes how these types are represented in a particular language. This
chapter explains the mapping that SCA uses for the Java language.

The following table summarizes the data type mapping between IDL and Java types. The
following sections of this chapter will provided the details on each mapping.

IDL Type Java Type


SCA::SCAInt8 byte
SCA::SCAUInt8 short
SCA::SCAInt16 short
SCA::SCAUInt16 int
SCA::SCAInt32 int
SCA::SCAUInt32 long
SCA::SCAInt64 long
SCA::SCAUInt64 long
SCA::SCAReal32 float
SCA::SCAReal64 double
SCA::SCAChar char
SCA::SCAUChar char
SCA::SCAString [Link]
SCA::SCAUString [Link]
SCA::SCABool boolean
SCA::SCAAny [Link]
SCA::SCATypeCode [Link]
SCA::SCAVoid void
SCA::SCAResult [Link]
sequence class (extends [Link])
enum enum
struct class
array [] or class (that wraps [])
const [Link]
interface interface
exception class (extends [Link])

For every type defined in IDL, the IDL compiler will generate the code required to expose the
proper Java definition of the type. In addition to the actual Java definition of the type, there is
also some support code generated for each interface which is used by SCA Framework to
make interface calls from Java to services implemented in the other supported languages.

2/21/2013 145
C++ Language Mappings

When building a Java application or component, the SCA SCons build system will compile
the Java definitions for all of the known IDL types and store them in a single jar file
APPS/lib/java/[Link]. See the section on the SCA Kernel interactions with the JVM
later in this chapter for more details on this.

The SCA Kernel has transitioned from using wide strings to Unicode strings. The
SCAWString and SCAWChar types will be supported for a limited time to allow
applications to migrate to Unicode strings and chars.

6.2. Mapping for Identifiers


IDL identifiers are mapped to Java with no change. For example:

IDL
enum Color { RED, GREEN, BLUE };

Java
public enum Color { RED, GREEN, BLUE }

There is one potential problem to be aware of. If the IDL file contains an identifier that is also
a Java reserved keyword, then the resulting Java code will not compile. Therefore, the use of
Java reserved words for identifiers is not allowed.
6.3. Mapping for Modules
IDL defined types are created in Java packages with the same name as the fully qualified IDL
name scope.

IDL
module SCA {
module FileReader {
// definitions
};
};

Java
package [Link];
// definitions

The IDL module constructs also affect other aspects of the SCA mapping. See the IDL
Compiler chapter for detailed information on how the IDL module statements are used.
6.4. Mapping for Basic Types
Basic data types, SCAInt8, SCAInt16, SCAInt32, SCAInt64, SCAReal32, SCAReal64
and SCABool are directly mapped to Java primitives with no potential for data loss. The
SCAChar is mapped to the Java char. This can cause issues because the Java char contains
multi-byte Unicode characters while the IDL definition of a SCAChar only accommodates

2/21/2013 146
C++ Language Mappings

the single-byte ISO Latin-1 character set. When passing SCAChar data from Java to a
different language, the high byte will be discarded.

The following table shows the Java mapping for the basis SCA types.

SCA IDL Type Java Type


SCAInt8 byte
SCAInt16 short
SCAInt32 int
SCAInt64 long
SCAReal32 float
SCAReal64 double
SCAChar char
SCAUChar char
SCABool boolean

The following structure definition illustrates this mapping.

IDL:
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

Java:
public class Node
{
public int id;
public float x;
public float y;
public float z;
}

6.5. Mapping for Unsigned Data Types


Since Java does not provide unsigned data types, the IDL unsigned integers are mapped to
larger Java integers to preserve their values. For example, SCAUInt8 is mapped to Java short
(16-bit). The exception is that SCAUInt64 is also mapped to long (64-bit).

SCA IDL Type Java Type


SCAUInt8 short
SCAUInt16 int
SCAUInt32 long
SCAUInt64 long

The following example illustrates this mapping.

2/21/2013 147
C++ Language Mappings

IDL
struct Time
{
SCAUInt8 hour;
SCAUInt8 minute;
SCAUInt8 second;
};

Java
public class Time
{
public short hour;
public short minute;
public short second;
}

Because of the mapping of IDL unsigned data to Java signed data, care must be taken when
dealing with the unsigned SCA data types in the Java code.

When calling an interface method implemented in a non-Java service, the Java number
may be truncated if its value is out of the supported range for the IDL type.

When calling an interface method implemented in a non-Java service and the Java value is
negative, the converted IDL unsigned value will be a large positive value.

If a non-Java client passes a large SCAUint64 value to an interface implemented in Java


and its value does not fit in a Java long, then the convert Java value will be a very large
negative value.
6.6. Mapping for String Types
Both SCAString and SCAUString are mapped to [Link]. Converting from a
SCAString or SCAUString to a Java value will not lose any information. When converting
from a Java value to a SCAString, the Java value is first converted to Unicode UTF8 value
which is then stored in the SCAString.

IDL:
struct address
{
SCAString street;
SCAString city;
SCAInt32 zipcode;
};

Java:
public class address
{
public String street;
public String city;
public int zipcode;

2/21/2013 148
C++ Language Mappings

6.7. Mapping for Enumerated Types


An IDL enum is directly mapped to Java enum.

IDL
enum Colors{
RED, GREEN, BLUE
};

Java
public enum Colors
{
RED, GREEN, BLUE
}

6.8. Mapping for Structures


An IDL structure maps to a Java class with all public fields. Each IDL structure member is
mapped to a corresponding member of the Java structure. The Java structure members appear
in the same order as the corresponding IDL structure members. For example:

IDL
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

Java
public class Node
{
public int id;
public float x;
public float y;
public float z;
}

6.9. Mapping for Arrays


Two types of array definitions are supported in IDL. Fixed size arrays must have their size
defined in the IDL and can never change. Dynamic arrays allow you to delay the specification
of the array size until it is actually allocated. Only arrays of rank 1 or 2 are supported.
Fixed size arrays
In Java, arrays are mapped to a Java class of the same name which wraps a Java array. The
class provides a setElementAt and elementAt method, like Java’s [Link], for setting
and accessing the members of the array. The following is an example of a one dimensional
array.

2/21/2013 149
C++ Language Mappings

IDL
typedef SCAInt32 Date[3];

Java
public class Date
{
public Date(){
data=new int[size];
}
public void setElementAt(int e, int index){
data[index]=e;
}
public int elementAt(int index){
return data[index];
}
public int[] getArray(){
return data;
}
public static final int size=3;
private int[] data;
}

The following example shows how the array can be used.

// Set the values of the array


Date dateVal = new Date();
[Link](8,0);
[Link](10,1);
[Link](2009,2);
[Link]("Data is " + [Link](0) + "/" +
[Link](1) + "/" + [Link](2));

The class also provided a getArray method that allows you to extract a reference to the
wrapped Java array which can then be used to

// Access wrapped Java array directly


int[] dateArray = [Link]();
[Link]("Data is " + dateArray[0] + "/" +
dateArray[1] + "/" + dateArray[2]);
dateArray[0] = 12;
[Link]("Modified data is " + dateArray[0] + "/" +
dateArray[1] + "/" + dateArray[2]);

Two dimensional IDL arrays are handled in a similar manner.

IDL
typedef SCA::SCAInt64 Matrix[5][5];

Java
public class Matrix
{

2/21/2013 150
C++ Language Mappings

public Matrix(){
data=new long[size1][size2];
}
public void setElementAt(long e, int index1, int index2){
data[index1][index2]=e;
}
public long elementAt(int index1, int index2){
return data[index1][index2];
}
public long[][] getArray(){
return data;
}
public long[] getRow(int index1){
return data[index1];
}
private long[][] data;
public static final int size1=5;
public static final int size2=5;
}

If an IDL array appears as a member of a structure, it is mapped directly to the member of the
Java defined structure.

IDL
struct Node2
{
SCAInt32 id;
SCAReal32 location[3];
};

Java
public class Node2
{
public int id;
public final float[] location= new float[3];
}

Dynamic Arrays
Dynamic Arrays are mapped to Java classes which are very similar to fixed size arrays except
they take in the size of the array as an argument of the constructor. Dynamic Arrays cannot be
declared inside structures and they are not a substitute for a [Link] since they do not
allow resizing of the array at runtime. Dynamic arrays exist primarily to provide more
optimized code in other languages supported by the SCA framework.

IDL
typedef Node NodeArray[];

Java
public class NodeArray
{
public NodeArray(int s1){
size=s1;

2/21/2013 151
C++ Language Mappings

data=new Node[size];
}
public void setElementAt(Node e, int index){
data[index]=e;
}
public Node elementAt(int index){
return data[index];
}
public Node[] getArray(){
return data;
}
public final int size;
private final Node[] data;
}

Two dimensional dynamic arrays are handled in a similar manner.


6.10. Mapping for Sequences
An IDL sequence is mapped to a Java class that inherits from [Link].

IDL
typedef SCASequence<Node> NodeSequence;

Java
public class NodeSequence extends [Link]<Node>
{
public NodeSequence(){
super();
}
public NodeSequence(int initialCapacity){
super(initialCapacity);
}
public NodeSequence(int initialCapacity, int capacityIncrement){
super(initialCapacity, capacityIncrement);
}
}

When an IDL sequence appears as a member of a structure, a Java class for the sequence is
defined inside the Java class for the structure and it is used for the structure member.

IDL
struct Node3
{
SCAInt32 id;
SCASequence<SCAReal32> location;
};

Java
public class Node3
{
public static class Internal_location_1 extends
[Link]<Float>

2/21/2013 152
C++ Language Mappings

{
public Internal_location_1(){
super();
}
public Internal_location_1(int initialCapacity){
super(initialCapacity);
}
public Internal_location_1(int initialCapacity,
int capacityIncrement){
super(initialCapacity, capacityIncrement);
}
}
public int id;
public Node3.Internal_location_1 location;
}

Since generated sequence classes inherit from [Link], they are used the same way as
any Java Vector object.

// Initialize contents of the sequence


SCAReal64Sequence seq = new SCAReal64Sequence();
[Link](1.0);
[Link](2.0);
[Link](3.0);

// Print contents of the sequence


for ( int i=0; i<[Link](); i++ )
[Link]("seq[" + i + "] = " + [Link](i));

6.11. Mapping for Vectors


Just like Sequence an IDL vector is mapped to a Java class that inherits from
[Link].

6.12. Mapping for Maps


An IDL map is mapped to a class that inherits from [Link].

IDL

typedef map<SCAString, SCAReal64> MapStringReal64;

Java
public class MapStringReal64 extends [Link]<String,Double> {
public MapStringReal64(){
super();
}
public MapStringReal64(int initialCapacity){
super(initialCapacity);
}

2/21/2013 153
C++ Language Mappings

public MapStringReal64(int initialCapacity, int loadFactor){


super(initialCapacity, loadFactor);
}
}

The following example shows how to create, initialize and print a map.

// Initialize contents of the map


MapStringReal64 realMap = new MapStringReal64();
[Link]("first value", 65.74);
[Link]("second value", 5.75);
[Link]("third value", 4.6);
[Link]("fourth value", 78.7);

// Print contents of the map


[Link](“realMap:” + [Link]());

6.13. Mapping for Type Aliases


A typedef is used in SCA IDL to define a sequence, an array or an alias for an existing type.
The Java mapping for sequences and arrays has already been discussed in the previous
sections.

The use of the IDL typedef to create a new name for an existing type must be handled
differently in Java because the language does not support this concept. Therefore, IDL typedef
definitions are first unwound to either the SCA basic type or the user defined IDL type that it
refers to and then the unwound type is used as the Java type. As a result, the name of the IDL
typedef type will never appear in the generated Java code.

The following examples show how IDL typedef definitions that refer to both SCA basic types
and other IDL defined types are unwound.

IDL
typedef SCAInt32 HourValue;
typedef SCAInt32 MinuteValue;
typedef SCAInt32 SecondValue;

struct TimeDef
{
HourValue hour;
MinuteValue minute;
SecondValue second;
};

typedef TimeDef LocalTime;


typedef TimeDef GMTTime;

interface SCAITimeConvert
{
LocalTime convert(in GMTTime time);

2/21/2013 154
C++ Language Mappings

};

Java
public class TimeDef
{
public int hour;
public int minute;
public int second;
}

public interface SCAITimeConvert extends [Link]


{
TimeDef convert(TimeDef time);
}

Notice how the HourValue, MinuteValue, SecondValue, LocalTime and GMTTime alias
types have been unwound and the SCA basic types or IDL defined types have been used
instead.
6.14. Mapping for SCATypeCode
The SCATypeCode type is a special type used by the SCA Framework to describe the details
about each IDL defined type. The SCA Framework creates instances of the SCATypeCode
using XML data generated by the IDL compiler. Each instance of the SCATypeCode
contains the complete description of one IDL defined type. For example, the description of a
structure would include the name and type for each of its members.

The SCATypeCode type is treated in IDL as a basic type and it can appear anywhere in the
IDL where a basic type can appear. For example it could be the member of a structure or one
of the arguments in an interface method.

In Java a type code value is represented by the SCATypeCode class. The definition of a
SCATypeCode contains a pair of values. These include a SCATypeCodeID value that
indicates the type of data and a description of the type. The contents of the description depend
on the value of the SCATypeCodeID. The SCATypeCode class is fairly complex and will
not be discussed in detail here. The data contained in this class is mostly used internally within
the SCA Framework. If you need to access these detailed type definitions you are encouraged
to use the [Link] service that is describe in detail in the Dynamic SCA
chapter of this manual.
6.15. Mapping for SCAAny
The SCAAny is a container data type which can hold a single value of any other arbitrary IDL
data type. Only values for types that are defined in IDL can be stored in a SCAAny. This is
because the SCAAny design requires a SCATypeCode value to describe the data it holds and
these are only generated by the IDL compiler and will not exist for types that are not defined
in IDL.

The Java mapping for the IDL type SCAAny fulfills two important requirements:

2/21/2013 155
C++ Language Mappings

It must handle the Java types in a type-safe manner.


It must handle values for complex types that are not known at compile time.

The first requirement covers the typical usage of the SCAAny type, the insertion of typed
values into the SCAAny and the type-safe extraction of the values. In Java the type-safety is
ensured by the SCAAny class and the Java JVM. When you try to insert a value into a
SCAAny, the class will make sure that the data being inserted is an IDL defined type and
consistent with the SCA type description. If it is not, then a SCASystemException will be
thrown. When you try to extract a value from the SCAAny, the JVM will attempt to cast it to
the type you requested. If the value can be converted then the extraction will succeed. If it
cannot be converted then a Java RuntimeException exception will be thrown.

The second requirement covers situations like the need to extract data from the SCAAny
when you do not know the type of data it contains. In this case the receiver must be able to
determine information about what type of data the SCAAny contains. To achieve this,
SCAAny contains a pair of values that includes the actual value of the data and a description
of its type. The type information can then be inspected to determine the details on the value
stored in the SCAAny instance.
The SCAAny class definition
In Java the SCAAny type is implemented by the [Link] class. The public methods for
the class are shown below.

package SCA;
public class SCAAny
{
// Constructors
public SCAAny()
public SCAAny(Object data);
public SCAAny(Object data, String typeString);

// Methods for inserting and extracting values


public void setSCAInt8(byte data);
public byte getSCAInt8();
public void setSCAUInt8(short data);
public short getSCAUInt8();
public void setSCAInt16(short data);
public short getSCAInt16();
public void setSCAUInt16(int data);
public int getSCAUInt16();
public void setSCAInt32(int data);
public int getSCAInt32();
public void setSCAUInt32(long data);
public long getSCAUInt32();
public void setSCAInt64(long data);
public long getSCAInt64();
public void setSCAUInt64(long data);
public long getSCAUInt64();
public void setSCAReal32(float data);
public float getSCAReal32();

2/21/2013 156
C++ Language Mappings

public void setSCAReal64(double data);


public double getSCAReal64();
public void setSCAChar(char data);
public char getSCAChar();
public void setSCAString(String data);
public String getSCAString();
public void setSCAUChar(char data);
public char getSCAUChar();
public void setSCAUString(String data);
public String getSCAUString();
public void setSCABool(boolean data);
public boolean getSCABool();
public void setSCAAny(SCAAny data);
public SCAAny getSCAAny();
public void setSCATypeCode(SCATypeCode data);
public SCATypeCode getSCATypeCode();
public void setSCAResult(SCAResult data);
public SCAResult getSCAResult();
public void setSCAObject(Object data);
public void setSCAObject(Object data, String typeString);
public Object getSCAObject();

// Flush the contents


public void flush();

// Methods for getting information about the contents


public String type();
public boolean empty();
public String toString();

// SCAAny data
private Object m_data;
private String m_type;

Examples of using the SCAAny are show in the following sections.


Creating new SCAAny values
The following example creates an empty SCAAny value.

// Create an empty SCAAny instance


[Link] any = new [Link]();

To create a new SCAAny value that contains a value you can use the constructor which takes
a Java Object and an optional string description of the type. Which form you use depends on
the way the SCA type is mapped in Java. If the SCA type maps to a Java class that is
generated by the IDL compiler, then you only need to provide the instance in the constructor.
This includes types like sequences, structures, enumerations, array and interfaces. The
following shows an example of this.

// Create a SCAAny instance which contains a structure value


Node node = new Node();

2/21/2013 157
C++ Language Mappings

[Link] = 123;
node.x = 1.0;
node.y = 2.0;
node.z = 3.0;
[Link] any = new [Link](node);

But, if the SCA type maps to a native Java type that cannot be uniquely mapped to a SCA
type then you will need to add the type description to explicitly specify the type. An example
of this is a Java String value which can be mapped to either a SCAString or a SCAUString
value.

// Create a SCAAny instance which contains a SCAString value


[Link] any = new [Link](new String(“test”),”[Link]”);

Because the SCAAny will only hold an object that inherits from the Java Object type, you
cannot create a new SCAAny with a primitive type directly. Instead you must use its
corresponding wrapper classes as shown in this example. Since the wrapper classes do have
unique SCA mappings, you must also include the type description in this case.

// Create a SCAAny instance which contains a SCAInt32 value


[Link] any = new [Link](new Integer(123),”SCA.SCAInt32”);
Inserting values into exiting SCAAny values
You also insert a value into an existing SCAAny instance. If the instance already holds a
value it will be replaced with the new value. Remember that the SCAAny can only hold a
single value at a time.

Inserting values into an existing SCAAny instance follows a similar pattern that was
described previously for constructing new SCAAny values with one exception. Since the
insertion of basic types into a SCAAny is so common, a special group of set methods is
provided. There is a separate set method defined for each basic SCA type. These methods
allow you to insert primitive values directly into the SCAAny without having to use the
wrapper classes.

// Insert a SCAInt32 value into a SCAAny instance


anyval.setSCAInt32(12);

// Insert a SCAString value into a SCAAny instance


[Link](“value”);

Non-basic types are inserted using the setSCAObject method. Here is an example of inserting
a sequence into a SCAAny.

// Insert a SCAReal64Sequence value into a SCAAny instance


SCAReal64Sequence seq = new SCAReal64Sequence();
[Link](1.0);
[Link](2.0);
[Link](seq);

2/21/2013 158
C++ Language Mappings

As before, since a SCA sequence has a unique mapping to a Java class, you do not need to add
the type description. But if the mapping is not unique you will need to.

// Insert a SCAString value into a SCAAny instance


[Link](new String(“value”),”[Link]”);

// Insert a SCAInt32 value into a SCAAny instance


[Link](new Integer(123),”SCA.SCAInt32”);

A SCAAny can even hold another SCAAny instance.

// Insert an SCAAny value to SCAAny instance


[Link] anyval2 = new [Link](new Long(123),”SCA.SCAInt64”);
[Link](anyval2);
Extracting the value contained in a SCAAny
To extract a value from the SCAAny, you use the get method that corresponds to the data
contained in it. When extracting values, it is important that you pick the correct method
otherwise Java will throw a RuntimeException exception.

// Extract a SCAInt32 from a SCAAny instance


try {
int int32val = anyval.getSCAInt32();
} catch (RuntimeException ex) {
[Link]("RuntimeException:" + [Link]());
}

For non-basic types, you will need to use the getSCAObject method to extract the value. This
value must be cast to the desired Java type as shown in this example.

// Extract a Node structure value from a SCAAny instance


try {
Node node = (Node)[Link]();
[Link]("Extracted value: id=" + [Link] +
" x=" + node.x +
" y=" + node.y +
" z=" + node.z);
} catch (RuntimeException ex) {
[Link]("RuntimeException:" + [Link]());
}

There may be cases where the SCAAny value may hold one of a number of different types
and you do not know at compilation time which one it is. In this case you can use the type
method to determine what type it contains so you can choose the correct get method. The
following example shows how several extractions can be used to handle different possible
types of values that may be in the SCAAny instance.

// Extract an unknown type from a SCAAny instance


int int32val;
float real32val;
if ( [Link]() == "SCA.SCAInt32" ) {

2/21/2013 159
C++ Language Mappings

int32val = anyval.getSCAInt32();
[Link]("int32val = " + int32val);
} else if ( [Link]() == "SCA.SCAReal32" ) {
real32val = anyval.getSCAReal32();
[Link]("real32val = " + real32val);
} else {
[Link]("Unsupported type " + [Link]());
}
Miscellaneous SCAAny methods
The SCAAny provides several miscellaneous methods that can be used to check if the
SCAAny contains any data or to flush its contents.

// Check if SCAAny is empty


If ( [Link]() ){
// SCAAny value is empty
}
// Flush the contents of the SCAAny which will now be empty
[Link]();

The SCAAny also implements the toString method which allows you to get a string
representation of its contents.

// Print the information about the contents of the SCAAny


[Link]("SCAAny value is " + [Link]());

6.16. Mapping for SCAResult


The SCAResult type is used to return error information from calls to interface methods. It
contains the following information

Error code
Message table ID
Message number
Message parameters

The values in a SCAResult instance can be used by the SCA Framework to format and
dispatch messages in the language appropriate for the current user. For more information on
using SCAResult for error processing see the Error Handling chapter of this manual.
SCAResult class definition
The SCAResult type is mapped to the following Java class

package SCA;
public class SCAResult
{
// Constructors
public SCAResult();
public SCAResult(int errorCode);
public SCAResult( int errorCode, int msgTableId, int messageID);

2/21/2013 160
C++ Language Mappings

// Setting values
public void setErrorCode( int errorCode );

// Return values
public int getErrorCode();
public int getTableID();
public int getMessageID();

// Add a new parameter


public void addSCAInt8(byte t );
public void addSCAUInt8(short t );
public void addSCAInt16(short t );
public void addSCAUInt16(int t );
public void addSCAInt32(int t );
public void addSCAUInt32(long t );
public void addSCAInt64(long t );
public void addSCAUInt64(long t );
public void addSCAReal32(float t );
public void addSCAReal64(double t );
public void addSCAChar(char t );
public void addSCAUChar(char t );
public void addSCAString(String t );
public void addSCAUString(String t );
public void addSCABool(boolean t );

// Compare all fields of SCAResult data, excluding parameters


public boolean equals(SCAResult sr );

// Return the parameters


public SCAAnySequence getParams();

// Return true if has parameters, return false otherwise.


public boolean hasParams();

// Return true if the error code == 0


public boolean isOk();

// Return true if it is a system error


public boolean isSystemError();

// Print raw contents of SCAResult


public void dump();

// Return a formatted message


public String toString();

// Predefined SCAResult values


public final static SCAResult SCASuccess = new SCAResult(0);
public final static SCAResult SCAError = new SCAResult(0X7FFFFFFF);
}

Two predefined SCAResult values are provided when you do not need to include more
detailed information to the callers.

// Return error

2/21/2013 161
C++ Language Mappings

return [Link];
// Return success
return [Link];

Examples of the usages of these are shown in the following sections.


Creating new SCAResult values
The following example creates SCAResult values with different levels of initialization.

// Create SCAResult with all zero values


[Link] rstat = new [Link]();
// Create SCAResult with only an error value
[Link] rstat = new [Link](1);
// Create SCAResult with error, tableID and messageID
[Link] rstat = new [Link](1,4,301);}

Resetting the error code in a SCAResult value


The error code in an existing SCAResult value can be reset as follows.

// Reset error code in SCAResult


[Link](201);
Adding parameters to a SCAResult value
You use one of the add methods to add a parameter to a SCAResult value.

// Add parameters to SCAResult value


rstat.addSCAInt8((byte)1);
rstat.addSCAInt16((short)12);
rstat.addSCAInt32((int)123);
rstat.addSCAInt64((long)1234);
rstat.addSCAUInt8((byte)2);
rstat.addSCAUInt16((short)23);
rstat.addSCAUInt32((int)234);
rstat.addSCAUInt64((long)2345);
rstat.addSCAReal32(12.34F);
rstat.addSCAReal64(123.456);
[Link]('A');
[Link]("TestString");
[Link]("TestUnicodeString");
[Link](true);
Interrogating the contents of a SCAResult
The isOk method provides a simple way to test if the SCAResult value has an error.

// Test if SCAResult has a non-zero error


if ( ![Link]() )
// Process error

The get methods can be used to extract the error, table and message values.

// Extract the error, tableID and messageID values


int error = [Link]();

2/21/2013 162
C++ Language Mappings

int tableid = [Link]();


int messageid = [Link]();

The hasParams and getParams methods can be used to determine if the SCAResult has
parameters and to process them. The parameter values are returned in a SCAAnySequence.

// If the SCAResult has parameters, print them


if ( [Link]() ) {
for ( int i=0; i<[Link](); i++ ) {
[Link] param = [Link](i);
[Link]("Param " + i + " = " + [Link]());
}
}
Miscellaneous SCAResult methods
The SCAResult also implements the toString and dump method which allows you to get or
print the contents. The toString method will attempt to format a message for the SCAResult
value while the dump method just prints the raw data.

// Print a string representation of the SCAAny


[Link]("SCAResult value is " + [Link]());

// Print contents using the dump method


[Link]();

6.17. Mapping for Constants


An IDL defined constants are mapped to an interface of the same name as the constant which
contains a single fixed data value with the name value which has the value of the IDL
constant.

IDL
const SCA::SCAInt32 NUM_OF_STATES = 50;

Java
public interface NUM_OF_STATES
{
final int value = 50;
}

The value of the constant can be referenced using the value field.

// Print value of constant defined in IDL


[Link]("constant value = " + NUM_OF_STATES.value);

6.18. Mapping for Interfaces


SCA interfaces are mapped directly to Java interfaces.

The following is a simple interface definition. This example is missing the definitions of all
the required types but they have no affect on actual interface mapping so they have been left
out to simplify the example.

2/21/2013 163
C++ Language Mappings

IDL
interface SCAIReader : SCA::SCAIService
{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
SCAINode getNode( in SCAInt32 id ) raises(ReaderException);
SCAVoid getNodeCoordinates( in SCAInt32 id,
out SCAReal32 x,
out SCAReal32 y,
out SCAReal32 z )
raises(ReaderException);
};

Java
public interface SCAIReader extends [Link]
{
void readModel(String name) throws ReaderException;
SCAINode getNode(int id) throws ReaderException;
void getNodeCoordinates(int id,
[Link]<Float> x,
[Link]<Float> y,
[Link]<Float> z) throws ReaderException;
}

Mapping for Interface Operations


Each interface operation (or method) is mapped to a method in the Java interface with the
same name.
Mapping for Interface Parameters
Each parameter in an IDL operation must have direction of in, out or inout. Input parameters
are mapped directly to their corresponding Java parameters. But, since Java does not support
output type parameters, they must be handled specially. The mapping for out or inout
parameters in Java uses a predefined generic class, [Link], that holds an instance of the
parameter.

package SCA;
public class Holder<T>{
public Holder(){
value=null;
}
public Holder(T obj){
value=obj;
}
public T value;
}

If the IDL parameter is one of the SCA basic types then the [Link] class must hold its
corresponding Java box type and not the primitive type. The following table shows the
corresponding box type for each SCA IDL type.

2/21/2013 164
C++ Language Mappings

IDL Type Java primitive type Java box type


SCA::SCAInt8 byte [Link]
SCA::SCAUInt8 short [Link]
SCA::SCAInt16 short [Link]
SCA::SCAUInt16 int [Link]
SCA::SCAInt32 int [Link]
SCA::SCAUInt32 long [Link]
SCA::SCAInt64 long [Link]
SCA::SCAUInt64 long [Link]
SCA::SCAReal32 float [Link]
SCA::SCAReal64 double [Link]
SCA::SCAChar char [Link]
SCA::SCAUChar char [Link]
SCA::SCABool boolean [Link]

When calling a method with output parameters, you must first create instances of the
[Link] class and pass them as the parameter as shown in this example.

[Link]<Float> x = new [Link]<Float>();


[Link]<Float> y = new [Link]<Float>();;
[Link]<Float> z = new [Link]<Float>();;
[Link](id,x,y,z);
[Link](“X=” + [Link]());
[Link](“Y=” + [Link]());
[Link](“Y=” + [Link]());

If any of these parameters was specified with the inout direction, the value in the holder class
should be set before the interface method is called.
6.19. Mapping for Exceptions
The SCA Framework predefines three exception types, [Link],
[Link] and [Link]. All user defined exceptions in
IDL must inherit either SCA::SCAUserException or another user-defined exception. Only
single inheritance is allowed.
SCAException interface
The base for all IDL defined exceptions is SCAException which is mapped to the java
interface [Link].

package SCA;
public interface SCAException
{
// Method to return description of the exception
String what();
// Method to get SCATypeCode for this exception
SCATypeCode getTypeCode();
// Method to get raw text string for this exception
String getText();
// Method to set raw text string for this exception

2/21/2013 165
C++ Language Mappings

void setText(String text);


}
SCAUserException class
The SCAUserException exception adds no new data to SCAException and should be used
as the base for all user defined exceptions. It is mapped to the predefined Java class
[Link] which implements the [Link] interface.

package SCA;
public class SCAUserException extends Exception
implements SCAException
{
// Constructor
public SCAUserException();
// Methods to return description of exception
public final String what();
public final String toString();
// Method to get SCATypeCode for this exception
public final SCATypeCode getTypeCode();
// Method to get raw text string for this exception
public final String getText();
// Method to set raw text string for this exception
public final void setText(String text);
// Method to set exception type
protected final void setType(String type);
// Exception data
private String m_type;
protected String m_text;
}
SCASystemException class
The SCASystemException exception should only be used internally by the SCA Framework
and adds an error ID member to SCAException. It is mapped to the predefined Java class
[Link] which implements the [Link] interface. Note that
[Link] inherits from Java’s RuntimeException exception, so it is treated
as an unchecked exception by the java runtime.

package SCA;
public class SCASystemException extends RuntimeException
implements SCAException
{
// Constructors
public SCASystemException();
public SCASystemException(int iid);
public SCASystemException(int iid, String text);
// Methods to return description of the exception
public final String what();
public final String toString();
// Method to get SCATypeCode for this exception
public final SCATypeCode getTypeCode();
// Method to get raw text string for this exception
public final String getText();
// Method to set raw text string for this exception

2/21/2013 166
C++ Language Mappings

public final void setText(String text);


// Method to set exception type
protected final void setType(String type);
// Method to return exception traceback
public static String getTrace(Throwable e);
// Exception data
private String m_type;
protected String m_text;
public int id;
}

Mapping for IDL defined user exceptions


User-defined exceptions are mapped to respective Java classes. All the user defined members
in an exception are mapped as public fields in the exception class.

IDL
exception ReaderException : SCAUserException
{
SCAString name;
SCAString error;
};

Java
public class ReaderException extends [Link]
{
public ReaderException();
public String name;
public String error;
};

The following code shows an example of how you throw a SCA exception in Java.

ReaderException ex = new ReaderException();


[Link] = “[Link]”;
[Link] = “The file does not exist”;
throw ex;

And the exception can be caught as follows.

try
{
// Code that triggers an exception
}
catch (ReaderException ex)
{
[Link]("ReaderException caught for");
[Link](“File: “ + [Link]);
[Link](“Error: “ + [Link]);
}

2/21/2013 167
C++ Language Mappings

The IDL raises clause


An IDL interface operation may contain a raises clause to indicate what kind of exceptions the
operation may throw.

IDL
interface SCAIReader : SCA::SCAIService
{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
};

Java
public interface SCAIReader extends [Link]
{
void readModel(String name) throws ReaderException;
}

Use of the raises clause is especially important in Java, since a method that throws an
exception should specify it in a throws clause. The SCASystemException exception is an
unchecked Java exception so it can always be thrown and users do not need to include it in the
raises clause. Other exceptions that may be thrown must be one of the exceptions in the raises
clause to inherit from one of them.
6.20. Mapping for SCA Services
Two types of code are generated for SCA service definitions.

The genskeleton command is used to generate the initial implementation skeletons for a
service. The generated skeletons can then be expanded with the code required to
implement the desired behavior for the various interface operations.

During the build process, various Java base classes are generated which are used to link
the developer generated implementation code to the SCA Framework. This is done to
reduce as much as possible the amount of code that must be written by the developer to
implement a service. These classes also provide a level of isolation between the service’s
implementation code and the SCA Framework. This allows for future changes to be made
in the interaction between the base classes and the SCA Framework without affecting the
developer’s implementation code.

The following is the IDL file for an example interface definition that will be used in this
section.

#ifndef SCA_FILEREADER_FILEREADER_IDL_INCLUDED
#define SCA_FILEREADER_FILEREADER_IDL_INCLUDED

#include "SCA/[Link]"

module SCA { module FileReader {

struct Node

2/21/2013 168
C++ Language Mappings

{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

exception ReaderException : SCAUserException


{
SCAString name;
SCAString error;
};

interface SCAINode;

interface SCAIReader : SCA::SCAIService


{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
SCAINode getNode( in SCAInt32 id ) raises(ReaderException);
};

interface SCAINode : SCA::SCAIService


{
SCAInt32 getID();
SCAReal32 getX();
SCAReal32 getY();
SCAReal32 getZ();
};

}; };

#endif

The following is the SDL for an example service that will implement these interfaces.

#ifndef FILEREADER_SDL_INCLUDED
#define FILEREADER_SDL_INCLUDED

#include "SCA/FileReader/[Link]"

module SCA { module FileReader { module Impl {

service [Link] {
interface SCA::FileReader::SCAIReader;
subservice NodeImpl ( in SCA::FileReader::Node node ) {
interface SCA::FileReader::SCAINode;
};
};

}; }; };

#endif

2/21/2013 169
C++ Language Mappings

The inheritance form of implementation


In the inheritance form of implementation, the implementation classes generated by
genskeleton will inherit from base classes generated by the IDL compiler at build time. These
base classes will then inherit from the interface classes and also provide all the necessary links
to the SCA Framework.

When the genskeleton command is run for the above SDL file to generate the skeleton code
for the service, it will generate two Java classes, FileReader which implements the
SCAIReader interface and NodeImpl which implements the SCAINode interface.

The Java implementation will be put in a package that is defined by the SDL module
statements. In this example it is [Link]. This will also define the subdirectory
where the implementation files will be written. In this example the actual file created for the
FileReader class will be SCA/FileReader/Impl/[Link].

The following is the file [Link] that is generated for the top-level service class.

package [Link];

public class FileReader extends FileReader_base


{
// Constructor
public FileReader ([Link] provider)
{
super();
setServiceProvider(provider);
}

// Methods for interface [Link]


public final void readModel (String name)
throws [Link]
{
//implementation goes here
}
public final [Link] getNode (int id)
throws [Link]
{
//implementation goes here
}
}

The implementation classes generated are fairly simple, but there are a couple of requirements
for these imposed by the SCA Framework. These are the requirements when using the default
or inheritance form of implementation.

The class must inherit from the base class generated by the IDL compiler.
The class can have only one constructor and it must have a single argument of
SCAIServiceProvider type. This argument is used by the base class to access the
SCA Framework.

2/21/2013 170
C++ Language Mappings

The base class constructor must be explicitly called from the class constructor.
The class must implement each of the operations defined in the interfaces it supports
except for SCAIService.

As long as these requirements are met, the developer is free to make any desired modifications
to these implementation classes.

The base class FileReader_base, which will be generated by the IDL compiler when it is run
during the build process, provides the following.

Inherits from the respective interface for each interface implemented by the service
class. In this example it will be the SCAIReader interface.
Provides the implementation for all of the required reference counting, interface
navigation and introspection methods in the SCAIService interface that every SCA
service class must implement.
Provides access to the SCA Framework facilities.

If the FileReader service used in this example implemented additional interfaces, the only
changes to the generated code would be the addition of the method definitions for the
operations in the new interfaces.

The SDL for the FileReader service also includes the definition of a subservice NodeImpl
which takes a Node constructor argument. A separate Java class, NodeImpl, will be
generated for the subservice class. The format of this class is identical to the FileReader class
except for the addition of an extra argument defined in the SDL file on the class constructor
and the interface methods it implements.

Following is the [Link] class generated by the genskeleton command

package [Link];

public class NodeImpl extends NodeImpl_base


{
// Constructor
public NodeImpl ([Link] provider,
[Link] node)
{
super();
setServiceProvider(provider);
}

// Methods for interface [Link]


public final int getID ()
{
//implementation goes here
}
public final float getX ()
{
//implementation goes here

2/21/2013 171
C++ Language Mappings

}
public final float getY ()
{
//implementation goes here
}
public final float getZ ()
{
//implementation goes here
}
}

Only subservice classes can have user specified constructor arguments. This is because
instances of the top-level FileReader class are instantiated by the IDL generated factory class
in response to getService calls made by the clients of the service. There is currently no way for
clients to passes constructor arguments through the getService call. On the other hand,
instances of subservice classes can only be generated by the implementation code in the
service. In this case the implementation is free to pass any desired arguments to the
constructors.

The following is an example implementation for the getNode method which returns an
instance of the SCAINode interface. The SDL definition for this service specifies that the
SCAINode interface is implemented by the NodeImpl subservice class. That means that the
getNode method needs to allocate an instance of the NodeImpl class and return the
SCAINode interface on it. The constructor for the NodeImpl class, generated by the
genskeleton utility, requires two parameters. The first parameter is the SCAIServiceProvider
interface which is available in the m_provider variable in the base class. The second argument
is an instance of the Node structure that was specified as a constructor argument in the SDL.

SCAINode FileReader::getNode(const SCAInt32 id)


{
// Find and initialize the node which cooresponds to ID
Node node = …

// Return a new subservice class instance for this node


NodeImpl spNode = new NodeImpl(m_provider,node);
return (SCAINode)spNode;
}
The ServiceAccess interface
The base classes generated by the IDL compiler will always implement the
[Link] interface. This interface is the link between the implementation of the
service and the SCA Framework. The following is the definition of the ServiceAccess
interface:

package SCA;
public interface ServiceAccess
{
// Load a SCA service
SCAIService getService(String name, String attr);

// Set the SCAIServiceProvider interface

2/21/2013 172
C++ Language Mappings

void setServiceProvider([Link] provider);


}

If the implementation of the service needs to load another SCA service, then the getService
method in the ServiceAccess class is used.

SCAIService spSvc;
spSvc = getService(“[Link]”, “”)

The delegation form of implementation


You use the delegate keyword in the SDL file to select the delegation form of implementation.
Currently the delegation form of implementation is not supported in Java.
Singleton Services
It is also possible to indicate that the service is a singleton in the SDL. The use of this keyword
has no affect on any of the Java implementation skeletons generated for a service. The
processing of singleton services is handled entirely in the factory support code that is
generated when the service is built. It is important to remember that even so the generated
skeletons are the same; the implementation code for a singleton service may need to be
different. Because multiple clients may be sharing the same instance of the service, the code
needs to make sure this is done in a safe manner.
Aggregation
The support for aggregation is requested with the aggregates and aggregated keywords in the
SDL. Currently aggregation is not supported in Java.
6.21. Mapping for SCA Components
The Java mapping uses a normal jar files for SCA components. The only code required for a
SCA component is support code generated by the IDL compiler during the build process. This
code is used by the SCA Framework to initialize the component and expose the services it
provides when the component is loaded at runtime. There is no code that the developer needs
to create for a component.
Embedded Components
Support for embedded components is requested with the embedded option in the CDL.
Currently embedded components are not supported in Java.
6.22. SCA Framework / JVM Interaction
Java Virtual Machine Initialization
The initialization of the Java virtual machine can be triggered in two different ways when
running SCA applications that use components written in Java.

If the SCA application is written in Java, then the application will normally be started
using the Java application launcher utility. In this case the application launcher is
responsible for initializing the JVM and the normal command line parameters and

2/21/2013 173
C++ Language Mappings

environment variables it supports are used to provide any user defined options for the
JVM.

If the SCA application is written in a language other than Java, then the JVM will be
initialized by the SCA Kernel when the first Java service is loaded. In this case, the SCA
Kernel JVMConfig configuration parameter is used to provide any user defined options
for the JVM.
The [Link] archive
When the scons build command is run to build the Java service, the IDL compiler will be run
on all the known IDL files to generate the required Java mappings. This includes all of the
IDL files in the APPS_SYSTEM and the APPS_LOCAL directories. The generated Java
files will be compiled and archived in a single jar archive, APPS_LOCAL/lib/java/
[Link]. This jar archive must be included in the class path for the JVM.

If the SCA application is written in Java, then the [Link] archive must be manually
added to the Java class path using either CLASSPATH environment variable or the
classpath or cp command line parameter for the Java application launcher utility.

If the SCA application is written in a language other than Java, then the SCA kernel will
initialize the JVM using the JVMConfig configuration variable. If no JVMConfig
variable is provided, then it will automatically provide one that includes an [Link]
archive which is located relative to the SCA resource directory which is specified with the
Resource configuration value.
JVMConfig=”-[Link]=Resource/../lib/java/[Link]”

If the SCA application is written in a language other than Java and the JVMConfig
configuration variable is provided, then the location of the [Link] archive must be
manually included in it.

For further details on setting the JVMConfig and other SCA configuration parameters please
refer to the SCA Kernel documentation.

2/21/2013 174
SCA Framework Template IDL to C++ Language Mapping

SCA Framework User Document

Chapter 7

IDL to .NET Language Binding

175
7. IDL to .NET Language Mapping
7.1. Introduction
The IDL language provides a language independent definition of SCA interfaces and data
types. In order to actually use these definitions, there must be a set of rules, commonly known
as a mapping that describes how these types are represented in a particular language. This
chapter explains the mapping that SCA uses for the .NET languages.

Since .NET has a unified type system, the SCA types can be used in any .NET language. The
following table summarizes the data type mapping between IDL, CLR, C# and Visual Basic
types. The following sections of this chapter will provide the details on each mapping.

IDL Type CLR Type C# Type VB Type


SCA::SCAInt8 SByte sbyte SByte
SCA::SCAUInt8 Byte byte Byte
SCA::SCAInt16 Int16 short Short
SCA::SCAUInt16 UInt16 ushort UShort
SCA::SCAInt32 Int32 int Integer
SCA::SCAUInt32 UInt32 uint UInteger
SCA::SCAInt64 Int64 long Long
SCA::SCAUInt64 UInt64 ulong ULong
SCA::SCAReal32 Single float Single
SCA::SCAReal64 Double double Double
SCA::SCAChar Char char Char
SCA::SCAUChar Char char Char
SCA::SCAString String string String
SCA::SCAUString String string String
SCA::SCABool Boolean bool Boolean
SCA::SCAAny [Link]
SCA::SCATypeCode [Link]
SCA::SCAResult [Link]
sequence class that inherits
from List
enum enum
struct struct
array [] or[][]
interface interface
exception class that inherits
from [Link]

See the HelloWorld Application chapter of this manual for examples on how SCA
applications can be written in different .NET languages. In that chapter both a C# and Visual
Basic version of the application is shown.

176
To reduce the amount of sample code, this chapter will only show examples in the C#
language.

For every type defined in IDL, the IDL compiler will generate the code required to expose the
proper CLR definition of the type. In addition to the actual CLR definition of the type, there is
also some support code generated for each interface which is used by SCA Framework to
make interface calls from .NET to services implemented in the other supported languages.
When building a .NET application or component, the SCA SCons build system will compile
the CLR definitions for all of the known IDL types and store them in a single assembly
APPS/WINNT/bin/[Link].

The SCA Kernel has transitioned from using wide strings to Unicode strings.
SCAWString will be supported for a limited time to allow applications to migrate to
Unicode strings and chars.

7.2. Mapping for Identifiers


IDL identifiers are mapped to CLR identifiers with no change. For example:

IDL
enum Color { RED, GREEN, BLUE };

C#
public enum Color { RED, GREEN, BLUE }

There is one potential problem to be aware of. If the IDL file contains an identifier that is also
a reserved keyword in the language you are using, then the code will not compile. Therefore,
the use of any of these reserved words for IDL identifiers is not allowed.
7.3. Mapping for Modules
SCA IDL namespaces are defined with the module keyword. These namespaces are mapped
directly to CLR namespaces.

IDL
module Test{

};

C#
namespace Test{

}

The IDL module constructs also affect other aspects of the SCA mapping. See the IDL
Compiler chapter for detailed information on how the IDL module statements are used.

177
7.4. Mapping for Basic Types
Basic data types, SCAInt8, SCAUInt8, SCAInt16, SCAUInt16, SCAInt32, SCAUInt32,
SCAInt64, SCAUInt64, SCAReal32, SCAReal64, SCAChar, SCAUChar and SCABool
are mapped to the corresponding Common Language Runtime (CLR) types. The SCAChar
is mapped to the CLR Char. This can cause issues because the CLR Char contains multi-byte
Unicode characters while the IDL definition of a SCAChar only accommodates the single-
byte ISO Latin-1 character set. When passing SCAChar data from .NET to a different
language, the high byte will be discarded.

The following table shows the CLR, C# and Visual Basic mappings for the basic SCA types.

IDL Type CLR Type C# Type VB Type


SCA::SCAInt8 SByte sbyte SByte
SCA::SCAUInt8 Byte byte Byte
SCA::SCAInt16 Int16 short Short
SCA::SCAUInt16 UInt16 ushort UShort
SCA::SCAInt32 Int32 int Integer
SCA::SCAUInt32 UInt32 uint UInteger
SCA::SCAInt64 Int64 long Long
SCA::SCAUInt64 UInt64 ulong ULong
SCA::SCAReal32 Single float Single
SCA::SCAReal64 Double double Double
SCA::SCAChar Char char Char
SCA::SCAUChar Char char Char
SCA::SCABool Boolean bool Boolean

The following structure definition illustrates this mapping.

IDL:
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

C#:
public struct Node
{
public int id;
public float x;
public float y;
public float z;
}

178
7.5. Mapping for String Types
Both SCAString and SCAUString are mapped to [Link]. Converting from a
SCAString or SCAUString to a CLR value will not lose any information. When converting
from a CLR value to a SCAString, the CLR value is first converted to an ANSI value which
is then stored in the SCAString.

IDL:
struct address
{
SCAString street;
SCAString city;
SCAInt32 zipcode;
};

C#:
public class address
{
public String street;
public String city;
public int zipcode;
}

7.6. Mapping for Enumerated Types


An IDL enum is mapped directly to a CLR enum.

IDL
enum Colors {
RED, GREEN, BLUE
};

C#
public enum Colors
{
RED, GREEN, BLUE
}

7.7. Mapping for Structures


An IDL structure maps to a CLR struct with all public fields. Each IDL structure member is
mapped to a corresponding member of the CLR structure. The CLR structure members appear
in the same order as the corresponding IDL structure members. For example:

IDL
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

179
C#
public struct Node
{
public int id;
public float x;
public float y;
public float z;
}

7.8. Mapping for Arrays


Two types of array definitions are supported in IDL. Fixed size arrays must have their size
defined in the IDL and can never change. Dynamic arrays allow you to delay the specification
of the array size until it is actually allocated. Only arrays of rank 1 or 2 are supported.
Fixed size arrays
There is no special code generated for the mapping of IDL defined arrays. Normal CLR arrays
should be used for these types. When arrays are allocated you need to make sure that the
correct length is specified. The array sizes are not checked when making interface calls
between .NET languages, but if making a call to another language through a SCA bridge the
sizes are checked and a SCASystemException will be thrown if incorrect.

IDL
typedef SCAInt32 Date[3];

C#
int[] date = new int[3];

Two dimension arrays use the CLR jagged array format.

IDL
typedef SCAInt32 Matrix[3][3];

C#
int[][] matrix = {
new int[] {1,3,5},
new int[] {0,2,4},
new int[] {11,22,22}
};

If an IDL array is defined in a structure, it is also mapped directly to a CLR array.

IDL
struct Node2
{
SCAInt32 id;
SCAReal32 location[3];
};

C#
public struct Node2

180
{
public int id;
public float[] location
}
Dynamic Arrays
Dynamic Arrays also use normal CLR arrays types. Since the size of a dynamic array is not
fixed in the IDL, you can use any appropriate size when you allocate the CLR array type.
Dynamic arrays exist primarily to provide more optimized code in other languages supported
by the SCA framework.
7.9. Mapping for Sequences
An IDL sequence is mapped to a class that inherits from [Link].

IDL
typedef SCASequence<SCA::SCAInt32> NodeSequence;

C#
public class NodeSequence : List<[Link]>{
public NodeSequence() { }
public NodeSequence(int initialCapacity): base(initialCapacity) { }
public override string ToString() {
string s="[";
foreach([Link] i in this){
s+=[Link]()+" ";
}
s+="]";
return s;
}
}

When an IDL sequence appears as a member of a structure, it is mapped directly to a


[Link] type as the member of the structure.

IDL
struct Node3{
SCAInt32 id;
SCASequence<SCAReal32> location;
};

C#
public struct Node3{
int id;
public List<float> location;
}

Since generated sequence classes inherit from List they are used the same way as any List
object.

// Initialize contents of the sequence


SCAReal64Sequence seq = new SCAReal64Sequence();

181
[Link](1.0);
[Link](2.0);
[Link](3.0);

//Print contents of the sequence


foreach (double val in seq)
[Link](val);

7.10. Mapping for Vectors

Just like Sequence an IDL vector is mapped to a class that inherits from
[Link].

7.11. Mapping for Maps


An IDL map is mapped to a class that inherits from
[Link].

IDL

typedef map<SCAString, SCAReal64> MapStringReal64;

C#
public class MapStringReal64 : Dictionary<string, double> {
public MapStringReal64(): base(){}
public MapStringReal64(int initialCapacity): base(initialCapacity){ }

public override string ToString()


{
string s="[";
foreach (KeyValuePair<string, double> dataEntry in this)
{
s+=[Link]("({0},{1})",[Link],[Link])+ ",";
}
if ( [Link](",") )
return [Link]([Link]-1) + "]";
else
return s + "]";
}
}

The following example shows how to create, initialize and print a map.

// Initialize contents of the map


MapStringReal64 realMap = new MapStringReal64();
[Link]("first value", 65.74);
[Link]("second value", 5.75);
[Link]("third value", 4.6);
[Link]("fourth value", 78.7);

182
// Print contents of the map
[Link]([Link]());

7.12. Mapping for Type Aliases


A typedef is used in SCA IDL to define a sequence, an array or an alias for an existing type.
The CLR mapping for sequences and arrays has already been discussed in the previous
sections.

The use of the IDL typedef to create a new name for an existing type must be handled
differently in .NET because not all of the different languages provide a similar capability.
Therefore, IDL typedef definitions are first unwound to either the SCA basic type or the user
defined IDL type that it refers to and then the unwound type is used as the CLR type. As a
result, the name of the IDL typedef type will never appear in the generated code.

The following examples show how IDL typedef definitions that refer to both SCA basic types
and other IDL defined types are unwound.

IDL
typedef SCAInt32 HourValue;
typedef SCAInt32 MinuteValue;
typedef SCAInt32 SecondValue;

struct TimeDef
{
HourValue hour;
MinuteValue minute;
SecondValue second;
};

typedef TimeDef LocalTime;


typedef TimeDef GMTTime;

interface SCAITimeConvert
{
LocalTime convert(in GMTTime time);
};

C#
public struct TimeDef
{
public int hour;
public int minute;
public int second;
}

public interface SCAITimeConvert : [Link]


{
TimeDef convert(TimeDef time);
}

183
Notice how the HourValue, MinuteValue, SecondValue, LocalTime and GMTTime alias
types have been unwound and the SCA basic types or IDL defined types have been used
instead.
7.13. Mapping for SCATypeCode
The SCATypeCode type is a special type used by the SCA Framework to describe the details
about each IDL defined type. The SCA Framework creates instances of the SCATypeCode
using XML data generated by the IDL compiler. Each instance of the SCATypeCode
contains the complete description of one IDL defined type. For example, the description of a
structure would include the name and type for each of its members.

The SCATypeCode type is treated in IDL as a basic type and it can appear anywhere in the
IDL where a basic type can appear. For example it could be the member of a structure or one
of the arguments in an interface method.

In .NET a type code value is represented by the SCATypeCode class. The definition of a
SCATypeCode contains a pair of values. These include a SCATypeCodeID value that
indicates the type of data and a description of the type. The contents of the description depend
on the value of the SCATypeCodeID. The SCATypeCode class is fairly complex and will
not be discussed in detail here. The data contained in this class is mostly used internally within
the SCA Framework. If you need to access these detailed type definitions you are encouraged
to use the [Link] service that is describe in detail in the Dynamic SCA
chapter of this manual.
7.14. Mapping for SCAAny
The SCAAny is a container data type which can hold a single value of any other arbitrary IDL
data type. Only values for types that are defined in IDL can be stored in a SCAAny. This is
because the SCAAny design requires a SCATypeCode value to describe the data it holds and
these are only generated by the IDL compiler and will not exist for types that are not defined
in IDL.

The .NET mapping for the IDL type SCAAny fulfills two important requirements:

It must handle the CLR types in a type-safe manner.


It must handle values for complex types that are not known at compile time.

The first requirement covers the typical usage of the SCAAny type, the insertion of typed
values into the SCAAny and the type-safe extraction of the values. In .NET the type-safety is
ensured by the SCAAny class and the CLR. When you try to insert a value into a SCAAny,
the class will make sure that the data being inserted is an IDL defined type and consistent with
the SCA type description. If it is not, then a SCASystemException will be thrown. When you
try to extract a value from the SCAAny, the CLR will attempt to cast it to the type you
requested. If the value can be converted then the extraction will succeed. If it cannot be
converted then a CLR Exception will be thrown.

184
The second requirement covers situations like the need to extract data from the SCAAny
when you do not know the type of data it contains. In this case the receiver must be able to
determine information about what type of data the SCAAny contains. To achieve this,
SCAAny contains a pair of values that includes the actual value of the data and a description
of its type. The type information can then be inspected to determine the details on the value
stored in the SCAAny instance.
The SCAAny class definition
In .NET the SCAAny type is implemented by the [Link] class. The public methods
for the class are shown below.

namespace SCA {
public class SCAAny
{
// Constructors
public SCAAny();
public SCAAny(Object data);
public SCAAny(Object data, String typeName);

// Methods for inserting and extracting values


public void setSCAInt8(sbyte data);
public sbyte getSCAInt8();
public void setSCAUInt8(byte data);
public byte getSCAUInt8();
public void setSCAInt16(short data);
public short getSCAInt16();
public void setSCAUInt16(ushort data);
public ushort getSCAUInt16();
public void setSCAInt32(int data);
public int getSCAInt32();
public void setSCAUInt32(uint data);
public uint getSCAUInt32();
public void setSCAInt64(long data);
public long getSCAInt64();
public void setSCAUInt64(ulong data);
public ulong getSCAUInt64();
public void setSCAReal32(float data);
public float getSCAReal32();
public void setSCAReal64(double data);
public double getSCAReal64();
public void setSCAChar(char data);
public char getSCAChar();
public void setSCAString(String data);
public String getSCAString();
public void setSCAUChar(char data);
public char getSCAUChar();
public void setSCAUString(String data);
public String getSCAUString();
public void setSCABool(bool data);
public bool getSCABool();
public void setSCAAny(SCAAny data);
public SCAAny getSCAAny();
public void setSCATypeCode(SCATypeCode data);
public SCATypeCode getSCATypeCode();

185
public void setSCAResult(SCAResult data);
public SCAResult getSCAResult();
public void setSCAObject(Object data);
public void setSCAObject(Object data, String typeName);
public Object getSCAObject();

// Flush the contents


public void flush();

// Methods for getting information about the contents


public String type();
public bool empty();
public override String ToString();

// Data
private Object m_data;
private String m_type;

}
}

Examples of using the SCAAny are show in the following sections.


Creating new SCAAny values
The following example creates an empty SCAAny value.

// Create an empty SCAAny instance


[Link] any = new [Link]();

To create a new SCAAny value that contains a value you can use the constructor which takes
a CLR Object and an optional string description of the type. Which form you use depends on
the way the SCA type is mapped in .NET. If the SCA type uniquely maps to a CLR type,
then you only need to provide the object in the constructor. Types like sequences, structures,
enumerations, interfaces and all basic types except characters and strings fall into this
category. The following shows several examples of this.

// Create a SCAAny instance which contains a structure value


Node node = new Node();
[Link] = 123;
node.x = 1.0;
node.y = 2.0;
node.z = 3.0;
[Link] any = new [Link](node);

// Create a SCAAny instance which contains a SCAInt64 value


[Link] any2 = new [Link]((long)123);

But, if the SCA type maps to a native CLR type that cannot be uniquely associated to a SCA
type then you will need to add the type description to explicitly specify the type. An example
of this is a CLR String value which can be mapped to either a SCAString or a SCAUString
value. If the type description is not specified when required a SCASystemException will be
thrown.

186
// Create a SCAAny instance which contains a SCAString value
[Link] any = new [Link](new String(“test”),”[Link]”);

Inserting values into existing SCAAny value


You can also insert a value into an existing SCAAny instance. If the instance already holds a
value it will be replaced with the new value. Remember that the SCAAny can only hold a
single value at a time.

Inserting values into an existing SCAAny instance follows a similar pattern that was
described previously for constructing new SCAAny values with one exception. Since the
insertion of basic types into a SCAAny is so common, a special group of set methods is
provided. There is a separate set method defined for each basic SCA type. These methods
allow you to easily insert primitive values directly into the SCAAny without having to specify
the SCA type names or do any casts to remove ambiguities.

// Insert an SCAInt32 value to SCAAny instance


anyval.setSCAInt32(12);

// Insert a SCAString value into a SCAAny instance


[Link](“value”);

Non-basic types are inserted using the setSCAObject method. Here is an example of inserting
a sequence into a SCAAny.

// Insert an SCAReal64Sequence value to SCAAny instance


SCAReal64Sequence seq = new SCAReal64Sequence ();
[Link](1.0);
[Link](2.0);
[Link](seq);

As before, since a SCA sequence has a unique mapping to a CLR class, you do not need to
add the type description. But if the mapping is not unique you will need to.

// Insert a SCAString value into a SCAAny instance


[Link](new String(“value”),”[Link]”);

A SCAAny can even hold another SCAAny instance.

// Insert an SCAAny value to SCAAny instance


SCAAny anyval2 = new SCAAny((long)123,"SCA.SCAInt64");
[Link](anyval2);

Extracting the value contained in a SCAAny


To extract a value from the SCAAny, you use the get method that corresponds to the data
contained in it. When extracting values, it is important that you pick the correct method
otherwise the CLR will throw a SystemException exception.

// Extract the value from an the SCAAny instance

187
try {
int int32val = anyval.getSCAInt32();
} catch (Exception ex) {
[Link]("Exception:" + ex);
}

For non-basic types, you will need to use the getSCAObject method to extract the value. This
value must be cast to the desired CLR type as shown in this example.

// Extract a Node structure value from a SCAAny instance


try {
Node node = (Node)[Link]();
[Link]("Extracted value: id=" + [Link] +
" x=" + node.x +
" y=" + node.y +
" z=" + node.z);
} catch (Exception ex) {
[Link]("Exception:" + ex);
}

There may be cases where the SCAAny value may hold a number of different types and you
do not know at compilation time which one it is. In this case you can use the type method to
determine what type it contains so you can choose the correct get method. The following
example shows how several extractions can be used to handle different possible types of
values that may be in the SCAAny instance.

// Extract an unknown type from a SCAAny instance


int int32val;
float real32val;
if ( [Link]() == "SCA.SCAInt32" ) {
int32val = anyval.getSCAInt32();
[Link]("int32val = " + int32val);
} else if ( [Link]() == "SCA.SCAReal32" ) {
real32val = anyval.getSCAReal32();
[Link]("real32val = " + real32val);
} else {
[Link]("Unsupported type " + [Link]());
}
Miscellaneous SCAAny methods
The SCAAny provides several miscellaneous methods that can be used to check if the
SCAAny contains any data or to flush its contents.

// Check if SCAAny is empty


If ( [Link]() ){
// SCAAny value is empty
}
// Flush the contents of the SCAAny which will now be empty
[Link]();

The SCAAny also implements the ToString method which allows you to get a string
representation of its contents.

188
// Print the information about the contents of the SCAAny
[Link]("SCAAny value is " + [Link]());

7.15. Mapping for SCAResult


The SCAResult type is used to return error information from calls to interface methods. It
contains the following information.

Error code
Message table ID
Message number
Message parameters

The values in a SCAResult instance can be used by the SCA Framework to format and
dispatch messages in the language appropriate for the current user. For more information on
using SCAResult for error processing see the Error Handling chapter of this manual.
SCAResult class definition
The SCAResult type is mapped to the following class:

namespace SCA {
public class SCAResult
{
// Constructors
public SCAResult();
public SCAResult(int errorCode);
public SCAResult( int errorCode, int msgTableId, int messageID;

// Setting values
public void setErrorCode( int errorCode );

// Return values
public int getErrorCode();
public int getTableID();
public int getMessageID();

// Add a parameter
public void addSCAInt8(sbyte t);
public void addSCAUInt8(byte t);
public void addSCAInt16(short t);
public void addSCAUInt16(ushort t);
public void addSCAInt32(int t);
public void addSCAUInt32(uint t);
public void addSCAInt64(long t);
public void addSCAUInt64(ulong t);
public void addSCAReal32(float t);
public void addSCAReal64(double t);
public void addSCAChar(char t);
public void addSCAUChar(char t);
public void addSCAString(string t);
public void addSCAUString(string t);
public void addSCABool(bool t);

189
// Compare all fields of SCAResult data, excluding parameters
public bool equals (SCAResult sr);

// Return the parameters


public SCAAnySequence getParams();

// Return true if has parameters, return false otherwise


public bool hasParams();

// Return true if the error code ==0


public bool isOk();

// Returns true if it is a system error


public bool isSystemError();

// Print raw contents of SCAResult


public void dump();

// Returns a formatted message


public override string ToString();

// Log SCAResult and/or call stack traceback.


public SCAResult log();
public SCAResult log(bool logTraceback);
public SCAResult log(bool logTraceback, int numFrames2Skip);

// Wrapping methods to access inner SCAResult object.


public void setInnerSCAResult(SCAResult result );
public SCAResult getInnerSCAResult();

// Apply error policy to SCAResult.


public SCAResult applyErrorPolicy();
public SCAResult applyErrorPolicy(string policyName);

// Predefined SCAResult values


public static SCAResult SCASuccess = new SCAResult(0);
public static SCAResult SCAError = new SCAResult(0X7FFFFFFF);
}
}

Two predefined SCAResult values are provided when you do not need to include more
detailed information to the callers.

// Return error
return [Link];
// Return success
return [Link];

Examples of the usages of these are shown in the following sections.


Creating new SCAResult values
The following example creates SCAResult values with different levels of initialization.

190
// Create SCAResult with all zero values
[Link] rstat = new [Link]();

// Create SCAResult with only an error value


[Link] rstat = new [Link](1);

// Create SCAResult with error, tableID and messageID


[Link] rstat = new [Link](1,4,301);}
Resetting the error code in a SCAResult value
The error code in an existing SCAResult value can be reset as follows.

// Reset error code in SCAResult


[Link](201);
Adding parameters to a SCAResult value
You use one of the add methods to add a parameter to a SCAResult value.

// Add parameters to SCAResult value


rstat.addSCAInt8((sbyte)1);
rstat.addSCAInt16((short)12);
rstat.addSCAInt32((int)123);
rstat.addSCAInt64((long)1234);
rstat.addSCAUInt8((byte)2);
rstat.addSCAUInt16((ushort)23);
rstat.addSCAUInt32((uint)234);
rstat.addSCAUInt64((ulong)2345);
rstat.addSCAReal32(12.34F);
rstat.addSCAReal64(123.456);
[Link]('A');
[Link]("TestString");
[Link]("TestUnicodeString");
[Link](true);
Interrogating the contents of a SCAResult
The isOk method provides a simple way to test if the SCAResult value has an error.

// Test if SCAResult has a non-zero error


if ( ![Link]() )
// Process error

The get methods can be used to extract the error, table and message values.

// Extract the error, tableID and messageID values


int error = [Link]();
int tableid = [Link]();
int messageid = [Link]();

The hasParams and getParams methods can be used to determine if the SCAResult has
parameters and to process them. The parameter values are returned in a SCAAnySequence.

// If the SCAResult has parameters, print them

191
if ( [Link]() ) {
for ( int i=0; i<[Link](); i++ ) {
[Link] param = [Link](i);
[Link]("Param " + i + " = " + [Link]());
}
}

Format a SCAResult Value


The ToString methods can be used to format a SCAResult value to a string.

[Link]("Error: "+[Link]());

SCAResult Logging
The log methods can be used to manually log the SCAResult error message using the
logger service. The inner wrapped objects are also logged recursively. See the ‘Logger
Service’ chapter of this manual for details on the Logger Service. If the logTraceback
parameter is true, the call stack traceback is also logged.
// Log SCAResult only
[Link]();

// Log SCAResult and traceback. By default skip 4 traceback frames


[Link](true);

// Log SCAResult and traceback. Skip 2 traceback frames.


[Link](true, 2);

Setting Inner SCAResult


A SCAResult value may also wrap an inner SCAResult value. This can be used when you
want to change the error value to something more appropriate for the current method but do
not want to lose the original error information. The wrapping may be recursive to any desired
level. The following shows an example of setting an inner SCAResult value.

int errorCode = [Link].MSG_ERROR_UNKNOWN_SIGNAL.value;


[Link] outerSCAResult = new [Link](errorCode,
m_msgTableId,
errorCode);
outerSCAResult.addSCAInt32(256);
errorCode = [Link].MSG_SERVICE_COMP_NOT_FOUND.value;
[Link] innerSCAResult = new [Link](errorCode,
m_msgTableId,
errorCode);
[Link]("[Link]");
[Link](innerSCAResult);
Apply Error Policy to SCAResult
An Error Policy defines a set of associated actions (such as Log, Replace, Traceback,
Terminate and Minidump), to be taken when handling the errors. The policies are
specified in the table [Link], which is installed as part of the
Kernel in the Resource directory. See the “Error Handling” chapter for more details.

192
// Apply error policy to SCAResult.
[Link]("SCAResult");

Miscellaneous SCAResult methods


The SCAResult also implements the ToString and dump method which allows you to get or
print the contents. The ToString method will attempt to format a message for the SCAResult
value while the dump method just prints the raw data.

// Print a string representation of the SCAAny


[Link]("SCAResult value is " + [Link]());

// Print contents using the dump method


[Link]();

7.16. Mapping for Constants


IDL defined constants are mapped to a struct of the same name as the constant which contains
a single fixed data value with the name value which has the value of the IDL constant.

IDL
const SCAInt32 NUM_OF_STATES = 50;

C#
public struct NUM_OF_STATES {
public const int value = (int)50;
}

The value of the constant can be referenced using the value field.

// Print value of constant defined in IDL


[Link]("constant value = " + NUM_OF_STATES.value);

7.17. Mapping for Interfaces


SCA interfaces are mapped directly to CLR interfaces.

The following is a simple interface definition. This example is missing the definitions of all
the required types but they have no affect on actual interface mapping so they have been left
out to simplify the example.

IDL
interface SCAIReader : SCA::SCAIService
{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
SCAINode getNode( in SCAInt32 id ) raises(ReaderException);
SCAVoid getNodeCoordinates( in SCAInt32 id,
out SCAReal32 x,
out SCAReal32 y,
out SCAReal32 z )
raises(ReaderException);

193
};

C#
public interface SCAIReader : [Link]
{
void readModel(string name);
SCAINode getNode(int id);
void getNodeCoordinates(int id,
out float x,
out float y,
out float z);
}
Mapping for Interface Operations
Each interface operation (or method) is mapped to a method in the CLR interface with the
same name.
Mapping for Interface Parameters
Each parameter in an IDL operation must have a direction of in, out or inout. They are
mapped to C# and Visual Basic according to the following table.

IDL direction CLR attribute C# keyword VB keyword


in In ByVal
out Out out ByRef
inout In+Out ref ByRef

7.18. Mapping for Exceptions


The SCA Framework predefines three exception types, [Link],
[Link] and [Link]. All user defined exceptions in
IDL must inherit either SCA::SCAUserException or another user-defined exception. Only
single inheritance is allowed
SCAException interface
The base for all IDL defined exceptions is SCAException which is mapped to the
[Link] class.

namespace SCA{
public class SCAException: [Link] {

// Constructor
public SCAException(){…}

// Apply error policy to the Exception.


public SCAResult applyErrorPolicy(){…}

// Apply error policy to this exception.


public SCAResult applyErrorPolicy(string policyName) {…}

// Throw the exception after applying “SCAException” error policy


public void throwit(){…}

194
// Throw the exception after applying the given policy
public void throwit(string policyName) {…}

// Log SCAException and/or call stack traceback


public SCAResult log(){…}
public SCAResult log(bool logTraceback) {…}
public SCAResult log(bool logTraceback, int numFrames2Skip) {…}

// Returns a formatted message


public override string ToString{…}

// Wrapping methods to access inner SCAException object.


public void setInnerSCAException(SCAException ex) {…}
public SCAException getInnerSCAException(){…}

// return a string to explain what message the exception carries


public string what(){…}

//Method to get SCATypeCode for this exception


public SCATypeCode getTypeCode(){…}

//Method to get raw text string for this exception


public string getText(){…}

//Method to set raw text string for this exception


public void setText(string text){…}
}
}

SCAUserException class
The SCAUserException exception adds no new data to SCAException and should be used
as the base for all user defined exceptions. It is mapped to the [Link] class
which inherits from the [Link] class.

namespace SCA {
public class SCAUserException: SCAException
{
public SCAUserException(){…}
public SCAUserException(string text){…}
}
}

SCASystemException class
The SCASystemException exception should only be used internally by the SCA Framework
and adds an error ID member to SCAException. It is mapped to the
[Link] class which inherits from the [Link] class.

namespace SCA {
public class SCASystemException: SCAException{
//Constructors
public SCASystemException() {…}

195
public SCASystemException(int iid) {…}
public SCASystemException(int iid, string text) {…}
public int id;
}
}
Mapping for IDL defined user exceptions
User-defined exceptions are mapped to respective classes. All the user defined members in an
exception are mapped as public fields in the exception class.

IDL
exception ReaderException : SCAUserException
{
SCAString name;
SCAString error;
};

C#
public class MyException : [Link]{
public MyException();
public string name;
public string error;
}

The following code shows an example of how you throw a SCA exception in C#.

ReaderException ex = new ReaderException();


[Link] = “[Link]”;
[Link] = “The file does not exist”;
throw ex;

And the exception can be caught as follows.

try
{
// Code that triggers an exception
}
catch (ReaderException ex)
{
[Link]("ReaderException Caught for”);
[Link](“File: “ + [Link]);
[Link](“Error: “ + [Link]);
}

The IDL raises clause


An IDL interface operation may contain a raises clause to indicate what kind of exceptions the
operation may throw.

IDL
interface SCAIReader : SCAIService
{

196
SCAVoid readModel( in SCAString name ) raises (ReaderException);
};

C#
interface TestInterface{
public void testEx();
}

Since the CLR does not support checked exceptions, the presence of a raises clause in the IDL
has no affect on any of the generated code. But, when implementing components in .NET it is
still important that the IDL definition of the interfaces that they implement contain the
appropriate raises clauses. This is because the various SCA language bridges do check the
exceptions thrown and will only pass those that have been specified. If an exception is thrown
that is not specified in the raises clause, it will be converted to a SCASystemException.

The SCASystemException exception is an unchecked exception that can always be thrown.


Users do not need to include SCASystemException or SCAException in the raises clause.
7.19. Mapping for SCA Services
Two types of code are generated for SCA service definitions.

The genskeleton command is used to generate the initial implementation skeleton for a
service. The generated skeleton can then be expanded with the code required to implement
the desired behavior for the various interface operations.

During the build process, various base or tie classes are generated which are used to link
the developer generated implementation code to the SCA Framework. This is done to
reduce as much as possible the amount of code that must be written by the developer to
implement a service. These classes also provide a level of isolation between the service’s
implementation code and the SCA Framework. This allows for future changes to be made
in the interaction between the base or tie classes and the SCA Framework without
affecting the developer’s implementation code.

The following is the IDL file for an example interface definition that will be used in this
section.

#ifndef SCA_FILEREADER_FILEREADER_IDL_INCLUDED
#define SCA_FILEREADER_FILEREADER_IDL_INCLUDED

#include "SCA/[Link]"

module SCA { module FileReader {

struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

197
exception ReaderException : SCAUserException
{
SCAString name;
SCAString error;
};

interface SCAINode;

interface SCAIReader : SCA::SCAIService


{
SCAVoid readModel( in SCAString name ) raises(ReaderException);
SCAINode getNode( in SCAInt32 id ) raises(ReaderException);
};

interface SCAINode : SCA::SCAIService


{
SCAInt32 getID();
SCAReal32 getX();
SCAReal32 getY();
SCAReal32 getZ();
};

}; };
#endif

The following is the SDL for an example service that will implement these interfaces.

#ifndef FILEREADER_SDL_INCLUDED
#define FILEREADER_SDL_INCLUDED

#include "SCA/FileReader/[Link]"

module SCA { module FileReader { module Impl {

service [Link] {
interface SCA::FileReader::SCAIReader;
subservice NodeImpl ( in SCA::FileReader::Node node ) {
interface SCA::FileReader::SCAINode;
};
};

}; }; };
#endif

The inheritance form of implementation


In the inheritance form of implementation, the implementation classes generated by
genskeleton will inherit from base classes generated by the IDL compiler at build time. These
base classes will then inherit from the interface classes and also provide all the necessary links
to the SCA Framework.

When the genskeleton command is run for the above SDL file to generate the skeleton code
for the service, it will generate two classes, FileReader which inherits from the SCAIReader

198
interface and FileReader_base and NodeImpl which inherits from the SCAINode interface
and NodeImpl_base.

The implementation will be put in a namespace that is defined by the SDL module statements.
In this example its namespace is [Link].

The following is the file [Link] that is generated for the top-level service class.

using [Link];

namespace SCA { namespace FileReader { namespace Impl {

public class FileReader: FileReader_base , [Link]


{
// Constructor
public FileReader ([Link] provider)
{
setServiceProvider(provider);
}

// Methods for interface [Link]


void [Link] (string name)
{
//implementation goes here
}

[Link] [Link] (int id)


{
//implementation goes here
}
}

} } }

The implementation classes generated are fairly simple, but there are a couple of requirements
for these imposed by the SCA Framework. These are the requirements when using the default
or inheritance form of implementation.

The class must inherit from the base class generated by the IDL compiler.
The class can have only one constructor and it must have a single argument of
SCAIServiceProvider type. This argument is used by the base class to access the
SCA Framework.
The class must implement each of the operations defined in the interfaces it supports
except for SCAIService.

As long as these requirements are met, the developer is free to make any desired modifications
to these implementation classes.

The base class FileReader_base, which will be generated by the IDL compiler when it is run
during the build process, provides the following.

199
Inherits from the respective interface for each interface implemented by the service
class. In this example it will be the SCAIReader interface.
Provides the implementation for all of the required reference counting, interface
navigation and introspection methods in the SCAIService interface that every SCA
service class must implement.
Provides access to the SCA Framework facilities.

If the FileReader service used in this example implemented additional interfaces, the only
changes to the generated code would be the addition of the method definitions for the
operations in the new interfaces.
Implementation for subservice classes
The SDL for the FileReader service also includes the definition of a subservice NodeImpl
which takes a Node constructor argument. A separate class, NodeImpl, will be generated for
the subservice class. The format of this class is identical to the FileReader class except for the
addition of an extra argument on the class constructor and the interface methods it
implements.

Following is the [Link] class generated by the genskeleton command

using [Link];

namespace SCA { namespace FileReader { namespace Impl {

public class NodeImpl: NodeImpl_base , [Link]


{
// Constructor
public NodeImpl ([Link] provider,
[Link] node)
{
setServiceProvider(provider);
}

// Methods for interface [Link]


public int [Link] ()
{
//implementation goes here
}
public float [Link] ()
{
//implementation goes here
}
public float [Link] ()
{
//implementation goes here
}
public float [Link] ()
{
//implementation goes here
}
}
} } }

200
Only subservice classes can have user specified constructor arguments. This is because
instances of the top-level FileReader class are instantiated by the IDL generated factory class
in response to getService calls made by the clients of the service. There is currently no way for
clients to pass constructor arguments through the getService call. On the other hand, instances
of subservice classes can only be created by the implementation code in the service. In this
case the implementation is free to pass any desired arguments to the constructors.
Creating instances of subservice classes
Instances of subservice classes can only be created by the implementation code in the service.
The following is an example implementation for the getNode method of the SCAIReader
interface which returns an instance of the SCAINode interface. The SDL definition for this
service specifies that the SCAINode interface is implemented by the NodeImpl subservice
class. That means that the getNode method needs to allocate an instance of the NodeImpl
class and return the SCAINode interface on it. The constructor for the NodeImpl class,
generated by the genskeleton utility, requires two parameters. The first parameter is the
SCAIServiceProvider interface which is available in the m_provider variable in the base
class. The second argument is an instance of the Node structure that was specified as a
constructor argument in the SDL.

SCAINode FileReader::getNode(const SCAInt32 id)


{
// Find and initialize the node which cooresponds to ID
Node node = …

// Return a new subservice class instance for this node


NodeImpl spNode = new NodeImpl(m_provider,node);
return (SCAINode)spNode;
}

The ServiceAccess interface


The base classes generated by the IDL compiler will always implement the
[Link] interface. This interface is the link between the implementation of the
service and the SCA Framework. The following is the definition of the ServiceAccess
interface:

namespace SCA{
public interface ServiceAccess {
SCAIService getService(string name, string attr) ;
void setServiceProvider(SCAIServiceProvider provider);
[Link] getServiceProvider();
}
}

If the implementation of the service needs to load another SCA service, then the getService
method in the ServiceAccess class is used.
SCAIService spSvc;
spSvc = getService(“[Link]”, “”)

201
The delegation form of implementation
There may be situations where the inheritance form of implementation is inconvenient
because of other requirements in your classes. An example is if you want to inherit the
implementation class from your own base class. This is not possible with the inheritance form
of implementation because the CLR does not allow multiple inheritance and the
implementation class must inherit from the base class generated by the IDL compiler. To
resolve this, the delegation form of implementation can be used. With delegation, the skeleton
classes generated by the IDL compiler do not inherit from a base or interface classes. Instead
the base class is replaced with a separate tie class which inherits from the interface class and
provides all the necessary links to the SCA Framework. When a new instance of the service is
requested, an instance of the tie class is constructed and returned. The tie class will internally
construct a separate instance of the implementation class when it is initialized. Interface calls
to the methods in the tie class are then delegated to the methods in the implementation class
that it wraps.

You use the delegate keyword in the SDL file to select the delegation form of implementation.
The following is the [Link] class that is generated for the top-level service class when
delegation is used. The lines in a darker shade of gray are the lines that are different from the
format of this file when the inheritance form of implementation is used.

using [Link];

namespace SCA { namespace FileReader { namespace Impl {

public class FileReader


{
// Constructor
public FileReader (FileReader_tie tie)
{
m_tie = tie;
}

// Methods for interface [Link]


public void readModel (string name)
{
//implementation goes here
}

public [Link] getNode (int id)


{
//implementation goes here
}

protected FileReader_tie m_tie;


}
} } }

Notice that class no longer inherits from a base class and as a result the interface methods
names are not longer in the scope of the interface. Because there is no requirement that the
implementation inherit from an IDL generated base class, you are fee to use any inheritance

202
structure you required. The class also saves a reference to the tie class which is required to
access the ServiceAccess interface that it implements.

Since a subservice was also defined in the SDL file, NodeImpl is also created as a delegated
subservice. A separate tie class named NodeImp_tie is created for the subservice which
creates an instance of the NodeImpl generated by the genskeleton command. Therefore, when
creating an instance of the subservice, the user will have to create an instance of the tie class.
The following illustrates how the getNode method would be implemented when delegation is
used.

public [Link] getNode (int id)


{
// Find and initialize the node which cooresponds to ID
Node node = …

// Return a new subservice class instance for this node


NodeImpl_tie spNode = new NodeImpl_tie(m_tie.getServiceProvider(),
node)
return (SCAINode)spNode;
}

Singleton Services
It is also possible to indicate that the service is a singleton in the SDL. The use of this keyword
has no affect on any of the implementation skeletons generated for a service. The processing
of singleton services is handled entirely in the factory support code that is generated when the
service is built. It is important to remember that even so the generated skeletons are the same;
the implementation code for a singleton service may need to be different. Because multiple
clients may be sharing the same instance of the service, the code needs to make sure this is
done in a safe manner.
Aggregation
The .NET mapping also supports the aggregates and aggregated keywords in the SDL. The
affect of these on the mapping for service objects is an advanced topic that is covered in a
separate manual.
7.20. Mapping for SCA Components
The .NET mapping uses normal assemblies for SCA components. The only code required for
a SCA component is support code generated by the IDL compiler during the build process.
This code is used by the SCA Framework to initialize the component and expose the services
it provides when the component is loaded at runtime. There is no code that the developer
needs to create for a component.
Embedded Components
Support for embedded components is requested with the embedded option in the CDL.
Currently embedded components are not supported in .NET.

203
SCA Framework Template IDL to .NET Language Mapping

SCA Framework User Document

Chapter 8

IDL to Python Scripting

204
SCA Framework Template IDL to Python Language Mapping

8. IDL to Python Language Mapping


8.1. Introduction
Python scripting in the SCA Framework allows a SCA enabled application to execute one or
more Python scripts at runtime. Users can also access SCA services from the Python
command line. In both cases, the Python scripts can load SCA services and invoke their
methods. SCA interfaces can also be implemented in Python scripts.

Python is a type-less language which means that you do not declare variables to be of a
specific type. Instead, any Python variable can assume any type at runtime. In addition to this,
the SCA mappings of types in many cases directly use native Python types. As a result many
of the type names defined in IDL never appear in Python. Instead you just use the native
Python types as appropriate. But because Python does no type checking, you have to be
careful when calling a SCA interface to make sure the arguments are Python objects of the
correct type. If you try to pass a Python object to a SCA interface that cannot be converted to
the required SCA type, then the SCA language bridge will throw a SCASystemException
exception.

The following table summarizes the data type mappings between IDL and Python types. The
following sections of this chapter will provided the details on each mapping.

IDL Type Python Type


SCA::SCAInt8 plain integer
SCA::SCAUInt8 plain integer
SCA::SCAInt16 plain integer
SCA::SCAUInt16 plain integer
SCA::SCAInt32 plain integer
SCA::SCAUInt32 long integer
SCA::SCAInt64 long integer
SCA::SCAUInt64 long integer
SCA::SCAReal32 float
SCA::SCAReal64 float
SCA::SCAChar string of length 1
SCA::SCAString string
SCA::SCAUChar Unicode string of length 1
SCA::SCAUString Unicode string
SCA::SCABool plain integer
SCA::SCAAny [Link] class
SCA::SCATypeCode [Link] class
SCA::SCAVoid None
SCA::SCAResult [Link] class
sequence list
array list of the array size (1D array)
list of lists of array size (2D array)
enum plain integer
struct SCA defined structure type

205
SCA Framework Template IDL to Python Language Mapping

interface SCA defined interface type or Python


class inheriting from SCAIServiceBase
exception [Link] class or SCA defined
exception type

8.2. Mapping for Identifiers


IDL identifiers are mapped to Python with no change. For example:

IDL
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};

Python
node = Node()
[Link] = 123
node.x = 2.345
node.y = 3.456
node.z = 4.567

Remember that most IDL defined identifies will never appear in the Python mappings. The
only IDL defined types whose identifiers will appear are enumerators, structures, exceptions
and constants. This will be described in more detail in the following sections.
8.3. Mapping for Modules
IDL defined types are created in Python modules with the same name as the fully qualified
IDL name scope. When referencing an interface or an IDL defined type, the fully qualified
name should be used.

IDL
module SCA { module Test {
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};
}; };

Python
node = [Link]()

206
SCA Framework Template IDL to Python Language Mapping

8.4. Mapping for Basic Types


SCA basic types are mapped directly to native Python types. Also since Python is a type-less
language, the SCA basic type names have no purpose in Python and are not exposed.

The mapping between SCA basic types and Python type happens in two directions. If the
Python script is calling an interface method written in a different language, the SCA language
bridge maps any input type in a two step process.
The Python value is converted to a C value
The range of the C value is checked to be consistent with the SCA type
These conversions use the functions provided by the Python interpreter and are quite liberal.
For example you they will convert a Python plain integer, long integer, floating point or even a
string value to a C long value as long as the conversion makes sense. The following examples
show some valid types of conversions that would be acceptable when making a call to an
interface method that has an input SCAInt32 value.

[Link](123)
[Link](long(123))
[Link] (123.0)
[Link] ('123')

But the following calls would throw a SCASystemException exception because they do not
represent a valid integer value.

[Link] (123.45)
[Link] ('123.45')

The following table shows the Python types and value ranges that can be converted to each
SCA basic type.

IDL Type Python Types Legal Range


SCA::SCAInt8 integer, long, -128,127
float, string
SCA::SCAUInt8 integer, long, 0,255
float, string
SCA::SCAInt16 integer, long, -32768,32767
float, string
SCA::SCAUInt16 integer, long, 0,65535
float, string
SCA::SCAInt32 integer, long, -2147483648,2147483647
float, string
SCA::SCAUInt32 integer, long, 0,4294967295
float, string
SCA::SCAInt64 integer, long, -9223372036854775808,
float, string 9223372036854775807
SCA::SCAUInt64 integer, long, 0,18446744073709551615
float, string

207
SCA Framework Template IDL to Python Language Mapping

SCA::SCAReal32 integer, long, -3.4028235×1038,


float, string 3.4028235×1038
SCA::SCAReal64 integer, long, -1.7976931348623157×10308,
float, string 1.7976931348623157×10308
SCA::SCAChar string string length 1
SCA::SCAString string
SCA::SCAUChar string, string length 1
Unicode string
SCA::SCAUString string,
Unicode string
SCA::SCABool integer, long, True = 0
float, string, False != 0
True, False

After making the actual call to the interface method, any output values must then be converted
back to a Python value. This conversion is much simpler because the SCA types are already
strongly typed and no value checking is required. The following table shows the Python type
that will be created for each value type.

IDL Type Python Type


SCA::SCAInt8 plain integer
SCA::SCAUInt8 plain integer
SCA::SCAInt16 plain integer
SCA::SCAUInt16 plain integer
SCA::SCAInt32 plain integer
SCA::SCAUInt32 long integer
SCA::SCAInt64 long integer
SCA::SCAUInt64 long integer
SCA::SCAReal32 floating point
SCA::SCAReal64 floating point
SCA::SCAChar string
SCA::SCAString string
SCA::SCAUChar Unicode string
SCA::SCAUString Unicode string
SCA::SCABool integer 0 or 1

The SCA Kernel has transitioned from using wide strings to Unicode strings. The
SCAWString and SCAWChar tyes will be supported for a limited time to allow
applications to migrate to Unicode strings and chars.

8.5. Mapping for Enumerated Types


Each enumerator of an enumerated type is mapped to a Python integer with the appropriate
value as show in this example.

IDL

208
SCA Framework Template IDL to Python Language Mapping

module SCA { module Test {


enum Color {
RED,
GREEN,
BLUE
};
}; };

Python
print 'Enumerator [Link] =',[Link]
print 'Enumerator [Link] =',[Link]
print 'Enumerator [Link] =',[Link]

The following output would be generated by this code

Enumerator [Link] = 0
Enumerator [Link] = 1
Enumerator [Link] = 2

Since the mapping for enumerators is to plain Python integers which are not write protected,
care should be taken to not accidentally change their values.

The actual enumeration type, Color in this example, is not required in Python and not exposed
in the mapping.
8.6. Mapping for Structures
Each IDL defined structure is mapped to a Python class which contains a data value for each
member.

IDL
module SCA { module Test {
struct Node
{
SCAInt32 id;
SCAReal32 x;
SCAReal32 y;
SCAReal32 z;
};
}; };

Python
node = [Link]()
[Link] = 123
node.x = 2.345
node.y = 3.456
node.z = 4.567
print 'node =',[Link],node.x,node.y,node.z

The structure objects also have a couple of special attributes that can be used to reflect on their
definition.

209
SCA Framework Template IDL to Python Language Mapping

Attribute Value
__doc__ String representation of definition
__name__ Name of structure
__members__ Python list with data member names

The following example shows how these attributes can be used.

Python
print '\nStructure name is',node.__name__
print '\n',node.__doc__
print '\nStructure members are',node.__members__

Would produce the following output:

Structure name is [Link]

Structure [Link] {
SCA.SCAInt32 id
SCA.SCAReal32 x
SCA.SCAReal32 y
SCA.SCAReal32 z
}

Structure members are ['id', 'x', 'y', 'z']

Because Python is type-less, each member in the structure is defined as a generic Python
object. When initializing the structure, you need to be careful that it can be converted to the
required SCA type when the structure passes through a SCA language bridge. If it cannot,
then a SCASystemException exception will be thrown at that time. The following IDL
contains a structure with an array member to demonstrate this.

IDL
module SCA { module Test {
struct Node2
{
SCAInt32 id;
SCAReal32 loc[3];
};
}; };

Python
node = [Link].Node2()
[Link] = 123
[Link] = [2.345,3.456,4.567]

When using structures, you should remember that Python assignment statements only
generate a new reference to the data. As a result, the change to the [Link] value in the
following example will also cause the value of the node1 reference to change.

node1 = [Link]()
[Link] = 1

210
SCA Framework Template IDL to Python Language Mapping

[Link] = node1
[Link] = 999

To make the node2 value a separate copy of the data so any changes to it will not affect the
node1 value, you can use the following code.

node1 = [Link]()
[Link] = 1
[Link] = [Link](node1)
[Link] = 999

8.7. Mapping for Arrays


Two types of array definitions are supported in IDL. Fixed size arrays must have their size
defined in the IDL and can never change. Dynamic arrays allow you to delay the specification
of the array size until it is actually allocated. Only arrays of rank 1 or 2 are supported.

Both types of arrays are mapped directly to native Python lists. As a result, the IDL defined
type name will not appear in the Python mapping.
Fixed size arrays
In Python, arrays are represented by normal Python lists. When arrays are created you need to
make sure that their length is correct and that each entry of the list can be converted to the
required SCA type. The array sizes and types are not checked when making calls within
Python but if making a call to an interface implemented in another language through a SCA
language bridge, a SCASystemException will be thrown if the length is incorrect or any of
the entries cannot be converted.

IDL
typedef SCAInt32 Date[3];

Python
date = [9,1,2009]

Two dimensional IDL arrays are represented as a list of lists.

IDL
typedef SCAInt64 Matrix[5][5];

Python
matrix = []
for i in range(5):
column = []
for j in range(5):
[Link]((i+1)*10 + (j+1))
[Link](column)

211
SCA Framework Template IDL to Python Language Mapping

Dynamic Arrays
Dynamic Arrays are handled the same way as fixed size arrays except they may have any
desired size. Dynamic arrays exist primarily to provide more optimized code in other
languages supported by the SCA framework.
8.8. Mapping for Sequences
In Python, sequences are represented by normal Python lists. When sequences are created you
need to make sure that each entry of the list can be converted to the required SCA type. The
entry types are not checked when making interface calls within Python but if making a call to
another language through a SCA language bridge a SCASystemException will be thrown if
any of the entries cannot be converted.

IDL
typedef sequence<SCAReal64> SCAReal64Sequence;

Python
# Initialize contents of the sequence
seq = []
for i in range(100):
[Link](i+1+.2)

# Print contents of the sequence


print seq

Since sequences are mapped directly to native Python lists, the IDL defined type name will
not appear in the Python mapping.
8.9. Mapping for Vectors
The mapping for Vectors is same as Sequences.

8.10. Mapping for Maps


In Python, maps are represented by normal Python Dictionaries. When maps are created you
need to make sure that each key or value entry of the map can be converted to the required
SCA type. The entry types are not checked when making interface calls within Python but if
making a call to another language through a SCA language bridge a SCASystemException
will be thrown if any of the entries cannot be converted.

IDL
typedef map<SCAString, SCAReal64> MapStringReal64;

Python

# Initialize contents of the map


realMap = {}
realMap[‘first value’] = 65.74
realMap[‘second value’] = 5.75

212
SCA Framework Template IDL to Python Language Mapping

realMap[‘third value’] = 4.6


realMap[‘fourth value’] = 78.7

# Print contents of the map


print realMap

Since maps are mapped directly to native Python dictionary, the IDL defined type name will
not appear in the Python mapping.

8.11. Mapping for Type Aliases


A typedef is used in SCA IDL to define a sequence, an array or an alias for an existing type.
The Python mapping for sequences and arrays has already been discussed in the previous
sections.

The use of the IDL typedef to create a new name for an existing type normally does not have a
meaning in Python because it is a type-less language. As a result most of the IDL defined type
names never appear in Python. The one exception to this is for structures where actual Python
classes are created to represent the IDL type. In this case, any aliases defined for these types in
IDL will also be available in Python as shown in the following examples.

IDL
module SCA { module Test {
struct TimeDef
{
SCAInt32 hour;
SCAInt32 minute;
SCAInt32 second;
};
typedef TimeDef LocalTime;
typedef TimeDef GMTTime;
}; };

Python
time = [Link]()
localtime = [Link]()
gmttime = [Link]()

8.12. Mapping for TypeCode


The SCATypeCode type is a special type used by the SCA Framework to describe the details
about each IDL defined type. The SCA Framework creates instances of the SCATypeCode
using XML data generated by the IDL compiler. Each instance of the SCATypeCode
contains the complete description of one IDL defined type. For example, the description of a
structure would include the name and type for each of its members.

The SCATypeCode type is treated in IDL as a basic type and it can appear anywhere in the
IDL where a basic type can appear. For example it could be the member of a structure or one
of the arguments in an interface method.

213
SCA Framework Template IDL to Python Language Mapping

In Python a type code value is represented by the SCATypeCode class. The definition of a
SCATypeCode contains a pair of values. These include a SCATypeCodeID value that
indicates the type of data and a description of the type. The contents of the description depend
on the value of the SCATypeCodeID. The SCATypeCode class is fairly complex and will
not be discussed in detail here. The data contained in this class is mostly used internally within
the SCA Framework.

If you need to access these detailed type definitions you are encouraged to use the
[Link] service that is describe in detail in the SCA SDK Advanced
Features manual.
8.13. Mapping for SCAAny
The SCAAny is a container data type which can hold a single value of any other arbitrary IDL
data type. Only values for types that are defined in IDL can be stored in a SCAAny. This is
because the SCAAny design requires a SCATypeCode value to describe the data it holds and
these are only generated by the IDL compiler and will not exist for types that are not defined
in IDL.

The normal mapping for the SCAAny type in the languages supported by SCA fulfills two
important requirements:
It must handle types in a type-safe manner.
It must handle values for complex types that are not known at compile time.
The first requirement covers the typical usage of the SCAAny type, the insertion of typed
values into the SCAAny and the type-safe extraction of the values. Because of the type-less
nature of Python, many of the type-safe features of the SCAAny provided in other languages
are not supported in Python. More details on what type-safe features are supported are
discussed later in this section.

The second requirement covers situations like the need to extract data from the SCAAny
when you do not know the type of data it contains. In this case the receiver must be able to
determine information about what type of data the SCAAny contains. To achieve this,
SCAAny contains a pair of values that includes the actual value of the data and a description
of its type. The type information, contained in a SCATypeCode value, can then be inspected
to determine the details on the value stored in the SCAAny instance.
The SCAAny class definition
The Python mapping for the IDL type SCAAny is pretty simple and is implemented by the
[Link] class. The methods for the class are shown below.

class SCAAny:

# Attributes
m_type = None
m_data = None

# Initialize the SCAAny


def __init__(self, data=None, tc=None):

214
SCA Framework Template IDL to Python Language Mapping

# Reset the value in the SCAAny


def setValue(self, data=None, tc=None):

# Return the type of data in the SCAAny


def getType(self):

# Return the data in the SCAAny


def getData(self):

# Determine if the SCAAny has data


def empty(self):

# Flush the SCAAny


def flush(self):

# Methods to format contents


def dump(self):
def __str__(self):

Examples of using the SCAAny are show in the following sections.


Creating new SCAAny values
The following example creates an empty SCAAny value.

# Create an empty SCAAny instance


any = [Link]()

To create a new SCAAny value that contains a value you can use the constructor which takes
a Python value and an optional string description of the type. The form you choose depends on
the type of the Python value you provide. The following table shows the Python types which
support an automatic mapping to a SCA type. For these types you only need to provide the
Python object when creating a SCAAny instance.

Python type SCA Type used


Plain Integer SCA.SCAInt32
Long integer SCA.SCAInt64
Boolean [Link]
Floating SCA.SCAReal64
String [Link]
Unicode [Link]
[Link] [Link]
[Link] [Link]
[Link] [Link]
SCA Structure Appropriate structure type
SCA Interface Appropriate interface type

The following shows some examples of this.

# Create a SCAAny instance which contains a SCAInt32 value


any = [Link](123)

215
SCA Framework Template IDL to Python Language Mapping

# Create a SCAAny instance which contains a SCABool value


any = [Link](True)

# Create a SCAAny instance which contains a structure value


node = [Link]()
[Link] = 123
node.x = 1.0
node.y = 2.0
node.z = 3.0
any = [Link](node)

If the Python value is not one of the types that supports an automatic mapping or if you want a
different mapping then you will need to add the type description to explicitly specify the type.
An example of this is a Python plain integer value which will normally map to a SCAInt32
value but you wish to make it a SCAInt64 value instead.

# Create a SCAAny instance which contains a SCAInt64 value


any = [Link](123,'SCA.SCAInt64')

Another example of this would be inserting a Python list that has no automatic mapping
defined.

# Create a SCAAny instance which contains a [Link] value


date = [9,1,2009]
any = [Link](date,'[Link]')

When both a Python object and the type description are given, some limited checking will be
done to ensure that the two are consistent. For example for an array a check is made to be sure
the Python object is a list and that its length is correct but the individual entries in the list will
not be checked. The complete checking will be performed when the data is actually used when
making an interface method call through a SCA language bridge.
Inserting values into existing SCAAny values
You can also insert a value into an existing SCAAny instance. If the instance already holds a
value it will be replaced with the new value. Remember that the SCAAny can only hold a
single value at a time.

Inserting values into an existing SCAAny instance follows the same pattern that was
described previously for constructing new SCAAny values and used the setValue method.

# Insert a SCAInt32 value into a SCAAny instance


[Link](123)

# Insert a [Link] value into a SCAAny instance


node = [Link]()
[Link] = 123
node.x = 1.0
node.y = 2.0
node.z = 3.0
[Link](node)

216
SCA Framework Template IDL to Python Language Mapping

# Insert a [Link] value into a SCAAny instance


date = [9,1,2009]
[Link](date,'[Link]')

A SCAAny can even hold another SCAAny instance.

# Insert an SCAAny value to SCAAny instance


any2 = [Link](123)
[Link](any2)

Extracting the value contained in a SCAAny


To extract a value from the SCAAny, you use the getData method.

# Extract a SCAInt32 from a SCAAny instance


val = [Link]()
print 'Extracted value is',val

There may be cases where the SCAAny value may hold one of a number of different types
and you do not know beforehand which one it contains. In this case you can use the getType
method to determine the type so you can process the data correctly. The getType method
returns a [Link] value which describes the type. The following example shows
how the type of the value can be tested at runtime to handle different possibilities.

# Extract an unknown type from a SCAAny instance


typeid = [Link]().getTypeID()
if typeid == SCA.TCID_Int32:
print 'SCAInt32 value is',[Link]()
elif typeid == SCA.TCID_Real64:
print 'SCAReal64 value is',[Link]()
elif typeid == SCA.TCID_String:
print 'SCAString value is',[Link]()
else:
print 'Unsupported type',[Link]().getTypeDesc()

Miscellaneous SCAAny methods


The SCAAny provides several miscellaneous methods that can be used to check if the
SCAAny contains any data or to flush its contents.

# Check if SCAAny is empty


if [Link]():
print 'The SCAAny is empty'

# Flush the contents of the SCAAny which will now be empty


[Link]()

The SCAAny also implements the dump method which allows you print its contents and the
__str__ method which allows you to convert its value to a string.

# Print the information about the contents of the SCAAny


[Link]()

217
SCA Framework Template IDL to Python Language Mapping

print str(any)

8.14. Mapping for SCAResult


The SCAResult type is used to return error information from calls to interface methods. It
contains the following information
Error code
Message table ID
Message number
Message parameters
The values in a SCAResult instance can be used by the SCA Framework to format and
dispatch messages in the language appropriate for the current user. For more information on
using SCAResult for error processing see the Error Handling chapter of this manual.
SCAResult class definition
The Python mapping for the IDL type SCAResult is implemented by the [Link]
class. The methods for the class are shown below.

class SCAResult:

# Supported attributes
m_errorCode=0
m_msgTable=0
m_messageID=0
m_params=None

# Initialization
def __init__(self, eid=0, tid=0, mid=0, params=None):

# Setting values
def setErrorCode(self,errorCode):

# Return values
def getErrorCode(self):
def getTableID(self):
def getMessageID(self):

# Add a new parameter


def addSCAInt8(self,value):
def addSCAUInt8(self,value):
def addSCAInt16(self,value):
def addSCAUInt16(self,value):
def addSCAInt32(self,value):
def addSCAUInt32(self,value):
def addSCAInt64(self,value):
def addSCAUInt64(self,value):
def addSCAReal32(self,value):
def addSCAReal64(self,value):
def addSCAChar(self,value):
def addSCAUChar(self,value):
def addSCAString(self,value):
def addSCAUString(self,value):

218
SCA Framework Template IDL to Python Language Mapping

def addSCABool(self,value):
def addParam(self, anyvalue):

# Compare all fields of SCAResult data, excluding parameters


def equals(self, obj):

# Return the parameters


def getParams(self):

# Return true if has parameters, return fals otherwise


def hasParams(self):

# Return true if the error code == 0


def isOK(self):

def SCABool(self):

# Return true if it is a system error


def isSystemError(self):

# Print the raw contents of the SCAResult


def dump(self):

# Return a formatted message


def __str__(self):

Two predefined SCAResult values are provided to indicate a simple success or error when
you do not need to include more detailed information to the callers.

// Return error
return [Link]
// Return success
return [Link]

Examples of the usages of these are shown in the following sections.


Creating new SCAResult values
The following example creates SCAResult values with different levels of initialization.

# Create SCAResult with all zero values


rstat = [Link]()
# Create SCAResult with only an error value
rstat = [Link](1)
# Create SCAResult with error, tableID and messageID
rstat = [Link](1,4,301)
Resetting the error code in a SCAResult value
The error code in an existing SCAResult value can be reset as follows.

# Reset error code in SCAResult


[Link](201)

219
SCA Framework Template IDL to Python Language Mapping

Adding parameters to a SCAResult value


You use one of the add methods to add a parameter to a SCAResult value. There is a separate
method for each basic type that is supported as a parameter value.

# Add parameters to SCAResult value


rstat.addSCAInt8(1)
rstat.addSCAInt16(12)
rstat.addSCAInt32(123)
rstat.addSCAInt64(1234)
rstat.addSCAUInt8(2)
rstat.addSCAUInt16(23)
rstat.addSCAUInt32(234)
rstat.addSCAUInt64(2345)
rstat.addSCAReal32(12.34)
rstat.addSCAReal64(123.456)
[Link]('A')
[Link]('TestString')
[Link]('TestUnicodeString')
[Link](True)

You can also use the addParam method to add a parameter which takes a SCAAny value.

[Link]([Link]('TestString'))

You can even create a SCAResult value and add parameters in one operation. But in this case
you can only user parameter values that have already been inserted into SCAAny instances.

params = []
[Link]([Link]("TestString"))
[Link]([Link](123))
rstat = [Link](1,4,301,params)

Interrogating the contents of a SCAResult


The isOk method provides a simple way to test if the SCAResult value has an error.

# Test if SCAResult has a non-zero error


if not [Link]():
print 'The SCAResult contains an error'

The get methods can be used to extract the error, table and message values.

# Extract the error, tableID and messageID values


error = [Link]()
tableid = [Link]()
messageid = [Link]()

The hasParams and getParams methods can be used to determine if the SCAResult has
parameters and to process them. The parameter values are returned in a SCAAnySequence.

# If the SCAResult has parameters, print them


if [Link]():

220
SCA Framework Template IDL to Python Language Mapping

params = [Link]()
for (i,param) in zip(range(len(params)),params):
print 'Param',i,'=',str(param)
Miscellaneous SCAResult methods
The SCAResult also implements the __str__ and dump methods which allow you to get or
print the contents. The __str__ method will attempt to format a message for the SCAResult
value using the MessageDispatcher service which is described in the Error Handling chapter
of this manual. The dump method will just print the raw data contained in the SCAResult
value.

# Print a string representation of the SCAAny


print 'SCAResult value is ' + str(rstat)

# Print contents using the dump method


[Link]()

8.15. Mapping for Constants


IDL defined constants are mapped directly to appropriate Python values in the module they
are defined in. Since the mapping for constants is to plain Python values which are not write
protected, care should be taken to not accidentally change their values.

IDL
module SCA { module Test {
const SCA::SCAInt32 NUM_OF_STATES = 50;
}; };

Python
# Print value of constant defined in IDL
print 'Constant value = ',[Link].NUM_OF_STATES

8.16. Mapping for Interfaces


There are two different Python mappings for SCA interfaces depending on what language
they are implemented in.
SCA interfaces implemented in a language other than Python are mapped to a special
SCA proxy class.
Interfaces implemented in Python are mapped to a normal Python class that inherits from
the [Link] class.
Since interfaces are either mapped to an instance of a generic proxy class or to a user provided
Python class, the IDL interface names are not used in Python and are not exposed. The only
required references to interface names are using string types which contain their name.

The following is a simple interface definition that will be used in this section to demonstrate
the use of SCA interfaces in Python.

IDL
module SCA { module Test {

221
SCA Framework Template IDL to Python Language Mapping

typedef SCAInt32 Date[3];


interface SCAITestInterface : SCA::SCAIService
{
SCAInt32 testInt32(in SCAInt32 inval,
out SCAInt32 outval,
inout SCAInt32 inoutval);
Date testDate(in Date inval,
out Date outval,
inout Date inoutval);
SCAInt32 testNoArg();
};
}; };

Mapping for Interface Operations


Each interface operation (or method) is mapped to a method in the Python class with the same
name. There is one exception to this rule. Since Python does not allow a class attribute with
the name print, if the IDL method name is print, it will be mapped to _print in Python.
Special Interface Attributes
The interface mappings also provide a couple of special attributes that can be used to reflect
their definition.

Attribute Value
__doc__ Information about interface object
__methods__ Python list with names of methods

The following example shows how these attributes can be used assuming you have an
instance of a Python mapping to the [Link] interface.

Python
# Variable sp points to a SCAITestInterface interface
print sp.__doc__
for meth in sp.__methods__:
print 'method ',meth

Would produce the following output:

SCAPyInterface object for interface [Link]


method addReference
method releaseReference
method getInterface
method getImplName
method getInstanceID
method testInt32
method testDate
method testNoArg

Mapping for Interface Parameters


The Python language does not support the concept of output arguments so the handling of
arguments in calls to interface methods must be a bit different. Only arguments with an IDL

222
SCA Framework Template IDL to Python Language Mapping

defined direction of in or inout should appear in the argument list. This is because these are the
only type of arguments that have an input value. The arguments should maintain the same
relative order as specified in the IDL. Each interface call will normally return a tuple of values.
The first member of the tuple is always the return value of the method unless it is a SCAVoid.
The remaining values in the tuple are any arguments with an IDL defined direction of inout or
out. Once again these will maintain the same relative order as specified in the IDL. Note that
arguments with a direction of inout appear in both the argument list and the return tuple.

The following example calls the testInt32 method of the SCAITestInterface interface. This
method has an argument of each of the supported directions plus a return value to show how
they are handled in Python.

inval = 1
inoutval = 3
(retval,outval,inoutval) = splist.testInt32(inval,inoutval)
print 'Call results: inval=%d outval=%d inoutval=%d retval=%d' %
(inval,outval,inoutval,retval)

Notice the actual call only passes the arguments with a direction of in and inout which are the
ones with input values. The argument with the out direction is not passed as an argument in
the call. The return value from the call is a tuple which contains the return value and the
arguments with a directions of out or inout.

While Python does not support the concept of output arguments it does support mutable
arguments which act like arguments with a inout direction. An example of this is an argument
which is a Python list type. Some SCA types map to mutable Python types. Examples of these
are arrays and sequences which map to Python lists. Even so these types of arguments could
be mapped to take advantage of the fact that they are mutable, this is not done. If this was done
then a different set of mapping rules would be used for different parameter types and this
would be confusing. As a result, even for SCA types which map to mutable Python types, a
parameter with a inout direction should still appear in both the argument list and the return
tuple. This is shown with the following example.

# Test with mutable arguments


indate = [11,12,13]
inoutdate = [31,32,33]
(retdate,outdate,inoutdate) = [Link](indate,inoutdate)
print 'Call results: inval=%s outval=%s inoutval=%s retval=%s' %
(indate,outdate,inoutdate,retdate)

If the total number of return values and arguments with a direction of out or inout is only one,
then the single value will be returned directly instead of in a tuple of length one. This is
demonstrated in the following example.

# Test with single value return


retval = [Link]()
print 'Call results: retval=%d' % retval

223
SCA Framework Template IDL to Python Language Mapping

You can also use keyword arguments when calling interface methods. In this case the order of
the arguments is not important, but you need to make sure that a value for each required
argument is supplied.

# Test with keyword arguments


ival = 1
ioval = 3
(rval,oval,ioval) = splist.testInt32(inoutval=ioval,inval=ival)
print 'Call results: inval=%d outval=%d inoutval=%d retval=%d' %
(ival,oval,ioval,rval)

Use of getInterface in Python


Since Python is a type-less language, the use of casting for interface navigation which is
supported by other language is not available in Python. Instead you must always make explicit
getInterface calls to obtain the desired interface pointer. Every SCA interface mapping
provides a getInterface method. This is true if the interface object is represented by a SCA
proxy object or a user provided Python class that inherits from the [Link]
class. The following example shows how this is done.

import SCA
svc = [Link]('ServiceName')
(ret,sp) = [Link]('[Link]')

The important thing to remember here is that the getService routine returns a
[Link] interface. You must then make a getInterface call on this object to obtain
the interface that you really need.
Implementing SCA Interfaces
Currently you cannot implement a normal SCA service in Python. But it is still possible to
implement a SCA interface in Python. A common pattern where this is needed is the listener
pattern. Consider the following IDL.

IDL
module SCA { module Test {
interface SCAITestListener : SCA::SCAIService
{
void notify(in SCA::SCAString msg);
};
interface SCAITestProcessor : SCA::SCAIService
{
void registerListener(in SCAITestListener spListener);
SCA::SCAResult process();
};
}; };

The service that implements the SCAITestProcessor interface is using a listener interface.
Any client of this service is required to implement the SCAITestListener interface and
register it with the service. The service can then use this interface to make calls back into the
client as required. This means that if the client using this service is written in Python, then it
must be able to implement the listener interface.

224
SCA Framework Template IDL to Python Language Mapping

A SCA interface can be implemented with a normal Python class. The class must follow the
following rules.
The class must inherit from the [Link] class provided with the SCA
framework.
The initialization routine in the implementation class must explicitly call the initialization
routine of the [Link] class. The arguments for this call must be a list
with the names of interfaces that the class will implement.
The class must implement each method in each of the interfaces that are implemented.
This also includes methods in any interfaces that they inherit from. You do not need to
implement the methods in [Link] because these are implemented in
[Link] class.

The following example shows a simple Python class that will implement the listener interface.

class MyPyImpl([Link]):

def __init__(self):
interfaces = ['[Link]']
[Link].__init__(self,interfaces)

def notify(self,msg):
print 'MyPyImpl::notify -',msg

The __init__ routine in [Link] checks to make sure that the Python class
implements each of the required interface methods. If any of the methods are missing it will
throw an exception.

When implementing interface methods, you need to use the same rules for handling
arguments that was described above. Only arguments with directions of in and inout should
appear as parameters to the method and the method should return a tuple which contains the
return value and any arguments with directions of out or inout. You also need to make sure
that the values in the return tuple can be converted to the required SCA types.

The following example shows how an instance of this interface can be created and passed to
the test service.

sp = [Link]('ServiceName','[Link]')
myinf = MyPyImpl()
[Link](myinf)
[Link]()

8.17. Mapping for Exceptions


The SCA Framework provides three predefined exception types, [Link],
[Link] and [Link]. All user defined exceptions in
IDL must inherit from either SCA::SCAUserException or another user-defined exception.
Only single inheritance is allowed.

225
SCA Framework Template IDL to Python Language Mapping

SCAException exception
The base for all IDL defined exceptions is SCAException which is mapped to the Python
class [Link].

class SCAException:

# Supported attributes
text = None
typecode = None

def __init__(self):

def what(self):

def getTypeCode(self):

def getText(self):

def setText(self,text):

def __str__(self):

Mapping for other exception types


The predefined exceptions [Link] and [Link] and
all user exceptions defined in IDL are mapped to internally generated Python classes. All the
user defined members in an exception are mapped to attributes in these exception classes.

Consider the listener example used in the previous section. Let’s modify the example so the
process method can now throw an exception by adding a raises clause to its IDL definition.
This exception will be thrown if the process method is called but a listener interface was not
registered.

IDL
module SCA { module Test {
exception NoListenerException : SCAUserException
{
SCAInt32 id;
};
interface SCAITestProcessor : SCA::SCAIService
{
void registerListener(in SCAITestListener spListener);
SCA::SCAResult process() raises(NoListenerException);
};
}; };

When calling the process method in Python, we can now catch the exception as follows.

try:
[Link]()
except [Link], exc:
print 'NoListenerException:',[Link]()
print 'id =',[Link]

226
SCA Framework Template IDL to Python Language Mapping

Because we caught the actual [Link] exception we have full access


to the data members defined in it. In this case this is the id data member.

It is also possible to catch the [Link] type which is the base SCA exception.
But in this case we would not have access to any data members defined in the actual
exception.

try:
[Link]()
except [Link], exc:
print 'SCAException:',exc

SCA exceptions do not inherit from Python's Exception type so you cannot catch them with an
except clause using it.

There may also be situations where you need to throw a SCA exception from a Python script.
This is unusual and normally will only occur if you are implementing an interface in Python.
The following Python code will implement the SCAITestProcessor interface that was
described before. In the implementation of the process method, an exception will be thrown if
the listener interface was never registered.

class MyPyImpl([Link]):

def __init__(self):
interfaces = []
[Link]('[Link]')
[Link].__init__(self,interfaces)

m_spListener = None

def registerListener(self,spListener):
self.m_spListener = spListener

def process(self):
if not self.m_spListener:
exc = [Link]()
[Link]('Listener interface was never registered')
[Link] = 123
raise exc
self.m_spListener.notify('This is test notification from Python')

The IDL raises clause


An IDL interface operation may contain a raises clause to indicate what kind of exceptions the
operation may throw. An example of this was shown previously. The presence of a raises
clause in the IDL has no affect on any of the actual Python code required to call or implement
the SCA interfaces. But, when implementing interfaces in Python it is still important that the
IDL definition of the interfaces contain the appropriate raises clauses. This is because the
various SCA language bridges will check the exceptions thrown and will only pass those that

227
SCA Framework Template IDL to Python Language Mapping

have been specified. If an exception is thrown that is not specified in the raises clause, it will
be converted to a SCASystemException and much of the information it contains may be lost.
8.18. Mapping for SCA Services
Currently, the implementation of SCA services in Python is not supported.
8.19. Mapping for SCA Components
Currently, the implementation of SCA components in Python is not supported.
8.20. The SCA Module
The Python mapping provides an SCA module which is used to access the SCA Framework
services from the Python script. The importing of the SCA module also insures that the SCA
Framework is successfully initialized so SCA services and predefined types can be accessed.

The following functions are available in this module.

Method Purpose
getService Load a SCA service
loadTypes Make IDL defined type available

The getService function is used to load SCA services. The following is an example of how it
is used.

import SCA
svc = [Link]('ServiceName')
(ret,sp) = [Link]('[Link]')

It is also possible to combine the two calls into one as shown below.

import SCA
sp = [Link]('ServiceName','[Link]')

The loadTypes function will be described in the next section.


8.21. Accessing IDL Type Definitions from Python
The various mappings defined for SCA types in this chapter fall into four different categories.
Some types are provided by the SCA Python Bridge. These types are immediately
available when the SCA module is imported. Examples of these types include SCAAny,
SCAResult and SCAException.
Some types are mapped to normal Python types. These include basic types, arrays and
sequences.
Some types required special Python classes to be created to represent the SCA type in
Python. These types include structures and exceptions.
Some types required instances of normal Python variables be created with the value
defined by an IDL definitions. Examples of these include enumerations and IDL defined
constants.

228
SCA Framework Template IDL to Python Language Mapping

The last two categories are important because they both required the SCA Python Bridge to
create Python objects at runtime which represent the IDL defined type. When using these
types, it is important to understand what actually triggers the creation of these Python objects.

The SCA Python Bridge will normally process these definitions when a proxy object is
created for a SCA interface and only the types referenced in that interface will be created.

The following IDL definitions will be used to demonstrate this. Two interfaces are defined
and each one references a separate structure definition. There is also a constant definition
included.

IDL
module SCA { module Test {
const SCAInt32 ERROR_1 = 1;
struct Struct1
{
SCAInt32 val;
};
interface SCAITestInterface1 : SCA::SCAIService
{
void method1(in Struct1 sval1);
};
struct Struct2
{
SCAInt32 val;
};
interface SCAITestInterface2 : SCA::SCAIService
{
void method2(in Struct2 sval2);
};
}; };

The following Python code illustrates when the various types will become available in the
Python script.

def TestVariables():
vars = []
[Link]('[Link].Struct1')
[Link]('[Link].Struct2')
[Link]('[Link].ERROR_1')
for var in vars:
try:
exec 'val = %s' % var
print '%s defined' % var
except:
print '%s not defined' % var

import SCA
print '\nStart of test'
TestVariables()

print '\nLoad service'


svc = [Link]('ServiceName')

229
SCA Framework Template IDL to Python Language Mapping

TestVariables()

print '\nCall to getInterface for [Link].SCAITestInterface1'


(ret,sp) = [Link]('[Link].SCAITestInterface1')
TestVariables()

print '\nCall to getInterface for [Link].SCAITestInterface2'


(ret,sp) = [Link]('[Link].SCAITestInterface2')
TestVariables()

print '\nCall to [Link] for [Link]'


[Link]('[Link]',True)
TestVariables()

Running this script generates the following output

Start of test
[Link].Struct1 not defined
[Link].Struct2 not defined
[Link].ERROR_1 not defined

Load service
[Link].Struct1 not defined
[Link].Struct2 not defined
[Link].ERROR_1 not defined

Call to getInterface for [Link].SCAITestInterface1


[Link].Struct1 defined
[Link].Struct2 not defined
[Link].ERROR_1 not defined

Call to getInterface for [Link].SCAITestInterface2


[Link].Struct1 defined
[Link].Struct2 defined
[Link].ERROR_1 not defined

Call to [Link] for [Link]


[Link].Struct1 defined
[Link].Struct2 defined
[Link].ERROR_1 defined

Notice that at the start of the test none of the types defined in the IDL are available. This is
even true after the getService call. This is because the getService call returns a
[Link] interface and none of the desired types are references by it. Only after the
getInterface call for [Link].SCAITestInterface1 do we get some types defined. In this
case only the structure [Link].Struct1 is defined because it is the only type referenced by
this interface. The second structure, [Link].Struct2, is not defined until the second
getInterface call for [Link].SCAITestInterface2 is made.

Notice that even after all of the getInterface calls, the constant value [Link].ERROR_1 is
still not defined. This is the normal case for constants because they are usually not directly
referenced by any of the methods in an interface so the SCA Python Bridge will never define
them.

230
SCA Framework Template IDL to Python Language Mapping

To resolve these issues, you must explicitly trigger the loading of these SCA type definitions
using the loadTypes function in the SCA module.

[Link]('[Link]',True)

The first argument to the loadTypes call is the IDL namespace for the types you want defined.
The second argument is a boolean value. If it is true then all the type in the specified
namespace and recursively all of the namespaces it contains will be defined. If false then only
the types in the specified namespace will be defined.

It is also possible to use the loadTypes call to force the definition of types before they would
normally be available. For example in the above example, if the loadTypes call is done
immediately after the SCA module is imported then all of the types will be defined and
available immediately.

Python
import SCA
print '\nImmediate call to [Link] for [Link]'
[Link]("[Link]",True)
TestVariables()

Will generate this output

Immediate call to [Link] for [Link]


[Link].Struct1 defined
[Link].Struct2 defined
[Link].ERROR_1 defined

8.22. Running Python Scripts


There are two different ways to run Python scripts in the SCA Framework
Scripts can be run from inside an application using the ScriptBroker service
Scripts can be run using the command line Python command
This section will briefly describe both of these methods. For complete details you should
consult the Scripting chapter in the SCA SDK Advanced Features manual.
Running Scripts with the ScriptBroker
The ScriptBroker is a service that is provided with the SCA Framework which can be used
to run Python scripts from inside an application. The following is a simple example of a C++
routine that will use the ScriptBroker to run a script.

#include <SCA/Framework/Scripting/SCAIScriptBroker.h>

void runScript(SCA::SCAString scriptName)


{
SCA::Framework::Scripting::SCAIScriptBroker spBroker;
spBroker = getSCAService("[Link]");
spBroker->runScript(scriptName);
}

231
SCA Framework Template IDL to Python Language Mapping

Complete details on using the ScriptBroker service are available in the Scripting chapter in
the SCA SDK Advanced Features manual.
Running Scripts from the command line
To run a Python script which used the SCA Framework from the command line, you need to
make sure the environment has been setup appropriately for the SCA Kernel. The following is
a simple CShell script that shows an example of this on the Windows platform.

#!/bin/csh
set ISYSTEM = D:/sCAKernel-V4-007
set path = ( $ISYSTEM/WINNT/bin $ISYSTEM/WINNT/lib $path )
setenv SCA_SERVICE_CATALOG "$ISYSTEM/res/[Link]"
setenv SCA_RESOURCE_DIR "$ISYSTEM/res"
setenv PYTHONPATH "$ISYSTEM/lib/python;$ISYSTEM/WINNT/bin"
/Tools-V5-004/python $*

This script is using the Python installation that is provided in the SCA Tools directory. This is
a good practice because you can be sure that it is the same version that the SCA Kernel was
built with. If you use the Python installation on your machine there could be problems if the
versions are not compatible.

For complete details on the initialization of the SCA Kernel, see the SCA Kernel chapter of
this manual.

232
SCA Framework User Document

Chapter 9

Messages and Internationalization

233
9. Messages and Internationalization
9.1. Introduction
Internationalization is the process of adding capabilities in the
software applications so that they can be adapted to various locales
(languages and regions) without re-building them.

Localization is the actual process of translating and formatting the


text and other GUI components.

The SCA Framework provides the following localization capabilities.

XML Message Tables


The text from messages, dialog boxes and widgets is stored in XML
message files.

Parameter Substitution
Support for number, date, time and currency formats.

Language Customization
The substitution parameters are indexed, so the order could be
different in different languages. This is necessary to support
different writing directions, grammar and composition.

Text Translation Service


Provides the interfaces to load the contents of the XML message
files and format messages.

9.2. Message Files


The message files supported by the SCA framework are UTF-8 encoded
XML files that allows a simple one-to-one mapping from a text ID to the
respective message text. The text includes place holders to allow
parameter substitution and formatting of number, date, time and
currency values.
Locale String
<localeLanguageCode>_<localeCountryCode>
The locale string contains the locale value, which is a 2-character
language code (as defined by ISO 639-1), optionally followed by an
underscore and a 2-character country identifier (as defined by ISO
3166). For example en for English, en_G for British, fr for French,
fr_CA for Canadian French etc. This format is also used in XML
documents as a value for the xml:lang attribute (as described in
[Link] )
Message File Naming Convention
The message file name has the following format:

<baseName>_<localeLanguageCode>_<localeCountryCode>.xml

234
Examples:
TextTranslation_fr.xml
TextTranslation_en_GB.xml

File Search Order


The message file is expected to reside in the component’s resource
directory. For more information on setting the resource directory see
the Kernel Configuration Variables seciton of SCA Kernel chapter in
this manual.

The SCA Kernel will first look in one of several subdirectories of the
resouce directory, RESDIR, for the message file. These are as follows.

Locale_<localeLanguageCode>_<localCountryCode>
Locale_<localeLangueCode>
If the messge file is not found in one of the subdirectores then it
will search directly in the resource diretory.

If a message file in the desired language can not be found, a final try
will be made to load the English version of the table using the same
search order as shown above.

The complete order of search is as follows.

RESDIR/Locale_<lang>_<country>/<baseName>_<lang>_<country>.xml
RESDIR/Locale_<lang>/<baseName>_<lang>.xml
RESDIR/<baseName>_<lang>_<country>.xml
RESDIR/<baseName>_<lang>.xml
RESDIR/Locale_en/<baseName>_en.xml
RESDIR/<baseName>_en.xml
Only the first file found using the above order is loaded.
Example:
baseName= “TextTranslation”,
localeLanguageCode = “fr”
localeCountryCode= ”CA”

Search order:
RESDIR/Locale_fr_CA/TextTranslation_fr_CA.xml
RESDIR/Locale_fr/TextTranslation_fr.xml
RESDIR/TextTranslation_fr_CA.xml
RESDIR/TextTranslation_fr.xml
RESDIR/Locale_en/TextTranslation_en.xml
RESDIR/TextTranslation_en.xml
Message File Format
The supported tags and their attributes are described below:

<sim_office_resource>

235
Wraps all nodes of the translation table entries. It can have
the following attributes:
version: <major-number>.<minor-number> (e.g. “1.0”) [mandatory]
comment: explains the context of the text in this file [optional]
author: In the English (“en”) version of the file, the email address
of the original author/programmer who created it, otherwise the
translator. [optional]
xml:lang: The language provided in this file. The language is also
mangled into the file name, but specifying it in the file again
allows for easier conversion to other formats. [optional]

<text>:
A translation unit. It contains the text node in the
translated language. It has the following attributes:

id: Specifies the string id that is used to retrieve the message


[mandatory]
comment: Can be used to explain the context of the text [optional]
author: If the text was not written by the author specified in the
<sim_office_resource > author attribute [optional]

<module>
A dialog box. It has one attribute:
id: Specifies the string id that is used in getModuleText
etc. [mandatory]
The following enclosed tags describe the text in the module:
<text>: This node describes the dialog’s caption; it has
the same attributes as the <text> tag described above. The
id attribute is optional here! If provided, it is used to
identify the context.
<help>: A help text for the dialog.

Text Formatting
The formatting place holders are embedded in the text. Since the
argument order can change in different languages, each argument is
prefixed by the index of its entry in the argument sequence that is
passed to the getFormattedText method. The index is 1-based. The
format of this prefix is %<index>:, so the first argument would be
%1:, the second %2: and so on.
This index reference is followed by the data formatting information.
Currently, there are three different formatting styles, which are
distinguished by the first character:
Currency Format ( $ )
The provided argument should be an integer or a floating point number .
If a floating point number is used the fractional part is ignored. The

236
units used for the currency argument depend on the current locale
setting. For example, in English they are cents.

Example:
Text: "The price is %1:$"
Arg1= 1999
Formatted Text: "The price is $19.99"

Date/Time Format ( # )
The provided argument should be an integer that stores the number of
seconds since 01/01/70 (UTC). This number will be converted to the
timezone that is set for the computer's system clock. It is possible to
define a different timezone by changing the environment variable TZ.
Caveat: changing this variable puts the whole process in a different
timezone, which could have unwanted effects in a multi-threaded
environment (unless secured by mutex sections). Accepted values for TZ
should be found in system's documentation.

How that date is displayed depends on the character that follows the #
character. The available options are identical to the formats accepted
by the standard C language function strftime (except that strftime
uses % as prefix)

code Meaning
a abbreviated weekday name (e.g. Fri)
A full weekday name (e.g. Friday)
b abbreviated month name (e.g. Oct)
B full month name (e.g. October)
c the standard date and time string
d day of the month, as a number (1-31)
H hour, 24 hour format (0-23)
I hour, 12 hour format (1-12)
j day of the year, as a number (1-366)
month as a number (1-12). Note: some versions of Microsoft Visual
m
C++ may use values that range from 0-11.
M minute as a number (0-59)
p locale's equivalent of AM or PM
S second as a number (0-59)
U week of the year, (0-53), where week 1 has the first Sunday
w weekday as a decimal (0-6), where Sunday is 0
W week of the year, (0-53), where week 1 has the first Monday
x standard date string
X standard time string
y year in decimal, without the century (0-99)
Y year in decimal, with the century
Z time zone name

Example:
Text: "Today is a %1:#A in %1:#B, the time is %1:#X",

237
Arg1 = 1130514894
Formatted Text: "Today is a Friday in October, the time is
5:54:54 PM".
All other Formats ( % )
This formatting is modeled after printf in the programming language C:
%[flags][width][.precision][modifier]conversion
conversion Output Example
c Character a
d or i Signed decimal integer 392
Scientific notation (mantise/exponent) using e
e 3.9265e+2
character
Scientific notation (mantise/exponent) using E
E 3.9265E+2
character
f Decimal floating point 392.65
g Use the shorter of %e or %f 392.65
G Use the shorter of %E or %f 392.65
o Signed octal 610
s String of characters sample
u Unsigned decimal integer 7235
x Unsigned hexadecimal integer 7fa
X Unsigned hexadecimal integer (capital letters) 7FA
p Pointer address B800:0000
Nothing printed. The argument must be a pointer to a
n signed int, where the number of characters written
so far is stored.
A % followed by another % character will write % to
%
stdout.

flags Description
Left-justify within the given field width; Right justification
-
is the default (see width sub-specifier).
Forces to precede the result with a plus or minus sign (+ or -)
+ even for positive numbers. By default, only negative numbers are
preceded with a - sign.
If no sign is going to be written, a blank space is inserted
(space)
before the value.
Used with o, x or X specifiers the value is preceded with 0, 0x
or 0X respectively for values different than zero.
Used with e, E and f, it forces the written output to contain a
# decimal point even if no digits would follow. By default, if no
digits follow, no decimal point is written.
Used with g or G the result is the same as with e or E but
trailing zeros are not removed.
Left-pads the number with zeroes (0) instead of spaces, where
0
padding is specified (see width sub-specifier).

width Description
Minimum number of characters to be printed. If the value to be
(number) printed is shorter than this number, the result is padded with
blank spaces. The value is not truncated even if the result is

238
larger.
The width is not specified in the format string, but as an
* additional integer value argument preceding the argument that
has to be formatted.

.precision Description
For integer specifiers (d, i, o, u, x, X): precision
specifies the minimum number of digits to be written. If the
value to be written is shorter than this number, the result
is padded with leading zeros. The value is not truncated even
if the result is longer. A precision of 0 means that no
character is written for the value 0.
For e, E and f specifiers: this is the number of digits to be
printed after the decimal point.
.number For g and G specifiers: This is the maximum number of
significant digits to be printed.
For s: this is the maximum number of characters to be
printed. By default all characters are printed until the
ending null character is encountered.
For c type: it has no effect.
When no precision is specified, the default is 1. If the
period is specified without an explicit value for precision,
0 is assumed.
The precision is not specified in the format string, but as
.* an additional integer value argument preceding the argument
that has to be formatted.

modifier description
The argument is interpreted as a short int or unsigned short
h
int (only applies to integer specifiers: i, d, o, u, x and X).
The argument is interpreted as a long int or unsigned long int
l for integer specifiers (i, d, o, u, x and X), and as a wide
character or wide character string for specifiers c and s.
The argument is interpreted as a long double (only applies to
L
floating point specifiers: e, E, f, g and G).

Example:
Text: "%1:%d + %2:%g %3:%s"
Arg1 = 1, Arg2 = 2.5, Arg3 = "is equal to..."
Formatted Text: "1 + 2.5 is equal to...".

Sample1: English Message File


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE SIMOFFICERES>
<!--
Copyright (c) 2005, [Link] Corporation. All Rights Reserved.
MSC PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<sim_office_resources version="1.0" xml:lang="en" comment="Translation
Test"
author="[Link]@[Link]">
<text id="color" comment="material"

239
author="[Link]@[Link]">Color</text>
<text id="help">Help</text>
<text id="formatTest">
This is a formatting test: string '%1:%ls', long: %2:%d, double:
%3:%1.3g
</text>
<text id="currencyTest">The price is %1:$</text>
<text id="dateTimeTest">Today is %1:#A %1:#B - %1:#x %1:#X</text>
<module id="mod_test">
<text id="m1">Text in mod_test::m1.</text>
<text id="m2">Text in mod_test::m2.</text>
</module>
</sim_office_resources>

Sample2: German Message File

<?xml version='1.0' encoding='UTF-8' ?>


<!DOCTYPE SIMOFFICERES>
<!--
Copyright (c) 2005, [Link] Corporation. All Rights Reserved.
MSC PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<sim_office_resources version="1.0" xml:lang="de" comment="Translation
Test"
author="[Link]@[Link]">
<text id="color" comment="material"
author="fred@acme_translation.com">Farbe</text>
<text id="help">Hilfe</text>
<text id="formatTest">
Dies ist ein Formatierungs-Test: Zeichenkette '%1:%ls', long:
%2:%d, double: %3:%1.3g
</text>
<text id="currencyTest">Der Preis beträgt %1:$</text>
<text id="dateTimeTest">Heute ist %1:#A %1:#B - %1:#x %1:#X</text>
<module id="mod_test">
<text id="m1">Der Text von mod_test::m1.</text>
<text id="m2">Der Text von mod_test::m2.</text>
</module>
</sim_office_resources>

9.3. Text Translation Service


Text Translation service provides the interfaces to load the contents
of the XML message files and format messages. These interfaces are
described in detail in the following sections.

SCA::Framework::SCAITextTranslationFactory Interface

The SCAITextTranslationFactory is used to create new translation tables


and provides access to the common settings object.

240
Member Functions
SCAResult getTextTranslationSettings (out SCAITextTranslationSettings
settings)
SCAResult createTextTranslationTable (in SCAUString fileBaseName, out
SCAITextTranslationTable newTable)
SCAResult setDefaultFallbackTranslationTable (in
SCAITextTranslationTable defaultTable)

Member Function Documentation


SCAResult getTextTranslationSettings (out
SCAITextTranslationSettings settings )

Returns the singleton instance of SCAITextTranslationSettings (which is


created by the framework on startup).

Parameters:
settings SCAITextTranslationSettings object
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult createTextTranslationTable ( in SCAUString fileBaseName,


out SCAITextTranslationTable
newTable )

Creates a new translation table instance.

Parameters:
fileBaseName Base-name of the message file, which is expected to
reside inside the components resource directory.
newTable Newly created text translation table.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult setDefaultFallbackTranslationTable ( in
SCAITextTranslationTable defaultTable )

Sets the default Translation Table. All translation tables created


after the default table has been set will have their fallback set to
the default table. Existing tables are not affected.

Parameters:
defaultTable Default text
translation table.
Returns:
Returns SCASuccess on success, else returns an error.

SCA::Framework::SCAITextTranslationSettings Interface

The SCAITextTranslationSettings has methods to set and get the current locale.

241
Member Functions
SCAResult getLocale (in LocaleCategory category, out SCAString
locale)
SCAResult getNativeLocale (in LocaleCategory category, out SCAString
nativeLocaleName)
SCAResult setLocale (in LocaleCategory category, in SCAString locale)

Member Function Documentation


SCAResult getLocale ( in LocaleCategory category,
out SCAString locale )

Inquires the currently used locale string.

Parameters:
category The category whose locale is requested.
locale Locale string
Returns:
Returns SCASuccess on success, else returns an error.

242
SCAResult getNativeLocale ( in LocaleCategory
category, out SCAString nativeLocaleName )

This method is used to inquire the locale name in a format that can be
used with native locale functions like setlocale or std::locale. For
example the locale names are different on Windows and UNIX.

Parameters:
category The category whose locale is requested.
nativeLocaleName Native locale string
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult setLocale ( in LocaleCategory category,


in SCAString locale )

Sets the locale string for the given category.

Parameters:
category Locale category
locale Locale string
Returns:
Returns SCASuccess on success, else returns an error.

LocaleCategory
The LocaleCategory is an enum defined below.
enum LocaleCategory
{
LC_All, // All categories. When inquiring, it returns the
locale last
// used to set LC_All.
LC_Messages,// Text translation. Determines the message file to
load.
LC_Collate, // String handling.
LC_CharType,// Character handling.
LC_Numeric, // Formatting of numbers.
LC_Monetary,// Formatting of monetary values.
LC_Time // Formatting of time and date.
};

Locale String
The locale string contains the locale value, which is a 2-character
language code (as defined by ISO 639-1), optionally followed by an
underscore and a 2-character country identifier (as defined by ISO
3166). For example “en” for English, “en_GB” for British, “fr” for
French, “fr_CA” for Canadian French etc. This format is also used in
XML documents as a value for the xml:lang attribute (as described in
[Link] )

243
Mixed Locales
The text translation service supports mixed locales by allowing the
assignment of different locales to different categories. The mixed
locales can be set either by making multiple calls to the ‘setLocale’
method or by making a single call using LC_ALL category and a mixed
locale strring. The mixed locale string has the following format:
“CATEGORY1=locale1; CATEGORY2=locale2; locale3;locale4...”
The optional category is in uppercase and the separation character is
semicolon “;”

For example the following call to setLocale will select German messages
with US-English numeric format and Japanese for all other categories,

SCAITextTranslationSettings spSettings;
spFactory->getTextTranslationSettings( spSettings );
spSettings->setLocale(LC_All, “LC_MESSAGES=de;LC_NUMERIC=en_US;ja”);

SCA::Framework::SCAITextTranslationTable Interface
The SCAITextTranslationTable makes the contents of a Message File
available to the client applications. The text translation table allows
a simple one-to-one mapping from a text ID to the respective text.
There is separate message file for each locale. Changing the locale
requires re-loading of the message file. When an exact match is not
possible, (i.e. locale is set to “fr-CA”, but translations exist only
for the “fr” locale), then only the first two characters (which always
indicate the language) are compared. If even then no match can be
found, the default will be English (“en”).
Member Functions

SCAResult getText (in SCAString textID, out SCA::SCAUString text)


SCAResult getTextByIntId (in SCAInt32 textID, out SCA::SCAUString
text)
SCAResult getModuleText (in SCAString moduleName, in SCAString
itemName, in GuiMessageKind kind, out SCA::SCAUString text)
SCAResult getFormattedText (in SCAString textID, in SCAAnySequence
args, out SCAUString text)
SCAResult getFormattedTextByIntId (in SCAInt32 textID, in
SCAAnySequence args, out SCAUString text)
SCAResult getFormattedModuleText (in SCAString moduleName, in
SCAString itemName, in GuiMessageKind kind, in
SCAAnySequence args, out SCAUString text)
SCAResult getModuleTextByComment (in SCAString moduleName, in
SCAString commentName, in SCAString itemName, in
GuiMessageKind kind, out SCA::SCAUString text)
SCAResult getFormattedModuleTextByComment (in SCAString moduleName,
in SCAString commentName, in SCAString itemName, in
GuiMessageKind kind, in SCAAnySequence args, out SCAUString
text)

244
SCAResult setFallbackTable (in SCAITextTranslationTable table)
SCAResult setFixedLocale (in SCAString locale)

Member Function Documentation

SCAResult getText ( in SCAString textID, out


SCA::SCAUString text )

Gets the simple unformatted text, which does not require any arguments.

Parameters:
textID String that identifies the message.
text Contains the simple text on return.
Returns:
Returns SCASuccess on success, else returns an error.
SCAResult getTextByIntId ( in SCAInt32 textID, out
SCA::SCAUString text )

Same as getText(), but instead of string the input is an integer


textID.

Parameters:
textID Integer value that identifies which message should be
looked up.
text Contains the simple text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getModuleText ( in SCAString moduleName,


in SCAString itemName,
in GuiMessageKind kind,
out SCA::SCAUString text )

Gets simple GUI text from <dialog> or <module> sections of the message
file.

Parameters:
moduleName Module name ( dialog name).
itemName Item name (widget name).
kind Sub-item type (GMK_Text, GMK_Help).
text Contains the simple text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getFormattedText ( in SCAString textID,


in SCAAnySequence args,
out SCAUString text )

Gets the formatted text. The section “Text Formatting” discusses the
formatting in detail.

Parameters:
textID String that identifies the message.

245
args List of message arguments used for formatting. Could be
NULLSP if no arguments are provided.
text Contains the translated and formatted text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getFormattedTextByIntId ( in SCAInt32


textID,
in SCAAnySequence args,
out SCAUString text )

Same as getFormattedText(), but instead of string the input is an


integer textID.

See also:
getFormattedText
Parameters:
textID Integer value that identifies which message should be
looked up.
args List of message arguments used for formatting. Could be
NULLSP if no arguments are provided.
text Contains the translated and formatted text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getFormattedModuleText ( in SCAString


moduleName,
in SCAString itemName,
in GuiMessageKind kind,
in SCAAnySequence args,
out SCAUString text )

Gets the formatted GUI text from <dialog> or <module> sections of the
message file. The section “Text Formatting” discusses the formatting in
detail.

Parameters:
moduleName Module name ( dialog name).
itemName Item name (widget name).
kind Sub-item type (GMK_Text, GMK_Help).
args List of message arguments used for formatting. Could
be NULLSP if no arguments are provided.
text Contains the translated and formatted text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getModuleTextByComment ( in SCAString


moduleName,
in SCAString commentName,
in SCAString itemName,
in GuiMessageKind kind,
out SCA::SCAUString text )

246
Gets simple GUI text from <dialog> or <module> sections of the message
file. Uses the combination of comment and id as the key. The key is of
the format (comment_id)

Parameters:
moduleName Module name ( dialog name).
commentName String that identifies the widget.
itemName Item name (widget name).
kind Sub-item type (GMK_Text, GMK_Help).
text Contains the translated and formatted text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getFormattedModuleTextByComment ( in SCAString


moduleName,
in SCAString commentName,
in SCAString itemName,
in GuiMessageKind kind,
in SCAAnySequence args,
out SCAUString text )

Gets formatted GUI text from <dialog> or <module> sections of the


message file. Uses the combination of comment and id as the key. The
key is of the format (comment_id). The section “Text Formatting”
discusses the formatting in detail.

Parameters:
moduleName Module name ( dialog name).
commentName String that identifies the widget.
itemName Name of the widget for which contains the text that
is searched.
kind Sub-item type (GMK_Text, GMK_Help).
args List of message arguments used for formatting. Could
be NULLSP if no arguments are provided.
text Contains the translated and formatted text on return.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult setFallbackTable ( in
SCAITextTranslationTable table )

This method sets the fallback translation table. The fallback table is
searched if a text ID is not found in this table. When the table is
created by the SCAITextTranslationFactory, the fall back table is set
to the default translation table.

Parameters:
table Fallback table.
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult setFixedLocale ( in SCAString locale )

247
Sets a fixed locale for the translation table which overrides the
locale set in the SCAITextTranslationSettings instance. Passing an
empty string resets the override and re-attaches the locale to the
global SCAITextTranslationSettings instance.

Parameters:
locale Locale string.
Returns:
Returns SCASuccess on success, else returns an error.

248
Using the Text Translation Service
The following C++ code snippets demonstrate how the text translation
service should be used. The intention is to demonstrate the usage of
methods. It uses the sample translation tables presented earlier in
this chapter. The real code should contain proper exception and
SCAResult handling.
SCA::SCAResult result;

// Get an instance of the SCAITextTranslationFactory


SCA::Framework::SCAITextTranslationFactory spFactory;
spFactory = getService("[Link]","");
if (spFactory == SCA::NULLSP){
std::cerr << "ERROR:Unable to load the TextTranslation service"
<< std::endl;
return SCA::SCAError;
}

// Set the Locale to German “de”


SCA::Framework::SCAITextTranslationSettings spSettings;
result = spFactory->getTextTranslationSettings(spSettings);
if (![Link]()){
std::cout << "Could not get SCAITextTranslationSettings"
<< std::endl;
return SCA::SCAError;
}
result = spSettings->setLocale(SCA::Framework::LC_All,"de");

// Create a text translation table by loading the messages from the


file
// $SCA_RESOURCE_DIR/TranslationSample_de.xml
SCA::Framework::SCAITextTranslationTable spTable;
result = spFactory-
>createTextTranslationTable(L"TranslationSample",spTable);

// Get the simple text without any place holders


SCA::SCAUString text;
result = spTable->getText("help",text);
std::printf("%ls\n",text.c_str());

// Get the text formatted using the supplied arguments for the place
holders
SCAAnySequence args;
args.push_back(SCA::SCAAny(SCA::SCAString("TestString")));
args.push_back(SCA::SCAAny(SCA::SCAInt32(1234)));
args.push_back(SCA::SCAAny(SCA::SCAReal32(123.456)));
result = spTable->getFormattedText("formatTest",args,text);
std::printf("%ls\n",text.c_str());

// Get Module text

249
result = spTable->getModuleText("mod_test","m1",
SCA::Framework::GMK_Text,text);
std::printf("%ls\n",text.c_str());
result = spTable->getModuleText("DeformPlotMetaDataFrame",
"Qt Linguist context",
SCA::Framework::GMK_Text,text);
std::printf("%ls\n",text.c_str());

Language Support Files


The text translation service uses several xml files to store language
and country settings. These files must be located in the applications
resource directory. At startup [Link] and
[Link] files are parsed to load the settings. Since
these settings are global they are read only once and are available to
all instances of the TextTranslationSettings object. The country map is
only required for Windows.
[Link]

<?xml version="1.0" encoding="utf-8"?>


<!-- for list of language/country strings, see
[Link] us/library/cdax410z(VS.71).aspx -->
<LanguagesMap version="1.0">
<language code="zh" defaultCountry="cn">chinese;
chinese-simplified;chs;chinese-traditional;cht</language>
<language code="cs" defaultCountry="cz">csy;czech</language>
<language code="da" defaultCountry="dk">dan;danish</language>
<language code="nl" defaultCountry="nl">dutch;nld;belgian;
dutch-belgian;nlb</language>
<language code="en" defaultCountry="us">english;australian;ena;
english-aus;canadian;enc;english-can;english-nz;enz;eng;
english-uk;uk;american;american english;american-english;
english-american;english-us;english-usa;enu;us;usa</language>
<language code="fi" defaultCountry="fi">fin;finnish</language>
<language code="fr" defaultCountry="fr">fra;french;frb;
french-belgian;frc;french-canadian;french-swiss;frs</language>
<language code="de" defaultCountry="de">deu;german;dea;
german-austrian;des;german-swiss;swiss</language>
<language code="el" defaultCountry="gr">ell;greek</language>
<language code="hu" defaultCountry="hu">hun;hungarian</language>
<language code="is" defaultCountry="is">icelandic;isl</language>
<language code="it" defaultCountry="it">ita;italian;
italian-swiss;its</language>
<language code="ja" defaultCountry="jp">japanese;jpn</language>
<language code="ko" defaultCountry="kr">kor;korean</language>
<language code="no" defaultCountry="no">norwegian</language>
<language code="nb" defaultCountry="no">nor;
norwegian-bokmal</language>
<language code="nn" defaultCountry="no">non;
norwegian-nynorsk</language>

250
<language code="pl" defaultCountry="pl">plk;polish</language>
<language code="pt" defaultCountry="pt">portuguese;ptg;
portuguese-brazil;ptb</language>
<language code="ru" defaultCountry="ru">rus;russian</language>
<language code="sk" defaultCountry="sk">sky;slovak</language>
<language code="es" defaultCountry="es">esp;spanish;esm;
spanish-mexican;esn;spanish-modern</language>
<language code="sv" defaultCountry="se">sve;swedish</language>
<language code="tr" defaultCountry="tr">trk;turkish</language>
</LanguagesMap>

[Link]

<?xml version="1.0" encoding="utf-8"?>


<!-- for list of language/country strings, see
[Link] -->
<CountriesMap version="1.0">
<country code="au">aus;australia</country>
<country code="at">aut;austria</country>
<country code="be">bel;belgium</country>
<country code="br">bra;brazil</country>
<country code="ca">can;canada</country>
<country code="cn">china;chn;pr china;pr-china</country>
<country code="cz">cze;czech</country>
<country code="dk">dnk;denmark</country>
<country code="fi">fin;finland</country>
<country code="fr">fra;france</country>
<country code="de">deu;germany</country>
<country code="gr">grc;greece</country>
<country code="hk">hkg;hong kong;hong-kong</country>
<country code="hu">hun;hungary</country>
<country code="is">iceland;isl</country>
<country code="ie">irl;ireland</country>
<country code="it">ita;italy</country>
<country code="jp">jpn;japan</country>
<country code="kr">kor;korea</country>
<country code="mx">mex;mexico</country>
<country code="nl">nld;holland;netherlands</country>
<country code="nz">nzl;new zealand;new-zealand;nz</country>
<country code="no">nor;norway</country>
<country code="pl">pol;poland</country>
<country code="pt">prt;portugal</country>
<country code="ru">rus;russia</country>
<country code="sg">sgp;singapore</country>
<country code="sk">svk;slovak</country>
<country code="es">esp;spain</country>
<country code="se">swe;sweden</country>
<country code="ch">che;switzerland</country>
<country code="tw">twn;taiwan</country>

251
<country code="tr">Turkey tur;turkey</country>
<country code="gb">gbr;britain;england;great britain;uk;united
kingdom;united-kingdom</country>
<country code="us">usa;america;united states;united-
states;us</country>
</CountriesMap>

252
SCA Framework Messages and Internationalization

SCA Framework User Document

Chapter 10

Error Handling

253
SCA Framework Error Handling

10. Error Handling


10.1. Introduction
Error handling is a crucial part of any programming project. SCA supports the two most
common forms for handling errors.

The interface methods throw exceptions.


The interface methods return error codes.

Both methods have their own advantages over the other and application developers should
choose the one that is most appropriate to their application.

Exceptions tend to be easier to implement than error codes. Consider the example where
routine A calls B, B calls C and C calls D and then D produces an error code. In this case C
has to check the code, return its own code, which would be checked by B which would return
its own code which would finally be checked by A. Whereas with exceptions, if D throws the
exception, then a simple try/catch block in A can catch it and no special code is required in
any of the intermediate routines in the call stack. Furthermore, many programmers get lazy
and do not always do the appropriate checking of error codes. With error codes this can be
disastrous because the error is lost and the caller will continue as if nothing happened. But
with exceptions, the errors will always be triggered. If the programmer does not include the
appropriate try/catch block for the exception, it will still be propagated up to the next routine
in the call stack until someone eventually catches it.

On the other hand, error codes tend to be more efficient then exceptions. To properly handle
exceptions, the compilers need to generate special support code in every routine to correctly
process them. This tends to make the generated code larger and adds overhead. Also, error
codes provide for more sophisticated processing of messages. This includes more flexible
formatting of error messages including parameter substitution and the ability to
internationalize the messages to any language supported by the application.

Exceptions and error codes are two different general error handling approach. The mixing of
the two can lead to confusion and should be avoided. The following conventions are
recommended for best practice.

If an interface method defines a raises clause for any explicit exceptions, then the method
should not use a SCAResult or any other value as an error indication.
If an interface method returns a SCAResult or any other value as an error indication, it should
not have a raises clause and it should not throw any exceptions.
Throwing user-defined exceptions is preferred over the throwing of any of the SCA provided
base exceptions.
Normally the same error handling method should be chosen for all interfaces implemented by
a given service.

Even if the SCAResult form of error handling is chosen, it is important to realize that calls to
SCA interface methods may still throw SCASystemException exceptions. This may occur if

254
SCA Framework Error Handling

the call crosses languages boundaries or accesses remote components. In this case the SCA
language bridges may need to report an error when trying to marshal the call. This is generally
not a problem because these types of errors are usually catastrophic in nature and there is no
recovery logic available. As a result the individual routines do not need to catch these
SCASystemException exceptions. Instead they can be caught in a global try/catch block at
the top of the applications call stack so the application can terminate cleanly.

Both SCA exceptions and the SCAResult forms of error handling described in this chapter
are available in all of the languages supported by the SCA framework. The exact syntax of
using them vary from language to language but their general functionality is similar. As a
result this chapter will only show examples using the C++ language. You should consult the
IDL Mapping chapters of this manual for the complete details of using these features in each
of the supported languages.

10.2. Using SCA Exceptions for Error Handling


The SCA exception processing is available in each of the languages supported by the SCA
framework including the Python scripting language. Exceptions can be thrown in one
language and caught in any of the other supported languages. The SCA language bridges will
catch the exception in the language it is thrown in, convert all of the data contained in it and
then rethrow the exception in the language of the caller. This entire process is transparent to
both the caller or the routine where the exception was thrown.

SCA exceptions are types that are defined by the user through the SCA IDL language. See the
IDL Language chapter of this manual for the complete details on how they are defined.

Three exceptions types, SCA::SCAException, SCA::SCASystemException, and


SCA::SCAUserException, are predefined in the SCA Framework. All user defined
exceptions must inherit SCA::SCAUserException or another user-defined exception. Only
single inheritance is allowed.

In addition to the definition of the exceptions, the IDL definition of interface methods may
have an optional raises clause. The raises clause defines what type of exceptions the method
may throw. The use of the raises clause in the IDL interface definitions is important. While
the raises information is not used by all languages when making intra language calls it is
required by some. For example C++ does not use the information but Java requires it. Also
when calls to SCA interface methods cross language boundaries, the various SCA language
bridges are responsible for marshalling the data. These bridges will not allow exceptions to
pass unless they have been specified in IDL. If a method throws an exception that is not
specified in the IDL definition, it will be converted to a SCASystemException exception and
some valuable information it contains may be lost. The section on exception propagation rules
later in this section discusses in detail the rules used by the language bridges to propagate
exceptions. Since the IDL definitions are language neutral and you never know which
language they be implemented in you should always include the raises information. Also you
can never be sure when a call to an interface may have to cross language boundaries.

255
SCA Framework Error Handling

An important thing to notice about SCA exceptions is they only contain data. The IDL
definition does not provide for any implementation to be included as part of the definition. The
main reason for this is that exceptions may need to be marshaled between different languages
and it is extremely difficult to marshal implementation. If you wish to attach implementation
to a SCA exception there are several ways this can be done. The easiest way is to create your
own custom class that inherits from the IDL defined SCA exception class. The disadvantage
of this approach is the implementation in your custom class and any data it contains will be
lost if the exception has to be marshaled to a different language. The second approach is to
include a SCA interface member in the definition of the exception which contains the
implementation you wish to associate with the exception. This interface will be correctly
marshaled between different language types. The disadvantage of this approach is that each
call to this interface will itself need to be marshaled back to the language that it was originally
implemented in. If the number of calls is small this is not a problem, but there can be
performance penalties if a large number of calls are made.

The following example IDL shows the definition of a user exception, ReaderException, and
an interface method, readModel, which can throw it. These definitions will be used for the
examples in rest of this section.

IDL
#ifndef SDK_ERRORHANDLING_EXCEPTIONS_FILEREADER_IDL_INCLUDED
#define SDK_ERRORHANDLING_EXCEPTIONS_FILEREADER_IDL_INCLUDED

#include "SCA/[Link]"

module SDK { module ErrorHandling { module Exceptions {

exception ReaderException : SCA::SCAUserException


{
SCA::SCAString modelName;
};

interface SCAIReader : SCA::SCAIService


{
void readModel( in SCA::SCAString name ) raises(ReaderException);
};

}; }; };

#endif

256
SCA Framework Error Handling

SCA Exception Hierarchy


The SCA exception hierarchy is shown below. The ultimate base of all SCA exceptions is
SCAException. The SCASystemException is a special exception that is mainly used by the
SCA framework to handle internal errors. The SCAUserException inherits SCAException
and it is the base for all user defined exceptions, directly or indirectly.

SCA Framework provided Exceptions


Three exceptions types, SCA::SCAException, SCA::SCASystemException, and
SCA::SCAUserException, are predefined in the SCA Framework.
The SCAException Exception
The SCAException is the base for all exceptions. It has the following IDL definitions.

IDL
module SCA {
exception SCAException
{
SCAString text;
};
};

This exception contains a SCAString value that the user can set to describe the nature of the
exception. Each language mapping for the SCAException provides a way to set and fetch the
value of this string. Since SCAException is the base class for all SCA exceptions, many of
the methods it contains are available to all SCA exceptions. The individual language mapping
for the SCAException may also contain other information required by the SCA Framework
but these should generally not be used for other purposes.

257
SCA Framework Error Handling

The SCASystemException Exception


SCASystemException is used to handle internal SCA framework errors that cannot be
conveniently reported in any other manner. Even if a method does not have a raises clause in
its definition, the SCASystemException may always be thrown. The IDL definition of the
SCASystemException is as follows.

IDL
module SCA {
exception SCASystemException : SCAException {
SCAInt32 id;
};
};

This exception contains an integer error value that is used to contain one of the following SCA
system errors.

SCA System Error ID SCA System Error Description


2000000010 Unknown error
2000000020 Invalid interface
2000000030 Invalid method
2000000040 Invalid Parameter(s)
2000000050 Undefined type code
2000000060 Communication failure
2000000070 Data conversion error
2000000080 Memory error
2000000090 Implementation not available
2000000100 Invalid exception thrown
2000000110 Error reading type codes
2000000120 Error in CORBA Rpc bridge
2000000130 Error in C++ bridge
2000000140 C++ interface cast failed
2000000150 XML TypeCode processing error
2000000160 Error in python bridge
2000000170 Marshalling error
2000000180 SCABinary processing error
2000000190 Internal Error
2000000200 Error in Java bridge
2000000210 SCAAny marshalling error
2000000220 SCA Kernel initialization error
2000000230 Invalid global service provider
2000000240 SCA Framework configuration error
2000000250 Error in .NET bridge
2000000260 SCADynAny error
2000000270 Corruption in SCASequence memory
2000000280 getSCAService error
2000000290 Error terminating the SCA Kernel
2000000300 Error initializing embedded component
2000000310 Error terminating embedded component
2000000320 Error parsing service version table

258
SCA Framework Error Handling

2000000330 SCA Kernel authentication failed


2000000340 Illegal ComponentManager implementation
2000000350 Operation requires the SCA Kernel to be up
2000000360 Invalid call to KernelBroker
2000000370 Exception thrown by
DotNetSubComponentManater
2000000380 The call to publish a Java service failed
2000000390 Kernel authentication failed loading a
Java service
2000000400 The call to load a Java component failed
2000000500 The call to get a Java service failed
2000000600 An internal error occurred in
JavaSubComponentManager
2000000700 Event Manager internal error
2000000701 Event Manager domain already exists error
2000000702 Event Manager domain does not exist
2000000800 Error parsing Error Policy Table
2000000801 Signal replaced with SCASystemException
2000000802 Error initializing the Error Manager
2000000803 .NET Exception replaced with
SCASystemException

Most of these errors are generated during the marshalling of data through SCA language
bridges. Many are unexpected problems which should never occur but there are others that can
easily occur because of the nature of some of the SCA language mappings. For example the
Python language only supports 32 and 64 bit integers. As a result types like the SCAInt16 are
mapped to a 32 bit integer. When an interface method is called that has a SCAInt16
argument, the value in the 32 bit Python integer is checked to make sure it will fit in the
required SCA type. If it is too large then a SCASystemException will be generated with one
of the above codes. It is the responsibility of the Python code to make sure that this condition
never happens.

For the complete definitions of these errors see the SCA/SystemError.h header file delivered
with the SCA Framework.
The SCAUserException Exception
The SCAUserException is the (direct or indirect) base for all user defined exceptions. It has
the following IDL definition.

IDL
module SCA {
exception SCAUserException: SCAException
{
};
};

This exception does not contain any data member. Its purpose is to only define the base class
for user defined exceptions.

259
SCA Framework Error Handling

Exception API
The syntax for using SCA exceptions and the API they provide is different for each supported
language. The following example code shows how an instance of the ReaderException can
be created and thrown in C++.

C++
ReaderException except;
[Link] = name;
[Link]("The requested model \""+name+
"\" could not be located.");
[Link]();

Notice that the actual exception is thrown using the throwit method it provides and not using
the normal C++ throw statement. This is an important rule which is discussed in detail in the
IDL to C++ Mapping chapter of this manual.

The exception can be caught and processed like this.

try {
spReader->readModel("[Link]");
} catch (SCAException& e) {
cout << [Link]() << endl;
}

For language specific exception APIs, please refer to the respective Language Mapping
chapters of this manual.
Exception Propagation Rules
The exact rules covering the throwing and catching of exception vary depending on whether
the thrower and the catcher are coded in the same language or in different languages.
Inter Language Propagation Rules
An IDL exception thrown from a callee can be caught by the caller even when the callee and
the caller are coded in different languages. In the case of inter language calls, the exceptions
must be marshaled through a SCA language bridge. The following rules apply in this case.

Exception types that are defined in the raises clause always pass through the language bridges.

Exception that inherits (directly or indirectly) from an exception in the raises clause always
passes through the language bridges.

Users may define their own non SCA exception classes that inherit from the SCA exception
classes. In this case the SCA exception that is inherited from is the one that determines if it
will pass through the language bridges. When these exceptions are thrown, only the data
defined in SCA exception definitions will be passed. Any data in the non SCA exception class
will be lost.

The SCASystemException always pass through the language bridges.

260
SCA Framework Error Handling

All other exceptions are blocked by the language bridge and a SCASystemException is
thrown instead. In this case any data contained in the original exception will be lost.

For an example of these rules, consider the following exception hierarchy.

IDL
exception SCAException { };
exception SCAUserException : SCAException { };
exception TestExcept1 : SCAUserException { };
exception TestExcept2 : TestExcept1 { };
exception TestExceptX: SCAUserException { };

The following table shows which combination of exceptions specified on the raises clause in
the IDL and the actual exception thrown are allowed to pass through the SCA language
bridges. The exceptions that are not allowed to pass will be converted to a
SCASystemException.

Raises clause Thrown Does bridge pass


SCAUserException TestException1 Yes
SCAUserException TestException2 Yes
SCAUserException TextExceptionX Yes
SCAUserException None SCA Exception No
TestException1 TestException1 Yes
TestException1 TestException2 Yes
TestException1 TextExceptionX No
TestException1 None SCA Exception No
TestException2 TestException1 No
TestException2 TestException2 Yes
TestException2 TextExceptionX No
TestException2 None SCA Exception No

Intra Language Propogation Rules


Normally when making interface calls between a caller and callee written in the same
language, the SCA framework is not involved. As a result the rules for using exceptions in this
case are the normal rules that apply to the language being used.
Exception Catching Rules
The rules covering which exceptions will be caught by which catch statement is completely a
function of the language you are catching the exception in. It does not matter which language
the exception was thrown in. This is because when an exception is marshaled through a SCA
language bridge it will be rethrown by the bridge in the language of the caller. The exception
that is rethrown is either the original exception thrown if it passes the propagation rules
discussed above or else a SCASystemException. In either case it is now a native exception in
the language of the caller and the rules for this language are used.

261
SCA Framework Error Handling

Most languages have a similar set of rules governing which exceptions will be caught by
which catch statement. Normally, a catch statement, or whatever the equivalent statement is in
the language you are using, will catch an exception that is the same as the one thrown or if it is
a base class of the one thrown. Using the same exception hierarchy that was used above the
following table shows how these rules typically work.

Catch Statement Exception Thrown Will it be Caught


SCAUserException TestException1 Yes
SCAUserException TestException2 Yes
SCAUserException TextExceptionX Yes
TestException1 TestException1 Yes
TestException1 TestException2 Yes
TestException1 TextExceptionX No
TestException2 TestException1 No
TestException2 TestException2 Yes
TestException2 TextExceptionX No
TestExceptionX TestException1 No
TestExceptionX TestException2 No
TestExceptionX TextExceptionX Yes

Recommended usage of SCA Exceptions


There is nothing special about SCA exceptions and the best practice usage of them is the same
as using normal exception processing. But there are a few rules that should be followed to
better utilize the infrastructure provided by the SCA framework.

Always throw user-defined exceptions. You should never directly throw a SCAException or
SCASystemException.

When you throw an SCA user-defined exception, always define the basic text field that is
provided by the SCAException. This way there will be some information about the exception
regardless of the exception class that is actually caught.

In your code, only add catch statements for exceptions that you expect to catch and have some
special processing for.

Always have a catch block for the SCAException class somewhere in the calling tree. Since
all SCA exceptions inherit from this one, this catch block will catch any SCA exception that
was not explicitly caught by any other catch block. The text field of this exception can then be
used to provide some useful information.
Complete Exception Error Handling Example for a SCA Service
The following is the complete implementation of an example FileReader service that shows
the use of SCA exceptions for error handling. This service implements the SCAIReader
interface.

262
SCA Framework Error Handling

The IDL for this example was defined earlier in this chapter. The SDL and CDL files for this
example are as follows.

SDL
#ifndef FILEREADER_SDL_INCLUDED
#define FILEREADER_SDL_INCLUDED

#include "SDK/ErrorHandling/Exceptions/[Link]"

module SDK { module ErrorHandling { module Exceptions {

service [Link]
{
interface SCAIReader;
};

}; }; };

#endif

CDL
#ifndef FILEREADER_CDL_INCLUDED
#define FILEREADER_CDL_INCLUDED

#include "[Link]"

component [Link]
{
service FileReader;
};

#endif

The SCAIReader interface contains a single method, readModel that must be implemented.
Only the portion of the implementation that shows the error handling functionality is shown in
this example. The rest of the code is omitted to keep the code sample small. The
implementation files for the FileReader service follow.

FileReader.h
#ifndef SDK_ERRORHANDLING_EXCEPTIONS_FILEREADER_H_INCLUDED
#define SDK_ERRORHANDLING_EXCEPTIONS_FILEREADER_H_INCLUDED

#include "FileReaderBase.h"

namespace SDK { namespace ErrorHandling { namespace Exceptions {

class FileReader : public FileReaderBase


{
public:

// Constructor and Destructor


FileReader(SCAIFileReaderFactoryAccess* factoryAccess);
virtual ~FileReader();

263
SCA Framework Error Handling

// Methods for interface [Link]


virtual SCA::SCAVoid readModel(const SCA::SCAString name);
};

} } }

#endif

[Link]
#include "FileReader.h"

namespace SDK { namespace ErrorHandling { namespace Exceptions {

// Constructor
FileReader::FileReader(SCAIFileReaderFactoryAccess* factoryAccess)
: FileReaderBase(factoryAccess)
{
}

// Destructor
FileReader::~FileReader()
{
}

SCA::SCAVoid FileReader::readModel(const SCA::SCAString name)


{
bool error;

// Locate the model


. . . .

// Return error if model could not be located


if ( error ) {
ReaderException except;
[Link] = name;
[Link]("The requested model \""+name+
"\" could not be located.");
[Link]();
}

// Process the model


. . . .

// Return error processing the model


if ( error ) {
ReaderException except;
[Link] = name;
[Link]("An error was encountered reading model \""+
name+"\".");
[Link]();
}

// Return
return;
}

264
SCA Framework Error Handling

} } }

The example client application that uses this version of the FileReader service is shown next.

[Link]
#include <iostream>
using namespace std;
#include <SCA/SCAKernel.h>
#include "SCA/Framework/SCAIMessageDispatcher.h"
#include <SDK/ErrorHandling/Exceptions/SCAIReader.h>

using namespace SCA;


using namespace SDK::ErrorHandling::Exceptions;

int main()
{
try {
cout << "Test using exceptions for error processing" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

// Load the FileReader service


SCAString svcName = "[Link]";
SCAIReader spReader = getSCAService(svcName);

// Read the model


try {
spReader->readModel("[Link]");
} catch (SCAException& e) {
cout << [Link]() << endl;
}

// Clean up
spReader = NULLSP;

// Terminate the SCA Kernel


terminateSCAKernel();

} catch (SCAException& e) {
cout << [Link]() << endl;
}
return 0;
}

10.3. Using SCAResult for Error Handling


Introduction
If you choose to use the error handling method where interface methods return error codes, the
SCA framework provides the SCAResult type. A SCAResult instance provides information
about what happened within the interface method. This includes whether the method was
successful or failed and optional information that is used to generate an appropriate error
message. The SCAResult data type is used in conjunction with the MessageDispatcher

265
SCA Framework Error Handling

service to format the messages in the desired language and optionally to dispatch them. In this
section, examples will show how the SCAResult data type and the MessageDispatcher
service can be used to process errors.

For this discussion we will use the same FileReader service that was previously used to
demonstrate the use of SCA exceptions for error handling. Only in this case we will modify
the IDL so the readModel method now returns a SCAResult value instead of throwing an
exception.

IDL
#ifndef SDK_ERRORHANDLING_SCARESULT_FILEREADER_IDL_INCLUDED
#define SDK_ERRORHANDLING_SCARESULT_FILEREADER_IDL_INCLUDED

#include "SCA/[Link]"

module SDK { module ErrorHandling { module SCAResult {

// Error codes
const SCA::SCAInt32 MODEL_LOCATE_ERR = 1;
const SCA::SCAInt32 MODEL_READ_ERR = 2;

// Message ids
const SCA::SCAInt32 MODEL_LOCATE_MSG = 101;
const SCA::SCAInt32 MODEL_READ_MSG = 102;

// Message severity values


enum MSG_SeverityType {
SDK_INFORMATION,
SDK_WARNING,
SDK_ERROR
};

interface SCAIReader : SCA::SCAIService


{
SCA::SCAResult readModel( in SCA::SCAString name );
};

}; }; };

#endif

The SCAResult data contents


The SCAResult type is used to return error information from calls to interface methods. It
contains the following information.

Error code – The meaning of the error code values are defined by the service you are using.
There may be a unique set of error codes for each method or a single set for the entire service
or component. You should consult the documentation of the service you are using for
definitions of the error codes that it may return.

266
SCA Framework Error Handling

Message table ID – The message table ID is a unique value that is assigned by the
MessageDispatcher service when a message table is registered. In order to use a message in a
message table, the message table must be first registered with the MessageDispatcher service.
This registration is the responsibility of the service that will be returning SCAResult values
that reference the message table.

Message number – Message number in the message table referenced by the message table ID.

Message parameters – Optional values for parameters that will be used to format the requested
messages.

The use of the message information in the SCAResult is optional. When used, the messages
in SCAResult values may also include parameter values that will be substituted during the
formatting of the message. The following types of parameters are supported in a SCAResult.

SCA Type
SCAInt8
SCAUInt8
SCAInt16
SCAUInt16
SCAInt32
SCAUInt32
SCAInt64
SCAUInt64
SCAReal32
SCAReal64
SCAChar
SCAUChar
SCAString
SCAUString
SCABool

You should consult the appropriate IDL mapping chapter for the language you are using for
the exact syntax for adding parameter values to a SCAResult instance.
Overview of using the SCAResult for Error Handling
The general error processing steps for using the SCAResult are as follows.

The client application loads the SCA FileReader service.


The constructor for the service instance uses the MessageDispatch to register its message
table with the framework and saves the message table ID that is returned.
The client calls the readModel interface method.
The readModel method tries to read the model but encounters an error. It formats a
SCAResult value and returns it to the caller. The SCAResult value includes an error code
value, the message table ID, the message number and any optional parameter values.
The client checks the error code in the SCAResult value to determine if there is an error.

267
SCA Framework Error Handling

The client uses the MessageDispatcher to format the message contained in the SCAResult
value. The formatted message is either dispatched to any registered message listeners or
returned to the client.
Registering Message Tables
The definition of messages that are reference by the SCAResult values must be defined in a
SCA XML message table. For a complete description of the format of these message tables
see the Messages and Internationalization chapter of this manual. For our test service we have
defined a simple message table with several messages. The following is the English version of
the message table.

FileReaderMsgTable_en.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!--
Copyright (c) 2009, [Link] Corporation. All Rights Reserved.
MSC PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<sim_office_resources version="1.0" xml:lang="en"
comment="Message Table for FileReader Service">
<text id="101" comment="MODEL_LOCATE_MSG" >
The requested model "%1:%s" could not be located.
</text>
<text id="102" comment="MODEL_READ_MSG" >
An error was encountered reading model "%1:%s:".
</text>
</sim_office_resources>

We also provide a German version of the messages.

FileReaderMsgTable_de.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!--
Copyright (c) 2009, [Link] Corporation. All Rights Reserved.
MSC PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<sim_office_resources version="1.0" xml:lang="en"
comment="Message Table for FileReader Service">
<text id="101" comment="MODEL_LOCATE_MSG" >
Das angeforderte Modell "%1:%s" konnte nicht gefunden werden.
</text>
<text id="102" comment="MODEL_READ_MSG" >
Beim Einlesen des Modells "%1:%s:" trat ein Fehler auf.
</text>
</sim_office_resources>

If you look at the IDL for FileReader example earlier in this chapter, you will see a set of IDL
constants were also defined for each message. These can be used when creating SCAResult
values instead of using hardcoded values. The use of these constants is a recommended
practice because it provides a consistent location to document the messages and makes
maintenance easier.

IDL

268
SCA Framework Error Handling

// Message ids
const SCAInt32 MODEL_LOCATE_MSG = 101;
const SCAInt32 MODEL_READ_MSG = 102;

In order to use a message table, the table must be first registered with the MessageDispatcher
service. Normally a service will do this registration in its constructor and save the message
table IDL for later use. When registering the message table you use the portion of the filename
for the table which does not include the language information. For our example, the name
used for the registration would be FileReaderMsgTable.

The following code shows how the the message table is registered.

C++
#include "SCA/Framework/SCAIMsgTableManager.h"

// Register our message table


SCA::Framework::SCAIMsgTableManager spManager;
spManager = getService("[Link]");
spManager->addTable(L"FileReaderMsgTable",m_msgTableID);

In this example code the message table ID returned is m_msgTableID which should be saved
for later use when it is necessary to format a SCAResult value.
Formatting a SCAResult value
There are a number of different ways that the SCAResult can be used to return error
information.

The SCAResult may only contain a success or failure indications


The SCAResult may only contain an error code value
The SCAResult may contain both an error code value and the information to format a
message.

There may be times when specific error code values are not required. Instead it is only
necessary to indicate if the method call succeeded or failed. In this case you can use one of the
two predefined SCAResult values provided by the SCA framework.

SCA::SCASuccess Error code = 0


SCA::SCAError Error Code = 0X7FFFFFFF

If the readModel method in our example only needed to return a generic error indication it
could use the predefined SCAError value as follows.

C++
return SCAError;

Normally, this is not the ideal solution because it does not provide any details to the caller
about what the error actual was. As a result it is usually a better solution if you at least return
an error code value that represents the error that occurred.

269
SCA Framework Error Handling

If you look at the example IDL again, you will notice that a set of constant values were also
defined for the error codes that can be returned. Depending on how you have set up your error
code values and message IDs, you may choose to use a single set of constant values for both.

// Error codes
const SCAInt32 MODEL_LOCATE_ERR = 1;
const SCAInt32 MODEL_READ_ERR = 2;

The use of these constants is a recommended practice because it provides a consistent place
where the possible error code values can be documented for the users of the service.
Additionally, the use of IDL defined constants reduces maintenance of the code. If you need
to change error values they only need to be changed in the IDL file and not in every
implementation and client file that uses them.

The readModel interface routine could now create a SCAResult instance containing only an
error code if that was appropriate. In this example we are using the IDL defined constants to
indicate the error code value.

C++
SCAResult rstat = SCAResult(MODEL_READ_ERR);
return rstat;

Normally, it is more desirable to also include message information that your callers can use to
format and display a message which described the details of the error. The following code
adds a message to the SCAResult value. The message requires one parameter which is the
name of the model that cannot be read.

C++
SCAResult rstat;
rstat = SCAResult(MODEL_READ_ERR,m_msgTableID,MODEL_READ_MSG);
[Link](name);
return rstat;

If the readModel method did not encounter any errors, then it should return the predefined
SCASuccess value to indicate that the operation was successful.

C++
return SCASuccess;

The exact syntax for using the SCAResult data type is a function of the language you are
using. Although the basic concepts are the same in all of the languages the exact syntaxes are a
bit different. For complete details you should consult the IDL mapping chapter in this manual
for your language.
Complete SCAResult Error Handling Example for a SCA Service
The following is the complete implementation of the example FileReader service which now
uses SCAResult values for error handling.

270
SCA Framework Error Handling

The IDL for this example was defined earlier in this chapter. The SDL and CDL files for this
example follow.

SDL
#ifndef FILEREADER_SDL_INCLUDED
#define FILEREADER_SDL_INCLUDED

#include "SDK/ErrorHandling/SCAResult/[Link]"

module SDK { module ErrorHandling { module SCAResult {

service [Link]
{
interface SCAIReader;
};

}; }; };

#endif

CDL
#ifndef FILEREADER_CDL_INCLUDED
#define FILEREADER_CDL_INCLUDED

#include "[Link]"

component [Link]
{
service FileReader;
};

#endif

The new versions of the implementation files for the service are as follows. Once again only
the error processing logic of the readModel method has been included.

FileReader.h
#ifndef SDK_ERRORHANDLING_SCARESULT_FILEREADER_H_INCLUDED
#define SDK_ERRORHANDLING_SCARESULT_FILEREADER_H_INCLUDED

#include "FileReaderBase.h"

namespace SDK { namespace ErrorHandling { namespace SCAResult {

class FileReader : public FileReaderBase


{
public:

// Constructor and Destructor


FileReader(SCAIFileReaderFactoryAccess* factoryAccess);
virtual ~FileReader();

// Methods for interface [Link]

271
SCA Framework Error Handling

virtual SCA::SCAResult readModel(const SCA::SCAString name);

private:
// Message table ID assigned by the MessageDispatcher
SCA::SCAInt32 m_msgTableID;
};

} } }

#endif

[Link]
#include "FileReader.h"
#include "SCA/Framework/SCAIMsgTableManager.h"
#include "SDK/ErrorHandling/SCAResult/FileReaderTypes.h"

namespace SDK { namespace ErrorHandling { namespace SCAResult {

// Constructor
FileReader::FileReader(SCAIFileReaderFactoryAccess* factoryAccess)
: FileReaderBase(factoryAccess)
{
// Register our message table
SCA::Framework::SCAIMsgTableManager spManager;
spManager = getService("[Link]");
spManager->addTable(L"FileReaderMsgTable",m_msgTableID);
}

// Destructor
FileReader::~FileReader()
{
}

SCA::SCAResult FileReader::readModel(const SCA::SCAString name)


{
SCA::SCAResult rstat;
bool error;

// Locate the model


. . . .

// Return error if model could not be located


if ( error ) {
rstat = SCA::SCAResult(MODEL_LOCATE_ERR,
m_msgTableID,
MODEL_LOCATE_MSG);
[Link](name);
return rstat;
}

// Process the model


. . . .

// Return error processing the model


if ( error ) {
rstat = SCA::SCAResult(MODEL_READ_ERR,

272
SCA Framework Error Handling

m_msgTableID,
MODEL_READ_MSG);
[Link](name);
return rstat;
}

// Successful return
return SCA::SCASuccess;
}

} } }

Use of SCAResult values in the client


Up until this point, we have discussed how the SCAResult values are created and returned
from a SCA service. Now we will discuss how the values are used by the clients of the
service.

The procedure for using the SCAResult value depends on the type of error and message
values it contains. For example if a simple SCASuccess or SCAError value is returned all
that is required is to check the error code as follows.

C++
if ( rstat ) {
cout << "Error encountered" << endl;
return 1;
}
if ( ![Link]() ) {
cout << "Error encountered" << endl;
return 1;
}

But the disadvantage of this approach is there is no indication of what the error may have
been. To add some additional information, the interface method may return different error
code values which may be checked.

C++
if ( rstat == MODEL_LOCATE_ERR ) {
cout << "Error encountered locating the model" << endl;
return 1;
} else if ( rstat == MODEL_READ_ERR ) {
cout << "Error encountered reading the model" << endl;
return 1;
}

But ideally the service will also include message information in the SCAResult value that can
be used to format a message. In this example we use the MessageDispatcher to format the
message and print it. The second blank argument to the getMessage call is the language the
message should be formatted in. In this case the blank value means the current default
language setting.

273
SCA Framework Error Handling

C++
if ( rstat ) {
SCA::Framework::SCAIMessageDispatcher spDispatcher;
spDispatcher = getSCAService("[Link]");
SCAUString ustr;
spDispatcher->getMessage(rstat,"",ustr);
cout << ustr << endl;
return 1;
}

The SCAResult class also contains a toString method that automates this work for you.

if ( rstat ) {
cout << [Link]() << endl;
return 1;
}

It is also possible to dispatch the message to any registered message listeners. See the section
on the MessageDispatcher later in this chapter for more details on message listeners. In this
example the dispatchMessage method is used to dispatch the message. The second argument
of zero in the call is severity level you can set. This value is passed to the message listeners
and they can use it as required.

C++
if ( rstat ) {
SCA::Framework::SCAIMessageDispatcher spDispatcher;
spDispatcher = getSCAService("[Link]");
spDispatcher->dispatchMessage(rstat,0);
return 1;
}

The following is simple C++ client application that uses the FileReader service and does the
appropriate handling of any errors. In this example we are using the toString method to format
the error message for printing.

[Link]
#include <iostream>
using namespace std;
#include <SCA/SCAKernel.h>
#include "SCA/Framework/SCAIMessageDispatcher.h"
#include <SDK/ErrorHandling/SCAResult/SCAIReader.h>
#include <SDK/ErrorHandling/SCAResult/FileReaderTypes.h>

using namespace SCA;


using namespace SDK::ErrorHandling::SCAResult;

int main()
{
try {
cout << "Test using MessageDispatcher to format errors" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

274
SCA Framework Error Handling

// Load the FileReader service


SCAString svcName = "[Link]");
SCAIReader spReader = getSCAService(svcName);

// Read the model


SCAResult rstat = spReader->readModel("[Link]");
if ( rstat ) {
cout << [Link]() << endl;
}

// Clean up
spReader = NULLSP;

// Terminate the SCA Kernel


terminateSCAKernel();

} catch (SCAException& e) {
cout << [Link]() << endl;
}
return 0;
}

If this application was run, and the readModel method returned an error indicating it could not
locate the model, the following is what the output of the formatted message would look like if
the default language was English.

The requested model "[Link]" could not be located.

If the default language was German, we would get the following.

Das angeforderte Modell "[Link]" konnte nicht gefunden werden.

It is also possible to use a message listener and then used the dispatchMessage method to
dispatch the error. This technique will be shown in the next section.

10.4. MessageDispatcher Service


The MessageDispatcher is a messaging service that formats the message information stored
in SCAResult values and optionally dispatches them. The MessageDispatcher service
provides three functions each of which is handled by a different interface.

SCAIMsgTableManager - Acts as a front-end to the TextTranslation service discussed in


the Messages and Internationalization chapter of this manual and manages instances of client
registered message tables and their locales

SCAIMsgListenerManager - Manages instances of client registered message listeners

SCAIMessageDispatcher - Formats and optionally dispatches messages

275
SCA Framework Error Handling

The MessageDispatcher service uses message listeners to process the dispatched messages.
The main reason for message listeners is to allow an application to compartmentalize the
handling of messages into a single piece of code instead of spreading it around the application.
A message listener is a SCA object which implements the SCAIMessageListener interface.
This code must be provided by the clients of the MessageDispatcher and instances of the
SCAIMessageListener interface must be registered by the client if the dispatching of
messages is used. Each message listener can specify its own locale that it wants any message
formatted in or it may choose to use the current system default locale. An application may
utilize as many message listeners as it needs. Normally a different listener would be used for
each different type of processing that is required for dispatched messages. For example there
may be one listener that handles the logging of messages to a log file and a different listener
that informs the user of the errors by displaying them in a message box.

The MessageDispatcher is tightly coupled with the SCAResult data type. The SCAResult
type provides the data structure where the information required for formatting the message is
stored. This include the message number, message table ID and any optional message
parameters. The MessageDispatcher service ignores the error code data value in the
SCAResult instant.

It is also possible to use the MessageDispatcher service to format general messages and not
just error messages. To do this you just create a SCAResult value with the appropriate
message information. In this case the error ID information has no meaning. The same interface
methods in the SCAIMessageDispatcher interface are then use to format and optionally
dispatch the message.

The following sections describe each of the three interfaces and shows examples of how they
are used.

SCA::Framework::SCAIMsgTableManager Interface

The SCAIMsgTableManager interface allows a client service to register


message tables with the MessageDispatcher.

Inherits SCA::SCAIService.

Member Functions
SCAResult addTable (in SCAUString fileBaseName, out SCAInt32 tableId)

Member Function Documentation

fileBaseName
SCAResult addTable ( in SCAUString
,
out SCAInt32 tableId
)

276
SCA Framework Error Handling

Method to add a message table to the Messaging service so it can be used in a SCAResult
value. If the table has already been added, then the table ID that was previously assigned for
it will be returned.
Parameters:
[in] fileBaseName Message table root name which does not include locale
information.
[out] tableId Table ID that can be used to create a SCAResult value.
Returns:
SCAResult Status of request which should always be a SCASuccess

In order to use a message table, the table must be first registered with the MessageDispatcher
service. Normally, a service will do this registration in its constructor and save the message
table ID for later use. To register the message table you use the portion of the filename for the
table which does not include the language information. In our example the complete name of
the message table names were FileReaderMsgTable_en.xml and FileReaderMsgTable_de.xml
so the name for addTable call would be FileReaderMsgTable.

The following code shows how the message table is registered using this interface.

C++
#include "SCA/Framework/SCAIMsgTableManager.h"

// Register our message table


SCA::Framework::SCAIMsgTableManager spManager;
spManager = getService("[Link]");
spManager->addTable(L"FileReaderMsgTable",m_msgTableID);

The addTable method returns an integer message table ID, m_msgTableID in this example,
which should be saved. It is required when creating SCAResult instances which reference
messages defined in this table. Once a table has been registered the table ID will be valid for
the duration of the current execution.

It is also important to understand that the addTable method will always return a SCASuccess
value. This is true even if there are no message tables available that match the name provided.
This is because the registering of a table does not trigger the processing of the actual XML file
for the message table. At the time of registration it is not known what language will actually
be used to format any of its messages and there may be multiple message tables available. The
actual language is not determined until a message is formatted so the processing of the XML
file must be delayed until that time. If the message table cannot be found or there are errors
reading it at this time, the formatting operation will instead return a message indicating why
the desired message could not be formatted. It will also include the message number and table
name so you can still determine what the original error was. The following is an example of
what one of these messages would look like.

Error formatting message 101 in table FileReaderMsgTable


XML file for message table FileReaderMsgTable for locale "en_US.1252"
or "en" does not exist.

277
SCA Framework Error Handling

SCA::Framework::SCAIMsgListenerManager Interface

The SCAIMsgListenerManager interface allows a client service to add and


remove message listeners.

Inherits SCA::SCAIService.

Member Functions
SCAResult addListener (in SCAIMessageListener msgListener, in SCAString locale)
SCAResult removeListener (in SCAIMessageListener msgListener)

Member Function Documentation

msgListener
SCAResult addListener ( in SCAIMessageListener
,
in SCAString locale
)

Method to add a message listener to the Messaging service.

Parameters:
[in] msgListener Interface to the listener that is to be added.
[in] locale Locale string for this message listener. All messages dispatched to
this listener will be formatted in this locale. The value can be an
empty string which means the listener uses the current default
locale.
Returns:
SCAResult Status of request which should always be SCASuccess

SCAResult removeListener ( in SCAIMessageListener msgListener )

Method to remove a message listener from the Messaging service.

Parameters:
[in] msgListener Interface to the listener that is to be removed.
Returns:
SCAResult Status of request which should always be SCASuccess

The SCAIMsgListenerManager allows clients to add and remove message listeners. Each
message listener can specify the language that it wants the messages formatted in. It is not
required for all registered listeners to use the same locale. The following example shows how
message listeners can be added and removed. In this case we will request that the messages
received by the listener be formatted in German.

C++
// Get instance of message listener
SCAIMessageListener spListener = . . .;

278
SCA Framework Error Handling

// Register our message listener using the German locale


SCA::Framework::SCAIMsgListenerManager spManager;
spManager = getSCAService("[Link]");
spManager->addListener(spListener,"de");

// Application does its thing

// Remove our message listener


spManager->removeListener(spListener);

This example does not show how the message listener was actually implemented. Later in this
section a number of examples of this will be provided.

SCA::Framework::SCAIMessageDispatcher Interface

The SCAIMessageDispatcher interface is used to format messages. The


formatted messages can either be dispatched to the registered message
listeners or returned to the caller.

Inherits SCA::SCAIService.

Member Functions
SCAResult setDefaultLocale (in SCAString locale)
SCAResult dispatchMessage (in SCAResult rStat, in SCAInt32 severity)
SCAResult getMessage (in SCAResult rStat, in SCAString locale, out SCAUString outString)

Member Function Documentation

SCAResult dispatchMessage ( in SCAResult rStat,


in SCAInt32 severity
)
Method to format a message described by a SCAResult value and dispatch it to all registered
listeners. The message may need to be formatted several times if multiple message listeners
have been added which requested different locales.
Parameters:
[in] rStat The SCAResult value to format
[in] severity The severity code for the message. This value is passed directly to the
message listeners.
Returns:
SCAResult Status of request

SCAResult getMessage ( in SCAResult rStat,


in SCAString locale,
out SCAUString outString
)
Method to format a message described by a SCAResult value and return it to the caller.
Parameters:
[in] rStat The SCAResult value to format

279
SCA Framework Error Handling

[in] locale The locale string that the message will be formatted in. The value can
be an empty string which means the current default locale is used.
[out] outString Formatted message value
Returns:
SCAResult Status of request

SCAResult setDefaultLocale ( in SCAString locale )


Method to set the default locale for all message listeners that are added with a blank locale
specified. Calls to this routine will affect message listeners that were previously added as well
as those that are added in the future.
Parameters:
[in] locale Locale string
Returns:
SCAResult Status of request

The SCAIMessageDispatcher interface is used by the client to request the formatting of a


message. The message can be either returned directly to the caller or can be dispatched to all
registered message listeners. The first example shows how the message can be formatted and
returned to the caller. In this example the current default locale is used for the message
translation.

C++
SCAResult rstat = sp->someMethod()
if ( rstat ) {
SCA::Framework::SCAIMessageDispatcher spDispatcher;
spDispatcher = getSCAService("[Link]");
SCAUString ustr;
spDispatcher->getMessage(rstat,"",ustr);
wcout << ustr << endl;
return 1;
}

It is also possible to dispatch the message to all register message listeners using the
dispatchMessage method. The second parameter in this call is the message severity. The
severity value is passed directly to the message listeners and not used by the
MessageDispatcher itself. Each application can define its own mechanism of interpreting the
severity code or it can choose to ignore it altogether. One common way of handling the
severity value is to use an IDL enum definition to contain the valid values. In the FileReader
example we have used the following values for the severity of a message.

IDL
enum SeverityType
{
SDK_INFORMATION,
SDK_WARNING,
SDK_ERROR
}

These values can be used in the call to the dispatchMessage method.

280
SCA Framework Error Handling

C++
SCAResult rstat = sp->someMethod()
if ( rstat ) {
SCA::Framework::SCAIMessageDispatcher spDispatcher;
spDispatcher = getSCAService("[Link]");
spDispatcher->dispatchMessage(rstat,SDK_ERROR);
return 1;
}

The dispatchMessage call may result in the requested message being formatted more than
once. This could happen if multiple message listeners are registered and they require different
languages.

The SCAIMessageDispatcher interface can also be used to change the default locale setting.

C++
SCA::Framework::SCAIMessageDispatcher spDispatcher;
spDispatcher = getSCAService("[Link]");
spDispatcher->setDefaultLocale("de");

It is important to remember that this default setting will affect all message listeners that are
currently registered which requested the default locale as well as any added in the future.
Message listeners currently registered that requested a specific locale are not affected.

SCA::Framework::SCAIMessageListener Interface

The SCAIMessageListener interface is used to implement message listeners


that can be used with the MessageDispatcher service.

Inherits SCA::SCAIService.

Member Functions
SCAResult doPublishMessage (in SCAUString str, in SCAInt32 severity)

Member Function Documentation

SCAResult doPublishMessage ( in SCAUString str,


in SCAInt32 severity
)

Method used by the MessageDispatcher to dispatch messages to the listeners that have been
registered with it.

Parameters:
[in] str Message to be dispatched.
[in] severity The severity level that was provided by the code that requested the
message to be dispatched.
Returns:

281
SCA Framework Error Handling

SCAResult Status of request

The SCAIMessageListener interface is used in the implementation of the message listeners


that the MessageDispatcher uses to dispatch messages. It must be implemented by the client
application that is using the MessageDispatcher service. Once an application has obtained an
instance of the SCA object that implements this interface, it must then register it with the
MessageDispatcher service. Once a message listener has been added then all messages
dispatched through the MessageDispatcher will be sent to the message listener until it is
removed.

There are a number of different techniques that can be used to implement the
SCAIMessageListener interface.

The interface can be implemented in a normal SCA service.


The interface can be implemented in a SCA service contained in an embedded component.
The interface can be implemented using techniques provided by the individual language
mappings. For example in C++ the SCAServiceObjectImpl templates could be used and in
Python the SCAIServiceBase class could be used.

Examples of the first and last of these methods are provided later in this section. For more
details on using embedded components and the SCAServiceObjectImpl templates see the SCA
SDK Advanced Features manual. The SCAIServiceBase class is described in the IDL to
Python Mapping chapter of this manual.

The SCAIMessageListener interface has a single method.

doPublishMessage ( in SCAUString str, in SCAInt32 severity );

When implementing the SCAIMessageListener interface, the doPublishMessage method


must be implemented. This method will be called by the MessageDispatcher when there is a
message to process. The first argument is the formatted text string for the message in the
language specified when the listener was registered. The second input is the severity code that
is provided by the call that originally dispatched the message. Each application can define its
own mechanism of interpreting the severity code or it can choose to ignore it altogether.
Message Listener example using SCAServiceObjectImpl template
The first example of using a message listener will implement it directly in the client
application program. This implementation will use one of the SCAServiceObjectImpl
templates provided by the SCA Framework to create a class which implements the
SCAIMessageListener interface. For complete details on using these templates see the SCA
SDK Advanced Features manual.

[Link]
#include <iostream>
using namespace std;
#include <SCA/SCAKernel.h>
#include <SCA/Framework/ServiceObjectImpl.h>

282
SCA Framework Error Handling

#include "SCA/Framework/SCAIMessageDispatcher.h"
#include "SCA/Framework/SCAIMsgListenerManager.h"
#include "SCA/Framework/SCAIMessageListener.h"
#include <SDK/ErrorHandling/SCAResult/SCAIReader.h>
#include <SDK/ErrorHandling/SCAResult/FileReaderTypes.h>

using namespace SCA;


using namespace SCA::Framework;
using namespace SDK::ErrorHandling::SCAResult;

//
// Implementation of SCAIMessageListener interface
//
char ImplName[] = "ExampleListener";
class Listener : SCAServiceObjectImpl1 <SCAIMessageListener,ImplName>
{
public:
// Constructors and Destructor
Listener() { }
~Listener() { }

// Methods for interface [Link]


SCAResult doPublishMessage(const SCAUString str,
const SCAInt32 severity) {
cout << "Error published with severity of "
<< severity << endl;
wcout << str << endl;
return SCASuccess;
}
};

int main()
{
try {
cout << "Test using local listener to format messages" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

// Get instance of message listener


Listener* pListener = new Listener();
SCAIMessageListener spListener = (SCAIMessageListener)pListener;

// Register our message listener


SCAIMsgListenerManager spManager;
spManager = getSCAService("[Link]");
spManager->addListener(spListener,"");

// Load the FileReader service


SCAString svcName = "[Link]";
SCAIReader spReader = getSCAService(svcName);

// Read the model


SCAResult rstat = spReader->readModel("[Link]");
if ( rstat ) {
SCAIMessageDispatcher spDispatcher = spManager;
spDispatcher->dispatchMessage(rstat,SDK_ERROR);

283
SCA Framework Error Handling

// Clean up
spReader = NULLSP;
spManager = NULLSP;

// Terminate the SCA Kernel


terminateSCAKernel();

} catch (SCAException& e) {
cout << [Link]() << endl;
}
return 0;
}

Message Listener example using a Logger Service Example


The next example of implementing a message listener will use a separate SCA service that
provides basic logging functionality. The logging service implements the SCAILogger
interface which provides methods to open and close the log file. It also implements the
SCAIMessageListener interface so it can function as a message listener and log any
messages it receives. The following is the complete definition of the logging service.

[Link]
#ifndef SDK_ERRORHANDLING_LOGGER_IDL_INCLUDED
#define SDK_ERRORHANDLING_LOGGER_IDL_INCLUDED

#include "SCA/[Link]"

module SDK { module ErrorHandling {

interface SCAILogger : SCA::SCAIService


{
SCA::SCAResult openLog( in SCA::SCAString fileName,
in SCA::SCABool append );
SCA::SCAResult writeLog( in SCA::SCAString msg );
SCA::SCAResult closeLog( );
};

}; };

#endif

[Link]
#ifndef LOGGER_SDL_INCLUDED
#define LOGGER_SDL_INCLUDED

#include "SDK/ErrorHandling/[Link]"
#include "SCA/Framework/[Link]"

module SDK { module ErrorHandling {

service [Link] {
interface SCA::Framework::SCAIMessageListener;

284
SCA Framework Error Handling

interface SCAILogger;
};

}; };

#endif

[Link]
#ifndef LOGGER_CDL_INCLUDED
#define LOGGER_CDL_INCLUDED

#include "[Link]"

component [Link]
{
service Logger;
};

#endif

The implementation for the logging service is as follows. To make the example code smaller
and easier to understand, the detailed error checking that would normally be part of the
implementation has been omitted.

Logger.h
#ifndef SDK_ERRORHANDLING_LOGGER_H_INCLUDED
#define SDK_ERRORHANDLING_LOGGER_H_INCLUDED

#include "LoggerBase.h"
#include <iostream>
#include <fstream>

namespace SDK { namespace ErrorHandling {

class Logger : public LoggerBase


{
public:

// Constructor and Destructor


Logger(SCAILoggerFactoryAccess* factoryAccess);
virtual ~Logger();

// Methods for interface [Link]


SCA::SCAResult doPublishMessage(const SCA::SCAUString str,
const SCA::SCAInt32 severity);

// Methods for interface [Link]


SCA::SCAResult openLog(const SCA::SCAString fileName,
const SCA::SCABool append);
SCA::SCAResult writeLog(const SCA::SCAString msg);
virtal SCA::SCAResult closeLog();

private:
std::ofstream m_file;
};

285
SCA Framework Error Handling

} }

#endif

[Link]
#include "Logger.h"
#include <SCA/StringUtility.h>
#include <time.h>
using namespace std;
using namespace SCA;

namespace SDK { namespace ErrorHandling {

// Constructor
Logger::Logger(SCAILoggerFactoryAccess* factoryAccess)
: LoggerBase(factoryAccess)
{
}

// Destructor
Logger::~Logger()
{
}

SCA::SCAResult Logger::doPublishMessage(const SCA::SCAUString str,


const SCA::SCAInt32 severity)
{
SCAString msg = StringUtility::stringFromWString(str);
m_file << "Error dispatched with severity of "
<< severity << endl;
m_file << msg << endl;
return SCASuccess;
}

SCA::SCAResult Logger::openLog(const SCA::SCAString fileName,


const SCA::SCABool append)
{
// Open the log file
if ( [Link]() ) {
return SCAError;
} else {
if ( append== true ) {
m_file.open(fileName.c_str(),
ios_base::out| ios_base::app);
} else {
m_file.open(fileName.c_str(),
ios_base::out| ios_base::trunc );
}
}

// Add the current date and time


time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );

286
SCA Framework Error Handling

m_file << "Log file opened on " << asctime(timeinfo);

return SCASuccess;
}

SCA::SCAResult Logger::writeLog(const SCA::SCAString msg)


{
m_file << msg << endl;
return SCASuccess;
}

SCA::SCAResult Logger::closeLog()
{
m_file.close();
return SCASuccess;
}

} }

The following is a sample client that uses the logging service to save all error messages in a
log file. It is similar to our previous example except it loads and initializes an instance of the
logging service and uses it for the message listener instead of providing its own
implementation. The client will also use the logging feature to save messages indicating the
flow of the program.

[Link]
#include <iostream>
#include <SCA/SCAKernel.h>
#include <SCA/Framework/ServiceObjectImpl.h>
#include "SCA/Framework/SCAIMessageDispatcher.h"
#include "SCA/Framework/SCAIMsgListenerManager.h"
#include "SCA/Framework/SCAIMessageListener.h"
#include <SDK/ErrorHandling/SCAResult/SCAIReader.h>
#include <SDK/ErrorHandling/SCAResult/FileReaderTypes.h>
#include <SDK/ErrorHandling/SCAILogger.h>

using namespace SCA;


using namespace SCA::Framework;
using namespace SDK::ErrorHandling;
using namespace SDK::ErrorHandling::SCAResult;

int main()
{
try {
cout << "Test using Logger service to process errors" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

// Get instance of error logger service and open a log file


SCAILogger spLogger;
spLogger = getSCAService("[Link]");
spLogger->openLog("[Link]",false);

// Register our message listener

287
SCA Framework Error Handling

SCA::Framework::SCAIMsgListenerManager spManager;
spManager = getSCAService("[Link]");
SCAIMessageListener spListener = spLogger;
spManager->addListener(spListener,"");

// Get SCAIMessageDispatcher interface for future error processing


// Load the FileReader service
SCAString svcName = "[Link]";
spLogger->writeLog("Getting "+svcName+" service");
SCAIReader spReader = getSCAService(svcName);

// Read the model


SCAString modelName = "[Link]";
spLogger->writeLog("Reading model "+modelName);
SCAResult rstat = spReader->readModel(modelName);
if ( rstat ) {
SCAIMessageDispatcher spDispatcher = spManager;
spDispatcher->dispatchMessage(rstat,SDK_ERROR);
}
// Clean up
spReader = NULLSP;
spManager->removeListener(spListener);
spManager = NULLSP;
spLogger->closeLog();
spLogger = NULLSP;

// Terminate the SCA Kernel


terminateSCAKernel();

} catch (SCAException& e) {
cout << [Link]() << endl;
}
return 0;
}

288
SCA Framework Error Handling

10.5. SCA Error Manager


The interfaces exposed by the Error Manager are used by the SCA Kernel
and users to perform various error management tasks such as applying
error policy actions to the following type of errors:
SCAException
SCAResult
Signals on Linux
C++ and .NET unhandled exceptions on Windows
b. Generate mini dump
c. Generate call stack traceback
d. Log messages

These are not SCA services and the implementations are language
specific. The Error Manager is currently implemented in C++ and .NET
languages. For detailed reference please see the sections ‘C++ Error
Manager API Reference’ and ‘.NET Error Manager API Reference’ of this
chapter.

Error Manager Settings in SCA Kernel Configuration File

Enable/Disable the Error Manager

The Error Manager can be enabled or disabled by specifying the options


in the SCA Kernel Configuration file.

Examples:

The following will enable the Error Manager.

<var name="ErrorManager" value=”Enabled=yes” />

The following will disable the Error Manager:

<var name="ErrorManager" value=”Enabled=no” />

The following will enable the Error Manager using the environment
variable only, when no configuration file is used.

setenv SCA_ERROR_MANAGER=”Enabled=yes”

Minidump Folder Path

Minidump files are created in this folder and use the following file
naming convention.

"[Link]"

For example: "[Link]"

Examples:

The following will set the Minidump path directly.

<var name="MinidumpPath" value=”/temp/minidumps/” />

289
SCA Framework Error Handling

The following will set the Minidump path using a combination of an


environment variable and the configuration variable.
setenv MY_MINIDUMP_PATH=”/temp/minidumps/”

<env name="%dumpPath%" value="MY_MINIDUMP_PATH"/>


<var name="MinidumpPath" value="%dumpPath%"/>

The following will set minidump path using the environment variable
only, when no configuration file is used.

setenv SCA_MINIDUMP_PATH=”/temp/minidumps/”

10.6. Error Policy Manager Service

Error Policy defines a set of associated actions to be taken when


handling errors.

The SCA Framework provides a default XML table to specify global error
policy actions (such as Log, Replace, Traceback, Terminate and
Minidump), to be applied when handling the errors. Users can also
provide their own replacement table.

This service provides an API to register the XML error policy table
with the SCA Framework and access policy actions.

The default policy table called "[Link]" (shown


below) is installed as part of the Kernel in the Resource directory.
The format is self explanatory.

[Link]
<?xml version="1.0" ?>
<!-- Table of Error handling policies -->
<SCA>
<policy name="SCAResult">
<action name="Log"/>
</policy>
<policy name="SCAException">
<action name="Log"/>
</policy>
<policy name="Signal">
<action name="Log"/>
<action name="Minidump"/>
</policy>
<policy name="FatalSignal">
<action name="Log"/>
<action name="Minidump"/>
<action name="Terminate"/>
</policy>
</SCA>

Sample Policy Table


<?xml version="1.0" ?>

290
SCA Framework Error Handling

<!-- Table of Error handling policies -->


<SCA>
<policy name="SCAResult">
<action name="Log"/>
</policy>
<policy name="Exception">
<action name="Log"/>
<action name="Traceback"/>
</policy>
<policy name="Signal">
<action name="Log"/>
<action name="Minidump"/>
<action name="Replace"/>
</policy>
<policy name="FatalSignal">
<action name="Log"/>
<action name="Minidump"/>
<action name="Terminate"/>
</policy>
</SCA>

SCA::Framework::SCAIErrorPolicyManager Interface
The purpose of this SCA service is to provide access to the error
policies specified in the XML policy table.

Member Functions
SCAResult setPolicyTable (in SCAString xmlTablePath)
Sets the XML policy table file path.
SCAResult getPolicyActions (in SCAString policy, out PolicyActionSequence policyActions)
Returns the names of the handlers for the given policy.
SCAResult getErrorPolicyStatus (out SCABool isEnabled)
Returns the status of Error Policy Management.
SCAResult getMinidumpPath (out SCAString minidumpPath)
Returns the path of the directory where minidumps are created.

Member Function Documentation

SCAResult getErrorPolicyStatus ( out SCABool isEnabled )

Parameters:
isEnabled true if Error Policy Management is enabled.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getMinidumpPath ( out SCAString minidumpPath )

Parameters:
minidumpPath Minidump path.
Returns:

291
SCA Framework Error Handling

Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getPolicyActions ( in SCAString policy,


out PolicyActionSequence policyActions )
Parameters:
policy Name of the error policy
policyActions List of policy actions for the given policy
enum PolicyAction {
POLICY_ACTION_LOG,
POLICY_ACTION_TRACEBACK,
POLICY_ACTION_REPLACE,
POLICY_ACTION_TERMINATE,
POLICY_ACTION_MINIDUMP,
POLICY_ACTION_CUSTOM
};

typedef sequence< PolicyAction > PolicyActionSequence;


Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setPolicyTable ( in SCAString xmlTablePath )

Parameters:
xmlTablePath - complete path of the XML policy table file
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

10.7. Signal Catchers in SCA Framework

The following signal and exception catchers are available in the SCA
Framework to catch signals/ unhandled exceptions and apply error
policies to them.

Vectored Exception Handler for C++ on Windows Platforms


UnhandledExceptionEventHandler for .NET
Signal Handler (sigaction) for Linux platforms.

C++ Signal Action Handlers


The C++ ErrorManager implements default Signal action handlers for
"Replace", "Terminate" and "Minidump" actions. The users can replace
these handlers with their own handlers or add their own "Custom" action
handler using "setSignalAction" method in the Error Manager.

Example:
This example shows how to replace the standard minidump action with a
user defined minidump action and calls handleSignal with the "Signal"

292
SCA Framework Error Handling

policy. The default actions for the “Signal” policy are "Log" and
"Minidump".

. . .
class MyMinidumpAction : public ISignalAction
{
public:
inline MyMinidumpAction(){;}
inline virtual SCAResult handleAction(const void* info,
SCASystemException& exception)
{
std::cout << "MyMinidumpAction Handler generated Minidump" << std::endl;
std::cout << "This action does not use the 'info' argument" << std::endl;
std::cout << "MyMinidump 1" << std::endl;
std::cout << "MyMinidump 2" << std::endl;
std::cout << "MyMinidump 3" << std::endl;

return SCASuccess;
}
};

. . .
IErrorManager* errorManager = SCA::ErrorManagerFactory::getErrorManager();
ISignalAction* myMiniDumpAction = new MyMinidumpAction();
if (myMiniDumpAction) {
// Set minidump action handler
ISignalAction* oldAction = NULL;
// Replace the standard minidump action with a custom minidump action
SCAResult rstat = errorManager->setSignalAction(POLICY_ACTION_MINIDUMP,
myMiniDumpAction, &oldAction);
if (!rstat) {
SCASystemException exception;
// Call handleSignal with "Signal" policy. The default actions for this
// policy are "Log" and "Minidump"
rstat = errorManager->handleSignal("Signal", 0, exception);

// Set the old signal action


if (!rstat && oldAction)
rstat = errorManager->setSignalAction(POLICY_ACTION_MINIDUMP,
oldAction);
}
delete myMiniDumpAction;
}
. . .

Output:
Unknown Exception occured. Process ID:73564 Thread ID: 24634
MyMinidumpAction Handler generated Minidump
This action does not use the 'info' argument
MyMinidump 1
MyMinidump 2
MyMinidump 3

.NET Exception Handlers


Since .NET does not have signals,everything is handled using the .NET
'Exception'. The .NET ErrorManager provides a method
'handleUnhandledException' instead of 'handleSignal'.

The .NET ErrorManager implements default action handlers for "Replace",


"Terminate" and "Minidump" actions. The users can replace these

293
SCA Framework Error Handling

handlers with their own handlers or add their own "Custom" action
handler using "setExceptionAction" method in the Error Manager.

Example:
. . .
IErrorManager errorManager = [Link]();
IExceptionAction oldAction;
IExceptionAction myMiniDumpAction = new MyMinidumpAction();
// Set minidump action handler
SCAResult rstat = [Link](
PolicyAction.POLICY_ACTION_MINIDUMP,
myMiniDumpAction, out oldAction);

SCAException exception = null;


// Call handleUnhandledException with "Signal" policy. The default actions
// for this policy are "Log" and "Minidump"
SCAResult rstat = [Link](
"Signal", null, ref exception);

10.8. SCAException throwit() Method


The throwit() method is automatically generated in all SCAException
inherited sub-classes.
It applies the specified error policy and then throws the SCAException.
The default policy is “SCAException”.

C++

// Applies the policy named policyName and throws the exception


void throwit(const SCAString& policyName="SCAException");

.NET

// Applies the policy named “SCAException” and throws the exception


[Link]();

// Applies the policy named policyName and throws the exception


[Link](string policyName);

For more details on the language specific exception APIs, please refer to the respective
Language Mapping chapters of this manual.

10.9. Wrapping of SCAResult and SCAException


Wrapping creates a new object and sets the original object as an inner
object.

The SCAResult and SCAException classes support inner objects. The


language bridges support passing of wrapped SCAResult and SCAException
objects across the bridge.

Note: This feature is currently only supported for C++ and .NET
languages. If a SCAException or SCAResult is passed across a bridge
involving one of the other SCA supported languages (Java, Python) or a

294
SCA Framework Error Handling

Remoting Bridge, the inner exceptions and inner SCAResult values will
be neglected.

C++ API for Wrapping


// Wrapping methods to set and get the inner exception
// if makeCopy is true the inner exception is cloned before setting
void SCA::SCAException::setInnerSCAException(SCA::SCAException * exPtr,
bool makeCopy=true)
SCA::SCAException* SCA::SCAException::getInnerSCAException() const

// Wrapping methods to set and get the inner SCAResult


void SCA::SCAResult::setInnerSCAResult(const SCA::SCAResult & result)
bool SCA::SCAResult::getInnerSCAResult(SCA::SCAResult & result) const

.NET API for Wrapping


// Wrapping methods to set and get the inner exception
public void [Link]([Link] ex )
public [Link] [Link]()

// Wrapping methods to set and get the inner SCAResult


public void [Link]([Link] result )
public [Link] [Link]()

10.10. SCAException and SCAResult Logging


The ‘log’ methods in these classes can be used to manually log the
SCAException and SCAResult objects using the logger service. The inner
wrapped objects are also logged recursively.

If the optional logTraceback parameter is true, the call stack


traceback is also logged.

C++

SCAResult::log(bool logTraceback=false);
SCAException::log(bool logTraceback=false);

.NET

[Link]();
[Link](bool logTraceback);
[Link]();
[Link](bool logTraceback);

10.11. Call Tracing


C++ Macros

The following C++ trace macro is provided to trace function and method
calls. The macro logs the source file name, source line number and the
function name.

295
SCA Framework Error Handling

#define SCA_TRACE_CALL

The genskeleton utility in the IDL compiler automatically inserts the


trace macros in the SCA Framework generated interface method calls.

The users must enable call tracing by defining the following symbol.

#define SCA_TRACE_CALL_ENABLED

.NET CallTracer

The .NET class CallTracer is provided to trace method calls. The


[Link]() method logs the source file name, source line
number and the function name.

The genskeleton utility in the IDL compiler automatically inserts the


following line in the SCA Framework generated interface method calls.

[Link]();

The users must enable call tracing by making the following call.

[Link]();

10.12. C++ Error Manager API Reference

SCA::IErrorManager Interface
The purpose of this interface is to provide error management
capabilities to C++ clients

Member Functions
virtual SCAResult handleSCAResult (const SCAString &policy, const SCAResult
&scaResult)=0
Apply Error Handling Policies to SCAResult.
virtual SCAResult handleSCAException (const SCAString &policy, const SCAException
&exception)=0
Apply Error Handling Policies to SCAException.
virtual SCAResult handleSignal (const SCAString &policy, const void *info,
SCASystemException &exception)=0
Apply Error Handling Policies to Signal.
virtual SCAResult writeMinidump ()=0
Generate and write minidump to a file. The minidump path could be
specified in the SCA Kernel Configuration file. If not specified in the
config file, the path is obtained as follows. GetTempPath() on Windows
Platforms. /tmp on non Windows Platforms. The file name is of the
following format: "SCAKernel-YYYYMMDDHHMMSS-ProcessID-
[Link]"
For example: "[Link]".
virtual SCAResult writeMinidump (const SCAString &dumpPath)=0

296
SCA Framework Error Handling

Generate and write minidump in the specified directory. The file name
is of the following format: "SCAKernel-YYYYMMDDHHMMSS-ProcessID-
[Link]" For example: "SCAKernel-20110615145676-56728-
[Link]".
virtual SCAResult writeMinidump (const SCAUString &dumpPath)=0
Generate and write minidump in the specified directory. The file name
is of the following format: "SCAKernel-YYYYMMDDHHMMSS-ProcessID-
[Link]"
For example: "[Link]".
virtual SCAResult getTraceback (SCAStringSequence &traceback, int
numFrames2Skip=2)=0
Generate and return the call stack traceback on demand.
virtual SCAResult setSignalAction (const PolicyAction &action, ISignalAction
*newActionHandler, ISignalAction **oldActionHandler=NULL)=0
Set the Signal action handler for the specified policy action.
virtual SCAResult logMessage (const SCAString &message, const Severity
&severity=DEBUG_SEVERITY)=0
Log the message.
virtual SCAResult logMessageSequence (const SCAStringSequence &msgSequence,
const Severity &severity=DEBUG_SEVERITY)=0
Log the message sequence.
virtual SCABool errorPoliciesEnabled ()=0
Check if error handling policies are enabled.

Static Public Member Functions


static SCABool errorManagementEnabled ()
Check if ErrorManagement is enabled.
static SCABool enableSCAErrorCatcher (SCABool enable)
Enable catcher in SCA Kernel to apply error policies
to Signals on Linux and Unhandled Exceptions on
Windows platforms. Vectored Exception Handler is used
for C++ on Windows Platforms
UnhandledExceptionEventHandler is used for .NET Signal
Handler (sigaction) is used for C++ on Linux.

Member Function Documentation

static SCABool enableSCAErrorCatcher ( SCABool enable )


Parameters:
enable If 'true' enable the catcher. If 'false' disable the catcher.
Returns:
Returns 'true' on success; 'false' on error.

static SCABool errorManagementEnabled ( )


Returns:
Returns 'true' or 'false'.

297
SCA Framework Error Handling

virtual SCABool errorPoliciesEnabled ( )


Returns:
Returns 'true' or 'false'.

virtual SCAResult getTraceback (SCAStringSequence & traceback,


int numFrames2Skip = 2 )
Parameters:
traceback Call stack traceback returned.
numFrames2Skip The number of stack frames to skip. The default is 2, which skip the
frames containing getTraceback and any internal calls.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult handleSCAException ( const SCAString & policy,


const SCAException & exception )
Parameters:
policy Name of the Error Handling policy to apply.
exception SCAException value to handle.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult handleSCAResult ( const SCAString & policy,


const SCAResult & scaResult )
Parameters:
policy Name of the Error Handling policy to apply.
scaResult SCAResult value to handle.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult handleSignal ( const SCAString & policy,


const void * info,
SCASystemException & exception )
Parameters:
policy Name of the Error Handling policy to apply.
info This input parameter is platform dependent. On Windows it is a pointer to
EXCEPTION_POINTERS structure. On Linux/Unix it is a pointer to 'siginfo_t'
exception If one of the policy action is "Replace", the signal is converted to
SCASystemException and returned in the 'exception' parameter. For all
other cases [Link] is set to zero.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

298
SCA Framework Error Handling

virtual SCAResult logMessage ( const SCAString & message,


const Severity & severity = DEBUG_SEVERITY )

Parameters:
message The message string to log.
severity Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY) Default is DEBUG_SEVERITY.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult logMessageSequence ( const SCAStringSequence & msgSequence,


const Severity & severity = DEBUG_SEVERITY
)
Parameters:
msgSequence The message string sequence to log.
severity Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY) Default is DEBUG_SEVERITY.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult setSignalAction ( const PolicyAction & action,


ISignalAction * newActionHandler,
ISignalAction ** oldActionHandler = NULL )
Parameters:
action The policy action. The possible values are:
POLICY_ACTION_REPLACE, POLICY_ACTION_TERMINATE,
POLICY_ACTION_MINIDUMP,POLICY_ACTION_CUSTOM
newActionHandler The new Signal action handler.
oldActionHandler The previous Signal action handler (if any) is returned in this
parameter.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult writeMinidump (const SCAUString & dumpPath )


Parameters:
dumpPath Minidump file directory.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult writeMinidump (const SCAString & dumpPath )

Parameters:

299
SCA Framework Error Handling

dumpPath Minidump file directory.


Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult writeMinidump ( )


Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCA::ISignalAction Interface

This Interface is used for implementing Signal Action handlers.

Member Functions
virtual SCAResult handleAction (const void *info, SCASystemException
&exception)=0
Handle the SignalAction.

Static Public Member Functions


static SCAResult getSignalMessage (const void *info, SCAString &sigMessage)
Return a meaningful message for the Signal, based on the info.
static ISignalAction * getSignalAction (const PolicyAction &action, const
SCAStringSequence &parameters)
Factory method to create an instance of the SignalAction handler.

Member Function Documentation

static ISignalAction* getSignalAction ( const PolicyAction & action,


const SCAStringSequence & parameters )
Parameters:
action The policy action. The possible values are: POLICY_ACTION_REPLACE,
POLICY_ACTION_TERMINATE,
POLICY_ACTION_MINIDUMP,POLICY_ACTION_CUSTOM
parameters Any action specific parameters can be passed here. For example for
POLICY_ACTION_MINIDUMP, parameters[0] is the minidump path.
Returns:
Returns ISignalAction* on success; otherwise returns NULL.

static SCAResult getSignalMessage ( const void * info,


SCAString & sigMessage )
Parameters:
info This parameter is used to pass platform dependent signal or Exception
parameters For example on Windows this could be
EXCEPTION_POINTERS*

300
SCA Framework Error Handling

sigMessage Message generated using the Signal information


Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

virtual SCAResult handleAction ( const void * info,


SCASystemException & exception )
Parameters:
info This parameter is used to pass platform dependent signal or Exception
parameters For example on Windows this could be EXCEPTION_POINTERS*
exception If the Signal is replaced with SCASystemException, the value is returned in
this parameter.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCA::ErrorManagerFactory Class

Static Public Member Functions


static IErrorManager * getErrorManager ()
Factory method to create an instance of the C++ ErrorManager.

Member Function Documentation

static IErrorManager* getErrorManager ( )


Returns:
Returns IErrorManager* on success; otherwise returns NULL.

10.13. .NET Error Manager API Reference

[Link] Interface

The purpose of this interface is to provide error management


capabilities to .NET clients
Member Functions

SCAResult handleSCAResult (string policy, SCAResult scaResult)


Apply Error Handling Policies to SCAResult.
SCAResult handleSCAException (string policy, SCAException exception)
Apply Error Handling Policies to SCAException.
SCAResult handleUnhandledException (string policy, Exception e, ref SCAException
exception)
Apply Error Handling Policies to Unhandled .NET Exceptions.
SCAResult writeMinidump ()
Generate and write minidump to a file. The minidump path could be specified in
the SCA Kernel Configuration file. If not specified in the config file, the path is
obtained using GetTempPath(). The file name is of the following format:

301
SCA Framework Error Handling

"[Link]" For example:


"[Link]".
SCAResult writeMinidump (string dumpPath)
Generate and write minidump in the specified directory. The file name is of the
following format: "[Link]"
For example: "[Link]".
SCAResult getTraceback (ref SCAStringSequence traceback)
Generate and return the call stack traceback on demand.
SCAResult getTraceback (ref SCAStringSequence traceback, int numFrames2Skip)
Generate and return the call stack traceback on demand.
SCAResult getTraceback (ref SCAStringSequence traceback, Exception e)
Generate and return the call stack traceback on demand.
SCAResult getTraceback (ref SCAStringSequence traceback, int numFrames2Skip,
Exception e)
Generate and return the call stack traceback on demand.
SCAResult setExceptionAction ([Link] action, IExceptionAction
actionHandler, out IExceptionAction oldActionHandler)
Set the new Unhandled Exception action handler for the specified policy action.
SCAResult logMessage (string message, [Link] severity)
Log the message.
SCAResult logMessage (string message)
Log the message with DEBUG_SEVERITY.
SCAResult logMessageSequence (SCAStringSequence msgSequence,
[Link] severity)
Log the message sequence.
SCAResult logMessageSequence (SCAStringSequence msgSequence)
Log the message sequence with DEBUG_SEVERITY.
bool errorPoliciesEnabled ()
Check if error handling policies are enabled.

Member Function Documentation

bool errorPoliciesEnabled ()
Returns:
Returns 'true' or 'false'.

SCAResult getTraceback (ref SCAStringSequence traceback,


int numFrames2Skip,
Exception e )
Parameters:
traceback Call stack traceback returned.
numFrames2Skip The number of call stack frames to skip.
e The Exception for which the traceback is generated.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

302
SCA Framework Error Handling

SCAResult getTraceback (ref SCAStringSequence traceback,


Exception e)
Parameters:
traceback Call stack traceback returned.
e The Exception for which the traceback is generated.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getTraceback ( ref SCAStringSequence traceback,


int numFrames2Skip )
Parameters:
traceback Call stack traceback returned.
numFrames2Skip The number of call stack frames to skip.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getTraceback ( ref SCAStringSequence traceback )


Parameters:
traceback Call stack traceback returned.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult handleSCAException ( string policy,


SCAException exception )
Parameters:
policy Name of the Error Handling policy to apply.
exception SCAException value to handle.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult handleSCAResult ( string policy,

SCAResult scaResult )
Parameters:
policy Name of the Error Handling policy to apply.
scaResult SCAResult value to handle.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult handleUnhandledException ( string policy,


Exception e,

303
SCA Framework Error Handling

ref SCAException exception )

Parameters:
policy Name of the Error Handling policy to apply.
e .NET Exception to handle
exception If one of the policy actions is "Replace", the Exception is converted to
SCAException and returned in the 'exception' parameter. For all other cases
[Link] is set to null.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessage ( string message )


Parameters:
message The message string to log.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessage ( string message,


[Link] severity )

Parameters:
message The message string to log.
severity Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessageSequence ( SCAStringSequence msgSequence )

Parameters:
msgSequence The message string sequence to log.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessageSequence ( SCAStringSequence msgSequence,


[Link] severity )

Parameters:
msgSequence The message string sequence to log.
severity Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setExceptionAction ( [Link] action,

304
SCA Framework Error Handling

IExceptionAction actionHandler,
out IExceptionAction oldActionHandler )

Parameters:

action The policy action. The possible values are:


POLICY_ACTION_REPLACE, POLICY_ACTION_TERMINATE,
POLICY_ACTION_MINIDUMP,POLICY_ACTION_CUSTOM
actionHandler The new action handler.
oldActionHandler The previous action handler (if any) is returned in this parameter.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult writeMinidump ( string dumpPath )


Parameters:
dumpPath Minidump file directory.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult writeMinidump ( )
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

[Link] Interface

This Interface is used for implementing .NET Exception Action handlers.

Member Functions
SCAResult handleAction (Exception e, ref SCAException exception)
Handle the Exception Action.

Member Function Documentation

SCAResult handleAction ( Exception e,


ref SCAException exception )
Parameters:
e .NET Exception to handle
exception If the Signal is replaced with SCAException, the value is returned in this
parameter.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

305
SCA Framework Error Handling

[Link] Class

Static Public Member Functions


static IErrorManager getErrorManager ()
Factory method to create an instance of the .NET ErrorManager.
static IExceptionAction getExceptionAction ([Link] action,
SCAStringSequence parameters)
Factory method to create an instance of ExceptionAction.

Member Function Documentation

static IErrorManager getErrorManager ( )


Returns:
Returns IErrorManager on success; otherwise returns null.

static IExceptionAction getExceptionAction ( [Link]


action, SCAStringSequence parameters )
Parameters:
action The policy action. The possible values are: POLICY_ACTION_REPLACE,
POLICY_ACTION_TERMINATE,
POLICY_ACTION_MINIDUMP,POLICY_ACTION_CUSTOM
parameters Any action specific parameters can be passed here. For example for
POLICY_ACTION_MINIDUMP, parameters[0] is the minidump path.
Returns:
Returns IExceptionAction on success; otherwise returns null.

306
SCA Framework User Document

Chapter 11

Multi-Threaded Applications

307
11. Multi-Threaded Applications
11.1. Introduction
Multithreading is a widespread programming and execution model that allows multiple
threads to exist within a single process. These threads share the process resources but are able
to execute independently. The threaded programming model provides developers with a
useful abstraction of this concurrent execution. The advantage of a multithreaded program is it
allows it to operate faster on computer systems that have multiple CPUs because the threads
can execute concurrently.

When building multi-threaded applications, there are several different aspects of the problem
that need to be addressed.

The various components of the application that are going to be run concurrently in
different threads must be thread-safe. This means that internal data structures in the
components must be protected in such a way that they cannot be corrupted when several
different threads are accessing them concurrently. This is usually done by protecting the
data with various synchronization primitives such as mutexes to lock data structures
against concurrent access and atomic operations.

The application must be able to create and manage multiple threads. Typically you also
want a way of creating and managing data that is unique for each thread and is not shared.

The SCA Framework handles each of these aspects differently which is described in the
following sections.
11.2. Thread Safety
The following portions of the SCA Framework are thread-safe.
Core services like ServiceManager, SharedLibraryManager and TextTranslation
IDL generated support code like the base and factory classes created for services
implemented in C++
Implementation for framework defined types like SCAAny, SCAResult and
SCATypeCode

Utility services like the XML reader and regular expression processor are not thread safe.
These services are not singletons and each user typically gets their own instance.
SCA Framework Synchronization Primitives
The SCA Framework provides a set of synchronization primitives that can be used by services
implemented in C++. For languages other than C++, you should use the threading primitives
provided by those languages. Both Java and the .NET languages have these built into the
language. The SCA provided primitives are implemented on top of the Intel Threading
Building Blocks, or TBB, package. It is not required that these primitives be used in all SCA

308
applications. Typically the use of threading synchronization primitives from different
threading packages in the same application is not a problem.

The following is the header file which defines the threading primitives provide by the SCA
Framework. It provides the following synchronization primitives.
Spin lock and mutex
Recursive lock and mutex
Atomic increment and decrement operations
Atomic counter template
Atomic pointer template

SCA/Threading/Threads.h
//
// Threading support used in SCA Kernel
//

#ifndef SCA_FRAMEWORK_SCATHREADS_H_INCLUDED
#define SCA_FRAMEWORK_SCATHREADS_H_INCLUDED

namespace SCA { namespace Threading {

//
// Single access spin mutex/lock
//
class SpinLock;
class SpinMutex
{
friend class SpinLock;
public:
SpinMutex();
~SpinMutex();
};
class SpinLock
{
public:
SpinLock();
SpinLock(SpinMutex&);
~SpinLock();
void acquire(SpinMutex&);
void release();
private:
SpinLock(const SpinLock&);
SpinLock& operator=(const SpinLock&);
};

//
// Single access recursive mutex/lock
//
class RecursiveLock;
class RecursiveMutex
{
friend class RecursiveLock;
public:

309
RecursiveMutex();
~RecursiveMutex();
};
class RecursiveLock
{
public:
RecursiveLock();
RecursiveLock(RecursiveMutex&);
~RecursiveLock();
void acquire(RecursiveMutex&);
void release();
private:
RecursiveLock(const RecursiveLock&);
RecursiveLock& operator=(const RecursiveLock&);
};

//
// Thread safe atomic increment and decrement operation
//

inline long
AtomicAdd(volatile long& value, long addend);
inline long
AtomicIncrement(volatile long& value);
inline long
AtomicDecrement(volatile long& value);
inline long
AtomicCompareExchange(volatile long& value,
long exchange,
long compare);
template <typename T>
inline T AtomicLoadAcquire(const volatile T& value);
template <typename T, typename V>
inline void AtomicStoreRelease(volatile T& value, const V rhs);

//
// Thread safe Atomic counter class
//

class AtomicCounter
{
public:
typedef long value_type;
// Default constructor
inline AtomicCounter() : value(0);
// Conversion operator
inline operator value_type() const;
// Assignment operator
inline value_type operator=(value_type rhs);
// Assignment operator
inline AtomicCounter& operator=(const AtomicCounter& rhs);
// Addition operator
inline value_type operator+=(value_type rhs);
// Subtraction operator
inline value_type operator-=(value_type rhs);
// Prefix increment operator
inline value_type operator++();
// Prefix decrement operator
inline value_type operator--();
// Postfix increment operator
inline value_type operator++(int);

310
// Postfix decrement operator
inline value_type operator--(int);
// Counter value
value_type value;
private:
// No copy constructor defined
inline AtomicCounter(const AtomicCounter&);
};

//
// Thread safe Atomic pointer class
//

template <typename T>


class AtomicPointer
{
public:
typedef T* value_type;
// Default constructor
inline AtomicPointer() : pointer(0);
// Conversion operator
inline operator value_type() const;
// Assignment operator
inline value_type operator=(value_type rhs);
// Indirect access member operator
inline value_type operator->() const;
// Pointer value
value_type pointer;
private:
// No copy constructor defined
inline AtomicPointer(const AtomicPointer&);
};

} }

#endif

The following example shows a simple class that uses a recursive lock and mutex to only
allow one thread at a time access to some shared data.

#include <map>
#inclued <SCA/SCA.h>
class SafeMap
{
public:
// Method to set value in shared data
void setMap(string key,int value) {
SCA::Threading::RecursiveLock lock(m_mutex);
m_mapData[key] = value;
}
// Method to get data from shared data
int getMap(string key) {
SCA::Threading::RecursiveLock lock(m_mutex);
return m_mapData[key];
}
private:

311
// Map data that must be protected
std::map<string,int> m_mapData;
// Mutex for protecting map data
SCA::Threading::RecursiveMutex m_mutex;
};

The following example shows the use of an atomic counter to implement reference counting
in a class.

class TestClass
{
public:
. . .
void addReference() {
m_refCount++;
}
void releaseReference() {
if(--m_refCount == 0) delete this;
}
private:
SCA::Threading::AtomicCounter m_refCount;
};

Kernel Thread Safety Configuration Options


There is a certain level of overhead associated with insuring that various pieces of the SCA
Framework are thread-safe. If you are running in a single threaded environment you may wish
to disable this feature. The SCA Kernel initialization processing provides the Locking
configuration variable that allows you to turn off the thread safety logic. For details on setting
SCA configuration variables see the SCA Kernel chapter of this manual.
11.3. Threading Infrastructure
The SCA Framework leaves the issues relating to the starting and management of individual
threads to the application. The reason for this is that only the application itself has the
knowledge required to decide how threads should be used and the framework does not want to
impose any restrictions relative to this. As a result the SCA Kernel does not provide any
infrastructure to create and manage threads. Also internally the SCA Kernel does not use or
have any expectation about the availability of multiple threads.

Another reason the SCA Framework has chosen not to provide any thread management
infrastructure is you typically do not want to use more than one threading management
package in a single application. The use of more than one can cause over subscription of
threads because the different packages do not know about each other which could cause
performance issues. Since many of the applications that may want to use the features of the
SCA Framework may already have their own threading support, it could cause problems if the
framework used a different package.
11.4. Testing Multi-Threaded Services
The SCA Framework provides the scautil utility program which provides a number of useful
options. These are described in detail in the SCA Utility Program chapter of this manual. One

312
of the options discussed in that chapter is the –test option which allows you to test SCA
components. The –mtest option is a variant of this which allows you to test the thread safety of
services in a multi-threaded environment.

The use of the -mtest option is similar to the normal -test option except the service driving the
test must implement the SCAIMultiThreadBatchTest interface instead of the
SCAIBatchTest interface. The difference in this interface is that the output from the test
should be returned as a string argument instead of being directly written to stdout. This way
the results of each call can be checked without concern about the output from the various
threads being interspersed.

To run the test, the scautil application gets a single instance of the test service. A call is then
made to the runMultiThreadBatchTest method in the test driver to get a baseline output in a
single-threaded environment. It then creates and starts 25 threads. Each thread makes a single
call to the runMultiThreadBatchTest method. The result of this is 25 different threads will be
exercising the test simultaneously. After all of the threads have finished, the output of each is
compared with the baseline output.

The following is an example of using the –mtest argument.

scautil –mtest [Link]

SCA::Framework::SCAIMultiThreadBatchTest Interface Reference

SCAIMultiThreadBatchTest is the interface used by the scautil program to run batch tests
on any service that implements it. In contrast to SCAIBatchTest, these tests are executed
concurrently by multiple threads. To support the running of tests in a multi-threaded
environment, all the output from the test service should be returned in the output arguments
instead of being directly sending it to stdout. This way the results of the test can be easily
tested without concern about the output from the various threads being interspersed with
each other.

Inherits SCA::SCAIService.

Member Functions
SCAResult runMultiThreadBatchTest (in SCAStringSequence args, out SCAString
output)

Member Function Documentation

SCAResult runMultiThreadBatchTest ( in SCAStringSequence args,


out SCAString output
)

Runs a test on a service.

Parameters:

313
args SCASequence of command line arguments
output The test must not write to stdout, instead all output should be appended to a
string variable and returned through this parameter.

11.5. Sample Multi-Threaded Application


In this section a small application is shown that demonstrates how you can use SCA services
in a multi-threaded environment. This application is actually a stripped down version the
actual scautil code and does the same process as the –mtest option discussed in the previous
section.

This is the execution flow for the application.


Loads a single instance of the service that drives the test.
Casts to the SCAIMultiThreadBatchTest interface.
Calls the runMultiThreadBatchTest method in a single threaded mode to establish a
baseline set of output.
Creates and starts 20 threads with each calling the runMultiThreadBatchTest method.
The output from the test that is run in each thread is compared against the baseline output.
For the threading infrastructure, this sample application uses the Intel TBB library to start and
manage threads. For the details on using the library the Intel TBB documentation should be
consulted.

[Link]
#include <iostream>
using namespace std;

#include <SCA/SCAKernel.h>
#include "SCA/Framework/SCAIMultiThreadBatchTest.h"
#include <SCA/SCAKernel.h>
#include <SCA/StringUtility.h>
using namespace SCA;
using namespace SCA::Framework;

#include <tbb/task.h>
#include "tbb/task_scheduler_init.h"

//
// Global variable for counting complete thread tasks
//
SCA::Threading::AtomicCounter tasksDone;

//
// Task for driving a thread instance
//
class TestThread : public tbb::task
{
public:
TestThread(SCAIMultiThreadBatchTest spTest,
SCAStringSequence args,
SCAString& result)

314
: m_spTest(spTest), m_args(args), m_result(result)
{
};
~TestThread()
{
};
tbb::task* execute()
{
m_spTest->runMultiThreadBatchTest(m_args,m_result);
++tasksDone;
return NULL;
}
private:
SCAIMultiThreadBatchTest m_spTest;
SCAStringSequence m_args;
SCAString& m_result;
};

int main()
{
try {

cout << "Initializing the SCA Kernel" << endl;


initializeSCAKernel(1);

// Load test service


SCAIMultiThreadBatchTest spTest;
spTest = getSCAService("[Link]");

// Get baseline results


SCAString baseline;
SCAStringSequence sqTestArgs;
sqTestArgs.push_back("0");
spTest->runMultiThreadBatchTest(sqTestArgs,baseline);
cout << "*** Baseline results" << endl << baseline << endl;

// Initialize the TBB library


const int numThreads = 20;
tbb::task_scheduler_init init(numThreads);

// Create a list of tasks


tbb::task_list tasks;
SCAString results[numThreads];
for ( SCAInt32 i=0; i<numThreads; i++ ) {
cout << "Allocating task for thread " << i+1 << endl;
sqTestArgs[0] = StringUtility::stringFromInt32(i+1);
TestThread& test = *new(tbb::task::allocate_root())
TestThread(spTest,sqTestArgs,results[i]);
tasks.push_back(test);
}

// Start all the tasks and wait for them to finish


cout << "Starting all threads" << endl << flush;
tbb::task::spawn_root_and_wait(tasks);
cout << flush;

// Make sure all threads finished

315
if ( tasksDone != numThreads )
cout << "***Error: Only " << tasksDone << " of "
<< numThreads << " threads finished" << endl;

// Check each thread result


for ( SCAInt32 i=0; i<numThreads; i++ ) {
if ( results[i] != baseline ) {
cout << "*** Thread " << i+1 << " results are incorrect"
<< endl;
cout << results[i] << endl;
} else {
cout << "*** Thread " << i << " results are correct" << endl;
}
}

// Clean up
spTest = NULLSP;

// Terminate kernel
terminateSCAKernel();

} catch( const SCAException& exc ) {


cout << "Caught SCAException: " << [Link]() << endl;
}

return 0;
}

We also need to implement a thread-safe SCA service to be tested. In this example it is a


simple service that implements the SCAIMultiThreadBatchTest interface. To demonstrate a
use of synchronization primitives, the test service will keep a std::map data structure. A single
instance of this map will be shared by each thread. The runMultiThreadBatchTest method
makes a series of modifications and queries on this data. Since the std::map data structure is
not thread safe itself, a locking primitive is used to gain exclusive use of the structure every
time it is accessed.

The following SDL and CDL files are used to define the service. We do not need to create an
IDL file because the only interface the service is implementing is defined in an IDL file that is
delivered with the SCA Framework.

[Link]
#ifndef THREADTESTER_SDL_INCLUDED
#define THREADTESTER_SDL_INCLUDED

#include "SCA/Framework/[Link]"

module SDK { module ThreadSafety {

service [Link]
{
interface SCA::Framework::SCAIMultiThreadBatchTest;
};

}; };

316
#endif

[Link]
#ifndef THREADTESTER_CDL_INCLUDED
#define THREADTESTER_CDL_INCLUDED

#include "[Link]"

component [Link]
{
service [Link];
};

#endif

The following is the implementation for the service.

ThreadTester.h
#ifndef SDK_THREADSAFETY_THREADTESTER_H_INCLUDED
#define SDK_THREADSAFETY_THREADTESTER_H_INCLUDED

#include "ThreadTesterBase.h"
#include "SCA/Threading/Threads.h"
using namespace SCA;
using namespace SCA::Threading;
#include <map>
using namespace std;

namespace SDK { namespace ThreadSafety {

class ThreadTester : public ThreadTesterBase


{
public:

// Constructor and Destructor


ThreadTester(SCAIThreadTesterFactoryAccess* factoryAccess);
virtual ~ThreadTester();

// Methods for interface [Link]


SCAResult runMultiThreadBatchTest(const SCAStringSequence& args,
SCAString& output);

private:

// Private methods for manipulating map data


void setMap(string,int);
int getMap(string);

// Map data that must be protected


map<string,int> m_mapData;

// Mutex for protecting map data


RecursiveMutex m_mutex;

317
};

} }

#endif

[Link]
#include "ThreadTester.h"
#include "SCA/StringUtility.h"

namespace SDK { namespace ThreadSafety {

// Constructor
ThreadTester::ThreadTester(SCAIThreadTesterFactoryAccess*
factoryAccess)
: ThreadTesterBase(factoryAccess)
{
}

// Destructor
ThreadTester::~ThreadTester()
{
}

// Method to test multi-threaded access to shared map data


SCAResult ThreadTester::runMultiThreadBatchTest(
const SCAStringSequence& args,
SCAString& output)
{
int count = 0;
for ( int j=0; j<50; j++ ) {
for ( int i=0; i<20; i++ ) {
string key = "Key" + args[0] + "_" +
StringUtility::stringFromInt32(i+1);
setMap(key,(100*j+i+1));
}
for ( int i=0; i<20; i++ ) {
string key = "Key" + args[0] + "_" +
StringUtility::stringFromInt32(i+1);
count += getMap(key);
}
}
output = StringUtility::stringFromInt32(count);
return SCASuccess;
}

// Method to set value in map


void ThreadTester::setMap(string key,int value)
{
RecursiveLock lock(m_mutex);
m_mapData[key] = value;
}

// Method to get value from map


int ThreadTester::getMap(string key)
{

318
RecursiveLock lock(m_mutex);
return m_mapData[key];
}

} }

The following is the output from the test. For this test 20 threads were used. The results of the
test show that each of the tests generates the same result as the single threaded baseline call.
This demonstrates that shared data structures are being correctly synchronized. As a simple
test of this you can comment the locking calls in the setMap and getMap methods of the
ThreadTester class and rerun the tests. You will probably get incorrect results or even a crash
because of corruption in the data structures being modified.

Initializing the SCA Kernel


SCA Kernel 4.8.0 successfully initialized
*** Baseline results
353000
Allocating task for thread 1
Allocating task for thread 2
Allocating task for thread 3
Allocating task for thread 4
Allocating task for thread 5
Allocating task for thread 6
Allocating task for thread 7
Allocating task for thread 8
Allocating task for thread 9
Allocating task for thread 10
Allocating task for thread 11
Allocating task for thread 12
Allocating task for thread 13
Allocating task for thread 14
Allocating task for thread 15
Allocating task for thread 16
Allocating task for thread 17
Allocating task for thread 18
Allocating task for thread 19
Allocating task for thread 20
Starting all threads
*** Thread 0 results are correct
*** Thread 1 results are correct
*** Thread 2 results are correct
*** Thread 3 results are correct
*** Thread 4 results are correct
*** Thread 5 results are correct
*** Thread 6 results are correct
*** Thread 7 results are correct
*** Thread 8 results are correct
*** Thread 9 results are correct
*** Thread 10 results are correct
*** Thread 11 results are correct
*** Thread 12 results are correct
*** Thread 13 results are correct
*** Thread 14 results are correct
*** Thread 15 results are correct
*** Thread 16 results are correct

319
*** Thread 17 results are correct
*** Thread 18 results are correct
*** Thread 19 results are correct

It is important to remember that because of the nondeterministic nature of multi-threaded


programs, a single test like this does not guarantee the correctness of the code. A more reliable
testing procedure is to use a tool that is specifically designed to analyze the execution flow of
a multi-threaded application and detect potential race conditions. This tool can be used in
conjunction with the SCA provided test driver to better determine the correctness of the code.

320
SCA Framework SDK

SCA Framework User Document

Chapter 12

Library Metadata and Versioning

321
SCA Framework SDK Library Metadata and Versioning

12. Library Metadata and Versioning


12.1. Introduction
The SCA Framework supports service versioning in the form of version numbers and embedded
metadata. The build system also supports versioning of library names and exported symbols.

Library Metadata
The SCASCons build system provides facilities to embed version numbers
and other metadata in SCA components and shared libraries. The
embedded metadata can be accessed in several ways. The embedded version
numbers can be used for runtime service version checking.

Versioning Scheme

The compatibility of a component is represented by major and minor


versions. The basic idea is that major versions are incompatible and
involve major changes to the API. The minor versions are backward
compatible with older minor versions but not forward compatible with
newer minor versions. The other metadata embedded in the component has
no affect on compatibility.

The following table shows some examples of the type of changes that
will increment version numbers.

Type of Change Increment Increment


major version minor version

Function or method implementation is No No


changed
New interface is added No Yes
New exported function or data is added No Yes
interface is changed Yes Reset to 0
Exported function or data is removed Yes Reset to 0
Exported function’s signature is Yes Reset to 0
changed

The mechanism for specifying the major and minor version numbers for SCA components
and normal shared libraries is described later in this chapter.

Default Metadata Provided by the Build System

Each time a SCA component is built, the SCASCons Build System automatically adds the
following metadata to it.

Metadata Auto Construction Variable Example


Generate
d
Kernel Major YES BUILDINFO_KernelMajorVers 5
Version ion

322
SCA Framework SDK Library Metadata and Versioning

Kernel Minor YES BUILDINFO_KernelMinorVers 1


Version ion
Build Number YES BUILDINFO_BuildNumber CL:53462
Build Date YES BUILDINFO_BuildDate Oct 28 2009
Build Time YES BUILDINFO_BuildTime 14:33:11
Platform YES BUILDINFO_Platform WINNT
Component Name YES BUILDINFO_Name [Link]
tor

All this data can be extracted programmatically from inside the component’s code or directly
from the shared library file using external utilities.

Build Number
The default value is the number of minutes elapsed since January 1,
1970 (epoch in UTC).

By convention for components developed by MSC, the build number is the


unique number provided by MSC’s code management system. For example, in
case of Perforce, it will be the Change List Number.

User Provided Metadata with BUILDINFO_xxx Construction Variables


The build information construction variables of the form
“BUILDINFO_xxx” can be defined in the default SConstruct file for the
component or shared library. See the SCASCons Build System chapter of
this manual for details on how construction variables are defined and
set.

Norm('BUILDINFO_MajorVersion','Major version number',None)


Norm('BUILDINFO_MinorVersion','Minor version number',None)
Norm('BUILDINFO_BuildNumber','Build number',None)

The component developer needs to specify the correct values for the
build information variables in the SConopts file. These values will be
used by all shared libraries and components in the root directory.

# Set version numbers to be embedded


major_version = 5
minor_version = 1
build_number = “CL:56473”

BUILDINFO_MajorVersion = major_version
BUILDINFO_MinorVersion = minor_version
BUILDINFO_BuildNumber = build_number

In order to use different version numbers for different shared


libraries in the same root, the values must be specified in the
SConscript file as shown below.

#
# Set build information
#
[Link](BUILDINFO_MajorVersion = "4")
[Link](BUILDINFO_MinorVersion = "3")

323
SCA Framework SDK Library Metadata and Versioning

[Link](BUILDINFO_BuildNumber = "CL:56473")

In addition to the auto generated data, users can also add their own customized metadata to the
component.

The following shows an example of adding two pieces of metadata to a source tree.

SConstruct
#
# Component metadata
#
Norm('BUILDINFO_ProductName,'Product Name',None)
Norm('BUILDINFO_BuildLabel','Build label',None)

The values of the construction variables are normally set in the “SConopts” file in the root of
the source tree. It is also possible to set these variables on the “scons” command line or in the
“SConscript” files in the various directories in the tree.

SConopts
#
# Set component metadata
#
BUILDINFO_ProductName = “GeomExpert”
BUILDINFO_BuildLabel= “V10”

Each time a component is built the auto defined data and the current values of any user
defined metadata construction variables will be stored in its shared library.

Currently, all BUILDINFO_ construction definitions are global to the source tree they are
defined in. This means that every component built in the same source tree will have the same
build metadata variables. But, it is possible to assign different values to the variables for each
component in the “SConscript” file in the directory where the component is built. Also, the
build metadata is currently managed at a component level and not at a service level.

12.2. Versioning of SCA Components


Mechanism for Specifying the Version Numbers
For SCA components the version numbers are specified in the CDL file.

The versioning is supported at Service level, but currently we can only


specify the version numbers in the CDL file, so all services in the
component must have the same version.

#ifndef SCA_GEOMETRY_VECTOR_CDL_INCLUDED
#define SCA_GEOMETRY_VECTOR_CDL_INCLUDED

#include "[Link]"

component [Link]
{

324
SCA Framework SDK Library Metadata and Versioning

majorVersion 3;
minorVersion 2;

service Vector;
};

#endif

The versioning could be just by major version or by both major and


minor version numbers. To only version the component by the major
version number, do not include the "minorVersion" command in the CDL
file.

The build system supports the automation of version numbers for SCA
components by using the special “MAJORVERSION” and “MINORVERSION”
number flags in the CDL file.

component [Link] {
majorVersion MAJORVERSION;
minorVersion MINORVERSION;

service MessageDispatcher;
};

To support this special format, when the BUILDINFO_MajorVersion and


BUILDINFO_MinorVersion construction variables are defined, the
following defines are automatically added for the IDL compiler.

[Link](SCAIDLDEFINES=['MAJORVERSION='+str(env['BUILDINFO_MajorVersi
on'])])
[Link](SCAIDLDEFINES=['MINORVERSION='+str(env['BUILDINFO_MinorVersi
on'])])

Example:

To version a SCA component is relatively easy because the build system


does much of the work.

The version numbers for the component are set in the CDL file.

#ifndef TESTCOMP_CDL
#define TESTCOMP_CDL
#include "[Link]"

component [Link] {
majorVersion MAJORVERSION;
minorVersion MINORVERSION;
service TestService;
};
#endif

The MAJORVERSION and MINORVERSION symbols used in this example require


that you define the BUILDINFO_MajorVersion and BUILDINFO_MinorVersion

325
SCA Framework SDK Library Metadata and Versioning

construction variables and set the values in the “SConopts” or


“SConscript” file. The following is an example of setting them in the
“SConopts” file.

BUILDINFO_MajorVersion = 10
BUILDINFO_MinorVersion = 4

Service Version Table

Applications and components may maintain a table containing the version


numbers of the compatible services directly used by them. The service
version table, for components, may be embedded in the CDL file and/or
it may be an external xml file. Applications can only use external xml
service tables.

When a service is called using one of the “getService” methods and no


version numbers are provided for the requested service, the SCA Kernel
will first try to look up the service in the service version table, if
one is provided.

The passing of version information when requesting a service is


discussed later in this chapter.

External XML Service Version Table

There is a separate table for each component containing the following


information.

Major and minor version numbers of the supported SCA kernel


Operating system name.
Name, major version and minor version of all required services.

The service table xml file must be provided in the component source directory or the
‘Apps/res/ServiceTables’ directory and must have the name which is generated from the fully
qualified component name and version numbers as shown below.
Component name= [Link]
Major version = 3
Minor version = 2

Service Table Name= SCA_CPP_Geometry_3_2_ServiceTable.xml

For applications the fully qualified table name must be provided.

ServiceTable: C:/GeomExpert/Resources/GeomExpert_ServiceTable.xml

Some sample tables are shown below.

<?xml version="1.0" ?>


<!-- Table of compatible services -->

326
SCA Framework SDK Library Metadata and Versioning

<SCA kernelMajor="4" kernelMinor="8" >


<session os="linux*">
<service name="[Link]" major="4" minor="8"/>
<service name="[Link]" major="3" minor="2"/>
<service name="[Link]" major="6" minor="1"/>
</session>
<session os="*">
<service name="[Link]" major="4" minor="8"/>
<service name="[Link]" major="3" minor="1"/>
<service name="[Link]" major="5" minor="2"/>
</session>
</SCA>

<?xml version="1.0" ?>


<!-- Table of compatible services -->
<SCA kernelMajor="*" kernelMinor="*" >
<session os="*">
<service name="[Link]" major="4" minor="8"/>
<service name="[Link]" major="3" minor="1"/>
<service name="[Link]" major="5" minor="2"/>
</session>
</SCA>

The “os” values in the service version table can use wildcards of the form "*" and
"win*".
The “kernelMajor” and/or “kernelMinor” can be “*”, meaning all Kernel versions are
supported.

CDL Embedded Service Version Table

This type of service version table is specified in the CDL file to be


embedded in the component and contains the following information.

Name, major version and minor version of all required services.


If same service is listed in both the embedded and external tables,
then the version numbers in the embedded table will take precedence.

#ifndef GEOMEXPERT_CDL_INCLUDED
#define GEOMEXPERT_CDL_INCLUDED

#include "[Link]"

component [Link]
{
majorVersion 5;
minorVersion 1;
...
versionTableEntry [Link] 6 2;
versionTableEntry [Link] 3 2;
versionTableEntry [Link] 2 2;
...

327
SCA Framework SDK Library Metadata and Versioning

service GeomExpertService;
};

#endif

Runtime Service Version Checking


The service callers can request a specific or latest version of a
service.

For all cases the SCA kernel verifies the following before getting a
service using the ‘getService’ method.
1. The service is compatible with the SCA Kernel.
2. The service version is compatible with the requested version.

Calling a Service from an Application


The optional xml service version table file name can be passed as
parameter to the “initializeSCAKernel” routine. The optional major and
minor version numbers can be passed as parameters to the getSCAService
routine.

initializeSCAKernel(0,"","/GeomApp/GeomApp_ServiceTable.xml");
. . .
SCAIService spService = getSCAService("[Link]", "3", "2");

Order of Precedence:
Version numbers passed as parameters to the “getSCAService” method.
Specified in the external xml service version table for the calling
component or application.
If no version number is passed the latest service version found in the
service catalog is returned. Versioned services have precedence over
non-versioned services.

Calling a Service from another Service


The “attribute” parameter of the “getService” method is used to pass
the optional version numbers of the requested service. The attributes
are comma delimited.

SCAIService SCAServiceAccess::getService(SCAString name, SCAString


attributes);

Order of Precedence:
Version numbers passed as parameters to the “getService” method.
Specified in the CDL file for the calling component.
Specified in the external xml service version table for the calling
component.
If no version number is passed the latest service version found in the
service catalog is returned. Versioned services have precedence over
non-versioned services.

328
SCA Framework SDK Library Metadata and Versioning

If required an xml service table can be provided in the component’s source directory or the
“Apps/res/ServiceTables” directory. The table name must be derived from the component
name as follows.

Component : [Link] 3.2


Service Table: SCA_CPP_Geometry_3_2_ServiceTable.xml
Examples of Calling Versioned Services

Requesting an exact service version

SCAIService spService;
spService= m_serviceAccess->getService("[Link]","major=4,
minor=1" );

Requesting an exact major version and latest minor version

SCAIService spService;
spService= m_serviceAccess->getService( "[Link]","major=4" );

Requesting the latest version

SCAIService spService;
spService= m_serviceAccess->getService( "[Link]" );

Managing the XML Service Version Tables


The following commands are provided to facilitate the creation of application’s or
component’s service version table. The common arguments used in these commands are
described below.

serviceTable: Either the fully qualified name of the xml table or the component's cdl file.
In the second case the xml table name is generated from the component name
in the cdl file.
session : The optional session name. The default is '*'

List all available SCA services from the Service Catalogs

scautil –listcatalog

Output:

Available SCA Services:


==================
1 [Link] 6.0
2 [Link]
3 [Link] 6.0
4 [Link] 6.0
5 [Link]
6 [Link] 6.0

329
SCA Framework SDK Library Metadata and Versioning

7 [Link] 6.0
8 [Link] 6.0
9 [Link] 6.0
10 [Link] 6.0
11 [Link]
12 [Link]
13 [Link] 6.0
14 [Link]
15 [Link] 6.0
16 [Link] 6.0
17 [Link] 6.0
18 [Link] 6.0
19 [Link] 6.0
20 [Link] 6.0

Add/Update all available versioned SCA services to the service table

scautil –addall serviceTable [session]

Example:

scautil –addall C:/Geometry/Geometry_Vector.cdl win32

Add/Update specified services to the service table.

scautil -add serviceTable services [session]

Example:

scautil -add c:/Geometry/Geometry_Vector.cdl 5,6,8-12,15 win32

The services argument contains the comma delimited item numbers of the services from the
command “scautil –listcatalog”. There must be no spaces between item numbers.

If the service already exists in the table it will be replaced.

List services from the specified service table


scautil -list serviceTable [session]

Example:

scautil -list /Geometry/Geometry_Vector_4_2_ServiceTable.xml win32

Output:
Service Table : /Geometry/Geometry_Vector_4_2_ServiceTable.xml
Kernel Version: 6.0
Session : win32

Services in the Session:


========================

330
SCA Framework SDK Library Metadata and Versioning

1 [Link] 6.0
2 [Link] 6.0
3 [Link] 6.0
4 [Link] 6.0
5 [Link] 6.0

Delete specified versioned services from the service table.

scautil -delete serviceTable services [session]

Example:

versiontool –delete c:/Geometry/Geometry_Vector.cdl 3,5-7,9 win32

The services argument contains the comma delimited item numbers of the services from the
'scautil -list' command. There must be no spaces between item numbers.

12.3. Versioning of Normal Shared Libraries

The normal shared libraries can also be versioned with only the major
version number or both the major and minor version numbers. The
"version=x" parameter of the "[Link]" command to enable
versioning. It can have one of the following values.

True/False - The version for the library is determined by the


"BUILDINFO_MajorVersion"
and "BUILDINFO_MinorVersion" construction
variables.

List - A list which can have 1 or 2 values for the major


and minor version numbers.

When a normal library is versioned, the following CPPDEFINES are


automatically defined as appropriate. These can be used in the code to
version the exported symbol names if required. Note that these
definitions are only made for files compiled in the same directory that
the "[Link]" command is used. If needed in other
directories, they must be manually added.

[Link](CPPDEFINES=[("MAJORVERSION",majorVersion)])
[Link](CPPDEFINES=[("MINORVERSION",minorVersion)])

Versioning of Exported Symbols in the Shared Libraries


It is necessary to version the exported symbols from a shared library
if you want to support the concurrent use of two different versions of
the library. In this case the symbol names must be unique in each
library so there are no clashes between the different versions when
they are loaded at the same time.

When versioning the symbols in a shared library, you normally need to


hard code version number for each symbol in the header files you
deliver with the library. This would be very inconvenient if these
header files had to be manually changed every time you created a new

331
SCA Framework SDK Library Metadata and Versioning

version of the library. To make this easier, you may request the header
files being installed to be preprocessed before they are written. This
can be used to substitute the actual version numbers into the files as
required. This feature is requested with the "preprocess" argument of
the install commands. The value of argument must be a Python map which
contains the symbols that should be substituted by the preprocessor.

vars = {}
vars['MAJORVERSION'] = str(env['BUILDINFO_MajorVersion'])
vars['MINORVERSION'] = str(env['BUILDINFO_MinorVersion'])
[Link]('test.h"),"include",preprocess=vars)

The preprocessing is done by the "pym" preprocessor that is part of the


tools.
This preprocessor is language neutral and requires that you use the
special character
sequences "[<" and "]>" to delineate substitution strings.

typedef class SHLIB_EXPORT TestClass_<[MAJORVERSION]>_<[MINORVERSION]>


{
public:
void meth();
} TestClass;

Also, when the file being installed is preprocessed, the normal


preprocessor command that start with "#", like "#define" and "#ifdef"
are ignored and only variable substitution is performed. This is done
because you normally want the "#" preprocessor commands to apply to the
preprocessing that occurs when the header files are actually used in a
compilation and not to manipulate the contents at installation time.

It may also be desirable to preprocess IDL files as they are installed.


You cannot use the previous procedure for this because the installation
of these files is handled by the build system and is not coded directly
in the SConscript file. To support IDL files, the build system will
scan each IDL files to see if has any preprocessor "[<" or "]>"
sequences in them. If they do then the files will be automatically
preprocessed on installation. In this case you must use the
"IDLPREPROCESS" construction variable to provide the map of
substitution strings.

Example:

The versioning of normal shared libraries is a bit more of an effort


because you must explicitly specify each symbol that is to be exported.
In this example we will version both the library name and the symbols
that are exported from the library.

The following is the definition of the header file "SharedLibrary.h"


for the shared library. This file is delivered to the users of the
library so we will use the preprocessing option on the install command
to substitute the correct version numbers in the definitions of the
exported symbols.

#ifndef SHAREDLIBRARY_H

332
SCA Framework SDK Library Metadata and Versioning

#define SHAREDLIBRARY_H

#include <SCA/SCA.h>

#ifdef SHLIB_BUILD
#define SHLIB_EXPORT SCA_EXPORT_SYM
#else
#define SHLIB_EXPORT SCA_IMPORT_SYM
#endif

typedef class SHLIB_EXPORT TestClass_<[LIBVERSION]>


{
public:
void meth();
} TestClass;

void SHLIB_EXPORT TestFunc_<[LIBVERSION]>();


inline void TestFunc() {
TestFunc_<[LIBVERSION]>();
}

#endif

The first thing done in this header file is to define the correct
settings for the visibility attributes. To do this we use the
"SHLIB_BUILD" macro definition to indicate that the library is being
built rather than being used. If the macro is defined we use the SCA
provided "SCA_EXPORT_SYM" macro to set the correct visibility attribute
for exporting the symbols. When users of the shared library include the
header file in their compilations, they will not have the "SHLIB_BUILD"
macro defined so the "SCA_IMPORT_SYM" macro value is used instead to
indicate the symbols are imported from a shared library they will link
against. In order for this technique to work correctly, each library
used should have its own unique macro to control the definition of the
visibility attributes.

#ifdef SHLIB_BUILD
#define SHLIB_EXPORT SCA_EXPORT_SYM
#else
#define SHLIB_EXPORT SCA_IMPORT_SYM
#endif

Then we define a C++ class that will be exported. For the class
definition we use a "typedef" statement. This definition will create an
exported symbol with the versioned name of "TestClass_X_Y", so it will
not clash with definitions from other versions of the library. But it
will also define an alias of "TestClass" for the class. This allows
the users of the library to use the non-versioned "TestClass" symbol in
their code and not have to worry about the version number. The actual
version number used will be set by the version of header file used when
they compile their application. Using this technique, the conversion to
a newer version of the library will only require a recompile with no
source code changes as long as the API has not changed.

typedef class SHLIB_EXPORT TestClass_<[LIBVERSION]>


{
...

333
SCA Framework SDK Library Metadata and Versioning

} TestClass;

The way to version a global function is similar except a "typedef"


statement cannot be used in a function definition to provide an alias.
Instead we provide a simple inline function that provides access to the
non-versioned name. Most compilers with optimize away this inline
function and there should be no performance penalty from using it.

void SHLIB_EXPORT TestFunc_<[LIBVERSION]>();


inline void TestFunc() {
TestFunc_<[LIBVERSION]>();
}

The following is the implementation file, "[Link]", for our


shared library.
In this case we have used a "#define" to provide the required name
mapping. Because this is only used in the implementation file that is
compiled when the library is built, it will not cause any potential
unintended errors for users of the library. In this example we have
used the "SCAVERNAMEMAJMIN" macro provided by the SCA Framework and
"VersionDefines.h" header file to format the versioned symbol name.
This macro used the CPPDEFINES for "MAJORVERSION" and "MINORVERSION"
that are automatically added by the build tools to determine the
version numbers.

#include <Test/SharedLibrary.h>
#include <iostream>
#include <SCA/VersionDefines.h>

#define TestClass SCAVERNAMEMAJMIN(TestClass)


#define TestFunc SCAVERNAMEMAJMIN(TestFunc)

void TestClass::meth ( )
{
}

void TestFunc()
{
}

One other important thing to notice in this example is that the


“#include” for the header files was <Test/SharedLibrary.h> and not
"SharedLibrary.h". This is important because we must use the
preprocessed version of the header file that is installed instead of
the original file that is in the source directory. Because of the
preprocessor substitution symbols in the source file, compilation
errors will occur if you use it directly.

The final part of this example is the "SConscript" file used to build
the library.
It uses many the following features when building the library.

The installed header file is preprocessed to substitute the correct


version numbers for the exported symbols.
The "[Link]" command is used to change the default visibility
of all symbols not explicitly exported to be "hidden".

334
SCA Framework SDK Library Metadata and Versioning

The "SHLIB_BUILD" macro is defined to indicate we are building and not


using the library.
The new "version" argument on the "[Link]" command is
used to version the name of the generated library.

Here is the complete "SConscript" file.

Import("env_base")
env = env_base.Copy()

#
# Install preprocessed header files
#
vars = {}
vars['LIBVERSION'] = str(env['BUILDINFO_MajorVersion']) + '_' + \
str(env['BUILDINFO_MinorVersion'])
[Link]("SharedLibrary.h","include/Test",preprocess=vars)

#
# Build shared library with hidden symbols
#
[Link](CPPDEFINES="SHLIB_BUILD")
[Link]()
[Link]("SharedLibrary",version=True)

retval = [Link](env_base)
Return('retval')

LIBS and LIBS2 Construction Variable Processing

Versioning of shared libraries require users of these shared libraries


to include the version number in the library names. This may affect
many directories in the source tree and it is inconvenient to have to
change each one of them every time the version of the library changes.
To make this easier, the tools support special processing for the
"LIBS" and "LIBS2" construction variables.
You can use the "[Link]" command to add a mapping of
library names that will be used when the LIBS and LIBS2 variables are
substituted during command generation. This can be used to substitute
the version name in place of the non-versioned name. The mappings added
with the "[Link]" command are global and will affect all
directories processed after the command is executed.

The tools provide the following mappings to automatically substitute


the correct names for the SCA libraries that are commonly used. In
these mappings the SCA Kernel version is X.Y.

[Link]('SCAKernel','SCAKernel_X')
[Link]('SCAKernelUtil','SCAKernelUtil_X_Y')
[Link]('SCAKernelBroker','SCAKernelBroker_X')

There is a restriction that must be followed for the LIBS and LIBS2
mapping to work correctly.

335
SCA Framework SDK Library Metadata and Versioning

If you use commands like “[Link]” to add libraries,


the names will not be mapped. Only names added directly to the LIBS and
LIBS2 variables are mapped.

12.4. Extracting Library Metadata Information


The metadata can be extracted in a variety ways.
Using scautil
The easiest way to extract the metadata is with the scautil utility that is provided with the SCA
Framework.

scautil -buildinfo component_ file [language]

Prints build and product information for the specified component file.

Arguments:

component_file: Component file could be a C++ shared library, a .NET


assembly dll or a Java jar file. For Java and .NET a
fully qualified file name must
language : This optional argument could be 'C++', 'java' or
'.NET'. The default is 'C++'
Examples:

scautil -buildinfo [Link]


scautil -buildinfo vector_4_2.so C++
scautil -buildinfo c:/geometry/vector_4_2.dll .NET
scautil -buildinfo /lib/java/geometry/vector_4_2.jar java

Sample Output:

Build Information for [Link]


Build Date = Sep 3 2010
Build Time = 12:31:14
Kernel Major Version = 5
Kernel Minor Version = 0
Platform = WINNT
Name = [Link]
Major Version = 3
Minor Version = 2
Build Number = CL:53467
ProductName = GeomExpert
BuildLabel = V10

scautil -versionstring shared_library

Prints embedded version string directly from a SCA or non-SCA shared


library binary file. Must specify the fully qualified absolute path
name of the Shared Library file. This option only works for C++ shared
libraries.

Example:

336
SCA Framework SDK Library Metadata and Versioning

scautil -versionstring /SCA/SCAKernel/WINNT/lib/[Link]

Output:

Embedded Version String:


MSC MinorVersion=0, ProductName=SCA Kernel, MajorVersion=6,
BuildLabel=V6-000, BuildVersion=0, ProductLabel=SCA, Platform=WINNT,
BuildDate=May 10 2010, BuildTime=12:53:42

The following environment variable could be set to specify the fully qualified name of the
SCA Kernel configuration file.

SCA_KERNEL_CONFIG_FILE_PATH= /SCA/SCAKernel/res/[Link]

Programmatically within the component


C++ Component
You can also access the build info programmatically from code inside the component. Note
that this will only work from code inside the component because the symbols used are not
exported from the components shared library. The following sample code shows how this can
be done for a sample component.

#include "VectorBuildInfo.h"
using namespace SCA::BuildInfo;
. . .
SCAString major = SCA_Geometry_Vector_MajorVersion();
SCAString minor = SCA_Geometry_Vector_MinorVersion();
SCAString buildNumber = SCA_Geometry_Vector_BuildNumber();
. . .

One routine is generated for each piece of build information. These routines are always in the
“SCA::BuildInfo” namespace and their names are of the form xxx_yyy where xxx is the fully
qualified component name with the periods replaced with underscore characters and yyy is the
name of the BuildInfo variable. In this example, one of the generated routine names is
“SCA_Geometry_Vector_MajorVersion”. This is generated from the fully qualified
component name, “[Link]”, and the “BuildInfo” variable name,
“MajorVersion”. A header file, “VectorBuildInfo.h”, is also generated which declares these
routines and should be included in any routine that is using them.

Java Component
import [Link];
. . .
ComponentFactory compFactory = new ComponentFactory();
String majorVersion = [Link]("MajorVersion");
String buildNumber = [Link]("BuildNumber");

337
SCA Framework SDK Library Metadata and Versioning

C# Component
[Link] compFactory = new
[Link]();
string majorVersion = [Link]("MajorVersion");
string buildNumber = [Link]("BuildNumber");
. . .
VB Component
. . .
Dim compFactory As [Link] = New
[Link]()
Dim majorVersion As String =
[Link]("MajorVersion")
Dim buildNumber As String = [Link]("BuildNumber")
. . .

Using SCAIServiceInfo interface

The SCA Framework provides an interface “SCAIServiceInfo” to query


build metadata from the service. All SCA services implement this
interface.

“SCAIServiceInfo” contains methods whose implementations are auto


generated in the Base or Tie class by the build system (E.g.
“VectorBase” or “VectorTie”). There is no need to include the interface
in the SDL file because it is automatically inserted by the IDL
compiler.

[Link]
interface SCAIServiceInfo : SCAIService
{
SCAResult getBuildInfo( in SCAString sName, out SCAString sValue );
SCAResult getMajorVersion(out SCAString majorVersion );
SCAResult getMinorVersion(out SCAString minorVersion );
SCAResult getBuildNumber(out SCAString buildNumber );
SCAResult getKernelMajorVersion(out SCAString kernelMajorVersion );
SCAResult getKernelMinorVersion(out SCAString kernelMinorVersion );
SCAResult getBuildDate(out SCAString buildDate );
SCAResult getBuildTime(out SCAString buildTime );
SCAResult getPlatform(out SCAString platform );
SCAResult getComponentName(out SCAString componentName );
};

[Link]
service [Link] {
interface SCA::Geometry::SCAIVector;
};

Usage Examples:

C++ Example

SCAIServiceInfo spServiceInfo;

338
SCA Framework SDK Library Metadata and Versioning

spServiceInfo = (SCAIServiceInfo) m_serviceAccess-


>getService(“[Link]”);
if (spServiceInfo) {
SCAString majorVersion;
spServiceInfo->getBuildInfo ("MajorVersion", majorVersion);
cout << "MajorVersion=" << majorVersion << endl;
spServiceInfo = NULLSP;
}
else {
cout << "Service " << sName << " does not implement SCAIServiceInfo"
<< endl;
}

VB Example
. . .
Dim spService As [Link] = getService("[Link]")
Dim spServiceInfo As SCAIServiceInfo =
DirectCast([Link]("[Link]"),
SCAIServiceInfo)
If spServiceInfo Is Nothing Then
[Link]("Service [Link] does not implement
SCAIServiceInfo")
Else
Dim majorVersion As String = ""
[Link]("MajorVersion", majorVersion)
[Link]("MajorVersion=" + majorVersion)
spServiceInfo = Nothing
End If
. . .

C# Example
. . .
SCAIService spService = getService("[Link]");
SCAIServiceInfo spServiceInfo =

(SCAIServiceInfo)[Link]("[Link]"
);
if (spServiceInfo != null)
{
string buildNumber;
[Link]("BuildNumber", out buildNumber);
[Link]("BuildNumber =" + buildNumber);
spServiceInfo = null;
}
else
{
[Link]("Service [Link] does not implement
SCAIServiceInfo");
}
. . .

Java Example
. . .
SCAIService spService = getService("[Link] ");
SCAIServiceInfo spServiceInfo =

339
SCA Framework SDK Library Metadata and Versioning

(SCAIServiceInfo)[Link]("[Link]"
);
spService = null;
if (spServiceInfo != null)
{
Holder<String> majorVersion = new Holder<String>();
[Link]("MajorVersion", majorVersion);
[Link]("MajorVersion=" + [Link]);
spServiceInfo = null;
}
else
{
[Link]("Service [Link] does not implement
SCAIServiceInfo");
}

Since versioning is at the component level, the methods of this


interface return the build information metadata from the component. All
services in the component return the same information.

This interface is only implemented on top level service objects.

Using SCAIComponentInfo Interface

The “SCAIComponentInfo” interface can be used to retrieve the


information directly from the component file in a language independent
manner.

The component file could be a C++ shared library, a .NET assembly dll or a Java jar file.
The “getComponentInfo” method is used to query version numbers and other embedded
metadata from the component library. Another method “getServiceVersionTable” is used to
query the embedded service version table.
[Link]

interface SCAIComponentInfo : SCAIService


{
/**
@brief Returns the component info embedded in the component library

@param compPath Fully qualified path of the component file


@param language Language of the component ‘C++’, ‘java’ or ‘.NET’
@param sName Name of the embedded build information to retrieve
@param sValue The build information retrieved from the component
@return SCASuccess if successful, else returns an error code.
*/
SCAResult getComponentInfo(in SCAString compPath, in SCAString
language,
in SCAString sName, out SCAString
sValue);

/**
@brief Returns the service version table embedded in the component
library

340
SCA Framework SDK Library Metadata and Versioning

@param compPath Fully qualified path of the component file


@param language Language of the component ‘C++’, ‘java’ or
‘.NET’
@param serviceTable The service version table retrieved from the
component
@return SCASuccess if successful, else returns an error code.
*/
SCAResult getServiceVersionTable(in SCAString compPath,
in SCAString language,
out SCAStringSequence serviceTable);
};

Usage Example:
This example shows how to query the embedded metadata and the service
version table from a .NET component’s assembly file “[Link]”
using SCAIComponentManager interface. Error handling is removed to
emphasize the usage.

C++ Code

SCAIComponentIndo spCompInfo;
spCompInfo = getSCAService ("[Link]");

if (spCompInfo) {
SCAString buildNumber;
spCompInfo->getComponentInfo ("/geometry/[Link]",
".NET", "BuildNumber", buildNumber);

cout << "BuildNumber = " << buildNumber << endl;

SCAStringSequence stringSequence;
compInfo->getServiceVersionTable("/geometry/[Link]",
".NET", stringSequence);
if ( [Link]() > 0 ) {
cout << "Service Version Table:" << endl;
for (unsigned i=0; i < [Link](); i++)
{
cout << stringSequence.r_at(i) << endl;
}
}

spCompInfo = NULLSP;
}

Using External Manifest Utility (versioninfo)

The build metadata is also embedded in the component or shared library


as a static string, which can be extracted directly from the binary
file using the external manifest utility. This however is a very slow
process and only suitable for use by support people to display version
information. NOT suitable for runtime checking by client applications
and services. Only works for C++ shared libraries.

341
SCA Framework SDK Library Metadata and Versioning

versioninfo -versionstring shared_library

Prints embedded version string directly from a SCA or non-SCA shared


library binary file. Must specify the fully qualified absolute path
name of the Shared Library file. This option only works for C++ shared
libraries.

Example:
versioninfo -versionstring /SCA/SCAKernel/WINNT/lib/[Link]

Embedded Version String:


MSC MinorVersion=0, ProductName=SCA Kernel, MajorVersion=6,
BuildLabel=V6-000,
BuildVersion=0, ProductLabel=SCA, Platform=WINNT, BuildDate=May 10
2010,
BuildTime=12:53:42

342
SCA Framework User Document

Chapter 13

Configuring and using the SCA


Kernal

342
13. Configuring and Using the SCA Kernel
13.1. Introduction
The SCA Framework provides an infrastructure to facilitate the design, coding and building of
applications. All access to these facilities is through a set of common services and interfaces
provided by the framework. The SCA Kernel portion of the framework provides the runtime
core functionality required by the framework. This includes the loading, unloading and
lifecycle management of services and shared libraries and the processing of messages and
events.

The SCA Kernel is composed of the following services.

ServiceManager which is responsible for loading and unloading of services.


SharedLibraryManager which is responsible for loading and unloading of shared libraries.
TextTranslation which provides the core message processing functions.
EventManager which provides facilities for event processing.

The TextTranslation service is described in the Messaging and Internationalization chapter in


this manual and the EventManager is described in the SCA SDK Advanced Features manual.
The rest of these services are discussed in this chapter.

The SCA Kernel is delivered in the SCAKernel shared library. There is also a SCAKernelUtil
shared library that is part of the kernel. The utility library is statically linked against the
SCAKernel shared library and all SCA components.
13.2. Initializing and Terminating the Kernel
The SCA Kernel must be initialized by the application before any services may be loaded.
When the kernel is initialized, a set of configuration data is required. This data can come from
environment variables or from a XML configuration file. Using configuration file is
recommended because there is less chance of conflicting environments between two different
applications using the SCA Kernel.

This section shows the API that is used for the initialization and termination of the SCA
Kernel in all supported languages. Code examples in each language are provided later in this
chapter.
SCA Kernel Initialization API
The following API is provided to initialize the SCA Kernel

C++
void initializeSCAKernel( SCA::SCAInt32 verbose=0,
const SCA::SCAString& configPath="")

Java
void [Link]()

343
void [Link](String configPath)

C#
void [Link]()
void [Link](string configPath)

Visual Basic
Sub [Link]()
Sub [Link](String configPath)

Python
import SCA

Each of these calls will throw a SCASystemException exception if errors occur trying to
initialize the kernel.

The configPath argument in each of these calls is the name of the XML configuration file. If it
is an empty string, the SCA Kernel is configured with environment variables. For Python the
name of the configuration file must be provided on the Python command line which is
discussed later in this chapter.

The verbose argument controls the amount of the output generated by the initialization
routines. If nonzero, the version of the SCA Kernel that is loaded will be printed.
SCA Kernel Termination API
The following API is provided to terminate the SCA Kernel

C++
SCA::SCAInt32 terminateSCAKernel()
SCA::SCAInt32 terminateSCAKernel(SCAStringSequence& orphans)

Java
void [Link]()

C#
void [Link] ()

Visual Basic
Sub [Link]()

Python
None available

Each of these calls will throw a SCASystemException exception if errors occur trying to
terminate the kernel.

It is not required to explicitly terminate the SCA Kernel in your application. The required
termination processing will automatically occur when the application terminates. You can

344
explicitly terminate the kernel at an earlier point if you want to release any resources it is
using.

It is important to understand that the call to terminate of the SCA Kernel does not force the
deleting of any SCA service objects instances that may still exist. The fact the instances still
exist means that there are active references to them from somewhere else in the application. If
the instances were forcibly deleted with active reference to them this could cause the
application to crash at a later time. Instead these instances are left alone but they are
disconnected from the SCA ServiceManager. This way the ServiceManager and other
services in the kernel can still release their resources and terminate. When the active
references to the left over service objects are finally remove, then they will automatically
delete themselves. This process is called orphaning. Some of languages provide a termination
call that will optionally provide a list of any orphaned services.

Examples of Configuring the SCA Kernel


The following simple examples show the use of the API to initialize and terminate the SCA
Kernel in each of the supported languages. The examples do no useful work but are just
provided to show the use of this API.

C++
#include <iostream>
#include <SCA/SCAKernel.h>
using namespace std;
using namespace SCA;

int main()
{
try {
cout << "Initializing the SCA Kernel" << endl;
initializeSCAKernel(1);
. . .
cout << "Terminating the SCA Kernel" << endl;
terminateSCAKernel();
} catch(SCAException& e) {
cout << "Error: " << [Link]() << endl;
}
return 0;
}

Java
import SCA.*;
import [Link].*;

public class Client{


public static void main (String args[]) {
try{
[Link]("Intitialize the SCA Kernel");
[Link]();
. . .
[Link]("Terminate the SCA Kernel");
[Link]();

345
} catch (SCASystemException e) {
[Link]("Error: " + [Link]());
}
}
}

C#
using System;
using SCA;

class ClientCS
{
static void Main(string[] args)
{
try {
[Link]("Initialization the SCA");
[Link]();
. . .
[Link]("Terminate the SCA");
[Link]();
} catch (SCAException e) {
[Link]("Error: " + [Link]());
}
}
}

Visual Basic
Imports SCA
Imports System

Module ModuleMain
Sub Main(ByVal args As String())
Try
[Link]("Initialize the SCA Kernel")
[Link]()
. . .
[Link]("Termination the SCA Kernel")
[Link]()
Catch e As SCAException
[Link]("Error: " + [Link]())
End Try
End Sub
End Module

Python
try:
print "Initializing the SCA Kernel"
import SCA
except [Link], e:
print "Error:",[Link]()
. . .

346
13.3. Kernel Configuration Variables
The SCA Kernel uses a set of configuration variables to help it locate required resources,
libraries and to define other options. The configuration variables can be set using environment
variables or from a XML configuration file, but not both. If a configuration file is used, the
environment variables have no effect on that kernel.

The following configuration variables are currently supported. For each configuration variable
the environment variable associated with it is given.

Variable Name Environment Variable Value Type


KernelLibPath N/A path
Resource SCA_RESOURCE_DIR List of paths
Catalog SCA_SERVICE_CATALOG List of paths
XMLParser SCA_XML_PARSER_DIR List of paths
JavaPath SCA_JAVA_COMP_PATH List of paths
JVMConfig SCA_JVM_CONFIG List of options
LibraryPath SCA_LD_LIBRARY_PATH List of paths
Debug SCA_KERNEL_DEBUG List of options
Locking SCA_KERNEL_LOCKING on or off
StdoutListener SCA_STDOUT_LISTENER List of options
FileLogListener SCA_FILELOG_LISTENER List of options
SyslogListener SCA_SYSLOG_LISTENER List of options
ErrorManager SCA_ERROR_MANAGER List of options
MinidumpPath SCA_MINIDUMP_PATH path

The SCA_ prefix of each environment variable in the above table can be changed by the
application. The API for this is discussed in a later section of this chapter.

The following table provides the description and default value for each configuration variable.

Variable Name Description and Default Value


KernelLibPath Defines the path where the SCA Kernel shared library was loaded
from. This value is determined internally by the kernel and cannot be
set by the application.
Resource Defines a set of paths for the location of the SCA resource
directories. The default uses the KernelLibPath configuration value
and is directory KernelLibPath/../../res.
Catalog Defines a set of paths for the files or directories where the SCA
service catalog information is obtained. The default value is the file
[Link] in each of the directories specified in the
Resource configuration value. At least one of these must exist.
XMLParser Defines a set of paths for the directories the XML parser service will
search for XML files. The search order used by the XML parser is to

347
first look in the directories defined by this value and then to look in
the directories defined by the Resource configuration value. If the
requested XML file is not in any of these directories it looks in the
current directory.
JavaPath Defines a set of paths for the root locations for loading Java
components. The default value is the directory
RESOURCE/../lib/java where RESOURCE is each of the directories
specified in the Resource configuration value.
JVMConfig Defines a set of configuration options for the Java virtual machine.
Multiple options are separated by commas. See the Java Mapping
chapter of this manual for a discussion of when this value is used and
what its default is.
LibraryPath Defines a set of paths for the root locations of C++ and .NET
components. The default value is taken from the appropriate system
environment library variable on the current platform (for example,
PATH on WINDOWS and LD_LIBRARY_PATH on Linux).
Debug Defines a set of debug output options. Multiple options are separated
by commas. The default is to generate no debug output.
Locking Specifies if thread safety is required for SCA Kernel. The default
value is on.
StdoutListener Disable the stdout logging listener by setting the optional value to be
off or one of the following logging filters.
Debug
Information
Warning
Error
Only messages with severity higher than or equal to the filter value
will be logged. The default filter is Debug, which is the lowest
severity and will cause all messages to be logged.
See the “Logger Service” chapter for examples of setting the listener
variables.
FileLogListener Enables the file logging listener. The value specifies the log file
path and/or the logging filter.

SyslogListener Enables the listener for logging to Windows Event Log or Linux
syslog. The optional value specifies the logging filter and/or the log
source.
ErrorManager List of options for the Error Manager. Currently, only one of the
following values can be specified.
value = “Enabled=yes” enables the Error Manager

348
value = “Enabled=no” disables the Error Manager
MinidumpPath Defines a path for minidump files
See “Error Handling” chapter for more details

13.4. Kernel Configuration File


An example XML configuration file is shown below.

[Link]
<?xml version="1.0"?>
<SCA>
<session os="win32">
<tmp name="%APPSYS%" value="%SCAKERNEL_LIBPATH%/../.."/>
<env name="%APPLOC%” value="MY_APPS_LOCAL"/>
<var name="Resource" value="%APPLOC%/res;%APPSYS%/res"/>
<tmp name="%TYPEJAR%" value="%APPLOC%/lib/java/[Link]"/>
<var name="JVMConfig" value="-[Link]=%TYPEJAR%"/>
<var name="Locking" value="off"/>
<var name="ErrorManager" value="Enabled=yes"/>
<var name="MinidumpPath" value="c:/temp/minidumps"/>
<var name="FileLogListener" value="C:/temp/[Link],Debug"/>
<var name="SyslogListener" value="Error"/>
<var name="StdoutListener" value="off"/>
</session>
<session os="linux32">
<tmp name="%APPSYS%" value="%SCAKERNEL_LIBPATH%/../.."/>
<env name="%APPLOC%” value="MY_APPS_LOCAL"/>
<var name="Resource" value="%APPLOC%/res:%APPSYS%/res"/>
<tmp name="%TYPEJAR%" value="%APPLOC%/lib/java/[Link]"/>
<var name="JVMConfig" value="-[Link]=%TYPEJAR%"/>
<var name="Locking" value="off"/>
</session>
</SCA>

The configuration files following the following rules.

The root tag must be <SCA>


The options for each platform should be grouped inside a <session> tag. A session must
exist for the platform you are running on.

If the value type is a list of paths, the paths must be separated by either a colon or
semicolon depending on the current platform.
If the value type is list of options, the options are separated by commas.
The syntax <var name=”X” value=”Y”> sets the configuration variable X = Y
The syntax <tmp name=”T” value=”S”> specifies a temporary variable T = S

349
The syntax <env name=”E” value=”N”> specifies a temporary variable whose value is
set to the value of the specified environment variable. E = NVAL where NVAL is the
value of environment variable N. A configuration error will occur if the specified
environment variable is not set.
While not required, the convention is for all temporary variable names to be enclosed in
percent signs such as %T% so they are easily distinguished from real configuration
values. The value of these variables will be substituted verbatim for all occurrences of the
name in the remaining entries in the current session.
The temporary variable %SCAKERNEL_LIBPATH% is a reserved name that stands
for the directory where the shared library for the SCA Kernel was loaded from. It is
determined by the SCA Kernel at runtime.

The following are the supported platform names.

win32
win64
aix
alpha
hpux
irix
hpuxipf
solaris
linux64
linux32
linuxipf

The following is an example of a simple setting of a configuration variable. This example sets
the value of the Locking variable to off.

<var name="Locking" value="off"/>

The configuration process supports the concept of temporary variables. Temporary variables
can be used to create a value that can subsequently be used in the setting of several
configuration values. This way the logic does not need to be repeated in more than one
configuration entry. Temporary variables may also be used to include the settings for system
environment variables in the configuration settings. The convention for temporary variable
names is to enclose them in percent signs like %APPLOC%. While this is not a requirement, it
is a good practice because it reduces the chance that the name of the temporary variable will
appear elsewhere in a configuration value which could cause undesired substitutions. Every
occurrence of the temporary variable name in all of the entries in the current session will be
substituted with its value. Note that this substitution occurs in every entry, even those that
appear before the definition of the temporary variable in the configuration file.

350
To include the setting of a system environment variable in the configuration you must first set
a temporary variable with its value. Only temporary variable names can be set to the value of
an environment variable. You cannot directly set an actual configuration variable. The
following is a sample configuration file entry that sets the temporary variable %APPLOC% to
the current value of the environment variable MY_APPS_LOCAL.

<env name=”%APPLOC%” value="MY_APPS_LOCAL” >

Temporary variable names can also be set in the configuration file. In this example the
%TYPEJAR% temporary variable is set to a string value. In this case the string value used
contains an instance of another temporary variable and its value will be substituted during the
process.

<tmp name="%TYPEJAR%" value="%APPLOC%/lib/java/[Link]"/>

The special reserved temporary variable of %SCAKERNEL_LIBPATH% is set by the


SCA Kernel to the directory where the actual SCA Kernel shared library was loaded from.
This value can then be used to set other values in the configuration file.

<tmp name="%APPSYS%" value="%SCAKERNEL_LIBPATH%/../.."/>

Default Configuration File Location


The SCA Kernel provides a set of default locations for the XML configuration file. If a special
string, auto, is specified as the configuration path, the SCA Kernel will look for the following
files and use the first one it finds. All of these locations are relative to the value of the
KernelLibPath configuration value.

KernelLibPath/[Link]
KernelLibPath/../bin/[Link]
KernelLibPath/../../res/[Link]

The following is an example of using this feature.

C++
initializeSCAKernel(1,"auto");

13.5. Runtime Access to Configuration Variables


The following API is provided to access the configuration variables at runtime. These
functions are currently only available in C++.

SCAStringSequence SCA::getSCAEnv( const SCAString variable )


SCAString SCA::getSCAEnvValue( const SCAString variable )

The definition of these symbols is in the SCA/KernelConfiguration.h include file delivered


with the SCA Framework.

351
The first routine returns a sequence of strings containing paths or options that were set for the
requested variable.

The second routine returns a single string value of the configuration variable. The function
should only be used for single value options, such as Locking. For multi-value options it will
only return the first value.
13.6. Changing the Prefix for Environement Variable Names
When using environment variables to configure the SCA Kernel, the default name of each
environment variable starts with SCA_. There may be cases where this may cause conflicts
with other requirements of your application. The following API is provided which allows you
to change this prefix.

SCA_EXPORT SCAVoid setSCAEnvPrefix( const SCAString prefix );


SCA_EXPORT SCAString getSCAEnvPrefix( );

The following example call will change the configuration process so each of the configuration
values will use an environment variable with a name like MYAPP_RESOURCE_DIR instead
of SCA_RESOURCE_DIR.

setSCAEnvPrefix("MYAPP");

Current these functions are only available in C+.


13.7. Building Applications using the SCA Kernel
The only special requirement when building an application using the SCA Framework is the
executable or shared library that does the actual initialization of the SCA Kernel needs to be
linked with the SCAKernel and SCAKernelUtil shared libraries. These libraries are provided
with the SCA Framework. The following SCASCons SConscript file can be used to build the
executable for a simple application that uses the SCA Framework.

Import("env_base")
env = env_base.Copy()

#================= Perform local customization here =================

[Link](LIBS=["SCAKernel","SCAKernelUtil"])
[Link]("Client")

#====================================================================

retval = [Link](env_base)
Return('retval')

For more information on the use of the SConscript files, see the SCASCons Build System
chapter in this manual.

352
13.8. Running Applications using the SCA Kernel
The following example CSH scripts show what is required to run an application using the
SCA Framework written in each of the supported languages. In this case a very simple
configuration is used and the required values are set using environment variables. The
Resource configuration value is the only value that is set.

C++
#! /bin/csh
#
set ILOCAL = D:/Builds/Initialization/Apps
set DLOCAL = $ILOCAL/WINNT
#
set ISYSTEM = D:/Kernel-WINNT/Apps-Opt
set DSYSTEM = $ISYSTEM/WINNT
#
set path = ( $DLOCAL/bin $DLOCAL/lib $DSYSTEM/bin $DSYSTEM/lib $path )
#
setenv SCA_RESOURCE_DIR "$ISYSTEM/res"
#
$DLOCAL/bin/[Link]

Java
#! /bin/csh
#
set ILOCAL = D:/Builds/Initialization/Apps
set DLOCAL = $ILOCAL/WINNT
#
set ISYSTEM = D:/Kernel-WINNT/Apps-Opt
set DSYSTEM = $ISYSTEM/WINNT
#
set path = ( $DLOCAL/bin $DLOCAL/lib $DSYSTEM/bin $DSYSTEM/lib $path )
#
setenv JRE /ThirdParty/jdk/1.6.0/WINNT
set JAVALIB = $ILOCAL/lib/java
set path = ( $path $JRE/jre/bin/client )
#
setenv SCA_RESOURCE_DIR "$ISYSTEM/res"
#
$JRE/bin/java -Xms256m -Xmx512m –cp \
"$JAVALIB;$JAVALIB\[Link];$JAVALIB\[Link]" Client

C# or Visual Basic
#! /bin/csh
#
set ILOCAL = D:/Builds/Initialization/Apps
set DLOCAL = $ILOCAL/WINNT
#
set ISYSTEM = D:/Kernel-WINNT/Apps-Opt
set DSYSTEM = $ISYSTEM/WINNT
#
set path = ( $DLOCAL/bin $DLOCAL/lib $DSYSTEM/bin $DSYSTEM/lib $path )
#
setenv SCA_RESOURCE_DIR "$ISYSTEM/res"
#

353
$DLOCAL/bin/[Link]

Python
#! /bin/csh
#
set ILOCAL = D:/Builds/Initialization/Apps
set DLOCAL = $ILOCAL/WINNT
#
set ISYSTEM = D:/Kernel-WINNT/Apps-Opt
set DSYSTEM = $ISYSTEM/WINNT
#
setenv PYTHONPATH "$ISYSTEM/lib/python;$DSYSTEM/bin"
setenv PYTHONHOME /ThirdParty/Python/2.5.0-1/WINNT
#
set path = ( $DLOCAL/bin $DLOCAL/lib $DSYSTEM/bin $DSYSTEM/lib $path )
set path = ( $PYTHONHOME/libs $path )
#
setenv SCA_RESOURCE_DIR "$ISYSTEM/res"
#
$PYTHONHOME/python ClientPy/[Link]

With the exception of Python, the only change to these scripts to use a XML configuration
files would be to remove the setting of the SCA_RESOURCE_DIR environment variable. The
initialization for the SCA Kernel in the source code for the application would also have to be
changed to include the name of the XML configuration file. For this simple example, the
following XML configuration file is equivalent to the previous environment variable
examples.

[Link]
<?xml version="1.0"?>
<SCA>
<session os="win32">
<var name="Resource" value="%SCAKERNEL_LIBPATH%/../../res"/>
</session>
<session os="win64">
<var name="Resource" value="%SCAKERNEL_LIBPATH%/../../res"/>
</session>
<session os="linux32">
<var name="Resource" value="%SCAKERNEL_LIBPATH%/../../res"/>
</session>
<session os="linux64">
<var name="Resource" value="%SCAKERNEL_LIBPATH%/../../res"/>
</session>
</SCA>

An example of a modified initialization call follows.

initializeSCAKernel(1,"[Link]");

The API to initialize the SCA Kernel in Python does not provide the ability to specify the
name of a XML configuration file. In Python, you must include this information on the
command line that runs the Python interpreter. In the above sample script for Python we
would use the following line to accomplish this.

354
$PYTHONHOME /python ClientPy/[Link] -SCAConfig="[Link]"

13.9. The SCA Services Catalog


The SCA service catalogs are XML files used by the SCA Kernel to determine which services
are available and in which component they are contained. These catalog files are created by
the SCASCons build system when you build your components and normally they should not
be manually changed.
SCASCons Build options for catalog processing
The SCASCons build system can create either a single XML service catalog with entries for
all the components it builds in the current source tree or it can create a separate XML file for
each component. The use of separate XML files can make the delivery of SCA components to
other users easier if more than one component is built in the same source tree. With this option
it is easier to package up and install the files for a component because all of its information is
in files unique to the component. If the single XML file option is used, then the installation
procedure has to update an existing catalog file or create a new one for each component
installed which complicates the process. If you are not delivering the components separately
you may wish to use a single XML catalog file because it is slightly more efficient.

The following examples shows how the construction variables for the SCASCons build
system are used to control these options.

Single Catalog File:


SCACATALOGDIR = ‘$APPS_LOCAL/res’
SCACATALOG = ‘[Link]’

Separate catalog file for each SCA component:


SCACATALOGDIR = ‘$APPS_LOCAL/res/catalog’
SCACATALOG = ‘split_by_component’

For more information on the setting of build system construction variables, see the
SCASCons Build System chapter in this manual.

Catalog Configuration Options


The Catalog configuration variable is used to specify the locations of the SCA service
catalogs. It contains a list of path entries where each one can point to either a single catalog
file or to a directory. If the entry is a directory then every XML file in that directory will be
read and each one must be a valid catalog file.

If the Catalog configuration value is not defined the kernel will look for the file
[Link] in each directory included in the Resource configuration value.
Service Catalog Precedence Rule for Duplicate Entries
If the same service is defined in more than one catalog file, the first one found will be used.
Any subsequent entries will be ignored.

355
Sample Service Catalog File
The following is a sample SCA service catalog file.

<?xml version="1.0" ?>


<SCA>
<component language="C++" library="SCAKernel" name="SCAKernel">
<service name="[Link]" />
<service name="[Link]" />
<service name="[Link]" />
<service name="[Link]" />
<service name="[Link]" />
</component>
<component language="C++" library="SCA/Framework/MessageDispatcher"
name="[Link]">
<service name="[Link]" />
</component>
</SCA>

13.10. Other Configuration Files


The SCA Kernel also requires several other types of configuration files.
IDL Type Definitions Files
To support the various dynamic features of the SCA Framework like scripting and the
SCAAny data type, the SCA Kernel needs to know information about the various interfaces
and types that are defined in IDL files. For details on these features see the IDL Language
chapter in this manual and SCA SDK Advanced Features manual. The SCA Kernel gets this
type information from a set of XML files generated by the IDL compiler. These files are
stored in the directory RESOURCE/types where RESOURCE is each of the directories
specified in the Resource configuration value.
Message Files
Application defined messages are stored in XML files that are installed as part of the build
process. These XML files are stored in the directories specified by the Resource configuration
value or in a subdirectory of them. See the Messages and Internationalization chapter of this
manual for complete details on these XML files and how they are located.
Language Support Files
The SCA Kernel requires several XML configuration files which define the supported
languages and country codes available to internationalize messages. These files must be stored
in one of the directories specified by the Resource configuration value.
1. [Link]
2. [Link]
The language support files are discussed in detail in the Messages and Internationalization
chapter of this manual.

356
13.11. Service Manager
The ServiceManager service provides important interfaces for managing the available
services. These interfaces expose methods to load services and to query kernel information
and available services. This section describes these interfaces and provides examples to
illustrate their usage.

SCA::Framework::SCAIServiceProvider Interface Reference

Interface used to load SCA services.

Inherits SCA::SCAIService.

Member Functions
SCAResult getService (in SCAString sName, in SCAString sAttr, out SCAIService
spService)

Member Function Documentation

SCAResult getService ( in SCAString sName,


in SCAString sAttr,
out SCAIService spService
)

Loads a SCA service.

Parameters:
[in] sName Fully qualified name of the service to load
[in] sAttr Additional keyword=value attributes to specify additional
information about the service to be loaded
[out] spService SCAIService interface to the loaded service
Return values:
SCAResult Status of the request

The SCAIServiceProvider interface implemented in the ServiceManager is the only way to


load a SCA service. The various language bridges and mappings provide different APIs to
load services. For example the C++ language mappings provides the routine
m_serviceAccess.getService()for loading services when inside other SCA services or the
routine getSCAService when external to a SCA service. But all of these APIs eventual use the
SCAIServiceProvider interface to do the actual loading of the service.

SCA::Framework::SCAIKernelInfo Interface

SCAIKernelInfo is used to query the Kernel version and other information

357
Member Functions
SCAResult getMajorVersion (out SCAString sMajorVersion)
SCAResult getMinorVersion (out SCAString sMinorVersion)
SCAResult getBuildVersion (out SCAString sBuildVersion)

Member Function Documentation


SCAResult getBuildVersion ( out SCAString sBuildVersion )
Returns the build version.

Parameters:
sBuildVersion Build version
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getMajorVersion ( out SCAString sMajorVersion )

Returns the major version .

Parameters:
sMajorVersion Major version
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getMinorVersion ( out SCAString sMinorVersion )

Returns the minor version.

Parameters:
sMinorVersion Minor version
Returns:
Returns SCASuccess on success, else returns an error.

The following example demonstrates how to get the Kernel version and build date using the
SCAIKernelInfo interface.

#include <SCA/Framework/SCAIKernelInfo.h>
#include <SCA/StringUtility.h>

namespace std;
using namespace SCA;
using namespace SCA::Framework;

358
// Get Kernel Version and build date
SCAIKernelInfo spInfo;
spInfo = getSCAService("[Link]");
SCAString sMajor,sMinor,sBuild;
spInfo->getMajorVersion(sMajor);
spInfo->getMinorVersion(sMinor);
spInfo->getBuildVersion(sBuild);
cout << "SCA Kernel version is " << sMajor << "."
<< sMinor << "." << sBuild << endl;
SCAString sDate,sTime;
spInfo->getBuildDate(sDate);
spInfo->getBuildTime(sTime);
cout << "SCA Kernel was built on " << sDate << " at "
<< sTime << endl;
spInfo = NULLSP;

SCA::Framework::SCAIServiceCatalog Interface

SCAIServiceCatalog is used to manage the service catalog

Member Functions

SCAResult getAvailableServices (out SCAStringSequence sqServices)


SCAResult getServiceInfo (in SCAString sName, out ServiceInfo info)

Member Function Documentation

SCAResult getAvailableServices ( out SCAStringSequence sqServices )

Gets the list of available services.

Parameters:
sqServices Available services
Returns:
Returns SCASuccess on success, else returns an error.

SCAResult getServiceInfo ( in SCAString sName, out ServiceInfo info )

Gets the service information.

359
Parameters:
sName Service name
info Service information
Returns:
Returns SCASuccess on success, else returns an error.

This example demonstrates how to get the list of services and query information on them
using the SCAIServiceCatalog interface.

#include <iostream>
#include <SCA/Framework/SCAIKernelInfo.h>
#include <SCA/Framework/SCAIServiceCatalog.h>
#include <SCA/StringUtility.h>

using namespace std;


using namespace SCA;
using namespace SCA::Framework;

// Query the available services and get service information


SCAIServiceCatalog spCatalog;
spCatalog = getSCAService("[Link]");
SCAStringSequence services;
spCatalog->getAvailableServices(services);
for ( size_t i=0; i<[Link](); i++ ) {
SCAString name = services.r_at(i);
ServiceInfo info;
SCAResult rstat = spCatalog->getServiceInfo(name,info);
SCAStringSequence parts;
parts = StringUtility::split([Link],"/");
cout << setiosflags(ios::left)
<< setw(50) << name
<< setw(25) << parts.r_at([Link]()-1)
<< setw(8) << [Link]
<< setw(5) << [Link]
<< endl;
};
spCatalog = NULLSP;

13.12. Shared Library Manager


The SharedLibraryManager service provides an interface for the loading and unloading of
shared libraries.
SCA::Framework::SCAISharedLibraryManager Interface Reference

The SCAISharedLibraryManager interface provides the methods for


processing shared libraries.

Inherits SCA::SCAIService.

360
Member Functions
SCAResult loadLibrary (in SCAString sName, out SCAInt32 iHandle)
SCAResult releaseLibrary (in SCAInt32 iHandle)
SCAResult findFunction (in SCAInt32 iHandle, in SCAString sFuncName,
out SCAVoidPtr pSym)
SCAResult getLibraryInfo (in SCAInt32 iHandle, out SCAString
sGenericName, out SCAString sRealName)
SCAVoid setReleaseQueueSize (in SCA::SCAUInt32 size)

Member Function Documentation

SCAResult findFunction ( in SCAInt32 iHandle,


sFuncName
in SCAString
,
out SCAVoidPtr pSym
)

findFunction returns the pointer to a requested function if it exists.

Parameters:
iHandle handle to the library (obtained via loadLibrary)
sName name of the function whose pointer is requested
pSym pointer to symbol
Returns:
status of request 0 if the symbol was found

SCAResult getLibraryInfo ( in SCAInt32 iHandle,


sGenericName
out SCAString
,
out SCAString sRealName
)

getLibraryInfo returns the generic library name and the real shared
library object name

Parameters:
iHandle handle to the library (obtained via loadLibrary)
sGenericName generic library name
sRealName real shared object name

361
Returns:
status of request 0 if the name was returned

SCAResult loadLibrary ( in SCAString sName,


out SCAInt32 iHandle
)

loadLibrary opens the shared library

Parameters:
sName name of the library
SCAIHandle handle to the opened library
Returns:
status of request 0 if the library was loaded correctly

SCAResult releaseLibrary ( in SCAInt32 iHandle )

releaseLibrary decrements the reference count on the shared library.


The library may be unloaded if there are no other references to it

Parameters:
iHandle handle to the library (obtained via load)
Returns:
status of request

SCAVoid setReleaseQueueSize ( in SCA::SCAUInt32 size )

setReleaseQueueSize change the release buffer size to the given size

Parameters:
size real shared object name

Library loading logic


The procedure the SharedLibraryManager uses to locate the shared library to load depends on
whether the name passed to the loadLibrary method is an absolute or relative name.

362
If the input name is an absolute path of the form of /.../libname or C:/.../libname then the
library is loaded directly from the path given. The libname portion of the name is also
modified to include the appropriate prefix and suffix required for shared libraries on the
current platform. This is the only attempt made for an absolute path.

If the input name is a relative name meaning it contains an embedded path separator character
but not a leading one, like dir/libname, or if only the library name is supplied, like libname,
then the following logic is used. The libname portion of the name is first modified to include
the appropriate prefix and suffix required for shared libraries on the current platform. The
LibraryPath configuration variable is then used to find the list of paths to search for the
library. If LibraryPath is not set then the following platform specific environment variables
are used.

Platform Environment Variable


Windows LIB

AIX LIBPATH

IRIX LD_LIBRARY64_PATH
LD_LIBRARY_PATH
Other Linux/Unix LD_LIBRARY_PATH

The relative or library only name is then appended to each search path. If the search path entry
is a relative directory name, it is made absolute by adding the current working directory to the
name.

Internally the SharedLibraryManager always uses absolute paths when loading libraries. This
is done for several reasons.

This keeps the number of directories that must be tried to load the shared library to a
minimum. Since most shared libraries for SCA components are in subdirectories and not
the root directory, you would have to include each subdirectory in the system search path
list. But since the SharedLibraryManager assembles the absolute directories itself, you can
give it a name relative to the root directory and it will only need to try to load from the
single subdirectory required.

The operating system rules for how the system search path for loading shared libraries is
used is different on the various platforms supported by SCA. By bypassing the Operating
System's processing of the system search path it is possible to provide a consistent loading
behavior across all platforms.
Library Release Queue
The life cycle control logic provided by the ServiceManager will unload the shared libraries
for SCA components when all references to the services in the component have been released.

363
To avoid unnecessary load and unload requests should one of the services in the component be
immediately loaded again, the SharedLibraryManager does not immediately unload shared
libraries when requested. Instead it keeps a queue of unload requests and will only unload the
actual library when the queue is full. At this point the shared library for the oldest queue entry
is unloaded. The default size of the queue is 10 entries but this can be changed with the
setReleaseQueueSize interface member. Setting the size of the release queue to zero will
disable this feature.
SharedLibraryManager example
The following example shows using the SharedLibraryManager to load and call a function in
a shared library. In this example we will be calling the SCA_CompInfo entry in the SCA
Kernel shared library to extract all the build information that is stored in the library.

#include <iostream>
#include <SCA/SCAKernel.h>
#include <SCA/KernelConfiguration.h>
#include <SCA/Framework/SCAISharedLibraryManager.h>
#include <SCA/StringUtility.h>

using namespace std;


using namespace SCA;
using namespace SCA::Framework;

// Load the SharedLibraryManager Service


SCAISharedLibraryManager spLib;
spLib = getSCAService("[Link]");

// Load the SCA Kernel shared library


SCAString kernelLibPath = getSCAEnvValue("KernelLibPath");
SCAString kernelLib = kernelLibPath + "/SCAKernel";
SCAInt32 iHandle;
SCAResult rStatus = spLib->loadLibrary(kernelLib,iHandle);
if( rStatus ) {
cout << "Error: Could not load library " << kernelLib << endl;
return 1;
}

// Get the address of the "SCA_CompInfo" symbol


SCAVoid* pSym;
rStatus = spLib->findFunction(iHandle,"SCA_Comp_Info",&pSym);
if( !rStatus ) {
SCAString sValue;
SCAString (*pfunc)(SCAString) = (SCAString(*)(SCAString))pSym;
cout << "Build Information for " << kernelLib << endl << endl;
// Get the build date
sValue = pfunc("BuildDate");
if ( [Link]() > 0 )
cout << " Build Date = " << sValue << endl;
// Get the build time
sValue = pfunc("BuildTime");
if ( [Link]() > 0 )
cout << " Build Time = " << sValue << endl;
// Get the other build information entries
sValue = pfunc("?");

364
SCAStringSequence varNames = StringUtility::split(sValue,",");
for ( size_t iLoc=0; iLoc<[Link](); iLoc++ ) {
sValue = pfunc(varNames[iLoc]);
if ( [Link]() > 0 )
cout << " " << left << setw(17)
<< varNames.r_at(iLoc) << " = "
<< sValue << endl;
}
} else {
cout << "No build information was available library"
<< kernelLib << endl;
}
spLib->releaseLibrary(iHandle);
spLib = NULLSP;

365
SCA Framework Configuring and Using the SCA Kernel

SCA Framework User Documentation

Chapter 14
Utility Services

366
SCA Framework Configuring and Using the SCA Kernel

13.13. Introduction
This chapter discusses the following utility services that are provided
as part of the SCA Framework. All Utility services are in [Link]
namespace.
XML Parser
Regular Expression Facility
System Utilities
Stream I/O Utilities
Timer service

13.14. XML Parser


The XML Parser is an efficient and high performance SCA compliant XML reader/writer
utility component. It is provides a set of services and interfaces to facilitate the parsing,
generating, manipulating, and validating of XML documents. It consolidates various features
of different XML Parsers by using a standard set of interfaces in a uniform manner across
different products within the Simulation enterprise umbrella.

XML Parser is implemented as a wrapper around libxml2, which is a third party XML
library.

The XML Parser supports the following parsing mechanisms.

1. Tree based parsing - Document Object Model (DOM)

This mechanism provides access to the information stored in the XML


document as ahierarchical object model. The DOM parser creates a
tree of nodes based on the structure and information in the XML
document. Once the document is loaded, the user can manipulate the
data by traversing the tree.

2. Event driven parsing - Simple API for XML (SAX)

This mechanism provides access to the information stored in the XML


document through a set of predefined events. The parser fires a
sequence of these events depending on the tags encountered while
reading an XML document. The user needs to provide event handlers to
intercept and process the events.

3. XSLT style sheet processor

XSLT is a declarative XML language that allows you to translate XML


files into arbitrary text output using a style sheet. The XSLT
processor provides the functions to perform the required
transformation.

The XML parser is composed of the following services.


[Link] –The DOM parser
[Link] –The SAX parser

367
SCA Framework Configuring and Using the SCA Kernel

[Link] – The XSLT style sheet processor

In the following sections we will discuss the interfaces supported by the XML Parser and
provide some usage examples.

DOM Parser Interfaces

SCA::MXP::SCAIDOMAttribute Represents an attribute of an element


SCA::MXP::SCAIDOMCDATASection Represents a CDATA section in an XML document
SCA::MXP::SCAIDOMCharacterData Represents a generic string in the DOM
SCA::MXP::SCAIDOMComment Represents an XML comment
SCA::MXP::SCAIDOMDocument Represents the entire HTML or XML document
SCA::MXP::SCAIDOMDocumentFragment Represents a part, or fragment, of the XML document
SCA::MXP::SCAIDOMDocumentType Represents a document type (DTD) in an XML document
SCA::MXP::SCAIDOMElement Represents one element in the DOM tree
Represents an entity, either parsed or unparsed, in an
SCA::MXP::SCAIDOMEntity
XML document
SCA::MXP::SCAIDOMEntityReference Represents an entity reference (<) in an XML document
Represents a collection of nodes that can be accessed
SCA::MXP::SCAIDOMNamedNodeMap
by name
SCA::MXP::SCAIDOMNode Represents all the nodes in a DOM tree
Provides the abstraction of an ordered collection of
SCA::MXP::SCAIDOMNodeList
nodes
SCA::MXP::SCAIDOMNotation Represents a notation declared in the DTD
SCA::MXP::SCAIDOMParser Represents an XML DOM parser
SCA::MXP::SCAIDOMProcessingInstruction Represents a processing instruction in an XML document
SCA::MXP::SCAIDOMText Represents text data in the parsed XML document

Only the key interfaces and methods are described here in more detail.
The example code in the next section demonstrates the use of these
interfaces and methods.

For complete description of all the interfaces and methods, please


consult the Online API Documentation.

SCA::MXP::SCAIDOMNode Interface
This interface describes all the basic operations of an XML DOM Node object.
See [Link]

Member Functions

SCAResult getName ( out SCAString name )

This method gets the name of the node.

Parameters:
name The name of the node.

368
SCA Framework Configuring and Using the SCA Kernel

Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult getValue ( out SCAString value )

This method gets the value of the node.

Parameters:
value The value of the node.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult getFirstChild ( out SCAIDOMNode child )

This method gets the first child node of this node.

Parameters:
child The first child of this node. It there is no such node it is NULL.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult getNextSibling ( out SCAIDOMNode sibling )

This method gets the node immediately following this node.

Parameters:
sibling The next sibling node. It contains null if this node has no next sibling(E.g. last node).
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult getNodeType ( out NodeType type )

This method gets the node type.

Parameters:
type Type of node. A node could be an element, attribute, text node, comment node, cdata
node, entity reference, entity, processing instruction, document node, dtd node, document
fragment, notation.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult getAttributes ( out SCAIDOMNamedNodeMap attributes )

This method gets the attributes of this node. The method is only
relevant for nodes of the type element.

Parameters:
attributes A NodeMap of the attributes of the element. It is null if a node has no attributes.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

369
SCA Framework Configuring and Using the SCA Kernel

SCA::MXP::SCAIDOMDocument Interface
This interface represents the entire XML document.
Conceptually, it is the root of the document tree, and
provides the primary access to the document's data. Since
nodes cannot exist outside the context of a document, this
interface also contains the factory methods needed to create
these objects. The node objects created have an owner document
attribute, which associates them with the document within
whose context they were created.
See [Link]

Inherits SCA::MXP::SCAIDOMNode.

Member Functions

SCAResult SCAIDOMDocument::documentElement ( out SCAIDOMElement element )

This method gets the root element of this document.

Parameters:
element The root element of the document.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCA::MXP::SCAIDOMParser Interface
This is the top-level interface which provides the basic
operations of the XML DOM parser like parsing a file, parsing
a string, and creating a document.
See [Link]

Member Functions

SCAResult parseFile ( in SCAString filename,


in SCABool validate,

in SCABool ignoreWhitespaceNodes,

in SCABool substituteEntities,
out SCAIDOMDocument doc
)

This method reads an XML document from an input file, creates a DOM
tree and sets it as the content of the output SCAIDOMDocument object.

Parameters:
filename The path to the xml file to be parsed.
validate Indicates if the document should be validated. The default is false.
You can check if an XML document contains a legal structure by
validating it against a given DTD. A DTD (Document Type Definition) is

370
SCA Framework Configuring and Using the SCA Kernel

used to define the legal building blocks of an XML document. It defines


the document structure with a list of legal elements.

ignoreWhitespaceNodes Indicates if blank nodes should be removed. The default is false.


substituteEntities Indicates if entities will be substituted.
Entities are variables used to define shortcuts to common text like &lt;
for “<”. By default, the parser will not substitute entity references, so
that you do not lose the entity reference information. To substitute
entities pass a true value in this argument.

doc The resultant SCAIDOMDocument object containing the content of the


XML file.
Note:
If blank nodes are removed (ignoreWhitespaceNodes is set to true), then reading the file again
will generate a DOM tree that differs in whitespace text nodes from the original file.
Returns:
Returns SCASuccess if no errors occurred parsing the XML; otherwise returns one of the errors
listed below.

ECODE_XML_PARSING_ERR: an error is reported by the parser library libxml2 if the XML


file or DTD file referenced in the XML contains errors and it cannot be parsed.
SCAResult contains the following information:
o Error message as returned by libxml2 [SCAString]
o Line number [SCAInt32]
o Column number [SCAInt16]
o libxml2 error domain [SCAInt16]
o libxml2 error code [SCAInt16]
o libxml2 error level [SCAInt16]
o file name [SCAString]
ECODE_FILE_NOT_FOUND: an error is reported by the parser if either the XML file or
Dtd file referenced in the XML file is not found at the specified path. File paths can be
absolute or relative.
SCAResult contains the following information:
o fileName contains file name (.xml or .dtd) [SCAString]
ECODE_INVALID_XML: an error is reported by the parser if the XML document does not
conform to the specified Dtd rules.
SCAResult contains the following information:
o Error message as returned by libxml2 [SCAString]
o Line number [SCAInt32]
o Column number [SCAInt16]
o libxml2 error domain [SCAInt16]
o libxml2 error code [SCAInt16]
o libxml2 error level [SCAInt16]

Remarks:

File paths can be absolute or relative. If a relative path is specified then the files are sequentially
searched in the following locations:

1. Directories specified in SCA XMLParser configuration variable.


2. Directories specified in SCA Resource configuration variable.
3. The process's current directory.

See the SCA Kernel chapter of this manual for details on setting SCA configuration variables.

SCA::MXP::SCAIDOMNamedNodeMap Interface
This interface represents a collection of nodes that can be accessed by name. Objects
implementing the named node map interface are used to represent collections of nodes that
can be accessed by name. SCAIDOMNamedNodeMap does not inherit from

371
SCA Framework Configuring and Using the SCA Kernel

SCAIDOMNodeList. Named node maps are not maintained in any particular order. Objects
contained in an object implementing named node map may also be accessed by an ordinal
index, but this is simply to allow convenient enumeration of the contents of a named node
map, and does not imply that the DOM specifies an order to these nodes. Named node map
objects in the DOM are live.
See [Link]

Member Functions

SCAResult item ( in SCAUInt32 index,

out SCAIDOMNode node


)

This method gets the node at position index in the named node map.

Parameters:
index Index of the node to be retrieved.
node The node at the position index in the named node map.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

DOM Parser Example


This example shows how to:

Parse and validate an XML file using the DOM Parser.


Traverse the DOM tree to print all the element nodes and their associated attributes.

The complete source code is shown below. This code demonstrates the use of several key
interfaces and methods, which are highlighted with a darker background.

[Link]
#include <iostream>
#include <SCA/SCAKernel.h>
#include "SCA/MXP/SCAIDOMParser.h"
#include "SCA/MXP/SCAIDOMDocument.h"
#include "SCA/MXP/SCAIDOMNode.h"
#include "SCA/MXP/SCAIDOMElement.h"
#include "SCA/MXP/SCAIDOMNamedNodeMap.h"

using namespace SCA;


using namespace SCA::MXP;
using namespace SCA::Framework;
using namespace std;

// Gets and prints all the attributes of the node


void print_attributes( SCAIDOMNode& spDOMNode )
{
// Get all the attributes of the node
SCAIDOMNamedNodeMap spAttributeMap;
spDOMNode->getAttributes( spAttributeMap );
if (spAttributeMap != NULLSP)
{

372
SCA Framework Configuring and Using the SCA Kernel

// Iterate through the attribute map to access the attributes


SCAUInt32 size=0;
spAttributeMap->mapSize(size);
for( unsigned int index = 0; index < size; index++)
{
// Get the attribute at the index th position in the node map
SCAIDOMNode attributeNode;
spAttributeMap->item( index, attributeNode );
if(attributeNode)
{
// Get and print the name and value of the attribute
SCAString attributeName;
attributeNode->getName( attributeName );
SCAString attributeValue;
attributeNode->getValue( attributeValue );
cout << " " << attributeName << " " << attributeValue << endl;
}
}
}
}

// Recursively print the given node, its siblings and all its children.
// Each node has a reference to its next sibling and its first child node
void print_elements( SCAIDOMNode & node )
{
for ( SCAIDOMNode spDOMNode = node;
spDOMNode != NULLSP;
spDOMNode->getNextSibling(spDOMNode) )
{
// Get the node type
NodeType type;
spDOMNode->getNodeType(type);

// If the node is an element node…


if (type == MXP_ELEMENT_NODE)
{
// Print the element name
SCAString name;
spDOMNode->getName( name );
cout << name << endl;

// Print the element attributes


print_attributes(spDOMNode);

// Recursively print all the children


SCAIDOMNode child;
spDOMNode->getFirstChild(child);
print_elements(child);
}
}
}

int main(int argc, char** argv)


{

try {

// Get the file to parse from the command line


if ( argc < 2 ) {
cout << "Error: XML file to parse must be a command argument" << endl;
return 1;
}
SCAString fileName = argv[1];

373
SCA Framework Configuring and Using the SCA Kernel

cout << "Parsing XML file " << fileName << " with DOM parser" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

// Load the DOM parser service


SCAIService spService;
spService = getSCAService( "[Link]");
if ( spService == NULLSP ) {
return SCAError;
}
SCAIDOMParser spMXPDOMParser = spService;
SCAIDOMDocument spDocument;
SCAResult rstat;

// Parse the input xml file


SCABool validate = true; // Validate the document
SCABool normalize = false; // Do not normalize the DOM tree
SCABool substEntities = false; // Do not susbtitute the entities
rstat = spMXPDOMParser->parseFile(fileName, validate, normalize,
substEntities, spDocument);
if ( [Link]() )
{
// Query the root node of the document tree
SCAIDOMElement spRoot;
spDocument->documentElement(spRoot);

// Print root node and all its children


if (spRoot)
{
SCAIDOMNode spRootNode = static_cast<SCAIDOMNode>(spRoot);
print_elements(spRootNode);
}
} else {
if ( [Link]() == 100002 ) {
cout << "Error: File " << fileName << " not found." << endl;
} else {
cout << "Error encountered parsing XML file" << endl;
[Link]();
}
}

// Terminate the SCA Kernel


terminateSCAKernel();

} catch(SCAException& e) {
cout << "Error: " << [Link]() << endl;
}
return 0;
}

SAX Parser Interfaces


SCA::MXP::SCAISAXContentHandler Represents the events to report the logical content of XML data
Represents events used to report declaration content of XML
SCA::MXP::SCAISAXDeclHandler
data
SCA::MXP::SCAISAXDtdHandler Represents events used to report DTD content of XML data
Represents events used to resolve external entities contained in
SCA::MXP::SCAISAXEntityResolver
XML data
SCA::MXP::SCAISAXErrorHandler Represents the events used to report error in XML data

374
SCA Framework Configuring and Using the SCA Kernel

SCA::MXP::SCAISAXParser Represents an XML SAX parser

Only the key interfaces and methods are described here in more detail. The example code in
the next section demonstrates the use of these interfaces and methods.

For complete description of all the interfaces and methods, please consult the Online API
Documentation.

SCA::MXP::SCAISAXParser Interface
This interface describes various operations of the XML SAX parser like parsing a file, parsing
a string, and setting various event handlers.

Member Functions

SCAResult parseFile ( in SCAString filename )

This method reads an XML document from input file and parses it.

Parameters:
filename The path to the file.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult setContentHandler ( in SCAISAXContentHandler contentHandler )

This method sets the content handler to contentHandler. The content


handler will handle basic content related events like
onStartDocument(), onEndDocument(), onStartElement(), onEndElement(),
onCharacters(), onComment() etc.

Parameters:
contentHandler The SCA component to receive events related to the logical content of the XML
data when an XML document is parsed.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult setErrorHandler ( in SCAISAXErrorHandler errorHandler )

This method sets the error handler to errorHandler. The error handler handles errors in the xml file with
events onError(), onWarning() and onFatalError().

Parameters:
errorHandler The SCA component to receive warning-error related events when an XML
document is parsed.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

375
SCA Framework Configuring and Using the SCA Kernel

SCA::MXP::SCAISAXContentHandler Interface
This interface represents the events to report the logical content of XML data. If the client
application needs to be notified of basic parsing events like start and end of elements,
character data etc, it should implement this interface and activate it using
SCAISAXParser::setContentHandler(). The parser can then report basic document-related events
through this interface. The order of events in this interface corresponds to the order of
information in the document.

All of an element's content, including character data, processing instructions, and sub-
elements, appears in order between the startElement event and the corresponding endElement
event.

Member Functions

SCAResult onStartDocument ( )

This is the first method to be called before any other methods in the
document. Override this to receive notification at the start of a
document.

Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.

SCAResult onEndDocument ( )

This is the last handler method to be called and is called after all
input has been read or when the parser has abandoned parsing because of
a fatal error. Override this to receive notification at the end of a
document.

Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.

SCAResult onStartElement ( in SCAString tagName,


in SAXAttributeList attributes
)

The parser calls this method when it parses a start element tag.
Override this to receive information about the elements. There is a
corresponding endElement call when the corresponding end element tag is
read. The startElement and endElement calls are always nested
correctly. Empty element tags cause a startElement call to be
immediately followed by an endElement call.

Parameters:
tagName The element name.
attributes List of name/value pairs corresponding to the elements attributes.
Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.

SCAResult onEndElement ( in SCAString tagName )

376
SCA Framework Configuring and Using the SCA Kernel

The parser calls this method when it parses an end element tag.
Override this to receive notification about end of an element.
startElement() and endElement() calls are always nested correctly.

Parameters:
tagName The element name.
Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.

SCAResult onCharacters ( in SCACharSequence character )

The parser calls this method when it has parsed a character data. There
character could be normal character data or inside a CDATA section; if
you need to distinguish between those two types you must use
SCAISAXContentHandler::onCdataBlock. Override this to receive
information about the character parsed.

Parameters:
character The character data.
Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.

SCA::MXP::SCAISAXErrorHandler Interface
This interface represents the events used to report error in XML data. If the client application
needs to be notified of parsing errors & warnings, it should implement this interface and
activate it using SCAISAXParser::setErrorHandler. The parser can then report parsing
errors and warnings through this interface.

SCAResult onWarning ( in SCAString parseException )

The parser calls this method to report a warning. Warnings are conditions that are not errors or fatal
errors as defined by the XML 1.0 specification. Override this method to perform customized error handling.

Parameters:
parseException The details of the warning, including description, line number, and column
number.
Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.

SCAResult onError ( in SCAString parseException )

The parser calls this method to report a recoverable error. A recoverable error corresponds to the
definition of "error" in section 1.2 of the XML 1.0 specification. The parser must continue to provide
normal parsing events after invoking this function. Override this method to perform customized error
handling.

Parameters:
parseException The details of the error, including description, line number, and column number.
Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.
Remarks:

377
SCA Framework Configuring and Using the SCA Kernel

If SCAError is returned, there was an error encountered when reporting the recoverable error.
The error described in this method's result is a different error than the recoverable error the
parser encountered.

SCAResult onFatalError ( in SCAString parseException )

The parser calls this method to report a non-recoverable error. Override this method to perform
customized error handling.

Parameters:
parseException The details of the error, including description, line number, and column number.
Returns:
Returns SCASuccess on success; otherwise returns SCAError and stops parsing the XML.
Remarks:
If SCAError is returned, there was an error encountered when reporting the non-recoverable
error. The error described in this method's result is a different error than the non-recoverable
error the parser encountered.

If SCASuccess is returned, the parser may continue to parse and report further errors but no
non-error parsing events are reported.

SAX Parser Example


The following sample program parses XML file using the event-based SAX parser and
generates the same result as the DOM parser example. The SAX parser requires the client to
implement the SCAISAXContentHandler and SCAISAXErrorHandler interfaces to
receive the events from the parser. This sample program uses one of the
SCAServiceObjectImpl templates provided by the SCA Framework to create a class which
implements theses interfaces. For complete details on using these templates see the SCA SDK
Advanced Features manual.

The following is the complete code for the sample program.

[Link]
#include <iostream>
#include <SCA/SCAKernel.h>
#include <SCA/Framework/ServiceObjectImpl.h>
#include <SCA/MXP/SCAISAXParser.h>
#include <SCA/MXP/SCAISAXContentHandler.h>
#include <SCA/MXP/SCAISAXErrorHandler.h>

using namespace std;


using namespace SCA;
using namespace SCA::Framework;
using namespace SCA::MXP;

typedef SCAISAXContentHandlerInterface::SAXAttributeList SAXAttributeList;

//
// Implementation of SCAISAXContentHandler interface
//
char CImplName[] = "ContentHandler";
class ContentHandler : SCAServiceObjectImpl1 <SCAISAXContentHandler,CImplName>
{
public:
// Constructors and Destructor
ContentHandler() { }
~ContentHandler() { }

378
SCA Framework Configuring and Using the SCA Kernel

// Methods for interface SCAISAXContentHandler


SCAResult onStartDocument() { return SCASuccess; }
SCAResult onEndDocument() { return SCASuccess; }
SCAResult onStartElement(const SCAString tagName,
const SAXAttributeList& attributes) {
cout << tagName << endl;
for ( size_t i=0; i<[Link](); i++ ) {
cout << " " << attributes.r_at(i).AttributeName << " "
<< attributes.r_at(i).AttributeValue << endl;
}
return SCASuccess;
}
SCAResult onEndElement(const SCAString tagName) { return SCASuccess; }
SCAResult onCharacters(const SCACharSequence& character)
{ return SCASuccess; }
SCAResult onIgnorableWhitespace(const SCAString whiteSpaces,
const SCAInt32 len) { return SCASuccess; }
SCAResult onCdataBlock(const SCAString text,
const SCAInt32 len) { return SCASuccess; }
SCAResult onComment(const SCAString text) { return SCASuccess; }
SCAResult onEntityReference(const SCAString entity) { return SCASuccess; }
SCAResult onStartDtd(const SCAString name,
const SCAString publicId,
const SCAString systemId) { return SCASuccess; }
SCAResult onEndDtd() { return SCASuccess; }
};

//
// Implementation of SCAISAXErrorHandler interface
//
char EImplName[] = "ErrorHandler";
class ErrorHandler : SCAServiceObjectImpl1 <SCAISAXErrorHandler,EImplName>
{
public:
// Constructors and Destructor
ErrorHandler() { }
~ErrorHandler() { }

// Methods for interface SCAISAXErrorHandler


SCAResult onWarning(const SCAString parseException) {
cout << "onWarning(): " << parseException << endl;
return SCASuccess;
}
SCAResult onError(const SCAString parseException) {
cout << "onError(): " << parseException << endl;
return SCASuccess;
}
SCAResult onFatalError(const SCAString parseException) {
cout << "onFatalError(): " << parseException << endl;
return SCASuccess;
}
};

int main(int argc, char** argv)


{
try {

// Get the file to parse from the command line


if ( argc < 2 ) {
cout << "Error: XML file to parse must be a command argument" << endl;
return 1;
}

379
SCA Framework Configuring and Using the SCA Kernel

SCAString fileName = argv[1];


cout << "Parsing XML file " << fileName << " with SAX parser" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

{
// Load SAX Parser
SCAIService spService;
spService = getSCAService( "[Link]");
if ( spService == NULLSP ) {
return SCAError;
}
SCAISAXParser spMXPSAXParser = spService;

// Register content handler


ContentHandler* pContent = new ContentHandler();
SCAISAXContentHandler spContent = (SCAISAXContentHandler)pContent;
spMXPSAXParser->setContentHandler(spContent);

// Set Handler Services


ErrorHandler* pError = new ErrorHandler();
SCAISAXErrorHandler spError = (SCAISAXErrorHandler)pError;
spMXPSAXParser->setErrorHandler(spError);

// Parse [Link]
SCAResult rStatus = spMXPSAXParser->parseFile(fileName);
}

// Terminate the SCA Kernel


terminateSCAKernel();

} catch(SCAException& e) {
cout << "Error: " << [Link]() << endl;
}
return 0;
}

XSLT Processor Interfaces


SCA::MXP::SCAIXSLT Interface
This interface provides methods to apply a style-sheet to an XML file, an XML string buffer
or an XML document.

Member Functions

SCAResult applyStyleSheetToXMLFile (in SCAString xmlFilePath, in SCAString xsltFilePath, out


SCAIDOMDocument doc)
Apply style sheet to an input xml file.

SCAResult applyStyleSheetToXMLDocument (in SCAIDOMDocument xmlDocument, in SCAString


xsltFilePath, out SCAIDOMDocument doc)
Apply style sheet to an input xml document.

SCAResult applyStyleSheetToXMLBuffer (in SCAString xmlStringBuffer, in SCAString xsltFilePath,


out SCAIDOMDocument doc)
Apply style sheet to an input xml string buffer.

SCAResult applySSBufferToXMLFile (in SCAString xmlFilePath, in SCAString xsltStringBuffer, out

380
SCA Framework Configuring and Using the SCA Kernel

SCAIDOMDocument doc)
Apply style sheet stored in a string buffer to an input xml file.

SCAResult applySSBufferToXMLDocument (in SCAIDOMDocument xmlDocument, in SCAString


xsltStringBuffer, out SCAIDOMDocument doc)
Apply style sheet stored in a string buffer to an input xml document.

SCAResult applySSBufferToXMLBuffer (in SCAString xmlStringBuffer, in SCAString xsltStringBuffer,


out SCAIDOMDocument doc)
Apply style sheet stored in a string buffer to an input xml string buffer.

381
SCA Framework Configuring and Using the SCA Kernel

13.15. Regular Expression Facility


The following sections list the interfaces provided by the [Link]
service for pattern matching using regular expressions. For detailed description of the methods
please consult the Online API Documentation.

SCA::RegExp::SCAIRegExp Interface
This interface provides methods for pattern matching using regular expressions.

Member Functions

SCAResult setPattern ( in SCAWString pattern )

This method sets the pattern string to 'pattern'. The 'pattern' may be
either regular expression syntax or wildcard syntax. The case
sensitivity, wildcard and minimal matching options are not changed.

Parameters:
pattern Pattern string.
Returns:
Returns SCASuccess if the 'pattern' is valid.
SCAError if the 'pattern' is not valid.

SCAResult enableCaseSensitiveSearches ( in SCABool sensitive )

This method enables or disables Case Sensitive matching. If 'sensitive'


is TRUE, Case Sensitivity is enabled. If 'sensitive' is FALSE, Case
Sensitivity is disabled. For example if sensitive is TRUE, \.txt$ will
match [Link] but not [Link].

Parameters:
sensitive SCABool value.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult enableWildCardMode ( in SCABool wildcard )

This method sets the wildcard mode for the regular expression. The
default is FALSE. Setting 'wildcard' to TRUE enables wildcard matching.
For example, r*.txt matches the string '[Link]' in wildcard mode,
but does not match 'readme'.

Parameters:
wildcard SCABool value.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult enableMinimalMatchingMode ( in SCABool minimal )

This method enables or disables minimal matching. If 'minimal' is


false, matching is greedy (maximal) which is the default. For example,
suppose we have input string "AbcAbcA" and pattern "A.*c", with the

382
SCA Framework Configuring and Using the SCA Kernel

maximal(greedy) matching, the match is "AbcAbc". But with minimal(non-


greedy) matching, the first match is "Abc".

Parameters:
minimal SCABool value.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult exactMatch ( in SCAWString str )

This method checks whether 'str' is matched exactly by this regular


expression. You can determine how much of the string was matched by
calling matchedLength(). For example, if the regular expression is
'blue', then exactMatch() returns SCASuccess only for input 'blue'. For
inputs 'bluebell', 'blutak' and 'lightblue', exactMatch() returns
SCAError and matchedLength() will return SCASuccess with length of
matched string 4, 3 and 0 respectively.

Parameters:
str SCAWString to match.
Returns:
Returns SCASuccess, if 'str' is matched exactly by the regular expression.
SCAError, if 'str' is not matched exactly by this regular expression.

SCAResult leftFind ( in SCAWString str,

in SCAInt32 offset,

out SCAInt32 pos


)

This method attempts to find a match in 'str' from position 'offset' (0


by default). Gets the position of the first match, or -1 if there was
no match. If 'offset' is -1, the search starts at the last character;
if -2, at the next to last character; etc.

Parameters:
str Input SCAString.
offset Index of the position at which the search is to begin.
pos Position of the first match.
Returns:
Returns SCASuccess if a match is found in 'str', else returns SCAError.

SCAResult rightFind ( in SCAWString str,

in SCAInt32 offset,

out SCAInt32 pos


)

This method attempts to find a match backwards in 'str' from position


'offset', Gets the position of the first match, or -1 if there was no
match. If 'offset' is -1 (the default), the search starts at the last
character; if -2, at the next to last character; etc.

Parameters:
str Input SCAString.

383
SCA Framework Configuring and Using the SCA Kernel

offset Index of the position at which the search is to begin.


pos Position of the first match from backwards.
Returns:
Returns SCASuccess if a match is found in 'str', else returns SCAError.

SCAResult matchedLength ( out SCAInt32 len )

This method gets the length of the last matched string.

Parameters:
len Length of the matched string
Returns:
Returns SCASuccess if there was a match, else returns SCAError.

SCAResult numCaptures ( out SCAInt32 captures )

This method gets the number of captures contained in the regular


expression.

Parameters:
captures Number of captures in regular expression.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult capturedTexts ( out SCAWStringSequence seq )

This method gets the SCAWStringSequence of the captured text strings.


The first string in the list is the entire matched string, each
subsequent list element contains a string that matched a (capturing)
sub expression of the regexp.

Parameters:
seq Sequence of captured strings.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult cap ( in SCAInt32 nth,


out SCAWString capturedText
)

This method gets the text captured by the 'nth' sub expression. The
entire match has index 0 and the parenthesized sub expressions have
indexes, starting from 1 (excluding non-capturing parentheses).

Parameters:
nth Sub expression index.
capturedText SCAWString containing the captured text.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult pos ( in SCAInt32 nth,

out SCAInt32 pos


)

384
SCA Framework Configuring and Using the SCA Kernel

This method gets the position of the 'nth' captured text in the
searched string. If 'nth' is 0 (the default), pos() returns the
position of the whole match.

Parameters:
nth Index of the captured text.
pos Position of the captured text.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult errorString ( out SCAWString errString )

This method gets a SCAWString that explains why a regular expression


pattern is invalid. If the pattern is valid the string returned is "no
error occurred".

Parameters:
errString Error SCAWString.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCAResult escape ( in SCAWString str,


out SCAWString escString
)

This method escapes every regular-expression special character in 'str'


with a backslash.

This method gets an SCAWString, with every regexp special character in


'str' is escaped with a backslash. The special characters are: $ ( ) *
+ . ? [ ] ^ { | }.

Parameters:
str Input string.
escString Escaped string.
Returns:
Returns SCASuccess on success; otherwise returns SCAError.

SCA::RegExp::SCAIRegExpFactory Interface
This interface creates objects that provide Regular Expression related services.

Member Functions

SCAResult createSCAIRegExp ( in SCAWString pattern,

in SCABool caseSensitive,

in SCABool wildcard,
out SCAIRegExp regexpObj
)

This method creates a reference to the SCAIRegExp interface.

385
SCA Framework Configuring and Using the SCA Kernel

Parameters:
pattern Pattern string for regular expression object.
caseSensitive Specifies whether pattern is case sensitive or not.
wildcard Specifies whether syntax is Wildcard or RegExp.
regexpObj SCAIRegExp object returned.
Returns:
Returns SCASuccess if the pattern is valid, else returns SCAError.

Regular Expression Example


This example shows the usage of the regular expression service. There is no error handling in
this code to simplify the example. Production code should check the SCAResult return
values.

[Link]
#include <SCA/SCAKernel.h>
#include "SCA/RegExp/SCAIRegExp.h"
#include "SCA/RegExp/SCAIRegExpFactory.h"

using namespace SCA;


using namespace SCA::RegExp;
using namespace std;

int main(int argc, char** argv)


{
try {

cout << "Test of regular expression processing" << endl;

// Initialize the SCA Kernel


initializeSCAKernel(1);

{
// Load RegularExpressionFactory
SCAIRegExpFactory spService;
spService = getSCAService("[Link]");

// Create SCAIRegExp processor


SCAIRegExp spRegExpService;
SCAWString pattern(L"dummy");
spService->createSCAIRegExp(pattern, false, false, spRegExpService);

// Sample data to process


SCAWString textString;
textString = L"I have sent you an email I have not sent you an email";
cout << "Sample data to process:" << endl;
wcout << textString << endl << endl;

// Search using leftFind


SCAInt32 pos;
pattern = L"sent";
spRegExpService->setPattern(pattern);
spRegExpService->leftFind(textString, 0, pos);
wcout << "Position of left most string \""
<< pattern << "\" is "<< pos <<endl;

// Search using rightFind


pattern = L"n[a-z]* s[a-z]*";
spRegExpService->setPattern(pattern);
spRegExpService->rightFind(textString, -1, pos);

386
SCA Framework Configuring and Using the SCA Kernel

wcout << "Position of right most string \""


<< pattern << "\" is "<< pos <<endl;

// Get matchedLength
SCAInt32 match_length;
spRegExpService->matchedLength(match_length);
cout<<"Length of last matched expression was " << match_length << endl;
}

// Terminate the SCA Kernel


terminateSCAKernel();

} catch(SCAException& e) {
cout << "Error: " << [Link]() << endl;
}
return 0;
}

Program output:
Test of regular expression processing
SCA Kernel 4.8.0 successfully initialized
Sample data to process:
I have sent you an email I have not sent you an email

Position of left most string "sent" is 7


Position of right most string "n[a-z]* s[a-z]*" is 32
Length of last matched expression was 8

387
SCA Framework Configuring and Using the SCA Kernel

13.16. System Utilities


The following sections list the interfaces provided by the [Link] service.
SystemUtils provide interfaces for following operations:

1. SCAIFileUtils – provides methods to conduct file system operations


2. SCAIOSUtils – provides methods for operating system operations such as getting and
setting environment variables.
3. SCAIPathUtils – provides methods for file path manipulations. These are strictly
string operations. Behavior of these methods tries to mimic Python [Link] module
behavior as much as possible.
4. SCAIPaths – provides consistent means to search for files in a list of directories.

SCA::SystemUtils::SCAIFileUtils Interface
This interface provides methods to conduct file system operations.
Most methods call the native stat() call hence the user needs privilages appropriate permission.

Public Member Functions


SCAResult checkAccess (in SCAUString path, in SCAInt32 mode)
SCAResult createUniqueTempFileName (in SCAUString dir, in SCAUString prefix, out
SCAUString fileName)
SCAResult exists (in SCAUString path, out SCABool exists)
SCAResult findFile (in SCAUString path, in SCAUString filePattern, out
SCAUStringSequence fullFilePath)
SCAResult getFileInformation (in SCAUString filePath, out SCAFileInfoBuffer
fileInfoBuffer)
SCAResult group (in SCAUString path, out SCAUString groupId)
SCAResult groupId (in SCAUString path, out SCAInt32 groupId)
SCAResult isDirectory (in SCAUString dirPath, out SCABool isDir)
SCAResult isFile (in SCAUString filePath, out SCABool isFile)
SCAResult isHidden (in SCAUString filePath, out SCABool isHid)
SCAResult listDirectoryContent (in SCAUString dirPath, in SCAUString nameFilter, in
SCAInt32 filterSpec, in SCAInt32 sortSpec, out SCAUStringSequence list)
SCAResult makeDirectory (in SCAUString path)
SCAResult owner (in SCAUString path, out SCAUString owner)
SCAResult ownerId (in SCAUString path, out SCAInt32 ownerId)
SCAResult removeDirectory (in SCAUString dirName)
SCAResult removeFile (in SCAUString path)
SCAResult rename (in SCAUString oldName, in SCAUString newName)
SCAResult size (in SCAUString path, out SCAInt64 size)

388
SCA Framework Configuring and Using the SCA Kernel

Detailed Description
This interface provides methods to conduct file system operations.
Most methods call the native stat() call hence the user needs privilages appropriate permission.

Member Function Documentation


SCAResult SCA::Util::SystemUtils::SCAIFileUtils::checkAccess (in SCAUString
path, in SCAInt32 mode)
Checks "path" for specified access mode. Returns SCASuccess, if "path" has specified mode,
else returns following from "Error code"
SCAOSERR_PATH_NULL, if "path" is NULL.
SCAOSERR_NOACCESS, if "path" does not have the specified mode or
SCAOSERR_NOENTITY, if "path" does not exists
SCAOSERR_INVALID, if "path" is invalid.
Parameters:
in path this methods checks access for this path
in returns the numerical access mode.
Returns:
SCAResult Status of request

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::createUniqueTempFileName
(in SCAUString dir, in SCAUString prefix, out SCAUString fileName)
Creates a unique temporary filename in the specified directory "dir". Returns SCASuccess, if
"fileName" has the newly created name, else returns following from "Error code"
SCAOSERR_NOTDIR, if "dir" is invalid.
Parameters:
in dir the unique temporary file name will be
created in this directory
in prefix the unique temporary file name will have this
prefix
out fileName this parameter returns the unique file name
Returns:
SCAResult Status of request

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::exists (in SCAUString path, out


SCABool exists)
"exists" will be set to TRUE if the file exists; otherwise set to FALSE. Return SCASuccess if
file exists or else returns following:
SCAOSERR_NOENTITY ,if "filePath" does not exists.
SCAOSERR_NOACCES, if user does not have rights to all directories named in the "filePath"
leading to the file.
SCAOSERR_ISDIR, if "filePath" specifies a directory.
SCAOSERR_INVALID, if "fileInfoBuffer" is NULL.

389
SCA Framework Configuring and Using the SCA Kernel

Parameters:
path this method checks for the existance of this path
exists will be set to true if "path" exists or else set to
false
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::findFile (in SCAUString path,


in SCAUString filePattern, out SCAUStringSequence fullFilePath)
Searches for the files matching the "filePattern" in the given "path". If the file found matching
"filePattern"in the given "path",then stores the full filepath in "fullFilePath". if "path" is
NULL, then current directory is used to search for the "filePattern" Returns SCASuccess if
the user has permission to traverse "path", else returns following from "Error code"
SCAOSERR_ACCES,if "path" does not have read permission
SCAOSERR_NOENTITY, if "path" is invalid.
Parameters:
path file path in which "filePattern" will be looked for
filePattern method looks for this string pattern in the "path"
fullFilePath this SCAUStringSequence will contain the full path
if "filePattern" is found
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::getFileInformation (in


SCAUString filePath, out SCAFileInfoBuffer fileInfoBuffer)
Gets the information about about the file specified by "filePath". Returns SCASuccess, if the
file information is obtained, else returns following from "Error code"
SCAOSERR_NOENTITY ,if "filePath" does not exists.
SCAOSERR_NOACCES, if user does not have rights to all directories named in the "filePath"
leading to the file.
SCAOSERR_ISDIR, if "filePath" specifies a directory.
SCAOSERR_INVALID, if "fileInfoBuffer" is NULL.
Parameters:
filePath file path to get file information of.
fileInfoBuff structure that returns the file information in.
er
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::group (in SCAUString path, out


SCAUString groupId)
Returns the group name for a file (UNIX-specific). This field will always be zero on
Windows systems. Returns SCASuccess if group for "path" is obtained. Else will return
following:
SCAOSERR_INVALID when the native stat() call returns EINVAL as the error.

390
SCA Framework Configuring and Using the SCA Kernel

SCAOSERR_NOENTITY when the native stat() call returns ENOENT as the error.
SCAOSERR_NOACCESS when the native stat() call returns any other error.
Parameters:
path Input string path to obtail group name.
groupId returns the groupd ID as a SCAUString.
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::groupId (in SCAUString path,


out SCAInt32 groupId)
Returns the group Id for a file (UNIX-specific). This field will always be zero on Windows
systems. Returns SCASuccess if groupId for "path" is obtained. Else will return following:
SCAOSERR_INVALID when the native stat() call returns EINVAL as the error.
SCAOSERR_NOENTITY when the native stat() call returns ENOENT as the error.
SCAOSERR_NOACCESS when the native stat() call returns any other error.
Parameters:
path Input string path to obtain group ID
groupId returns the group ID value
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::isDirectory (in SCAUString


dirPath, out SCABool isDir)
"isDir" is set to true if dirPath parameter represents a directory. Returns SCASuccess if
"dirPath" represents a directory. Else will return following:
SCAOSERR_INVALID when the native stat() call returns EINVAL as the error.
SCAOSERR_NOENTITY when the native stat() call returns ENOENT as the error.
SCAOSERR_NOACCESS when the native stat() call returns any other error.
SCAOSERR_NOTDIR when "isDir" is a location on the filesystem but not a directory. For ex: a
file.
Parameters:
dirPath Input string path to check
isDir is set to true when "dirPath" points to a directory
else set to false.
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::isFile (in SCAUString filePath,


out SCABool isFile)
"isFile" will be set to true if filePath parameter represents a file. Returns SCASuccess if
"filePath" represents a file. Else will return following:
SCAOSERR_INVALID when the native stat() call returns EINVAL as the error.
SCAOSERR_NOENTITY when the native stat() call returns ENOENT as the error.
SCAOSERR_NOACCESS when the native stat() call returns any other error.

391
SCA Framework Configuring and Using the SCA Kernel

SCAOSERR_NOTFILE when "isFile" is a location on the filesystem but not a file. For ex: a
directory.
Parameters:
filePath Input string path to check
isFile is set to true when "filePath" points to a file else
set to false.
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::isHidden (in SCAUString


filePath, out SCABool isHid)
On Windows isHid returns true if the file attributes state the file is hidden. On Linux and
Unix systems if the file starts with a period, ".", then isHid returns true. Returns SCASuccess
if "filePath" represents a hidden file, else returns following from "Error code"
SCAOSERR_NOTHID, if the file not hidden.
SCAOSERR_NOTFILE On Windows, the actual file existance matters since the method checks
file attributes. Therefore if the file doesn't exist, this error is returned.
Parameters:
filepath Input file path string.
isHid boolean returns true for a hidden file and false for
non-hidden file.
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::listDirectoryContent (in


SCAUString dirPath, in SCAUString nameFilter, in SCAInt32 filterSpec, in
SCAInt32 sortSpec, out SCAUStringSequence list)
List names of all the files and sub directories in "dirPath", ordered in accordance with
"sortSpec" and filtered in accordance with "filterSpec" and "nameFilter". Retrurns
SCASuccess if "dirPath" exists and is readable, else returns following from "Error code"
SCAOSERR_NOACCESS, if the user does not have access permission.
Parameters:
dirPath Input directory path string.
nameFilter string which contains wildcard characters like "*"
and "?". For example, nameFilter= "*.txt" "*"
matches zero or more of any characters. "?" matches
any single character
filterSpec use the values from the "listDir filterSpec" list,
those values can be ORed together as necessary.
Several of these fields have default valuse. If none
of FILTER_ALL bits are specified, the default is
they are all on. If none of FILTER_RWEMASK bits are
specified, the default is they are all on.
sortSpec use the values from the "listDir sortSpec" list
documented above. Only one from SORT_BY_TIME,
SORT_BY_SIZE, SORT_BY_NAME, SORT_IGNORECASE or
SORT_LOCALEAWARE may be specified. Opions
SORT_DIRSFIRST and SORT_DESCENDING can be ORed in

392
SCA Framework Configuring and Using the SCA Kernel

addition to these.
list List of files and directories.
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::makeDirectory (in SCAUString


path)
Creates a directory for the given path. Returns the following error codes if operation fails:
SCAOSERR_ACCES - the path is inaccessible for the user.
SCAOSERR_EXIST - a file or a directory exists with the same name.
Parameters:
path make a directory specified in the path
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::owner (in SCAUString path, out


SCAUString owner)
"owner" is set to the owner for a file (UNIX-specific). This field will always be zero on
Windows systems. Note: Due to implementation limitations, there might be a case where the
actual owner may not be the one returned. This is due to the fact that the Owner ID can be
associated with more than one username. Returns SCASuccess if owner ID is obtained for the
"path" specified. Else will return the following:
SCAOSERR_INVALID when the native stat() call returns EINVAL as the error.
SCAOSERR_NOENTITY when the native stat() call returns ENOENT as the error.
SCAOSERR_NOACCESS when the native stat() call returns any other error.
SCAOSERR_INVALIDUID when owner name cannot be found using the stat() call owner ID.
Parameters:
path owner name is obtained for this path
owner returns the owner name as a SCAUString
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::ownerId (in SCAUString path,


out SCAInt32 ownerId)
Returns the owner Id for a file (UNIX-specific). This field will always be zero on Windows
systems. Returns SCASuccess if ownerID is obtailed for the "path" specified. Else will return
the following:
SCAOSERR_INVALID when the native stat() call returns EINVAL as the error.
SCAOSERR_NOENTITY when the native stat() call returns ENOENT as the error.
SCAOSERR_NOACCESS when the native stat() call returns any other error.
Parameters:
path owner ID is obtained for this path
ownerId returns the owner ID as a SCAInt32

393
SCA Framework Configuring and Using the SCA Kernel

Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::removeDirectory (in


SCAUString dirName)
Removes the directory specified by "dirName". The directory must be empty for rmdir() to
succeed. Returns SCASuccess if directory "dirName" is removed, else returns following from
"Error code"
SCAOSERR_NOTEMPTY, the directory is not empty, or the directory is either the current
working directory or the root directory.
SCAOSERR_NOTDIR, Given path is not a directory
SCAOSERR_NOENTITY, Path is invalid.
SCAOSERR_NOACCESS, A program has an open handle to the directory.
Parameters:
dirName removes the directory in the specified path
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::removeFile (in SCAUString


path)
Removes the given file path. Returns the following error codes if operation fails:
SCAOSERR_NOENTITY - path does not exist.
SCAOSERR_ACCES - the path is inaccessible for the user.
SCAOSERR_ISDIR - path is a directory.
Parameters:
path removes the file in the specified path
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::rename (in SCAUString


oldName, in SCAUString newName)
Renames the file or directory specified by "oldName" to the name given by "newName". The
"oldName" must be the path of an existing file or directory. The "newName" must not be the
name of an existing file or directory. You can use rename to move a file from one directory or
device to another by giving a different path in the "newName" argument. You can use rename
to move a directory within the filesystem. Returns SCASuccess if "oldName" is renamed
with "newName", else returns following from "Error code"
SCAOSERR_NOACCESS, File or directory specified by "newName" already exists or could not
be created (invalid path); or "oldName" is a directory and "newName" specifies a different path
SCAOSERR_NOENTITY, File or path specified by "oldName" not found.
SCAOSERR_INVALID, Name contains invalid characters.
Parameters:
oldName old name of the file or directory
newName file or directory has to be renamed to the name

394
SCA Framework Configuring and Using the SCA Kernel

Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIFileUtils::size (in SCAUString path, out


SCAInt64 size)
Returns the size of the file in bytes. Returns SCASuccess if size is found. Else size would be
assigned 0
SCAOSERR_NOENTITY is returned if "path" is not found.
Parameters:
path file path of which size is obtained
size is returned through this parameter
Returns:
SCAResult Status of request.

SCA::SystemUtils::SCAIOSUtils Interface
This interface provides methods to run system commands and edit environment variables.

Public Member Functions


SCAResult getArchitectureString (out SCAUString archString)
SCAResult getCurrentSystemLibraries (out SCASystemLibrarySeq libs)
SCAResult getCurrentWorkingDirectory (out SCAUString currentDir)
SCAResult getenv (in SCAUString varName, out SCAUString value)
SCAResult homeDirectoryPath (out SCAUString homeDir)
SCAResult putenv (in SCAUString varName, in SCAUString value)
SCAResult runSystemCommand (in SCAUString command, out SCAInt32 exitStatus)
SCAResult setCurrentWorkingDirectory (in SCAUString dirPath)
SCAResult unsetenv (in SCAUString varName)

Detailed Description
This interface provides methods for operating system operations such as getting and setting
environment variables.

Member Function Documentation


SCAResult SCA::Util::SystemUtils::SCAIOSUtils::getArchitectureString (out
SCAUString archString)
Gets the name of the system architecure. On Windows it returns the following accordingly:
x86
x86_64

395
SCA Framework Configuring and Using the SCA Kernel

WOW64
x64 On Linux platforms it returns the sysname and machine separated by a space generated from
the native uname() call.
Parameters:
out archString SCAUString contains the architecture string.
Returns:
SCAResult Status of request.

SCAResult SCA::Util::SystemUtils::SCAIOSUtils::getCurrentSystemLibraries (out


SCASystemLibrarySeq libs)
Reports versions of SCA Kernel libraries being used.

Parameters:
out SCASystemLibr that contains the library information. Please
arySeq refer to the SCASystemLibrarySeq
documentation for details.

Returns:
SCAResult Status of request.
SCAResult SCA::Util::SystemUtils::SCAIOSUtils::getCurrentWorkingDirectory
(out SCAUString currentDir)
Gets absolute path of the application"s current working directory.

Parameters:
out SCAUString that contains the current working directory.

Returns:
SCAResult Status of request.
SCAResult SCA::Util::SystemUtils::SCAIOSUtils::getenv (in SCAUString
varName, out SCAUString value)
Gets the value from the environment variable "varName".

Parameters:
in varName SCAUString contains the environment variable
name.
out value SCAUString contains (if existing) the value
of the provided variable name.

Returns:
SCASuccess if "varName" exists in the environment, else returns following from "Error code" *
SCAOSERR_INVALID, if "varName" is invalid

396
SCA Framework Configuring and Using the SCA Kernel

SCAResult SCA::Util::SystemUtils::SCAIOSUtils::homeDirectoryPath (out


SCAUString homeDir)
Gets the user"s home directory. i.e. the value of environment variable "HOME". If
"HOME" is not set, then value of "USERPROFILE". If both values are not set on Windows
an empty string is returned and other platforms the root of filesystem is returned.

Parameters:
out homeDir SCAUString contains the home directory path.

Returns:
SCAResult Status of request.
SCAResult SCA::Util::SystemUtils::SCAIOSUtils::putenv (in SCAUString
varName, in SCAUString value)
Creates or modifies the environment variable "varName".

Parameters:
in varName SCAUString contains the environment variable
name.
in value SCAUString contans the value fro the variable
name. SCASuccess, if "varName" is added to
environment, else returns following from
"Error code"
SCAOSERR_ENV_NULL, if "varName" is NULL
SCAOSERR_ENVVALUE_NULL, if "value" is NULL.

SCAResult SCA::Util::SystemUtils::SCAIOSUtils::runSystemCommand (in


SCAUString command, out SCAInt32 exitStatus)
Passes "command" to the command interpreter, which executes the string as an operating-
system command. It waits until the execution of command is completed then returns the exit
status of the execution.

Parameters:
in command SCAUString contains the system command to be
executed.
out SCAInt32 contains the exit code from the system
command run.

Returns:
SCASuccess if the "command" is executed successfully. else returns following from "Error code"
SCAOSERR_2BIG, Argument list (which is system dependent) is too big.
SCAOSERR_NOENTITY, if the "command" is invalid.
SCAOSERR_NOEXEC, if Command-interpreter file has invalid format and is not
executable.
SCAOSERR_NOMEM, Not enough memory is available to execute command;
or available memory has been corrupted; or invalid block exists, indicating that
process making call was not allocated properly.

397
SCA Framework Configuring and Using the SCA Kernel

SCAResult SCA::Util::SystemUtils::SCAIOSUtils::setCurrentWorkingDirectory
(in SCAUString dirPath)
Sets application"s current working directory to "dirPath".

Parameters:
in dirPath SCAUString contains the path to which the
current working directory will be set to.

Returns:
SCAResult Status of request.
SCAResult SCA::Util::SystemUtils::SCAIOSUtils::unsetenv (in SCAUString
varName)
Removes environment variable "varName".

Parameters:
in varName SCAUString contains

Returns:
SCASuccess, if "varName" is successfully deleted from the environment, else returns following
from "Error code"
SCAOSERR_ENV_NULL, if "varName" is NULL

SCA::Util::SystemUtils::SCAIPaths Interface

The purpose of this interface is to provide a consistent means to


search for files in a list of directories.
import "[Link]";

Public Member Functions


SCAResult addPathString (in SCAUString path, in AddPathType addType, in SCABool
removeDuplicates)
SCAResult addPathStrings (in SCAUStringSequence paths, in AddPathType addType, in
SCABool removeDuplicates)
SCAResult addPaths (in SCAIPaths paths, in AddPathType addType, in SCABool
removeDuplicates)
SCAResult addOSPath (in SCAUString envVariable, in AddPathType addType, in SCABool
removeDuplicates)
SCAResult removePathString (in SCAUString pathString)
SCAResult removePaths (in SCAIPaths paths)
SCAResult getPathStrings (out SCAUStringSequence paths)
SCAResult getPathStringsEx (out SCAUStringSequence paths, in
SCA::Framework::SCAIConfiguration spConfiguration)
SCAResult findFile (in SCAUString fileName, out SCAUString filePath)
SCAResult findFileEx (in SCAUString fileName, out SCAUString filePath, in
SCA::Framework::SCAIConfiguration spConfiguration)

398
SCA Framework Configuring and Using the SCA Kernel

SCAResult clear ()

Detailed Description
The purpose of this interface is to provide a consistent means to search for files in a list of
directories.

Member Function Documentation


SCAResult SCA::Util::SystemUtils::SCAIPaths::addOSPath (in SCAUString
envVariable, in AddPathType addType, in SCABool removeDuplicates)

Adds the path from the Operating system’s environment variable.

Parameters:
envVariable The OS environment variable containing the paths to
be added
addType Option to specify whether to append or prepend the
path
removeDuplic If true, all the duplicate paths are removed from
ates the path list. If ‘addType’ is ADD_PATH_APPEND the
last occurrence of the path is kept. If ‘addType’ is
ADD_PATH_PREPEND the first occurrence of the path is
kept.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::addPaths (in SCAIPaths paths, in
AddPathType addType, in SCABool removeDuplicates)

Updates path by adding the contents of the input SCAIPaths.

Parameters:
paths SCAIPaths interface object
addType Option to specify whether to append or prepend the
path
removeDuplic If true, all the duplicate paths are removed from
ates the path list. If ‘addType’ is ADD_PATH_APPEND the
last occurrence of the path is kept. If ‘addType’ is
ADD_PATH_PREPEND the first occurrence of the path is
kept.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::addPathString (in SCAUString
path, in AddPathType addType, in SCABool removeDuplicates)

399
SCA Framework Configuring and Using the SCA Kernel

Updates the paths by adding the contents of the input path.

Parameters:
path string representing the path
addType Option to specify whether to append or prepend the
path
removeDuplic If true, all the duplicate paths are removed from
ates the path list. If ‘addType’ is ADD_PATH_APPEND the
last occurrence of the path is kept. If ‘addType’ is
ADD_PATH_PREPEND the first occurrence of the path is
kept.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::addPathStrings (in
SCAUStringSequence paths, in AddPathType addType, in SCABool
removeDuplicates)

Updates the paths by adding the contents of the input list of paths.

Parameters:
paths string sequence representing the list of paths
addType Option to specify whether to append or prepend the
path
removeDuplic If true, all the duplicate paths are removed from
ates the path list. If ‘addType’ is ADD_PATH_APPEND the
last occurrence of the path is kept. If ‘addType’ is
ADD_PATH_PREPEND the first occurrence of the path is
kept.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::clear ()

This method removes all paths from the path list.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::findFile (in SCAUString fileName,
out SCAUString filePath)

Sequentially searches for the file in the list of paths.

400
SCA Framework Configuring and Using the SCA Kernel

Parameters:
fileName File name to search
filePath Absolute path to the file found

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::findFileEx (in SCAUString
fileName, out SCAUString filePath, in SCA::Framework::SCAIConfiguration
spConfiguration)

Sequentially searches for the file in the list of paths.

Parameters:
fileName File name to search
filePath Absolute path to the file found
spConfigurat Smart pointer to the Configuration interface, to be
ion used to get the variables to be expanded.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::getPathStrings (out
SCAUStringSequence paths)

Returns the list of directory paths.

Parameters:
paths list of absolute directory paths

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::getPathStringsEx (out
SCAUStringSequence paths, in SCA::Framework::SCAIConfiguration
spConfiguration)

Returns the list of directory paths and expand any configuration variables.

Parameters:
paths list of absolute directory paths
spConfigurat Smart pointer to the Configuration interface, to be
ion used to get the variables to be expanded. The
variable name must be enclosed between ?[ and ]?
characters as in ?[ENV_VARIABLE]? For example
?[INSTALL_ROOT]?/plugins should return the path that

401
SCA Framework Configuring and Using the SCA Kernel

starts with the content of the configuration


variable INSTALL_ROOT.

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::removePaths (in SCAIPaths paths)

Removes the directories belonging to the input SCAIPaths from the list of paths.

Parameters:
paths SCAIPaths interface object

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult SCA::Util::SystemUtils::SCAIPaths::removePathString (in SCAUString
pathString)

Removes the input directory from the paths.

Parameters:
pathString string representing a path

Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCA::Util::SystemUtils::SCAIPathUtils Interface

This interface contains methods for file path manipulations.


import "[Link]";
Public Member Functions
SCAUString absolutePath (in SCAUString path) raises
(FileNoAccessException,IncompatiblePathsException)
SCAUString convertPath (in SCAUString pathString, in SCAOSType toFormat)
SCAUString directoryPath (in SCAUString path)
SCAUString driveName (in SCAUString path)
SCAUString extension (in SCAUString path)
SCAUString fileName (in SCAUString path)
SCABool isAbsolute (in SCAUString path)
SCAUString join (in SCAUStringSequence paths)
SCAUString normCase (in SCAUString path)

402
SCA Framework Configuring and Using the SCA Kernel

SCAUString normPath (in SCAUString path)


SCAUString relativePath (in SCAUString path, in SCAUString startPoint)
void splitPath (in SCAUString path, out SCAUString drive, out SCAUString dir, out SCAUString
fileName, out SCAUString fileExt)

Detailed Description
This interface contains methods for file path manipulations.
Unlike in SCAIFileUtils interface, none of the methods check the existence of any of the paths
provided. All operations are string based. Some methods do call other methods in the service that
do file system operations such as to obtain the current working directory to find the absolute path
for a given path.
On all platforms return values will only contain the forward slash "/" as the path separator. If the
user needs backward slash "\" as the path separator on Windows, he should call convertPath

Member Function Documentation


SCAUString SCA::Util::SystemUtils::SCAIPathUtils::absolutePath (in SCAUString
path) raises (FileNoAccessException,IncompatiblePathsException)
Returns the absolute path of the specified file. The existance of file is not checked.
For ex: if current working directory is /A/B/C and
absolutePath ("[Link]" ) -> returnValue = /A/B/C/[Link]
absolutePath ("D/[Link] ) -> returnValue = /A/B/C/D/[Link]\n absolutePath
("../[Link] ) -> returnValue = /A/B/[Link]

Parameters:
in path SCAUString to get the absolute path.

Returns:
SCAUString that contains the absolute path.
SCAUString SCA::Util::SystemUtils::SCAIPathUtils::convertPath (in SCAUString
pathString, in SCAOSType toFormat)

Returns the pathString parameter formated according to the toFormat parameter. For example, if the
"pathString"= "\temp1\temp2".

"toFormat" = Unix, then "convertedDirectory" = "/temp1/temp2"


"toFormat" = Windows, then "convertedDirectory" = "\temp\temp2"
Parameters:
in pathString SCAUString to convert according to platform.
in toFromat an enum that contains the platform according
to which the path would be converted.
Returns:
SCAUString that contains the converted path.

403
SCA Framework Configuring and Using the SCA Kernel

SCAUString SCA::Util::SystemUtils::SCAIPathUtils::directoryPath (in


SCAUString path)

Returns the directory string from the given path. If path is:

"C:/dir1\dir2/[Link]" then returnValue = "C:/dir1/dir2"


"/root/dir1/dir2/[Link]" then returnValue = "/root/dir1/dir2"
Parameters:
in path SCAUString that contains the whole path.
Returns:
SCAUString that contains the directory part of the path provided.

SCAUString SCA::Util::SystemUtils::SCAIPathUtils::driveName (in SCAUString


path)

Returns the drivename of the given path. Only Windows platforms return meaningful results. Any
other platform returns an empty result. For UNC paths it returns the computer name. If path is:

"C:/dir1/[Link]" then returnValue = "C:"


"\\server\dir1\[Link]" then returnValue = \server
"//server/dir1/[Link]" then returnValue = \server
Parameters:
in path SCAUString that contains the whole path.
Returns:
SCAUString that contains the drive name of the path provided.

SCAUString SCA::Util::SystemUtils::SCAIPathUtils::extension (in SCAUString


path)

Returns the extension of the given file path. If path is:

"[Link]" then returnValue = "txt"


"[Link]" then returnValue = "bak"
"myfile" then returnValue = "" - empty string
Parameters:
in path SCAUString that contains the whole path.
Returns:
SCAUString that contains the extension of the path provided.

404
SCA Framework Configuring and Using the SCA Kernel

SCAUString SCA::Util::SystemUtils::SCAIPathUtils::fileName (in SCAUString


path)

Returns the filename of the given path. If path is:

"C:/dir1/dir2/[Link]" then returnValue = "myfile"


"C:/dir1/dir2/[Link]" then returnValue = "[Link]"
"C:/dir1/dir2/myfile" then returnValue = "myfile"
Parameters:
in path SCAUString that contains the whole path.
Returns:
SCAUString that contains the file name of the path provided.

SCABool SCA::Util::SystemUtils::SCAIPathUtils::isAbsolute (in SCAUString path)


Checks if the provided path is an absolute path. On Windows joinedPath would be true if path
started with "\\" or drive letter, colon and "\\" or "/" - For example "C:\\" or "C:/" On POSIX
platforms, joinedPath would be true only if path started with "/"

Parameters:
in path SCAUString that contains the path to check
absoluteness.

Returns:
SCABool is set to true if path provided is aboslute or else, false.
SCAUString SCA::Util::SystemUtils::SCAIPathUtils::join (in
SCAUStringSequence paths)

Returns a SCAUstring with all the paths passed in through the SCAUStringSequence joined together.
If an absolute path is found as one of the elements of SCAUStringSequence all previous components
will be discarded. If an empty sequence is given, returned string would be an empty string.

Parameters:
in paths SCAUStringSequence containing paths to join.

Returns:
SCAUString contains the joined path.
SCAUString SCA::Util::SystemUtils::SCAIPathUtils::normCase (in SCAUString
path)

Returns the path parameter with case normalized. On Linux and Unix systems the path is returned
unchanged. On Windows the string path is converted to all lowercase.

Parameters:

405
SCA Framework Configuring and Using the SCA Kernel

in path SCAUString to normalize the case.

Returns:
SCAUString contains the path with normalized case.
SCAUString SCA::Util::SystemUtils::SCAIPathUtils::normPath (in SCAUString
path)

Returns the path normalized. This collapses redundant separators and up-level references so that A//B,
A/B/, A/./B and A/foo/../B all become A/B. Existance of file is not checked.

Parameters:
path SCAUString to normalize the path.

Returns:
SCAUString contains the normalized path.
SCAUString SCA::Util::SystemUtils::SCAIPathUtils::relativePath (in SCAUString
path, in SCAUString startPoint)

Returns the path relative to startPoint. "path" and "startPoint" have to be in the same drive. The routine
will go up in "path" and "startPoint" until a common directory is found. If none is found, common
would be the root of the filesystem. The existance of file is not checked. The startPoint must be a
directory. If a filename is given, it will be assumed as a directory.

Parameters:
in path SCAUString contains the end point of relative
path.
in startPoint SCAUString contains the start point of
relative path.

Returns:
SCAUString contains the relative path from startPoint to end point represented by path parameter.
void SCA::Util::SystemUtils::SCAIPathUtils::splitPath (in SCAUString path, out
SCAUString drive, out SCAUString dir, out SCAUString fileName, out SCAUString
fileExt)
Method to break the "path" into its components. If the "path" does not contain the particular
component, a blank will be returned. Each component includes any appropriate separation
characters so if they are combined back together, the results is the same as the input.

For example

"path" = "C:\dir1/dir2\[Link]"

Then:

"drive" = "C:"

406
SCA Framework Configuring and Using the SCA Kernel

"dir" = "/dir1/dir2/"
"fileName" = "filename"
"fileExt" = ".ext"

Special Windows Notes:

On Windows forward and backward slashes in the input are treated the same. On output, all
slashes are converted to forward slashes. If the file name is a UNC format, then the computer
name is returned in the "drive" parameter.

For example

"path" = "\\computer\dir1\dir2\[Link]"

Then

"drive" = "\\computer"
"dir" = "/dir1/dir2/"
"fileName" = "[Link]"
"fileExt" = ".new"

Parameters:
path [in] Input path to be parsed
drive [out] drive letter followed by a colon (:) or UNC
computer name preceded by double slash (//). For
Unix platforms, a single forward slash (/) is
returned to mark the root of the filesystem. If
"path" is not absoulte "drive" is always returned
blank.
dir [out] Absolute or relative directory path. If the
path was absolute, this will contain a forward slash
at the beginning to mark absoluteness on all
platforms.
fileName [out] Base filename without extension
fileExt [out] Filename extension preceded by a leading
period (.)

System Utils example


SCA::SCAIService spService;
SCA::Util::SystemUtils::SCAIFileUtils iFileUtils;
SCA::Util::SystemUtils::SCAIOSUtils iOSUtils;

SCAResult res;

spService = m_serviceAccess->getService("[Link]",res);
if (res) return res;

iFileUtils = static_cast<SCA::Util::SystemUtils::SCAIFileUtils>
(spService);

iOSUtils = static_cast<SCA::Util::SystemUtils::SCAIOSUtils>
(spService);
SCAUString currentWorkingDir;

407
SCA Framework Configuring and Using the SCA Kernel

res = iOSUtils->getCurrentWorkingDirectory(currentWorkingDir);

SCABool bExists;
res = iFileUtils->exists(currentWorkingDir,bExists);

408
SCA Framework Configuring and Using the SCA Kernel

13.17. Stream I/O Facility


The following sections list the interfaces provided by the [Link]
service. For detailed description of the methods please consult the Online API Documentation.

SCA::Framework::SCAIStream Interface
This interface is an abstraction of the IO stream. It contains methods common to both input
and output streams.
Member Functions

SCAResult seek (in SCAInt64 position, in SCAUInt8 origin)


Moves the stream pointer to the desired location.

SCAResult tell (out SCAInt64 position)


Reports the position of the stream pointer.

SCAResult eof ()
Reports whether the stream pointer is at the end of the stream.

SCA::Framework::SCAIInStream Interface
This interface is used for reading from the stream. It provides methods to read all the IDL
supported data types.

Inherits SCA::Framework::SCAIStream.

Member Functions

SCAResult enableByteSwapping ()
Enable byte swapping. This method sets the stream so that it
converts data from one Endian system to another as the data
is read. Caution: This needs to be used only if the client is
sure that the conversion is appropriate. Otherwise, it may
result in bad data values. The client needs to write a known
value at the head of the stream and read it to determine if
swapping is needed and then call this method.
SCAResult readInt8 (out SCAInt8 value)
Reads a SCAInt8 value from the current position in the stream.

SCAResult readUInt8 (out SCAUInt8 value)


Reads a SCAUInt8 value from the current position in the stream.

SCAResult readInt8Sequence (inout SCAInt8Sequence value)


Reads a sequence of SCAInt8 values from the current position in the stream.

SCAResult readUInt8Sequence (inout SCAUInt8Sequence value)


Reads a sequence of SCAUInt8 values from the current position in the stream.

SCAResult readInt8Buffer (inout SCAInt8Sequence value, in SCAInt32 size)


Reads a sequence of SCAInt8 values from the current position in the stream.

SCAResult readUInt8Buffer (inout SCAUInt8Sequence value, in SCAInt32 size)

409
SCA Framework Configuring and Using the SCA Kernel

Reads a sequence of SCAUInt8 values from the current position in the stream.
... ...

SCA::Framework::SCAIOutStream Interface
This interface is used for writing to the stream. It provides methods to write all the IDL
supported data types.

Inherits SCA::Framework::SCAIStream.

Member Functions

SCAResult writeInt8 (in SCAInt8 value)


Writes a SCAInt8 value from the current position in the stream.

SCAResult writeUInt8 (in SCAUInt8 value)


Writes a SCAUInt8 value from the current position in the stream.

SCAResult writeInt8Sequence (in SCAInt8Sequence value)


Writes a sequence of SCAInt8 values from the current position in the stream.

SCAResult writeUInt8Sequence (in SCAUInt8Sequence value)


Writes a sequence of SCAUInt8 values from the current position in the stream.

SCAResult writeInt8Buffer (in SCAInt8Sequence value, in SCAInt32 size)


Writes a sequence of SCAInt8 values from the current position in the stream.

SCAResult writeUInt8Buffer (in SCAUInt8Sequence value, in SCAInt32 size)


Writes a sequence of SCAUInt8 values from the current position in the stream.
... ...

SCA::Framework::SCAIStreamIOFactory Interface
This interface is used to create a new IO stream.

Member Functions

SCAResult createInStream (in SCAString filePath, out SCAIInStream spStream)


Creates an input only stream.

SCAResult createOutStream (in SCAString filePath, out SCAIOutStream spStream)


Creates an output only stream.

SCAResult createInOutStream (in SCAString filePath, out SCAIOutStream spStream)


Creates a stream for input and output.

410
SCA Framework Configuring and Using the SCA Kernel

13.18. Timer Service


Timer service provides user with a tool that notifies listeners after
each time-out event. A timer can be recurring or a single-shot.
Recurring timer will keep notifying the listener until the timer is
stopped; whereas a single-shot timer will only notify the listener once
and stop.

The service is an actual factory for timer objects. It is a singleton


service. The factory can create as many timer objects as the user
desires. All timer objects are thread safe.

A listener can be registered for 2 timer objects. But user must take
care to implement the listener object in a thread-safe manner since
notifying from each timer object happens on its own thread.

SCA::Util::Timer::SCAITimerFactory Interface

Interface to create Timer objects.

Public Member Functions


SCAResult createTimer (out SCAITimer timer)

Detailed Description
Interface to create a Timer.

Member Function Documentation


SCAResult SCA::Util::Timer::SCAITimerFactory::createTimer (out SCAITimer
timer)
Returns a new instance of a timer object. Timer factory service is a singleton service, it
generates thread-safe timer objects for user.

SCA::Util::Timer::SCAITimer Interface Reference

Interafce for actual Timer object operations. Each Timer has a list of
SCAITimerListeners and a delay (the time between timerTickPerformed()
calls). When delay milliseconds have passed, the Timer calls each
listener's timerTickPerformed() method. This cycle repeats until stop()
is called, or halts immediately if the Timer is single-shot.

Public Member Functions


SCAResult isActive (out SCABool isActive)
SCAResult start (in SCAInt32 msec, in SCABool sshot)
SCAResult changeInterval (in SCAInt32 msec)
SCAResult stop ()

411
SCA Framework Configuring and Using the SCA Kernel

SCAResult getDelay (out SCAInt32 delay)

Detailed Description
Interafce for actual Timer object operations. Each Timer has a list of SCAITimerListener(s) and a
delay (the time between timerTickPerformed() calls). When delay milliseconds have passed, the
Timer calls each listener's timerTickPerformed() method. This cycle repeats until stop() is called,
or halts immediately if the Timer is single-shot.

Member Function Documentation


SCAResult SCA::Util::Timer::SCAITimer::changeInterval (in SCAInt32 msec)
Changes the timeout interval to msec milliseconds. If the timer signal is pending, it will be
stopped and restarted with the new interval and the existing condition for repeat.

Parameters:
in msec SCAInt32 value to which the time out value
shall be set to.

Returns:
Status of the call.
SCAResult SCA::Util::Timer::SCAITimer::getDelay (out SCAInt32 delay)
Returns the delay, in milliseconds, between firings of action events.

Parameters:
out delay Gets the current timeout value as a SCAInt32.

Returns:
Status of the call.
SCAResult SCA::Util::Timer::SCAITimer::isActive (out SCABool isActive)
Returns TRUE if the timer is running (pending); otherwise returns FALSE.

Parameters:
out isActive SCABool is set to True if Timer is active,
else False.

Returns:
SCASuccess if an active Timer is running else return INVALID_TIMER_OBJ error.
SCAResult SCA::Util::Timer::SCAITimer::start (in SCAInt32 msec, in SCABool
sshot)
Starts the timer with an msec milliseconds timeout, and returns a SCAResult if starting the
timer failed. If sshot is TRUE, the timer will be activated only once; otherwise it will
continue until it is stopped by calling stop().

Parameters:
in msec Timout value in milliseconds as a SCAInt32

412
SCA Framework Configuring and Using the SCA Kernel

value.
in sshot SCABool set to True if the Timer should be
single shot, set to False if Timer should be
recurring.

Returns:
Status of the call.
SCAResult SCA::Util::Timer::SCAITimer::stop ()
Stops the running timer.

Returns:
Status of the call.

Timer Service Example

// This is a listener setup for the timer using


// #include <SCA/Framework/ServiceObjectImpl.h>
char TestTimerListenerNameStart[] = "TestTimerListenerStart";
class TestTimerListenerStart : SCAServiceObjectImpl2Base
<SCA::Util::Timer::SCAITimerListener,
SCA::Util::Timer::SCAIListener,
TestTimerListenerNameStart>
{
public:
// Constructors and Destructor
TestTimerListenerStart() { }
TestTimerListenerStart(SCAString name):m_name(name){}
~TestTimerListenerStart() { }
// Methods for interface [Link]
SCAResult timerTickPerformed(const
Util::Timer::SCAITimerEventArgs &actionArg, const
Util::Timer::SCAITimer &timer)
{
cout<<m_name<<" was notified. Calling start()"<<endl;
}

SCAITimerListener getSCAListener() { return


SCAITimerListener(this);}
private:
SCAString m_name;
};

// code to create a timer object


SCAIService spService;
SCAITimerFactory timerFac;
SCAITimer timerInf;
spService = m_serviceAccess->getService
("[Link]",rstat);
if(rstat) return rstat;
timerFac = static_cast<SCA::Util::Timer::SCAITimerFactory>
(spService);

cout<<"Creating timer object."<<endl;

413
SCA Framework Configuring and Using the SCA Kernel

rstat = timerFac->createTimer(timerInf);
if(rstat) return rstat;

// create a new listener


SCAITimerListener testTimerList =
(SCA::Util::Timer::SCAITimerListener::pointer) new
TestTimerListenerStart("Listener 3");
timerInf->addListener(SCA::Util::Timer::TimerListener,
TIMER_EVENT,
testTimerList);
timerInf->start(100,true); // true here means single shot
// therefore stopping is not needed.

414
SCA Framework User Document

Chapter 15

SCA Utility Program and Testing


Components
14. SCA Utility Program and Testing Components
14.1. Introduction
This chapter describes the functionality available in the SCA Framework for testing of
services and components. In particular it discusses the SCA utility program scautil and the
TestRun environment routine of the SCA SCons build system. The combination of these two
can be used to test loading of components, query information and run tests. The tests could be
run either manually or as part of the build process.
14.2. The SCA Utility Program
The SCA utility program scautil is used to perform the following tasks.
Test Kernel initialization
Run a test service
Run a script
Test loading of a shared library
Query the Kernel information
Query the shared library build information

There is no script provided with the SCA Framework to run the scautil program because it
would be difficult to provide one that was general enough to be helpful. But, the scautil is just
a normal SCA application and it requires the same configuration as any SCA application. The
details of this are discussed in SCA Kernel chapter of this manual. As an example, the
following simple C shell script could be used to run the delivered version of the Framework.
#! /bin/csh
#
set ISYSTEM = D:/SCAKernel-V4-007
set DSYSTEM = $ISYSTEM/WINNT
#
set path = ( $DSYSTEM/lib $DSYSTEM/bin $path )
#
setenv SCA_SERVICE_CATALOG "$ISYSTEM/res/[Link]"
#
setenv SCA_RESOURCE_DIR "$ISYSTEM/res"
#
$DSYSTEM/bin/[Link] $*

Typically, you would need to modify this to also point to the APPS directory for the
components you have built.

The syntax for running scautil is a follows.


Syntax:
scautil [arg1] [arg2] [arg3] . . .

The rest of this section describes the usage of the scautil program.
Print the help message
The –h argument can be used to generate a listing of all the available options that the scautil
program supports.
scautil -h

Testing Kernel Initialization


If no arguments are provided to the command, the program initializes the SCA Kernel and
then exits. This can be used to test for the proper configuration of the Kernel.
Usage:
scautil

Output:
SCA Kernel 4.7.0 successfully initialized
SCAUtil: No arguments were specified
SCAUtil: Kernel loaded successfully and is now cleaning up

Running a Batch Test


One of the most commonly used options of the scautil utility is to use it to run component
tests. To do this you must code a test service which implements the SCAIBatchTest interface.
The requested service is loaded and the runBatchTest method is called. Any additionally
arguments supplied on the command line are passed to the service in a sequence of strings.
Usage:
scautil -test servicename [optional arguments...]

Examples:
scautil -test [Link] BaseImpl SmartPointer

The complete details of this feature are described later in this chapter.

Run a Script
The –script option can be used to run a script using the runScript method of the ScriptBroker
service.
Usage:
scautil -script file

Example:
scautil -script [Link]

Test Loading of a Shared Library


The –testload option can be used to test if the specified library exists and can be loaded
correctly. If the loading of the library fails, a detailed error message is provided which can be
helpful to determine why the load failed.
Usage:
scautil -testload [-noinfo] library_name
This option also checks if any of the known symbols that a SCA component might export
from a library exist and outputs this information.

If the optional argument –noinfo is specified as the second argument, the library is loaded but
no information will printed except for the appropriate errors if the load is unsuccessful.
Example:
scautil -testload [Link]

Output:
SCA Kernel 4.7.0 successfully initialized

Symbol SCA_Comp_Info was found at address 008869D0

Library generic name is SCAKernel


Library full name is /SCA/SCAKernel-V4-007/WINNT/bin/[Link]

Query SCA Kernel Information


The –kernelinfo command can be used to show the information about the SCA Kernel that is
being used.
Usage:
scautil -kernelinfo

Output:
SCA Kernel 4.7.0 successfully initialized

Kernel Build Information

Build Date = Jul 28 2009


Build Time = 18:16:09
Major Version = 4
Minor Version = 7
Source Label = V4-007

Query Shared Library Build Information


To print the build and product information for the specified SCA component, you can use the -
buildinfo option.
Usage:
scautil -buildinfo library_name

Example:
scautil -buildinfo C:/SCAKernel-V4-007/WINNT/bin/[Link]

Output:
Build Information for [Link]

Build Date = Jul 28 2009


Build Time = 18:16:09
MajorVersion = 4
MinorVersion = 7
BuildVersion = 0
BuildLabel = V4-007
ProductName = SCA Kernel
ProductLabel = SCA

Every SCA component will have information with the date and time of the build. See the SCA
Build System Guide for the details on how you can add other build information to a
component.

14.3. Testing of SCA components


The scautil command provides the –test option which can be used for testing components. To
use this option, you normally write a separate service that is used to drive the test. This test
service must implement the SCAIBatchTest interface.

SCA::Framework::SCAIBatchTest Interface Reference

SCAIBatchTest is interface used by the scautil program to run batch tests on any service
that implements it.

Inherits SCA::SCAIService.

Member Functions
SCAResult runBatchTest (in SCAStringSequence args)

Member Function Documentation


SCAResult runBatchTest ( in SCAStringSequence args )
Runs test on a service.
Parameters:
args SCASequence of command line arguments

Running Tests Manual


Tests can be run manually using the scautil program.
scautil -test servicename [optional arguments...]

For example the following command will test the base class implementation and smart
pointers.
scautil -test [Link] BaseImpl SmartPointer

When manually running tests, the output you get is what is directly produced by the service
you use to run the test. In order to check if the test was successful, you either have to have self
checking built into the testing service or you need to compare the output against a baseline that
you know is correct. Because of this, the preferable way is to run the tests using the SCA build
system and the TestRun environment command which provides much more flexibility and
power.
Running Tests with the Build System
The TestRun environment command is used to run tests as part of the build process. This
feature is primarily designed for cases where the tests can be run in a batch mode and is
generally not appropriate for testing interactive applications.

The basic idea is to run the test whenever the test component is built. The output from the run
can then be compared to the baseline data contained in a text file to find any regressions.
Syntax:
Def TestRun ( program=None,
component=None,
baseline=None,
command=None,
args=None,
aliases=None,
fixup=None,
nocatalog=None,
loadpaths=None,
setup=None,
cleanup=None,
title=None,
dependfiles=None,
dependaliases=None,
preprocess=None,
addtodefaults=None)

The following are the arguments that are available for the TestRun routine.

Argument Description

program
Programs(s) that this test is dependent on. They must be built in the
current build run.
Components(s) that this test is dependent on. They must be built in the
component current build run. Non C++ components can be specified by prefacing
them with the language and a virtical slash. (java|X.Y.Z)
baseline
The baseline results file for the test. If this argument is omitted, then no
check is performed on the test output.
The actual command that will run the test. If this argument is omitted,
command
then the first entry in the program argument is used. This argument may
be a python function or an executable program in the Apps Local or
Apps System bin directory.
args Any additional arguments to be passed to the command running the tests.
aliases
Aliases that can be used as targets on the scons command to request the
running of this test.
fixup
Python script that is used to modify each line of output from the test run
before it is compared to the baseline output.
Normally the test is also made dependent on the Service catalog to make
nocatalog sure any catalog updates are done before the test is run. If this argument
is set true, then this dependency is not established.
loadpaths Any extra paths for loading libraries to be used when running the test.
These paths may be absolute or relative to the bin or lib subdirectory,
depending on the current platform, in the APPS_LOCAL_MACH and
APPS_SYSTEM_MACH directories.
setup
Python script that will be run before the actual test is run. It can be used
to do any special setup processing that the run requires.
cleanup
Python script that will be run after the actual test is run. It can be used to
do any required clean up processing after the test.
title Title which is printed out for test
dependfiles File or list of files that the test is dependent on
dependaliases Alias or list of aliases that the test is dependent on
The baseline file is run through a macro preprocessor before it is used.
The value of this option is a Python dictionary that contains the variables
and their values which are referenced in the preprocessor commands. For
preprocess
example:
env = {}
env['VAR1'] = True
env['VAR2'] = False
[Link](...,preprocess=env)
If true, the targets of the test are added to the list of default targets. This
addtodefaults
way the test will run if no command line targets are provided. The
normal behavior is the test will only run if it is requested by a target on
the command line.

Setting up Test Aliases


Normally the [Link] command in your SConscript file should define an alias for the
test. This makes it much easier to request which test you want to run on the scons command.
The following shows an example of how this is done.
[Link](program="KernelUse",
baseline="[Link]",
aliases="KernelUseTest")

[Link](program="MemManager",
baseline="[Link]",
aliases="MemManagerTest")

To select the test you want to run, you use the alias name on the build command.
scons KernelUseTest
scons KernelUseTest MemManagerTest

Specifying when Tests run by Default


By default, the targets from the TestRun command are not added to the list of targets that
SCons will build if you do not request any on the command line. This means if you use a build
command similar to the following, the test will not be run.
scons

You can change this behavior by adding the addtodefaults argument on the TestRun
command. Now the tests will be run when no targets are given on the command line.
[Link](program="MemManager",
baseline="[Link]",
aliases="MemManagerTest"
addtodefaults=True)

Running Test Using a SCA Test Component


A typical test scenario is to have a separate SCA component that is used to test your
production components. Normally the component to do the testing is built in the same
directory where the TestRun routine is issued. The following is an example of how this type
of test is run.
[Link](component="[Link]",
command="scautil",
args="-test [Link]",
baseline="[Link]",
aliases="CatalogTest")

In this case, the test component, [Link], is built in the current directory. The
scautil command with the -test option is used to load and run the test service it contains. The
output from the run is compared to the baseline data contained in the file [Link]
which is also in the current directory. This test will be run when the CatalogTest alias is
specified on the scons command as follows.
scons CatalogTest

Testing Using a Program


A similar test could have been done using a program instead of a SCA component as the test
driver. This is shown in the following example.
# Build a main program that depends on a shared library
[Link]("UtilTest","Utilities")
[Link]("UtilTest")

# Run the test and check the results


[Link](program="UtilTest",
baseline="[Link]",
loadpaths="File/Utilities",
alias=”UtilitiesTest”)

In this example we are using a program, UtilTest, built in the current directory to run the tests
on a non-SCA shared library, Utilities. The shared library is built in a different directory so we
set up a dependency between the program and the shared library to make sure it will be built
when needed. The TestRun routine specifies that we are using a program to run our tests. In
this case, it is not necessary to specify the command to run since it is the same as was
specified in the program argument. We have also used the loadpaths argument so the loader
can find the shared library. This is required since the File/Utilities directory, where the shared
library is built, is not in the default load path.

Testing Using Python Script


You can also use a Python script as the driver for the test. The following is an example of how
this can be done.
# Set Python's path to the current directory and import the script
import sys
[Link](0,[Link]("."))
import TestScript

# Run the test


[Link]( command=[Link],
baseline=”[Link]”,
aliases="TestRunTest")

In this example, the TestRun routine executes the test function in the [Link] Python
script. If you want to use the feature to compare the test results to a baseline, then the script
should return a Python list containing the lines of output to be compared. The following is an
example of what the Python script could look like.
# Python script to drive test
import SCA
def test(env,args):
output = []
spService = [Link](‘[Link]’)
if not spService:
[Link](‘Error loading service’)
return output
(ret,inf) = [Link](‘[Link]’)
if ret:
[Link](str(ret))
return output
entry = [Link](‘TestEntry’)
[Link](‘Catalog entry = ’ + entry)
return output

Using a fixup Routine


Sometimes it is difficult to use the baseline compare feature because some lines of output
change from run to run and these will always trigger an error. A simple example of this could
be if the output contained the date of the run. To handle these situations, you can provide a
Python script to the TestRun routine that is used to process each line of output before it is
compared to the baseline. The following is an example of doing this.
# Set Python's path to the current directory and import fixup script
import sys
[Link](0,[Link]("."))
import CatalogTestFixUp

# Run the test


[Link](component="[Link]",
command="scautil",
args="-test [Link]",
baseline="[Link]",
fixup=[Link],
aliases="CatalogTest")

In this example the fixup routine in the Python script [Link] is used to process
each line of output. It looks for any occurrences of a date with the form dd/mm/yyyy and
replaces it with a generic xx/xx/xxxx so the compare can be successful.
import re
def fixup(env,line):
line = [Link](" [0-9]{2}/[0-9]{2}/[0-9]{4} "," xx/xx/xxxx ",line)
return line

The fixup routine is called with two arguments. The first argument is the current SCons
environment that the test is running in and the second argument is the line of output to be
processed.

The fixup routine can also specify that the output line should completely be deleted from the
comparison as follows.
def fixup(env,line):
if [Link](“Sting to trigger line deletion”) > 0:
return []
return line

Or it can replace one line with several lines.


def fixup(env,line):
if [Link](“Line to be replace with several lines”) > 0:
line = []
[Link](“new line 1”)
[Link](“new line 2”)
return line
return line

In general, the return value from the fixup routine should be one of the following.
The original string value of the line
A new string value for the line
A list of string values to replace the original one. This list may be empty.

Using the Preprocessor on the Baseline Text


The fixup routine provides a convenient way to handle simple changes in the output which
only affect a single line. If the changes that need to be made involve processing a block of
lines as a unit then it can be difficult to do with the fixup feature. To handle these cases, the
TestRun command provides a simple preprocessor that can be used to customize the baseline
text before it is used to test the result. To use this feature you add a preprocessor argument to
the TestRun command. The value of the argument is a Python dictionary which contains the
preprocessor variable names and their values. The following example shows the use of this
feature for the case where a particular test is only run the Windows platform.
# Setup the preprocessor arguments
vars = {}
if env[‘MACHINE’] == “WINNT”:
vars[‘WINNT’] = True
else
vars[‘WINNT’] = False

# Run the test


[Link](component="[Link]",
command="scautil",
args="-test [Link]",
baseline="[Link]",
preprocess=vars,
aliases="CatalogTest")

The baseline text file, [Link], would then include the appropriate preprocessor
command to skip the relative lines if the test is not being run on Windows.
Line for all machine
#if WINNT
Line for Windows only
#endif
Line for all machines

Performing Setup and Clean Operations


There may be cases when you need to do some special setup processing before the test is run
and related clean up processing after the test. An example of this may be the creation of
special input files and the deleting of temporary files created during the test. It is important to
remember that these types of operations should not be performed directly in the SConscript
file for a number of reasons.
Any setup type operations executed directly in the SConscript file will be performed
every time the build is run, even so the actual test may not be executed during the current
build.
The SConscript file is always completely executed before any targets are built which
means in this case before any tests are run. As a result there is no way to perform any
cleanup operations in SConscript file.
The proper way to perform these types of operations is to use the setup and cleanup arguments
in the TestRun command. Each of these should point to a Python routine which takes a single
argument which is the SCons environment for the test. The setup routine, if provided, will be
run immediately before the test is run and the cleanup routine will be run immediately after the
test is run. The following shows an example of how these can be used.
import os

# Setup routine
SetupFunc(env):
# Create a test input file
try:
file = open(‘[Link]’, 'w')
for i in range(1024):
[Link](" ")
[Link]()
except:
pass

# Cleanup routine
CleanupFunc(env):
try:
[Link](‘[Link]’)
except:
pass

# Run the test


[Link](component="[Link]",
command="scautil",
args="-test [Link]",
baseline="[Link]",
setup=SetupFunc,
cleanup=CleanupFunc,
aliases="CatalogTest")

Special Construction Variables used by the TestRun Command


The TestRun command also looks for several special construction variables in the build
environment to provide additional control on the test. These are shown in the following table.
Variable Meaning
TESTRUN_DEBUG
SCA Kernel debug parameters which are normally set with the
system environment variable SCA_KERNEL_DEBUG.
TESTRUN_ENV
Python dictionary with values to be added to the operating system
environment for the test.
Replacements to the default Apps Local and Apps System
TESTRUN_LOADPATH
locations that are added for the test command. These are in
addition to any paths that are specified using the loadpaths
argument to the TestRun command.

The following example shows how these can be used.

# Setup special environment for the test


env['TESTRUN_DEBUG'] = "ShrLibLoad=all"
pylib = [Link](env['APPS_LOCAL'],"lib","python")
scripts = [Link](env['APPS_LOCAL'],"res","scripts")
env['TESTRUN_ENV'] = { "PYTHONHOME":env['PYTHON_SYSTEM'],
"PYTHONPATH":pylib+[Link]+scripts }

# Run the test


[Link](component="[Link]",
command="scautil",
args="-test [Link]",
baseline="[Link]",
aliases="PythonTest")
SCA Framework SCA Utility Program and Testing Components

SCA Framework User Document

Chapter 16

SCASCons Build System

427
SCA Framework SCASCons Build System

15. SCASCons Build System


The SCA Build System is used to build SCA Framework components. Together, the build
system and the SCA IDL compiler make the development of SCA components easier for the
programmer by automating many of the required steps in the coding and build process.
The SCA build system utilizes the SCons utility to do the builds. SCons is an open source
software build tool that is an improved cross-platform replacement for the classic Make utility.
SCons is implemented as a Python script and set of modules. Because SCons configuration
files are actually executed as Python scripts, build customization can be done using the Python
language.

The SCons system has been customized for the SCA environment and provides the following
functionality.
Automatic traversal of the source tree processing all directories containing a
SConscript file
Setting up appropriate processing for every file in a directory with a supported file
type
Automating the building and management of SCA components
This section provides a basic overview of the SCA build system and describes the steps for
building a SCA service. For a complete description of the build system, see the document
SCA Build System Guide.
15.1. Configuring the Build System
The build system has to be configured before it can run successfully. The main parts of
configuring the build are as follows:
1. Create the source tree, which contains all the code files to build.
2. Create the configuration files in the source tree with proper construction variables.
3. Install the SCA Build System (if it is not already installed).
4. Install any required third party software.
5. Set the system environment variables.

Construction Variables
The SCA build system uses construction variables containing string values that are substituted
into command lines or used by the builder functions. The construction variables may contain
paths, compiler flags and other build options.

The following places can be used to specify the construction variables.


1. The SConscript files in each directory
2. Using command line arguments
3. The [Link] option file in the users home directory
4. The SConopts option file in the root directory of the source tree
Examples:

428
SCA Framework SCASCons Build System

APPS_DIR = "MyComponent-015"
SCA_OBJECT = “C:/Builds/HelloWorld”
APPS_SYSTEM = “C:/SCA/SCAKernel-V4-007”
APPS_LOCAL = “C:/Builds/HelloWorld/Apps”

Note that these examples show the setting of configuration variables on the command line and
the SConopts files. The syntax for setting configuration variables in the SConscript file is
discussed later.
Directory Trees Processed by the Build System
The SCA build systems processes several different directory trees including the source tree,
the object tree, and two delivery trees. Depending on the options the user has set, these
directory trees may overlay each other or be completely separate.
Source
The source tree contains the source code for the SCA components you are developing. The
source tree is normally stored in source control so any changes can be controlled and tracked.
As far as the build system is concerned, it is a directory tree containing the source and has no
dependency on any source control software.

The source tree is also where you must run the build command. The root of the source tree is
determined by the presence of a file named SConstruct. If you start the build in a
subdirectory within the source tree with the –D option, the build system will traverse up the
directory tree until it finds a SConstruct file to determine where the root of the source tree is
located.
Object
The object directory contains transitory files created during the build that can be deleted
afterwards if desired. Each build run will only rebuild files that are out of date in the object
directory. The location for the object directory is defined by the SCA_OBJECT construction
variable, and it has the same directory structure as the source tree.
Apps System
The Apps System directory contains all of the components that make up the release of the
product on which your component is based. This is where the SCA Framework is located as
well as any other components that your component uses. It does not contain your component.
The tree is organized in a structure optimized for running the application.

The types of files listed below are stored in both the Apps System and Apps Local directory
trees.
IDL files
C++ header files generated from the IDL files
Dynamically linked shared library for the component
Resource files that are required by the component
The location of the Apps System directory is defined by the APPS_SYSTEM (absolute path)
construction variable or the APPS_DIR (relative path) construction variable.

429
SCA Framework SCASCons Build System

Apps Local
The Apps Local tree has the same structure as the Apps System and only contains the
components that you have built. This is where you will find the build results for your
component. Some of the files in this directory are copied from the source tree, some from the
object tree and some are generated directly in the tree.

The location of the Apps Local directory is defined by the APPS_LOCAL (absolute path)
construction variable. If APPS_LOCAL variable is not defined, then the default location is
used which is under the object directory.
Third Party tree
The build system provides facilities for including support for third party packages. Third party
packages are non-SCA components that are required to build and run an application. Support
for Mozilla, Qt, and Python packages is supplied by default. Support for additional libraries
can be added. This support requires that the third party package be installed in a directory
structure that is understood by the build system.

The basic directory hierarchy for the third party tree is:

ThirdParty/Package/Version/Platform

This structure allows support for multiple versions of each package on each platform type.
The version identifiers in the above tree are just directory names and can be numeric,
alphabetic or any combination of both. Multiple packages can be installed under the same
third party tree or they may be installed in different trees. Depending on how the version of the
package is located at run time, the ThirdParty, PackageX or VersionX directory levels many
not be required in the directory tree.

430
SCA Framework SCASCons Build System

Tools Directory
The Tools tree contains the SCA Build System and the other tools required for building SCA
Components. These are some of the utilities included.
genskeleton - Generate skeletons for service implementations
idl - SCA IDL Compiler
scons - SCA Build system
This location could be added to the operating system’s path environment variable to make it
easy to run the tools.
Rules for locating Apps System and Third Party Trees
There is a common set of rules that are used to locate the Apps System and third party
directory trees. These rules allow you to specify the full path to the directory or only the
directory name and the build system will determine its full path. The table below shows what
construction variables can be used. The X field in the variable names can be APPS or a third
party package name.

Variable Description
X_SYSTEM Full path to the location of the X directory tree.
X_DIR Directory name of the X tree.
X_BASE Name of the base directory for locating the X_DIR directory
for package X.
SCA_THIRDPARTY_BASE Name of the base directory for locating X_DIR directories
for third party packages only.
SCA_BASE Name of the base directory for locating X_DIR directories
for the APPS and third party packages.

To locate APPS_SYSTEM, either the APPS_SYSTEM or the APPS_DIR variable must be


specified. If the APPS_SYSTEM variable is used, it already contains the full path to the
desired directory and the search is done. However, if the APPS_DIR variable is used, the
following locations are searched to determine the full path.
If APPS_BASE is defined: APPS_BASE/APPS_DIR.
If SCA_BASE is defined: SCA_BASE/APPS_DIR.
../APPS_DIR relative to the location of the SCons script running.
Locating third party directories follows the same general rule except the third party directory
tree structure is used. For the third party package X, either the X_SYSTEM or the X_DIR
variable must be specified. If the X_SYSTEM variable is used, it already contains the full
path to the desired directory and the search is done. In this case it should point to the specific
platform specific directory for the desired version of the package. For example, the Qt
package on Windows could be located using the following value.

QT_SYSTEM = “C:/SCA/ThirdParty/Qt/3.3.2/WINNT”

431
SCA Framework SCASCons Build System

If the X_DIR variable is used, the following locations are searched to determine the full path.
The MACH value in these rules is substituted with the appropriate value for the platform you
are building for.
If X_BASE is defined: X_BASE/X_DIR/MACH.
If SCA_THIRDPARTY_BASE is defined:
SCA_THIRDPARTY_BASE/X/X_DIR/MACH.
If SCA_BASE is defined: SCA_BASE/ThirdParty/X/X_DIR/MACH.
../ThirdParty/X/X_DIR/MACH relative to the location of the scons script running.

Rules for locating Apps Local and object trees


The location of the Apps Local and Object directory trees is controlled by the construction
variables SCA_OBJECT and APPS_LOCAL.

The following table shows the possible combinations for SCA_OBJECT and
APPS_LOCAL and how they affect the location of these trees.

Location of Apps
SCA_OBJECT APPS_LOCAL Location of Object Tree
Local Tree
Source/ObjectSubTree
Not set Not set Source/Apps
e.g. /source/WINNT_SRC_DEBUG
Set Not set SCA_OBJECT/Apps SCA_OBJECT/ObjectSubTree
Not set Set APPS_LOCAL Source/ObjectSubTree
Set Set APPS_LOCAL SCA_OBJECT/ObjectSubTree

The ObjectSubTree could be MACH_SOURCE_DEBUG or MACH_SOURCE_OPT


depending on debug or optimized build. For example on Windows if the Source directory is
TestComp, then ObjectSubTree could be WINNT_TESTCOMP_DEBUG or
WINNT_TESTCOMP_OPT.

The APPS_LOCAL construction variable is not normally set in the users [Link]
options file. Normally its location is set using the SCA_OBJECT construction variable.
Configuration files
There are four main types of configuration files that control the configuration of the build
which are described below. The build system uses a directory hierarchy model so the
appropriate configuration files must be present at the appropriate places in the source tree for
the whole directory structure to be processed.

An important point to remember is that the build system uses these files to create the build
environment. The build system only propagates the HOME environment variable into the
build environment from the list of environment variables defined for the user. None of the
other environment variables set by the user are propagated. The reason for this is to maintain a
standard build environment independent of the user settings. There are also some operating
system environment variables that individual system commands required that are also

432
SCA Framework SCASCons Build System

automatically propagated into the build environment. An example of this is the TMP variable
that is required by the Windows linker.
SConstruct
This is the master configuration file and must exist in the root of the source tree. It is used to
initiate build processing by identifying the root of the source tree and specifying any special
build system configuration options for it.

The SConstruct file provides customizations and extensions to the build system itself.
Examples of these types of customizations might be adding user specific construction
variables, environment routines and third party packages. Because the SConstruct file is run
at an early stage of the build process, the rules for coding this file are different than the two
options files. Setting values for construction variables should not be done in this file. Only
new construction variable names and their default values can be declared. Customized values
for these variables should be set in the normal manner in the SConopts or [Link]
files or on the command line.

After the initial setup, this file only needs to be updated when new build configuration options
are needed, such as adding a third party software dependency. An example SConstruct file
with one third party software configuration is provided below.

# Main SCons configuration file for the SCA build system.


from [Link] import *

#================== Perform local customization here ==================

#
# Set up for LibXML processing
#
def IncludeLibXML2(env, compile=True,extraincs=[],
link=True,extralibs=[]):
# Set compilation related values
if compile:
libXMLInc = [Link]("$LIBXML_SYSTEM", "include")
[Link]( CPPPATH = libXMLInc )
for inc in [Link](extraincs):
[Link]( CPPPath = [Link]( libXMLInc, inc ))
# Set link related values
if link:
if env["MACHINE"] == "LX8664":
[Link]( LINKFLAGS=[Link]("$LIBXML_SYSTEM", "lib",
"[Link].2") )
else:
[Link](LIBPATH=[Link]("$LIBXML_SYSTEM", "lib"))
[Link](LIBS="libxml2")
for lib in [Link](extralibs):
[Link](LIBS=lib)

# Initialize the package


ThirdPartyPackage('libxml', 'libxml2 support', IncludeLibXML2)

#======================================================================

433
SCA Framework SCASCons Build System

import [Link]
[Link]()

There is a sample SConstruct file, in the Runtime/lib/python/SCASCons subdirectory of the


Tools tree, with a list of all the available commands.
SConopts
This file is in the root of the source tree and contains build options, i.e. construction variable
settings, unique to this source tree. The file should only set options that are specific to the
source tree as they will be treated as default values for every user working in the tree.
Examples of this type of information might be SCA Framework version, build information,
and third party versions.

After the initial setup, this file only needs to be updated when new build configuration options
are needed, such as using different version of the SCA Framework. The [Link] file,
which is described next, contains options that are unique to users but not to the source tree.
The same types of items can go into either of the files, but they are separated for the reasons
described.

An example of the SConopts file is provided below.

# Source tree specific build options file


import SCASCons

# Apps System directory location relative to APPS_BASE.


APPS_DIR = "SCAKernel-V4-007"

# Third party option for LibXML.


if [Link] == 'WINNT':
LIBXML_DIR = "2-2.6.27-2"
else:
LIBXML_DIR = "2-2.6.27"

SConscript
One of these configuration files must exist in each directory that is to be processed. If a
directory does not have a SConscript file, then processing will stop at that point and the
directory and all of its subdirectories will be skipped. This small file can also contain special
build instructions for the files in its directory. If there are no special requirements, as in this
example, then the default version of this file still needs to be present.

Import("env_base")
env = env_base.Copy()

#================= Perform local customization here =================

#====================================================================

retval = [Link](env_base)
Return('retval')

434
SCA Framework SCASCons Build System

[Link]
This optional file exists in the user’s home directory and contains user-specific build options
used for any builds that they perform. Options in this file have precedence over options in the
SConopts file, and unlike the SConopts file, this file may change often depending on the
user’s environment.

User specific options should be put in each user’s [Link] file. Examples of this
information might be temporary object locations and output requests. You can also override
any of the settings in the SConopts file. You may wish to do this if you want to build against
a different version of a third party package for example. Be careful about the settings you put
in this file because they will affect every build you as a specific user run no matter which
source tree you are processing.

Before using the SCA build system, you need to make sure your personal build options file is
setup correctly. The file is a Python script that is run at the start of the build process.

An example of the [Link] file is provided below.

import sys
import os

# Set location for object tree


root = [Link]([Link]())
if [Link] == “win32”:
SCA_OBJECT = “C:/Builds/” + root
else:
SCA_OBJECT = “/tmp/rich/Builds/” + root

# Set reduced command output


COMMANDPRINT = ‘short’

Normally you should only define the locations of the SCA_OBJECT and optionally the
APPS_LOCAL directory trees in your [Link] file. The APPS_SYSTEM directory
is defined in the SConopts file, which resides in the root of the source tree. If
APPS_LOCAL directory is not defined, then the default location is used and is under the
object directory.
Setting up the Build System in a New Source Tree
Setting up the SCA Build System in a new source tree is a relatively simple task. In the root of
source tree, you need to copy the following configuration files.
Copy [Link] to SConstruct
Copy [Link] to SConscript
Copy [Link] to SConopts
The example configuration files can be found in the SCASCons directory which is located in
the Runtime/lib/python/SCASCons subdirectory of the Tools tree. These configuration files
should be modified as required for the source tree. In particular, the SConopts file should be
modified to specify the correct version of the SCA Framework that will be used.

435
SCA Framework SCASCons Build System

Next, you need to create a SConscript file in each directory in the source tree that needs to be
processed. If required you may modify these files to do special processing in their directory.
For details on the available customization options for these files, see the document SCA Build
System Guide.
Setting up your Runtime Environment for the Build System
There are a couple of settings in your runtime environment that you will usually want to set up
when using the SCA build system

1. Add the Tools System directory to the user’s path environment variable. This is not
required, but if it isn’t in the path, the scons command will require a fully qualified path
name each time it is executed. The path used in the example configuration files is
C:\SCA\Tools-V5-003.
2. Your home directory must be defined with the HOME environment variable. This is
standard for Linux and UNIX, but Windows users may have to add it manually if they
want to use the [Link] file.
3. Create the TMP environment variable on Windows to define a directory for temporary
files if it has not already been defined. This is required by the Windows Linker for
temporary storage.
The SCons Construction Environment
The construction environment is a special Python object which is usually referenced with the
Python variable named env. This object is used by SCons to store the current values for each
construction variable. It also contains the API that is used in the SConscript files to
manipulate it. The construction environment and its construction variables contain all of the
knowledge required to create the actual commands that will be run during the build.

When SCons starts up, the first thing it does is initialize the base construction environment.
For example, on Linux it initializes the processing for C and C++ files. The builder defines a
construction variable, CCCOM, which contains the actual command used to compile the
files.

CCCOM = $CC $CCFLAGS $CPPFLAGS $CPPDEFFLAGS $CPPINCFLAGS


-c -o $TARGET $SOURCES

Notice that the compilation command definition is mostly composed of other construction
variables. By modifying any of the variables, or the CCCOM variable itself, you have
complete control over the actual commands used by the build system to build the various
types of targets.

After SCons creates the base construction environment, the SConopts and [Link]
option files are executed. They can modify any construction variables as required for this
build. The complete order of precedence, starting with the highest, for setting construction
variables is as follows.

436
SCA Framework SCASCons Build System

SConscript Options in this directory only


Command line Options for this run only
[Link] Options for this user only
SConopts Options for the source tree only
Defaults Default options provided by SCons

As the SCA Build System processes the source tree, the SConscript file in each directory is
executed. The first two lines of each SConscript file should be the following.

Import("env_base")
env = env_base.Copy()

These two lines make a copy of the base construction environment that will be used in this
directory. A copy of the construction environment is made in each directory so any changes
made to it in the current directory will not affect processing in any other directory. You should
not make any changes to the base construction variable, env_base, directly. If you wish to
have change you make in the current directory be propagated down to all of its subdirectories
you should use the [Link] command.
Modifying Construction Variables in the SConscript File
The SConscript configuration files are run as part of the actual build operations, so they must
follow some rules that are different from the options files discussed previously. Instead of
setting construction variables using normal Python global variables, they must be accessed in
the actual SCons construction environment.

if env[‘MACHINE’] == ‘LX86’:
[Link](CCFLAGS=["-wd810"])

When the actual build commands are run, the current working directory is in the root of the
source tree. This means that when build options include paths arguments, they should
normally be coded as absolute paths or paths relative to the root of the source tree and not
paths relative to the directory containing the SConscript file.

[Link](CCFLAGS=["-IFramework/include"])

There is a common exception to the rule. Construction variable names, which end with
PATH, are treated differently. The path names in these variables are relative to the directory
that contains the SConscript file. If you want these values to be relative to the root of the
source tree, you can use the special syntax of #/… to indicate this. You can also code these as
absolute paths if you wish but this is not normally a good practice because it makes relocating
the source tree more difficult. In the following examples, all of the paths are equivalent
assuming the SConscript file is in directory /scasystem/Framework/Kernel.

[Link](CPPPATH="#/Framework/KernelUtil")
[Link](CPPPATH="/scasystem/Framework/KernelUtil")
[Link](CPPPATH="../KernelUtil")

437
SCA Framework SCASCons Build System

If you have platform specific construction variables in the SConscript files, you should use
the construction variable MACHINE to test for the current platform.

if env["MACHINE"] == "LX86":
. . .
elif env["MACHINE"] == "WINNT":
. . .
Special processing for CPPPATH construction variable
The CPPPATH construction variable has two functions.
Adds directories to the list of include paths searched by the C preprocessor just like -I
arguments in the CCFLAGS variable.
Triggers dependency processing between all of these header files located in these
directories.
If the directory contains header files in which you want to include all dependency scanning
and testing then they should be added with the CPPATH construction variable. Notice how
the -I preprocessor argument is not used in this case. It will be added automatically when the
values are added to the CCFLAGS variable by SCons.

[Link](CPPPATH=["$QT_SYSTEM/include"])

If the directory contains packages that change very seldom and you do not wish to do any
dependency scanning or testing then they should be added directly to the CCFLAGS
construction variable. In this case, the -I flag is now required because these arguments are sent
directly to the compiler.

[Link](CCFLAGS=["-I$QT_SYSTEM/include"])

Available construction variables


The following are some of the commonly used construction variables that you might set in the
SConscript files.

CCFLAGS C and C++ compiler options


CPPDEFINES C preprocessor defines
CPPFLAGS C preprocessor options
CPPPATH C preprocessor include paths
CXXFLAGS C++ compiler options
FORTRANFLAGS FORTRAN compiler options
LIBPATH Link library paths
LIBS Link libraries
LINKFLAGS Link program options

438
SCA Framework SCASCons Build System

BUILDTYPE Optimized or debug build selection


COMMANDPRINT Level of build output desired

For a complete list of the available construction variables you can run the following command
from inside any SCons source tree.

scons –h

Commonly Used Environment Routines


The following are some common environment routines that are used in the SConscript files.
For details on all of the available routines, see the document SCA Build System Guide.
Modifying construction variables
To replace the value of a variable with a new value you can use either of the following
commands.
[Link](VARIABLE=value)
env[“VARIABLE”] = value

For example, the following command specifies the additional libraries to link.
[Link](LIBS=["comdlg32",”wsock32",”[Link]"])

To append a new value to an existing variable you use the following command.
[Link](VARIABLE=[value])

To prepend a new value to an existing variable you use the following command.
[Link](VARIABLE=[value])

Building programs and libraries


When the SCA Build system finds a SDL or a CDL file in a directory, it will automatically
trigger the building of a static object library or a dynamically linked shared library. The
building of a program or a non-SCA shared object or shared library must be explicitly
requested in the SConscript file. The object files used to build each of these will include all of
the objects files generated in the current directory and the any objects files from its
subdirectories that were not previously used in the building of a different library or program.

The following routines are available in the SConscript file to trigger the build.
# Build a main program in the current directory
[Link](progname,aliases=None)

# Build a shared library in the current directory


[Link](shlibname,aliases=None)

# Build an object library in the current directory


[Link](objlibname,aliases=None)

439
SCA Framework SCASCons Build System

Adding libraries and objects to a link


Sometime you may need to add extra shared libraries or object files to a link. The following
routines allow you to do this.
[Link](names,appendend=None)
[Link](names)
Installing files
The SCons will automatically install certain file types into the APPS_LOCAL directory
when they are found in the source tree. Examples of these include IDL files and any XML
files. The following routine can be used to explicitly install other files that are not supported.
[Link](files,installdir,aliases=None,newname=None)
Propagating commands to subdirectories
As discussed before, changes made to the values of construction variables are local to the
directory they are made in. Sometimes you may wish for these changes to apply for the
current directory and all of it subdirectories. The [Link] routine allows you to do this.
[Link](routine,*args,**keywords)

The arguments to this routine are the name of any other environment routine and its
arguments. For example, the following will change the C compiler flags in the current
directory and all subdirectories.
# Change only in current directory
[Link](CCFLAGS=["-wd810"])

# Change in current directory and all subdirectores


[Link]([Link],CCFLAGS=["-wd810"])

Skipping files and directories


A number of routines are provided which allow you to skip files or directories that the build
system would normally process.
[Link](names)
[Link](dirs)
[Link]()
Microsoft Visual Studio Projects
SCons automatically builds Visual Studio project files using its complete knowledge of the
build tree. There is one project file generated for each SCA component, main program, static
object library and shared library. There is also a global solution file that is generated in the root
of the source tree that can be used to reference all of the project files contained in the source
tree.

When you do a build from within Visual Studio, the project files will invoke SCons to do the
actual build. This causes the same build procedure to be used whether you are running from
the command line for from within the Visual Studio IDE and you will get the same build
behavior and results.

440
SCA Framework SCASCons Build System

The Visual Studio project files can also be generated by executing the following command
from the root directory of the source tree.

scons msvs

For more details on Visual Studio projects, see the document SCA Build System Guide.
15.2. Running the Build
Build Tasks
When building SCA components, the build system will take care of most of required tasks.
This processing is triggered by the presence of the appropriate files in the directory being
processed. The following are some of the tasks that are automatically performed.

5. The IDL compiler processes the IDL file, generates header files for each interface,
and stores them in the APPS_LOCAL tree.
6. The IDL compiler processes the SDL file and generates the required base class files
for the service and each sub-service defined. These will be stored in the object
directory.
7. The IDL compiler processes the CDL file and generates the required initialization
function for the component. This file will also be stored in object directory.
8. The build system compiles and links all of the code created in the previous steps as
well as the source in the source directory; it then stores the object files in the object
directory. The component’s dynamically linked shared library and any other files that
come out of the linking procedure will be copied into the APPS_LOCAL directory
for future use.
9. The build system adds an entry to the Service catalog for each service that is contained
in the component. The service catalog’s path is
APPS_LOCAL/res/[Link] in the Apps Local directory.
SCons Command
The simplest way to run SCons is from the root of the source tree. The following command
will cause the entire tree to be built.
scons

Or to build only selected components you simply add the name of the component.
scons HelloWorldCPP

Running SCons from a Subdirectory


By default, SCons requires a SConstruct file to be in the current directory when you run the
command. If you are working in a subdirectory of the source tree, you must use one of the
following options to cause SCons to search up the directory tree to find the SConstruct file,
which defines the root of the entire source tree.

Search up directory tree for SConstruct and build all default targets.

441
SCA Framework SCASCons Build System

scons –D

You can also use other targets on this command. A common example would be if you are
working in the source directory for a component, for example HelloWorldCPP, and you
wanted to rebuild the HelloWorldCPP shared library. You can use the following command to
accomplish this.
scons –D HelloWorldCPP

Phases of the Build Process


The build is performed in three phases: configuration file processing, dependency processing,
and executing build commands. These phases are described below.
Configuration file processing
The first phase of the build process is to process all of the configuration files. The system
traverses the source tree and performs the steps below in each directory.

The build executes the SConscript file. The build skips the directory if it does not
contain a SConscript file.
The build processes each file in the directory and creates build actions for it if the file
type is supported. The file is ignored if the type is not supported. As the build actions
are created, they are linked together into a global dependency tree containing all of the
relationships of the files in the source tree and the targets that they generate.

As each directory is processed, a list of object files created is maintained. If the build system
determines that an object library, shared library or main program is to be built, this list of
object files is used. If none of these is built in the directory, then the list of object files is
passed back to the parent directory to be added to its list of object files. This way, whenever
an object library, shared library or main program is built, it will contain all of the object files
from the current directory and any unused objects from its subdirectories.
Dependency processing
SCons automatically scans the source files for any implicit dependencies they have and adds
them to the global dependency tree. Examples of these are the include files a C++ source file
references.
Executing build commands
After all of the dependencies have been determined, SCons checks if any of the dependencies
are out of date. By default, MD5 checksums are used to determine when a dependency has
changed instead of file timestamps. This is so clock differences between file servers do not
affect the build process and allow SCons to rebuild only the minimal files required.

It is important to note that no targets are built during configuration file and dependency
processing phases. The build commands such as [Link] and
[Link] found in SConscript files are only used to create entries in the global
dependency tree. The actual targets are not built until the final phase of the build, using the
information in the dependency tree. This is important because any Python code you add to

442
SCA Framework SCASCons Build System

SConscript file will be executed before any actual targets are built. There is no way to control
the exact order in which these targets are built. The only thing that can be assured is that all
dependencies for a target will be built before the target.
Removing Files Created by the Build
SCons has a clean option that allows you to remove all the targets it has built. This is
requested with the -c argument. If you include a target on the command then only that target
and all of the targets required to build it will be removed.
scons -c
scons -c HelloWorldCPP
scons -D -c HelloWorldCPP

You should take care using the clean command without any targets because it may delete
things you don’t expect. If you want to do a clean build, the easiest and fastest thing to do is to
just delete the entire object tree.
SCons Debugging Options
There are several SCons command line options available to help debug any build problems.

Prints debugging information for level “x”. For a list of the available
debugprint=x
levels use debugprint=’?’
Print tree of dependencies generated by SCons. This option can
--debug=tree
generate a large amount of output for big source trees.
--debug=explain Give an explanation why each target is being built.

It is also sometimes desirable to see the actual values of various construction variables that
will be used for the build. This can be done by using the name of the construction variable as
the target on the SCons command line.
scons CPPATH

This command will not perform a build, but will instead traverse the source tree and show the
default value for the CPPATH construction variable and any directory that has a different
value. The printing of construction variables values is only triggered when all of the targets on
the command line are upper case. If any of them contain lower case characters then they are
assumed normal build targets and a normal build is performed.
Selecting Debug and Optimize builds
The SCA Build System supports both debug and optimized builds. The appropriate compiler
options are provided for each of these. These are controlled with the BUILDTYPE variable,
which accepts a value of debug or opt. This variable can be specified on the command line
but is normally only used in the SConopts or [Link] options file.
BUILDTYPE=debug
BUILDTYPE=opt

For convenience, special command line only options are supported to control the type of build.
scons debug=yes
scons debug=no

443
SCA Framework SCASCons Build System

scons opt=yes
scons opt=no

There is no difference between specifying debug=yes or opt=no, on the command line. They
will both generate a debug compile. Similarly, debug=no and opt=yes will both generate an
optimized compile.

It should also be noted that the debug and optimize compile options only change the compiler
options that are used. No special preprocessor defines are generated to indicate which is being
used. If these are desired, you need to add them yourself. This was done because large
amounts of undesired debug output can be generated if all programmers are triggering off the
same preprocessor values

444
SCA Framework User Document

Chapter 17

Logger Service

445
Logger Service
17. Introduction

The SCA Framework provides a ‘Logger’ service to log messages. This is a singleton service, which
implements the 'SCAILogger' interface.

The log methods in the Logger call the ‘write’ methods of all the registered listeners. The SCA Framework
provides some ready to use logging listeners. These stock listeners are described in the next section.

The developers are able to create and add their own logging listeners by implementing the
‘SCAILogListener’ interface. They can also remove or replace the stock listeners provided by the SCA
Kernel.

The 'SCAILogger' and ‘SCAILogListener’ interfaces are described later in this chapter.

17.2 Logging Filters


The following Logging filters, listed in the order of severity, can be specified in the Kernel configuration
file. Only messages with severity higher than or equal to the filter value will be logged. The default filter is
“Debug”, which is the lowest severity and will cause all messages to be logged.

“Debug”
“Information”
“Warning”
“Error”

17.3 SCA Framework Provided Logging Listeners


The SCA Framework provided logging listeners can be enabled or disabled by setting options in the Kernel
configuration file. See the chapter “Configuring and Using the SCA Kernel” for more details.

The Listener options are specified in the following format.

<var name="ListenerName" value=”param1,param2,...” />

StdoutListener

The StdoutListener logs to the console. This listener is enabled by default, even if no value is specified in
the Kernel configuration file. The default filter of “Debug” is used. The other stock listeners must be
enabled in the SCA Kernel configuration file.

This listener can be disabled either by programmatically removing it from the Logger or setting the value to
“off” in the SCA Kernel Configuration file. The “off” option is only available for this listener.

Format:

<var name="StdoutListener" value=”option” />

Examples:

The following will turn off the StdoutListener.

446
<var name="StdoutListener" value=”off” />

The following will set the StdoutListener with “Information” filter.

<var name="StdoutListener" value=”Information” />

If no filter is specified the default filter of “Debug” is used.

FileLogListener

The FileLogListener logs to a text file. The messages are appended to the file.

This listener is disabled by default. It can be enabled by specifying the options in the SCA Kernel
Configuration file.

Format:

<var name="FileLogListener" value=”logFilePath,filter” />

Examples:

The following setting in the SCA Kernel configuration file will enable the FileLogListener with “Error”
filter. The messages with priority of “Error” or higher will be logged to the file ‘[Link]’.

<var name="FileLogListener" value=”C:\\temp\\[Link],Error” />

The following will enable the FileLogListener with “Information” filter. This example shows specifying
the listener parameters using an environment variable.

setenv SCA_FILELOG_LISTENER=”/temp/[Link],Information”

The environment variable is specified in the SCA Kernel configuration file as shown below.

<env name="%fileListener%" value="SCA_FILELOG_LISTENER"/>


<var name="FileLogListener" value="%fileListener% "/>

SysLogListener

The SysLogListener logs to Windows Event Log or Linux syslog.

This listener is disabled by default. It can be enabled by specifying the options in the SCA Kernel
Configuration file.

Format:

<var name="SysLogListener" value=”filter,logSource” />

Examples:

The following setting in the SCA Kernel configuration file will enable the SysLogListener with “Warning”
filter and prepend “SCAKernel” to every logged message as the log source.

447
<var name="SysLogListener" value=”Warning,SCAKernel” />

The following will enable the SysLogListener with “Debug” filter and no log Source.

<var name="SysLogListener" value=”” />

The following will enable the SysLogListener with “Information” filter and no log Source.

<var name="SysLogListener" value=”Information” />

17.4. Examples of Listener Settings in SCA Kernel Configuration File


The following configuration settings will enable the ‘StdoutListener’ with “Information” filter,
‘SysLogListener’ with “Error” filter and ‘FileLogListener’ with “Information” filter.

<?xml version="1.0"?>
<SCA>
<session os="*">
<env name="%res%" value="SCA_RESOURCE_DIR"/>
<var name="Resource" value="%res%"/>
<var name="StdoutListener" value="Information" />
<var name="SysLogListener" value="Error" />
<env name="%file%" value="SCA_FILELOG_LISTENER"/>
<var name="FileLogListener" value="%file%,Information" />
</session>
</SCA>

The following configuration settings will disable the ‘StdoutListener’; enable the ‘SysLogListener’ with
“Error” filter and “SCAKernel” log source; and enable the ‘FileLogListener’ with the specified file name
and “Debug” filter.

<?xml version="1.0"?>
<SCA>
<session os="win32">
<env name="%res%" value="SCA_RESOURCE_DIR"/>
<var name="Resource" value="%res%"/>
<var name="StdoutListener" value="off" />
<var name="SysLogListener" value="Error,SCAKernel" />
<var name="FileLogListener" value="C://temp//[Link],Debug" />
</session>
</SCA>

17.5. Logger Service API


The Logger service implements the ‘SCAILogger’ and ‘SCAILogListener’ interfaces. The methods of
these interfaces are described below.

SCA::Framework::Logger::SCAILogger Interface

The purpose of this SCA service is to provide an interface to log messages. Developers are
able to add their own logging listeners by implementing the SCAILogListener interface.

448
Member Functions
SCAResult logMessage (in SCAString message, in Severity sev)
Log the message.

SCAResult logMessageSequence (in SCAStringSequence msgSequence, in Severity sev)


Log the sequence of messages.

SCAResult logFormattedMessage (in SCAString message, in SCAAnySequence args, in


SCAString locale, in Severity sev)
Log after formatting the message.

SCAResult logMessageW (in SCAUString message, in Severity sev)


Log the message.

SCAResult logMessageSequenceW (in SCAUStringSequence msgSequence, in Severity


sev)
Log the sequence of messages.

SCAResult logFormattedMessageW (in SCAUString message, in SCAAnySequence args,


in SCAString locale, in Severity sev)
Log after formatting the message.

SCAResult addSCALogListener (in SCAListenerType listenerType, in SCAStringSequence


parameters)
Adds a SCA Framework provided log listener.

SCAResult removeSCALogListener (in SCAListenerType listenerType)


Removes a SCA Framework provided log listener.

SCAResult addLogListener (in SCAILogListener logListener, out ListenerId id)


Adds a new user implemented log listener and returns the id assigned to it.

SCAResult removeLogListener (in SCAILogListener logListener)


Removes the log listener from the list of listeners.

SCAResult removeLogListenerById (in ListenerId id)


Removes the log listener from the list of listeners.

Member Function Documentation


SCAResult addLogListener ( in SCAILogListener logListener,
out ListenerId Id )
Parameters:
logListener Smart pointer to the user implemented log listener.
id Unique id assigned to the new log listener.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult addSCALogListener ( in SCAListenerType listenerType,


in SCAStringSequence parameters )
Parameters:
listenerType Could be 'STDOUT_LISTENER', 'SYSLOG_LISTENER' or 'FILE_LISTENER',

449
identifying the three listeners provided by the SCA Framework.
parameters Contains any additional parameters required by the SCA Framework
provided listener. For STDOUT_LISTENER parameters[0] contains the
filter name. For SYSLOG_LISTENER parameters[0] contains the filter
name. parameters[1] contains the logSource. For FILE_LISTENER
parameters[0] contains the log file path. parameters[1] contains the
filter name.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logFormattedMessage ( in SCAString message,


in SCAAnySequence args,
in SCAString locale,
in Severity sev )
Parameters:
message The message with formatting arguments. Because the argument order can
change in different languages, each argument is prefixed by the index of its
entry in the args sequence that is passed into this method. The index is 1-
based.
The format of this prefix is "%<index>:", so the first argument would be
noted as "%1:", the second "%2:" and so on.
This index reference can be followed by information on how the data should
be formatted. Currently, there are three different formatting styles, which
are distinguished by the first character:
Currency: indicated by '$'. The provided argument should be a floating
point number (the fractional part is ignored!), or an integer.
Example: "The price for this feature is %1:$"
Arg1 = 1999 --> "The price for this feature is $19.99"
Date/Time: indicated by '#'. The provided argument should be an integer
that stores the number of seconds since 01/01/70 (UTC). This number will
be converted to the timezone that is set for the computer's system clock. It
is possible to define a different timezone by changing the environment
variable "TZ". Caveat: changing this variable puts the whole process in a
different timezone, which could have unwanted effects in a multi-threaded
environment (unless secured by mutex sections). Accepted values for TZ
should be found in system's documentation.
How that date is displayed depends on the letter that must follow the '#'
character, the available options are identical to the formats accepted by the
C function strftime() (except that those use '' as prefix). A reference can be
found here: [Link]
Example: "Today is a %1:#A in %1:#B, the time is %1:#X"
Arg1= 1130514894-->"Today is a Friday in May, the time is 5:54:54 PM".
All other: indicated by ‘%’.
This formatting is modeled after "printf" in the programming language C:
%<flags><width><.prec><modifier><conversion>. A description of these:
[Link]
Example: "%1:%d + %2:%g %3:%s"
Arg1 = 1, Arg2 = 2.5, Arg3 = "is equal to..." --> "1 + 2.5 is equal to..."
Furthermore, strings in the parameter list can be text-IDs themselves. The
purpose of this is to make it easier to re-use texts. The conversion flag "S"
is used for that (opposed to conversion flag "s", which would just insert the
string as it appears in the list).
args List of message arguments. The 'args' parameter supports the following
types.
SCAInt8 SCAUInt8 SCAInt16 SCAUInt16 SCAInt32
SCAUInt32 SCAInt64 SCAUInt64 SCAReal32 SCAReal64
SCAChar SCAString* SCAUString* SCABool

450
locale Public locale name. Identifies the locale like it would be done in an XML
"lang" attribute as described in:
[Link]
Only the ISO 639 2-character language codes with optional country
identifier based on ISO 3166 are supported!
Examples: "en", "en_US", "de", "de_DE", "de_CH", "fr_CA", "ja", "ja_JP"
If an empty locale string “” is passed, the default value is used.
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logFormattedMessageW ( in SCAUString message,


in SCAAnySequence args,
in SCAString locale,
in Severity sev )
Parameters:
message The message with formatting arguments. See 'logFormattedMessage' for
description.
args List of message arguments. The 'args' parameter supports the following
types.
SCAInt8 SCAUInt8 SCAInt16 SCAUInt16 SCAInt32
SCAUInt32 SCAInt64 SCAUInt64 SCAReal32 SCAReal64
SCAChar SCAString* SCAUString* SCABool
locale Public locale name. See 'logFormattedMessage' for description.
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessage ( in SCAString message,


in Severity sev )
Parameters:
message The message string to log
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessageSequence ( in SCAStringSequence msgSequence,


in Severity sev )
Parameters:
msgSequence The message string sequence to log
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessageSequenceW ( in SCAUStringSequence msgSequence,


in Severity sev )
Parameters:
msgSequence The message string sequence to log
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,

451
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult logMessageW ( in SCAUString message,


in Severity sev )
Parameters:
message The message string to log
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult removeLogListener ( in SCAILogListener logListener )

Parameters:
logListener Smart pointer to the log listener to remove.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult removeLogListenerById ( in ListenerId id )


Parameters:
id Id of the log listener to remove.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult removeSCALogListener ( in SCAListenerType listenerType )

Parameters:
listenerType Could be 'STDOUT_LISTENER', 'SYSLOG_LISTENER' or 'FILE_LISTENER',
identifying the three listeners provided by the SCA Framework.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

452
SCA::Framework::Logger::SCAILogListener Interface
The purpose of this SCA service is to provide an interface to implement custom logging
listeners.

Member Functions
SCAResult write (in SCAString str, in Severity sev)
Formats and writes the SCAString to the listener target. Used by the
SCAString versions of the logger methods.

SCAResult writeW (in SCAUString str, in Severity sev)


Formats and writes the SCAUString to the listener target. Used by the
SCAUString versions of the logger methods.

SCAResult writeSequence (in SCAStringSequence strSequence, in Severity sev)

Formats and writes the SCAStringSequence to the listener target. Used by


the SCAStringSequence versions of the logger methods.

SCAResult writeSequenceW (in SCAUStringSequence strSequence, in Severity sev)

Formats and writes the SCAUStringSequence to the listener target. Used by


the SCAUStringSequence versions of the logger methods.

Member Function Documentation

SCAResult write ( in SCAString str,


in Severity sev )
Parameters:
str The SCAString to write
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERIT
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult writeW ( in SCAUString str,


in Severity sev )
Parameters:
str The SCAUString to write
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult writeSequence ( in SCAStringSequence strSequence,


in Severity sev )
Parameters:
strSequence The SCAStringSequence to write
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.
SCAResult writeSequenceW ( in SCAUStringSequence strSequence,
in Severity sev )

453
Parameters:
strSequence The SCAUStringSequence to write
sev Message severity (DEBUG_SEVERITY, INFORMATION_SEVERITY,
WARNING_SEVERITY, ERROR_SEVERITY)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

Example of Adding a Custom Log Listener


This example uses a SCA service to implement the SCAILogListener interface. But any other method of
implementing the interfaces, such as sub service objects or templates could be used.

[Link] file
#ifndef CUSTOMLISTENERCOMP_CDL
#define CUSTOMLISTENERCOMP_CDL

#include "[Link]"

component [Link] {
service CustomListener;
};
#endif

[Link] file
#ifndef CUSTOMLISTENER_SDL
#define CUSTOMLISTENER_SDL

#include "SCA/Framework/Logger/[Link]"

module Listeners {

service [Link] {
interface SCA::Framework::Logger::SCAILogListener;
};

};
#endif

CustomListener.h file
#ifndef LISTENERS_CUSTOMLISTENER_H_INCLUDED
#define LISTENERS _CUSTOMLISTENER_H_INCLUDED

#include "CustomListenerBase.h"

namespace Listeners {

class CustomListener : public CustomListenerBase


{
public:

// Constructor and Destructor


CustomListener(SCAICustomListenerFactoryAccess* factoryAccess);
virtual ~CustomListener();

// Methods for interface [Link]


virtual SCA::SCAResult write(

454
const SCA::SCAString str,
const SCA::Framework::Logger::Severity sev );
virtual SCA::SCAResult writeW(
const SCA::SCAUString str,
const SCA::Framework::Logger::Severity sev );
virtual SCA::SCAResult writeSequence(
const SCA::SCAStringSequence strSequence,
const SCA::Framework::Logger::Severity sev );
virtual SCA::SCAResult writeSequenceW(
const SCA::SCAUStringSequence strSequence,
const SCA::Framework::Logger::Severity sev );
};

#endif

[Link] file
#include "CustomListener.h"

using namespace std;


using namespace SCA;
using namespace SCA::Framework::Logger;

namespace Listeners {

// Constructor
CustomListener::CustomListener(SCAICustomListenerFactoryAccess* factoryAccess)
: CustomListenerBase(factoryAccess)
{

// Destructor
CustomListener::~CustomListener()
{

SCA::SCAResult CustomListener::write(const SCA::SCAString str,


const SCA::Framework::Logger::Severity sev)
{
if (sev == DEBUG_SEVERITY)
cout << "Custom DEBUG! " << str << endl;
else if (sev == INFORMATION_SEVERITY)
cout << "Custom INFORMATION! " << str << endl;
else if (sev == WARNING_SEVERITY)
cout << "Custom WARNING! " << str << endl;
else if (sev == ERROR_SEVERITY)
cout << "Custom ERROR! " << str << endl;

return SCA::SCASuccess;
}

SCA::SCAResult CustomListener::writeW(const SCA::SCAUString str,


const SCA::Framework::Logger::Severity sev)
{
if (sev == DEBUG_SEVERITY)
wcout << "Custom DEBUG! " << str << endl;
else if (sev == INFORMATION_SEVERITY)
wcout << "Custom INFORMATION! " << str << endl;
else if (sev == WARNING_SEVERITY)

455
wcout << "Custom WARNING! " << str << endl;
else if (sev == ERROR_SEVERITY)
wcout << "Custom ERROR! " << str << endl;

return SCASuccess;
}

SCA::SCAResult CustomListener::writeSequence(const SCA::SCAStringSequence&


strSequence, const SCA::Framework::Logger::Severity sev)
{
for (size_t i=0; i<[Link](); i++) {
if (sev == DEBUG_SEVERITY)
cout << "Custom DEBUG! " << strSequence[i] << endl;
else if (sev == INFORMATION_SEVERITY)
cout << "Custom INFORMATION! " << strSequence[i] << endl;
else if (sev == WARNING_SEVERITY)
cout << "Custom WARNING! " << strSequence[i] << endl;
else if (sev == ERROR_SEVERITY)
cout << "Custom ERROR! " << strSequence[i] << endl;
}

return SCASuccess;
}

SCA::SCAResult CustomListener::writeSequenceW(const SCA::SCAUStringSequence&


strSequence, const SCA::Framework::Logger::Severity sev)
{
for (size_t i=0; i<[Link](); i++) {
if (sev == DEBUG_SEVERITY)
wcout << "Custom DEBUG! " << strSequence[i] << endl;
else if (sev == INFORMATION_SEVERITY)
wcout << "Custom INFORMATION! " << strSequence[i] << endl;
else if (sev == WARNING_SEVERITY)
wcout << "Custom WARNING! " << strSequence[i] << endl;
else if (sev == ERROR_SEVERITY)
wcout << "Custom ERROR! " << strSequence[i] << endl;
}

return SCA::SCASuccess;
}

Adding the Listener to the Logger

SCAResult AddCustomListener()
{
// Get the Logger service
SCAResult rstat;
SCAILogger spLogger = m_serviceAccess->getService("[Link]",
rstat);
if (rstat) return rstat;

// Get the Custom Listener


SCAILogListener spCustomListener;
spCustomListener = m_serviceAccess->getService("[Link]",
rstat);
if (rstat) return rstat;

// Add the Custom Listener

456
ListenerId listenerID;
rstat = spLogger->addLogListener(spCustomListener, listenerID);

return rstat;
}

17.6. Example of Logging Using the Logger Service


In C++ Client
. . .
SCAILogger spLogger = getSCAService("[Link]");
if (spLogger != NULLSP) {
SCAResult rstat= spLogger->logMessage(SCAString("Message"),ERROR_SEVERITY);
}
. . .

In C++ Service
. . .
SCAresult rstat;
SCAILogger spLogger= m_serviceAccess->getService("[Link]",rstat);
if (!rstat) {
rstat= spLogger->logMessage(SCAString("Message"),ERROR_SEVERITY);
}
. . .

In C# Client
. . .
SCAIService spService = [Link]("[Link]");
SCAILogger spLogger = (SCAILogger) spService;
if (spLogger != null) {
SCAResult rstat= [Link]("Message",Severity.ERROR_SEVERITY);
}
. . .

17.7. C++ Logging Macros


For convenience the following C++ logging macros are provided in the header file ‘LoggingMacros.h’.
These macros use the Logger service to log the messages.
The macros are almost as efficient as using the Logger service directly. Since the SCA Kernel stores a
SCAILogger pointer, the only inefficiency comes from additional method calls to get the pointer.

// Logs a SCAString MSG using the given SEVERITY


#define SCA_LOG_MESSAGE(MSG,SEVERITY) …

// Logs a SCAUString MSG using the given SEVERITY


#define SCA_LOG_MESSAGEW(MSG,SEVERITY) …

// Logs a SCAString MSG using the DEBUG_SEVERITY


#define SCA_LOG_DEBUG_MESSAGE(MSG) …

// Logs a SCAUString MSG using the DEBUG_SEVERITY


#define SCA_LOG_DEBUG_MESSAGEW(MSG) …

457
If the following preprocessor symbol is defined, the messages are output directly to stdout instead of going
through the Logger service.

#define SCA_LOG_MESSAGE_DISABLED

Examples:
. . .
SCA_LOG_DEBUG_MESSAGE(SCAString("Could not load MXPDOMParser"));
. . .
SCA_LOG_DEBUG_MESSAGEW(SCAString(L”File Name: ") + fileName);
. . .
SCA_LOG_MESSAGE(SCAString("Generating Minidump"),INFORMATION_SEVERITY);

458
SCA Framework User Document

Chapter 18

Event Manager Service

459
18. Event Manager Service
18.1. Introduction

The SCA Kernel provides an Event Manager by which applications are able to announce and be notified
that events have occurred. This functionality follows the publish/subscribe model where events are
announced by applications (published) and interested parties (subscribers) are notified of the event.

The Event Manager system uses the following terms and high level definitions.

Domain A domain is a namespace for events. Events can be published and


handled in the context of a domain.

Channel A channel is similar to a Domain except that it is unnamed (private).


Events can be published and handled in context of a channel.

Event: An event is a message announced by an application. Each event has


a unique type identifier (Event ID) within its domain/channel.
Events also contain a SCAAny value for pertinent application data.
Applications determine and manage the types of events appropriate
for publishing and subscribing within their application domains.
Events may be published either synchronously or asynchronously:

Synchronous: The event is immediately sent to all subscribing


listeners.

Asynchronous: The event is placed in a queue to await processing at


a later time. Applications control when queued events are sent to
listeners.

Publisher A publisher is the application that announces (publishes) an event.

Subscriber (or Listener) A subscriber is an object that implements an interface


(SCAIEventListener) and is invoked when its event is published.

Event Manager (EM) The Event Manager is the administrator of the event system. It
manages Domains, registers listeners, processes published events,
invokes subscribers of the events, etc.

The publish/subscribe paradigm of event handling follows roughly the following sequence of events in the
current version of the SCA Kernel:

o Applications create domains/channels.


o Applications register event listeners within the domains/channels.
o As applications perform their tasks they publish events at strategic times.
o When an event is published the EM invokes event listeners registered for the event.

An Important Note on Listeners


When the EM delivers an event to a listener the listener performs operations appropriate for the event.
In all types of event delivery it is expected that listeners will not carry out operations that take a
significant amount of time. Should time consuming operations be necessary applications should

460
perform the processing in a separate application thread or via some other mechanism to avoid tying up
the EM.

18.2. Event Manager Features


Multiple Thread Support
The Event Manager supports multiple threads in two ways: the EM is thread-safe and it gives applications
the option of using a dedicated thread for the delivery of asynchronous events.

Logging
The EM supports logging to allow applications to view the activities of the EM for informational or
debugging purposes. Detailed, Medium, and No-output modes are supported. This feature is built upon the
SCA Logging service.

Event Filters
Listeners in a domain may specify a filter by which it can specify the set of event id’s that will be delivered
to the listener.

Listener Priorities
When an event is published or posted there may be multiple listeners that subscribe to the event. This
priority is used to determine the order of delivery of an event to its matching listeners.

Asynchronous Event Priorities


Asynchronous events may be delivered in bulk when an application requests that the queue be processed.
Asynchronous events are assigned priorities which are used to determine the order of delivery of events in
the queue.

The next few sections provide some details on the behavior and properties of domains, channels, events,
and listeners.

Domains
Domains allow applications to create a public mechanism for publishing and listening for events. Any
application may create listeners in a domain and events matching the listener’s event filter will be delivered
to the listener. Domain names must be unique and each domain is assigned a unique identifier when it is
created.

Some EM functions support Domain name wildcards. This allows multiple domains to be selected using a
“*” wildcard. For example: “Graphics.*” or “Solver*.Thermal” may be specified.

Channels
Channels allow applications to create a private mechanism for publishing and listening for events.
Channels do not have names so applications cannot know the identifier of a channel until run time. Only
the application that creates a channel knows its id. Applications that wish to use the channel must
somehow get the id from the creating routine. Any application that knows the identifier of a channel may
create listeners for the channel and it is the responsibility of applications to communicate channel ID’s as
appropriate.

461
Events
Events may be published in domains and channels. When publishing an event the application specifies how
the event should be delivered. There are two options:

Synchronous The event will be delivered immediately (blocked call) to all appropriate
listeners. There are two options for delivery of events:

Consumable The EM will find all matching listeners for the event, place them in priority
order (see Listeners), and deliver the event to the listeners in priority order.
Delivery of the event will stop the first time a listener returns that it handled
the event (i.e. it consumed the event).

Non-Consumable Same as Consumable except that the event will be delivered to all matching
listeners.

Asynchronous The call to publish the event is not blocked and will return immediately to
the application. Asynchronous event publishing does not support
consumable types; all asynchronous events are non-consumable. The actual
delivery of the event will happen in one of two ways:

Default The event will be placed in a queue to await processing. The EM will not
act upon events in the queue until explicitly directed to do so by an
application. When the EM processes the queue, all events in the queue will
be processed in event priority order.

Dedicated Thread The event is delivered to all matching listeners immediately but in a
different (dedicated) thread than the application thread. The events are
delivered serially but in the dedicated thread.

Applications assign a priority to each asynchronous event. This is used to determine the delivery order of
the asynchronous events. It should be noted that the order of delivery for asynchronous events is not
guaranteed to be consistent. Applications specify the priority of asynchronous events and they will be
delivered in priority order but the order of events with the same priority may be inconsistent.

Listeners
Listeners are created by application and registered with domains or channels. Domain listeners may
include an event filter allowing applications to specify which event ID’s should be delivered to the listener.
Channel listeners do not have event filters and events published in the channel will be delivered to all the
channel’s listeners. Each listener is assigned a priority by the application that will be used to determine the
delivery order of the event.

18.3. Registering Listeners


To the EM a listener is a pointer to an implementation of the SCAIEventListener interface. Applications
implement the interface and pass the interface pointer to the EM so that is can be registered with a channel
or domain(s).

When an event is published/posted the EM will deliver the event to all matching listeners registered with
the domain/channel. There are several methods that can be used to register listeners with a domain or
channel.

Registering a Listener with a Channel

462
The function addChannelListener registers a listener with a channel.

ChannelId channelID; // supplied by the channel’s creator

// the priority of the listener


ListenerPriority priority = ListenerPriorityPreferFirst;

SCAResult res = spEM->addChannelListener( channelID, spListener,


priority );
if ( ![Link]() )
// error handling

Registering a Listener with a Domain

The function addDomainFilteredListener registers a listener with a domain.

DomainId domainID; // either provided by the domain’s


// creating application or queried using
// the domain name
// the priority of the listener
ListenerPriority priority = ListenerPriorityAny;
EventFilter filter = {1,2,10,-20}; // the event filter for the
// listener. This listener
// will receive events numbered
// 1, 2, and 10-20 inclusive

SCAResult res = spEM->addDomainFilteredListener( domainId,


spListener, priority, filter );
if ( ![Link]() )
// error handling

Registering a Listener with Multiple Domains

The function addDomainFilteredListeners registers a listener with multiple domains using a list of
domain ids.

ListenerPriority priority; // The priority of the listener


EventFilter eFilter; // the filter used to determine
// which events will be delivered
// to the listener. Because this
// filter is empty all events will
// be delivered.
ListenerFilters lFilters; // A list of ListenerFilter
// structures specifying the
// domains for the listener.

ListenerFilter lFilter1;
[Link] = “Domain1ForThisListener”;
[Link].push_back( 1 );
[Link].push_back( 2 );
[Link].push_back( 7 );
lFilters.push_back( lFilter1 );

ListenerFilter lFilter2;
[Link] = “Domain2ForThisListener”;

463
[Link].push_back( 15 );
[Link].push_back( 52 );
[Link].push_back( 74 );
lFilters.push_back( lFilter2 );

SCAResult res = spEM->addDomainFilteredListeners(spListener,


priority, eFilter, lFilters );
if ( ![Link]() )
// error handling

Registering a Listener with Multiple Domains Using a Wildcard

The function addDomainFilteredListenerWildCard registers a listener with multiple domains using a


wild-carded domain name filter.

// The priority of the listener


ListenerPriority priority = ListenerPriorityPreferLast;
EventFilter eFilter = { 1, -10 }; // the filter used to
// determine which events will be
// delivered to the listener.
// This filter uses a range to
// specify that events 1 through 10
// (inclusive) will be delivered to
// the listener.
DomainFilter dFilter(“MyDomains.*”); // the domain name wildcard
// that will be used to identify
// domains for this listener.

SCAResult res;
res = spEM->addDomainFilteredListenerWildCard( spListener,
priority,
filter,
dFilter );
if ( ![Link]() )
// error handling

18.4. Publishing/Posting Events


The EM receives events from applications and delivers them to registered listeners. So that applications
will be able to predict the behavior of the EM, this section describes how the EM will deliver events in
three publish/post situations:

The following scenarios begin when an event is published/posted and domains, channels, listeners, etc. are
already in place. The descriptions below omit data validation and error processing.

Publishing a Synchronous Event


When a synchronous event is published in a domain or channel the EM will:

1) Search the set of listeners registered for the event’s domain/channel to find all those that
match the event’s id. Listeners for domains have event filters which are used to determine if
the listener is to receive the event. By definition channel listeners receive all events published
in the channel so no filtering is needed.

2) The set of matching listeners is sorted according to their priority.

464
3) The event is delivered to the listeners in priority order. If the event is consumable then
delivery will stop the first time a listener indicates that it handled the event. If the event is
non-consumable then the event will be delivered to all listeners.

The call to publish the event is a blocked call and the function will not return until the above
processing is complete.

The following code example demonstrates creating a domain and publishing an event in the domain.

// create the domain


DomainName domainName = “ApplicationDomainName”;
DomainId domainId;
SCAResult res = spEM->createDomain( domainName, domainId );
if ( ![Link]() )
// error handling

// publish a synchronous event


Consumable bConsumable = false;
SCAEvent EventToPublish;
[Link] = domainId; // domain id
[Link] = 1; // event id
[Link] <<= 0; // application data
res = spEM->publishEvent( EventToPublish, bConsumable );
if ( ![Link]() )
// error handling

Posting an Asynchronous Event (default mode)


When an asynchronous event is posted in default mode the EM will place the event in a queue where it
will wait to be delivered. Events accumulate in the queue until an application makes a specific call to
deliver these events. When this request is made the EM will:

1) Sort the queued events into event priority order. When an event is posted it is assigned a
priority by the application. This is used now to determine the order of delivery of events.
Domain events are delivered before channel events. Higher priority events will be delivered
before lower priority events but events within the same priority will be delivered in an
arbitrary order.

2) For each event, in priority order, the EM will (first for all channel events and then for all
domain events):

a) Search the set of listeners registered for the event’s domain/channel to find all those that
match the event’s id. Listeners for domains have event filters which are used to
determine if the listener is to receive the event. By definition channel listeners receive all
events published in the channel so no filtering is needed.

b) The set of matching listeners is sorted according to their priority.

c) The event is delivered to the listeners in priority order. Consumable/non-consumable is


not supported for asynchronous events so the event will be delivered to all matching
listeners. Once completely delivered the event is removed from the queue.

The call to deliver events in the queue is a blocked call and the function will not return until the
above processing has completed.

465
The following is a code example of posting and delivering asynchronous events in the application
thread (default mode).

// post an asynchronous event


SCAEvent EventToPost;
[Link] = channelId; // channel id
[Link] = 1; // event id
[Link] <<= 0; // application data
res = spEM->postAsyncEvent(EventToPost, EventPriorityNormal,
NULLSP);
if ( ![Link]() )
// error handling

// NOTE: the event is now in the queue waiting to be delivered

// post another asynchronous event


[Link] = domainId; // domain id
[Link] = 2; // event id
[Link] <<= 1; // application data
res = spEM->postAsyncEvent( EventToPost,
EventPriorityNormal,
NULLSP);
if ( ![Link]() )
// error handling

// NOTE: now there are two events waiting in the queue

// deliver the asynchronous events


SCAResult res = spEM->deliverAsyncEvents();
if ( ![Link]() )
// error handling

// NOTE: both events in the queue were delivered in the


// call to deliverAsyncEvents and the queue is now empty. This
// call was blocked and did not return until both events were
// delivered (including time spent in the application listeners).

There can be any combination of domain and channel events in the queue.

Posting an Asynchronous Event in the Dedicated Asynchronous Event Thread


When applications want to have events delivered in a separate thread they call
startAsyncEventDispatcher which instructs the EM to start the dedicated delivery thread. In this
function the EM will:

1) Create a new thread and a queue for events to be delivered in the new thread. In the new
thread, the EM waits until it is notified that an event has been added to the new queue.

2) (In the application thread) If there are unpublished events in the original asynchronous event
queue they will be sorted into priority order and placed into the new dedicated thread queue.
This will trigger the event’s delivery in the dedicated event thread.

After the dedicated event delivery thread is started the EM needs only to place posted asynchronous
events in the queue. This will automatically trigger delivery of the event in the dedicated thread as
described above.

466
The following is a code example of posting asynchronous events in a dedicated thread.

// start the dedicated asynchronous delivery thread. From this


// time forward all asynchronous events will be delivered in the
// dedicated event thread.
res = spEM->startAsyncEventDispatcher();
if ( ![Link]() )
// error handling

// post an asynchronous event


SCAEvent EventToPost;
[Link] = domainId; // domain id
[Link] = 1; // event id
[Link] <<= 0; // application data
res = spEM->postAsyncEvent( EventToPost,
EventPriorityNormal,
NULLSP);
if ( ![Link]() )
// error handling

// NOTE: because the EM is running a dedicated thread the event was


// delivered in that thread. The call was not blocked by the
// delivery of the event.

// post another asynchronous event


[Link] = channelId; // channel id
[Link] = 2; // event id
[Link] <<= 1; // application data
res = spEM->postAsyncEvent( EventToPost,
EventPriorityNormal,
NULLSP);
if ( ![Link]() )
// error handling

// NOTE: this event was also delivered in the delivery thread in the
// call to postAsyncEvent

// NOTE: no call to deliverAsyncEvents is required because the


// events have already been delivered. deliverAsyncEvents will
// return an error if it is called after the dedicated delivery
// thread has been started.

In all cases of event delivery the total amount of time required depends on how long the listeners take to do
their processing. The intent is that listeners perform minimal processing and, should significant work be
required, that the work be passed to a different thread by the listener.

18.5. Event Manager Domain [Link]


[Link] is a domain created automatically by the Event Manager. The Event Manager will
publish administrative events in this domain so that applications can monitor the status of the EM. Only
the EM is allowed to publish events in this domain. All events published in the domain will be
synchronous.

The event types published in [Link] domain are:

467
EventNotFound, //! No event was found (from peekAsyncEvent)
[Link] = 0
[Link] = -1
[Link] = unused

AsynchronousEventDelivered, //! An asynchronous event was delivered


[Link] = pid
[Link] = AsynchronousEventDelivered
[Link] = eid of delivered event

UnhandledSynchronousEvent, //! Synchronous event was not handled


[Link] = pid of unhandled event
[Link] = UnhandledSynchronousEvent
[Link] = data from unhandled event

UnhandledAsynchronousEvent, //! An asynchronous event was not handled


[Link] = pid of unhandled event
[Link] = UnhandledAsynchronousEvent
[Link] = data from unhandled event

DomainCreated, //! A domain was created


[Link] = [Link]
[Link] = DomainCreated
[Link] = domain name

DomainDeleted, //! A domain was deleted


[Link] = [Link]
[Link] = DomainDeleted
[Link] = domain id

ChannelDeleted //! A channel was deleted


[Link] = [Link]
[Link] = ChannelDeleted
[Link] = channel id

Applications may register listeners for [Link] but they may not publish events in this
domain. This domain will be excluded from queries using domain name filters.

18.6. Miscellaneous Event Manager Data Structures

The following typedefs and declarations are used by the EM interfaces.

typedef SCAInt32 EventId;


typedef SCAInt32 DomainId;

468
typedef SCAInt32 ChannelId;
typedef SCAInt32 PathId;
typedef SCAString DomainName;
typedef SCABool Consumable;
typedef SCAString DomainFilter;

typedef sequence<EventId> EventFilter;


typedef sequence<DomainId> DomainIdList;

enum EventPriority
{
EventPriorityHigh,
EventPriorityNormal,
EventPriorityLow
};

enum ListenerPriority
{
ListenerPriorityFirst,
ListenerPriorityPreferFirst,
ListenerPriorityAny,
ListenerPriorityPreferLast,
ListenerPriorityLast
};

typedef SCASequence<ListenerFilter> ListenerFilters;

const SCAUInt32 EVENT_HANDLED = 1;


const SCAUInt32 EVENT_NOT_HANDLED = 0;

const SCAUInt32 NoLogging = 0;


const SCAUInt32 Medium = 1;
const SCAUInt32 Detailed = 2;

const SCAString EventServiceDomainName = "[Link]";

18.7. SCA::Framework::ListenerFilter Struct Reference


import "[Link]";

List of all members.

Public Attributes
DomainName name
EventFilter filter
name of the domain

469
Detailed Description
ListenereFilter: used to automatically associate listeners to domains whose name
matches a wildcard domain name filter

The documentation for this struct was generated from the following file:

IDL/[Link]

18.8. SCA::Framework::SCAEvent Struct Reference

import "[Link]";

List of all members.

Public Attributes
PathId pID
EventId eID
channel/domain of the event

SCAAny data
ID of the event.

Detailed Description
SCAEvent: holds data for a published event

The documentation for this struct was generated from the following file:

IDL/[Link]

18.9. SCA::Framework::SCAIEventListener Interface Reference


import "[Link]";

List of all members.

Public Member Functions


SCAResult handleEvent (in SCAEvent evnt)

Detailed Description
interface SCAIEventListener

470
Member Function Documentation

SCAResult handleEvent ( in SCAEvent evnt )

This function is supplied by the application and performs actions


appropriate for the event. When and event is published/posted this
function will be called to deliver the event to the appropriate
listeners.

This function should return EVENT_HANDLED if the event was consumed


(handled) or EVENT_NOT_HANDLED if the event was not handled. Other
listeners may or may not be given a chance to handle the event, based
on the event’s properties (i.e., is the event consumable or not).

Parameters:
in SCAEvent evnt The event to handle

The documentation for this interface was generated from the following file:

IDL/[Link]

18.10. SCA::Framework::SCAIEventManager Interface Reference


import "[Link]";

List of all members.

Public Member Functions


SCAResult createDomain (in DomainName dName, out DomainId dID)
SCAResult deleteDomain (in DomainId dID)
SCAResult getDomainID (in DomainName dName, out DomainId dID)
SCAResult getDomainName (in DomainId dID, out DomainName dName)
SCAResult getDomainIDsWildcard (in DomainFilter dFilter, out
DomainIdList dIdList)
SCAResult createChannel (out ChannelId cID)
SCAResult deleteChannel (in ChannelId cID)
SCAResult addDomainFilteredListener (in DomainId dID, in
SCAIEventListener spListener, in ListenerPriority priority, in
EventFilter filter)

471
SCAResult addDomainFilteredListeners (in SCAIEventListener
spListener, in ListenerPriority priority, in ListenerFilters lFilters)
SCAResult addDomainFilteredListenerWildCard (in SCAIEventListener
spListener, in ListenerPriority priority, in EventFilter eFilter, in
DomainFilter dFilter)
SCAResult removeDomainFilteredListenerWildCard (in
SCAIEventListener spListener)
SCAResult addChannelListener (in ChannelId cID, in SCAIEventListener
spListener, in ListenerPriority prioritity)
SCAResult changeListenerPriority (in PathId pID, in SCAIEventListener
spListener, in ListenerPriority priority)
SCAResult removeListener (in PathId pID, in SCAIEventListener
spListener)
SCAResult publishEvent (in SCAEvent evnt, in Consumable
bComsumable)
SCAResult postAsyncEvent (in SCAEvent evnt, in EventPriority priority, in
SCAIEventListener spListener)
SCAResult deliverAsyncEvents ()
SCAResult startAsyncEventDispatcher ()
SCAResult peekAsyncEvent (in PathId pID, in EventId eId, out SCAEvent
evnt)
SCAResult removeAsyncEvent (in PathId pID, in EventId eID)
SCAVoid setLoggingLevel (in SCAUInt32 loggingLevel)
SCAUInt32 getLoggingLevel ()

Detailed Description
interface SCAIEventManager

Member Function Documentation

SCAResult addChannelListener ( in ChannelId cID,


spListener
in SCAIEventListener
,
in ListenerPriority prioritity
)

Register a listener with a channel.

472
Parameters:
in ChannelId cID id of the channel for the listener
in SCAIEventListener spListener listener to add to the channel
in ListenerPriority prioritity priority of the channel

SCAResult
( in DomainId dID,
addDomainFilteredListener
in spListener
SCAIEventListener ,
in ListenerPriority priority,
in EventFilter filter
)

This function adds a listener with an event filter to a domain. Domain


Listeners may specify an event filter. This defines the subset of
events that will be delivered to the listener. EventFilters are a
sequence of EventIds that will be delivered to the listener. Ranges may
be specified using a negative number to denote the top end of the
range. For example: [1, -4, 7, -10, 16] includes IDs 1 through 4, 7
through 10 and 16

Parameters:
in DomainId dID, id of the domain for the listener
in SCAIEventListener spListener listener to add to the domain
in ListenerPriority priority priority of the listener
in EventFilter filter event filter for the listener

SCAResult in spListener
(
addDomainFilteredListeners SCAIEventListener ,
in ListenerPriority priority,
in ListenerFilters lFilters
)

Add a listener with the same listener priority to multiple domains.


lFilters is a list of listener filters, each of which specify a domain
name and event filter. The listener will be added to each of these
domains with the specified event filters and priority. The domain name
in the listener filter is not wild-carded.

Parameters:
in SCAIEventListener spListener listener to add to the domain

473
in ListenerPriority priority priority of the listener
in ListenerFilters lFilters a list of listener filters, each of which specify a
domain name and event filter.

in
SCAResult spListene
( SCAIEventListener
addDomainFilteredListenerWildCard r,

in ListenerPriority priority,
in EventFilter eFilter,
in DomainFilter dFilter
)

Use a wildcard to add a listener to domains. This function will


associate a wildcarded domain name (DomainFilter) with a listener. This
function does two things:

The listener will be registered to all existing domains whose names match
the filter

The listener and domain filter will be remembered and the listener will be
automatically registered with all subsequently created domains whose
names match the filter.

Parameters:
in SCAIEventListener spListener listener to add to the domains
in ListenerPriority priority priority of the listener
in EventFilter eFilter event filter for the listener
in DomainFilter dFilter specifies which domains will receive the listener

SCAResult changeListenerPriority ( in PathId pID,


spListener
in SCAIEventListener
,
in ListenerPriority priority
)

Change the priority of a listener. Returns ListenerPriorityAlreadyUsed


if a listener with the desired priority has already been registered for
the same domain/channel. In such a case, the priority will not be
changed.

474
If pathID is zero, change the priority for the listener on all
domains/channels. In this case, should an error be encountered updating
the listener on a domain/channel it will be ignored and processing will
continue.

Parameters:
in PathId pID id of the domain/channel
in SCAIEventListener spListener listener who's priority is changing
in ListenerPriority priority new listener priority

SCAResult createChannel ( out ChannelId cID )

This function creates a channel

Parameters:
out ChannelId cID id of the created channel

dName
SCAResult createDomain ( in DomainName
,
out DomainId dID
)

This function creates a domain. It will look to the list of listeners


registered with domain name wilds cards and register all those with
matching filters with the new domain.

Parameters:
in DomainName dName name of the domain
out DomainId dID id of the created domain

SCAResult deleteChannel ( in ChannelId cID )

This function deletes a channel. Data structures associating listeners


with the channel will be deleted and the EM will no longer hold a
reference to the listener from the deleted channel.

Parameters:
in ChannelId cID id of the channel to delete

475
SCAResult deleteDomain ( in DomainId dID )

This function deletes a domain. Data structures associating listeners


with the domain will be deleted and the EM will no longer hold a
reference to the listener from the deleted domain.

Parameters:
in DomainId dID id of the domain to delete

SCAResult deliverAsyncEvents ( )

Deliver all events in the asynchronous event queue. This is a blocked


call in the same thread as the callers and will not return until all
asynchronous events in the queue have been delivered. This is function
only valid when running in default thread mode.

dName
SCAResult getDomainID ( in DomainName
,
out DomainId dID
)

Return the ID of a domain given its name

Parameters:
in DomainName dName name of the domain
out DomainId dID id matching the domain name

dFilter
SCAResult getDomainIDsWildcard ( in DomainFilter
,
out DomainIdList dIdList
)

Return the ID's of all domains matching a domainFilter

Parameters:

476
in DomainFilter dFilter domain name filter used to find domains
out DomainIdList dIdList list of id's of domains whose names match the
filter

SCAResult getDomainName ( in DomainId dID,


out DomainName dName
)

Return the name of a domain given its ID

Parameters:
in DomainId dID id the domain name
out DomainName dName name of the matching domain

SCAUInt32 getLoggingLevel ( )

getLoggingLevel returns the current level of logging information for


the Event Manager

pID
SCAResult peekAsyncEvent ( in PathId
,
in EventId eId,
out SCAEvent evnt
)

Finds an event from the asynchronous queue. Returns EventNotFound if


the event is not found in the queue. This is only valid when running in
default thread mode.

Parameters:
in PathId pID the channel/domain id of the event
in EventId eId the id of the event
out SCAEvent evnt the matching event (if any)

SCAResult postAsyncEvent ( in SCAEvent evnt,

477
in EventPriority priority,
in SCAIEventListener spListener
)

Post an asynchronous event. This will either place the event in a queue
to await later delivery (default thread mode) or will add the event to
the queue to be delivered in the separate delivery thread (dedicated
thread mode). Applications may provide a callback (spListener) that
will be invoked when the event is delvered.

Parameters:
in SCAEvent evnt the event to post
in EventPriority priority the event's priority
in SCAIEventListener spListener the listener to call when the event is
delivered (may be null)

SCAResult publishEvent ( in SCAEvent evnt,


in Consumable bComsumable
)

Synchronously publish (deliver) an event in either a channel or domain.


The event will be delivered to matching listeners in ListenerPriority
order per the comsumable state of the event:

consumable (true) The event will be delivered to listeners in priority


order until a listener returns EVENT_HANDLED. Deliver of the event will
stop once a listener has handled the event.

non-consumable (false) The event will be delivered to all listeners in


ListenerPriority order

If no listeners match the event or no listeners return EVENT_HANDLED


the EM will publish an unhandled event in [Link]

This is a blocked call and all event deliveries will be completed when
this function returns.

Parameters:
in SCAEvent evnt event to publish
in Consumable bComsumable specifies if the event is consumable

pID
SCAResult removeAsyncEvent ( in PathId
,

478
in EventId eID
)

Removes all events from the asynchronous queue that match the supplied
event id. This function returns EventNotFound if the event is not found
in the queue. This is only valid when running in default thread mode.

Parameters:
in PathId pID the channel/domain id of the event
in EventId eID the id of the event to remove

in
SCAResult spListen )
( SCAIEventListene
removeDomainFilteredListenerWildCard er
r

Removes a listener from the list of listeners automatically added to


domains whose name matches a DomainFilter. When
addDomainFilteredListenerWildCard is called, among other things, the
listener and wild-carded domain name are added to a data structure used
to automatically register the listener with subsequently created
domains. This function removes the listener from that data structure so
that it will no longer be automatically registered with domains. This
function DOES NOT removed the listener from any existing domains. This
can be done by using the function removeListener.

Parameters:
in SCAIEventListener spListener listener to remove

SCAResult removeListener ( in PathId pID,


in SCAIEventListener spListener
)

Remove a listener from the specified domain/channel. If pathID is zero,


then the listener will be removed from all domains.

Parameters:
in PathId pID id of the domain/channel
in SCAIEventListener spListener listener to remove

479
SCAVoid setLoggingLevel ( in SCAUInt32 loggingLevel )

sets the level of logging information for the Event Manager

Parameters:
in SCAUInt32 loggingLevel The new logging level (NoLogging = 0,
Medium = 1, Detailed = 2)

SCAResult startAsyncEventDispatcher ( )

Start the dedicated thread for delivering asynchronous events. Events


that are already in the asynchronous event queue will be delivered when
the thread starts.

The documentation for this interface was generated from the following file:

IDL/[Link]

480
SCA Framework User Document

Chapter 19
SCA Plug-in for Visual Studio

481
19. SCA Plug-in for Visual Studio
Building SCA components involves the creation of various files that define the SCons source
tree and the component itself. These contain general information such as locations for SCA
tools and kernel and the details of the component you are building. Some of the files required
are as follows.
- The source tree root must contain a SConstruct file, a SConopts and a SConscript
file.
- The SConopts file contains information like the SCA Kernel location and the
requirements for Java Support.
- Any sub-directory that needs to be processed should include a SConscript file.
- IDL, SDL and CDL files are used to define the components and services.
- Source code files in one of the supported languages to provide the implementation of
your services.
The SCA Visual Studio plug-in make is easier to create SCA components by automating the
process of creating and populating these files. You only have to fill in the required information
in Windows forms and the plug-in will create the required files and store them in the source
tree in their correct locations.
You can then edit the files using the Visual Studio editor or any of the special snippet tools
provided by the plug-in. When the Build button in Visual Studio is pressed, it will invoke
SCons, the SCA build tool to build the component. You then have the ability to debug the
application the same way you can debug any other Visual Studio project.

19.1. Setup Requirements


Installing the plug-in
The setup file for the SCA Visual Studio plug-in is delivered with the SCA Framework.
Kernel-WIN8664\Apps-Opt\WIN*/bin/SCA_VS_Setup.exe
Kernel-WIN8664\Apps-Opt\WIN*/bin/SCA_VS_Setup.msi
To install the plug-in, just run the setup exe file. The plug-in will install correctly using either
Visual Studio 2005 or Visual Studio 2010.
The SCA_TOOLS environment variable
You must set the environment variable SCA_TOOLS to point to the location of the SCA
tools you will be using. The Tools directory contains multiple python, C shell and
Command Prompt files.
Merge Tool
This Visual Studio plug-in uses a text merge tool to merge source files generated by
running genskeleton. This is the case when source files already exist and genskeleton
creates new versions of then which are saved with an extension of .new. When these new
files are generated they are not added to the Solution Explorer but the merge tool is run
which allows you to do the desired merges.

482
The Visual Studio plug-in automatically searches for [Link] and [Link] in
the System Path and App Paths registry entry. If either of them is found, it will be used as
the default merge tool with priority given to WinMerge.

If the plug-in cannot find [Link] or [Link] it will display an error message
at the start of the New Project. If this is the case you can create a SCA_MERGE_TOOL
environment variable to point to the merge tool. You can select a tool other than
WinMerge or p4merge but it has to be executable in this format:
[Link] [file1] [file2]
The two files to be merged must be passed as command line arguments separated by a
space.
Configuration errors
At various steps in the process of developing components and applications, the plug-in
needs to run the SCons build system.
Building skeleton implementation files
Updating Visual Studio configuration files to include files created by the plug-in
Building the component or application
If there are any configuration errors, then these SCons runs may failure will only appear
in the Visual Studio output window for the last case listed above. For the other two cases
there will be no indication of failure other than the expected files will not show up in the
solution explorer. In this case, there should be a log file, [Link], created in the project
directory. You need to look at this file to see the reason for the failure.

483
19.2. New Project Dialog Box

Above is the New Project dialog box of Visual Studio 2010. Under Visual C++, the new
entry SCAProject appears which contains the SCAApplication and SCAComponent
templates. The SCAApplication template lets you create an application which initializes
the SCA Kernel and can load SCA Components and the SCAComponent template lets
you create new components. In both cases these projects can be added to an existing
SCons source tree or a new source can be created to contain them.

Although SCAApplication and SCAComponent entries appear under C++ section, you
can choose the actual implementation language for them in a future dialog box.

The Name field should be the component name for the SCAComponent or
SCAApplication.

When using this plug-in the preferred source tree layout is the following:

484
This layout was selected to be consistent with the Visual Studio project creation layout.
In this case, the Location value should point to the root of the source tree. And the
component or the CDL file will be created in the directory [Location]\[Name]. The
primary use of the Location field is to locate the root directory of the SCons source tree
which will contain your project. The way this is done is described below. If you want the
actual location of the SCA component or application to be in a lower subdirectory then
shown above, you will get the opportunity to specify this in a future dialog box.

Note: Neither of these project types support "Create directory for solution" and "Add to
source control". Therefore these boxes should be unchecked.

19.3. The Source Tree and its relationship to the Visual Studio project
It is important you understand the relationship between the SCons source tree and the
Visual Studio project. This is complicated by the fact that a SCons source tree may
contains many different SCA components and applications. But a Visual Studio project
may only contain a single SCA component or a single SCA application. This means that
the SCons source tree may actually contain more than one Visual Studio projects.

Visual Studio also supports Solutions with may contain more than one project. SCons
will build a single Visual Studio solution file for each Visual Studio project and also a
global Visual Studio solution file in the root of the source tree that contains entries for
every project it contains.

A SCons source tree has the following characteristics:

The root of the tree is marked by the presence of a SConstruct file. A SConopts file
is also present in the root to define user options such as adding Java support.
Components (defined by CDL files) are mapped to Visual studio projects and are
contained in subdirectories of the source tree. Each of these subdirectories needs to
contain a SConscript file which tells SCons to process that directory.
Services (defined in SDL files) can be defined in the same directory as the component
or in subdirectories of the component directory.
Data types which are defined in IDL files can be located anywhere in the source tree.
This is possible because the #include statements in IDL and SDL files must specify
the path where they are installed in the APPS tree and not their location in the source
tree.
Language source files are generated in the same directory as the SDL file except for
Java where source files have to be in a directory structure that reflects their package
declaration.

To help maintain the above mentioned layout, the plug-in looks for a SConstruct file in
the Location specified in the previously discussed New Project dialog box. If a

485
SConstruct file is found, that location is treated as the root of the source tree and the new
project will be added to the existing source tree.

If a SConstruct file is not found it searches in parent directories till either a SConstruct
file is found or the search hits the root of the file system. If a SConstruct file is found in
any of the parent directories you are prompted to select if this directory is the desired root
directory. If you reply yes then the plug-in moves onto collect information about the
project.

If a SConstruct file is not found or you select no to the above prompt, then the plug-in
produces a dialog box to collect the information to create a new the source tree.

Once the root of the source tree is decided the plug-in will create the appropriate
SConstruct, SConopts and SConscript files in it. The plug-in will only create the
SConopts file for new source trees. In case of an existing tree, the SConopts file will
have to be manually edited if you need to change it.

486
19.4. SCA Component
Below is the dialog box to collect information about a new SCA Component.

487
The Implementation Language combo box allows you to select the language you wish
to implement the component in.

The Component name field is automatically filled with the information from the New
Project dialog box.

The Component Source Tree Location is the CDL file's location relative to the root of
the source tree. The default value will be .\[ComponentName] which is a subdirectory
directly under the root of the source tree. If you want the component to reside in a
subdirectory lower than this you can change the value here. If any of these subdirectories
do not exist, the plug-in will create them. It will also make sure an appropriate
SConscript file exists in each one.

Location of Component in Delivery Tree defines the path where the library file (.dll for
C++, C# and Visual Basic and .jar for Java) will be installed in the delivery tree. This
location is relative to the delivery tree’s lib directory
APPS_LOCAL\WIN*\lib
The next section of the dialog box gathers the information required to implement a
service in the component. You can only define one service in this dialog. If you wish to
add additional services, this can be conveniently done a latter time using the CDL code
snippets provided by the plug-in. These are discussed latter in this chapter.

The Service Namespace defined in this box reflects the namespace in the generated C++,
C# or Visual Basic source files or the package statement in generated Java source files.
(Source files are generated when genskeleton is run. This is discussed later in the
chapter.)

The Service Name is the full dotted name of the service, for example [Link].
The last portion of the dotted name will be used as the name of implementation class and
its source file.

By default the SDL file is created in the same directory as the CDL file. But when Create
Service Subdirectory box is selected, the SDL file is created in a subdirectory with the
name of the SDL file.

The final section of the dialog box lets you specify the interfaces that the service will
implement. These should only include new interfaces that your component creates and
delivers to its consumers. Preexisting interfaces defined by other components that you
implement should not be included here. The interfaces specified will be defined in an
IDL file which is created in the same directory as the CDL file. No methods will be
added to the interfaces. The actual methods are added using the IDL snippet which is
described latter in this chapter. Additional interfaces can be easily added at a later time
using the SDL snippet tools.

488
19.5. SCA Application
Below is the dialog box to collect information about a new SCA Application. In the
example the Visual Studio New Project dialog box Location was set to “C:\Apps”.

The Implementation Language combo box allows you to select the language you wish
to implement the component in.

The Application Location is the applications location relative to the root of the source tree.
The default value will be .\[ApplicationName] which is a subdirectory directly under the root
of the source tree. If you want the application to reside in a subdirectory lower than this you
can change the value here. If any of these subdirectories do not exist, the plug-in will create
them. It will also make sure an appropriate SConscript file exists in each one.

19.6. The rewriting of the vcproj and [Link] files


For both of these projects, the plug-in will make a quick SCons run immediately after you
select the Finish button. The purpose of this run is to recreate the vcproj or [Link], file
depending on the Visual Studio version you are using, so the solution tree will properly
include the IDL, SDL, CDL and SCon* files that were created by the plug-in. When these
files are rewritten, Visual Studio will detect the change and prompt you on what to do with the
newly created files. If you do not get these prompts then check the [Link] file in the project
directory to see if there were any problems with the SCons run.
The points to remember about the following prompts are as follows

The files on the disk are newer hence always select the option to load files from
the disk.
Files get modified outside the environment hence always reload to see the
changes.

489
Updated files are already saved hence discard existing changes and load the
project from disk.

For Visual Studio 2005 or 2008:

Select Discard in-memory changes

Select Discard to load the vcproj written by SCons.

For Visual Studio 2010:

Select Reload for this dialog box.

490
Select Yes for this dialog box.

19.7. 64-bit Windows issues


For 64-bit platform users, when either a new application or a component project is
created, the Platform setting in Configuration Properties of the Solution might default to
Win32 which results in the project being skipped if you are building for the 64-bit
platform. If the output of Visual Studio states the Project was skipped when the Build
button is pressed, change the platform in Configuration Properties from Win32 to X64.

19.8. Visual Studio IDE Enhancements


Running genskeleton
Once you have created a new SCA Component project, you can run genskeleton on the
SDL file to create its skeleton implementation files by right clicking on the SDL file In
the solution explore and selecting genskeleton. You may also want to rerun genskeleton
on existing services after you have made changes to its IDL or SDL files.

491
This command will run SCA_TOOLS\[Link] to generate implementation files
followed by a SCA_TOOLS\[Link] to recreate the vcproj or [Link] files to
include the newly generated implementation files.

The [Link] run will produce the dialogs described earlier because it is causing the
vcproj or [Link] files to be rewritten. You should choose the prompts to refresh
project.

After genskeleton is run the plug-in may run a merge tool. If the source is being
generated for the first time there is nothing to merge. But if you are rerunning
genskeleton on a service that already has source files, the genskeleton script will not
overwrite the existing source files. Instead it will add a .new extension to the newly
created files. In this case you will need to merge the appropriate changes into your
existing source files.
Automating the additions of code in CDL, SDL and IDL files
The plug-in provides a set of custom snippets which make the adding of additional
definitions in CDL, SDL and IDL files easier. When you right-click in the editor window
when editing one of these files, a menu appears with a set of options. When one of the

492
snippet options is selected, it will display a dialog box which gathers the required
information needed to perform the respective task.

The code generated by the snippet will be inserted into the file being edited at the
location where the cursor is pointing at the time when the right-mouse button is clicked.

Note for user: when adding new items to these files you should check if the items are
added to the correct position in the files. For example if adding items to IDL files, make
sure they are under the correct module statements.
CDL snippet
The following snippet options are available when you right-click in the edit window for a
CDL file.

The Add Service option will add the definition for a new service by creating a new SDL
file. The options available are similar to those describe earlier in the New Component
dialog box, but no new IDL files will be added. You will need to manually add these if
needed. Since a new SDL file is being created, the [Link] command will be run will
be made to update the vcproj or [Link] files. You should choose the prompts to
refresh project. You will then need to run genskeleton to create the source files for the
implementation.
SDL snippets
The following snippet options are available when you right-click in the edit window for a SDL
file.

493
The Add Subservice option adds code for a new subservice in the selected SDL file. After
adding the subservice, you will then need to run genskeleton to create the source files for
the subservice implementation.

The Implement Interface option adds code to implement interfaces in the selected SDL
file. If there are interfaces defined in IDL files located in the same directory as the SDL
file the Implement Interface dialog box will list the interfaces defined in it. If any of the
listed interfaces are added, then a #include statement will be added to the top of the SDL
file. If you add an unlisted interface, you have to manually include the appropriate IDL
file with a #include statement.

IDL snippets
The following snippet options are available when you right-click in the edit window for an
IDL file.

494
The Add Interface option generates code to define new interfaces in the IDL file. If the
interface should be in an existing namespace you can have the cursor at the appropriate
position and leave the namespace textbox blank in the Add Interface dialog box.
Otherwise you should add the appropriate namespace for the interface and appropriate
IDL module statements will be generated. Once again make sure the cursor is pointing to
the spot in the IDL file where you want the module inserted.

The Add Method option generates code to define a new method definition in the IDL file.
The standard SCA types are listed for parameter types while user-defined types can be
defined in the provided text boxes.

The Add Struct option generates code to define a new struct definition in the IDL file.
The standard SCA types are listed for member types while user-defined types can be
defined in the provided text boxes.

The Add Enum option generates code to define a new enum definition in the IDL file.

495
SCA Framework User Document

Chapter 20
Configuration Manager Service

496
20. Configuration Manager Service
20.1. Introduction

The purpose of the Configuration Manager Service is to provide access to application’s


configuration data in a platform independent manner. The service consolidates the
information and functionality in one place so the application and other services can have the
functionality without adding much code.

SCA services used by applications often have a need to access data specific to the current
application session, such as configuration options. Because the services cannot be tightly
coupled to the application, the application must create a SCA interface and pass it to the
services so they can query and modify the required data. This code is often repeated
throughout the application and the services it uses.

The Configuration Manager Service solves this problem by offering a consistent mechanism
for getting, setting, loading and saving the configuration data, such as user options and
resource paths, so accessing and managing the data across many different components is much
easier. Configuration data stays manageable because there is one standard for controlling it.
The persistent configuration data is saved in an xml text file.

This is a Singleton service that implements the SCAIConfigurationManager interface,


described later in this chapter.

20.2. Configuration XML File

The configuration file is a hierarchical xml file. The configurations are organized in
groups, sub-groups and variables. The file also has a version number. Each group can
have multiple sub-groups and/or variables. Each variable can have one or more values,
depending on the type. There is no limit on the number of nested levels of sub-groups.

A persistent write counter is also saved in the file. Its value is incremented every time the
data is written to the file. The purpose of this counter is to protect the data from
clobbering by multiple processes. See ‘File Locking and Multi Process Safety’ for details.

<?xml version="1.0" ?>


<!-- Table of Configuration variables -->
<SCA>
<configuration writecounter="counter" version="version" >
<group name="Group11">
<group name="Group21">
<variable name="variable1" type="variable1Type"
readOnly="true or false">
<value>value1</value>
</variable>
</group>

497
<group name="Group22">
<variable name="variable2" type="variable2Type"
readOnly="true or false">
<value>value1</value>
<value>value2</value>
. . .
</variable>
<group name="Group31">
<variable name="variable3" type="variable3Type"
readOnly="true or false">
<value>value1</value>
</variable>
<group name="Group41">
<variable name="variable4" type="variable4Type"
readOnly="true or false">
<value>value1</value>
<value>value2</value>
. . .
</variable>
. . .
</group>
. . .
</group>
. . .
</group>
. . .
</group>
<group name="Group12">
. . .
</group>
. . .
</configuration>
</SCA>

A sample configuration file is shown in the ‘Usage Example’ section.

20.3. Configuration Variables


The configuration variables are organized in groups and subgroups.

Naming Convention
A fully qualified variable name is of the following format.

group1.group2…[Link]

The name cannot contain blank spaces or the characters ‘[‘, ‘]’ or ‘?’.

A fully qualified name must be passed to any method requiring the variable or group
name.

498
Supported Data Types
The following data types are supported for the variable values. Methods are provided to
set and get these value types.

SCAInt64 SCAReal64 SCABool SCAUString SCAInt64Sequence


SCAReal64Sequence SCABoolSequence SCAUStringSequence

Variable Attributes
The variables can have readOnly and/or transient attributes.

The true value for the readOnly attribute means the variable, in the xml file, is read only
and cannot be overwritten at runtime. They can only be modified by editing the XML
file.

The true value for the transient attribute means the variable should not be saved to the
xml file. The transient values never appear in the XML file. They can only be added and
modified at runtime.

Variable Substitution
The Configuration Manager supports substitution of variable names embedded in string values.
The variable name, to be substituted, must be enclosed between ?[ and ]? characters as in
?[ENV_VARIABLE]?. The methods ‘getString’, ‘getStringSequence’ and ‘expandString’
support variable substitution.

For example if a string variable ‘INSTALL_ROOT’ has a value of “/Application/Components/”,


the string “?[INSTALL_ROOT]?/plugins” will be expanded to
“/Application/Components/INSTALL_ROOT”.

20.4. Support for Named Configurations


The ConfigurationManager is a Singleton service which manages multiple named
configurations. It provides a factory method to create new instances of the configurations
and access existing instances by name. The configuration names are only runtime
identifications and are not persisted in xml files.

20.5. Creating OS Environment Variables from Configuration Variables


The Configuration manager provides capability to automatically create OS Environment
variables from configuration variables. This feature also supports variable substitution to
allow creation of the environment variable based on the value of other configuration
variables.

All the environment variables to be created must be specified in the


OSEnvironmentVariables group, at root level, in the 'configuration' section of the
configuration file. When the configuration file is loaded these OS environment variables

499
are automatically created. But before creation, any references to other variables in the
environment variable are substituted with their values. These variables are not added to
the configuration instance.

OS Environment Load Options

enum OSEnvironmentOption {
ENV_NEGLECT_ALL,
ENV_NEGLECT_COMMON,
ENV_REPLACE_COMMON
};

OSEnvironmentOption Description
ENV_NEGLECT_ALL Neglect all the environment variables.
ENV_NEGLECT_COMMON Neglect the environment variables which
already exist.
ENV_REPLACE_COMMON Overwrite the environment variables which
already exist.
Note: The values are NOT appended or
prepended.

SCA Kernel Configuration in Configuration File

It is also possible to specify the SCA Kernel Configuration and the Client configuration
in the same XML file. The SCAKernel initialization neglects the configuration nodes in
the xml file. The configuration manager load method neglects the session nodes.
See the ‘SCA Kernel’ chapter for more information on SCA Kernel Configuration files.

Query SCA Kernel Configuration Variables

The Configuration Manager supports a special named configuration called


“SCAKernelConfiguration”, which could be used to query SCA Kernel Configuration
variables.

Only getVariableList, getString, getStringSequence, getReadOnlyStatus and


getTransientStatus methods are supported. This is a read-only configuration and the
values cannot be changed or saved in the configuration file.

All other methods return an error telling that “SCAKernelConfiguration” does not
support the given method.

The following code snippet shows how to query the SCA Kernel Configuration Variables

. . .
SCAIConfiguration spKernelConfiguration;
spConfigMgr->getConfiguration("SCAKernelConfiguration", spKernelConfiguration);

500
SCAUStringSequence resValues;
spKernelConfiguration->getStringSequence("Resource", false, resValues);
for (SCAUStringSequence::size_type i=0; i<[Link](); i++)
cout<<"Resource:"<<StringUtility::stringFromUString(resValues.r_at(i))<<endl;
SCAUString catValue;
spKernelConfiguration->getString("Catalog", false, catValue);
cout << "Catalog: " << StringUtility::stringFromUString(catValue) << endl;
. . .

20.6. Configuration Manager Service API

The Configuration Manager Service implements the SCAIConfigurationManager and


SCAIConfiguration interfaces.

The methods of these interfaces are described below.

SCA::Framework::SCAIConfigurationManager Interface

Member Functions
SCAResult getConfiguration (in SCAUString name, out SCAIConfiguration
spConfiguration)
Factory method to get a named instance of the Configuration. If the instance
does not exist a new named instance is created, else the existing instance is
returned.

SCAResult removeConfiguration (in SCAUString name)


Remove a named instance of the Configuration.

SCAResult setEventPublishingStatus (in SCABool publish)


Set Event publishing status. When event publishing is turned on the
ConfigurationManager publishes the following events to the domain
"[Link]"
EVENT_VARIABLE_CHANGED EVENT_VARIABLE_REMOVED
EVENT_GROUP_REMOVED EVENT_CONFIGURATION_LOADED.

SCAResult cleanupLockFiles ()
Remove any lock files left due to abnormal termination.

Member Function Documentation

SCAResult cleanupLockFiles ( )
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getConfiguration ( in SCAUString name,


out SCAIConfiguration spConfiguration
)
Parameters:

501
name Configuration name. If the name does not exist a new named
instance is created, else the existing instance is returned.
spConfiguration Smart pointer to the SCAIConfiguration interface
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult removeConfiguration ( in SCAUString name )


Parameters:
name Configuration name
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setEventPublishingStatus ( in SCABool publish )


Parameters:
publish event publishing status
true enables event publishing
false disables event publishing (default)
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCA::Framework::SCAIConfiguration Interface

Member Functions
SCAResult setInt (in SCAUString name, in SCAInt64 value)
Sets a SCAInt64 value of a variable.

SCAResult getInt (in SCAUString name, out SCAInt64 value)


Gets a SCAInt64 value of a variable.

SCAResult setReal (in SCAUString name, in SCAReal64 value)


Sets a SCAReal64 value of a variable.

SCAResult getReal (in SCAUString name, out SCAReal64 value)


Gets a SCAReal64 value of a variable.

SCAResult setBool (in SCAUString name, in SCABool value)


Sets a SCABool value of a variable.

SCAResult getBool (in SCAUString name, out SCABool value)


Gets a SCABool value of a variable.

SCAResult setString (in SCAUString name, in SCAUString value)


Sets a SCAUString value of a variable.

SCAResult getString (in SCAUString name, in SCABool expandVariables, out SCAUString


value)
Gets a SCAUString value of a variable.

502
SCAResult setStringFromEnvironmentVariable (in SCAUString name, in SCAUString
envVariable)
Creates and sets a configuration variable from an OS environment variable.

SCAResult setIntSequence (in SCAUString name, in SCAInt64Sequence value)


Sets a SCAInt64Sequence value of a variable.

SCAResult getIntSequence (in SCAUString name, out SCAInt64Sequence value)


Gets a SCAInt64Sequence value of a variable.

SCAResult setRealSequence (in SCAUString name, in SCAReal64Sequence value)


Sets a SCAReal64Sequence value of a variable.

SCAResult getRealSequence (in SCAUString name, out SCAReal64Sequence value)


Gets a SCAReal64Sequence value of a variable.

SCAResult setBoolSequence (in SCAUString name, in SCABoolSequence value)


Sets a SCABoolSequence value of a variable.

SCAResult getBoolSequence (in SCAUString name, out SCABoolSequence value)


Gets a SCABoolSequence value of a variable.

SCAResult setStringSequence (in SCAUString name, in SCAUStringSequence value)


Sets a SCAUStringSequence value of a variable.

SCAResult getStringSequence (in SCAUString name, in SCABool expandVariables, out


SCAUStringSequence value)
Gets a SCAUStringSequence value of a variable.

SCAResult removeVariable (in SCAUString name)


removes a configuration variable from the settings.

SCAResult removeGroup (in SCAUString group)


removes a group or sub-group and all its children from the settings.

SCAResult saveToFile (in SCAUString fileName, in SCAUString group, in SCAUInt32


version, in SCAUInt32 lockTimout)
Saves the configurations to the specified xml file.

SCAResult loadFromFile (in SCAUString fileName, in SCAUString group, in


ConfigMergeType mergeType, in OSEnvironmentOption osEnvOption, out
SCAUInt32 version, in SCAUInt32 lockTimout)
Loads the configurations from the specified xml file.

SCAResult setTransientStatus (in SCAUString name, in SCABool isTransient)


Toggle transient status of the variable.

SCAResult getTransientStatus (in SCAUString name, out SCABool isTransient)


Gets the transient status of the variable.

SCAResult setReadOnlyStatus (in SCAUString name, in SCABool isReadOnly)


Sets the read only status of the variable.

SCAResult getReadOnlyStatus (in SCAUString name, out SCABool isReadOnly)

503
Gets the read only status of the variable.

SCAResult expandString (in SCAUString inputString, out SCAUString expandedString)


Expands any configuration variable names in the input string, enclosed
between ?[ and ]? , with their values. See ‘getString’ method for details.

SCAResult getVariableList (in SCAUString group, out SCAUStringSequence variables)


Gets the list of the configuration variables in the sub-group specified by the
group.

SCAResult cleanupLockFile ()
Remove the lock file left due to abnormal termination.

SCAResult setSCAAnyValue (in SCAUString name, in SCAAny value)

Sets the SCAAny inserted value of a variable.

SCAResult getSCAAnyValue (in SCAUString name, out SCAAny value)

Gets the SCAAny inserted value of a variable.

getVariableType (in SCAUString name, out TypeCodeID id, out SCABool


SCAResult
isSequence)

Gets the type code ID of the variable

Member Function Documentation

SCAResult cleanupLockFile ( )
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult expandString ( in SCAUString inputString,


out SCAUString expandedString
)
Parameters:
inputString input string to be expanded.
expandedString expanded string.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getBool ( in SCAUString name,

out SCABool value


)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

504
SCAResult getBoolSequence ( in SCAUString name,

out SCABoolSequence value


)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getInt ( in SCAUString name,

out SCAInt64 value


)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getIntSequence ( in SCAUString name,

out SCAInt64Sequence value


)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getReadOnlyStatus ( in SCAUString name,


out SCABool isReadOnly
)
Parameters:
name Fully qualified name of the configuration variable
isReadOnly read only status; true indicates that the variable in the xml file is read
only and cannot be overwritten; false indicates that the variable can be
overwritten in the xml file
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getReal ( in SCAUString name,

out SCAReal64 value

505
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getRealSequence ( in SCAUString name,

out SCAReal64Sequence value


)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getString ( in SCAUString name,

in SCABool expandVariables,

out SCAUString value


)
Parameters:
name Fully qualified name of the configuration variable
expandVariables Option to specify whether to expand the variable references The
variable name must be enclosed between ?[ and ]? characters as in
?[ENV_VARIABLE]? For example ?[INSTALL_ROOT]?/plugins should
return the path that starts with the content of the configuration
variable INSTALL_ROOT.
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getStringSequence ( in SCAUString name,

in SCABool expandVariables,

out SCAUStringSequence value


)
Parameters:
name Fully qualified name of the configuration variable
expandVariables Option to specify whether to expand the variable references (see
getString method)
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

506
SCAResult getTransientStatus ( in SCAUString name,
out SCABool isTransient
)
Parameters:
name Fully qualified name of the configuration variable
isTransient transient status. See 'setTransientStatus' method for description.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getVariableList ( in SCAUString group,


out SCAUStringSequence variables
)
Parameters:
group Name of the sub-group. If an empty string is passed here, all the
configuration variables are returned.
variables list of variable names.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult loadFromFile ( in SCAUString fileName,


in SCAUString group,

in ConfigMergeType mergeType,

in OSEnvironmentOption osEnvOption,
out SCAUInt32 version,
in SCAUInt32 lockTimout
)
Parameters:
fileName Fully qualified name of the xml configuration file. An ‘*’ wild card could
be used for a directory name to load multiple configuration files in the
same configuration. See the section ‘Using Wild Cards for Directory
names’ for more details.
group Name of the group. Only data under the named group will be loaded.
Empty string for group loads the entire file.
mergeType Describes how to merge the loaded and existing Configuration groups
and variables. The following merge types are supported.
CONFIG_REPLACE All current data is deleted and the new data is loaded
CONFIG_REPLACE_COMMON The common variables take on new values
from the file. The new variables are not loaded.
CONFIG_MERGE The common variables are ignored and new variables
from the file are added.
CONFIG_MERGE_OVERWRITE The common variables take on new values
from the file and new variables from the file are added.
osEnvOption Describes how to create the OS Environment variables using the values
in the configuration file's "OSEnvironmentVariables"
group. The following options are supported.
ENV_NEGLECT_ALL Neglect all the environment variables in the group
ENV_NEGLECT_COMMON Neglect the environment variables which
already exist

507
ENV_REPLACE_COMMON Overwrite the environment variables which
already exist
version File version number
lockTimout Time out in milliseconds before returning without locking the file
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

Using Wild Cards for Directory Names

An '*' wild card can be used for directory names passed to the load method. This allows
loading of all the configuration files from all the directories satisfying the wild card
simultaneously in the same configuration.

Note: More advanced wild cards values like "res*" or wild cards in file names are not
supported.

The following is an example of how wild cards could be used to specify multiple
configuration files to load. The configuration files from the resource directories of all the
plug-ins will be loaded.
. . .
// Get the ConfigurationManager Service
SCAIConfigurationManager spConfigMgr;
spConfigMgr = getSCAService("[Link]");
if (spConfigMgr != NULLSP) {
// Get a named instance of a configuration
SCAIConfiguration spConfiguration;
SCAResult rstat;
rstat= spConfigMgr->getConfiguration("AppConfiguration", spConfiguration);
rstat = spConfiguration->loadFromFile("./Plugins/*/Apps/res", . . .);
}
. . .

SCAResult removeGroup ( in SCAUString group )


Parameters:
group Fully qualified name of the group or sub-group
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult removeVariable ( in SCAUString name )


Parameters:
name Fully qualified name of the configuration variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult saveToFile ( in SCAUString fileName,


in SCAUString group,

508
in SCAUInt32 version,
in SCAUInt32 lockTimout
)
Parameters:
fileName Fully qualified name of the xml configuration file
group Name of the group. Only data under the named group will be saved.
Empty string for group saves the entire tree.
version Version number to assign to the file
lockTimout Time out in milliseconds before returning without locking the file
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setBool ( in SCAUString name,

in SCABool value
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setBoolSequence ( in SCAUString name,

in SCABoolSequence value
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setInt ( in SCAUString name,

in SCAInt64 value
)
Parameters:
name Fully qualified name of the configuration variable
(group1.group2....[Link]) For example: [Link]
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setIntSequence ( in SCAUString name,

in SCAInt64Sequence value

509
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setReadOnlyStatus ( in SCAUString name,


in SCABool isReadOnly
)
Parameters:
name Fully qualified name of the configuration variable
isReadOnly read only status; true indicates that the variable in the xml file is read
only and cannot be overwritten; false indicates that the variable can be
overwritten in the xml file
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setReal ( in SCAUString name,

in SCAReal64 value
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setRealSequence ( in SCAUString name,

in SCAReal64Sequence value
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setString ( in SCAUString name,

in SCAUString value
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:

510
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setStringFromEnvironmentVariable ( in SCAUString name,


in SCAUString envVariable
)
Parameters:
name Fully qualified name of the configuration variable
envVariable Name of the OS environment variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setStringSequence ( in SCAUString name,

in SCAUStringSequence value
)
Parameters:
name Fully qualified name of the configuration variable
value Value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setTransientStatus ( in SCAUString name,


in SCABool isTransient
)
Parameters:
name Fully qualified name of the configuration variable
isTransient transient status; false indicates that the variable will be saved to the file;
true indicates that the variable will not be saved to the file.
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult setAnyValue ( in SCAUString name,

in SCAAny value
)
Parameters:
name Fully qualified name of the configuration variable
value SCAAny inserted value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getAnyValue ( in SCAUString name,

out SCAAny value


)
Parameters:

511
name Fully qualified name of the configuration variable
value SCAAny inserted value of the variable
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult getVariableType ( in SCAUString name,

out TypeCodeID id,


out SCABool isSequence
)
Parameters:
name Fully qualified name of the configuration variable
id TypeCodeID of the variables value
isSequence true if it is one of the sequence types, otherwise false
Returns:
Returns SCASuccess on success; otherwise returns a SCAResult error.

SCAResult Errors
The ConfigurationManager service methods return the following SCAResult errors,
which are defined in the [Link] file.

Error or Message ID Code Message


CM_ERROR_ENV_NULL 1 Environment variable is empty.
CM_ERROR_ENVVALUE_NULL 2 Environment variable has NULL value.
CM_ERROR_PATH_NULL 3 Path is NULL.
CM_ERROR_FILE_LOCKED 4 Cannot access the file. It is locked by
another client.
CM_ERROR_FILE_MODIFIED 5 Cannot write to the file. Another client
has modified the file.
CM_CONFIG_NOT_FOUND 6 The configuration not found!
CM_CONFIG_NAME_NULL 7 The configuration name is empty.
CM_XML_UNSUPPORTED_VARIABLE_TYPE 8 XML error: The variable has
unsupported type.
CM_XML_UNSUPPORTED_ATTRIBUTE 9 XML error: Variable has an
unsupported attribute.
CM_XML_ATTRIBUTE_NOT_FOUND 10 XML error: Variable has a missing
attribute.
CM_XML_NO_VALUES_FOUND 11 XML error: No values found for the
variable.
CM_XML_ELEMENT_NOT_FOUND 12 XML error: element not found!
CM_ERROR_FILE_OPEN 13 Error opening the configuration file
CM_ERROR_VARIABLE_ALREADY_EXISTS 14 The configuration variable already
exists!
CM_ERROR_VARIABLE_NOT_FOUND 15 The configuration variable not found!
CM_ERROR_GROUP_NOT_FOUND 16 The configuration group not found!
CM_ERROR_UNSUPPORTED_MERGE_TYPE 17 The ConfigMergeType is not supported
CM_ERROR_READ_ONLY_VARIABLE 18 The read only configuration variable
cannot be changed or removed.

512
CM_ERROR_INVALID_NAME 19 Invalid configuration variable or group
name.
CM_ERROR_INCORRECT_VARIABLE_TYPE 20 The configuration variable is of
incorrect type.
CM_ERROR_UNSUPPORTED_VARIABLE_TYPE 21 The configuration variable has invalid
type.

Explanation of Configuration Merge Options (ConfigMergeType)

enum ConfigMergeType {
CONFIG_REPLACE,
CONFIG_REPLACE_COMMON,
CONFIG_MERGE,
CONFIG_MERGE_OVERWRITE
};

When the configurations are loaded from the xml file, the variables and groups are
merged based on the merge type passed to the load method. The following table describes
the supported merge types.

ConfigMergeType Description
CONFIG_REPLACE All current data is deleted and the
new data is loaded
CONFIG_REPLACE_COMMON The common variables take on new
values from the file. The new
variables are not loaded.
CONFIG_MERGE The common variables are ignored and
new variables from the file are added
CONFIG_MERGE_OVERWRITE The common variables take on new
values from the file and new
variables from the file are added.

20.7. Multi Thread/Process Safety


The ConfigurationManager service is multi thread safe.

Note: Multithreading is not supported on any UNIX platforms.

Also, multiple processes, running locally or across the network, can simultaneously
access the same configuration file. The ConfigurationManager accomplishes this using
the following mechanisms.
Write Counter
The configuration xml file stores a persistent ‘writeCounter’ to protect the data from
clobbering.

1. The counter is read and kept in memory every time the file is read.
2. Before saving the data to the file, the counter in the file is compared to the counter
when the file was opened.

513
3. If the two counter values are different, it means that another process has updated
the data in the file after it was loaded in the current process. This scenario
generates an error saying “You cannot write to the file... Another client has
modified the file”
4. If the two counter values are same, the counter in the file is incremented and the
data is saved to the file.

File Locking
The configuration file is locked during access (Open/Read/Write/Close) by creating a
lock file with the same name, at the same location as the xml file, but with ’lck’
extension. The lock file is deleted after access. If the lock file already exists and another
client tries to create one, the call will fail and it will have to wait for the first client to
delete it. The ‘loadFromFile’ and ‘saveToFile’ methods take a ‘lockTimeout’ parameter,
which specifies the amount of time (in milliseconds) to wait before returning an error
indicating that the file is locked and cannot be accessed.

Note: All client applications must have same access rights to the configuration xml file.
This locking mechanism will not work if some clients have write access while others only
have read access.

Lock File Cleanup


Under normal program execution the lock files are automatically deleted when the locks
are released. But in case of signal or other application crash there may be left over lock
files. The Configuration Manager Services keeps track of the last lock file used in each
active instance of the Configuration and has an internal signal catcher that attempts to
cleanup these lock files, in case of signals.

Note: This cleanup mechanism is not fool proof. There will be instances where the lock
files will have to be manually deleted.

Usage Example
The sample configuration file ‘[Link]’ used in the example code is listed below.

<?xml version="1.0" ?>


<!-- Table of Configuration variables -->
<SCA>
<configuration writeCounter="0" version="5" >
<variable name="ENV_VAR1" type="String">
<value>/DummyPath1</value>
</variable>
<variable name="ENV_VAR2" type="String">
<value>/DummyPath2</value>
</variable>
<group name="win32">
<group name="GroupX">
<variable name="componentName" type="String" readOnly="true">
<value>Versioning Component</value>

514
</variable>
<variable name="services" type="StringSequence">
<value>Service A</value>
<value>Service B</value>
<value>Service B</value>
<value>Service B</value>
</variable>
<variable name="APPDATA_PATH" type="String">
<value>c:/applicationData</value>
</variable>
<variable name="path" type="String">
<value>?[[Link].APPDATA_PATH]
?/temp/minidumps?[ENV_VAR1]??[ENV_VAR2]?/local</value>
</variable>
<group name="GroupY">
<variable name="serviceCount" type="Int">
<value>4352</value>
</variable>
<variable name="idList" type="IntSequence">
<value>42</value>
<value>56</value>
<value>77</value>
</variable>
<variable name="tolerance" type="Real">
<value>0.000000000025</value>
</variable>
<group name="GroupZ">
<variable name="serviceCount" type="Int">
<value>4352</value>
</variable>
</group>
</group>
</group>
<group name="GroupA">
<variable name="variable1" type="Int">
<value>0345</value>
</variable>
<variable name="variable2" type="StringSequence">
<value>String 1</value>
<value>String 2</value>
<value>String 3</value>
</variable>
</group>
</group>
<variable name="rootLevelVariable" type="String" readOnly="true">
<value>Root level variable</value>
</variable>
</configuration>
</SCA>

The following sample code demonstrates the use of the Configuration Manager Service.

Note: Error handling is disabled for simplicity. The actual code must check for the SCAResult
value retuned from the interface methods. Also, full path of the configuration file must be passed
to the loadFromFile(…) and saveToFile(…) methods. The sample code only shows the file name.

#include <SCA/StringUtility.h>
#include <SCA/SCAKernel.h>
#include <SCA/Framework/SCAIConfigurationManager.h>

515
#include <SCA/Framework/SCAIConfiguration.h>
#include <unicode/ustream.h>
#define LOCK_TIMEOUT 30000

using namespace SCA;


using namespace SCA::Framework;
using namespace std;

// Query and print all the configuration variable names


SCAResult printVariableList(const SCAString& header,
const SCAIConfiguration& spConfiguration)
{
SCAUStringSequence variables;
SCAResult rstat = spConfiguration->getVariableList("", variables);
if ( rstat ) return rstat;
cout << header << endl;
for (SCAUStringSequence::size_type i=0; i<[Link](); i++)
cout << " Variable: " << variables.r_at(i) << endl;

return rstat;
}

int main()
{

// Initialize the SCAKernel


try {
initializeSCAKernel(1);
} catch (SCAException& e){
cout<<"-> initializeSCAKernel failed" << endl << [Link]() << endl;
return 0;
}

// Get the ConfigurationManager Service


SCAIConfigurationManager spConfigMgr;
spConfigMgr=getSCAService("[Link]");
if (spConfigMgr != NULLSP) {
// Get a named instance of a configuration
SCAIConfiguration spConfiguration;
SCAResult rstat = spConfigMgr->getConfiguration(
"Sample Configuration", spConfiguration);

// Turn ON Event Publishing


rstat = spConfigMgr->setEventPublishingStatus(true);

// Load a Configuration file


SCAUInt32 configVersion;
rstat = spConfiguration->loadFromFile("[Link]", "",
CONFIG_REPLACE, ENV_REPLACE_COMMON, configVersion, LOCK_TIMEOUT);

// Add some new configuration variables


rstat = spConfiguration->setInt("[Link]", 4321);
rstat = spConfiguration->setInt("[Link]", 9845);
rstat = spConfiguration->setInt("[Link]", 53455);

// Now get those variables and print their values


SCAInt64 intVal;
rstat = spConfiguration->getInt("[Link]", intVal);
cout << "[Link]=" << intVal << endl;
rstat = spConfiguration->getInt("[Link]", intVal);
cout << "[Link]=" << intVal << endl;
rstat = spConfiguration->getInt("[Link]", intVal);
cout << "[Link]=" << intVal << endl;

516
// Save to another file
rstat = spConfiguration->saveToFile("[Link]", "", 8,
LOCK_TIMEOUT);
// Remove a group from the configurations just saved
rstat = spConfiguration->removeGroup("[Link]");

cout << "== Load with different ConfigMergeType options ==" << endl;

// Set a new value for a variable that was in the group just deleted
rstat = spConfiguration->setInt("[Link]", 25);

// CONFIG_REPLACE_COMMON
// Now load the group from the file with CONFIG_REPLACE_COMMON option. The
// above value for "[Link]" should revert to 4252
rstat = spConfiguration->loadFromFile("[Link]", "",
CONFIG_REPLACE, ENV_REPLACE_COMMON, configVersion, LOCK_TIMEOUT);
rstat=spConfiguration->getInt("[Link]",intVal);
cout << "[Link]=" << intVal << endl;

// Query and print the variables after reloading the group [Link]
// with CONFIG_REPLACE_COMMON option
rstat=printVariableList(
"After loading with CONFIG_REPLACE_COMMON",spConfiguration);

// CONFIG_MERGE:
// Set a new value for the same variable
rstat = spConfiguration->setInt("[Link]", 32);

// Now load the group from the file with CONFIG_MERGE option. The value for
// "[Link]" should stay at 32 and new values
// added
rstat = spConfiguration->loadFromFile("[Link]", "",
CONFIG_REPLACE, ENV_REPLACE_COMMON, configVersion, LOCK_TIMEOUT);
rstat = spConfiguration->getInt("[Link]",
intVal);
cout << "[Link]=" << intVal << endl;

// Query and print the variables after reloading the group [Link]
// with CONFIG_MERGE option
rstat = printVariableList("After loading with CONFIG_MERGE",
spConfiguration);

// CONFIG_MERGE_OVERWRITE:
// Now load the group from the file with CONFIG_MERGE_OVERWRITE option.
// The value for "[Link]" should change to 4252
// and new values added
rstat = spConfiguration->loadFromFile("[Link]", "",
CONFIG_REPLACE, ENV_REPLACE_COMMON, configVersion, LOCK_TIMEOUT);

spConfiguration->getInt("[Link]", intVal);
cout << "[Link]=" << intVal << endl;
// Query and print the variables after reloading the group [Link]
// with CONFIG_MERGE_OVERWRITE option
rstat=printVariableList(
"After loading with CONFIG_MERGE_OVERWRITE", spConfiguration);

// Set and get a Real Sequence as variable’s value


SCAReal64Sequence realSequence;
realSequence.push_back(5.234);
realSequence.push_back(-7.566);
realSequence.push_back(3829.22232);
spConfiguration->setRealSequence("[Link]",realSequence);

517
[Link]();
spConfiguration->getRealSequence("[Link]",realSequence);
cout << "[Link]" << endl;
for (SCAReal64Sequence::size_type i=0; i<[Link](); i++)
cout << realSequence.r_at(i) << endl;

// Set a String variable


spConfiguration->setString("[Link].APPDATA_PATH", "/CMTest/AppData");

// Get the path variable without substitution


SCAUString path;
rstat = spConfiguration->getString("[Link]", false, path);
cout << "[Link] without variable substitution: " << path <<endl;

// Get the path variable with substitution


rstat = spConfiguration->getString("[Link]", true, path);
cout << "[Link] with variable substitution: " << path << endl;

// Set the osPath variable from 'PATH' environment variable


spConfiguration->setStringFromEnvironmentVariable("[Link]", "PATH");

// Retrieve the osPath variable


SCAUString pathString;
rstat = spConfiguration->getString("[Link]", true, pathString);
cout<<"[Link]="<< pathString << endl;

// Set and get transient status of a variable


spConfiguration->setTransientStatus("Linux*.[Link]",true);
SCABool isTransient=false;
spConfiguration->getTransientStatus("Linux*.[Link]",
isTransient);
cout << "Transient status= " << isTransient << endl;

// Set and get readOnly status


spConfiguration->setReadOnlyStatus("Linux*.[Link]", true);
SCABool isReadOnly=false;
spConfiguration->getReadOnlyStatus("Linux*.[Link]",
isReadOnly);
cout << "ReadOnly status= " << isReadOnly << endl;

// Change the readOnly status to false, before removing the variable


spConfiguration->setReadOnlyStatus("Linux*.[Link]",false);

// Now remove the variable


rstat = spConfiguration->removeVariable("Linux*.[Link]");

// Expand the input string using variable substitution.


SCAUString expandedString;
rstat = spConfiguration->expandString(
"/minidumps?[[Link].APPDATA_PATH]?/local?[ENV_VAR1]??[ENV_VAR2]?",
expandedString);
cout << "String before expansion=" <<
"/minidumps?[[Link].APPDATA_PATH]?/local?[ENV_VAR1]??[ENV_VAR2]?"
<< endl;
cout << "String after expansion=" << expandedString << endl;
}

// Terminate the SCA Kernel.


try {
terminateSCAKernel();
} catch(SCAException& e) {
cout<<"Termination of the kernel failed! "<< endl << [Link]() << endl;
return 0;

518
}
return 0;
}

PROGRAM OUTPUT:
SCA Kernel 9.0.0 successfully initialized
[Link]=4321
[Link]=9845
[Link]=53455
== Load with different ConfigMergeType options ==
[Link]=4352
After loading with CONFIG_REPLACE_COMMON
Variable: ENV_VAR1
Variable: ENV_VAR2
Variable: rootLevelVariable
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link].variable1
Variable: [Link].variable2
Variable: [Link]
[Link]=32
After loading with CONFIG_MERGE
Variable: ENV_VAR1
Variable: ENV_VAR2
Variable: rootLevelVariable
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link].variable1
Variable: [Link].variable2
Variable: [Link].APPDATA_PATH
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
[Link]=4352
After loading with CONFIG_MERGE_OVERWRITE
Variable: ENV_VAR1
Variable: ENV_VAR2
Variable: rootLevelVariable
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link].variable1
Variable: [Link].variable2
Variable: [Link].APPDATA_PATH
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
Variable: [Link]
[Link]
5.234
-7.566

519
3829.22
[Link] without variable substitution:
?[[Link].APPDATA_PATH]?/temp/minidumps?[ENV_VAR1]??[ENV_VAR2]?/local
[Link] with variable substitution:
/CMTest/AppData/temp/minidumps/DummyPath1/DummyPath2/[Link]=
C:\Program Files (x86)\Intel\ComposerXE-2011\redist\intel64\mkl;C:\Program
Files (x86)\Intel\ComposerXE-2011\redist\ia32\mkl;C:\Program Files
(x86)\Intel\ComposerXE-2011\redist\intel64\mpirt;...
Transient status= 1
ReadOnly status= 1
String before expansion=
/minidumps?[[Link].APPDATA_PATH]?/local?[ENV_VAR1]??[ENV_VAR2]?
String after expansion=/minidumps/CMTest/AppData/local/DummyPath1/DummyPath2

520
SCA Framework User Documentation Configuration Manager Service

SCA Framework User Documentation

Chapter 21
Task Manager

521
SCA Framework User Documentation Task Manger

21. Task Manger

21.1. Introduction
The TaskManager provides the ability to run and manage a set of asynchronous tasks running in different
threads. The TaskManager supports the following basic functionality.
Schedule tasks to run from a pool of worker thread
Running tasks on dedicated threads
Monitor the progress of long running tasks
Cancel tasks
Waiting for tasks to finish
Determine the status of tasks
Over-subscription conditions exist when an application has too many threads
running that are competing for the finite available resources on the machine.
In this case thrashing can occur which can significantly reduce overall
throughput of the application. If different components of the same
application create and schedule threads with no knowledge of similar
activities by other components, then over-subscription conditions can easily
occur. To keep this from occurring, a centralized component should be used to
create and manage the required threads. The TaskManager is designed to fill
this role.
Using the TaskManager, the user can queue up tasks without worrying about
thread assignments and the TaskManager will run the tasks using an internally
managed pool of worker threads. By controlling the number of tasks running
simultaneous, over-subscription conditions can be minimized.
There are also situations where applications may require dedicated threads to
execute tasks for the duration of the run or to execute time critical small
tasks that cannot wait for one of the pool threads to become available. For
these situations the TaskManager manages a separate pool of private or
dedicated threads that can be used to run these tasks.

21.2. Creating task objects


Tasks that are processed by the TaskManager are instances of classes which
implement the SCAITask interface. The SCA Framework currently supports the
implementation of tasks in the C++ and C# languages.
SCAITask interface
All task objects must implement the SCAITask interface. The SCAITask
interface has a single method, execute(), which must be implemented by the
user. The code contained in this method will be called when the task is
executed.
SCAITask interface inherits from the SCAIBaseTask interface. This interface
provides a number of methods that are used by the TaskManager to process the
task and by the developer to query the task for its status, errors and
outputs. Developers do not need to implement the methods in this interface.
The SCA Framework provides a set of base classes that developers should use
which implement these methods.

522
SCA Framework User Documentation Task Manger

Inheritance diagram for SCA::Framework::TaskManager::SCAITask:

Detailed Description
Interface that all task objects processed by the TaskManager must implement

When implementing tasks, developers only need to implement the execute()


method which performs the actual work required by the task. The
implementation for all of the methods in the inherited base interfaces will
be provided by the SCA Framework.

Member Function Documentation

void execute ()

Method used to implement the business logic for the task.

SCAIBaseTask interface
SCAITask interface inherits from the SCAIBaseTask interface. This interface
provides a number of methods that are used by the TaskManager to process the
task and by the developer to query the task for its status, errors and
outputs. Developers do not need to implement the methods in this interface.
The SCA Framework provides a set of base classes which implement these
methods. These base classes should be used by the developer when they
implement their task objects.
Inheritance diagram for SCA::Framework::TaskManager::SCAIBaseTask:

Detailed Description
This interface provides methods used to manage an individual task.
Normally the developer of the task does not need to implement any of the
methods in SCAIBaseTask interface. The SCA Framework provides a default
implementation that should be used instead.
Some of the methods in this interface are intended to be used by the
implementation of execute() method in the task as follows.

523
SCA Framework User Documentation Task Manger

Get input arguments


Set task progress
Set task output values
Set task error information
Check if the task has been canceled

Other methods are intended to be used by the clients of the TaskManager as


follows.
Get the status of the task
Get the task output values
Get the task error information
Set the event channels used by the task
Cancel the execution of the task
Wait for the task to finish executing

A few of the methods are intended only for use by the TaskManager and should
not be called by the user.

Member Function Documentation

void setInput (in SCAAnySequence input)

Sets the input arguments for the task.


This method is normally called by the client as part of the initialization of
the task object before it is scheduled with the TaskManager.
Parameters:
in input Task input values

SCAAnySequence getInput ()

Returns any input arguments for the task.


This method is normally called by the implementation of the execute() method
in the task to retrieve the input arguments when it is executed.
Returns:
SCAAnySequence Task input arguments.

void setOutput (in SCAAnySequence output)

Sets the output values for the task.


This method is normally called by the implementation of the execute() method
in the task to return any output values when the execution of the task is
complete.
Parameters:
in output Task output values

524
SCA Framework User Documentation Task Manger

SCAAnySequence getOutput ()

Returns any output values for the task.


This method is normally called by the client after the task is finished
executing to retrieve its output values.
Returns:
SCAAnySequence Task output values.

TaskStatus getStatus ()

Returns the current status for the task.


This method is normally called by the client to determine the current status
of the task.
Returns:
TaskStatus Current status for the task

void setProgress (in SCAReal64 progress)

Sets the progress indicator for the task.


This method should be periodically called by the implementation of the
execute() method in the task to indicate the percentage of work that has been
performed. There are two methods that clients of the TaskManager can use to
monitor the progress of a task. It can make periodic calls to the
getProgress() method on the task or it can register a channel using the
setProgressChannel() method and use an EventManager listener to receive
EID_PROGRESS events.
Parameters:
in progress The percentage of the task execution
processing that has already been completed.
Normally the range will be a value between
0.0 and 1.0 but the actual values used are
left to the user.

SCAReal64 getProgress ()

Returns the current progress indicator for the task.


This method is normally called by the client to determine the current
progress of the task. Alternatively, the client can register a channel using
the setProgressChannel() method and use an EventManager listener to receive
EID_PROGRESS events.
Returns:
SCAReal64 Current progress for the task which is the percentage of the task execution processing
that has already been completed. Normally the range will be a value between 0.0 and 1.0 but the
actual values used are left to the user.

void setErrorInfo (in SCAResult info)

Sets the error information for the task.

525
SCA Framework User Documentation Task Manger

If the implementation of the execute() method in task encounters an error, it


should use this method to indicate the information about the error. If no
error information is set, the TaskManager will assume the task finished
successfully. If the task execution throws an uncaught exception, the
TaskManager will catch the exception and call setErrorInfo() with the
formated exception description.
Parameters:
in info Error information for the task

SCAResult getErrorInfo ()

Returns the current error information for the task.


This method is normally called by the client to retrieve the error
information if the task status indicates it finished with an error.
Returns:
SCAResult Current error information for the task

SCAUInt64 getTaskID ()

Returns the ID for the task.


The TaskManager assigns a unique ID to every task that is scheduled with the
queue() method or executed with the runNow() method. These IDs are used to
identify the tasks in logger messages and events processed by the
TaskManager.
Returns:
SCAUInt64 The task ID

void setProgressChannel (in SCAInt64 channelID)

Registers a channel that an application can use to monitor progress events


for an executing task.
If the client wants to monitor the progress of a task using events rather
then directly calling the SCAITask getProgress() method, it should create an
EventManager channel and register it with the task. Clients interested in
monitoring the progress must register an event listener with the EventManager
for this channel.
As the task executes, it should call the setProgress() method to indicate its
progress. For each of these calls, the TaskManager will post an EID_PROGRESS
event on the registered channel indicating the progress. Each EID_PROGRESS
event contains the task ID and name which can be used to identify which task
it is for.
The channel used for progress events may be the same channel that is used for
cancel events and it may be shared between multiple task objects.
Parameters:
in channelID EventManager channel ID

SCAInt64 getProgressChannel ()

Returns the ID for the current registered progress channel for the task.

526
SCA Framework User Documentation Task Manger

Returns:
SCAInt64 ID for Current progress channel for the task

void setCancelChannel (in SCAInt64 channelID)

Registers a channel that an application can use to signal the TaskManager


that a task is to be canceled
If the client wants to trigger the cancellation of a task by posting an event
instead of directly calling to the SCAITask cancel() method, it should create
an EventManager channel and register it with the task. When this channel is
registered, the TaskManager will set up a listener which will process
EID_CANCEL events and set the tasks status to STATUS_CANCELLED when received.
When the client wants to cancel a task, it can post an EID_CANCEL event on
this channel. Each EID_CANCEL event contains the task ID which is be used to
identify which task it is for.
As the task executes, it is responsible for periodically calling the
isCancelled() method to check if it has been canceled. If it has been
canceled it should clean things up and exit.
The channel used for cancel events may be the same channel that is used for
progress events and it may be shared between multiple task objects.
Parameters:
in channelID EventManager channel ID

SCAInt64 getCancelChannel ()

Returns the ID for the current registered cancel channel for the task.

Returns:
SCAInt64 ID for current cancel channel for the task

SCAResult cancel ()

Cancels a task.

Calling the cancel() method on a task sets the tasks status to


STATUS_CANCELLED. If the task is still in the TaskManager queue the task will
be canceled before it is eventually scheduled for execution. If the task is
already executing, the task itself must perform the cancellation. To do this,
the task is responsible for periodically calling the isCancelled() method to
check if it has been canceled. If it has been canceled it should clean things
up and exit.

Tasks can also be canceled by registering a channel using the


setCancelChannel() method with the task. Then to cancel the task the client
can post an EID_CANCEL event on this channel.
Returns:
SCAResult Status of the cancel request

527
SCA Framework User Documentation Task Manger

SCABool isCancelled ()

Checks if a task has been canceled.


This method will return true if the current status is STATUS_CANCELLED or
STATUS_CANCELLING. This method should be periodically called by the
implementation of the execute() method in the task to check if it has been
canceled. If it has been canceled it should clean things up and exit.
Returns:
SCABool Flag indicating if the task has been scheduled for cancellation.

SCAResult wait (in SCABool waitInQueue)

Forces the current thread to wait until the task has finished executing.
If the current state of the task is STATUS_EXECUTING or STATUS_CANCELLING,
the current thread will wait until the task has completed. If the value of
the waitInQueue parameter is true, then the current thread will also wait if
the object has a status of STATUS_QUEUED meaning it is still in the queue
waiting to execute. If the current status or the value of the waitInQueue
parameter does not allow the call to wait, an appropriate SCAResult value
will be returned.
If multiple threads are waiting for the same task, they will all be notified
when the task finishes. The notification for each thread happens sequentially
and in no particular order.
Returns:
SCAResult Status of the wait request

void setStatus (in TaskStatus status)

Sets the status for the task.


This method should not be called by the developer. It is used internally by
the TaskManager to manage the status of the task.
Parameters:
in status Task status.

void setImplName (in SCAUString taskName)

Sets a name for the task.


This method should not be called by the developer. It is used internally by
the TaskManager to set the name of a task. The client provides the task name
in the queue() or runNow() methods. The task name is used for logging
messages and in events processed by the TaskManager.
Parameters:
in taskName Name given to the task.

void internal_notify ()

Notify threads waiting for the task to finish.

528
SCA Framework User Documentation Task Manger

This method should not be called by the developer. It is used internally by


the TaskManager to notify threads waiting for the task to finish.

void setQObjID (in SCAUInt64 id)

Set the queue ID for a task.


This method should not be called by the developer. It is used internally by
the TaskManager to process the canceling of tasks that are still in the
queue.

TaskStatus enum
Describes the different states that a task can have.
Enumerator:
STATUS_INITIALIZED Default status of a newly created task.
STATUS_QUEUED The task is queued and is waiting for an available thread. This is before the
execute() method is called. Task objects in this state can be queued again and if so will inherit the
new priorities.
STATUS_EXECUTING The task is currently executing the execute() method. Task objects in
this state cannot be queued again.
STATUS_CANCELLING The cancel() method has been called while the Task was executing.
The task is still in the execute() method because it has not finished the processing of the cancel
request yet. Task objects in this state cannot be queued again.
STATUS_CANCELLED The task was successfully canceled. The task processed the cancel
request and the object can be queued again.
STATUS_DONE The task finished successfully and the object can be queued again.
STATUS_FAILED The task finished with errors and the object can be queued again.

SchedulePriority enum
Describes the different scheduling priority values that a queued task can
have
Enumerator:
SCHEDPRI_NORMAL Normal priority.
SCHEDPRI_LOW Low priority.
SCHEDPRI_HIGH High priority.

ExecutePriority enum
Describes the different execution priority values that a queued task can have
Enumerator:
EXECPRI_1
EXECPRI_2
EXECPRI_3
EXECPRI_4
EXECPRI_5

529
SCA Framework User Documentation Task Manger

EXECPRI_6
EXECPRI_7
EXECPRI_8
EXECPRI_9
EXECPRI_10

LoggingLevel enum
Describes the different levels of logging supported by the TaskManager.
Enumerator:
LOGGING_NONE No logging is done.
LOGGING_NORMAL Log when tasks are queued, started and finish.
LOGGING_HIGH Logs additional information intended for troubleshooting.

EventIds enum
Values of the event IDs for the various events posted by the TaskManager.
Enumerator:
EID_STATUS ID for status events which will contain a StatusEvent structure for the event data.
EID_PROGRESS ID for progress events which will contain a ProgressEvent structure for the
event data
EID_CANCEL ID for cancel events which will contain an integer task ID for the event data.

ProgressEvent structure

Detailed Description
This structure contains the data that is provided in EID_PROGRESS events.

Member Data Documentation

SCAInt32 taskID
The TaskManager assigned task ID for the task generating the event.

SCAUString taskName
The user assigned task name for the task generating the event.

SCAReal64 progress
The percentage of the task execution processing that has already been completed. Normally the range
will be a value between 0.0 and 1.0 but the actual values used is left to the user.

StatusEvent structure

530
SCA Framework User Documentation Task Manger

Detailed Description
This structure contains that data that is provided in EID_STATUS events.

Member Data Documentation

SCAInt32 taskID
The TaskManager assigned task ID for the task generating the event.

SCAUString taskName
The user assigned task name for the task generating the event.

TaskStatus status
The new status for the task.
SCAInt64 cancelID
The ID for the registered cancel channel for the task.
SCAInt64 progressID
The ID for the registered progress channel for the task.

21.3. Implementing user tasks in C++


For C++, the SCA/TaskManager/SCATaskBase.h header file is provided which
contains the implementation for the SCATaskImpl base class that should be
used to implement task objects. The base class implements the following
interfaces.
SCA::Framework::TaskManager::SCAITask
SCA::Framework::SCAIEventListener
SCA::SCAIService
To implement a task object you define your own class which inherits from
SCATaskImpl. The only method that this class must implement is the execute
method of the SCAITask interface. The following is a simple example of the
implementation of a task object.
#include "SCA\TaskManager\SCATaskBase.h"

class MyTask : public SCATaskImpl {


public:
MyTask(){
}
~MyTask() {
}
SCAVoid execute() {
// Business logic goes here
}
};

531
SCA Framework User Documentation Task Manger

Currently this is the only form of implementation of task objects that is


supported. The implementation of task objects using the subservice
declaration in the SDL files for SCA services is not supported.
The implementation of the getInterface method in the SCATaskImpl only knows
about the SCA Framework provided interfaces that it implements. There may be
situations where you will want the task object to implement some other
interfaces. To do this you will need to provide your own implementation of
the getInterface method which will handle the casting to these additional
interfaces. The following example shows what the getInterface method would
look like if your task also implemented the SCAITest interface.
SCAInt32 getInterface(const SCAUUID& uuid, SCAVoid**iface) {
if ( uuid == SCAITest::getUUID() ) {
*iface = static_cast< SCAITestInterface* >(this);
return 0;
}
return getInternalInterface(uuid,iface);
}

21.4. Implementing user tasks in C#


For C#, the SCA Framework provides the implementation for the managed version
of the SCATaskImpl base class that should be used to implement task objects.
The base class implements the following interfaces.
[Link]
[Link]
[Link]
To implement a task object you define your own class which inherits from
SCATaskImpl. The only method that this class must implement is the execute
method of the SCAITask interface. The following is a simple example of the
implementation of a task object.
using [Link];

class MyTask : SCATaskImpl {


public MyTask() {
}
public override void execute() {
// Business logic goes here
}
}

Currently this is the only form of implementation of task objects that is


supported. The implementation of task objects using the subservice
declaration in the SDL files for SCA services is not supported.

21.5. TaskManager Service


The TaskManager provides the ability to run and manage a set of asynchronous tasks running in different
threads. The TaskManager allows users to execute tasks in two different ways.
Using an available thread from a pool of worker threads
Using a dedicated thread.
Each time a task is executed a new task ID is provided. This task ID is
returned from the queue() and runNow() methods. The task ID can also be
retrieved directly from the task object using the getTaskID() method. The

532
SCA Framework User Documentation Task Manger

task ID is used to identify the task in the events processed by the


TaskManager and in its log entries.

SCAITaskManager interface
Inheritance diagram for SCAITaskManager:

Detailed Description
This is the main interface for the TaskManager. It is used to configure the
TaskManager and to schedule asynchronous tasks to be run.

Member Function Documentation

SCAResult queue (in SCAITask task, in SCAUString taskName, in SchedulePriority


schedPriority, in ExecutePriority execPriority, out SCAUInt64 taskID)

Adds an asynchronous task to the TaskManager queue to be executed when a


worker thread becomes available
The schedPriority parameter sets the priority used for scheduling tasks. This
priority is used to select the next task from the queue to execute when a
worker thread becomes available.
The execPriority parameter sets the priority used for executing tasks. This
priority is a hint used by the OS to schedule CPU resources on the machine.
Parameters:
in task Task to be queued
in taskName Name of the task that is used in logger
messages and in events published by the
TaskManager.
in schedPriority Task priority used to control the order that
queued tasks are scheduled for execution.
in execPriority Execution priority given to the worker thread
on which the task is assigned.
out taskID Unique ID assigned to the task.

Returns:
SCAResult Status of call

SCAResult runNow (in SCAITask task, in SCAUString taskName, in ExecutePriority


execPriority, out SCAUInt64 taskID)

Starts the execution of an asynchronous task immediately using a dedicated


thread

533
SCA Framework User Documentation Task Manger

Unlike the queue() method, the runNow() method will cause the input task to
be run immediately instead of waiting for an available worker thread. A
separate pool of private threads is used to run these tasks. The size of this
pool will be dynamically increased if a thread is not currently available.
Use of this method should be limited to tasks that do not require a
significant amount of resources since it can cause an over-subscription
condition that may lead to thrashing.
The runNow() method only guarantees that a new thread will be created
instantly but the Operating System is responsible for ultimately giving CPU
time for each thread to run. The execPriority parameter can be used to
control this scheduling.
Parameters:
in task Task to be executed
in taskName Name of the task that is used in logger
messages and in events published by the
TaskManager.
in execPriority Execution priority given to the worker thread
on which the task is assigned.
out taskID Unique ID assigned to the task.

Returns:
SCAResult Status of call

SCAResult setLoggingLevel (in LoggingLevel level)

Sets the logging level to be used by the TaskManager


The default logging level is LOGGING_NONE.
Parameters:
in level Logging level to be used.

Returns:
SCAResult Status of call

LoggingLevel getLoggingLevel ()

Returns the logging level currently used by the TaskManager

Returns:
LoggingLevel Current logging level

SCAResult setEventPublishingStatus (in SCABool status)

Controls whether the TaskManager will publish events describing tasks as they
are executed
If set to true, the TaskManager will publish EID_STATUS events to the
[Link] domain to indicate when tasks have been queued,
scheduled, canceled and finished. The default is not to publish events.
This method has no effect on the use of event Channels within individual
event objects to use progress and cancel events.

534
SCA Framework User Documentation Task Manger

NOTE: This method registers the TaskManager domain with the EventManager.
Therefore this method has to be called before the domain ID for TaskManager
can be requested by the application.
Parameters:
in status Logging level to be used

Returns:
SCAResult Status of call

SCABool getEventPublishingStatus ()

Returns the event publishing status of the TaskManager.

Returns:
LoggingLevel Current event publishing status

SCAResult setThreadPoolSize (in SCAInt64 size)

Sets the size of the pool of worker threads used for queued tasks
The worker thread pool size can only be set before any tasks have been queued
or run by the TaskManager. Once any tasks have been processed, the thread
pool size is fixed and cannot be changed. Since the TaskManager internally
uses the Intel TBB package for thread scheduling, the same restriction
applies to calls made directly to TBB that will trigger the initialization of
its thread pool, like tbb::task_scheduler_init. If any of these calls have
been made this method will have no effect.
Parameters:
in size Size of thread pool

Returns:
SCAResult Status of call

SCAInt64 getThreadPoolSize ()

Returns the size of the pool of worker threads used for running queued tasks
The pool of worker threads is used to run tasks scheduled with the queue()
method.
Returns:
SCAInt64 Size of thread pool

SCAInt64 getNumberOfDedicatedThreads ()

Returns the number of threads used to run dedicated tasks.


These threads are created when requests are made to run tasks on a dedicated
thread using the runNow() method instead of using the queue() method. When a
task using one of these threads is finished executing, the thread will be
returned to a pool to be used for future requests. The threads are killed
when the TaskManager is shut down.

535
SCA Framework User Documentation Task Manger

Returns:
SCAInt64 Number of currently created dedicated threads

21.6. Scheduling tasks to run


The following are the basic steps required to schedule a task to run.
Get a new instance of a task object or reuse an existing one
Set any input parameters
Schedule the task to run with either the queue() or runNow() method.
When the task has finished executing
Get status of task
If task executed successfully, get any task outputs
If task execution failed, get the detailed error information
In general, task objects should be fully initialized with their required data
before you schedule them to execute. This is because once they have been
scheduled you have little control over the relative timing between the thread
that scheduled the task and the thread that executes the task. This means
that calls to setInput(), setProgressChannel() and setCancelChanel() should
be made before the call to queue() or runNow().
Task scheduling priority
Task scheduling priorities are defined by the SchedulePriority enumerator
which contains 3 levels, SCHEDPRI_HIGH, SCHEDPRI_NORMAL and SCHEDPRI_LOW. The
scheduling priority is used when picking the next task to execute when a
worker thread becomes available. Once the tasks are executing, the scheduling
priority has no affect.
Task execution priority
To control the priority that is given to a task once it has started executing
on a thread, the queue() and runNow() methods provide a separate execution
priority. The execution priorities are defined by the ExecutePriority
enumerator which contains 10 levels, EXECPRI_1,…,EXECPRI_10. It is important
to understand that the execution priority is only a hint used by the OS to
schedule the available threads it has on the available CPUs on the machine.
How the OS uses the priority varies between the different operating systems.
The following table shows the mapping used for the various task execution
priorities to the Windows and Linux native thread priorities.

TaskManager
Linux Thread
Execution Windows Native Priority Value
Nice Value
Priority
EXECPRI_1 THREAD_PRIORITY_LOWEST -4
EXECPRI_2 THREAD_PRIORITY_LOWEST -3
EXECPRI_3 THREAD_PRIORITY_BELOW_NORMAL -2
EXECPRI_4 THREAD_PRIORITY_BELOW_NORMAL -1
EXECPRI_5 THREAD_PRIORITY_NORMAL 0
EXECPRI_6 THREAD_PRIORITY_NORMAL 1
EXECPRI_7 THREAD_PRIORITY_ABOVE _NORMAL 2
EXECPRI_8 THREAD_PRIORITY_ABOVE _NORMAL 3

536
SCA Framework User Documentation Task Manger

EXECPRI_9 THREAD_PRIORITY_HIGHEST 4
EXECPRI_10 THREAD_PRIORITY_HIGHEST 5

Executing tasks using the thread pool


The TaskManager maintains a pool of worker threads that is used to run the
queued tasks. To schedule a task to run using one of these threads you use
the queue() method. This method takes 5 parameters.
1. The SCAITask interface for the task to be executed.
2. The name of the task which is used to identify the task in events
processed by the TaskManager and in its log entries. This name is also
returned when the SCAIService::getImplName() method on the task object
is called.
3. Scheduling priority for the task which is defined by the
SchedulePriority enumerator.
4. Execution priority for the task which is defined by the ExecutePriority
enumerator.
5. An output parameter with the task ID which is a unique number assigned
to the task by the TaskManager when it is scheduled.
Chronologically it is hard to predict when a task in the queue will be
executed. This is a function of the number of tasks waiting in the queue,
their scheduling priority and the amount of time that the currently running
tasks will take. This means users should not use queue() to execute tasks
that are time critical. Instead the runNow() method should be used for these
tasks.
The following example shows how a task object can be created, initialized,
and scheduled.
C++
SCAITask spTask = SCAITask(new MyTask());
SCAAnySequence input;
input.push_back(SCAAny(2.345e+01));
spTask->setInput(input);
SCAUInt64 id;
SCAResult rstat = tm->queue(spTask,"Task1",SCHEDPRI_NORMAL,EXECPRI_5,id);

C#
SCAITask spTask = new MyTask();
SCAAnySequence input = new SCAAnySequence();
[Link](new SCAAny(1.23,"SCA.SCAReal64"));
[Link](input);
ulong id;
SCAResult rstat = [Link](spTask,"Task1",SchedulePriority.SCHEDPRI_NORMAL,
ExecutionPriority.EXECPRI_5,out id);

Controlling the size of the thread pool


The default size of the pool of worker threads is set to the number of cores
available on the local machine minus one. You have the ability to set the
thread pool size using the setThreadPoolSize() method in the SCAITaskManager
interface.
It is important to remember that the worker thread pool size can only be set
before any tasks have been queued or run by the TaskManager. Once any tasks
have been processed, the thread pool size is fixed and cannot be changed.

537
SCA Framework User Documentation Task Manger

Since the TaskManager internally uses the Intel TBB package for thread
scheduling, the same restriction applies to calls made directly to TBB that
will trigger the initialization of its thread pool, like
tbb::task_scheduler_init(). If any of these calls have been made then a call
to setThreadPoolSize() will also have no effect.

Executing tasks using dedicated threads


Tasks executed using runNow() get dedicated threads assigned to them
immediately. The TaskManager maintains a separate pool of threads to run
these tasks. The size of this queue will be dynamically adjusted as required
to support the number of simultaneous threads requested. When running tasks
on dedicated threads you should be careful to avoid over-subscription
conditions because these threads are sharing the same finite machine
resources that are being used by tasks running in the normal thread pool. As
a result, tasks run with the runNow() method should generally be of short
duration or not consume a lot of system resources.
The runNow() method takes 4 parameters.
1. The SCAITask interface for the task to be executed.
2. The name of the task which is used to identify the task in events
processed by the TaskManager and in its log entries. This name is also
returned when the SCAIService::getImplName() method on the task object
is called.
3. Execution priority for the task which is defined by the ExecutePriority
enumerator.
4. An output parameter with the task ID which is a unique number assigned
to the task by the TaskManager when it is scheduled.
Note the parameters to the runNow() method are the same as those for the
queue() method except there is no scheduling priority because these tasks are
scheduled to run immediately and not added to a queue.
The following example shows how a task object can be created, initialized,
and scheduled.
C++
SCAITask spTask = SCAITask(new MyTask());
SCAAnySequence input;
input.push_back(SCAAny(2.345e+01));
spTask->setInput(input);
SCAUInt64 id;
SCAResult rstat = tm->runNow(spTask,"Task1",EXECPRI_5,id);

C#
SCAITask spTask = new MyTask();
SCAAnySequence input = new SCAAnySequence();
[Link](new SCAAny(1.23,"SCA.SCAReal64"));
[Link](input);
ulong id;
SCAResult rstat = [Link](spTask,"Task1",ExecutionPriority.EXECPRI_5,id);

TBB compatibility
Internally the TaskManager uses the TBB ThirdParty package to manage the
thread pool used to run tasks. This means that code used in the application
which utilizes the various TBB supplied algorithms can safely coexist with

538
SCA Framework User Documentation Task Manger

tasks scheduled by the TaskManager without concern about over-subscribing the


available resources.

21.7. Task status


As a task goes through the process of being queued and executed, it maintains
a status indicator which describes its current state. The various states that
a task may have are defined by the TaskStatus enum.
STATUS_INITIALIZED Default status of a newly created task.
STATUS_QUEUED The task is queued and is waiting for an available
thread. This is before the execute() method is called.
Task objects in this state can be queued again and if
so will inherit the new priorities.
STATUS_EXECUTING The task is currently executing the execute() method.
Task objects in this state cannot be queued again.
STATUS_CANCELLING The cancel() method has been called while the Task
was executing. The task is still in the execute()
method because it has not finished the processing of
the cancel request yet. Task objects in this state
cannot be queued again.
STATUS_CANCELLED The task was successfully canceled. The task
processed the cancel request and the object can be
queued again.
STATUS_DONE The task finished successfully and the object can be
queued again.
STATUS_INITIALIZED Default status of a newly created task.

The following are examples of how the state of a task will change for typical
processing flows.
The task runs successfully:
STATUS_INITIALIZED
TaskManager adds task to queue
STATUS_QUEUED
Task is selected from queue to run – execute() method is called
STATUS_EXECUTING
Task finishes executing and returns from execute() method
STATUS_DONE
If an exception was thrown while in the execute() method:
STATUS_INITIALIZED
TaskManager adds task to queue
STATUS_QUEUED
Task is selected from queue to run – execute() method is called
STATUS_EXECUTING
Exception is thrown during execution of task and caught by the TaskManager
STATUS_FAILED
The information in the exception will be formatted and stored in a SCAResult
value in the task object. This information can be retrieved by the client
using the getErrorInfo() method after the task has finished executing.
A task can also indicate it failed by calling the setErrorInfo() method
before it returns from the execute() method. If the SCAResult value provided
in this call contains any value other then SCASuccess, then the TaskManager

539
SCA Framework User Documentation Task Manger

will also set the status to STATUS_FAILED when the tasks returns from the
execute() method.
The task is cancelled while still in queue:
STATUS_INITIALIZED
TaskManager adds task to queue
STATUS_QUEUED
cancel() called before task is scheduled to executed
STATUS_CANCELLED
Task is eventually selected from queue to run, but because it was
canceled it is ignored
The task is cancelled while executing:
STATUS_INITIALIZED
TaskManager adds task to queue
STATUS_QUEUED
Task is selected from queue to run – execute() method is called
STATUS_EXECUTING
cancel() is called while task is executing
STATUS_CANCELLING
Task processes cancel request and returns from execute()
STATUS_CANCELLED

21.8. Life-cycle for task objects


In C++ the life-cycle of task objects is maintained using reference counting
which means that a task object will automatically be deleted when there are
no outstanding references to it. It is important to remember that the
TaskManager does not keep references to task objects after the task object
has finished executing. This means that if you wish to extract output and
error information from a task object when it has finished executing, you will
need to keep a reference to it in your code. Using this reference to the task
object, you can make calls on it to fetch this information.
The same basic rule exists for C# except it uses garbage collection rather
than reference counting to manage the life-cycle.
Reusing task objects
It is possible to reuse instances of task objects once they are no longer
being used by the TaskManager. If the task object has any of the following
status values then it may be rescheduled with the queue() or runNow()
methods.
STATUS_INITIALIZED
STATUS_DONE
STATUS_CANCELLED
STATUS_FAILED
If you reuse a task object, you need to make sure to reset any input, output,
error and progress information it held from its previous use before it is
rescheduled.

21.9. Detecting when tasks have finished


Since tasks scheduled to run with the TaskManager run asynchronously in the
background, you will need to take special actions if you wish to know when

540
SCA Framework User Documentation Task Manger

they have finished executing. Currently there are two different methods to
detect when a task has finished executing.
Explicitly waiting for tasks to finish
You can cause a thread to wait until a task finishes by calling the wait()
method on the task object. Any thread that has a reference to the task object
can call this method. When called, the method checks if the task has a status
of STATUS_EXECUTING, meaning the task’s execute() method is still being
processed, and if so the calling thread will go to sleep. When the task
finishes and returns from the execute() method, the sleeping thread will be
woken up. It is legal for multiple threads to be waiting for the same task to
finish executing. In this case the waking up of the threads happens
sequentially and there is no guarantee which thread will be awoken first.
The wait() method contains a Boolean waitInQueue parameter. When the
parameter is set to true, the caller will wait even if the task is still in
the queue. When set to false, the caller will only wait if the task is
executing.
Using TaskManager status events
You may also determine when tasks have finished executing by listening to
status events that are published by the EventManager. The details on doing
this are described in the Using TaskManager status events section later in
this chapter.

21.10. Cancelling tasks


The TaskManager supports the canceling of tasks after they have been queued.
There are two ways to cancel a task.

If you hold a reference to the task, you can call the cancel() method
on the task object to cancel it.
If a cancel channel has been registered with the task object and you
have the channel ID, you can send a CancelEvent event to cancel it. See
the Using cancel events section later in this chapter for details on
using this technique for cancelling tasks.

You can only cancel a task if it is in the queue waiting for execution or if
it is currently executing. If you try to cancel a task while it has any other
status, the cancel() method will return an error or the CancelEvent event
will have no effect.
Cancelling a task while still in queue
During the time a task is in the queue and waiting to execute, its status is
STATUS_QUEUED, you can call the cancel() method or send a CancelEvent event
to cancel it. In this case the status of the object is set to
STATUS_CANCELLED to make sure it will not be executed. The status transition
of the object for this case is as follows:
STATUS_INITIALIZED
TaskManager adds task to queue
STATUS_QUEUED
cancel() called before task is scheduled to executed
STATUS_CANCELLED

541
SCA Framework User Documentation Task Manger

Task is selected from queue to run, but because it is canceled it is


not run
Task objects that were canceled while they were in the queue can be
immediately rescheduled if needed.
Cancelling a task while executing
The cancelling of a task while it is executing has to be a cooperative action
between the code in the tasks execute() method and the TaskManager. This is
required because there is no way to preemptively kill a running thread. When
a client calls cancel() on an executing task or a CancelEvent event is sent,
the status in the task object is set to STATUS_CANCELLING. The code in the
execute() method should periodically call the isCancelled() method to
determine if the task was cancelled. If it was cancelled, it should clean up
and return from the execute() method. The task object should never exit or
kill the thread. After the code returns from the execute() method the
TaskManager will set the status to STATUS_CANCELLED. At this point the task
object can be rescheduled if needed.
Following is a summary of the status transition for this process:
STATUS_INITIALIZED
TaskManager adds task to queue
STATUS_QUEUED
Task is selected from queue to run – execute() method is called
STATUS_EXECUTING
cancel() is called while task is executing
STATUS_CANCELLING
Task processes cancel request and returns from execute()
STATUS_CANCELLED

21.11. Event publishing for TaskManager


The TaskManager support 3 types of events.
Status change events published by the TaskManager to
[Link] domain.
Progress events published by tasks to notify clients of progress updates.
Cancel events published by clients and processed by task objects to cancel
themselves.
These events are identified by the EventIds enumerator.
ID for status events which will contain a StatusEvent structure for the
EID_STATUS
event data.
ID for progress events which will contain a ProgressEvent structure for
EID_PROGRESS
the event data
ID for cancel events which will contain an integer task ID for the event
EID_CANCEL
data.

Using status events


TaskManager can be configured to publish events to notify registered
listeners of status changes to tasks. Please see the EventManager chapter for
the details on how event listeners can be registered. The current status of a
task can also be retrieved at any time by calling its getStatus() method.
Event publishing in the TaskManager must be enabled by calling the
setEventPublishingStatus(true) method. The default setting is for no status

542
SCA Framework User Documentation Task Manger

events to be published. All status events published by the TaskManager are


sent to the [Link] domain.
The SCAEvent structure for status events contains the following values:
pID - ID for [Link] domain
eID - EID_STATUS value defined in the EventIds enum
data - SCAAny value that contains a StatusEvent structure
The StatusEvent structure stored in the event data contains the following
members
taskID - Task ID assigned by the TaskManager when the task was
scheduled
taskName - Task name passed to the queue() or runNow() method
status - New task status
cancelID - The current cancel EventManager channel registered with the
task
progressID - The current progress EventManager channel registered with
the task
An example use of status events could be for an application to provide an
applet that shows the status of all asynchronous tasks. Using the cancel and
progress channel information provided in the events, the applet could also
show task progress and allow the user to cancel the tasks.
To receive these events the client must implement the SCAIEventListener
interface and register it with the EventManager. The following code shows an
example implementation for a listener in C++.
C++
char ListenerName[] = "StatusListener";
class SListener : SCAServiceObjectImpl1 <SCAIEventListener,ListenerName>
{
public:
SListener() { }
~SListener() { }
SCAResult handleEvent(const SCAEvent& scaevent) {
if ([Link] == EID_STATUS) {
StatusEvent sevent;
[Link] >>= sevent;
cout << "Listener: " << [Link]
<<" status updated to: ";
if ([Link] == STATUS_INITIALIZED)
cout << "STATUS_INITIALIZED." << endl;
else if ([Link] == STATUS_QUEUED)
cout << "STATUS_QUEUED." << endl;
else if ([Link] == STATUS_EXECUTING)
cout << "STATUS_EXECUTING." << endl;
else if ([Link] == STATUS_DONE)
cout << "STATUS_DONE." << endl;
return EVENT_HANDLED;
}
return EVENT_NOT_HANDLED;
}
};

543
SCA Framework User Documentation Task Manger

Using progress events


The base class implementation provided by the SCA Framework for tasks
provides the infrastructure to allow tasks to publish events to show their
progress. Unlike status events, these events are published through an
EventManager channel. This functionality is especially useful for updating a
UI progress bar. The progress bar would register a listener with the
appropriate channel and receive progress updates from the task.
To enable progress event publishing the client must use the EventManager to
create a channel and then register it with the task object using the
setProgressChannel() method. This processing should be done before the task
is queued.
In the execute() method the task implementation should periodically call the
setProgress() method with the appropriate progress represented by a SCAReal64
value. The meaning of the value is left to the application but a value with a
range of 0.0 to 1.0, which represents the percentage completion, is
appropriate. When setProgress() is called and a progress channel has been
registered, the base class implementation will publish an event with the
progress value.
The EventManager channel used for progress events does not have to be unique
for each task object. You can share a single channel between different task
objects if desired. The progress events published contain additional data in
them that allows the listeners to identify which of the tasks the event is
for. It is also possible to share the same channel between progress events
and cancel events which can simplify things as explained in the next section.
The SCAEvent structure for progress events contains the following values:
pID = ID for the registered event channel
eID = EID_PROGRESS value defined in the EventIds enum
data = SCAAny value that contains a ProgressEvent structure
The ProgressEvent structure stored in the event data contains the following
members
taskID - Task ID assigned by the TaskManager when the task was
scheduled
taskName - Task name passed to the queue() or runNow() method
progress - The SCAReal64 progress value
To receive these events the client must implement the SCAIEventListener
interface and register it with the EventManager. The following code shows an
example implementation for a listener in C++.
C++
charListenerName[] = "ProgressListener";
class PListener : SCAServiceObjectImpl1 <SCAIEventListener,ListenerName>
{
public:
// Constructors and Destructor
PListener() { }
~PListener() { }
SCAResult handleEvent(const SCAEvent& scaevent) {
if ([Link] == EID_PROGRESS) {
ProgressEvent pevent;
[Link] >>= pevent;
cout << "Progress Listener: " << [Link]
<<" progress is " << [Link] << endl;
return EVENT_HANDLED;
}

544
SCA Framework User Documentation Task Manger

return EVENT_NOT_HANDLED;
}
};

Using cancel events


There are two ways to cancel tasks. The client can directly call the cancel()
method on the task object or it can publish cancel events to an EventManager
channel. Cancel events differ from progress event because they work in the
opposite direction. In the case of progress events, the task object is
publishing the event and the client code provides the listener to receive the
events. For cancel events, the client code does the publishing and the task
object provides the listener. Once again, the implementation of the base
classes provided by the SCA Framework does this work for you.
To enable the handling of cancel events, the client must use the EventManager
to create a channel and then register it with the task object using the
setCancelChannel() method. This processing should be done before the task is
queued. It is OK to share the same channel between progress and cancel
events. This can be handy in cases like a UI progress bar implementation.
Since it already has the knowledge of the progress channel it could also use
it to implement a cancel button with little additional effort.
The SCAEvent structure for cancel events should contain the following values:
pID = ID for the registered event channel
eID = EID_CANCEL value defined in the EventIds enum
data = SCAAny value that contains the SCAUInt64 task ID of the task to
be canceled
The following is a C++ example showing how a cancel event can be sent by
client code.
SCAEvent cancelEvent;
[Link] = cancelChan;
[Link] = EID_CANCEL;
SCAAny param <<= id; // id is the task ID returned from queue() or runNow()
[Link] = param;
eventManager->publishEvent(cancelEvent,false);

NOTE: Since a new task ID is generated for every queue() and runNow() call,
clients should be careful to assign the correct ID in the cancel event after
they have queued the tasks.

21.12. Logging from the TaskManager


TaskManager provides logging capabilities for users. Logging can be used for
troubleshooting and for a chronologically sorted report.
Three levels of logging are supported:
LOGGING_NONE No logging is done
LOGGING_NORMAL Prints when tasks were queued, started to execute and finished
LOGGING_HIGH Logs additional information intended for troubleshooting

Logging is enabled for the TaskManager by calling the setLoggingLevel()


method on the TaskManager which takes a single argument, the logging level.
For the details on controlling where the logged messages go please see the
Logger Service chapter in the User's manual.

545
SCA Framework User Documentation

There are three general forms of the messages logged by the TaskManager. The
first form is for general messages relative to the overall behavior of the
TaskManager as shown in this example
62 Tue May 29 11:41:38 2012
--Event Publishing enabled.

The second form of logged messages related to the processing of individual


task objects. These messages will include the task ID and name for the task
objects affected.
62 Tue May 29 11:41:38 2012
id: 28 name: MyTask1 --Queuing the task. Changing status to STATUS_QUEUED.

The last form of logged messages shows how the individual threads are being
used. In addition to the task ID and name, these will also include the ID for
the thread assigned to the task.
1667 Tue May 29 11:41:39 2012
thread id: 7468 id: 31 name: MyTask3 --Starting to execute the task.
Status set to STATUS_EXECUTING.

546

You might also like