summaryrefslogtreecommitdiffstats
path: root/sca-cpp/tags/cpp-stable-20060304/sca/Developers Guide.txt
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/tags/cpp-stable-20060304/sca/Developers Guide.txt')
-rw-r--r--sca-cpp/tags/cpp-stable-20060304/sca/Developers Guide.txt346
1 files changed, 346 insertions, 0 deletions
diff --git a/sca-cpp/tags/cpp-stable-20060304/sca/Developers Guide.txt b/sca-cpp/tags/cpp-stable-20060304/sca/Developers Guide.txt
new file mode 100644
index 0000000000..96b0476174
--- /dev/null
+++ b/sca-cpp/tags/cpp-stable-20060304/sca/Developers Guide.txt
@@ -0,0 +1,346 @@
+Tuscany SCA For C++ Developers Guide
+====================================
+
+Contents:
+ Developing Services in C++
+ Running C++ Services
+
+
+See cpp/build.txt in the parent directory or the cpp/sca/INSTALL file
+for build instructions.
+
+Building the tools
+------------------
+
+NOTE: this is built and installed by the build step above.
+
+Currently, there is only one tool: "scagen". It can be built using the
+ant build script at \tuscany\cpp\sca\tools\scagen\build.xml.
+The default target "all" will build the java jars, documentation,
+scripts and a zip file of the whole thing. This is all the ant
+build tasks apart from "test" which runs all the junit tests.
+
+The ant build script can be altered to add the junit tests to the
+default target. Replace the line
+
+<property name="junit.jar.folder" value="${basedir}/lib" />
+
+The "test" task was not included in "all" as it requires a
+junit jar file to run. This jar is available here:
+http://www.junit.org/index.htm testing has been done with
+Junit version 3.8.1.
+
+Running the scagen tool
+-----------------------
+
+The scagen tool user interface is quite basic in this initial release.
+It can be run from the scagen.jar file using "java -jar scagen.jar"
+or from small scripts - scagen.cmd for Windows and scagen.sh for Unix.
+The parameters are:
+ -dir <the path to the sca module root directory>
+ -output <the path to an output directory where the generated file will be placed>
+
+e.g.
+ scagen -dir c:\mymodules\module1 -output c:\mymodules\bld\module1
+
+What scagen does
+----------------
+
+The input directory passed to the scagen tools as
+the -dir parameter method is taken to be the SCA
+module root directory. All the sca.module and .fragment
+files in that directory are inspected to resolve all
+the <component/> elements within them.
+
+Each <component/> element found is inspected
+to see if it has a <implementation.cpp/> element within it.
+
+Each <implementation.cpp/> element should have a
+header attribute that represents a C++ header file
+that contains function prototypes for the C++
+implementation of the service. An optional class
+attribute can be used to select one class if more than
+one that is present in the header file. The default
+class is the one with the same name as the header file.
+The tool will verify that the implementation header
+contains an appropriate class prototype.
+
+The directory that contains the implementation header
+should also contain a matching .componentType file for
+the equivalent SCA component. So for example, a
+MyServiceImpl.h file would have a corresponding
+MyServiceImpl.componentType file in the same directory.
+
+Each componentType file is inspected for <service/>
+and <reference/> elements. For each <service/> element
+that is found that contains a <interface.cpp/> element
+within it,
+
+the header attribute of the <interface.cpp/> is taken
+as the filename of the C++ interface header for the
+SCA service. This C++ header file is opened and used
+as a means for specifying the SCA service resulting
+in an appropriate wrapper and proxy being generated
+for this service interface. Both method bodies and h
+eaders are generated in the given output directory.
+The processing of a <reference/> element is the same
+except that only a proxy header and implementation
+re generated.
+
+
+Getting started with the code
+-----------------------------
+
+The following is a list of tasks that are performed by the scagen tool
+for each task we will describe technically how it is accomplished and
+the location of the code that can be inspected/changed to alter the
+behaviour.
+
+Here are the tasks listed, below is a paragraph for each one:
+
+ o (Overall structure of the code)
+ o Walking the input directory
+ o Scanning the .module and .fragment files
+ o finding the C++ implementation headers
+ o finding/checking the classname in the C++ implementation headers
+ o find the matching .componentTemplate files
+ o going into the componentTemplate files to extract the interface header filenames
+ o going into the interface header files and parsing them to extract the method signatures
+ into a network of objects we can inspect.
+ o taking all the meta data stored as objects and building a DOM for XSLT processing
+ o using XSLT to produce a proxy header
+ o using XSLT to produce a proxy implementation
+ o using XSLT to produce a wrapper header
+ o using XSLT to produce a wrapper implementation
+
+
+Overall structure of the code
+-----------------------------
+
+There are two packages org.apache.tuscany.sca.cpp.tools.common and
+org.apache.tuscany.sca.cpp.tools.services. The ...common package is
+taken from some existing code that was also contributed to axis that
+was used to parse C++ code and do various tasks like insert trace.
+This code was repackaged and shipped as a tuscany package but there
+has been a desire not to change it significantly from the equivalent
+org.apache.axis.tools.common package to leave the door open for
+future convergence.
+
+Where the ...common package has been amended (for example to cope with
+namespaces better or the provision of an Options.reset method to reset a static
+variable and enable the tuscany junit tests to run independently) these
+have been flagged with a "Tuscany" comment. The ...common package basically
+provides two functions - 1) the ability to go into a directory (see DirectoryTree.java)
+and process files that fit a particular filter (e.g. "*.hpp") by passing them to
+implementer of the FileActor Interface (see the classes "Headers" for the
+actor that processes C++ headers and "XMLFileActor" for the file actor that
+processes the .componentType and sca.module/fragment files.)
+
+The ...services package contains the majority of code written afresh for the
+scagen tool including the subclasses of XMLFileActor (see ComponentTypeFileHandler.java
+and ModuleOrFragmentFileHandler.java) that are the classes that tie this
+package to the ...common package and which are called by the
+DirectoryTree walker.
+
+Walking the module root input directory
+---------------------------------------
+
+The main method of the scagen class creates an instance of
+"DirectoryScanner" and registers with it a file handler of
+type "ModuleOrFragmentFileHandler" for all files that end
+in ".module" or ".fragment". On calling the "walkTree" method
+on the scanner it will in turn call the actOnFile method on the
+ModuleOrFragmentFileHandler for appropriate files.
+
+Scanning the .module and .fragment files
+----------------------------------------
+
+The scanning of these files by the respective "ModuleOrFragmentFileHandler"
+and "ComponentTypeFileHandler" is mostly handled by the superclass
+"XMLFileActor". This class will recursively goes through the whole
+XML file and considers the name of the XML element it finds.
+"XMLFileActor" contains a map of element names to element handlers
+that will "flatten out" the structure of the XML file "above" the
+level of node we are interested in.
+
+So for example the ComponentTypeFile handler sets up the handlers
+map as follows:
+
+ GenericDomNodeHandler gdnh = new GenericDomNodeHandler();
+ handlers.put("componentType", gdnh);
+ handlers.put("interface.cpp", gdnh);
+ ServiceDomNodeHandler sdnh = new ServiceDomNodeHandler();
+ handlers.put("service", sdnh);
+
+ ReferenceDomNodeHandler rdnh = new ReferenceDomNodeHandler();
+ handlers.put("reference", rdnh);
+
+The majority of processing done by these DomNOdeHandlers is to
+place the attributes and values discovered into another map that
+maps an (static version of) the XPath of a value to the value itself.
+So for example "/componentType/service/interface.cpp/@header" might contain
+the current ("root to here") value of the header attribute of the current
+interface.
+
+Particular handlers for the "leaves" of this tree
+such as ServiceDomNodeHandler and ReferenceDomNodeHandler
+can then consume these values from the map without having
+to be concerned with the actual names of things,
+like the service name, appearing in the key. It should be
+understood though that there are multiple values placed in the map
+for one "key" as the processing works its way through the
+XML tree. For example the processing of a second component will
+overlay its data over the same keys as the first component.
+(After "wiping" the appropriate subtree.)
+
+Finding the C++ implementation headers
+--------------------------------------
+
+The "/module/component/implementation.cpp/@header" and
+is used to key into the name of the implementation header
+and this is opened directly and passed to the
+actOnFileMethod of a Headers object from the ...common package
+bypassing the DirectoryScanner code. The path is relative to
+the given (-dir option) module root directory.
+
+Finding/checking the classname in the C++ implementation headers
+-----------------------------------------------------------------
+
+This implementation header is not used to define the
+methods of the SCA service but rather is opened to check
+ any given implementation.cpp/@class attribute
+(or find out the name of the implementation class
+in the header if this is not specified in the XML. This
+is done using the same method that later parses the interface
+C++ headers into java objects - we just them inspect the
+class attribute of the "Signature" objects that represent the methods
+we find in the header.
+
+Find the matching .componentType files
+------------------------------------------
+
+By SCA convention we go to the same directory as the implementation
+files and look for the XXX.componentType files with the same name.
+A instance of the ComponentDOMNodeHandler handles the data in the
+Component Element and pre-creates a ComponentTypeFileHandler that
+will eventually be called to process the .componentType file. This
+object receives a number of "setParameter" calls to poke into it
+matadata that is available prior/outside the the actual .componentType
+file it will read.
+
+Go into the componentType files to extract the interface header filenames
+-----------------------------------------------------------------------------
+
+We open up the .componentTemplateFiles with exactly the same
+mechanism as we read the sca.module/fragment file (by creating
+a DOM and descending through it this time using a ComponentTypeFileHandler that it
+has had various data values ( e.g. the implementation class and namespace used later)
+poked into it. The ComponentTypeFileHandler itself has individual
+handlers for the service and reference XML/DOM element/nodes
+that is comes across (ServiceDomNodeHandler and ReferenceDomNodeHandler
+respectively). Each these handlers will pull out the name of
+a C++ interface header and use it to resolve the interface of the
+SCA Service.
+
+Parsing the interface header files for signatures
+-------------------------------------------------
+
+The Service/Reference DOM Node hander both call the
+ ServicesGenerator.handleInterfaceHeader(parameters, true);
+method, the second parameter is used to differentiate
+the call source as we don't need wrapper files for
+SCA references (just proxies).
+
+The ServicesGenerator uses the Headers file actor from
+the ...common package to create a List of Signature
+objects that describe the interface methods in the C++
+header.
+
+Take all the meta data stored as objects and build a DOM
+--------------------------------------------------------
+We now have a List of Signature objects and a map that
+represents the flattened information that we have pulled
+from the XML files in the ServiceGenerator class.
+We call a "createDOMofMethods" method
+to consolidate all this information into one DOM
+(this task should be split into more than one method as the
+signature/parameter list of the method is too large).
+
+Use XSLT to produce the output files (Proxy/Wrapper headers and Implementations)
+--------------------------------------------------------------------------------
+
+The ServicesGenerator.handleInterfaceHeader(parameters, forReference);
+method closes of with the code:
+
+ createProxyCPPFromDom(outputDir, dom);
+ createProxyHeaderFromDom(outputDir, dom);
+
+ if (!forReference) {
+ createWrapperCPPFromDom(outputDir, dom);
+ createWrapperHeaderFromDom(outputDir, dom);
+ }
+
+
+Each of the create methods sets up the output
+file name and a different XSLT transform and calls
+"createOutputFromDom" to transform/filter the data in the
+"model" that is held in our DOM of the data to a particular
+"view" as expressed in the C++ output file.
+
+The four XSLT style sheets are in rough order of the output
+file and this corresponds very roughly to a depth first descent
+of the DOM tree so, for example, we could have in a stylesheet:
+
+...
+ void* </xsl:text>
+ <xsl:value-of select="$class"/><xsl:text>::newImplementation()
+ {
+ return new </xsl:text><xsl:value-of select="../@implClass"/><xsl:text><xsl:text>(target);
+ }
+
+which would be output as:
+
+ void* MyClassImpl_MyClass_Proxy::newImplementation()
+ {
+ return new MyClassImpl(target)
+ }
+
+given appropriate valies for $class and "../@implClass" and
+$class might be defined to be:
+xsl:variable name="clazz">
+ <xsl:value-of select="../@implClass"/>
+ <xsl:text>_</xsl:text>
+ <xsl:value-of select="../@nameOfServiceOrReference"/>
+ <xsl:text>_Proxy</xsl:text>
+</xsl:variable>
+
+giving "MyClassImpl_MyClass_Proxy"
+
+The stylesheets can be found in the xsl subdirectory of the
+org.apache.tuscany.sca.cpp.tools.services package.
+
+Unit Testing Scagen Code Changes
+--------------------------------
+
+The junit unit test
+ /tuscany/cpp/sca/tools/scagen/
+ junit/org/apache/tuscany/sca/cpp/tools/junit/TestAllModulesTest.java
+
+will dynamically look for all the subdirectores of the directory
+path given by TuscanyTestCase.junit_modules and run the scagen
+tool on them as if they were modules roots.
+
+By convention an "expected_output" directory is located
+(see the CVS tree or the test program) and the actual
+and expected results compared. This testcase is thus a
+good first/basic regression test for any changes.
+
+New test cases can thus be added without having to write
+any new junit java code by by creating new SCA modules and
+the associated expected Scagen output - perhaps by using the tool
+initially and checking the output is satisfactory before copying
+it to the expected output directory at:
+
+/tuscany/cpp/sca/tools/scagen/junit/testoutput/<module>/expected_output
+where input data is taken from
+/tuscany/cpp/sca/tools/scagen/junit/testinput/modules/<module>