You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tuscany.apache.org by Jean-Sebastien Delfino <js...@apache.org> on 2006/08/10 18:24:44 UTC

Re: [C++] Initial support for new composite model

Andrew Borley wrote:
> Also, I get a NPE when running SCAGEN on the BigBank sample - everything
> seems to get happily generated though. The output is below - anyone 
> else see
> this?
>
> Pete - are you still using VC++6 for windows development? I have a 
> VC++7 SCA
> build working happily here if you want the patch.
>
> Andy
>
>
> $ java -jar $TUSCANY_SCACPP/bin/scagen.jar -dir . -output . -verbose
> Scagen processing SCA composite file
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\Accounts.composite
> Scagen processing C++ implementation header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl.h
> Scagen processing SCA componentType file
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl.componentType 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_AccountService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_AccountService_Proxy.h 
>
> Scagen creating SCA for C++ wrapper implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_AccountService_Wrapper.cpp 
>
> Scagen creating SCA for C++ wrapper header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_AccountService_Wrapper.h 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_accountData_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_accountData_Proxy.h 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_stockQuote_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountServiceImpl_stockQuote_Proxy.h 
>
> Scagen processing C++ implementation header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataServiceImpl.h
> Scagen processing SCA componentType file
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataServiceImpl.componentType 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataServiceImpl_AccountDataService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataServiceImpl_AccountDataService_Proxy.h 
>
> Scagen creating SCA for C++ wrapper implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataServiceImpl_AccountDataService_Wrapper.cpp 
>
>
> Scagen creating SCA for C++ wrapper header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\AccountDataServiceImpl_AccountDataService_Wrapper.h 
>
> java.lang.NullPointerException
>        at org.apache.tuscany.sca.cpp.tools.common.Options.set(Unknown
> Source)
>        at 
> org.apache.tuscany.sca.cpp.tools.common.CParsingTool.<init>(Unknown
> Source)
>        at 
> org.apache.tuscany.sca.cpp.tools.services.ServicesGenerator.<init>(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.ServicesGenerator.handleInterfaceHeader(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.ReferenceDomNodeHandler.createProxyForReference(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.ReferenceDomNodeHandler.handleNode(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.mapNodeToHandlerAndHandle(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.handleChildElements(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.handleNode(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.ComponentDomNodeHandler.handleNode(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.mapNodeToHandlerAndHandle(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.handleChildElements(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.handleNode(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.GenericDomNodeHandler.mapNodeToHandlerAndHandle(Unknown 
>
> Source)
>        at 
> org.apache.tuscany.sca.cpp.tools.services.DomHandler.handleDom(Unknown
> Source)
>        at 
> org.apache.tuscany.sca.cpp.tools.services.XMLFileActor.actOnFile(Unknown
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.CompositeOrFragmentFileHandler.actOnFile(Unknown 
>
> Source)
>        at
> org.apache.tuscany.sca.cpp.tools.services.DirectoryScanner.walkTree(Unknown 
>
> Source)
>        at org.apache.tuscany.sca.cpp.tools.services.Scagen.main(Unknown
> Source)
> Scagen processing C++ implementation header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl.h
> Scagen processing SCA componentType file
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl.componentType 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Proxy.h 
>
> Scagen creating SCA for C++ wrapper implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Wrapper.cpp 
>
> Scagen creating SCA for C++ wrapper header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Wrapper.h 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteWebService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_webService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_webService_Proxy.h 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteWebService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_webService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_webService_Proxy.h 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Proxy.h 
>
> Scagen creating SCA for C++ wrapper implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Wrapper.cpp 
>
> Scagen creating SCA for C++ wrapper header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_StockQuoteService_Wrapper.h 
>
> Scagen processing C++ interface header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteWebService.h
> Scagen creating SCA for C++ proxy implementation
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_webService_Proxy.cpp 
>
> Scagen creating SCA for C++ proxy header
> d:\tuscany\cpp\sca\samples\BigBank\Accounts\.\StockQuoteServiceImpl_webService_Proxy.h 
>
>

I'm getting the same NPE, didn't notice it before. If I comment out 
AccountDataService in the .composite file I'm not getting the NPE so it 
must be specific to this particular service or AccountDataService.h 
maybe? I have no idea why Options.set(...) would throw an NPE on ly with 
AccountDataService... I started to look at the scagen but having trouble 
understanding what it does. Could one of you post to the dev list a 
brief description of how scagen works?  Thanks.

-- 
Jean-Sebastien


---------------------------------------------------------------------
To unsubscribe, e-mail: tuscany-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: tuscany-dev-help@ws.apache.org


Re: [C++] Initial support for new composite model

Posted by Andrew Borley <aj...@gmail.com>.
I've followed the code through - it basically walks the .composite and
.componentType files and then the header files, converts this info into an
xml doc and the runs a set of stylesheets to create the proxy and wrapper
files.
I can take a look at this when I get time - it doesn't seem to be hurting at
the moment.

Andy


On 8/10/06, Pete Robbins <ro...@googlemail.com> wrote:
>
> I have to say I have never looked at the Java code but I have editted the
> stylesheets to fix problems.
>
> Cheers,
>
> --
> Pete
>
>

Re: [C++] Initial support for new composite model

Posted by Pete Robbins <ro...@googlemail.com>.
I have to say I have never looked at the Java code but I have editted the
stylesheets to fix problems.

Cheers,

-- 
Pete

Re: [C++] Initial support for new composite model

Posted by Pete Robbins <ro...@googlemail.com>.
>
>
> I'm getting the same NPE, didn't notice it before. If I comment out
> AccountDataService in the .composite file I'm not getting the NPE so it
> must be specific to this particular service or AccountDataService.h
> maybe? I have no idea why Options.set(...) would throw an NPE on ly with
> AccountDataService... I started to look at the scagen but having trouble
> understanding what it does. Could one of you post to the dev list a
> brief description of how scagen works?  Thanks.


Look what I found! >>


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>





-- 
Pete