فهرست منبع

Merge pull request #6666 from rpastrana/HPCC-12606-MoveDESDLToOss

HPCC-12476 Move DESDL components to OSS HPCC-Platform

Reviewed-By: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 10 سال پیش
والد
کامیت
77873fd886
56فایلهای تغییر یافته به همراه14953 افزوده شده و 19 حذف شده
  1. 1 0
      esp/CMakeLists.txt
  2. 56 0
      esp/esdllib/CMakeLists.txt
  3. 2092 0
      esp/esdllib/esdl_def.cpp
  4. 200 0
      esp/esdllib/esdl_def.hpp
  5. 262 0
      esp/esdllib/esdl_def_helper.cpp
  6. 50 0
      esp/esdllib/esdl_def_helper.hpp
  7. 69 0
      esp/esdllib/esdl_transformer.hpp
  8. 1866 0
      esp/esdllib/esdl_transformer2.cpp
  9. 517 0
      esp/esdllib/esdl_transformer2.ipp
  10. 211 0
      esp/esdllib/params2xml.cpp
  11. 30 0
      esp/esdllib/params2xml.hpp
  12. 209 0
      esp/esdllib/wsexcept.cpp
  13. 1 0
      esp/scm/espscm.cmake
  14. 1 0
      esp/scm/smcscm.cmake
  15. 185 0
      esp/scm/ws_esdlconfig.ecm
  16. 2 0
      esp/services/CMakeLists.txt
  17. 76 0
      esp/services/esdl_svc_engine/CMakeLists.txt
  18. 2463 0
      esp/services/esdl_svc_engine/esdl_binding.cpp
  19. 347 0
      esp/services/esdl_svc_engine/esdl_binding.hpp
  20. 102 0
      esp/services/esdl_svc_engine/esdl_svc_engine.cpp
  21. 68 0
      esp/services/esdl_svc_engine/esdl_svc_engine.hpp
  22. 51 0
      esp/services/esdl_svc_engine/esdl_svc_engine_plugin.cpp
  23. 65 0
      esp/services/ws_esdlconfig/CMakeLists.txt
  24. 25 0
      esp/services/ws_esdlconfig/esdlconfig_errors.h
  25. 90 0
      esp/services/ws_esdlconfig/ws_esdlconfigplugin.cpp
  26. 1235 0
      esp/services/ws_esdlconfig/ws_esdlconfigservice.cpp
  27. 62 0
      esp/services/ws_esdlconfig/ws_esdlconfigservice.hpp
  28. 3 0
      esp/xslt/CMakeLists.txt
  29. 333 0
      esp/xslt/esdl2ecl.xslt
  30. 448 0
      esp/xslt/esxdl2xsd.xslt
  31. 895 0
      esp/xslt/roxie_page.xsl
  32. 2 1
      initfiles/componentfiles/configxml/@temp/CMakeLists.txt
  33. 67 0
      initfiles/componentfiles/configxml/@temp/esp_service_DynamicESDL.xsl
  34. 26 0
      initfiles/componentfiles/configxml/@temp/esp_service_WsSMC.xsl
  35. 1 0
      initfiles/componentfiles/configxml/CMakeLists.txt
  36. 13 0
      initfiles/componentfiles/configxml/buildsetCC.xml.in
  37. 3 0
      initfiles/componentfiles/configxml/cgencomplist_linux.xml
  38. 4 1
      initfiles/componentfiles/configxml/cgencomplist_win.xml
  39. 40 0
      initfiles/componentfiles/configxml/esdlsvcengine.xsd
  40. 1 1
      initfiles/etc/DIR_NAME/genenvrules.conf
  41. 1 0
      tools/CMakeLists.txt
  42. 6 10
      tools/esdlcmd-xml/CMakeLists.txt
  43. 84 0
      tools/esdlcmd/CMakeLists.txt
  44. 808 0
      tools/esdlcmd/esdl-publish.cpp
  45. 1 0
      tools/esdlcmd/esdl.install
  46. 1 0
      tools/esdlcmd/esdl.uninstall
  47. 459 0
      tools/esdlcmd/esdl2ecl.cpp
  48. 47 0
      tools/esdlcmd/esdlcmd.cpp
  49. 54 0
      tools/esdlcmd/esdlcmd.hpp
  50. 149 0
      tools/esdlcmd/esdlcmd_common.cpp
  51. 303 0
      tools/esdlcmd/esdlcmd_common.hpp
  52. 626 0
      tools/esdlcmd/esdlcmd_core.cpp
  53. 25 0
      tools/esdlcmd/esdlcmd_core.hpp
  54. 189 0
      tools/esdlcmd/esdlcmd_shell.cpp
  55. 26 0
      tools/esdlcmd/sourcedoc.xml
  56. 2 6
      tools/esdlcomp/CMakeLists.txt

+ 1 - 0
esp/CMakeLists.txt

@@ -26,4 +26,5 @@ HPCC_ADD_SUBDIRECTORY (smc "PLATFORM")
 HPCC_ADD_SUBDIRECTORY (test "PLATFORM")
 HPCC_ADD_SUBDIRECTORY (tools "CLIENTTOOLS")
 HPCC_ADD_SUBDIRECTORY (xslt "PLATFORM")
+HPCC_ADD_SUBDIRECTORY (esdllib "PLATFORM")
 

+ 56 - 0
esp/esdllib/CMakeLists.txt

@@ -0,0 +1,56 @@
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+################################################################################
+# Component: esdllib
+
+project( esdllib )
+
+include_directories (
+    ${HPCC_SOURCE_DIR}/esp/bindings/SOAP/xpp
+    ${HPCC_SOURCE_DIR}/system/xmllib
+    ${HPCC_SOURCE_DIR}/esp/bindings
+    ${HPCC_SOURCE_DIR}/esp/platform
+    ${HPCC_SOURCE_DIR}/system/include
+    ${HPCC_SOURCE_DIR}/esp/esdllib
+    ${HPCC_SOURCE_DIR}/system/jlib
+    ${HPCC_SOURCE_DIR}/system/security/shared
+    ${HPCC_SOURCE_DIR}/rtl/include #IXMLWriter
+    ${HPCC_SOURCE_DIR}/common/thorhelper #JSONWRITER
+)
+
+ADD_DEFINITIONS ( -D_USRDLL -DESDLLIB_EXPORTS )
+
+set ( SRCS
+    esdl_def.cpp
+    esdl_def_helper.cpp
+    esdl_transformer2.cpp
+    params2xml.cpp
+    ${HPCC_SOURCE_DIR}/esp/bindings/SOAP/xpp/xpp/xpputils.cpp
+    ${HPCC_SOURCE_DIR}/esp/services/common/wsexcept.cpp
+)
+
+HPCC_ADD_LIBRARY( esdllib SHARED ${SRCS}
+    ${HEADERS}
+)
+
+install ( TARGETS esdllib RUNTIME DESTINATION bin LIBRARY DESTINATION lib )
+
+add_dependencies ( esdllib jlib)
+
+target_link_libraries ( esdllib
+    jlib
+    xmllib
+    thorhelper
+)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2092 - 0
esp/esdllib/esdl_def.cpp


+ 200 - 0
esp/esdllib/esdl_def.hpp

@@ -0,0 +1,200 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef ESDLDEF_HPP
+#define ESDLDEF_HPP
+
+#include "jliball.hpp"
+#include "esp.hpp"
+#include "soapesp.hpp"
+#include "ws_ecl_client.hpp"
+#include "jqueue.tpp"
+
+#ifdef _WIN32
+ #ifdef ESDLLIB_EXPORTS
+  #define esdl_decl __declspec(dllexport)
+ #else
+  #define esdl_decl
+ #endif
+#else
+ #define esdl_decl
+#endif
+
+typedef enum EsdlDefTypeId_
+{
+    EsdlTypeElement,
+    EsdlTypeAttribute,
+    EsdlTypeArray,
+    EsdlTypeEnumDef,
+    EsdlTypeEnumRef,
+    EsdlTypeStruct,
+    EsdlTypeRequest,
+    EsdlTypeResponse,
+    EsdlTypeMethod,
+    EsdlTypeService,
+    EsdlTypeVersion,
+    EsdlTypeEnumDefItem
+} EsdlDefTypeId;
+
+#define DEPFLAG_COLLAPSE    (0x01)
+#define DEPFLAG_ARRAYOF     (0x02)
+#define DEPFLAG_STRINGARRAY (0x04)    // Set dynamically by gatherDependencies to indicate stylesheet should output
+                                    // an EspStringArray structure definition.
+
+interface IEsdlDefObject : extends IInterface
+{
+    virtual const char *queryName()=0;
+    virtual const char *queryProp(const char *name)=0;
+    virtual bool hasProp(const char *name)=0;
+    virtual int getPropInt(const char *pname, int def = 0)=0;
+    virtual void toXML(StringBuffer &xml, double version = 0, IProperties *opts=NULL, unsigned flags=0)=0;
+    virtual EsdlDefTypeId getEsdlType()=0;
+    virtual bool checkVersion(double ver)=0;
+    virtual bool checkFLVersion(double ver)=0;
+    virtual bool checkOptional(IProperties *opts)=0;
+    virtual IPropertyIterator* getProps()=0;
+};
+
+typedef IEsdlDefObject * IEsdlDefObjPtr;
+
+interface IEsdlDefObjectIterator : extends IInterface
+{
+    virtual bool        first(void)=0;
+    virtual bool        next(void)=0;
+    virtual bool        isValid(void)=0;
+    virtual unsigned    getFlags(void)=0;
+    virtual IEsdlDefObject& query()=0;
+    virtual IEsdlDefObjectIterator* queryBaseTypesIterator()=0;
+};
+
+interface IEsdlDefAttribute : extends IEsdlDefObject
+{
+};
+
+interface IEsdlDefElement : extends IEsdlDefObject
+{
+    virtual IProperties *queryRecSelectors()=0;
+    virtual IPropertyTree *queryPtdSelectors()=0;
+};
+
+interface IEsdlDefArray : extends IEsdlDefObject
+{
+    virtual IProperties *queryRecSelectors()=0;
+};
+
+interface IEsdlDefEnumDef : extends IEsdlDefObject
+{
+};
+
+interface IEsdlDefEnumRef : extends IEsdlDefObject
+{
+};
+
+interface IEsdlDefEnumDefItem : extends IEsdlDefObject
+{
+};
+
+interface IEsdlDefVersion : extends IEsdlDefObject
+{
+};
+
+interface IEsdlDefStruct : extends IEsdlDefObject
+{
+    virtual IEsdlDefObjectIterator *getChildren()=0;
+    virtual IEsdlDefObject *queryChild(const char *name, bool nocase=false)=0;
+};
+
+
+
+interface IEsdlDefMethod : extends IEsdlDefObject
+{
+    virtual const char *queryRequestType()=0;
+    virtual const char *queryResponseType()=0;
+    virtual const char *queryProductAssociation()=0;
+    virtual bool isProductDefault()=0;
+    virtual const char *queryLogMethodName()=0;
+    virtual const char *queryMethodFLReqFormat()=0;
+    virtual const char *queryMethodFLRespFormat()=0;
+    virtual const char *queryMethodName()=0;
+    virtual const char *queryMbsiProductAssociations()=0;
+    virtual int queryVariableLengthRecordProcessing()=0;
+    virtual int queryAllowMultipleEntryPerUnitNumber()=0;
+};
+
+interface IEsdlDefMethodIterator : extends IInterface
+{
+    virtual bool        first(void)=0;
+    virtual bool        next(void)=0;
+    virtual bool        isValid(void)=0;
+    virtual IEsdlDefMethod &query()=0;
+};
+
+interface IEsdlDefService : extends IEsdlDefObject
+{
+    virtual IEsdlDefMethodIterator *getMethods()=0;
+    virtual IEsdlDefMethod *queryMethodByName(const char *name)=0;
+    virtual IEsdlDefMethod *queryMethodByRequest(const char *reqname)=0;
+    virtual void methodsNamesToXML(StringBuffer& xml, const char* ver, IProperties* opts)=0;
+};
+
+interface IEsdlDefFile : extends IInterface
+{
+    virtual IEsdlDefObjectIterator *getChildren()=0;
+};
+
+interface IEsdlDefFileIterator : extends IIteratorOf<IEsdlDefFile>
+{
+};
+
+interface IEsdlDefinition : extends IInterface
+{
+    virtual void addDefinitionsFromFile(const char *filename)=0;
+    virtual void addDefinitionFromXML(const StringBuffer & xmlDef, const char * esdlDefName, int ver)=0;
+    virtual void addDefinitionFromXML(const StringBuffer & xmlDef, const char * esdlDefId)=0;
+
+    virtual IEsdlDefStruct *queryStruct(const char *name)=0;
+    virtual IEsdlDefObject *queryObj(const char *name)=0;
+    virtual IEsdlDefService *queryService(const char *name)=0;
+
+    virtual IEsdlDefFileIterator *getFiles()=0;
+
+    // A service name is required, the method name(s) provided must be part of the service
+    //
+    // To support the calculation and return of just the dependent elements for the given service and/or
+    // method(s). If provided with requestedVersion and requestedOptional parameters it will only return
+    // structure defs for those structures satisfying the request. Note that elements within structures
+    // will are not filtered by optional & version, as we can't modify the EsdlDefObjects in place.
+    //
+    virtual IEsdlDefObjectIterator *getDependencies( const char* service, const char* method, double requestedVer=0, IProperties *opts=NULL, unsigned flags=0  )=0;
+    virtual IEsdlDefObjectIterator *getDependencies( const char* service, StringArray &methods, double requestedVer=0, IProperties *opts=NULL, unsigned flags=0 )=0;
+    virtual IEsdlDefObjectIterator *getDependencies( const char* service, const char* delimethodlist, const char* delim, double requestedVer, IProperties *opts, unsigned flags )=0;
+
+    virtual IProperties *queryOptionals()=0;
+    virtual void setFlConfig(IPropertyTree* p)=0;
+    virtual IPropertyTree* getFlConfig()=0;
+    virtual bool hasFileLoaded(const char *filename)=0;
+    virtual bool hasXMLDefintionLoaded(const char *esdlDefName, int ver)=0;
+    virtual bool hasXMLDefintionLoaded(const char *esdlDefId)=0;
+};
+
+esdl_decl IEsdlDefinition *createNewEsdlDefinition(const char *esdl_ns=NULL);
+esdl_decl IEsdlDefinition *createEsdlDefinition(const char *esdl_ns=NULL);
+esdl_decl IEsdlDefinition *queryEsdlDefinition(const char *esdl_ns=NULL);
+esdl_decl void releaseEsdlDefinition(const char *esdl_ns=NULL);
+
+
+#endif //ESDLDEF_HPP

+ 262 - 0
esp/esdllib/esdl_def_helper.cpp

@@ -0,0 +1,262 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#pragma warning(disable: 4786)
+
+#include "xslprocessor.hpp"
+#include "esdl_def.hpp"
+#include "esdl_def_helper.hpp"
+
+typedef IXslTransform* IXslTransformPtr;
+typedef IProperties* IPropertiesPtr;
+
+
+typedef MapBetween<EsdlXslTypeId, EsdlXslTypeId, IXslTransformPtr, IXslTransformPtr> MapXslIdToTransform;
+typedef MapBetween<EsdlXslTypeId, EsdlXslTypeId, IPropertiesPtr, IPropertiesPtr> MapXslIdToProperties;
+
+
+class EsdlDefinitionHelper : public CInterface, implements IEsdlDefinitionHelper
+{
+
+private:
+    MapXslIdToTransform transforms;
+    MapXslIdToProperties parameters;
+
+    void insertAtRoot(StringBuffer& target, StringBuffer& value, bool insertWithinRootStartTag=false);
+
+public:
+    IMPLEMENT_IINTERFACE;
+
+    EsdlDefinitionHelper() {}
+
+    ~EsdlDefinitionHelper()
+    {
+        HashIterator tit(transforms);
+        for(tit.first(); tit.isValid(); tit.next())
+        {
+            IMapping& et = tit.query();
+            IXslTransform** trans = transforms.mapToValue(&et);
+            if(trans && *trans)
+                (*trans)->Release();
+        }
+
+        HashIterator pit(parameters);
+        for(pit.first(); pit.isValid(); pit.next())
+        {
+            IMapping& et = pit.query();
+            IProperties** props = parameters.mapToValue(&et);
+            if(props && *props)
+                (*props)->Release();
+        }
+    }
+
+    virtual void loadTransform( StringBuffer &path, IProperties *params, EsdlXslTypeId xslId );
+    virtual void setTransformParams( EsdlXslTypeId xslId, IProperties *params );
+
+    virtual void toXML( IEsdlDefObjectIterator &objs, StringBuffer &xml, double version, IProperties *opts, unsigned requestedFlags=0 );
+
+    virtual void toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0 );
+    virtual void toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, StringBuffer &xslt, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0 );
+    virtual void toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns=NULL, unsigned flags=0 );
+
+    void loadTransformParams( EsdlXslTypeId xslId );
+
+
+};
+
+// Simplified from the insertAtRoot function in quickxsltlib misc.cpp
+void EsdlDefinitionHelper::insertAtRoot(StringBuffer& target, StringBuffer& value, bool insertWithinRootStartTag/*=false*/)
+{
+    const char* p = strchr(target.str(), '>');
+    if (p)
+    {
+        int pos = p-target.str();
+        if (!insertWithinRootStartTag)
+            pos++;
+        target.insert(pos,value);
+    }
+}
+
+void EsdlDefinitionHelper::loadTransform( StringBuffer &path, IProperties *params, EsdlXslTypeId xslId )
+{
+    StringBuffer xsl;
+    xsl.loadFile(path);
+
+    Owned<IXslProcessor> proc  = getXslProcessor();
+    IXslTransform* trans = proc->createXslTransform();
+
+    trans->setXslSource(xsl, xsl.length(), "esdldefhelper", ".");
+
+    transforms.setValue( xslId, trans );
+    parameters.setValue( xslId, params );
+
+    return;
+}
+
+void EsdlDefinitionHelper::setTransformParams( EsdlXslTypeId xslId, IProperties *params )
+{
+    parameters.setValue( xslId, params );
+}
+
+void EsdlDefinitionHelper::toXML( IEsdlDefObjectIterator& objs, StringBuffer &xml, double version, IProperties *opts, unsigned requestedFlags )
+{
+    TimeSection ts("serializing EsdlObjects to XML");
+
+    ForEach( objs )
+    {
+        IEsdlDefObject &esdlObj = objs.query();
+        unsigned objFlags = objs.getFlags();
+        StringBuffer curObjXml;
+
+        // Get the current structure serialized as normal to the curObjXml buffer
+        esdlObj.toXML( curObjXml, version, opts );
+
+        if( requestedFlags & objFlags & DEPFLAG_COLLAPSE )
+        {
+            IEsdlDefObjectIterator* baseTypes = objs.queryBaseTypesIterator();
+
+            if( baseTypes == NULL )
+                throw MakeStringException(0, "EsdlDefinitionHelper::toXML - Collapsed flag enabled, but unable to query the base types iterator");
+
+            ForEach( *baseTypes )
+            {
+                StringBuffer baseStr;
+                IEsdlDefObject& baseObj = baseTypes->query();
+
+                // Get the collapsed form of the base_type- just it's child elements
+                // not including the start tag, attributes or end tag.
+                baseObj.toXML( baseStr, version, opts, DEPFLAG_COLLAPSE );
+
+                // Insert the 'collapsed' form of the current base_type object
+                // into the current struct's serialized representation.
+                this->insertAtRoot(curObjXml, baseStr);
+            }
+        } //else { DBGLOG("  <%s> Collapse failed flag check requested[0x%x] & object[0x%x] & const[0x%x]",esdlObj.queryName(), requestedFlags, objFlags, DEPFLAG_COLLAPSE); }
+
+        if( requestedFlags & DEPFLAG_ARRAYOF )
+        {
+            if( objFlags & DEPFLAG_ARRAYOF )
+            {
+                // Add arrayOf="1" attribute to all structs with flag set.
+                StringBuffer attribute(" arrayOf=\"1\"");
+                this->insertAtRoot(curObjXml, attribute, true);
+            }
+
+            if( objFlags & DEPFLAG_STRINGARRAY )
+            {
+                // Add espStringArray="1" attribute to the struct with flag set.
+                StringBuffer attribute(" espStringArray=\"1\"");
+                this->insertAtRoot(curObjXml, attribute, true);
+            }
+        }
+
+        // Add the serialization of the current structure to the xml output StringBuffer
+        xml.append( curObjXml );
+    }
+
+    return;
+}
+
+void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns, unsigned flags)
+{
+    StringBuffer xml;
+    int xmlLen = 0;
+    IXslTransform* trans = *( transforms.getValue( xslId ) );
+
+    this->loadTransformParams( xslId );
+
+    if( trans )
+    {
+        IProperties* params = *( parameters.getValue(xslId) );
+        const char *tns = (ns) ? ns :params->queryProp("tnsParam");
+
+        xml.appendf("<esxdl name=\"custom\" EsdlXslTypeId=\"%d\" xmlns:tns=\"%s\" ns_uri=\"%s\">", xslId, tns ? tns : "urn:unknown", tns ? tns : "urn:unknown");
+        this->toXML( objs, xml, version, opts, flags );
+        xml.append("</esxdl>");
+
+        xmlLen = xml.length();
+        trans->setXmlSource( xml.str(), xmlLen );
+        trans->transform(xsd);
+
+    } else {
+        throw (MakeStringException( 0, "Unable to find transform for EsdlXslTypeId=%d", xslId ));
+    }
+
+    return;
+}
+
+void EsdlDefinitionHelper::toWSDL( IEsdlDefObjectIterator &objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version, IProperties *opts, const char *ns, unsigned flags)
+{
+    StringBuffer xml;
+    int xmlLen = 0;
+    IXslTransform* trans = *( transforms.getValue( xslId ) );
+
+    this->loadTransformParams( xslId );
+
+    if( trans )
+    {
+        IProperties* params = *( parameters.getValue(xslId) );
+        const char *tns = (ns) ? ns :params->queryProp("tnsParam");
+
+        xml.appendf("<esxdl name=\"custom\" EsdlXslTypeId=\"%d\" xmlns:tns=\"%s\" ns_uri=\"%s\" version=\"%f\">", xslId, tns ? tns : "urn:unknown", tns ? tns : "urn:unknown", version);
+        this->toXML( objs, xml, version, opts, flags );
+        xml.append("</esxdl>");
+
+        xmlLen = xml.length();
+        trans->setXmlSource( xml.str(), xmlLen );
+        trans->transform(xsd);
+
+    } else {
+        throw (MakeStringException( 0, "Unable to find transform for EsdlXslTypeId=%d", xslId ));
+    }
+
+    return;
+}
+
+
+void EsdlDefinitionHelper::toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xml, StringBuffer &xslt, double version, IProperties *opts, const char *ns, unsigned flags)
+{
+    return;
+}
+
+void EsdlDefinitionHelper::loadTransformParams( EsdlXslTypeId xslId)
+{
+    IXslTransform* trans = *( transforms.getValue(xslId) );
+    IProperties* params = *( parameters.getValue(xslId) );
+
+    if( !trans )
+    {
+        throw (MakeStringException( 0, "Unable to find transform for EsdlXslTypeId=%d", xslId ));
+    }
+
+    if( params )
+    {
+        Owned<IPropertyIterator> it = params->getIterator();
+        for (it->first(); it->isValid(); it->next())
+        {
+            const char *key = it->getPropKey();
+            //set parameter in the XSL transform skipping over the @ prefix, if any
+            const char* paramName = *key == '@' ? key+1 : key;
+            trans->setParameter(paramName, StringBuffer().append('\'').append(params->queryProp(key)).append('\'').str());
+        }
+    }
+}
+
+esdl_decl IEsdlDefinitionHelper* createEsdlDefinitionHelper( )
+{
+    return new EsdlDefinitionHelper( );
+}

+ 50 - 0
esp/esdllib/esdl_def_helper.hpp

@@ -0,0 +1,50 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+// esdl_def_helper.hpp : interface for the IEsdlDefinitionHelper class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(ESDL_DEF_HELPER_HPP)
+#define ESDL_DEF_HELPER_HPP
+
+#include "esp.hpp"
+#include "esdl_def.hpp"
+
+#pragma warning(disable: 4786)
+
+typedef enum EsdlXslTypeId_
+{
+    EsdlXslToXsd,
+    EsdlXslToWsdl
+} EsdlXslTypeId;
+
+interface IEsdlDefinitionHelper : extends IInterface
+{
+    virtual void loadTransform( StringBuffer &path, IProperties *params, EsdlXslTypeId xslId )=0;
+    virtual void setTransformParams( EsdlXslTypeId xslId, IProperties *params )=0;
+
+    virtual void toXML( IEsdlDefObjectIterator& objs, StringBuffer &xml, double version=0, IProperties *opts=NULL, unsigned flags=0 )=0;
+    virtual void toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xsd, EsdlXslTypeId xslId, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
+    virtual void toXSD( IEsdlDefObjectIterator& objs, StringBuffer &xsd, StringBuffer& xslt, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
+    virtual void toWSDL( IEsdlDefObjectIterator& objs, StringBuffer &wsdl, EsdlXslTypeId xslId, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
+};
+
+
+esdl_decl IEsdlDefinitionHelper* createEsdlDefinitionHelper( );
+
+#endif // !defined(ESDL_DEF_HELPER_HPP)

+ 69 - 0
esp/esdllib/esdl_transformer.hpp

@@ -0,0 +1,69 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef __ESDL_TRANSFORMER_HPP__
+#define __ESDL_TRANSFORMER_HPP__
+
+#include "esdl_def.hpp"
+
+typedef  enum EsdlProcessMode_
+{
+    EsdlRequestMode,
+    EsdlResponseMode
+} EsdlProcessMode;
+
+interface IEsdlMethodInfo : extends IInterface
+{
+    virtual const char *queryMethodName()=0;
+    virtual const char *queryRequestType()=0;
+    virtual const char *queryResponseType()=0;
+};
+
+typedef void REQUEST_HOOK (IEspContext& ctx, IEspStruct& req, StringBuffer& query, void* parm);
+
+#define ESDL_TRANS_SOAP_IN            0x0001
+#define ESDL_TRANS_SOAP_OUT            0x0002
+#define ESDL_TRANS_ROW_IN            0x0004
+#define ESDL_TRANS_ROW_OUT            0x0008
+
+#define ESDL_TRANS_TRIM                0x0010
+#define ESDL_TRANS_NO_DEFAULTS        0x0020
+
+#define ESDL_TRANS_INPUT_XMLTAG        0x0100
+#define ESDL_TRANS_OUTPUT_XMLTAG    0x0200
+#define ESDL_TRANS_OUTPUT_ROOT        0x0400
+
+#define ESDL_TRANS_START_AT_ROOT    0x1000
+
+interface IXmlWriterExt;
+interface IEsdlTransformer : extends IInterface
+{
+    virtual IEsdlMethodInfo *queryMethodInfo(const char* service, const char *method)=0;
+    virtual int process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, StringBuffer &xmlout, const char *xmlin, unsigned int flags=0, const char *ns=NULL, const char *schema_location=NULL)=0;
+    virtual int process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, IPropertyTree &in, IXmlWriterExt * writer, unsigned int flags, const char *ns=NULL)=0;
+    virtual int processElement(IEspContext &ctx, const char* service, const char *parentStructName, IXmlWriterExt * writer, const char *xmlin)=0;
+    virtual void processHPCCResult(IEspContext &ctx, IEsdlDefMethod &mthdef, const char *xml, IXmlWriterExt * writer, StringBuffer &logdata, unsigned int flags = 0, const char *ns=NULL, const char *schema_location=NULL)=0;
+};
+
+esdl_decl IEsdlTransformer *createEsdlXFormerFromXMLFiles(StringArray &files, StringArray &types);
+
+esdl_decl IEsdlTransformer *createEsdlXFormerFromXMLFilesV2(StringArray &files);
+
+esdl_decl IEsdlTransformer *createEsdlXFormer(IEsdlDefinition* def);
+
+
+#endif

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1866 - 0
esp/esdllib/esdl_transformer2.cpp


+ 517 - 0
esp/esdllib/esdl_transformer2.ipp

@@ -0,0 +1,517 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef __ESDL_TRANSFORMER2_IPP__
+#define __ESDL_TRANSFORMER2_IPP__
+
+#pragma warning(disable : 4786)
+
+#include "jliball.hpp"
+#include "espcontext.hpp"
+#include "esdl_transformer.hpp"
+#include <xpp/XmlPullParser.h>
+#include <map>
+#include "esdl_def.hpp"
+#include "eclhelper.hpp"
+
+class Esdl2Base;
+
+typedef Esdl2Base * EsdlBasePtr;
+typedef IPropertyTree * IPTreePtr;
+
+typedef CopyReferenceArrayOf<Esdl2Base> EsdlBaseArray;
+typedef MapStringTo<EsdlBasePtr> EsdlBaseMap;
+
+typedef EsdlBaseArray * EsdlBaseArrayPtr;
+typedef MapStringTo<EsdlBaseArrayPtr> EsdlBaseArrayMap;
+typedef MapStringTo<IPTreePtr> AddedList;
+
+// ======================================================================================
+
+typedef enum
+{
+    ESDLT_UNKOWN,
+    ESDLT_STRUCT,
+    ESDLT_REQUEST,
+    ESDLT_RESPONSE,
+    ESDLT_COMPLEX,
+    ESDLT_STRING,
+    ESDLT_INT8,
+    ESDLT_INT16,
+    ESDLT_INT32,
+    ESDLT_INT64,
+    ESDLT_UINT8,
+    ESDLT_UINT16,
+    ESDLT_UINT32,
+    ESDLT_UINT64,
+    ESDLT_BOOL,
+    ESDLT_FLOAT,
+    ESDLT_DOUBLE,
+    ESDLT_BYTE,
+    ESDLT_UBYTE
+} Esdl2Type;
+
+// ======================================================================================
+// Context for ESDL transformer
+
+class Esdl2Transformer;
+
+class Esdl2TransformerContext
+{
+public:
+    Esdl2Transformer& xformer;
+    IXmlWriterExt *writer;
+    EsdlProcessMode mode;
+    unsigned int flags;
+    XmlPullParser *xppp;
+    double client_ver;
+    IProperties* param_groups;
+    StringAttr root_type;
+    bool skip_root;
+    int counter;
+    StringBuffer ns;
+    StringBuffer schemaLocation;
+    bool do_output_ns;
+
+public:
+
+
+    Esdl2TransformerContext(Esdl2Transformer& xformer_, IXmlWriterExt *writer_ , double client_ver_, IProperties *pgs, EsdlProcessMode mode_, unsigned int flags_=0, const char *nsp=NULL, const char *schema_location=NULL)
+        : xformer(xformer_), xppp(NULL), client_ver(client_ver_), mode(mode_), param_groups(pgs), skip_root(false), counter(0), flags(flags_), ns(nsp),schemaLocation(schema_location)
+    {
+        writer = writer_;
+        do_output_ns = (nsp && *nsp) ? true : false;
+    }
+
+    Esdl2TransformerContext(Esdl2Transformer& xformer_, IXmlWriterExt *writer_ , XmlPullParser &xppx_, double client_ver_, IProperties *pgs, EsdlProcessMode mode_, unsigned int flags_=0, const char *nsp=NULL, const char *schema_location=NULL)
+        : xformer(xformer_), xppp(&xppx_), client_ver(client_ver_), mode(mode_), param_groups(pgs), skip_root(false), counter(0), flags(flags_), ns(nsp), schemaLocation(schema_location)
+    {
+            writer = writer_;
+            do_output_ns = (nsp && *nsp) ? true : false;
+    }
+
+    virtual ~Esdl2TransformerContext(){}
+
+    Esdl2Base* queryType(const char* name);
+};
+
+// ======================================================================================
+//  class Esdl2LocalContext
+
+class Esdl2LocalContext
+{
+    typedef StringAttrMapping StringMap;
+    StringMap   *m_dataFor;
+    StringArray *m_dataOrig;
+
+public:
+    Esdl2LocalContext() : dataForProcessed(false), m_dataFor(NULL), m_dataOrig(NULL),m_startTag(NULL)  { }
+    ~Esdl2LocalContext() { delete m_dataFor; delete m_dataOrig; }
+
+    bool dataForProcessed;
+    StartTag* m_startTag;
+
+    void setDataFor(const char* name, const char* val)
+    {
+        if (!m_dataFor)
+            m_dataFor = new StringMap();
+        m_dataFor->setValue(name,val);
+    }
+    void setDataOrig(const char* name)
+    {
+        if (!m_dataOrig)
+            m_dataOrig = new StringArray();
+        m_dataOrig->append(name);
+    }
+
+    //void handleDataFor(StringBuffer& out);
+    void handleDataFor(IXmlWriterExt & writer);
+};
+
+// ======================================================================================
+// class Esdl2Base
+
+class Esdl2Base : public CInterface
+{
+protected:
+    IEsdlDefObject* m_def;
+    Esdl2Type type_id;
+
+    StringAttr xml_tag;
+    StringAttr param_group;
+
+    Esdl2Base* data_for; // only support one for now.
+    bool m_hasDataFrom;
+
+    bool might_skip_root;
+    bool count_output;
+    bool count_value;
+
+public:
+    IMPLEMENT_IINTERFACE;
+
+    Esdl2Base(Esdl2Transformer *xformer, IEsdlDefObject* def, Esdl2Type t=ESDLT_UNKOWN, bool might_skip_root_=false);
+    virtual ~Esdl2Base();
+
+    virtual bool hasChild() { return false; }
+    virtual bool hasDefaults() { return false; }
+    virtual Esdl2Base* queryChild(const char* name, bool nocase=false);
+    virtual void addChildren(Esdl2Transformer *xformer, IEsdlDefObjectIterator *it);
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false)=0;
+    virtual void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false){}
+    virtual void processElement(Esdl2TransformerContext &ctx)
+    {
+        throw MakeStringException(-1, "ESDL Error: processElement not implemented for %s", queryName());
+    }
+
+    virtual void serialize(StringBuffer &out)=0;
+    virtual void buildDefaults(Esdl2Transformer *xformer, StringBuffer &path, IProperties *defvals){}
+    virtual void serialize(StringBuffer &out, const char *type);
+    virtual void serialize_children(StringBuffer &out) { }
+    void serialize_attributes(StringBuffer &out);
+
+    void setMightSkipRoot(bool skip) { might_skip_root = skip; }
+    IEsdlDefObject* queryEsdlDefObject() { return m_def; }
+    void mergeBaseType(Esdl2Transformer *xformer, const char *base_type);
+
+    const char *queryName(){ return m_def->queryName();}
+    const char* queryDefaultValue() { return m_def->queryProp("default"); }
+    // return "" for NULL
+    const char* queryDefaultValueS() { const char* s = m_def->queryProp("default"); return s?s:""; }
+
+    const char *queryEclName() { return m_def->queryProp("ecl_name"); }
+    const char* queryEclNull() { return m_def->queryProp("ecl_null"); }
+    const char* queryInputName(Esdl2TransformerContext &ctx){if (ctx.flags & ESDL_TRANS_INPUT_XMLTAG) return xml_tag.get(); else return queryName();}
+    const char* queryOutputName(Esdl2TransformerContext &ctx){if (ctx.flags & ESDL_TRANS_OUTPUT_XMLTAG) return xml_tag.get(); else return queryName();}
+    Esdl2Base*   queryDataFor() { return data_for; }
+    void setDataFor(Esdl2Base* node)
+    {
+        if (data_for)
+            throw MakeStringException(-1, "Feature not supported: data-for only for single field. Field: %s", queryName());
+        data_for = node;
+    }
+    bool hasDataFrom() { return m_hasDataFrom; }
+    void setHasDataFrom() { m_hasDataFrom = true; }
+
+    // return true if it passed version check
+    bool checkVersion(Esdl2TransformerContext &ctx);
+
+    void countContent(Esdl2TransformerContext &ctx);
+
+    void output_content(Esdl2TransformerContext &ctx, const char *tagname);
+    void output_content(Esdl2TransformerContext &ctx);
+    void output_content(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *tagname);
+    void output_content(Esdl2TransformerContext &ctx, IPropertyTree *pt);
+    void output_content(Esdl2TransformerContext &ctx, const char * content, const char *tagname, unsigned leadinzeros);
+
+
+    void output_ecl_date(Esdl2TransformerContext &ctx, const char *tagname);
+};
+
+Esdl2Base *createEsdlObject(Esdl2Transformer *xformer, IEsdlDefObject *def);
+
+
+// ======================================================================================
+// class Esdl2EnumItem
+
+class Esdl2EnumItem : public Esdl2Base
+{
+    StringAttr value;
+public:
+    Esdl2EnumItem(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def)
+    {
+        value.set(def->queryProp("enum"));
+    }
+    virtual ~Esdl2EnumItem(){}
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name,Esdl2LocalContext* local=NULL, bool count=false){}
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlEnumItem");
+    }
+
+};
+
+class Esdl2EnumType : public Esdl2Base
+{
+    StringAttr base_type;
+
+public:
+    Esdl2EnumType(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def)
+    {
+        base_type.set(def->queryProp("base_type"));
+    }
+    virtual ~Esdl2EnumType(){}
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false){}
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlEnumType");
+    }
+
+};
+
+class Esdl2EnumRef : public Esdl2Base
+{
+    StringAttr enum_type;
+
+public:
+    Esdl2EnumRef(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def)
+    {
+        enum_type.set(def->queryProp("enum_type"));
+    }
+
+    virtual ~Esdl2EnumRef(){}
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    virtual void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlEnumRef");
+    }
+};
+
+
+class Esdl2Attribute : public Esdl2Base
+{
+public:
+    Esdl2Attribute(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def){}
+    virtual ~Esdl2Attribute(){}
+
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false)
+    {
+        ctx.xppp->skipSubTree();
+    }
+    virtual void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlAttribute");
+    }
+};
+
+class Esdl2Element : public Esdl2Base
+{
+    StringAttr complex_type;
+    StringAttr simple_type;
+    Esdl2Base *esdl_type;
+
+public:
+    Esdl2Element(Esdl2Transformer *xformer, IEsdlDefObject *def);
+
+    virtual void buildDefaults(Esdl2Transformer *xformer, StringBuffer &path, IProperties *defvals);
+
+    virtual ~Esdl2Element(){}
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    virtual void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlElement");
+    }
+};
+
+class Esdl2Array : public Esdl2Base
+{
+    StringAttr type;
+    StringAttr item_tag;
+    Esdl2Base *esdl_type;
+
+    bool inited;
+    bool type_unknown;
+public:
+    Esdl2Array(Esdl2Transformer *xformer, IEsdlDefObject *def);
+    virtual ~Esdl2Array(){}
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlArray");
+    }
+
+    void init(Esdl2TransformerContext &ctx);
+
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    virtual void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+};
+
+class Esdl2Struct : public Esdl2Base
+{
+protected:
+    EsdlBaseArray m_children;  //elements and arrays
+    EsdlBaseArrayMap xml_tags;
+    bool isElement;
+
+private:
+    EsdlBaseMap   m_child_map;
+
+public:
+    Esdl2Struct(Esdl2Transformer *xformer, IEsdlDefStruct *def, Esdl2Type t=ESDLT_STRUCT);
+    virtual ~Esdl2Struct();
+
+    virtual bool hasChild() { return !m_children.empty(); }
+    virtual void serialize_children(StringBuffer &out)
+    {
+        ForEachItemIn(idx, m_children)
+        {
+            Esdl2Base &child = m_children.item(idx);
+            child.serialize(out);
+        }
+
+    }
+
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    virtual void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    virtual void processElement(Esdl2TransformerContext &ctx);
+
+    virtual void buildDefaults(Esdl2Transformer *xformer, StringBuffer &path, IProperties *defvals);
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "Esdl2Struct");
+    }
+
+    virtual void addChildren(Esdl2Transformer *xformer, IEsdlDefObjectIterator *it);
+    Esdl2Base*  queryChild(const char* name, bool nocase=false);
+};
+
+class Esdl2Request : public Esdl2Struct
+{
+    Owned<IProperties> defvals;
+
+public:
+    Esdl2Request(Esdl2Transformer *xformer, IEsdlDefStruct *def) : Esdl2Struct(xformer, def, ESDLT_REQUEST)
+    {
+        //might_skip_root = true; --> this is not true for Engine 1
+        buildDefaults(xformer);
+    }
+
+    virtual ~Esdl2Request(){}
+
+    void process(Esdl2TransformerContext &ctx, IPropertyTree *pt, const char *out_name, Esdl2LocalContext* local, bool count);
+
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlRequest");
+    }
+
+    virtual void buildDefaults(Esdl2Transformer *xformer);
+
+    virtual void addDefaults(IPropertyTree *req);
+};
+
+class Esdl2Response: public Esdl2Struct
+{
+public:
+    Esdl2Response(Esdl2Transformer *xformer, IEsdlDefStruct *def) : Esdl2Struct(xformer, def, ESDLT_RESPONSE)
+    {
+        might_skip_root=true;
+    }
+
+    virtual ~Esdl2Response(){}
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlResponse");
+    }
+
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false);
+    void processChildNamedResponse(Esdl2TransformerContext &ctx, const char *out_name);
+};
+
+class Esdl2Method : public Esdl2Base, implements IEsdlMethodInfo
+{
+private:
+    IEsdlDefMethod* m_methodDef;
+
+public:
+    IMPLEMENT_IINTERFACE;
+
+    Esdl2Method(Esdl2Transformer *xformer, IEsdlDefMethod *def)
+    : Esdl2Base(xformer, def), m_methodDef(dynamic_cast<IEsdlDefMethod*>(def))
+    {
+    }
+
+    virtual ~Esdl2Method(){}
+
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false){}
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlMethod");
+    }
+
+    virtual const char *queryMethodName() { return queryName();}
+    virtual const char *queryRequestType() { return m_methodDef->queryRequestType(); }
+    virtual const char *queryResponseType() { return m_methodDef->queryResponseType(); }
+};
+
+
+typedef Esdl2Method * EsdlMethodPtr;
+typedef CopyReferenceArrayOf<Esdl2Method> EsdlMethodArray;
+typedef MapStringTo<EsdlMethodPtr> EsdlMethodMap;
+
+
+class Esdl2Service : public Esdl2Base
+{
+    EsdlMethodArray methods;  //elements and arrays
+    EsdlMethodMap meth_map;
+    float default_client_version;
+public:
+
+    Esdl2Service(Esdl2Transformer *xformer, IEsdlDefObject *def) : Esdl2Base(xformer, def), default_client_version(1.0f){}
+    virtual ~Esdl2Service(){}
+
+    virtual void process(Esdl2TransformerContext &ctx, const char *out_name, Esdl2LocalContext* local=NULL,bool count=false){}
+    void serialize(StringBuffer &out)
+    {
+        Esdl2Base::serialize(out, "EsdlEnumItem");
+    }
+};
+
+class Esdl2Transformer : public CInterface, implements IEsdlTransformer
+{
+private:
+    Owned<IEsdlDefinition> m_def;
+
+    EsdlBaseArray types;  //elements and arrays
+    EsdlBaseMap type_map;
+
+    EsdlMethodArray methods;  //elements and arrays
+    EsdlMethodMap meth_map;
+
+    void addType(Esdl2Base* type);
+    void addMethod(Esdl2Base *item);
+
+public:
+    IMPLEMENT_IINTERFACE;
+
+    Esdl2Transformer(IEsdlDefinition* def);
+
+    virtual ~Esdl2Transformer();
+
+    Esdl2Base* queryType(const char* name);
+    IEsdlMethodInfo *queryMethodInfo(const char* service,const char *method);
+
+    void serialize(StringBuffer &out);
+
+    //NOT BEING USED ANYWHERE
+    //virtual int process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, IClientWsEclRequest &clReq, IEspStruct& r, REQUEST_HOOK* reqHook);
+
+    virtual int process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, StringBuffer &xmlout, const char *xmlin, unsigned int flags = 0, const char *ns=NULL, const char *schema_location=NULL);
+    virtual int process(IEspContext &ctx, EsdlProcessMode mode, const char* service, const char *method, IPropertyTree &in, IXmlWriterExt * writer, unsigned int flags, const char *ns);
+    virtual int processElement(IEspContext &ctx, const char* service, const char *parentStructName, IXmlWriterExt * writer, const char *in);
+    virtual void processHPCCResult(IEspContext &ctx, IEsdlDefMethod &mthdef, const char *xml, IXmlWriterExt * writer, StringBuffer &logdata, unsigned int flags = 0, const char *ns=NULL, const char *schema_location=NULL);
+};
+
+#endif

+ 211 - 0
esp/esdllib/params2xml.cpp

@@ -0,0 +1,211 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#pragma warning(disable : 4786)
+
+#include "jliball.hpp"
+#include "esdl_def.hpp"
+#include "params2xml.hpp"
+
+
+void child2xml(IEsdlDefinition *esdl, IEsdlDefObject &child, StringBuffer &flexpath, IProperties *params, StringBuffer &xmlstr, StringBuffer &path, unsigned flags, double ver, int flexpath_setpoint);
+
+
+void paramsStruct2xml(IEsdlDefinition *esdl, IEsdlDefStruct *est, const char *tagname, IProperties *params, StringBuffer &xmlstr, StringBuffer &path, unsigned flags, double ver, bool isroot)
+{
+    xmlstr.append('<').append(tagname).append('>');
+    unsigned xml_setpoint=xmlstr.length();
+
+    StringBuffer flexpath(path);
+    if (flexpath.length())
+        flexpath.append(".");
+    unsigned flexpath_setpoint = flexpath.length();
+
+    if (est->queryProp("base_type"))
+    {
+        IEsdlDefStruct *base = esdl->queryStruct(est->queryProp("base_type"));
+        Owned<IEsdlDefObjectIterator> bt = base->getChildren();
+        ForEach(*bt)
+            child2xml(esdl, bt->query(), flexpath, params, xmlstr, path, flags, ver, flexpath_setpoint);
+    }
+
+    Owned<IEsdlDefObjectIterator> it = est->getChildren();
+    ForEach(*it)
+        child2xml(esdl, it->query(), flexpath, params, xmlstr, path, flags, ver, flexpath_setpoint);
+
+    if (isroot || xml_setpoint<xmlstr.length())
+        xmlstr.append("</").append(tagname).append('>');
+    else
+        xmlstr.setLength(xml_setpoint - strlen(tagname) - 2);
+}
+
+
+esdl_decl void params2xml(IEsdlDefinition *def, const char *structname, IProperties *params, StringBuffer &xmlstr, unsigned flags, double ver)
+{
+    IEsdlDefStruct *est = def->queryStruct(structname);
+    if (!est)
+        throw MakeStringException(-1, "parms2xml: ESDL Struct %s not found", structname);
+
+    StringBuffer path;
+    paramsStruct2xml(def, est, structname, params, xmlstr, path, flags, ver, true);
+}
+
+
+
+esdl_decl void params2xml(IEsdlDefinition *def, const char *service, const char *method, EsdlDefTypeId esdltype, IProperties *params, StringBuffer &xmlstr, unsigned flags, double ver)
+{
+    if (esdltype!=EsdlTypeRequest && esdltype!=EsdlTypeResponse)
+        throw MakeStringException(-1, "parms2xml: Only ESDL request and response types supported");
+    IEsdlDefService *srv = def->queryService(service);
+    if (!srv)
+        throw MakeStringException(-1, "parms2xml: ESDL Service %s not found", service);
+    IEsdlDefMethod *mth = srv->queryMethodByName(method);
+    if (!mth)
+        throw MakeStringException(-1, "parms2xml: ESDL Method %s not found", method);
+    if (esdltype==EsdlTypeRequest)
+        params2xml(def, mth->queryRequestType(), params, xmlstr, flags, ver);
+    else if (esdltype==EsdlTypeResponse)
+        params2xml(def, mth->queryResponseType(), params, xmlstr, flags, ver);
+}
+
+void child2xml(IEsdlDefinition *esdl, IEsdlDefObject &child, StringBuffer &flexpath, IProperties *params, StringBuffer &xmlstr, StringBuffer &path, unsigned flags, double ver, int flexpath_setpoint)
+{
+    if (child.checkVersion(ver))
+    {
+        const char *name = child.queryName();
+        const char *xml_tag = child.queryProp("xml_tag");
+        const char *tagname;
+        if (xml_tag && *xml_tag && flags & PARAMS2XML_OUTPUT_XML_TAG_NAME)
+            tagname = xml_tag;
+        else
+            tagname = name;
+
+        if (xml_tag && *xml_tag && flags & PARAMS2XML_INPUT_XML_TAG_NAME)
+            name = xml_tag;
+
+        switch (child.getEsdlType())
+        {
+            case EsdlTypeElement:
+            {
+                flexpath.append(name);
+                const char *complex_type = child.queryProp("complex_type");
+                if (complex_type)
+                {
+                    IEsdlDefStruct *cst = esdl->queryStruct(complex_type);
+                    if (cst)
+                        paramsStruct2xml(esdl, cst, tagname, params, xmlstr, flexpath, flags, ver, false);
+                }
+                else
+                {
+                    const char *val = params->queryProp(flexpath.str());
+                    if (val && *val)
+                    {
+                        xmlstr.append('<').append(tagname).append('>');
+                        encodeUtf8XML(val, xmlstr);
+                        xmlstr.append("</").append(tagname).append('>');
+                    }
+                }
+                flexpath.setLength(flexpath_setpoint);
+                break;
+            }
+            case EsdlTypeEnumRef:
+            {
+                flexpath.append(name);
+                const char *val = params->queryProp(flexpath.str());
+                if (val && *val)
+                {
+                    xmlstr.append('<').append(tagname).append('>');
+                    encodeUtf8XML(val, xmlstr);
+                    xmlstr.append("</").append(tagname).append('>');
+                }
+                flexpath.setLength(flexpath_setpoint);
+                break;
+            }
+
+            case EsdlTypeArray:
+            {
+                const char *item_tag = child.queryProp("item_tag");
+                if (!item_tag || !*item_tag)
+                    item_tag = "item";
+                const char *artype = child.queryProp("type");
+                IEsdlDefStruct *cst = esdl->queryStruct(artype);
+
+                flexpath.append(name);
+
+                if (cst)
+                {
+                    flexpath.append('.').append(artype);
+                    unsigned arpath_setpoint = flexpath.length();
+
+                    flexpath.append('.').append("itemcount");
+                    const char *countstr = params->queryProp(flexpath.str());
+                    flexpath.setLength(arpath_setpoint);
+
+                    int itemcount = (countstr) ? atoi(countstr) : 0;
+                    if (itemcount)
+                    {
+                        xmlstr.append('<').append(name).append('>');
+                        unsigned arxml_setpoint = xmlstr.length();
+                        for (int pos = 0; pos < itemcount; pos++)
+                        {
+                            flexpath.append('.').append(pos);
+                            paramsStruct2xml(esdl, cst, item_tag, params, xmlstr, flexpath, flags, ver, false);
+                            flexpath.setLength(arpath_setpoint);
+                        }
+                        if (xmlstr.length()>arxml_setpoint)
+                            xmlstr.append("</").append(name).append('>');
+                        else
+                            xmlstr.setLength(arxml_setpoint - strlen(name) - 2);
+                    }
+                }
+                else
+                {
+                    const char *val = params->queryProp(flexpath.str());
+                    if (val && *val)
+                    {
+                        xmlstr.append('<').append(name).append('>');
+                        unsigned arxml_setpoint = xmlstr.length();
+                        StringBuffer itemval;
+                        for (const char *finger=val; *finger; finger++)
+                        {
+                            if (strchr("\n\r", *finger))
+                            {
+                                if (itemval.length())
+                                {
+                                    xmlstr.append('<').append(item_tag).append('>');
+                                    encodeUtf8XML(itemval.str(), xmlstr);
+                                    xmlstr.append("</").append(item_tag).append('>');
+                                }
+                                itemval.clear();
+                            }
+                            else
+                                itemval.append(*finger);
+                        }
+                        if (xmlstr.length()>arxml_setpoint)
+                            xmlstr.append("</").append(name).append('>');
+                        else
+                            xmlstr.setLength(arxml_setpoint - strlen(name) - 2);
+                    }
+                }
+                flexpath.setLength(flexpath_setpoint);
+                break;
+            }
+            default:
+                break;
+        };
+    }
+}

+ 30 - 0
esp/esdllib/params2xml.hpp

@@ -0,0 +1,30 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef PARAMS2XML_HPP
+#define PARAMS2XML_HPP
+
+#include "jliball.hpp"
+#include "esdl_def.hpp"
+
+#define PARAMS2XML_OUTPUT_XML_TAG_NAME 0x0001
+#define PARAMS2XML_INPUT_XML_TAG_NAME 0x0002
+
+esdl_decl void params2xml(IEsdlDefinition *def, const char *structname, IProperties *params, StringBuffer &xmlstr, unsigned flags, double ver);
+esdl_decl void params2xml(IEsdlDefinition *def, const char *service, const char *method, EsdlDefTypeId esdltype, IProperties *params, StringBuffer &xmlstr, unsigned flags, double ver);
+
+#endif //PARAMS2XML_HPP

+ 209 - 0
esp/esdllib/wsexcept.cpp

@@ -0,0 +1,209 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include "platform.h"
+#include "wsexcept.hpp"
+
+class CWsException : public CInterface,
+implements IWsException
+{
+public:
+    IMPLEMENT_IINTERFACE
+
+    CWsException (const char* source, WsErrorType errorType )
+    {
+        if (source)
+            source_.append(source);
+        errorType_ = errorType;
+    }
+    CWsException( IMultiException& me, WsErrorType errorType )
+    {
+        append(me);
+        errorType_ = errorType;
+
+        const char* source = me.source();
+
+        if (source)
+            source_.append(source);
+    }
+    CWsException( IException& e, const char* source, WsErrorType errorType )
+    {
+        IMultiException* me = dynamic_cast<IMultiException*>(&e);
+        if ( me ) {
+            append(*me);
+        } else
+            append(e);
+        errorType_ = errorType;
+
+        if (source)
+            source_.append(source);
+    }
+
+    //convenience methods for handling this as an array
+    virtual aindex_t ordinality() const
+    {
+        synchronized block(m_mutex);
+        return array_.ordinality();
+    }
+    virtual IException& item(aindex_t pos) const
+    {
+        synchronized block(m_mutex);
+        return array_.item(pos);
+    }
+    virtual const char* source() const
+    {
+        synchronized block(m_mutex);
+        return source_.str();
+    }
+
+    //for complete control...caller is responsible for thread safety!
+    virtual IArrayOf<IException>& getArray()     { return array_;              }
+
+    // add another exception. Pass ownership to this obj:
+    // i.e., caller needs to make sure that e has one consumable ref count
+    virtual void append(IException& e)
+    {
+        synchronized block(m_mutex);
+        array_.append(e);
+    }
+    virtual void append(IMultiException& me)
+    {
+        synchronized block(m_mutex);
+
+        IArrayOf<IException>& exceptions = me.getArray();
+        const char* source = me.source();
+        ForEachItemIn(i, exceptions)
+        {
+            IException& e = exceptions.item(i);
+            if (source && *source)
+            {
+                StringBuffer msg;
+                msg.appendf("[%s] ",source);
+                e.errorMessage(msg);
+                array_.append(*MakeStringExceptionDirect(e.errorAudience(), e.errorCode(), msg));
+            }
+            else
+                array_.append(*LINK(&e));
+        }
+    }
+
+
+    StringBuffer& serialize(StringBuffer& buffer, unsigned indent = 0, bool simplified=false, bool root=true) const
+    {
+        synchronized block(m_mutex);
+
+        if (root)
+            buffer.append("<Exceptions>");
+
+        if (!simplified)
+        {
+            if (indent) buffer.append("\n\t");
+            buffer.appendf("<Source>%s</Source>", source_.str());
+        }
+
+        ForEachItemIn(i, array_)
+        {
+            IException& exception = array_.item(i);
+
+            if (indent) buffer.append("\n\t");
+            buffer.append("<Exception>");
+
+            if (indent) buffer.append("\n\t\t");
+            buffer.appendf("<Code>%d</Code>", exception.errorCode());
+
+            if (indent) buffer.append("\n\t\t");
+            buffer.appendf("<Audience>%s</Audience>", serializeMessageAudience( exception.errorAudience() ));
+
+            if (simplified)
+            {
+                if (indent) buffer.append("\n\t\t");
+                StringBuffer msg;
+                buffer.appendf("<Source>%s</Source>", source_.str());
+            }
+
+            if (indent) buffer.append("\n\t\t");
+
+            StringBuffer msg;
+            StringBuffer encoded;
+            encodeXML(exception.errorMessage(msg).str(), encoded);
+            buffer.appendf("<Message>%s</Message>", encoded.str());
+
+            if (indent) buffer.append("\n\t");
+            buffer.append("</Exception>");
+        }
+
+        if (root)
+            buffer.append("</Exceptions>");
+        return buffer;
+    }
+
+    virtual int errorCode() const
+    {
+        synchronized block(m_mutex);
+        return ordinality() == 1 ? item(0).errorCode() : -1;
+    }
+    virtual StringBuffer& errorMessage(StringBuffer &msg) const
+    {
+        synchronized block(m_mutex);
+        ForEachItemIn(i, array_)
+        {
+            IException& e = item(i);
+
+            StringBuffer buf;
+            msg.appendf("[%3d: %s] ", e.errorCode(), e.errorMessage(buf).str());
+        }
+        return msg;
+    }
+    virtual MessageAudience errorAudience() const
+    {
+        synchronized block(m_mutex);
+        return ordinality() == 1 ? item(0).errorAudience() : MSGAUD_unknown;
+    }
+    virtual WsErrorType errorType() const
+    {
+        synchronized block(m_mutex);
+        return errorType_;
+    }
+private:
+    CWsException( const CWsException& );
+    IArrayOf<IException> array_;
+    StringBuffer         source_;
+    mutable Mutex        m_mutex;
+    WsErrorType          errorType_;
+};
+
+IWsException esdl_decl *makeWsException(IMultiException& me, WsErrorType errorType)
+{
+    return new CWsException(me, errorType);
+}
+IWsException esdl_decl *makeWsException(IException& e, WsErrorType errorType, const char* source)
+{
+    return new CWsException(  e, source, errorType );
+}
+IWsException esdl_decl *makeWsException(int errorCode, WsErrorType errorType, const char* source, const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    IException *e = MakeStringExceptionVA(errorCode, format, args);
+    va_end(args);
+
+    return new CWsException(  *e, source, errorType );
+}
+IWsException esdl_decl *makeWsException(const char *source, WsErrorType errorType)
+{
+    return new CWsException(source, errorType);
+}

+ 1 - 0
esp/scm/espscm.cmake

@@ -42,6 +42,7 @@ set ( ESPSCM_SRCS
       ws_topology.ecm
       ws_workunits.ecm
       ws_packageprocess.ecm
+      ws_esdlconfig.ecm
     )
 
 foreach ( loop_var ${ESPSCM_SRCS} )

+ 1 - 0
esp/scm/smcscm.cmake

@@ -36,6 +36,7 @@ set ( ESPSCM_SRCS
       ws_topology.ecm
       ws_workunits.ecm
       ws_packageprocess.ecm
+      ws_esdlconfig.ecm
     )
 
 foreach ( loop_var ${ESPSCM_SRCS} )

+ 185 - 0
esp/scm/ws_esdlconfig.ecm

@@ -0,0 +1,185 @@
+/*##############################################################################
+HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+############################################################################## */
+
+ESPrequest EchoRequest
+{
+    string Request;
+};
+
+ESPresponse EchoResponse
+{
+    string Response;
+};
+
+ESPstruct BaseESDLStatus
+{
+    int Code;
+    string Description;
+};
+
+ESPrequest GetESDLDefinitionRequest
+{
+    string Id;
+};
+
+ESPresponse [exceptions_inline] GetESDLDefinitionResponse
+{
+    string Id;
+    string XMLDefinition;
+    ESPstruct BaseESDLStatus status;
+};
+
+ESPrequest PublishESDLDefinitionRequest
+{
+    string ServiceName;
+    string XMLDefinition;
+    boolean DeletePrevious;
+};
+
+ESPresponse [exceptions_inline] PublishESDLDefinitionResponse
+{
+    string ServiceName;
+    int EsdlVersion;
+    boolean DeletePrevious;
+    ESPstruct BaseESDLStatus status;
+};
+
+ESPrequest PublishESDLBindingRequest
+{
+    string EspProcName;        //Name of ESP Process
+    string EspBindingName;     //Name of ESP Binding - optional, but we must be able to look it up. We can look it up by EspProc + Esp Port or EspProc + Esp Service.
+    string EspPort;            //Esp Proc + Esp port = ESP Binding
+    string EspServiceName;     //Esp Proc + Esp service name = ESP Binding
+                               //Therefore, either pass in EspBindingName, or Esp Port or ESP ServiceName
+    string EsdlDefinitionID;   // The ESDL definition name.ver
+    string EsdlServiceName;    //Name of service as defined in ESDL Definition
+
+    boolean Overwrite;
+    string Config; // dynamic xml, can have <Binding EspProcess=xxx EspBinding=WsAccurint><Definition name=xx id=xx.yy><Methods><Method>...
+                   //              or  <Definition name=xx id=xx.yy><Methods><Method>...
+                   //              or  <Methods><Method>....
+                   //<methods><Method name="name"  url="http://10.173.128.100:9876" password="h7webmX+vmTgtAsFmC+ahQ==" username="rpastrana" queryname="UPS_Services.RightAddressService" status="available" testrepo="0" querytype="roxie"/><Methods>
+};
+
+ESPresponse [exceptions_inline] PublishESDLBindingResponse
+{
+    string EsdlDefinitionID; // The ESDL definition name.ver
+    boolean Overwrite;
+    string EspProcName;     //Name of ESP Process
+    string EspPort;         //Name + port = service
+    ESPstruct BaseESDLStatus status;
+};
+
+ESPrequest ConfigureESDLBindingMethodRequest
+{
+    string EspProcName;       //Name of ESP Process
+    string EspBindingName;    //Name + port = binding
+    string EspPort;            //Esp Proc + Esp port = ESP Binding
+    string EsdlDefinitionID;   // The ESDL definition name.ver
+    string EsdlServiceName;    //Name of service as defined in ESDL Definition
+    //string MethodName;         //If no port is provided
+    boolean Overwrite;
+    //string Attributes;        //xml <methods><Method name="name" url="http://vvvzzz.yyy.xxx:9876" password="h7fermX+gmYuuBwUsS-qeZ==" username="myname" queryname="UPS_Services.RightAddressService" status="available" testrepo="0" querytype="roxie"/><Methods>
+    string Config; // dynamic xml, can have <Binding EspProcess=xxx EspBinding=WsAccurint><Definition name=xx id=xx.yy><Methods><Method>...
+                   //              or  <Definition name=xx id=xx.yy><Methods><Method>...
+                   //              or  <Methods><Method>....
+                   //<methods><Method name="name"  url="http://10.173.128.100:9876" password="h7webmX+vmTgtAsFmC+ahQ==" username="rpastrana" queryname="UPS_Services.RightAddressService" status="available" testrepo="0" querytype="roxie"/><Methods>
+};
+
+ESPresponse [exceptions_inline] ConfigureESDLBindingMethodResponse
+{
+    string ServiceName;         //which ESDL definition are we configuring
+    int ServiceEsdlVersion;     //which version of the ESDL def are we configuring
+    string EspProcName;         //Name of ESP Process
+    ESPstruct BaseESDLStatus status;
+};
+
+ESPrequest GetESDLBindingRequest
+{
+    string EspProcName;   //Name of ESP Process
+    string EspBindingName;
+    string EspPort;       //Name + port = service
+    string EsdlBindingId; //espprocname.espbinding
+};
+
+ESPresponse [exceptions_inline] GetESDLBindingResponse
+{
+    string ServiceName;  //which ESDL definition are we configuring
+    string EspProcName;   //Name of ESP Process
+    string BindingName;
+    string EspPort;
+    string ConfigXML;
+    ESPstruct BaseESDLStatus status;
+};
+
+ESPrequest DeleteESDLDefinitionRequest
+{
+    string Id;
+    string Name;
+    string Version;
+};
+
+ESPrequest DeleteESDLBindingRequest
+{
+    string Id;
+    string EspProcess;
+    string EspBinding;
+};
+
+ESPresponse [exceptions_inline] DeleteESDLRegistryEntryResponse
+{
+    string DeletedTree;
+    ESPstruct BaseESDLStatus status;
+};
+
+ESPrequest ListESDLDefinitionsRequest
+{
+};
+
+ESPstruct ESDLBinding
+{
+    string EspProcess;
+    string EspBinding;
+    string Id;
+};
+
+ESPstruct ESDLDefinition
+{
+    string Name;
+    int Seq;
+    string Id;
+};
+
+ESPresponse [exceptions_inline] ListESDLDefinitionsResponse
+{
+    ESParray<ESPstruct ESDLDefinition, Definition> Definitions;
+};
+
+ESPrequest ListESDLBindingsRequest
+{
+};
+
+ESPresponse [exceptions_inline] ListESDLBindingsResponse
+{
+    string BindingsXML;
+    ESParray<ESPstruct ESDLBinding, Binding> Bindings;
+};
+
+ESPservice [version("1.0"), default_client_version("1.0"), exceptions_inline("./smc_xslt/exceptions.xslt")] WsESDLConfig
+{
+    ESPmethod Echo(EchoRequest, EchoResponse);
+    ESPmethod PublishESDLDefinition(PublishESDLDefinitionRequest, PublishESDLDefinitionResponse);
+    ESPmethod PublishESDLBinding(PublishESDLBindingRequest, PublishESDLBindingResponse);
+    ESPmethod ConfigureESDLBindingMethod(ConfigureESDLBindingMethodRequest, ConfigureESDLBindingMethodResponse);
+    ESPmethod GetESDLBinding(GetESDLBindingRequest, GetESDLBindingResponse);
+    ESPmethod DeleteESDLBinding(DeleteESDLBindingRequest, DeleteESDLRegistryEntryResponse);
+    ESPmethod DeleteESDLDefinition(DeleteESDLDefinitionRequest, DeleteESDLRegistryEntryResponse);
+    ESPmethod GetESDLDefinition(GetESDLDefinitionRequest, GetESDLDefinitionResponse);
+    ESPmethod ListESDLDefinitions(ListESDLDefinitionsRequest, ListESDLDefinitionsResponse);
+    ESPmethod ListESDLBindings(ListESDLBindingsRequest, ListESDLBindingsResponse);
+};
+
+SCMexportdef(WsESDLConfig);
+
+SCMapi(WsESDLConfig) IClientWsESDLConfig *createWsESDLConfigClient();

+ 2 - 0
esp/services/CMakeLists.txt

@@ -30,3 +30,5 @@ HPCC_ADD_SUBDIRECTORY (ws_topology "PLATFORM")
 HPCC_ADD_SUBDIRECTORY (ws_workunits "PLATFORM")
 HPCC_ADD_SUBDIRECTORY (WsDeploy "PLATFORM")
 HPCC_ADD_SUBDIRECTORY (ws_packageprocess "PLATFORM")
+HPCC_ADD_SUBDIRECTORY (ws_esdlconfig "PLATFORM")
+HPCC_ADD_SUBDIRECTORY (esdl_svc_engine "PLATFORM")

+ 76 - 0
esp/services/esdl_svc_engine/CMakeLists.txt

@@ -0,0 +1,76 @@
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+################################################################################
+
+
+# Component: esdl_svc_engine
+#####################################################
+# Description:
+# ------------
+#    Cmake Input File for esdl_svc_engine
+#####################################################
+
+project( esdl_svc_engine )
+
+set (   SRCS
+        esdl_binding.cpp
+        esdl_svc_engine_plugin.cpp
+        esdl_svc_engine.cpp
+    )
+
+include_directories (
+         ${HPCC_SOURCE_DIR}/dali/base
+         ${HPCC_SOURCE_DIR}/esp/esplib
+         ${HPCC_SOURCE_DIR}/esp/platform
+         ${HPCC_SOURCE_DIR}/esp/services
+         ${HPCC_SOURCE_DIR}/esp/services/common
+         ${HPCC_SOURCE_DIR}/esp/clients
+         ${HPCC_SOURCE_DIR}/esp/bindings
+         ${HPCC_SOURCE_DIR}/esp/bindings/SOAP/xpp
+         ${HPCC_SOURCE_DIR}/esp/bindings/http/client
+         ${HPCC_SOURCE_DIR}/system/jlib
+         ${HPCC_SOURCE_DIR}/system/xmllib
+         ${HPCC_SOURCE_DIR}/system/security/securesocket
+         ${HPCC_SOURCE_DIR}/system/security/shared
+         ${HPCC_SOURCE_DIR}/system/include
+         ${HPCC_SOURCE_DIR}/system/mp
+         ${HPCC_SOURCE_DIR}/common/deftype
+         ${HPCC_SOURCE_DIR}/common/environment
+         ${HPCC_SOURCE_DIR}/common/thorhelper
+         ${HPCC_SOURCE_DIR}/ecl/hql
+         ${HPCC_SOURCE_DIR}/rtl/include
+         ${HPCC_SOURCE_DIR}/esp/esdllib
+    )
+
+ADD_DEFINITIONS( -D_USRDLL )
+
+HPCC_ADD_LIBRARY( esdl_svc_engine SHARED ${SRCS} )
+install ( TARGETS esdl_svc_engine RUNTIME DESTINATION bin LIBRARY DESTINATION lib )
+add_dependencies (esdl_svc_engine espscm)
+target_link_libraries ( esdl_svc_engine
+         jlib
+         xmllib
+         esphttp
+         mp
+         hrpc
+         nbcd
+         eclrtl
+         deftype
+         hql
+         remote
+         dalibase
+         securesocket
+         esdllib
+    )

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2463 - 0
esp/services/esdl_svc_engine/esdl_binding.cpp


+ 347 - 0
esp/services/esdl_svc_engine/esdl_binding.hpp

@@ -0,0 +1,347 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+#ifndef _EsdlBinding_HPP__
+#define _EsdlBinding_HPP__
+
+#include "esdl_def.hpp"
+#include "esdl_transformer.hpp"
+#include "esdl_def_helper.hpp"
+#include "jsmartsock.hpp"
+#include "dasds.hpp"
+#include "jptree.hpp"
+#include "xsdparser.hpp"
+
+static const char* ESDL_DEFS_ROOT_PATH="/ESDL/Definitions/";
+static const char* ESDL_DEF_PATH="/ESDL/Definitions/Definition";
+static const char* ESDL_DEF_ENTRY="Definition";
+
+static const char* ESDL_BINDINGS_ROOT_PATH="/ESDL/Bindings/";
+static const char* ESDL_BINDING_PATH="/ESDL/Bindings/Binding";
+static const char* ESDL_BINDING_ENTRY="Binding";
+
+#define SDS_LOCK_TIMEOUT (30*1000) // 5mins, 30s a bit short
+
+#include "SOAP/Platform/soapbind.hpp"
+
+#define ERR_ESDL_BINDING_AUTHERROR  401
+#define ERR_ESDL_BINDING_BADACCOUNT 402
+#define ERR_ESDL_BINDING_BADREQUEST 403
+#define ERR_ESDL_BINDING_BADABI     410
+#define ERR_ESDL_BINDING_BADBRAND   411
+#define ERR_ESDL_BINDING_BADBROKER  412
+#define ERR_ESDL_BINDING_TESTCASE   413
+#define ERR_ESDL_BINDING_BADVERSION 414
+#define ERR_ESDL_BINDING_UNEXPECTED 498
+#define ERR_ESDL_BINDING_UNAVAIL    499
+#define ERR_ESDL_BINDING_INTERNERR  999
+
+//#define ESDL_TRANS_START_AT_ROOT
+#define ESDL_BINDING_RESPONSE_XML   0x02000
+#define ESDL_BINDING_RESPONSE_JSON  0x04000
+#define ESDL_BINDING_REQUEST_XML    0x08000
+#define ESDL_BINDING_REQUEST_JSON   0x10000
+
+#define CACHED_RESULT_NAME  "_cached_result"
+#define REQ_REF_NUM_NAME    "_req_ref_num"
+#define MCACHE_OBJECT_KEY   "_mcache_object_key_"
+
+class EsdlServiceImpl : public CInterface, implements IEspService
+{
+private:
+    IEspContainer *container;
+    MapStringToMyClass<ISmartSocketFactory> connMap;
+
+public:
+    StringBuffer                m_espServiceType;
+    StringBuffer                m_espServiceName;
+    StringBuffer                m_espProcName;
+    Owned<IPropertyTree>        m_pServiceConfig;
+    Owned<IPropertyTree>        m_pServiceMethodTargets;
+    Owned<IEsdlTransformer>     m_pEsdlTransformer;
+
+public:
+    IMPLEMENT_IINTERFACE;
+    EsdlServiceImpl()  {}
+
+    ~EsdlServiceImpl();
+
+    virtual const char * getServiceType()
+    {
+        return m_espServiceType.str();
+    }
+
+    virtual bool init(const char * name, const char * type, IPropertyTree * cfg, const char * process)
+    {
+        init(cfg, process, name);
+        return true;
+    }
+
+    virtual void setContainer(IEspContainer * container_)
+    {
+        container = container_;
+    }
+
+    virtual void setEsdlTransformer(IEsdlTransformer * transformer)
+    {
+        m_pEsdlTransformer.setown(transformer);
+    }
+
+    virtual void clearDESDLState()
+    {
+        if(m_pEsdlTransformer)
+            m_pEsdlTransformer.clear();
+        if(m_pServiceMethodTargets)
+            m_pServiceMethodTargets.clear();
+    }
+
+    virtual void init(const IPropertyTree *cfg, const char *process, const char *service);
+    virtual void configureTargets(IPropertyTree *cfg, const char *service);
+    virtual void handleServiceRequest(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, Owned<IPropertyTree> &tgtcfg, Owned<IPropertyTree> &tgtctx, const char *ns, const char *schema_location, IPropertyTree *req, StringBuffer &out, StringBuffer &logdata, unsigned int flags);
+    virtual void generateTransactionId(IEspContext & context, StringBuffer & trxid)=0;
+    void generateTargetURL(IEspContext & context, IPropertyTree *srvinfo, StringBuffer & url, bool isproxy);
+    void sendTargetSOAP(IEspContext & context, IPropertyTree *srvinfo, const char * req, StringBuffer &resp, bool isproxy,const char * targeturl);
+    virtual IPropertyTree *createTargetContext(IEspContext &context, IPropertyTree *tgtcfg, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *req_pt){return NULL;}
+    virtual IPropertyTree *createInsContextForRoxieTest(IEspContext &context, IPropertyTree *tgtcfg, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *req_pt){return NULL;}
+    virtual void getTargetResponseFile(IEspContext & context, IPropertyTree *srvinfo, const char * req, StringBuffer &resp);
+    virtual void esdl_log(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *tgtcfg, IPropertyTree *tgtctx, IPropertyTree *req_pt, const char *xmlresp, const char *logdata, unsigned int timetaken){}
+    virtual void processHeaders(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, const char *ns, StringBuffer &req, StringBuffer &headers){};
+    virtual void processRequest(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, const char *ns, StringBuffer &req, StringBuffer &hashedReq) {};
+    virtual void processResponse(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, const char *ns, StringBuffer &resp,StringBuffer &hashedReq) {};
+    virtual void createServersList(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, StringBuffer &servers) {};
+
+    void handleEchoTest(const char *mthName, IPropertyTree *req, StringBuffer &soapResp, unsigned flags=0);
+    virtual void handleFinalRequest(IEspContext &context, Owned<IPropertyTree> &tgtcfg, Owned<IPropertyTree> &tgtctx, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, const char *ns, StringBuffer& req, StringBuffer &out, bool isroxie, bool isproxy);
+    void getSoapBody(StringBuffer& out,StringBuffer& soapresp);
+    void getSoapError(StringBuffer& out,StringBuffer& soapresp,const char *,const char *);
+    virtual void generateHashFromReq(IEsdlDefService &srvdef,
+                                    IEsdlDefMethod &mthdef,
+                                    const StringBuffer &req,
+                                    StringBuffer &hashedReq) {};
+};
+
+//RODRIGO: BASE URN should be configurable.
+#define ESDLBINDING_URN_BASE "urn:hpccsystems:ws"
+
+class EsdlBindingImpl : public CHttpSoapBinding
+{
+private:
+    //==========================================================================================
+    // the following class implements notification handler for subscription to dali for environment
+    // updates by other clients.
+    //==========================================================================================
+    class CESDLBindingSubscription : public CInterface, implements ISDSSubscription
+    {
+    private :
+        CriticalSection daliSubscriptionCritSec;
+        SubscriptionId sub_id;
+        EsdlBindingImpl * thisBinding;
+
+    public:
+        CESDLBindingSubscription(EsdlBindingImpl * binding)
+        {
+            thisBinding = binding;
+            VStringBuffer fullBindingPath("/ESDL/Bindings/Binding[@id=\'%s.%s\']",thisBinding->m_processName.get(),thisBinding->m_bindingName.get());
+            CriticalBlock b(daliSubscriptionCritSec);
+            try
+            {
+                sub_id = querySDS().subscribe(fullBindingPath.str(), *this, true);
+            }
+            catch (IException *E)
+            {
+                // failure to subscribe implies dali is down... is this ok??
+                // Is this bad enough to halt the esp load process??
+                E->Release();
+            }
+        }
+
+        virtual ~CESDLBindingSubscription()
+        {
+            unsubscribe();
+        }
+
+        void unsubscribe()
+        {
+            CriticalBlock b(daliSubscriptionCritSec);
+            try
+            {
+                if (sub_id)
+                {
+                    querySDS().unsubscribe(sub_id);
+                    sub_id = 0;
+                }
+            }
+            catch (IException *E)
+            {
+                E->Release();
+            }
+            sub_id = 0;
+        }
+
+        IMPLEMENT_IINTERFACE;
+        void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen=0, const void *valueData=NULL);
+    };
+
+    class CESDLDefinitionSubscription : public CInterface, implements ISDSSubscription
+    {
+    private :
+        CriticalSection daliSubscriptionCritSec;
+        SubscriptionId sub_id;
+        EsdlBindingImpl * thisBinding;
+
+        public:
+        CESDLDefinitionSubscription(EsdlBindingImpl * binding)
+        {
+            thisBinding = binding;
+            //for some reason subscriptions based on xpaths with attributes don't seem to work correctly
+            //fullBindingPath.set("/ESDL/Bindings/Binding[@EspBinding=\'WsAccurint\'][@EspProcess=\'myesp\']");
+
+            CriticalBlock b(daliSubscriptionCritSec);
+            try
+            {
+                sub_id = querySDS().subscribe(ESDL_DEF_PATH, *this, true);
+            }
+            catch (IException *E)
+            {
+                // failure to subscribe implies dali is down... is this ok??
+                // Is this bad enough to halt the esp load process??
+                E->Release();
+            }
+        }
+
+        virtual ~CESDLDefinitionSubscription()
+        {
+            unsubscribe();
+        }
+
+        void unsubscribe()
+        {
+            CriticalBlock b(daliSubscriptionCritSec);
+            try
+            {
+                if (sub_id)
+                {
+                    querySDS().unsubscribe(sub_id);
+                    sub_id = 0;
+                }
+            }
+            catch (IException *E)
+            {
+                E->Release();
+            }
+            sub_id = 0;
+        }
+
+        IMPLEMENT_IINTERFACE;
+        void notify(SubscriptionId id, const char *xpath, SDSNotifyFlags flags, unsigned valueLen=0, const void *valueData=NULL);
+    };
+
+    Owned<IPropertyTree>                    m_bndCfg;
+    Owned<IPropertyTree>                    m_esdlBndCfg;
+
+    Owned<IEsdlDefinition>                  m_esdl;
+    Owned<IEsdlDefinitionHelper>            m_xsdgen;
+
+    StringArray                             m_esdlDefinitions;
+    StringAttr                              m_bindingName;
+    StringAttr                              m_processName;
+    StringAttr                              m_espServiceName; //previously held the esdl service name, we are now
+                                                              //supporting mismatched ESP Service name assigned to a different named ESDL service definition
+    Owned<CESDLBindingSubscription>         m_pBindingSubscription;
+    Owned<CESDLDefinitionSubscription>      m_pDefinitionSubscription;
+    CriticalSection                         configurationLoadCritSec;
+
+    virtual void clearDESDLState()
+    {
+        if (m_esdl)
+            m_esdl.clear();
+        if(m_esdlBndCfg)
+            m_esdlBndCfg.clear();
+        if (m_pESDLService)
+            m_pESDLService->clearDESDLState();
+        //prob need to un-initesdlservinfo as well.
+        DBGLOG("Warning binding %s.%s is being un-loaded!", m_processName.get(), m_bindingName.get());
+    }
+
+public:
+    EsdlServiceImpl * m_pESDLService;
+    //CIArrayOf<EsdlServiceImpl> m_esdlServices;
+    IMPLEMENT_IINTERFACE;
+
+    EsdlBindingImpl();
+    EsdlBindingImpl(IPropertyTree* cfg, const char *bindname=NULL, const char *procname=NULL);
+
+    ~EsdlBindingImpl()
+    {
+    }
+
+    virtual void initEsdlServiceInfo(IEsdlDefService &srvdef);
+
+    virtual void addService(const char * name, const char * host, unsigned short port, IEspService & service);
+
+    int onGetInstantQuery(IEspContext &context, CHttpRequest* request, CHttpResponse* response,    const char *serviceName, const char *methodName);
+    int HandleSoapRequest(CHttpRequest* request, CHttpResponse* response);
+
+    void handleHttpPost(CHttpRequest *request, CHttpResponse *response);
+    void handleJSONPost(CHttpRequest *request, CHttpResponse *response);
+
+    int onGetXsd(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *serviceName, const char *methodName);
+    virtual bool getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, const char *service, const char *method, bool standalone);
+    int onGetWsdl(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *serviceName, const char *methodName);
+    int onGetXForm(IEspContext &context, CHttpRequest* request,   CHttpResponse* response, const char *serv, const char *method);
+    virtual int onGetFile(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *pathex);
+    int getJsonTestForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response);
+    void getRequestContent(IEspContext &context, StringBuffer & req, CHttpRequest* request, const char * servicename, const char * methodname, const char *ns, unsigned flags);
+    void setXslProcessor(IInterface *xslp){}
+
+    int getQualifiedNames(IEspContext& ctx, MethodInfoArray & methods);
+
+    StringBuffer & getServiceName(StringBuffer & resp)
+    {
+        return resp.append( m_pESDLService->getServiceType());
+    }
+    bool isValidServiceName(IEspContext &context, const char *name)
+    {
+        return strieq(name,  m_pESDLService->getServiceType());
+    }
+    bool qualifyServiceName(IEspContext &context, const char *servname, const char *methname, StringBuffer &servQName, StringBuffer *methQName);
+    virtual bool qualifyMethodName(IEspContext &context, const char *methname, StringBuffer *methQName);
+    void getSoapMessage(StringBuffer& soapmsg, IEspContext& ctx, CHttpRequest* request, const char *serv, const char *method);
+    virtual const char *queryServiceType()=0;
+    virtual StringBuffer &generateNamespace(IEspContext &context, CHttpRequest* request, const char *serv, const char *method, StringBuffer &ns);
+    virtual int onGetReqSampleXml(IEspContext &ctx, CHttpRequest* request, CHttpResponse* response, const char *serv, const char *method);
+    virtual int onGetRespSampleXml(IEspContext &ctx, CHttpRequest* request, CHttpResponse* response, const char *serv, const char *method);
+    virtual void handleSoapRequestException(IException *e, const char *source);
+
+    int onGetSampleXml(bool isRequest, IEspContext &ctx, CHttpRequest* request, CHttpResponse* response, const char *serv, const char *method);
+    static void splitURLList(const char* urlList, StringBuffer& protocol,StringBuffer& UserName,StringBuffer& Password, StringBuffer& ipportlistbody, StringBuffer& path, StringBuffer& options);
+    static void transformGatewaysConfig( IPropertyTree* srvcfg, IPropertyTree* forRoxie );
+    static bool makeURL( StringBuffer& url, IPropertyTree& cfg );
+
+    bool usesESDLDefinition(const char * name, int version);
+    bool usesESDLDefinition(const char * id);
+
+private:
+    int onGetRoxieBuilder(CHttpRequest* request, CHttpResponse* response, const char *serv, const char *method);
+    int onRoxieRequest(CHttpRequest* request, CHttpResponse* response, const char *  method);
+    bool getRoxieConfig(StringBuffer & queryName, StringBuffer & url, StringBuffer & username, StringBuffer & password, const char *method);
+    void getSoapMessage(StringBuffer& out,StringBuffer& soapresp,const char * starttxt,const char * endtxt);
+
+    bool reloadBinding(const char *binding, const char *process);
+    bool reloadDefinitions(IPropertyTree * esdlBndCng);
+};
+
+#endif //_EsdlBinding_HPP__

+ 102 - 0
esp/services/esdl_svc_engine/esdl_svc_engine.cpp

@@ -0,0 +1,102 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+#pragma warning (disable : 4786)
+
+#include "esdl_svc_engine.hpp"
+#include "params2xml.hpp"
+
+void CEsdlSvcEngine::init(IPropertyTree *cfg, const char *process, const char *service)
+{
+    EsdlServiceImpl::init(cfg, process, service);
+
+    m_service_ctx.setown( createPTree("Context", false) );
+    ensurePTree(m_service_ctx, "Row");
+}
+
+CEsdlSvcEngine::~CEsdlSvcEngine()
+{
+}
+
+CEsdlSvcEngineSoapBindingEx::CEsdlSvcEngineSoapBindingEx()
+{
+}
+
+CEsdlSvcEngineSoapBindingEx::CEsdlSvcEngineSoapBindingEx(IPropertyTree* cfg, const char *bindname, const char *procname) : EsdlBindingImpl(cfg, bindname, procname)
+{
+}
+
+void CEsdlSvcEngineSoapBindingEx::handleSoapRequestException(IException *e, const char *source)
+{
+    WsErrorType  errorType = WSERR_NOERR;
+
+    const int    errorcode = e->errorCode();
+    StringBuffer errorMessage;
+    e->errorMessage(errorMessage);
+
+    ESPLOG(LogMax,"EsdlBindingImpl:HandleSoapRequest response error code: %d /nmerror message: %s",  errorcode, errorMessage.str());
+
+    IWsException *wsex = dynamic_cast<IWsException *> (e);
+
+    switch (errorcode){
+    case ERR_ESDL_BINDING_AUTHERROR: case ERR_ESDL_BINDING_BADACCOUNT: case ERR_ESDL_BINDING_BADABI:
+    case ERR_ESDL_BINDING_BADBRAND:  case ERR_ESDL_BINDING_BADBROKER:  case ERR_ESDL_BINDING_TESTCASE:
+        errorType = WSERR_CLIENT ;
+        break;
+    case 2:
+        e->Release();
+        wsex = makeWsException(ERR_ESDL_BINDING_BADREQUEST, WSERR_CLIENT, source, errorMessage.str());
+        break;
+    default:
+        errorType = WSERR_SERVER;
+        break;
+    }
+
+    if ( wsex )
+        throw wsex;
+    else
+        throw makeWsException( *e, errorType, source );
+}
+
+IPropertyTree *CEsdlSvcEngine::createTargetContext(IEspContext &context, IPropertyTree *tgtcfg, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *req_pt)
+{
+    const char *querytype = tgtcfg->queryProp("@querytype");
+    if (!querytype || !strieq(querytype, "ROXIE")) //only roxie?
+        return NULL;
+
+    StringBuffer trxid;
+    generateTransactionId(context, trxid);
+
+    Owned<IPropertyTree> localCtx(createPTreeFromIPT(m_service_ctx, ipt_none));
+    ensurePTree(localCtx, "Row/Common");
+    localCtx->setProp("Row/Common/TransactionId", trxid.str());
+
+    return localCtx.getLink();
+}
+
+void CEsdlSvcEngine::generateTransactionId(IEspContext & context, StringBuffer & trxid)
+{
+    //RANDOMNUM_DATE for now.
+    CriticalBlock b(trxIdCritSec);
+    Owned<IJlibDateTime> _timeNow =  createDateTimeNow();
+    SCMStringBuffer _dateString;
+    _timeNow->getDateString(_dateString);
+    trxid.appendf("%u_%s",getRandom(),_dateString.str());
+}
+
+void CEsdlSvcEngine::esdl_log(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *tgtcfg, IPropertyTree *tgtctx, IPropertyTree *req_pt, const char *rawresp, const char *logdata, unsigned int timetaken)
+{
+}

+ 68 - 0
esp/services/esdl_svc_engine/esdl_svc_engine.hpp

@@ -0,0 +1,68 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef _ESPWIZ_Esdl_SVC_Engine_HPP__
+#define _ESPWIZ_Esdl_SVC_Engine_HPP__
+
+#include "esdl_binding.hpp"
+#include "wsexcept.hpp"
+#include "dasds.hpp"
+
+class CEsdlSvcEngine : public EsdlServiceImpl
+{
+private:
+    CriticalSection trxIdCritSec;
+
+public:
+    Owned<IPropertyTree> m_service_ctx;
+
+    IMPLEMENT_IINTERFACE;
+    CEsdlSvcEngine(){}
+
+    ~CEsdlSvcEngine();
+
+    virtual void init(IPropertyTree *cfg, const char *process, const char *service);
+    void generateTransactionId(IEspContext & context, StringBuffer & trxid);
+    virtual IPropertyTree *createTargetContext(IEspContext &context, IPropertyTree *tgtcfg, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *req_pt);
+    virtual void esdl_log(IEspContext &context, IEsdlDefService &srvdef, IEsdlDefMethod &mthdef, IPropertyTree *tgtcfg, IPropertyTree *tgtctx, IPropertyTree *req_pt, const char *xmlresp, const char *logdata, unsigned int timetaken);
+};
+
+class CEsdlSvcEngineSoapBindingEx : public EsdlBindingImpl
+{
+public:
+
+public:
+    IMPLEMENT_IINTERFACE;
+
+    CEsdlSvcEngineSoapBindingEx();
+    CEsdlSvcEngineSoapBindingEx(IPropertyTree* cfg, const char *bindname=NULL, const char *procname=NULL);
+
+    ~CEsdlSvcEngineSoapBindingEx()
+    {
+    }
+
+    virtual void addService(const char * name, const char * host, unsigned short port, IEspService & service)
+    {
+         m_pESDLService = dynamic_cast<CEsdlSvcEngine*>(&service);
+        EsdlBindingImpl::addService(name, host, port, service);
+    }
+
+    virtual const char *queryServiceType(){return  m_pESDLService->getServiceType();}
+    virtual void handleSoapRequestException(IException *e, const char *source);
+};
+
+#endif //_ESPWIZ_Esdl_SVC_Engine_HPP__

+ 51 - 0
esp/services/esdl_svc_engine/esdl_svc_engine_plugin.cpp

@@ -0,0 +1,51 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#pragma warning (disable : 4786)
+
+//ESP Bindings
+#include "http/platform/httpprot.hpp"
+
+//ESP Service
+#include "esdl_svc_engine.hpp"
+
+#include "espplugin.hpp"
+
+extern "C"
+{
+
+ESP_FACTORY IEspService * esp_service_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process)
+{
+    CEsdlSvcEngine* service = new CEsdlSvcEngine;
+    service->init(cfg, process, name);
+    return service;
+}
+
+ESP_FACTORY IEspRpcBinding * esp_binding_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process)
+{
+    return new CEsdlSvcEngineSoapBindingEx(cfg, name, process);
+}
+
+IEspProtocol * http_protocol_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process);
+
+
+ESP_FACTORY IEspProtocol * esp_protocol_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process)
+{
+    return http_protocol_factory(name, type, cfg, process);
+}
+
+};

+ 65 - 0
esp/services/ws_esdlconfig/CMakeLists.txt

@@ -0,0 +1,65 @@
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+################################################################################
+
+
+# Component: ws_esdlconfig
+#####################################################
+# Description:
+# ------------
+#    Cmake Input File for ws_esdlconfig
+#####################################################
+
+project( ws_esdlconfig )
+
+
+#include(${HPCC_LN_SOURCE_DIR}/esp/scm/lnespscm.cmake)
+include(${HPCC_SOURCE_DIR}/esp/scm/espscm.cmake)
+
+set (    SRCS
+         ${ESPSCM_GENERATED_DIR}/ws_esdlconfig_esp.cpp
+         ws_esdlconfigplugin.cpp
+         ws_esdlconfigservice.cpp
+    )
+
+include_directories (
+         ${HPCC_SOURCE_DIR}/dali/base
+         ${HPCC_SOURCE_DIR}/common/environment
+         ${HPCC_SOURCE_DIR}/system/include
+         ${HPCC_SOURCE_DIR}/system/jlib
+         ${HPCC_SOURCE_DIR}/system/security/shared
+         ${HPCC_SOURCE_DIR}/system/security/securesocket
+         ${HPCC_SOURCE_DIR}/system/security/LdapSecurity
+         ${HPCC_SOURCE_DIR}/system/mp
+         ${HPCC_SOURCE_DIR}/system/xmllib
+         ${HPCC_SOURCE_DIR}/esp/platform
+         ${HPCC_SOURCE_DIR}/esp/clients
+         ${HPCC_SOURCE_DIR}/esp/bindings
+         ${HPCC_SOURCE_DIR}/esp/bindings/SOAP/xpp
+         ${HPCC_SOURCE_DIR}/esp/bindings/http/platform
+         ${HPCC_SOURCE_DIR}/esp/smc/SMCLib
+         ${HPCC_SOURCE_DIR}/esp/services/esdl_svc_engine
+         ${HPCC_SOURCE_DIR}/esp/esdllib
+    )
+
+ADD_DEFINITIONS( -D_USRDLL )
+
+HPCC_ADD_LIBRARY( ws_esdlconfig SHARED ${SRCS} )
+install ( TARGETS ws_esdlconfig RUNTIME DESTINATION bin LIBRARY DESTINATION lib )
+target_link_libraries ( ws_esdlconfig
+         jlib
+         esphttp
+         environment
+    )

+ 25 - 0
esp/services/ws_esdlconfig/esdlconfig_errors.h

@@ -0,0 +1,25 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef ESDLCONFIG_ERRORS_H_
+#define ESDLCONFIG_ERRORS_H_
+
+#include "errorlist.h"
+
+#define ESDL_MISSING_PARAM      ESDL_PROCESS_ERROR_START+1
+
+#endif /* ESDLCONFIG_ERRORS_H_ */

+ 90 - 0
esp/services/ws_esdlconfig/ws_esdlconfigplugin.cpp

@@ -0,0 +1,90 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#pragma warning (disable : 4786)
+
+#ifndef WsESDLConfig_API
+#ifdef _WIN32
+#define WsESDLConfig_API __declspec(dllexport)
+#else
+#define WsESDLConfig_API
+#endif //_WIN32
+#endif //WsESDLConfig_API
+
+#include "ws_esdlconfig_esp.ipp"
+
+//ESP Bindings
+#include "httpprot.hpp"
+
+//ESP Service
+#include "ws_esdlconfigservice.hpp"
+
+#include "espplugin.hpp"
+
+extern "C"
+{
+//when we aren't loading dynamically
+// Change the function names when we stick with dynamic loading.
+ESP_FACTORY IEspService * esp_service_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process)
+{
+    if (strcmp(type, "ws_esdlconfig")==0)
+    {
+        CWsESDLConfigEx* service = new CWsESDLConfigEx;
+
+        service->init(cfg, process, name);
+        return service;
+    }
+    return NULL;
+}
+
+
+
+ESP_FACTORY IEspRpcBinding * esp_binding_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process)
+{
+    if (strcmp(type, "ws_esdlconfigSoapBinding")==0)
+    {
+#ifdef _DEBUG
+        http_soap_log_level log_level_ = hsl_all;
+#else
+        http_soap_log_level log_level_ = hsl_none;
+#endif
+        return new CWsESDLConfigSoapBindingEx(cfg, name, process, log_level_);
+    }
+
+    return NULL;
+}
+
+ESP_FACTORY IEspProtocol * esp_protocol_factory(const char *name, const char* type, IPropertyTree *cfg, const char *process)
+{
+    if (strcmp(type, "http_protocol")==0)
+    {
+        return new CHttpProtocol;
+    }
+    else if(strcmp(type, "secure_http_protocol") == 0)
+    {
+        IPropertyTree *sslSettings;
+        sslSettings = cfg->getPropTree(StringBuffer("Software/EspProcess[@name=\"").append(process).append("\"]").append("/EspProtocol[@name=\"").append(name).append("\"]").str());
+        if(sslSettings != NULL)
+        {
+            return new CSecureHttpProtocol(sslSettings);
+        }
+    }
+
+    return NULL;
+}
+
+};

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1235 - 0
esp/services/ws_esdlconfig/ws_esdlconfigservice.cpp


+ 62 - 0
esp/services/ws_esdlconfig/ws_esdlconfigservice.hpp

@@ -0,0 +1,62 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef _ESPWIZ_WsESDLConfig_HPP__
+#define _ESPWIZ_WsESDLConfig_HPP__
+
+#include "ws_esdlconfig_esp.ipp"
+#include "esdlconfig_errors.h"
+
+static const char* FEATURE_URL="ESDLConfigAccess";
+
+class CWsESDLConfigSoapBindingEx : public CWsESDLConfigSoapBinding
+{
+public:
+    CWsESDLConfigSoapBindingEx(IPropertyTree *cfg, const char *name, const char *process, http_soap_log_level llevel=hsl_none) : CWsESDLConfigSoapBinding(cfg, name, process, llevel) {}
+    virtual void getNavigationData(IEspContext &context, IPropertyTree & data){};
+};
+
+class CWsESDLConfigEx : public CWsESDLConfig
+{
+public:
+    IMPLEMENT_IINTERFACE;
+    virtual ~CWsESDLConfigEx(){};
+    virtual void init(IPropertyTree *cfg, const char *process, const char *service);
+    static bool existsESDLDefinition(const char * servicename, unsigned ver);
+    static bool existsESDLDefinition(const char * definitionid);
+    static bool existsESDLMethodDef(const char * esdlDefinitionName, unsigned ver, const char * esdlServiceName, const char * methodName);
+    static int publishESDLBinding(const char * bindingName, IPropertyTree * methodsConfig, const char * espProcName, const char * espPort, const char * esdlDefinitionName, int esdlDefinitionVersion, const char * esdlServiceName, StringBuffer & message, bool overwrite);
+    static IPropertyTree * getEspProcessRegistry(const char * espprocname, const char * espbingingport, const char * servicename);
+    static void ensureESDLServiceBindingRegistry(const char * espProcName, const char * espBindingName, bool readonly);
+    static IPropertyTree * getESDLDefinitionRegistry(const char * wsEclId, bool readonly);
+    static void addESDLDefinition(IPropertyTree * queryRegistry, const char * name, IPropertyTree * definitionInfo, StringBuffer &newId, unsigned &newSeq, const char *userid, bool deleteprev);
+    static int publishESDLMethod(const char * espProcName, const char * espBindingName, const char * srvDefId, const char * methodName, IPropertyTree * attributesTree, bool readonly, StringBuffer & message);
+    static int getBindingXML(const char * espProcName, const char * espBindingName, StringBuffer & bindingXml, StringBuffer & msg);
+
+    bool onGetESDLBinding(IEspContext &context, IEspGetESDLBindingRequest &req, IEspGetESDLBindingResponse &resp);
+    bool onEcho(IEspContext &context, IEspEchoRequest &req, IEspEchoResponse &resp);
+    bool onPublishESDLDefinition(IEspContext &context, IEspPublishESDLDefinitionRequest &req, IEspPublishESDLDefinitionResponse &resp);
+    bool onPublishESDLBinding(IEspContext &context, IEspPublishESDLBindingRequest &req, IEspPublishESDLBindingResponse &resp);
+    bool onConfigureESDLBindingMethod(IEspContext &context, IEspConfigureESDLBindingMethodRequest &req, IEspConfigureESDLBindingMethodResponse &resp);
+    bool onDeleteESDLBinding(IEspContext &context, IEspDeleteESDLBindingRequest &req, IEspDeleteESDLRegistryEntryResponse &resp);
+    bool onDeleteESDLDefinition(IEspContext &context, IEspDeleteESDLDefinitionRequest &req, IEspDeleteESDLRegistryEntryResponse &resp);
+    bool onGetESDLDefinition(IEspContext &context, IEspGetESDLDefinitionRequest&req, IEspGetESDLDefinitionResponse &resp);
+    bool onListESDLDefinitions(IEspContext &context, IEspListESDLDefinitionsRequest&req, IEspListESDLDefinitionsResponse &resp);
+    bool onListESDLBindings(IEspContext &context, IEspListESDLBindingsRequest&req, IEspListESDLBindingsResponse &resp);
+};
+
+#endif //_ESPWIZ_WsESDLConfig_HPP__

+ 3 - 0
esp/xslt/CMakeLists.txt

@@ -40,6 +40,9 @@ FOREACH( iFILES
     ${CMAKE_CURRENT_SOURCE_DIR}/wsecl3_jsontest.xsl
     ${CMAKE_CURRENT_SOURCE_DIR}/wsecl3_result.xslt
     ${CMAKE_CURRENT_SOURCE_DIR}/passwordupdate.xsl
+    ${CMAKE_CURRENT_SOURCE_DIR}/esdl2ecl.xslt
+    ${CMAKE_CURRENT_SOURCE_DIR}/esxdl2xsd.xslt
+    ${CMAKE_CURRENT_SOURCE_DIR}/roxie_page.xsl
 )
     Install ( FILES ${iFILES} DESTINATION componentfiles/xslt COMPONENT Runtime )
 ENDFOREACH ( iFILES )

+ 333 - 0
esp/xslt/esdl2ecl.xslt

@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+##############################################################################
+# HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##############################################################################
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+	<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
+	<xsl:param name="sourceFileName" select="'UNKNOWN'"/>
+	<xsl:variable name="docname" select="/expesdl/esxdl/@name"/>
+	<xsl:template match="/">
+		<xsl:apply-templates select="expesdl"/>
+	</xsl:template>
+	<xsl:template name="doNotChangeManuallyComment">
+		<xsl:text>/*** Not to be hand edited (changes will be lost on re-generation) ***/
+/*** ECL Interface generated by esdl2ecl version 1.0 from </xsl:text><xsl:copy-of select="$sourceFileName"/> <xsl:text>.xml. ***/
+/*===================================================*/
+
+</xsl:text>
+	</xsl:template>
+	<xsl:template match="expesdl">
+			<xsl:apply-templates select="esxdl"/>
+	</xsl:template>
+	<xsl:template match="esxdl">
+	             <xsl:call-template name="doNotChangeManuallyComment"/>
+			<xsl:text>export </xsl:text>
+			<xsl:choose>
+				<xsl:when test="starts-with(@name, 'wsm_')"><xsl:value-of select="substring(@name, 5)"/></xsl:when>
+				<xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
+			</xsl:choose>
+			<xsl:text> := MODULE
+
+</xsl:text>
+		<xsl:if test="$docname='wsm_share'">
+		<xsl:text>export t_IntegerArrayItem := record
+	integer value { xpath('')};
+end;
+
+export t_StringArrayItem := record
+	string value { xpath(''), MAXLENGTH(8192) };
+end;
+
+</xsl:text>
+		</xsl:if>
+		<xsl:apply-templates select="EsdlStruct"/>
+		<xsl:apply-templates select="EsdlRequest"/>
+		<xsl:apply-templates select="EsdlResponse"/>
+
+		<xsl:text>
+end;
+
+</xsl:text>
+          <xsl:call-template name="doNotChangeManuallyComment"/>
+	</xsl:template>
+
+	<xsl:template match="EsdlElement[@complex_type]">
+		<xsl:if test="not(@ecl_hide) and (@ecl_keep or not(@get_data_from))">
+		  <xsl:text>	</xsl:text><xsl:call-template name="output_ecl_complex_type"/><xsl:text> </xsl:text> <xsl:call-template name="output_ecl_name"/><xsl:text> {</xsl:text><xsl:call-template name="output_xpath"/><xsl:text>};</xsl:text><xsl:call-template name="output_comments"/>
+          <xsl:text>
+</xsl:text>
+		</xsl:if>
+	</xsl:template>
+	<xsl:template match="EsdlElement[@type]">
+		<xsl:if test="not(@ecl_hide) and (@ecl_keep or not(@get_data_from))">
+			<xsl:text>	</xsl:text><xsl:call-template name="output_basic_type"/><xsl:text> </xsl:text><xsl:call-template name="output_ecl_name"/><xsl:text> {</xsl:text><xsl:call-template name="output_xpath"/><xsl:if test="@ecl_max_len"><xsl:text>, maxlength(</xsl:text><xsl:value-of select="@ecl_max_len"/><xsl:text>)</xsl:text></xsl:if><xsl:text>};</xsl:text><xsl:call-template name="output_comments"/>
+<xsl:text>
+</xsl:text>
+		</xsl:if>
+	</xsl:template>
+	<xsl:template match="EsdlEnum">
+		<xsl:variable name="entype" select="@enum_type"/>
+		<xsl:text>	</xsl:text><xsl:call-template name="output_enum_type"/><xsl:text> </xsl:text><xsl:call-template name="output_ecl_name"/><xsl:text> {</xsl:text><xsl:call-template name="output_xpath"/><xsl:text>}; </xsl:text><xsl:call-template name="output_comments"/>
+<xsl:text>
+</xsl:text>
+	</xsl:template>
+	<xsl:template match="EsdlArray[@type='string']">
+		<xsl:if test="not(@ecl_hide) and (@ecl_keep or not(@get_data_from))">
+		<xsl:text>	dataset(</xsl:text><xsl:call-template name="output_arrayitem_ref"/><xsl:text>) </xsl:text><xsl:call-template name="output_ecl_name"/>
+		<xsl:text> {xpath('</xsl:text>
+		<xsl:if test="not(@flat_array)"><xsl:value-of select="@name"/></xsl:if><xsl:text>/</xsl:text><xsl:call-template name="output_item_tag"/><xsl:text>')</xsl:text>
+		<xsl:choose>
+			<xsl:when test="@max_count_var"><xsl:text>, MAXCOUNT(</xsl:text><xsl:value-of select="@max_count_var"/><xsl:text>)</xsl:text></xsl:when>
+			<xsl:when test="@max_count"><xsl:text>, MAXCOUNT(</xsl:text><xsl:value-of select="@max_count"/><xsl:text>)</xsl:text></xsl:when>
+				<xsl:otherwise><xsl:text>, MAXCOUNT(1)</xsl:text></xsl:otherwise>
+		</xsl:choose>
+		<xsl:text>};</xsl:text><xsl:call-template name="output_comments"/>
+		<xsl:text>&#xa;</xsl:text>
+	</xsl:if>
+	</xsl:template>
+	<xsl:template match="EsdlArray[starts-with(@ecl_type,'string') or starts-with(@ecl_type,'unicode')]">
+		<xsl:if test="not(@ecl_hide) and (@ecl_keep or not(@get_data_from))">
+          <xsl:text>&#9;</xsl:text>
+		  <xsl:value-of select="@ecl_type"/><xsl:text> </xsl:text><xsl:call-template name="output_ecl_name"/>
+		  <xsl:text> {xpath('</xsl:text>
+		  <xsl:value-of select="@name"/>
+		  <xsl:text>')};</xsl:text>
+		  <xsl:call-template name="output_comments"/>
+		  <xsl:text>&#xa;</xsl:text>
+        </xsl:if>
+	</xsl:template>
+	<xsl:template match="EsdlArray">
+		<xsl:if test="not(@ecl_hide) and (@ecl_keep or not(@get_data_from))">
+			<xsl:text>	dataset(</xsl:text> <xsl:call-template name="output_ecl_array_type"/><xsl:text>) </xsl:text><xsl:call-template name="output_ecl_name"/>
+            <xsl:text> {xpath('</xsl:text>
+			<xsl:if test="not(@flat_array)"><xsl:value-of select="@name"/></xsl:if><xsl:text>/</xsl:text><xsl:call-template name="output_item_tag"/><xsl:text>')</xsl:text>
+			<xsl:choose>
+				<xsl:when test="@max_count_var"><xsl:text>, MAXCOUNT(</xsl:text><xsl:value-of select="@max_count_var"/><xsl:text>)</xsl:text></xsl:when>
+				<xsl:when test="@max_count"><xsl:text>, MAXCOUNT(</xsl:text><xsl:value-of select="@max_count"/><xsl:text>)</xsl:text></xsl:when>
+				<xsl:otherwise><xsl:text>, MAXCOUNT(1)</xsl:text></xsl:otherwise>
+			</xsl:choose>
+		<xsl:text>};</xsl:text><xsl:call-template name="output_comments"/>
+		<xsl:text>
+</xsl:text>
+		</xsl:if>
+	</xsl:template>
+
+	<xsl:template match="EsdlStruct">
+		<xsl:if test="not(@ecl_hide) and (@ecl_keep or not(@get_data_from))">
+			<xsl:text>export t_</xsl:text><xsl:call-template name="output_ecl_name"/><xsl:text> := record</xsl:text><xsl:if test="@RecordCode"><xsl:text> //RecordCode[</xsl:text><xsl:value-of select="@RecordCode"/><xsl:text>]</xsl:text></xsl:if>
+			<xsl:if test="@base_type"><xsl:call-template name="output_ecl_base_type"/></xsl:if>
+			<xsl:if test="@max_len"><xsl:text>, MAXLENGTH (</xsl:text><xsl:value-of select="@max_len"/><xsl:text>)</xsl:text></xsl:if>
+			<xsl:text>
+</xsl:text>
+			<xsl:apply-templates select="*"/>
+			<xsl:if test="@element and not(*[@name='Content_'])">	string Content_ {xpath('')};
+</xsl:if>
+			<xsl:text>end;
+
+</xsl:text>
+		</xsl:if>
+	</xsl:template>
+
+	<xsl:template match="EsdlRequest">
+		<xsl:text>export t_</xsl:text><xsl:call-template name="output_ecl_name"/><xsl:text> := record</xsl:text>
+		<xsl:if test="@base_type"><xsl:call-template name="output_ecl_base_type"/></xsl:if>
+		<xsl:if test="@max_len"><xsl:text>, MAXLENGTH (</xsl:text><xsl:value-of select="@max_len"/><xsl:text>)</xsl:text></xsl:if>
+		<xsl:text>
+</xsl:text>
+		<xsl:apply-templates select="*"/>
+		<xsl:text>end;
+
+</xsl:text>
+	</xsl:template>
+
+	<xsl:template match="EsdlResponse">
+		<xsl:text>export t_</xsl:text><xsl:call-template name="output_ecl_name"/><xsl:text> := record</xsl:text>
+		<xsl:if test="@base_type"><xsl:call-template name="output_ecl_base_type"/></xsl:if>
+		<xsl:if test="@max_len"><xsl:text>, MAXLENGTH (</xsl:text><xsl:value-of select="@max_len"/><xsl:text>)</xsl:text></xsl:if>
+		<xsl:text>
+</xsl:text>
+		<xsl:apply-templates select="*"/>
+		<xsl:text>end;
+
+</xsl:text>
+	</xsl:template>
+
+
+<xsl:template name="output_ecl_name">
+
+<xsl:choose>
+	<xsl:when test="@ecl_name"><xsl:value-of select="@ecl_name"/></xsl:when>
+	<xsl:otherwise>
+		<xsl:variable name="nameword" select="translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
+		<xsl:if test="/expesdl/keywords/keyword[@word=$nameword]"><xsl:text>_</xsl:text></xsl:if><xsl:value-of select="@name"/>
+	</xsl:otherwise>
+</xsl:choose>
+
+</xsl:template>
+
+<xsl:template name="output_basic_type">
+	<xsl:param name="basic_type" select="@type"/>
+	<xsl:param name="size" select="@max_len"/>
+	<xsl:choose>
+		<xsl:when test="@ecl_type"><xsl:value-of select="@ecl_type"/><xsl:if test="not(@ecl_max_len)"><xsl:value-of select="$size"/></xsl:if></xsl:when>
+		<xsl:when test="$basic_type='int'"><xsl:text>integer</xsl:text><xsl:if test="not(@ecl_max_len)"><xsl:value-of select="$size"/></xsl:if></xsl:when>
+		<xsl:when test="$basic_type='long'"><xsl:text>integer4</xsl:text><xsl:if test="not(@ecl_max_len)"><xsl:value-of select="$size"/></xsl:if></xsl:when>
+		<xsl:when test="$basic_type='short'"><xsl:text>integer2</xsl:text></xsl:when>
+		<xsl:when test="$basic_type='bool'"><xsl:text>boolean</xsl:text></xsl:when>
+		<xsl:when test="$basic_type='string'"><xsl:text>string</xsl:text><xsl:if test="not(@ecl_max_len)"><xsl:value-of select="$size"/></xsl:if></xsl:when>
+		<xsl:when test="$basic_type='double'"><xsl:text>real8</xsl:text></xsl:when>
+		<xsl:when test="$basic_type='float'"><xsl:text>real4</xsl:text></xsl:when>
+		<xsl:when test="$basic_type='base64Binary'"><xsl:text>string</xsl:text></xsl:when>
+		<xsl:when test="$basic_type"><xsl:value-of select="$basic_type"/><xsl:if test="not(@ecl_max_len)"><xsl:value-of select="$size"/></xsl:if></xsl:when>
+		<xsl:otherwise><xsl:text>string</xsl:text><xsl:if test="not(@ecl_max_len)"><xsl:value-of select="$size"/></xsl:if></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="output_enum_type">
+	<xsl:variable name="etype" select="@enum_type"/>
+	<xsl:choose>
+		<xsl:when test="/expesdl/types/type[@name=$etype]/@base_type">
+			<xsl:call-template name="output_basic_type">
+				<xsl:with-param name="basic_type" select="/expesdl/types/type[@name=$etype]/@base_type"/>
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:call-template name="output_basic_type"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+
+
+<xsl:template name="output_ecl_base_type">
+	<xsl:variable name="btype" select="@base_type"/>
+	<xsl:if test="@base_type">
+		<xsl:variable name="srcfile" select="/expesdl/types/type[@name=$btype]/@src"/>
+		<xsl:text> (</xsl:text>
+		<xsl:if test="$sourceFileName != $srcfile">
+			<xsl:value-of select="$srcfile"/><xsl:text>.</xsl:text>
+		</xsl:if>
+		<xsl:text>t_</xsl:text><xsl:value-of select="$btype"/><xsl:text>)</xsl:text>
+	</xsl:if>
+</xsl:template>
+
+<xsl:template name="output_ecl_complex_type">
+	<xsl:variable name="ctype" select="@complex_type"/>
+	<xsl:choose>
+		<xsl:when test="@ecl_type"><xsl:value-of select="@ecl_type"/></xsl:when>
+		<xsl:otherwise>
+			<xsl:variable name="srcfile" select="/expesdl/types/type[@name=$ctype]/@src"/>
+			<xsl:if test="$sourceFileName != $srcfile">
+				<xsl:value-of select="$srcfile"/><xsl:text>.</xsl:text>
+			</xsl:if>
+			<xsl:text>t_</xsl:text><xsl:value-of select="$ctype"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="output_ecl_array_type">
+	<xsl:variable name="ctype" select="@type"/>
+	<xsl:choose>
+		<xsl:when test="@ecl_type"><xsl:value-of select="@ecl_type"/></xsl:when>
+		<xsl:otherwise>
+			<xsl:variable name="srcfile" select="/expesdl/types/type[@name=$ctype]/@src"/>
+			<xsl:if test="$sourceFileName != $srcfile">
+				<xsl:value-of select="$srcfile"/><xsl:text>.</xsl:text>
+			</xsl:if>
+			<xsl:text>t_</xsl:text><xsl:value-of select="$ctype"/>
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="output_comments">
+	<xsl:if test="@ecl_comment"><xsl:value-of select="@ecl_comment"/></xsl:if>
+	<xsl:choose>
+		<xsl:when test="@complex_type">
+			<xsl:variable name="ctype" select="@complex_type"/>
+			<xsl:if test="/expesdl/types/type[@name=$ctype]/@comment">
+				<xsl:text>//</xsl:text><xsl:value-of select="/expesdl/types/type[@name=$ctype]/@comment"/>
+			</xsl:if>
+		</xsl:when>
+		<xsl:when test="@enum_type">
+			<xsl:variable name="etype" select="@enum_type"/>
+			<xsl:if test="/expesdl/types/type[@name=$etype]/@comment">
+				<xsl:text>//</xsl:text><xsl:value-of select="/expesdl/types/type[@name=$etype]/@comment"/>
+			</xsl:if>
+		</xsl:when>
+	</xsl:choose>
+	<xsl:if test="@optional">
+		<xsl:text>//hidden[</xsl:text><xsl:value-of select="@optional"/><xsl:text>]</xsl:text>
+	</xsl:if>
+	<xsl:if test="@ecl_type and (@type or @complex_type)">
+        <xsl:choose>
+         <xsl:when test="name()='EsdlArray'">
+           <xsl:text> // Real type: </xsl:text>
+           <xsl:text>dataset(t_</xsl:text>
+           <xsl:value-of select="@type"/>
+           <xsl:text>) </xsl:text>
+           <xsl:call-template name="output_ecl_name"/>
+           <xsl:text> {xpath('</xsl:text>
+           <xsl:value-of select="@name"/>
+           <xsl:text>/</xsl:text>
+           <xsl:call-template name="output_item_tag"/>
+           <xsl:text>')};</xsl:text>
+         </xsl:when>
+         <xsl:when test="name()='EsdlElement' and starts-with(@ecl_type,'tns:')">
+           <xsl:text> // Real type: RECORD t_</xsl:text>
+           <xsl:value-of select="@type|@complex_type"/>
+         </xsl:when>
+         <xsl:when test="name()='EsdlElement' and not(starts-with(@ecl_type,'tns:'))">
+           <xsl:text> // Xsd type: </xsl:text>
+           <xsl:value-of select="@type|@complex_type"/>
+         </xsl:when>
+         <xsl:otherwise>
+             <xsl:value-of select="@type"/>
+         </xsl:otherwise>
+        </xsl:choose>
+    </xsl:if>
+</xsl:template>
+
+<xsl:template name="output_xpath">
+	<xsl:text>xpath('</xsl:text>
+	<xsl:choose>
+		<xsl:when test="@ecl_path"><xsl:value-of select="@ecl_path"/></xsl:when>
+		<xsl:otherwise><xsl:if test="@attribute"><xsl:value-of select="'@'"/></xsl:if> <xsl:value-of select="@name"/></xsl:otherwise>
+	</xsl:choose>
+	<xsl:text>')</xsl:text>
+</xsl:template>
+
+<xsl:template name="output_arrayitem_ref">
+	<xsl:choose>
+		<xsl:when test="@ecl_item"><xsl:text>t_</xsl:text><xsl:value-of select="@ecl_item"/></xsl:when>
+		<xsl:otherwise><xsl:if test="$sourceFileName!='share'"><xsl:text>share.</xsl:text></xsl:if><xsl:text>t_StringArrayItem</xsl:text></xsl:otherwise>
+	</xsl:choose>
+</xsl:template>
+
+<xsl:template name="output_item_tag">
+    <xsl:choose>
+         <xsl:when test="@item_tag"><xsl:value-of select="@item_tag"/></xsl:when>
+         <xsl:when test="@type and (@type='int' or @type='integer' or @type='bool' or @type='short' or @type='float' or @type='double' or @type='string' or @type='long' or @type='decimal' or @type='byte' or @type='unsignedInt' or @type='unsignedShort' or @type='unsignedByte')">
+           <xsl:value-of select="'Item'"/>
+         </xsl:when>
+         <xsl:when test="@type">
+           <xsl:value-of select="@type"/>
+         </xsl:when>
+         <xsl:otherwise><xsl:value-of select="'Item'"/></xsl:otherwise>
+    </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet>

+ 448 - 0
esp/xslt/esxdl2xsd.xslt

@@ -0,0 +1,448 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+##############################################################################
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
+    <xsl:param name="create_wsdl" select="false()"/>
+    <xsl:param name="location" select="'http://localhost:8000/WsService?ver_=0'"/>
+    <xsl:param name="tnsParam" select="/esxdl/@ns_uri"/>
+    <xsl:param name="version" select="/esxdl/@version"/>
+    <xsl:param name="no_annot_Param" select="false()"/>
+    <xsl:param name="all_annot_Param" select="false()"/>
+
+    <!--
+        Note: This version of the stylesheet assumes that the XML input has been processed
+        in the following ways:
+
+        - All structures not explicitly referenced or used in another structure
+          have been stripped out.
+        - All ancestor structure's elements are collapsed into the defintion
+          of their children.
+        - In order for ArrayOf definitions to be generated, the esdl XML this processes
+          must have the desired structures marked with 'arrayOf="1"' attributes.
+    -->
+
+    <xsl:template match="esxdl">
+        <xsl:choose>
+            <xsl:when test="$create_wsdl">
+                <xsl:call-template name="CreateWsdl"/>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:call-template name="CreateSchema"/>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+
+    <xsl:template match="EsdlStruct">
+        <xsd:complexType>
+          <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+          <!--
+            Only emit the xsd group element if our current struct has at least one child node.
+          -->
+          <xsl:if test="child::*[1]">
+            <xsl:variable name="xsd_group">
+              <xsl:choose>
+                <xsl:when test="@xsd_group"><xsl:value-of select="@xsd_group"/></xsl:when>
+                <xsl:otherwise>all</xsl:otherwise>
+              </xsl:choose>
+            </xsl:variable>
+            <xsl:element name="xsd:{$xsd_group}">
+              <xsl:apply-templates select="EsdlElement|EsdlArray|EsdlEnum"/>
+            </xsl:element>
+          </xsl:if>
+        </xsd:complexType>
+        <!--
+            Under the original non-esdl schema/wsdl generation, when an EspArray is defined:
+
+                ESParray<ESPstruct RedFlag> RedFlags;
+
+            it causes the the output of a separate complexType named 'ArrayOfRedFlags'.
+            Contrast that with an ESParray definition like:
+
+                ESParray<ESPstruct RiskIndicator, HighRiskIndicator> HighRiskIndicators;
+
+            which generates XSD output consisting of an unnamed complexType in place.
+          We duplicate that behavior by adding an 'arrayOf' attribute to EsdlStruct
+          definitions which are used in such ArrayOf definitions. In addition to the
+          actual struct's defn output above, we output it's related ArrayOf defn below.
+        -->
+        <xsl:if test="@arrayOf='1'">
+            <!--
+                For whatever reason the current non-esdl based XSD/WSDL generator always
+                generates an 'ArrayOfName' defn whenever an 'ArrayOfNameEx' is generated
+                even if ArrayOfName is never used. Duplicate this behavior here but it's
+                isolated to this one location so will be easy to remove if desired.
+            -->
+            <xsl:if test="@name='NameEx'">
+                <xsd:complexType name="ArrayOfName">
+                    <xsd:sequence>
+                        <xsd:element minOccurs="0" maxOccurs="unbounded" name="Name" type="tns:Name"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsl:if>
+            <xsd:complexType>
+                <xsl:attribute name="name">ArrayOf<xsl:value-of select="@name"/></xsl:attribute>
+                <xsd:sequence>
+                    <xsd:element minOccurs="0" maxOccurs="unbounded">
+                        <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+                            <xsl:attribute name="type">tns:<xsl:value-of select="@name"/></xsl:attribute>
+                    </xsd:element>
+                </xsd:sequence>
+            </xsd:complexType>
+        </xsl:if>
+        <!--
+            This structure has been marked as the first to use an array EspStringArray
+            so a separate EspStringArray structure definition must be generated.
+        -->
+        <xsl:if test="@espStringArray='1'">
+            <xsd:complexType name="EspStringArray">
+                <xsd:sequence>
+                    <xsd:element name="Item" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
+                </xsd:sequence>
+            </xsd:complexType>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template match="EsdlElement">
+        <xsd:element>
+            <xsl:if test="not(@required)">
+                <xsl:attribute name="minOccurs">0</xsl:attribute>
+            </xsl:if>
+            <xsl:attribute name="name">
+                <xsl:choose>
+                    <xsl:when test="@xml_tag"><xsl:value-of select="@xml_tag"/></xsl:when>
+                    <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
+                </xsl:choose>
+            </xsl:attribute>
+            <xsl:attribute name="type">
+                <xsl:choose>
+                    <xsl:when test="@xsd_type"><xsl:value-of select="@xsd_type"/></xsl:when>
+                    <xsl:when test="@type='bool'">xsd:<xsl:value-of select="'boolean'"/></xsl:when>
+                    <xsl:when test="@type='unsigned'">xsd:<xsl:value-of select="'unsignedInt'"/></xsl:when>
+                    <xsl:when test="@type">xsd:<xsl:value-of select="@type"/></xsl:when>
+                    <xsl:when test="@complex_type">tns:<xsl:value-of select="@complex_type"/></xsl:when>
+                </xsl:choose>
+            </xsl:attribute>
+            <!--
+                There are some .ecm files which use 'boolean' instead of 'bool', and for some reason those fields
+                don't ever have a 'default' attribute when the XSD is generated. Reproduce that behavior here:
+             -->
+            <xsl:if test="@default and @type != 'boolean'">
+                <xsl:attribute name="default">
+                    <xsl:choose>
+                        <xsl:when test="@type='bool' and @default='1'">true</xsl:when>
+                        <xsl:when test="@type='bool' and @default='0'">false</xsl:when>
+                        <!--
+                                The Request defined in wsm_echotest.ecm has a default value which includes some
+                                characters normally encoded (eg &amp;) in an XSDs attribute. The XSD currently
+                                generated by the ESPs doesn't encode them. I've hardcoded the default value here
+                                to duplicate that behavior. The XML generated by the esdl_def code encodes the
+                                characters already encoded so they'd need a double-decoding here. This seemed the
+                                simplest solution. Perhaps we need to revisit when and what the esdl_def toXML code
+                                encodes and what it doesn't.
+                         -->
+                        <xsl:when test="@name='ValueIn' and ../@name='EchoTestRequest' and starts-with(./@default, 'Test')">
+                            <xsl:text disable-output-escaping="yes">Test string: &lt;abc&gt; &amp; &lt;def&gt;</xsl:text>
+                        </xsl:when>
+                        <xsl:otherwise><xsl:value-of select="@default"/></xsl:otherwise>
+                    </xsl:choose>
+                </xsl:attribute>
+            </xsl:if>
+            <xsl:if test="boolean($all_annot_Param)">
+                <xsl:if test="@html_head or @form_ui or @collapsed or @cols or @rows">
+                    <xsd:annotation>
+                        <xsd:appinfo>
+                            <form>
+                                <xsl:if test="@form_ui">
+                                    <xsl:attribute name="ui"><xsl:value-of disable-output-escaping="yes" select="@form_ui"/></xsl:attribute>
+                                </xsl:if>
+                                <xsl:if test="@html_head">
+                                    <xsl:attribute name="html_head"><xsl:value-of disable-output-escaping="yes" select="@html_head"/></xsl:attribute>
+                                </xsl:if>
+                                <xsl:if test="@collapsed">
+                                    <xsl:attribute name="collapsed">
+                                        <xsl:choose>
+                                            <xsl:when test="@collapsed=1">true</xsl:when>
+                                            <xsl:otherwise>false</xsl:otherwise>
+                                        </xsl:choose>
+                                    </xsl:attribute>
+                                </xsl:if>
+                                <xsl:if test="@cols">
+                                    <xsl:attribute name="formCols"><xsl:value-of select="@cols"/></xsl:attribute>
+                                </xsl:if>
+                                <xsl:if test="@rows">
+                                    <xsl:attribute name="formRows"><xsl:value-of select="@rows"/></xsl:attribute>
+                                </xsl:if>
+                            </form>
+                        </xsd:appinfo>
+                    </xsd:annotation>
+                    </xsl:if>
+                </xsl:if>
+        </xsd:element>
+    </xsl:template>
+
+    <xsl:template match="EsdlEnumItem" mode="annotation">
+        <xsl:if test="@desc">
+            <item>
+                <xsl:attribute name="name"><xsl:value-of select="@enum"/></xsl:attribute>
+                <xsl:attribute name="description"><xsl:value-of select="@desc"/></xsl:attribute>
+            </item>
+        </xsl:if>
+    </xsl:template>
+
+    <xsl:template match="EsdlEnumItem">
+        <xsd:enumeration>
+            <xsl:attribute name="value"><xsl:value-of select="@enum"/></xsl:attribute>
+        </xsd:enumeration>
+    </xsl:template>
+
+    <xsl:template match="EsdlEnumType">
+        <xsd:simpleType>
+            <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+            <!--
+                EnumType has annotation only if it's EnumItems have @desc attributes.
+                Check the first EnumItem to see if it has a @desc attribute
+             -->
+            <xsl:if test="(EsdlEnumItem[@desc]) and EsdlEnumItem/@desc!=''">
+                <xsl:if test="not($no_annot_Param) or boolean($all_annot_Param)">
+                    <xsd:annotation>
+                        <xsd:appinfo>
+                            <xsl:apply-templates select="EsdlEnumItem" mode="annotation" />
+                        </xsd:appinfo>
+                    </xsd:annotation>
+                </xsl:if>
+            </xsl:if>
+            <xsd:restriction>
+                <xsl:attribute name="base">xsd:<xsl:value-of select="@base_type"/></xsl:attribute>
+                <xsl:apply-templates select="EsdlEnumItem"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsl:template>
+
+    <xsl:template match="EsdlEnum">
+        <xsd:element>
+            <xsl:choose>
+                <xsl:when test="@required"></xsl:when>
+                <xsl:otherwise>
+                    <xsl:attribute name="minOccurs">0</xsl:attribute>
+                </xsl:otherwise>
+            </xsl:choose>
+            <xsl:attribute name="name">
+                <xsl:choose>
+                    <xsl:when test="@xml_tag"><xsl:value-of select="@xml_tag" /></xsl:when>
+                    <xsl:otherwise><xsl:value-of select="@name" /></xsl:otherwise>
+                </xsl:choose>
+            </xsl:attribute>
+            <xsl:attribute name="type">
+                <xsl:choose>
+                    <xsl:when test="@xsd_type"><xsl:value-of select="@xsd_type" /></xsl:when>
+                    <xsl:when test="@enum_type">tns:<xsl:value-of select="@enum_type" /></xsl:when>
+                </xsl:choose>
+            </xsl:attribute>
+            <xsl:if test="@default or (@default='')">
+                <xsl:attribute name="default"><xsl:value-of select="@default"/></xsl:attribute>
+            </xsl:if>
+        </xsd:element>
+    </xsl:template>
+    <xsl:template match="EsdlArray">
+        <xsl:choose>
+            <xsl:when test="boolean(@item_tag)">
+                <xsd:element minOccurs="0">
+                    <xsl:attribute name="name">
+                        <xsl:choose>
+                            <xsl:when test="@xml_tag"><xsl:value-of select="@xml_tag"/></xsl:when>
+                            <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
+                        </xsl:choose>
+                    </xsl:attribute>
+                    <xsd:complexType>
+                        <xsd:sequence>
+                            <xsd:element minOccurs="0" maxOccurs="unbounded">
+                                <xsl:attribute name="name"><xsl:value-of select="@item_tag"/></xsl:attribute>
+                                <xsl:choose>
+                                    <xsl:when test="@type='string'">
+                                        <xsl:attribute name="type">xsd:string</xsl:attribute>
+                                    </xsl:when>
+                                    <xsl:otherwise>
+                                        <xsl:attribute name="type">tns:<xsl:value-of select="@type"/></xsl:attribute>
+                                    </xsl:otherwise>
+                                </xsl:choose>
+                            </xsd:element>
+                        </xsd:sequence>
+                    </xsd:complexType>
+                </xsd:element>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:choose>
+                    <xsl:when test="@type='string'">
+                        <!--
+                            Adjust the element definition so that it's type is tns:EspStringArray to
+                            match the behavior of the current generator. Note that this doesn't generate
+                            the actual EspStringArray defn, just a reference to where it's used.
+                         -->
+                        <xsd:element minOccurs="0">
+                            <xsl:attribute name="name">
+                                <xsl:choose>
+                                    <xsl:when test="@xml_tag"><xsl:value-of select="@xml_tag"/></xsl:when>
+                                    <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
+                                </xsl:choose>
+                            </xsl:attribute>
+                            <xsl:attribute name="type">tns:EspStringArray</xsl:attribute>
+                        </xsd:element>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsd:element minOccurs="0">
+                            <xsl:attribute name="name">
+                                <xsl:choose>
+                                    <xsl:when test="@xml_tag"><xsl:value-of select="@xml_tag"/></xsl:when>
+                                    <xsl:otherwise><xsl:value-of select="@name"/></xsl:otherwise>
+                                </xsl:choose>
+                            </xsl:attribute>
+                            <xsl:attribute name="type">tns:ArrayOf<xsl:value-of select="@type"/></xsl:attribute>
+                        </xsd:element>
+                    </xsl:otherwise>
+                </xsl:choose>
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+    <xsl:template match="EsdlRequest">
+        <xsd:element>
+            <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+            <xsd:complexType>
+                <xsd:all>
+                    <xsl:apply-templates select="EsdlElement|EsdlArray|EsdlEnum"/>
+                </xsd:all>
+            </xsd:complexType>
+        </xsd:element>
+    </xsl:template>
+    <xsl:template match="EsdlResponse">
+        <xsd:element>
+            <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+            <xsd:complexType>
+                <xsd:all>
+                    <xsl:apply-templates select="EsdlElement|EsdlArray|EsdlEnum"/>
+                </xsd:all>
+            </xsd:complexType>
+        </xsd:element>
+    </xsl:template>
+    <xsl:template match="EsdlService">
+        <wsdl:message name="EspSoapFault">
+            <wsdl:part name="parameters" element="tns:Exceptions"/>
+        </wsdl:message>
+        <xsl:for-each select="/esxdl/EsdlMethod">
+            <wsdl:message>
+                <xsl:attribute name="name"><xsl:value-of select="@name"/>SoapIn</xsl:attribute>
+                <wsdl:part name="parameters">
+                    <xsl:attribute name="element">tns:<xsl:value-of select="@request_type"/></xsl:attribute>
+                </wsdl:part>
+            </wsdl:message>
+            <wsdl:message>
+                <xsl:attribute name="name"><xsl:value-of select="@name"/>SoapOut</xsl:attribute>
+                <wsdl:part name="parameters">
+                    <xsl:attribute name="element">tns:<xsl:value-of select="@response_type"/></xsl:attribute>
+                </wsdl:part>
+            </wsdl:message>
+        </xsl:for-each>
+        <wsdl:portType>
+            <xsl:attribute name="name"><xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
+            <xsl:for-each select="/esxdl/EsdlMethod">
+                <wsdl:operation>
+                    <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+                    <wsdl:input>
+                        <xsl:attribute name="message">tns:<xsl:value-of select="@name"/>SoapIn</xsl:attribute>
+                    </wsdl:input>
+                    <wsdl:output>
+                        <xsl:attribute name="message">tns:<xsl:value-of select="@name"/>SoapOut</xsl:attribute>
+                    </wsdl:output>
+                    <wsdl:fault name="excfault" message="tns:EspSoapFault"/>
+                </wsdl:operation>
+            </xsl:for-each>
+        </wsdl:portType>
+        <wsdl:binding>
+            <xsl:attribute name="name"><xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
+            <xsl:attribute name="type">tns:<xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
+            <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
+            <xsl:for-each select="/esxdl/EsdlMethod">
+                <wsdl:operation>
+                    <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+                    <soap:operation style="document">
+                        <xsl:attribute name="soapAction"><xsl:value-of select="../@name"/>/<xsl:value-of select="@name"/>?ver_=<xsl:value-of select="$version"/></xsl:attribute>
+                    </soap:operation>
+                    <wsdl:input>
+                        <soap:body use="literal"/>
+                    </wsdl:input>
+                    <wsdl:output>
+                        <soap:body use="literal"/>
+                    </wsdl:output>
+                    <wsdl:fault name="excfault">
+                        <soap:fault name="excfault" use="literal"/>
+                    </wsdl:fault>
+                </wsdl:operation>
+            </xsl:for-each>
+        </wsdl:binding>
+        <wsdl:service>
+            <xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
+            <wsdl:port>
+                <xsl:attribute name="name"><xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
+                <xsl:attribute name="binding">tns:<xsl:value-of select="@name"/>ServiceSoap</xsl:attribute>
+                <soap:address location="{$location}"/>
+            </wsdl:port>
+        </wsdl:service>
+    </xsl:template>
+    <xsl:template name="CreateSchema">
+        <xsl:param name="inwsdl" select="false()"/>
+        <xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+            <xsl:attribute name="targetNamespace"><xsl:value-of select="$tnsParam"/></xsl:attribute>
+            <xsl:copy-of select="namespace::tns"/>
+
+            <xsd:element name="string" nillable="true" type="xsd:string"/>
+            <xsd:complexType name="EspException">
+                <xsd:all>
+                    <xsd:element name="Code" type="xsd:string" minOccurs="0"/>
+                    <xsd:element name="Audience" type="xsd:string" minOccurs="0"/>
+                    <xsd:element name="Source" type="xsd:string" minOccurs="0"/>
+                    <xsd:element name="Message" type="xsd:string" minOccurs="0"/>
+                </xsd:all>
+            </xsd:complexType>
+            <xsd:complexType name="ArrayOfEspException">
+                <xsd:sequence>
+                    <xsd:element name="Source" type="xsd:string" minOccurs="0"/>
+                    <xsd:element name="Exception" type="tns:EspException" minOccurs="0" maxOccurs="unbounded"/>
+                </xsd:sequence>
+            </xsd:complexType>
+            <xsd:element name="Exceptions" type="tns:ArrayOfEspException"/>
+            <xsl:apply-templates select="EsdlEnumType" />
+            <xsl:apply-templates select="EsdlStruct"/>
+            <xsl:apply-templates select="EsdlRequest"/>
+            <xsl:apply-templates select="EsdlResponse"/>
+
+        </xsd:schema>
+    </xsl:template>
+    <xsl:template name="CreateWsdl">
+        <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/">
+            <xsl:attribute name="targetNamespace"><xsl:value-of select="$tnsParam"/></xsl:attribute>
+            <xsl:copy-of select="namespace::tns"/>
+            <wsdl:types>
+                <xsl:call-template name="CreateSchema">
+                    <xsl:with-param name="inwsdl" select="true()"/>
+                </xsl:call-template>
+            </wsdl:types>
+            <xsl:apply-templates select="EsdlService[1]"/>
+        </wsdl:definitions>
+    </xsl:template>
+</xsl:stylesheet>

+ 895 - 0
esp/xslt/roxie_page.xsl

@@ -0,0 +1,895 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+##############################################################################
+-->
+
+<!DOCTYPE xsl:stylesheet [
+    <!ENTITY nbsp "&#160;">
+    <!ENTITY apos "&#39;">
+]>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
+    exclude-result-prefixes="fo">
+    <xsl:output method="html" indent="yes" omit-xml-declaration="yes"
+      doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
+    <!-- ===============================================================================
+  parameters
+  ================================================================================ -->
+    <xsl:param name="serviceName" select="'FormTest'"/>
+    <xsl:param name="methodName" select="'BasicTest'"/>
+    <xsl:param name="destination" select="'zz'"/>
+    <xsl:param name="header" select="'xx'"/>
+    <xsl:param name="roxiebody" select="'yy'"/>
+    <xsl:param name="roxieUrl" select="'aa'"/>
+    <!-- ===============================================================================-->
+    <xsl:template match="/">
+    <html>
+        <head>
+            <title>Roxie Test Page</title>
+
+<script type="text/javascript" src="files_/get_input.js"/>
+<script type="text/javascript" src="files_/stack.js"/>
+<script type="text/javascript" src="files_/stringbuffer.js"/>
+
+<script type="text/javascript">
+<![CDATA[
+  var xmlhttp = null;
+
+function isSpace(ch) {
+    if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
+        return true;
+    return false;
+}
+
+function show_hide_advanced_button(obj, ctrl)
+{
+ if (obj.style.display == 'block') {
+ obj.style.display='none';
+ ctrl.value ="Advanced >>";
+ return ">>";
+ } else {
+ obj.style.display='block';
+ ctrl.value ="Advanced <<";
+ return "<<";
+ }
+}
+
+// return true if succeeded
+function loadXMLDoc(url, user, passwd)
+{
+  // code for Mozilla, etc.
+   if (window.XMLHttpRequest)  {
+     xmlhttp=new XMLHttpRequest();
+  }
+  // code for IE
+  else if (window.ActiveXObject)  {
+     try {
+        xmlhttp=new ActiveXObject("Msxml2.XMLHTTP.4.0");
+    } catch (e) {
+       try {
+           xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
+      } catch (e) {
+         xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
+     }
+   }
+    if (xmlhttp == null) {
+      alert("Can not create XMLHTTP in IE");
+      return false;
+    }
+  }
+
+   if (xmlhttp)  {
+     xmlhttp.onreadystatechange = xmlhttpChange;
+//   alert("url: "+url);
+     xmlhttp.open("POST",url,true, user, passwd);
+
+     //Set headers
+     try
+     {
+        xmlhttp.setRequestHeader('Content-type', document.getElementById("req_content").value);
+
+     } catch (e) {
+         alert("Exception when setRequestHeader(): "+e);
+     }
+
+     var xml = document.getElementById("req_body").value;
+      var button = document.getElementById("sendButton");
+      if (button)
+      {
+          button.value = "Please wait ...";
+          button.disabled = true;
+     }
+
+      document.getElementById("body").style.cursor = "wait";
+      xmlhttp.send(xml);
+  }
+
+   return true;
+}
+
+function xmlEncode(val)
+{
+    return val.toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");
+}
+
+function getAttrs(node)
+{
+     var attrs = node.attributes;
+     if (attrs==null)
+        return "";
+     var s = "";
+     for (var i = 0; i<attrs.length; i++)  {
+         var node = attrs.item(i);
+         s += ' ' + node.nodeName + '=' + '"' + xmlEncode(node.nodeValue) + '"';
+     }
+     //alert("Node: "+node.tagName + "; attrs=" + node.attributes + "; s="+s);
+     return s;
+}
+
+function allSpaces(s)
+{
+   if (s==null) return true;
+   for (var i=0; i<s.length; i++)
+      if ( !isSpace(s.charAt(i)) )
+        return false;
+   return true;
+}
+
+function toXML2(buf, tree)
+{
+      //alert("toXML2: name="+tree.tagName + "; type="+tree.nodeType);
+      switch (tree.nodeType)
+      {
+      case 1: // document.ELEMENT_NODE:
+           var count = tree.childNodes.length;
+           if (count==0)  {
+                 buf.push("<" + tree.tagName + getAttrs(tree) + "/>");
+           } else  {
+               var val = "";
+               var started = false;
+               for (var i=0; i<count; i++)
+               {
+                   var node = tree.childNodes[i];
+
+                    switch (node.nodeType)
+                    {
+                    case 3: // document.TEXT_NODE:
+                      if (!allSpaces(node.nodeValue))
+                        val += xmlEncode(node.nodeValue);
+                     //else  alert("Ignore text node: ["+node.nodeValue+"]");
+                     break;
+                    case 8: // document.COMMENT_NODE:
+                       val += "<!" + "--"+node.nodeValue+"--" + ">";
+                       break;
+                  case 4: // document.CDATA_SECTION_NODE:
+                        val += "<![" + "CDATA[" + node.nodeValue + "]]" + ">";
+                        break;
+               case 7: // document.PROCESSING_INSTRUCTION_NODE:
+                     val += "<?"+node.target + " " + node.data + "?>";
+                     break;
+               case 1: // document.ELEMENT_NODE:
+                    if (!started) {
+                             buf.push( "<"+tree.tagName+getAttrs(tree)+">");
+                             started = true;
+                        }
+                        if (val.length>0) {
+                           buf.push(val);
+                           val = '';
+                        }
+                       toXML2(buf, node);
+                       break;
+
+                    default:
+                        alert("Unhandled node [1]: <" + node.tagName + ">; type: " + node.nodeType );
+                  }
+               }
+
+               if (!started)
+                     buf.push( "<"+tree.tagName+getAttrs(tree) + ">");
+                  buf.push(val + "</" + tree.tagName + ">");
+         }
+         break;
+
+      case 7: // document.PROCESSING_INSTRUCTION_NODE:
+         buf.push( "<?"+tree.target + " " + tree.data + "?>");
+         break;
+
+      case 8: // document.COMMENT_NODE:
+         buf.push("<!" + "--"+node.nodeValue+"--" + ">");
+         break;
+
+      defailt:
+           alert("Unhandled node [2]: <" + tree.tagName + ">; type: " + tree.nodeType );
+      }
+
+      //alert("buf = " + buf.join('|'));
+}
+
+function toXML(tree)
+{
+     var buf = new Array();
+     if (tree)
+         toXML2(buf,tree);
+
+     return buf.join('');
+}
+
+function toXMLIndented2(buf, tree, indent)
+{
+      //alert("toXML2: name="+tree.tagName + "; type="+tree.nodeType);
+      switch (tree.nodeType)
+      {
+      case 1: // document.ELEMENT_NODE:
+           var count = tree.childNodes.length;
+           if (count==0)  {
+                 buf.push(indent + "<" + tree.tagName + getAttrs(tree) + "/>");
+           } else  {
+               var val = "";
+               var started = false;
+               for (var i=0; i<count; i++)
+               {
+                   var node = tree.childNodes[i];
+
+                  switch (node.nodeType)
+                  {
+                  case 3: // document.TEXT_NODE:
+                    if (!allSpaces(node.nodeValue))
+                       val += xmlEncode(node.nodeValue);
+                    //alert("Text node: ["+node.nodeValue+"]");
+                    break;
+                   case 8: // document.COMMENT_NODE:
+                       val += "<!" + "--"+node.nodeValue+"--" + ">";
+                       break;
+                case 4: // document.CDATA_SECTION_NODE:
+                        val += "<![" + "CDATA[" + node.nodeValue + "]]" + ">";
+                        break;
+               case 7: // document.PROCESSING_INSTRUCTION_NODE:
+                     if (val.length==0)
+                         val += indent + " <?"+node.target + " " + node.data + "?>\n";
+                     else // in mixed content environment
+                         val += "<?"+node.target + " " + node.data + "?>";
+                     break;
+               case 1: // document.ELEMENT_NODE:
+                    if (!started) {
+                       buf.push( indent + "<"+tree.tagName+getAttrs(tree) + ">");
+                       started = true;
+                    }
+
+                     if (val.length>0) {
+                        buf.push(val);
+                        val = '';
+                     }
+                       toXMLIndented2(buf, node,indent+' ');
+                       break;
+
+                 default:
+                        alert("Unhandled node [1]: <" + node.tagName + ">; type: " + node.nodeType );
+                }
+               }
+
+                if (!started)
+                     buf.push( indent + "<"+tree.tagName+getAttrs(tree) + ">" + val + "</" + tree.tagName + ">");
+                  else
+                     buf.push(indent + val + "</" + tree.tagName + ">");
+         }
+         break;
+
+      case 7: // document.PROCESSING_INSTRUCTION_NODE:
+         buf.push(indent+ "<?"+tree.target + " " + tree.data + "?>");
+         break;
+
+      case 8: // document.COMMENT_NODE:
+         buf.push("<!" + "--"+node.nodeValue+"--" + ">");
+         break;
+
+      defailt:
+           alert("Unhandled node [2]: <" + tree.tagName + ">; type: " + tree.nodeType );
+      }
+
+      //alert("buf = " + buf.join('|'));
+}
+
+function toXMLIndented(tree)
+{
+     var buf = new Array();
+     if (tree)
+         toXMLIndented2(buf,tree,"");
+
+     return buf.join('\n');
+}
+
+function setResponseBodyHeader()
+{
+    if (xmlhttp.responseText == "")
+    {
+        var msg = "Empty response detected:\n ";
+        msg += "Status Code: " + xmlhttp.status+"\n";
+        alert(msg);
+    }
+    // if "OK"
+    else if (xmlhttp.status==200)
+    {
+        try
+        {
+            //IE
+            xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
+            xmlDoc.async="false";
+            xmlDoc.loadXML(xmlhttp.responseText);
+        }
+        catch(e)
+        {
+            try
+            {
+                //the others
+                parser=new DOMParser();
+                xmlDoc=parser.parseFromString(xmlhttp.responseText,"text/xml");
+            }
+            catch(e)
+            {
+                document.getElementById("resp_body").value = xmlhttp.responseText;
+                alert('Problem parsing response' + e.message);
+                return;
+            }
+        }
+
+        var action = xmlDoc.getElementsByTagName('*')[0].nodeName;
+        // roxie-request and error actions expected as <action><content>XML</content></action>
+        if (action == "roxie-request")
+        {
+            x = xmlDoc.getElementsByTagName('content')[0].childNodes;
+
+            content = '';
+            for (var i = 0; i<x.length;i++)
+                content = content + x[i].nodeValue;
+
+            document.getElementById("resp_body").setAttribute('wrap', 'hard');
+            document.getElementById("resp_body").value = "";
+
+            if (document.getElementById("prettify_resp").checked)
+                document.getElementById("resp_body").value = prettifyXML(content);
+            else
+                document.getElementById("resp_body").value = content;
+        }
+        else if (action == "error")
+        {
+            x = xmlDoc.getElementsByTagName('content')[0].childNodes;
+
+            content = '';
+            for (var i = 0; i<x.length;i++)
+                content = content + x[i].nodeValue;
+
+            document.getElementById("resp_body").value = content;
+        }
+        else
+        {
+            if (document.getElementById("prettify_resp").checked)
+                document.getElementById("resp_body").value = prettifyXML(xmlhttp.responseText);
+            else
+                document.getElementById("resp_body").value = xmlhttp.responseText;
+        }
+    }
+    else
+    {
+        document.getElementById("resp_body").value = xmlhttp.responseText;
+        var msg = "Problem occurred in response:\n ";
+        msg += "Status Code: " + xmlhttp.status+"\n";
+        msg += "Messsage: "+xmlhttp.statusText + "\n";
+        msg += "Response: see Response Body";
+        alert(msg);
+    }
+}
+
+function xmlhttpChange()
+{
+    // if xmlhttp shows "loaded"
+    if (xmlhttp.readyState==4)
+    {
+        var button = document.getElementById("sendButton");
+        if (button)
+        {
+            button.value = "Send Request";
+            button.disabled = false;
+        }
+
+        document.getElementById("body").style.cursor = "default";
+        setResponseBodyHeader();
+    }
+}
+
+function onSendRequest()
+{
+    // check well-formness
+    if (document.getElementById("check_req").checked)
+    {
+        var doc = parseXmlString(document.getElementById("req_body").value);
+        if (!doc) return;
+    }
+
+    if (document.getElementById("req_url").value == "")
+    {
+        alert("Please speficy the target ROXIE url protocol://host:port in the 'Advanced' section");
+        return true;
+    }
+
+    // clear
+    document.getElementById("resp_body").value = "";
+   // document.getElementById("resp_header").value = "";
+
+    var url = "]]><xsl:value-of select="$destination"/><![CDATA[";
+    url = url + "&_RoxieRequest";
+    url = url + "&roxie-url=" + document.getElementById("req_url").value;
+    var user = document.getElementById("username").value;
+    var passwd = document.getElementById("password").value;
+    loadXMLDoc(url,user,passwd);
+    return true;
+}
+
+//-------------------------------------------------------------------
+
+// mozilla only
+function checkForParseError (xmlDocument)
+{
+    var errorNamespace = 'http://www.mozilla.org/newlayout/xml/parsererror.xml';
+    var documentElement = xmlDocument.documentElement;
+    var parseError = { errorCode : 0 };
+    if (documentElement.nodeName == 'parsererror' &&
+        documentElement.namespaceURI == errorNamespace) {
+          parseError.errorCode = 1;
+         var sourceText = documentElement.getElementsByTagNameNS(errorNamespace, 'sourcetext')[0];
+         if (sourceText != null) {
+           parseError.srcText = sourceText.firstChild.data
+        }
+        parseError.reason = documentElement.firstChild.data;
+    }
+    return parseError;
+}
+
+function parseXmlString(xml)
+{
+   var xmlDoc = null;
+
+   try {
+      var dom = new DOMParser();
+      xmlDoc = dom.parseFromString(xml, 'text/xml');
+      var error = checkForParseError(xmlDoc);
+      if (error.errorCode!=0)
+      {
+         alert(error.reason + "\n" + error.srcText);
+         return null;
+      }
+   } catch (e) {
+     try {
+        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+        xmlDoc.async="false";
+        xmlDoc.loadXML(xml);
+        if (xmlDoc.parseError != 0)
+        {
+          alert("XML Parse Error: " + xmlDoc.parseError.reason);
+          return null;
+        }
+     } catch(e) {
+        alert("Error: " + e.name + "\n" + e.message);
+        return null;
+     }
+  }
+
+   if (!xmlDoc)
+     alert("Create xmlDoc failed! You browser is not supported yet.");
+
+   return xmlDoc;
+}
+
+function getRootElement(xmlDom)
+{
+   var root = null;
+   if (xmlDom)
+   {
+     root = xmlDom.firstChild;
+     if (root && root.nodeType!=1) // IE treat <?xml ?> as first child
+     {
+         //alert("firstChild type = " + root.nodeType);
+      root = xmlDom.childNodes[1];
+     }
+   }
+
+   return root;
+}
+
+function isBlank(s)
+{
+   var len = s ? s.length : 0;
+   for (var i=0; i<len; i++)
+   {
+       var ch = s.charAt(i);
+       if (ch != ' ' && ch != '\t' && ch!='\n')
+          return false;
+   }
+   return true;
+}
+
+//-------------------------------------------------------------------
+
+function hasAttr(tree)
+{
+    // some browser (such as IE) does not support hasAttributes()
+    if (tree.hasAttributes)
+        return tree.hasAttributes();
+    else
+        return tree.attributes!=null && tree.attributes.length>0;
+}
+
+function removeEmptyNodes(tree)
+{
+//     alert("Node type: " + tree.nodeType + "\nNode value:"+tree.nodeValue+"\nTag name:"+tree.tagName);
+
+      if (tree.nodeType==1) // ELEMENT_NODE
+      {
+          var count = tree.childNodes.length;
+          if (count==0 && !hasAttr(tree))
+             return null;
+          for (var i = count-1; i>=0; i--)  // do backward so the remove would not invalid the list
+          {
+              var node = tree.childNodes[i];
+              var newnode = removeEmptyNodes(node);
+              if (!newnode)
+                  tree.removeChild(node);
+              else
+                  tree.replaceChild(newnode,node);
+         }
+         return (tree.hasChildNodes()  || hasAttr(tree)) ? tree : null;
+    } else if (tree.nodeType==3) {
+        if ( (isBlank(tree.nodeValue) || tree.nodeValue=='0') && !hasAttr(tree) )
+          return null;
+   }
+
+    return tree;
+}
+
+function getFirstElementNode(tree)
+{
+      if (tree)
+      {
+          var nodes = tree.childNodes;
+        for (var i=0; i<nodes.length; i++)
+        {
+             var node = nodes[i];
+             if (node.nodeType == 1)
+                return node;
+          }
+     }
+
+     return null;
+}
+
+function clearEmptyFields(xml)
+{
+    var doc = parseXmlString(xml);
+    if (!doc) return null;
+    var root = doc.documentElement;
+    var body = getFirstElementNode(root);
+    if (!body) return null;
+    var req = getFirstElementNode(body);
+    if (!req) return null;
+    var reqTag = req.tagName;
+    var newreq = removeEmptyNodes(req);
+    if (!newreq)
+         newreq = doc.createElement(reqTag);
+    body.replaceChild(newreq,req);
+    return root;
+}
+
+function onClearEmptyFields()
+{
+       var ctrl = document.getElementById("req_body");
+       var xml = ctrl.value;
+       var tree = clearEmptyFields(xml);
+
+       if (tree)
+       {
+          var newxml;
+          var prettify = document.getElementById("prettify_req").checked;
+          if (prettify)
+               newxml = toXMLIndented(tree);
+          else
+               newxml = toXML(tree);
+
+          ctrl.value = '<?xml version="1.0" encoding="UTF-8"?>' + (prettify?'\n':'') + newxml;
+       }
+}
+
+function prettifyXML(inXML)
+{
+       var doc = parseXmlString(inXML);
+       return prettifyXMLDom(doc);
+}
+
+function prettifyXMLDom(doc)
+{
+      if (doc)
+       {
+            // IE, Opera do not support xmlVersion, xmlEncoding
+            var version = (doc.xmlVersion==undefined)?"1.0":doc.xmlVersion;
+            var encoding = (doc.xmlEncoding==undefined) ? "utf-8" : doc.xmlEncoding;
+            var xmlDeclare =  '<?xml version="' + version + '" encoding="' + encoding + '"?>';
+            return xmlDeclare + "\n" + toXMLIndented(doc.documentElement);
+       }
+       return "";
+}
+function onPrettifyXML(txtCtrl, chkCtrl)
+{
+       var ctrl = document.getElementById(txtCtrl);
+       if (isBlank(ctrl.value))
+        return;
+       var doc = parseXmlString(ctrl.value);
+       var chkbox = document.getElementById(chkCtrl);
+       var checked =  chkbox.checked;
+       var xmlDeclare = null;
+
+       if (doc) {
+            var version = (doc.xmlVersion==undefined)?"1.0":doc.xmlVersion;
+            var encoding = (doc.xmlEncoding==undefined) ? "utf-8" : doc.xmlEncoding;
+            xmlDeclare =  '<?xml version="' + version + '" encoding="' + encoding + '"?>';
+          doc = doc.documentElement;
+      }
+      else
+          chkbox.checked = !checked;
+
+       var value = ctrl.value;
+       if (doc)
+       {
+           if (checked)
+               value = toXMLIndented(doc);
+          else
+               value = toXML(doc);
+       }
+
+       ctrl.value = xmlDeclare + (checked?'\n':'') + value;
+}
+
+function constructXmlFromConciseForm(txt)
+{
+     var ret = new StringBuffer();
+     var stack = new Stack();
+     var curIdx = 0;
+     var len = txt.length;
+     while (curIdx<len)
+     {
+           while ( isSpace(txt.charAt(curIdx)) ) { curIdx++; }
+           if (txt.charAt(curIdx) == ']')
+           {
+                var tag = stack.pop();
+                if (!tag) {
+                      var msg = "Invalid data: no tag for ]:\n";
+                      msg += txt.substr(0,curIdx+1)+ "<<ERROR<<" + txt.substring(curIdx+1);
+                      alert(msg);
+                      return null;
+                }
+                ret.append("</" + tag + ">");
+                curIdx++;
+                continue;
+           }
+
+           // parse tag
+           var idx =curIdx;
+           while (idx<len) {
+                var ch = txt.charAt(idx);
+                if (ch=='(' || ch =='[')
+                    break;
+                idx++;
+           }
+           // trim spaces
+           var end = idx-1;
+           while ( isSpace(txt.charAt(end)) ) { end--; }
+           var tag = txt.substring(curIdx,end+1);
+           //alert("tag: ["+tag+']');
+           if (ch=='(')
+           {
+                curIdx = idx+1;
+                idx = txt.indexOf(')',curIdx);
+                if (idx<0) { alert("Invalid input: not ending '(' for <"+tag+">"); return null; }
+                ret.append('<'+tag+'>' + txt.substring(curIdx, idx) + '</' + tag + '>');
+                curIdx = idx+1;
+           } else if (ch=='[') {
+                 stack.push(tag);
+                 //alert("stack.push: [" + tag+']');
+                 ret.append('<' + tag + '>');
+                 curIdx = idx+1;
+           } else {
+               alert("Invalid input: ["+ ch + "]; only '(' or '[' is valid after tag <"+tag+">.");
+               return null;
+           }
+     }
+     return ret.toString();
+}
+
+function inputReturnMethod()
+{
+    var txt = gWndObj.value;
+    gWndObjRemoveWatch();
+
+    if (txt!=null && txt!="")
+    {
+       var xml = constructXmlFromConciseForm(txt)
+
+       var tagLen = gMethodName.length+2;
+       if ( xml.substr(0, tagLen) != ('<'+gMethodName+'>') ) {
+           alert("The request must starts with <"+gMethodName+">");
+           return;
+      }
+
+      var head = '<?xml version="1.0" encoding="UTF-8"?>'
+             + '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope"'
+             + ' xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding"'
+             + ' xmlns="http://webservices.seisint.com/' + gServiceName + '">'
+             + ' <soap:Body><'
+             + gMethodName + 'Request>';
+        var end = '</' + gMethodName + 'Request></soap:Body></soap:Envelope>';
+        xml = head + xml.substring(tagLen, xml.length-tagLen-1) + end;
+        document.getElementById('req_body').value =  xml;
+
+        /*TODO: request prettify_req. Why this does not work??
+        var checked = document.getElementById('prettify_req').checked;
+        if (checked) { xml = prettifyXml(xml); }
+        alert(document.getElementById('req_body'));
+        document.getElementById('req_body').value =  xml;
+        alert(document.getElementById('req_body').value);
+        */
+     }
+     document.getElementById('import').disabled = false;
+}
+
+var roxieBody = ']]><xsl:variable name="temp">
+ <xsl:call-template name="string-replace">
+  <xsl:with-param name="src" select="$roxiebody"/>
+  <xsl:with-param name="replace" select="'&#xa;'"/>
+  <xsl:with-param name="by" select="'\r'"/>
+ </xsl:call-template>
+</xsl:variable>
+<xsl:call-template name="string-replace">
+  <xsl:with-param name="src" select="$temp"/>
+  <xsl:with-param name="replace" select="'&#xd;'"/>
+  <xsl:with-param name="by" select="'\n'"/>
+</xsl:call-template><![CDATA[';
+
+function setRoxieBody()
+{
+     var ctrl = document.getElementById("req_body");
+     if (!ctrl) return;
+     ctrl.value = prettifyXML(roxieBody);
+     return true;
+}
+
+]]>
+
+var gServiceName = "<xsl:value-of select="$serviceName"/>";
+var gMethodName = "<xsl:value-of select="$methodName"/>";;
+
+</script>
+        </head>
+        <body id="body" onload="setRoxieBody()">
+            <h3>
+                <xsl:value-of select="concat($serviceName, '::', $methodName)"/>
+                - This transaction will not be logged!
+            </h3>
+            <span id="auth_" style="display:none"> Username: <input type="text" name="username" id="username" value="" size="10"/>
+                            Password:   <input type="password" name="password" id="password" size="10"/>
+            </span>
+                      <hr/>
+             <table width="100%">
+               <th>Request </th> <th>Response</th>
+                <tr>
+                  <td width="50%">
+                 <table width="100%" border="0" cellspacing="0" cellpadding="1">
+
+                    <tr>
+                        <td>
+                           <table width="100%">
+                            <tr> <td align="left"><b>Request Body:</b></td>
+                             <td align="right">
+                                   <input type="button" value="Remove Empty Node" onclick="onClearEmptyFields()"/>
+                                    <input type="checkbox" id="prettify_req" checked="true" onclick="onPrettifyXML('req_body','prettify_req')">Prettify XML</input>
+                                    </td>
+                                 </tr>
+                           </table>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td>
+                            <textarea id="req_body" name="req_body" style="width:100%" rows="30" wrap="on"/>
+                        </td>
+                    </tr>
+                           </table>
+                          </td>
+                           <td width="50%">
+                  <table width="100%" border="0" cellspacing="0" cellpadding="1">
+                    <tr>
+                      <td>
+                       <table width="100%">
+                          <tr>
+                        <td> <b>Response Body:</b>  </td>
+                        <td align="right"><input type="checkbox" id="prettify_resp" checked="true" onclick="onPrettifyXML('resp_body','prettify_resp')">Prettify XML</input>  </td>
+                        </tr>
+                       </table>
+                       </td>
+                    </tr>
+                    <tr>
+                        <td>
+                            <textarea id="resp_body" name="response" style="width:100%" rows="30" wrap="on" readonly="true"></textarea>
+                        </td>
+                    </tr>
+                 </table>
+                </td>
+                </tr>
+                    <tr>
+                        <td align="left">
+                            <input type="button" id="sendButton" value="Send Request" onclick="onSendRequest()"/>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td align="left" class='options'>
+                            <input type='button' id='advanced_button' value='Advanced &gt;&gt;'
+                                onclick='show_hide_advanced_button(document.getElementById("option_span"), document.getElementById("advanced_button"));' />
+                            <span id='option_span' style='display:none'>
+                                <table style="background-color:#DCDCDC">
+                                    <tr>
+                                        <td colspan="2">
+                                        <input type="checkbox" checked="true" id="check_req"> Check well-formness before send</input>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <td>
+                                            <b>Target Roxie URL:</b>
+                                        </td>
+                                        <td>
+                                            <!--input type="text" id="req_host"/-->
+                                            <xsl:element name="input">
+                                                <xsl:attribute name="id">req_url</xsl:attribute>
+                                                <xsl:attribute name="size">25</xsl:attribute>
+                                                <xsl:attribute name="value"><xsl:value-of select="$roxieUrl" /></xsl:attribute>
+                                            </xsl:element>
+                                        </td>
+                                    </tr>
+                                    <textarea id="req_content" style="display:none" rows="1">
+                                        <xsl:value-of select="$header" />
+                                    </textarea>
+                                </table>
+                            </span>
+                        </td>
+                    </tr>
+                </table>
+        </body>
+    </html>
+   </xsl:template>
+   <xsl:template name="string-replace">
+      <xsl:param name="src"/>
+      <xsl:param name="replace"/>
+      <xsl:param name="by"/>
+      <xsl:choose>
+        <xsl:when test="contains($src,$replace)">
+          <xsl:value-of select="substring-before($src,$replace)"/>
+          <xsl:value-of select="$by"/>
+          <xsl:call-template name="string-replace">
+            <xsl:with-param name="src" select="substring-after($src,$replace)"/>
+            <xsl:with-param name="replace" select="$replace"/>
+            <xsl:with-param name="by" select="$by"/>
+          </xsl:call-template>
+        </xsl:when>
+        <xsl:otherwise>
+         <xsl:value-of select="$src"/>
+        </xsl:otherwise>
+      </xsl:choose>
+   </xsl:template>
+</xsl:stylesheet>

+ 2 - 1
initfiles/componentfiles/configxml/@temp/CMakeLists.txt

@@ -22,6 +22,7 @@ FOREACH ( iFILES
     ${CMAKE_CURRENT_SOURCE_DIR}/plugins.xsl
     ${CMAKE_CURRENT_SOURCE_DIR}/esp_service_WsSMC.xsl
     ${CMAKE_CURRENT_SOURCE_DIR}/roxiePlugins.xsl
+    ${CMAKE_CURRENT_SOURCE_DIR}/esp_service_DynamicESDL.xsl
 )
     Install ( FILES ${iFILES} DESTINATION componentfiles/configxml/@temp COMPONENT Runtime )
-ENDFOREACH ( iFILES )
+ENDFOREACH ( iFILES )

+ 67 - 0
initfiles/componentfiles/configxml/@temp/esp_service_DynamicESDL.xsl

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+################################################################################
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:space="default" xmlns:seisint="http://seisint.com"  xmlns:set="http://exslt.org/sets" exclude-result-prefixes="seisint set">
+    <xsl:import href="esp_service.xsl"/>
+
+    <xsl:template match="EspService">
+        <xsl:param name="bindingNode"/>
+        <xsl:param name="authNode"/>
+        <xsl:variable name="serviceType" >
+            <xsl:choose>
+                <xsl:when test="Properties/@type='DynamicESDL'">
+                    <xsl:value-of select="@name"/>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:value-of select="Properties/@type"/>
+                </xsl:otherwise>
+            </xsl:choose>
+        </xsl:variable>
+        <xsl:variable name="serviceName" select="concat($serviceType, '_', @name, '_', $process)"/>
+        <xsl:variable name="bindName" select=" $bindingNode/@name"/>
+        <xsl:variable name="bindType">
+            <xsl:variable name="protocolBasedBindingType" select="Properties/Binding[@protocol=$bindingNode/@protocol]/@type"/>
+                <xsl:choose>
+                    <xsl:when test="string($protocolBasedBindingType)!=''">
+                        <xsl:value-of select="$protocolBasedBindingType"/>
+                    </xsl:when>
+                    <xsl:otherwise>
+                        <xsl:value-of select="Properties/@bindingType"/>
+                    </xsl:otherwise>
+                </xsl:choose>
+        </xsl:variable>
+        <xsl:variable name="servicePlugin">
+            <xsl:call-template name="defineServicePlugin">
+                <xsl:with-param name="plugin" select="Properties/@plugin"/>
+            </xsl:call-template>
+        </xsl:variable>
+        <EspService name="{$serviceName}" type="{$serviceType}" plugin="{$servicePlugin}">
+            <!--xsl:call-template name="processServiceSpecifics">
+                <xsl:with-param name="serviceType" select="$serviceType"/>
+            </xsl:call-template-->
+        </EspService>
+        <EspBinding name="{$bindName}" service="{$serviceName}" protocol="{$bindingNode/@protocol}" type="{$bindType}" plugin="{$servicePlugin}" netAddress="0.0.0.0" port="{$bindingNode/@port}" defaultBinding="true">
+            <xsl:call-template name="bindAuthentication">
+                <xsl:with-param name="bindingNode" select="$bindingNode"/>
+                <xsl:with-param name="authMethod" select="$authNode/@method"/>
+                <xsl:with-param name="service" select="Properties/@type"/>
+            </xsl:call-template>
+        </EspBinding>
+    </xsl:template>
+</xsl:stylesheet>

+ 26 - 0
initfiles/componentfiles/configxml/@temp/esp_service_WsSMC.xsl

@@ -121,6 +121,10 @@ This is required by its binding with ESP service '<xsl:value-of select="$espServ
             <xsl:with-param name="bindingNode" select="$bindingNode"/>
             <xsl:with-param name="authNode" select="$authNode"/>
         </xsl:apply-templates>
+        <xsl:apply-templates select="." mode="WsESDLConfig">
+            <xsl:with-param name="bindingNode" select="$bindingNode"/>
+            <xsl:with-param name="authNode" select="$authNode"/>
+        </xsl:apply-templates>
     </xsl:template>
 
     <!-- WS-SMC -->
@@ -535,6 +539,28 @@ This is required by its binding with ESP service '<xsl:value-of select="$espServ
         </EspBinding>
     </xsl:template>
 
+<!-- WS-ESDLCONFIG -->
+    <xsl:template match="EspService" mode="WsESDLConfig">
+     <xsl:param name="bindingNode"/>
+     <xsl:param name="authNode"/>
+     <xsl:variable name="serviceType" select="'ws_esdlconfig'"/>
+     <xsl:variable name="serviceName" select="concat($serviceType, '_', @name, '_', $process)"/>
+     <xsl:variable name="bindName" select="concat($serviceType, '_', $bindingNode/@name, '_', $process)"/>
+     <xsl:variable name="bindType" select="'ws_esdlconfigSoapBinding'"/>
+     <xsl:variable name="servicePlugin">
+     <xsl:call-template name="defineServicePlugin">
+      <xsl:with-param name="plugin" select="'ws_esdlconfig'"/>
+</xsl:call-template>
+</xsl:variable>
+<EspService name="{$serviceName}" type="{$serviceType}" plugin="{$servicePlugin}"/>
+<EspBinding name="{$bindName}" service="{$serviceName}" protocol="{$bindingNode/@protocol}" type="{$bindType}" plugin="{$servicePlugin}" netAddress="0.0.0.0" port="{$bindingNode/@port}">
+<xsl:call-template name="bindAuthentication">
+<xsl:with-param name="bindingNode" select="$bindingNode"/>
+<xsl:with-param name="authMethod" select="$authNode/@method"/>
+<xsl:with-param name="service" select="'ws_esdlconfig'"/>
+</xsl:call-template>
+</EspBinding>
+</xsl:template>
     <!-- ws_access-->
     <xsl:template match="EspService" mode="ws_access">
         <xsl:param name="bindingNode"/>

+ 1 - 0
initfiles/componentfiles/configxml/CMakeLists.txt

@@ -82,6 +82,7 @@ FOREACH( iFILES
     ${CMAKE_CURRENT_SOURCE_DIR}/sasha.xsl
     ${CMAKE_CURRENT_SOURCE_DIR}/eclcc.xsl
     ${CMAKE_CURRENT_SOURCE_DIR}/validateAll.xsl
+    ${CMAKE_CURRENT_SOURCE_DIR}/esdlsvcengine.xsd
 )
     Install ( FILES ${iFILES} DESTINATION componentfiles/configxml COMPONENT Runtime)
 ENDFOREACH ( iFILES )

+ 13 - 0
initfiles/componentfiles/configxml/buildsetCC.xml.in

@@ -314,6 +314,19 @@
                           service="ecldirect"/>
     </Properties>
    </BuildSet>
+   <BuildSet deployable="no"
+             installSet="deploy_map.xml"
+             name="DynamicESDL"
+             path="componentfiles/esdlsvcengine"
+             processName="EspService"
+             schema="esdlsvcengine.xsd">
+     <Properties bindingType="EsdlBinding"
+                 defaultPort="8043"
+                 defaultResourcesBasedn="ou=EspServices,ou=ecl"
+                 defaultSecurePort="18043"
+                 plugin="esdl_svc_engine"
+                 type="DynamicESDL"/>
+    </BuildSet>
   </Build>
 </Programs>
 </Environment>

+ 3 - 0
initfiles/componentfiles/configxml/cgencomplist_linux.xml

@@ -300,4 +300,7 @@
             path="componentfiles/configxml"
             processName="PluginProcess"
             schema="plugin.xsd"/>
+  <Component name="DynamicESDL" processName='EspService' schema='esdlsvcengine.xsd' deployable='no'>
+   <File name="@temp/esp_service.xsl" method="esp_service_module"/>
+  </Component>
 </Components>

+ 4 - 1
initfiles/componentfiles/configxml/cgencomplist_win.xml

@@ -303,4 +303,7 @@
             path="componentfiles/configxml"
             processName="PluginProcess"
             schema="plugin.xsd"/>
-</Components>
+  <Component name="DynamicESDL" processName='EspService' schema='esdlsvcengine.xsd' deployable='no'>
+   <File name="@temp/esp_service.xsl" method="esp_service_module"/>
+  </Component>
+</Components>

+ 40 - 0
initfiles/componentfiles/configxml/esdlsvcengine.xsd

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+    <xs:include schemaLocation="environment.xsd"/>
+    <xs:element name="EspService">
+        <xs:complexType>
+            <xs:attribute name="build" type="buildType" use="required">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <viewType>hidden</viewType>
+                        <tooltip>The build name to be deployed</tooltip>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="buildSet" type="buildSetType" use="required">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <viewType>hidden</viewType>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="name" type="xs:string" use="required" default="">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <title>Dynamic ESDL Service Name</title>
+                        <required>true</required>
+                        <tooltip>Name for this Dynamic ESDL based web service interface.</tooltip>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="description" type="xs:string" use="optional" default="My ESDL Based Web Service Interface">
+                <xs:annotation>
+                    <xs:appinfo>
+                        <title>ESDL Service Description</title>
+                        <tooltip>Describes each ESDL based web service interface</tooltip>
+                    </xs:appinfo>
+                </xs:annotation>
+            </xs:attribute>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>

+ 1 - 1
initfiles/etc/DIR_NAME/genenvrules.conf

@@ -1,7 +1,7 @@
 
 [Algorithm]
 max_comps_per_node=4
-do_not_generate=SiteCertificate,dfuplus,soapplus,eclplus,ldapServer,ws_account,eclserver,ecldirect
+do_not_generate=SiteCertificate,dfuplus,soapplus,eclplus,ldapServer,ws_account,eclserver,ecldirect,DynamicESDL
 avoid_combo=dali-eclagent,dali-sasha
 comps_on_all_nodes=dafilesrv,ftslave
 exclude_from_comps_on_all_nodes=ldapServer

+ 1 - 0
tools/CMakeLists.txt

@@ -14,6 +14,7 @@
 #    limitations under the License.
 ################################################################################
 HPCC_ADD_SUBDIRECTORY (esdlcomp)
+HPCC_ADD_SUBDIRECTORY (esdlcmd)
 HPCC_ADD_SUBDIRECTORY (esdlcmd-xml)
 HPCC_ADD_SUBDIRECTORY (hidl)
 HPCC_ADD_SUBDIRECTORY (backupnode "PLATFORM")

+ 6 - 10
tools/esdlcmd-xml/CMakeLists.txt

@@ -40,16 +40,12 @@ ADD_DEFINITIONS( -D_CONSOLE -O0 )
 
 HPCC_ADD_EXECUTABLE ( esdl-xml ${SRCS} )
 
-# The tool esdl-xml is built in HPCCPlatform as a build-time
-# pre-req. But it is not distributed in CE packages.
-if ("${BUILD_LEVEL}" STREQUAL "ENTERPRISE" OR "${BUILD_LEVEL}" STREQUAL "INTERNAL")
-    MESSAGE("----INSTALLING ESDL-XML")
-    install ( TARGETS esdl-xml RUNTIME DESTINATION ${EXEC_DIR} )
-    if ( UNIX )
-        install ( PROGRAMS esdl-xml.install DESTINATION etc/init.d/install COMPONENT Runtime )
-        install ( PROGRAMS esdl-xml.uninstall DESTINATION etc/init.d/uninstall COMPONENT Runtime )
-    endif ( UNIX )
-endif()
+MESSAGE("----INSTALLING ESDL-XML")
+install ( TARGETS esdl-xml RUNTIME DESTINATION ${EXEC_DIR} )
+if ( UNIX )
+    install ( PROGRAMS esdl-xml.install DESTINATION etc/init.d/install COMPONENT Runtime )
+    install ( PROGRAMS esdl-xml.uninstall DESTINATION etc/init.d/uninstall COMPONENT Runtime )
+endif ( UNIX )
 
 target_link_libraries ( esdl-xml
                         jlib

+ 84 - 0
tools/esdlcmd/CMakeLists.txt

@@ -0,0 +1,84 @@
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+################################################################################
+
+# Component: esdlcmd
+
+#####################################################
+# Description:
+# ------------
+#    Cmake Input File for esdlcmd
+#####################################################
+
+
+project( esdlcmd )
+
+include(${HPCC_SOURCE_DIR}/esp/scm/smcscm.cmake)
+
+set ( SRCS
+         ${ESPSCM_GENERATED_DIR}/common_esp.cpp
+         ${CMAKE_CURRENT_SOURCE_DIR}/esdlcmd.cpp
+         ${CMAKE_CURRENT_SOURCE_DIR}/esdlcmd_shell.cpp
+         ${CMAKE_CURRENT_SOURCE_DIR}/esdlcmd_core.cpp
+         ${CMAKE_CURRENT_SOURCE_DIR}/esdlcmd_common.cpp
+         ${CMAKE_CURRENT_SOURCE_DIR}/esdl2ecl.cpp
+         ${CMAKE_CURRENT_SOURCE_DIR}/esdl-publish.cpp
+         ${ESPSCM_GENERATED_DIR}/ws_esdlconfig_esp.cpp
+    )
+
+include_directories (
+         ${CMAKE_BINARY_DIR}
+         ${CMAKE_BINARY_DIR}/oss
+         ${HPCC_SOURCE_DIR}/system/include
+         ${HPCC_SOURCE_DIR}/system/jlib
+         ${HPCC_SOURCE_DIR}/esp/clients
+         ${HPCC_SOURCE_DIR}/system/security/shared
+         ${HPCC_SOURCE_DIR}/system/mp
+         ${HPCC_SOURCE_DIR}/common/dllserver
+         ${HPCC_SOURCE_DIR}/common/fileview2
+         ${HPCC_SOURCE_DIR}/common/environment
+         ${HPCC_SOURCE_DIR}/esp/bindings
+         ${HPCC_SOURCE_DIR}/esp/bindings/SOAP/xpp
+         ${HPCC_SOURCE_DIR}/esp/platform
+         ${HPCC_SOURCE_DIR}/system/xmllib
+         ${HPCC_SOURCE_DIR}/system/scm
+         ${HPCC_SOURCE_DIR}/system/security/scm
+         ${HPCC_SOURCE_DIR}/esp/platform
+         ${HPCC_SOURCE_DIR}/tools/esdlcomp
+         ${HPCC_SOURCE_DIR}/tools/esdlcmd-xml
+         ${HPCC_SOURCE_DIR}/esp/esdllib
+    )
+
+ADD_DEFINITIONS( -D_CONSOLE -O0 )
+
+HPCC_ADD_EXECUTABLE ( esdl ${SRCS} )
+
+add_dependencies ( esdl
+                   espscm
+                 )
+
+install ( TARGETS esdl RUNTIME DESTINATION ${EXEC_DIR} )
+target_link_libraries ( esdl
+        jlib
+        esphttp
+        xmllib
+        esdllib
+        esdlcomp
+    )
+
+if ( UNIX )
+    install ( PROGRAMS esdl.install DESTINATION etc/init.d/install COMPONENT Runtime )
+    install ( PROGRAMS esdl.uninstall DESTINATION etc/init.d/uninstall COMPONENT Runtime )
+endif ( UNIX )

+ 808 - 0
tools/esdlcmd/esdl-publish.cpp

@@ -0,0 +1,808 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include "jliball.hpp"
+#include "esdl_def.hpp"
+#include "esdlcmd_common.hpp"
+
+#include "esdlcmd_core.hpp"
+#include "build-config.h"
+
+
+class EsdlPublishCmdCommon : public EsdlCmdCommon
+{
+protected:
+    StringAttr optSource;
+    StringAttr optService; //RODRIGO, which service??? ESP Service? ESDL service? they could be one and the same, not sure
+    StringAttr optWSProcAddress;
+    StringAttr optWSProcPort;
+    StringAttr optVersionStr;
+    double     optVersion;
+    StringAttr optUser;
+    StringAttr optPass;
+    StringAttr optESDLDefID;
+    StringAttr optESDLService;
+
+    StringAttr optTargetESPProcName;
+    StringAttr optTargetAddress;
+    StringAttr optTargetPort;
+    bool       optOverWrite;
+
+    Owned<EsdlCmdHelper> esdlHelper;
+
+public:
+    EsdlPublishCmdCommon()
+    {
+        esdlHelper.setown(EsdlCmdHelper::createEsdlHelper());
+    }
+
+    virtual int processCMD() = 0;
+
+    virtual bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+        if (iter.done())
+        {
+            usage();
+            return false;
+        }
+
+        for (; !iter.done(); iter.next())
+        {
+            if (parseCommandLineOption(iter))
+                continue;
+
+            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+                return false;
+        }
+
+        return true;
+    }
+
+    virtual void usage()
+    {
+         printf(
+                "   -s, --server <ip>            IP of server running ESDL services\n"
+                "   --port <port>                ESDL services port\n"
+                "   -u, --username <name>        Username for accessing ESDL services\n"
+                "   -pw, --password <pw>         Password for accessing ESDL services\n"
+                "   --version <ver>              ESDL service version\n"
+                );
+        EsdlCmdCommon::usage();
+    }
+
+    virtual bool parseCommandLineOption(ArgvIterator &iter)
+    {
+        if (iter.matchFlag(optSource, ESDL_CONVERT_SOURCE))
+            return true;
+        if (iter.matchFlag(optService, ESDLOPT_SERVICE))
+            return true;
+        if (iter.matchFlag(optWSProcAddress, ESDL_OPT_SERVICE_SERVER) || iter.matchFlag(optWSProcAddress, ESDL_OPTION_SERVICE_SERVER))
+            return true;
+        if (iter.matchFlag(optVersionStr, ESDLOPT_VERSION))
+            return true;
+        if (iter.matchFlag(optUser, ESDL_OPT_SERVICE_USER) || iter.matchFlag(optUser, ESDL_OPTION_SERVICE_USER))
+            return true;
+        if (iter.matchFlag(optPass, ESDL_OPT_SERVICE_PASS) || iter.matchFlag(optPass, ESDL_OPTION_SERVICE_PASS))
+            return true;
+        if (iter.matchFlag(optWSProcPort, ESDL_OPTION_SERVICE_PORT) || iter.matchFlag(optWSProcPort, ESDL_OPT_SERVICE_PORT))
+            return true;
+        if (iter.matchFlag(optOverWrite, ESDL_OPTION_OVERWRITE) )
+            return true;
+
+        return false;
+    }
+
+    virtual bool finalizeOptions(IProperties *globals)
+    {
+        if (!optVersionStr.isEmpty())
+        {
+            optVersion = atof( optVersionStr.get() );
+            if( optVersion <= 0 )
+            {
+                throw MakeStringException( 0, "Version option must be followed by a real number > 0" );
+            }
+        }
+        else
+        {
+            fprintf(stderr, "\nWARNING: ESDL Version not specified.\n");
+        }
+
+        if (optSource.isEmpty())
+            throw MakeStringException( 0, "Source ESDL XML definition file must be provided" );
+
+        if (optService.isEmpty())
+            throw MakeStringException( 0, "Name of ESDL based service must be provided" );
+
+        if (optWSProcAddress.isEmpty())
+            throw MakeStringException( 0, "Server address of ESDL process server must be provided" );
+
+        if (optWSProcPort.isEmpty())
+            throw MakeStringException( 0, "Port on which ESDL process is listening must be provided" );
+
+        return true;
+    }
+};
+
+class EsdlPublishCmd : public EsdlPublishCmdCommon
+{
+public:
+    int processCMD()
+    {
+        Owned<IClientWsESDLConfig> esdlConfigClient = EsdlCmdHelper::getWsESDLConfigSoapService(optWSProcAddress, optWSProcPort, optUser, optPass);
+        Owned<IClientPublishESDLDefinitionRequest> request = esdlConfigClient->createPublishESDLDefinitionRequest();
+
+        StringBuffer esxml;
+        esdlHelper->getServiceESXDL(optSource.get(), optESDLService.get(), esxml, optVersion);
+
+        if (esxml.length()==0)
+        {
+            fprintf(stderr,"\nESDL Definition for service %s could not be loaded from: %s\n", optESDLService.get(), optSource.get());
+            return -1;
+        }
+
+        request->setServiceName(optESDLService.get());
+
+        if (optVerbose)
+            fprintf(stderr,"\nESDL Definition: \n%s\n", esxml.str());
+
+        request->setXMLDefinition(esxml.str());
+        request->setDeletePrevious(optOverWrite);
+
+        Owned<IClientPublishESDLDefinitionResponse> resp = esdlConfigClient->PublishESDLDefinition(request);
+
+        bool validateMessages = false;
+        if (resp->getExceptions().ordinality()>0)
+        {
+            EsdlCmdHelper::outputMultiExceptions(resp->getExceptions());
+            return 1;
+        }
+
+        fprintf(stdout, "\n %s. Service Name: %s, Version: %d", resp->getStatus().getDescription(),resp->getServiceName(),resp->getEsdlVersion());
+
+        return 0;
+    }
+
+    void usage()
+    {
+        printf("\nUsage:\n\n"
+                "esdl publish <servicename> <filename.ecm> [command options]\n\n"
+                "   <servicename>        The ESDL defined ESP service to publish\n"
+                "   <filename.ecm>       The ESDL file containing service definition\n"
+                "Options (use option flag followed by appropriate value):\n"
+                "   --overwrite                    Overwrite the latest version of this ESDL Definition\n"
+                );
+
+        EsdlPublishCmdCommon::usage();
+    }
+
+    bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+       if (iter.done())
+       {
+           usage();
+           return false;
+       }
+
+       //First x parameter's order is fixed.
+       //<servicename>
+       //<filename.ecm>       The ESDL file containing service definition\n"
+       for (int cur = 0; cur < 2 && !iter.done(); cur++)
+       {
+          const char *arg = iter.query();
+          if (*arg != '-')
+          {
+              switch (cur)
+              {
+               case 0:
+                   optESDLService.set(arg);
+                   break;
+               case 1:
+                   optSource.set(arg);
+                   break;
+               default:
+                   fprintf(stderr, "\nUnrecognized positional argument detected : %s\n", arg);
+                   usage();
+                   return false;
+              }
+          }
+          else
+          {
+              fprintf(stderr, "\nOption detected before required arguments: %s\n", arg);
+              usage();
+              return false;
+          }
+
+          iter.next();
+       }
+
+       for (; !iter.done(); iter.next())
+       {
+           if (parseCommandLineOption(iter))
+               continue;
+
+           if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+               return false;
+       }
+
+       return true;
+    }
+
+    bool finalizeOptions(IProperties *globals)
+    {
+        if (!optVersionStr.isEmpty())
+        {
+            optVersion = atof( optVersionStr.get() );
+            if( optVersion <= 0 )
+            {
+                throw MakeStringException( 0, "Version option must be followed by a real number > 0" );
+            }
+        }
+        else
+        {
+            fprintf(stderr, "\nWARNING: ESDL Version not specified.\n");
+        }
+
+        if (optSource.isEmpty())
+            throw MakeStringException( 0, "Source ESDL XML definition file must be provided" );
+
+        if (optESDLService.isEmpty())
+            throw MakeStringException( 0, "Name of ESDL based service must be provided" );
+
+        if (optWSProcAddress.isEmpty())
+            throw MakeStringException( 0, "Server address of ESDL process server must be provided" );
+
+        if (optWSProcPort.isEmpty())
+            throw MakeStringException( 0, "Port on which ESDL process is listening must be provided" );
+
+        return true;
+    }
+};
+
+class EsdlBindServiceCmd : public EsdlPublishCmdCommon
+{
+protected:
+    StringAttr optPortOrName;
+    StringAttr optInput;
+
+public:
+    int processCMD()
+    {
+        Owned<IClientWsESDLConfig> esdlConfigClient = EsdlCmdHelper::getWsESDLConfigSoapService(optWSProcAddress, optWSProcPort, optUser, optPass);
+        Owned<IClientPublishESDLBindingRequest> request = esdlConfigClient->createPublishESDLBindingRequest();
+
+        fprintf(stderr,"\nAttempting to configure ESDL Service: '%s'\n", optESDLService.get());
+
+        request->setEspProcName(optTargetESPProcName);
+        request->setEspPort(optTargetPort);
+        request->setEspServiceName(optService);
+        request->setEsdlServiceName(optESDLService);
+        request->setEsdlDefinitionID(optESDLDefID);
+        request->setConfig(optInput);
+        request->setOverwrite(optOverWrite);
+
+        if (optVerbose)
+            fprintf(stderr,"\nMethod config: %s\n", optInput.get());
+
+        //Owned<IClientConfigureESDLServiceResponse> resp = esdlConfigClient->ConfigureESDLService(request);
+        Owned<IClientPublishESDLBindingResponse> resp = esdlConfigClient->PublishESDLBinding(request);
+
+        if (resp->getExceptions().ordinality()>0)
+        {
+            EsdlCmdHelper::outputMultiExceptions(resp->getExceptions());
+            return 1;
+        }
+
+        fprintf(stdout, "\n %s.", resp->getStatus().getDescription());
+
+        return 0;
+    }
+
+    void usage()
+    {
+        printf( "\nUsage:\n\n"
+                "esdl bind-service <TargetESPProcessName> <TargetESPBindingPort | TargetESPServiceName> <ESDLDefinitionId> <ESDLServiceName> [command options]\n\n"
+                "   TargetESPProcessName                             The target ESP Process name\n"
+                "   TargetESPBindingPort | TargetESPServiceName      Either target ESP binding port or target ESP service name\n"
+                "   ESDLDefinitionId                           The Name and version of the ESDL definition to bind to this service (must already be defined in dali.)\n"
+                "   ESDLServiceName                                  The Name of the ESDL Service (as defined in the ESDL Definition)\n"
+
+                "\nOptions (use option flag followed by appropriate value):\n"
+                "   --config <file|xml>                              Configuration XML for all methods associated with the target Service\n"
+                "   --overwrite                                      Overwrite binding if it already exists\n");
+
+                EsdlPublishCmdCommon::usage();
+//RODRIGO update this usage
+        printf( "\n Use this command to publish ESDL Service based bindings.\n"
+                "   To bind an ESDL Service, provide the target ESP process name\n"
+                "   (ESP Process which will host the ESP Service as defined in the ESDL Definition.) \n"
+                "   It is also necessary to provide the Port on which this service is configured to run (ESP Binding),\n"
+                "   and the name of the service you are binding.\n"
+                "   Optionally provide configuration information either directly, or via a\n"
+                "   configuration file in the following syntax:\n"
+                "     <Methods>\n"
+                "     \t<Method name=\"myMethod\" url=\"http://10.45.22.1:292/somepath?someparam=value\" user=\"myuser\" password=\"mypass\"/>\n"
+                "     \t<Method name=\"myMethod2\" url=\"http://10.45.22.1:292/somepath?someparam=value\" user=\"myuser\" password=\"mypass\"/>\n"
+                "     </Methods>\n"
+                );
+
+        printf("\nExample:"
+                ">esdl bind-service myesp 8088 WsMyService --config /myService/methods.xml\n"
+                );
+    }
+
+    bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+        if (iter.done())
+        {
+            usage();
+            return false;
+        }
+
+        //First 4 parameter's order is fixed.
+        //TargetESPProcessName
+        //TargetESPBindingPort | TargetESPServiceName
+        //ESDLDefinitionId
+        //ESDLServiceName
+        for (int cur = 0; cur < 4 && !iter.done(); cur++)
+        {
+           const char *arg = iter.query();
+           if (*arg != '-')
+           {
+               switch (cur)
+               {
+                case 0:
+                    optTargetESPProcName.set(arg);
+                    break;
+                case 1:
+                    optPortOrName.set(arg);
+                    break;
+                case 2:
+                    optESDLDefID.set(arg);
+                    break;
+                case 3:
+                    optESDLService.set(arg);
+                    break;
+                default:
+                    fprintf(stderr, "\nUnrecognized positional argument detected : %s\n", arg);
+                    usage();
+                    return false;
+               }
+           }
+           else
+           {
+               fprintf(stderr, "\nOption detected before required arguments: %s\n", arg);
+               usage();
+               return false;
+           }
+
+           iter.next();
+        }
+
+        for (; !iter.done(); iter.next())
+        {
+            if (parseCommandLineOption(iter))
+                continue;
+
+            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+                return false;
+        }
+
+        return true;
+    }
+
+    bool parseCommandLineOption(ArgvIterator &iter)
+    {
+        if (iter.matchFlag(optInput, ESDL_OPTION_CONFIG) )
+            return true;
+        //if (iter.matchFlag(optOverWrite, ESDL_OPTION_OVERWRITE) )
+        //    return true;
+
+        if (EsdlPublishCmdCommon::parseCommandLineOption(iter))
+            return true;
+
+        return false;
+    }
+
+    bool finalizeOptions(IProperties *globals)
+    {
+        if (optInput.length())
+        {
+            const char *in = optInput.get();
+            while (*in && isspace(*in)) in++;
+            if (*in!='<')
+            {
+                StringBuffer content;
+                content.loadFile(in);
+                optInput.set(content.str());
+            }
+        }
+
+        if (optESDLDefID.isEmpty())
+            throw MakeStringException( 0, "ESDL definition ID must be provided!" );
+
+        if (optESDLService.isEmpty())
+            throw MakeStringException( 0, "ESDL service definition name must be provided!" );
+
+        if(optTargetESPProcName.isEmpty())
+            throw MakeStringException( 0, "Name of Target ESP process must be provided!" );
+
+        if (optPortOrName.isEmpty())
+            throw MakeStringException( 0, "Either the target ESP service port of name must be provided!" );
+        else
+        {
+            const char * portorname =  optPortOrName.get();
+            isdigit(*portorname) ? optTargetPort.set(portorname) : optService.set(portorname);
+        }
+
+        if (optWSProcAddress.isEmpty())
+            throw MakeStringException( 0, "Server address of ESDL process server must be provided" );
+
+        if (optWSProcPort.isEmpty())
+            throw MakeStringException( 0, "Port on which ESDL process is listening must be provided" );
+
+        return true;
+    }
+};
+
+class EsdlBindMethodCmd : public EsdlBindServiceCmd
+{
+protected:
+    StringAttr optMethod;
+    StringAttr optBindingName;
+
+public:
+    int processCMD()
+    {
+        Owned<IClientWsESDLConfig> esdlConfigClient = EsdlCmdHelper::getWsESDLConfigSoapService(optWSProcAddress, optWSProcPort, optUser, optPass);
+        Owned<IClientConfigureESDLBindingMethodRequest> request = esdlConfigClient->createConfigureESDLBindingMethodRequest();
+
+        fprintf(stderr,"\nAttempting to configure Method : '%s'.'%s'\n", optService.get(), optMethod.get());
+        request->setEspProcName(optTargetESPProcName);
+        request->setEspBindingName(optBindingName);
+        request->setEsdlServiceName(optService.get());
+        VStringBuffer id("%s.%d", optService.get(), (int)optVersion);
+        request->setEsdlDefinitionID(id.str());
+        request->setConfig(optInput);
+        request->setOverwrite(optOverWrite);
+
+        if (optVerbose)
+            fprintf(stderr,"\nMethod config: %s\n", optInput.get());
+
+        Owned<IClientConfigureESDLBindingMethodResponse> resp = esdlConfigClient->ConfigureESDLBindingMethod(request);
+
+        if (resp->getExceptions().ordinality()>0)
+        {
+            EsdlCmdHelper::outputMultiExceptions(resp->getExceptions());
+            return 1;
+        }
+
+        fprintf(stdout, "\n %s.", resp->getStatus().getDescription());
+
+        return 0;
+    }
+
+    void usage()
+    {
+        printf( "\nUsage:\n\n"
+                "esdl bind-method <TargetESPProcessName> <TargetESPBindingName> <TargetServiceName> <TargetServiceDefVersion> <TargetMethodName> [command options]\n\n"
+                "   TargetESPProcessName                             The target ESP Process name\n"
+                "   TargetESPBindingName                             The target ESP binding name associated with this service\n"
+                "   TargetServiceName                                The name of the Service to bind (must already be defined in dali.)\n"
+                "   TargetServiceDefVersion                          The version of the target service ESDL definition (must exist in dali)\n"
+                "   TargetMethodName                                 The name of the target method (must exist in the service ESDL definition)\n"
+
+                "\nOptions (use option flag followed by appropriate value):\n"
+                "   --config <file|xml>                              Configuration XML for all methods associated with the target Service\n"
+                "   --overwrite                                      Overwrite binding if it already exists\n");
+
+                EsdlPublishCmdCommon::usage();
+
+        printf( "\n Use this command to publish ESDL Service based bindings.\n"
+                "   To bind a ESDL Service, provide the target ESP process name\n"
+                "   (esp which will host the service.) \n"
+                "   It is also necessary to provide the Port on which this service is configured to run (ESP Binding),\n"
+                "   and the name of the service you are binding.\n"
+                "   Optionally provide configuration information either directly, or via a\n"
+                "   configuration file in the following syntax:\n"
+                "     <Methods>\n"
+                "     \t<Method name=\"myMethod\" url=\"http://10.45.22.1:292/somepath?someparam=value\" user=\"myuser\" password=\"mypass\"/>\n"
+                "     \t<Method name=\"myMethod2\" url=\"http://10.45.22.1:292/somepath?someparam=value\" user=\"myuser\" password=\"mypass\"/>\n"
+                "     </Methods>\n"
+                );
+
+        printf("\nExample:"
+                ">esdl bind-service myesp 8088 WsMyService --config /myService/methods.xml\n"
+                );
+    }
+
+    bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+        if (iter.done())
+        {
+            usage();
+            return false;
+        }
+
+        //First 5 parameter order is fixed.
+        for (int cur = 0; cur < 5 && !iter.done(); cur++)
+        {
+           const char *arg = iter.query();
+           if (*arg != '-')
+           {
+               switch (cur)
+               {
+                case 0:
+                    optTargetESPProcName.set(arg);
+                    break;
+                case 1:
+                    optBindingName.set(arg);
+                    break;
+                case 2:
+                    optService.set(arg);
+                    break;
+                case 3:
+                    optVersionStr.set(arg);
+                    break;
+                case 4:
+                    optMethod.set(arg);
+                    break;
+                default:
+                    fprintf(stderr, "\nUnrecognized positional argument detected : %s\n", arg);
+                    usage();
+                    return false;
+               }
+           }
+           else
+           {
+               fprintf(stderr, "\noption detected before required arguments: %s\n", arg);
+               usage();
+               return false;
+           }
+
+           iter.next();
+        }
+
+        for (; !iter.done(); iter.next())
+        {
+            if (parseCommandLineOption(iter))
+                continue;
+
+            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+                return false;
+        }
+
+        return true;
+    }
+
+    bool finalizeOptions(IProperties *globals)
+    {
+        if (optInput.length())
+        {
+            const char *in = optInput.get();
+            while (*in && isspace(*in)) in++;
+            if (*in!='<')
+            {
+                StringBuffer content;
+                content.loadFile(in);
+                optInput.set(content.str());
+            }
+        }
+
+        if (!optVersionStr.isEmpty())
+        {
+            optVersion = atof( optVersionStr.get() );
+            if( optVersion <= 0 )
+            {
+                throw MakeStringException( 0, "Version option must be followed by a real number > 0" );
+            }
+        }
+        else
+            throw MakeStringException( 0, "ESDL service definition version must be provided!" );
+
+        if(optTargetESPProcName.isEmpty())
+            throw MakeStringException( 0, "Name of Target ESP process must be provided" );
+
+        if (optService.isEmpty())
+            throw MakeStringException( 0, "Name of ESDL based service must be provided" );
+
+        if (optWSProcAddress.isEmpty())
+            throw MakeStringException( 0, "Server address of ESDL process server must be provided" );
+
+        if (optWSProcPort.isEmpty())
+            throw MakeStringException( 0, "Port on which ESDL process is listening must be provided" );
+
+        if (optMethod.isEmpty())
+            throw MakeStringException( 0, "Name of ESDL based method must be provided" );
+
+        if (optBindingName.isEmpty())
+            throw MakeStringException( 0, "Name of ESP binding must be provided" );
+
+        return true;
+    }
+};
+
+class EsdlGetCmd : public EsdlPublishCmdCommon
+{
+    protected:
+        StringAttr optId;
+    public:
+        bool parseCommandLineOptions(ArgvIterator &iter)
+           {
+               if (iter.done())
+               {
+                   usage();
+                   return false;
+               }
+
+               //First parameter is fixed.
+               for (int cur = 0; cur < 1 && !iter.done(); cur++)
+               {
+                  const char *arg = iter.query();
+                  if (*arg != '-')
+                  {
+                      switch (cur)
+                      {
+                       case 0:
+                           optId.set(arg);
+                           break;
+                       default:
+                           fprintf(stderr, "\nUnrecognized positional argument detected : %s\n", arg);
+                           usage();
+                           return false;
+                      }
+                  }
+                  else
+                  {
+                      fprintf(stderr, "\noption detected before required arguments: %s\n", arg);
+                      usage();
+                      return false;
+                  }
+
+                  iter.next();
+               }
+
+               for (; !iter.done(); iter.next())
+               {
+                   if (parseCommandLineOption(iter))
+                       continue;
+
+                   if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+                       return false;
+               }
+
+               return true;
+           }
+
+        bool parseCommandLineOption(ArgvIterator &iter)
+        {
+            if (iter.matchFlag(optTargetAddress, ESDL_OPTION_TARGET_ESP_ADDRESS))
+                return true;
+            if (iter.matchFlag(optTargetPort, ESDL_OPTION_TARGET_ESP_PORT) )
+                return true;
+
+            if (EsdlPublishCmdCommon::parseCommandLineOption(iter))
+                return true;
+
+            return false;
+        }
+
+        bool finalizeOptions(IProperties *globals)
+        {
+            if (optWSProcAddress.isEmpty())
+                throw MakeStringException( 0, "Server address of WsESDLConfig server must be provided" );
+
+            if (optWSProcPort.isEmpty())
+                throw MakeStringException( 0, "Port on which WsESDLConfig is listening must be provided" );
+
+            if (optId.isEmpty())
+                throw MakeStringException( 0, "ESDL ID must be provided" );
+
+            return true;
+        }
+};
+
+class EsdlGetDefinitionCmd : public EsdlGetCmd
+{
+    public:
+        int processCMD()
+        {
+            Owned<IClientWsESDLConfig> esdlConfigClient = EsdlCmdHelper::getWsESDLConfigSoapService(optWSProcAddress, optWSProcPort, optUser, optPass);
+            Owned<IClientGetESDLDefinitionRequest> request = esdlConfigClient->createGetESDLDefinitionRequest();
+
+            fprintf(stdout,"\nAttempting to get ESDL definition: %s\n", optId.get());
+
+            request->setId(optId);
+
+            Owned<IClientGetESDLDefinitionResponse> resp = esdlConfigClient->GetESDLDefinition(request);
+
+            if (resp->getExceptions().ordinality()>0)
+            {
+                EsdlCmdHelper::outputMultiExceptions(resp->getExceptions());
+                return 1;
+            }
+
+            fprintf(stdout, "\n%s", resp->getXMLDefinition());
+            fprintf(stdout, "\n%s.", resp->getStatus().getDescription());
+
+            return 0;
+        }
+
+        void usage()
+        {
+
+            printf( "\nUsage:\n\n"
+                    "esdl get-definition <ESDLDefinitionID> [command options]\n\n"
+                    "Options (use option flag followed by appropriate value):\n"
+                    "   ESDLDefinitionID                             The ESDL Definition id <esdldefname>.<esdldefver>\n"
+                   );
+
+                    EsdlPublishCmdCommon::usage();
+
+            printf( "\n\n Use this command to get DESDL definitions.\n"
+                    " To specify the target DESDL based service configuration, provide the target ESP process \n"
+                    " (esp process name or machine IP Address) which hosts the service.\n"
+                    " It is also necessary to provide the Port on which this service is configured to run,\n"
+                    " and the name of the service.\n"
+                    );
+        }
+};
+
+class EsdlGetBindingCmd : public EsdlGetCmd
+{
+public:
+    int processCMD()
+    {
+        Owned<IClientWsESDLConfig> esdlConfigClient = EsdlCmdHelper::getWsESDLConfigSoapService(optWSProcAddress, optWSProcPort, optUser, optPass);
+        Owned<IClientGetESDLBindingRequest> request = esdlConfigClient->createGetESDLBindingRequest();
+
+        fprintf(stdout,"\nAttempting to get ESDL binding: %s\n", optId.get());
+
+        request->setEsdlBindingId(optId);
+
+        Owned<IClientGetESDLBindingResponse> resp = esdlConfigClient->GetESDLBinding(request);
+
+        if (resp->getExceptions().ordinality()>0)
+        {
+            EsdlCmdHelper::outputMultiExceptions(resp->getExceptions());
+            return 1;
+        }
+
+        fprintf(stdout, "\n%s", resp->getConfigXML());
+        fprintf(stdout, "\n%s.", resp->getStatus().getDescription());
+
+        return 0;
+    }
+
+    void usage()
+    {
+
+        printf( "\nUsage:\n\n"
+                "esdl get-binding <ESDLBindingId> [command options]\n\n"
+                "Options (use option flag followed by appropriate value):\n"
+                "   ESDLBindingId                             The target ESDL binding id <espprocessname>.<espbindingname>\n"
+               );
+
+                EsdlPublishCmdCommon::usage();
+
+        printf( "\n\n Use this command to get DESDL Service based bindings.\n"
+                " To specify the target DESDL based service configuration, provide the target ESP process \n"
+                " (esp process name or machine IP Address) which hosts the service.\n"
+                " It is also necessary to provide the Port on which this service is configured to run,\n"
+                " and the name of the service.\n"
+                );
+    }
+};

+ 1 - 0
tools/esdlcmd/esdl.install

@@ -0,0 +1 @@
+installFile "$binPath/esdl" "/usr/bin/esdl" 1 || exit 1

+ 1 - 0
tools/esdlcmd/esdl.uninstall

@@ -0,0 +1 @@
+removeSymlink "/usr/bin/esdl"

+ 459 - 0
tools/esdlcmd/esdl2ecl.cpp

@@ -0,0 +1,459 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include "jliball.hpp"
+#include "xslprocessor.hpp"
+
+#include "esdlcmd_core.hpp"
+#include "build-config.h"
+
+typedef IPropertyTree * IPTreePtr;
+
+class TypeEntry : public CInterface
+{
+public:
+    IMPLEMENT_IINTERFACE;
+
+    StringAttr name;
+    StringAttr src;
+    StringBuffer comment;
+    StringAttr base_type;
+    IPTreePtr ptree;
+
+    TypeEntry(const char *name_, const char *src_, IPropertyTree *ptree_) :
+        name(name_), src(src_), ptree(ptree_)
+    {}
+};
+
+typedef TypeEntry * TypeEntryPtr;
+
+typedef MapStringTo<IPTreePtr> AddedList;
+typedef MapStringTo<TypeEntryPtr> TypeIndex;
+
+
+class EsdlIndexedPropertyTrees
+{
+public:
+    CIArrayOf<TypeEntry> types;
+
+    AddedList included;
+    TypeIndex index;
+
+    Owned<IPropertyTree> all;
+
+    EsdlIndexedPropertyTrees()
+    {
+        all.setown(createPTree("ESDL_files", false));
+    }
+
+    ~EsdlIndexedPropertyTrees()
+    {
+        all.clear();
+    }
+
+    StringBuffer &getQualifiedTypeName(const char *localsrc, const char *type, StringBuffer &qname)
+    {
+        if (type && *type)
+        {
+            TypeEntry **typeEntry = index.getValue(type);
+            if (typeEntry && *typeEntry)
+            {
+                const char *src = (*typeEntry)->src.get();
+                if (stricmp(src, localsrc))
+                {
+                    const char *finger = src;
+                    if (!strnicmp(finger, "wsm_", 4))
+                    {
+                        finger+=4;
+                    }
+                    qname.appendf("%s.", finger);
+                }
+                qname.appendf("t_%s", type);
+            }
+        }
+        return qname;
+    }
+
+    void loadFile(const char *srcpath, const char *srcfile, const char *srcext="", IProperties *versions=NULL, bool loadincludes=false)
+    {
+        if (!srcfile || !*srcfile)
+            throw MakeStringException(-1, "EsdlInclude no file name");
+
+        if (!included.getValue(srcfile))
+        {
+            DBGLOG("ESDL Loading include: %s", srcfile);
+
+            StringBuffer fileName(srcpath);
+            fileName.append(srcfile);
+
+            IPropertyTree *src = NULL;
+
+            if (stricmp(srcext,".ecm")==0)
+            {
+                fileName.append(".ecm");
+                StringBuffer esxml;
+                EsdlCmdHelper::convertECMtoESXDL(fileName.str(), srcfile, esxml, false, true, true);
+                src = createPTreeFromXMLString(esxml, 0);
+            }
+            else if (!srcext || !*srcext || stricmp(srcext, ".xml")==0)
+            {
+                fileName.append(".xml");
+                src = createPTreeFromXMLFile(fileName.str(), false);
+            }
+            else
+            {
+                StringBuffer msg("Unsupported file type: ");
+                msg.append(srcfile);
+
+                throw MakeStringExceptionDirect(-1, msg.str());
+            }
+
+            if (!src)
+            {
+                StringBuffer msg("EsdlInclude file not found - ");
+                msg.append(fileName);
+                throw MakeStringExceptionDirect(-1, msg.str());
+            }
+
+            included.setValue(srcfile, src);
+            all->addPropTree("esxdl", src);
+
+            StringArray add_includes;
+
+            Owned<IPropertyTreeIterator> iter = src->getElements("*");
+            ForEach (*iter)
+            {
+                IPropertyTree &e = iter->query();
+                const char *tag = e.queryName();
+                if (!stricmp(tag, "EsdlInclude"))
+                    add_includes.append(e.queryProp("@file"));
+                else if (!stricmp(tag, "EsdlVersion"))
+                {
+                    if (versions)
+                        versions->setProp(e.queryProp("@name"), e.queryProp("@version"));
+                }
+                else
+                {
+                    e.setProp("@src", srcfile);
+                    const char *name = e.queryProp("@name");
+                    if (name && *name)
+                    {
+                        TypeEntry *te =  new TypeEntry(name, srcfile, &e);
+                        // types.append(*dynamic_cast<CInterface*>(te));
+                        types.append(*(te));
+                        index.setValue(name, te);
+                        if (!stricmp(tag, "EsdlEnumType"))
+                        {
+                            te->base_type.set(e.queryProp("base_type"));
+                            te->comment.append("values[");
+                            bool start=1;
+                            Owned<IPropertyTreeIterator> it = e.getElements("EsdlEnumItem");
+                            for (it->first(); it->isValid(); it->next())
+                            {
+                                IPropertyTree &item = it->query();
+                                te->comment.appendf("'%s',", item.queryProp("@enum"));
+                            }
+                            te->comment.append("'']");
+                        }
+                    }
+                }
+            }
+
+            if (loadincludes)
+            {
+                ForEachItemIn(idx, add_includes)
+                {
+                    const char *file=add_includes.item(idx);
+                    loadFile(srcpath, file, srcext, versions, loadincludes);
+                }
+            }
+        }
+    }
+};
+
+class Esdl2EclCmd : public EsdlConvertCmd
+{
+public:
+    Esdl2EclCmd() : optGenerateAllIncludes(false), optOutputExpandedXML(false), optHPCCCompFilesDir(COMPONENTFILES_DIR)
+    {}
+
+    virtual bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+        if (iter.done())
+        {
+            usage();
+            return false;
+        }
+
+        //First two parameters' order is fixed.
+        for (int par = 0; par < 2 && !iter.done(); par++)
+        {
+            const char *arg = iter.query();
+            if (*arg != '-')
+            {
+                if (optSource.isEmpty())
+                    optSource.set(arg);
+                else if (optOutDirPath.isEmpty())
+                    optOutDirPath.set(arg);
+                else
+                {
+                    fprintf(stderr, "\nunrecognized argument detected before required parameters: %s\n", arg);
+                    usage();
+                    return false;
+                }
+            }
+            else
+            {
+                fprintf(stderr, "\noption detected before required parameters: %s\n", arg);
+                usage();
+                return false;
+            }
+
+            iter.next();
+        }
+
+        for (; !iter.done(); iter.next())
+        {
+            if (iter.matchFlag(optGenerateAllIncludes, ESDL_CONVERT_ALL))
+                continue;
+            if (iter.matchFlag(optOutputExpandedXML, ESDL_CONVERT_EXPANDEDXML) || iter.matchFlag(optOutputExpandedXML, ESDL_CONVERT_EXPANDEDXML_x))
+                continue;
+            if (iter.matchFlag(optHPCCCompFilesDir, HPCC_COMPONENT_FILES_DIR) || iter.matchFlag(optHPCCCompFilesDir, HPCC_COMPONENT_FILES_DIR_CDE))
+                continue;
+
+            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+                return false;
+        }
+
+        return true;
+    }
+
+    esdlCmdOptionMatchIndicator matchCommandLineOption(ArgvIterator &iter, bool finalAttempt)
+    {
+        if (iter.matchOption(optSource, ESDL_CONVERT_SOURCE))
+            return EsdlCmdOptionMatch;
+        if (iter.matchOption(optOutDirPath, ESDL_CONVERT_OUTDIR))
+            return EsdlCmdOptionMatch;
+        if (iter.matchFlag(optOutputExpandedXML, ESDL_CONVERT_EXPANDEDXML) || iter.matchFlag(optOutputExpandedXML, ESDL_CONVERT_EXPANDEDXML_x))
+            return EsdlCmdOptionMatch;
+        if (iter.matchFlag(optHPCCCompFilesDir, HPCC_COMPONENT_FILES_DIR) || iter.matchFlag(optHPCCCompFilesDir, HPCC_COMPONENT_FILES_DIR_CDE))
+            return EsdlCmdOptionMatch;
+
+        return EsdlCmdCommon::matchCommandLineOption(iter, true);
+    }
+
+
+    virtual bool finalizeOptions(IProperties *globals)
+    {
+        return EsdlConvertCmd::finalizeOptions(globals);
+    }
+
+    virtual int processCMD()
+    {
+        if (!optOutDirPath.isEmpty())
+            recursiveCreateDirectory(optOutDirPath.get());
+
+        StringBuffer srcPath;
+        StringBuffer srcName;
+        StringBuffer srcExt;
+
+        splitFilename(optSource.get(), NULL, &srcPath, &srcName, &srcExt);
+
+        unsigned start = msTick();
+        EsdlIndexedPropertyTrees trees;
+        trees.loadFile(srcPath.str(), srcName.str(), srcExt.str(), NULL, optGenerateAllIncludes);
+        DBGLOG("Time taken to load ESDL files %u", msTick() - start);
+
+        StringBuffer idxxml("<types><type name=\"StringArrayItem\" src=\"share\"/>");
+
+        DBGLOG("\tSTART INDEX");
+        HashIterator iit(trees.index);
+        for (iit.first(); iit.isValid(); iit.next())
+        {
+            const char *key = (const char *) iit.get().getKey();
+            TypeEntry ** typ = trees.index.getValue(key);
+            if (typ)
+            {
+                StringBuffer src((*typ)->src.get());
+                if (!strnicmp(src.str(), "wsm_", 4))
+                    src.remove(0, 4);
+                idxxml.appendf("<type name=\"%s\" src=\"%s\" ", (*typ)->name.get(), src.str());
+                if ((*typ)->comment.length())
+                    idxxml.appendf("comment=\"%s\" ", (*typ)->comment.str());
+                if ((*typ)->base_type.length())
+                    idxxml.appendf("base_type=\"%s\" ", (*typ)->base_type.get());
+                idxxml.append("/>");
+            }
+        }
+
+        DBGLOG("\tEND INDEX");
+        idxxml.append("</types>");
+
+        idxxml.append("<keywords>");
+        idxxml.append("<keyword word=\"shared\"/>");
+        idxxml.append("<keyword word=\"function\"/>");
+        idxxml.append("<keyword word=\"record\"/>");
+        idxxml.append("<keyword word=\"header\"/>");
+        idxxml.append("<keyword word=\"service\"/>");
+        idxxml.append("<keyword word=\"type\"/>");
+        idxxml.append("<keyword word=\"penalty\"/>");
+        idxxml.append("<keyword word=\"isvalid\"/>");
+        idxxml.append("</keywords>");
+
+        if (optGenerateAllIncludes)
+        {
+            Owned<IPropertyTreeIterator> files = trees.all->getElements("esxdl");
+            ForEach(*files)
+            {
+
+                IPropertyTree &file = files->query();
+                const char * filename = file.queryProp("@name");
+                StringBuffer xmlfile;
+                toXML(&file, xmlfile, 0,0);
+
+                //expandEsxdlForEclGeneration(trees, src);
+                outputEcl(srcPath.str(), filename, optOutDirPath.get(), idxxml.str(), xmlfile);
+            }
+        }
+        else
+        {
+            int count = trees.all->getCount("esxdl");
+            if (trees.all->getCount("esxdl") > 0)
+            {
+                IPropertyTree *file = trees.all->getPropTree("esxdl[1]");
+                if (file)
+                {
+                    StringBuffer xmlfile;
+                    toXML(file, xmlfile, 0,0);
+
+                    //expandEsxdlForEclGeneration(trees, srcName.str());
+                    outputEcl(srcPath.str(), srcName.str(), optOutDirPath.get(), idxxml.str(), xmlfile); //rodrigo
+                }
+            }
+        }
+
+        return 0;
+    }
+
+    virtual void usage()
+    {
+        fputs("\nUsage:\n\n"
+                "esdl ecl sourcePath outputPath [options]\n"
+                "\nsourcePath must be absolute path to the ESDL Definition file containing the"
+                "EsdlService definition for the service you want to work with.\n"
+                "outputPath must be the absolute path where the ECL output with be created."
+                "   Options:\n"
+                "      -x, --expandedxml     Output expanded XML files\n"
+                "      --all                 Generate ECL files for all includes\n"
+                ,stdout);
+    }
+
+    void outputEcl(const char *srcpath, const char *file, const char *path, const char *types, const char * xml)
+    {
+        DBGLOG("Generating ECL file for %s", file);
+
+
+        StringBuffer filePath;
+        StringBuffer fileName;
+        StringBuffer fileExt;
+
+        splitFilename(file, NULL, &filePath, &fileName, &fileExt);
+
+        const char *finger = fileName.str();
+        if (!strnicmp(finger, "wsm_", 4))
+            finger+=4;
+
+        StringBuffer outfile;
+        if (path && *path)
+        {
+            outfile.append(path);
+            if (outfile.length() && !strchr("/\\", outfile.charAt(outfile.length()-1)))
+                outfile.append('/');
+        }
+        outfile.append(finger).append(".ecl");
+
+        StringBuffer fullname(srcpath);
+        if (fullname.length() && !strchr("/\\", fullname.charAt(fullname.length()-1)))
+            fullname.append('/');
+        fullname.append(fileName.str()).append(".xml");
+
+        StringBuffer expstr;
+        expstr.append("<expesdl>");
+        expstr.append(types);
+        expstr.append(xml);
+        expstr.append("</expesdl>");
+
+        if (optOutputExpandedXML)
+        {
+            StringBuffer xmlfile;
+            if (path && *path)
+            {
+                xmlfile.append(path);
+                if (xmlfile.length() && !strchr("/\\", xmlfile.charAt(xmlfile.length()-1)))
+                    xmlfile.append('/');
+            }
+            xmlfile.append(finger).append("_expanded.xml");
+            Owned<IFile> ifile =  createIFile(xmlfile.str());
+            if (ifile)
+            {
+                Owned<IFileIO> ifio = ifile->open(IFOcreate);
+                if (ifio)
+                {
+                    ifio->write(0, expstr.length(), expstr.str());
+                }
+            }
+        }
+
+        Owned<IProperties> params = createProperties();
+        params->setProp("sourceFileName", finger);
+        StringBuffer esdl2eclxslt (optHPCCCompFilesDir.get());
+        esdl2eclxslt.append("/xslt/esdl2ecl.xslt");
+        esdl2eclxsltTransform(expstr.str(), esdl2eclxslt.toCharArray(), params, outfile.str());
+    }
+
+    void esdl2eclxsltTransform(const char* xml, const char* sheet, IProperties *params, const char *filename)
+    {
+        StringBuffer xsl;
+        xsl.loadFile(sheet);
+
+        Owned<IXslProcessor> proc  = getXslProcessor();
+        Owned<IXslTransform> trans = proc->createXslTransform();
+
+        trans->setXmlSource(xml, strlen(xml));
+        trans->setXslSource(xsl, xsl.length(), "esdl2ecl", ".");
+
+        if (params)
+        {
+            Owned<IPropertyIterator> it = params->getIterator();
+            for (it->first(); it->isValid(); it->next())
+            {
+                const char *key = it->getPropKey();
+                //set parameter in the XSL transform skipping over the @ prefix, if any
+                const char* paramName = *key == '@' ? key+1 : key;
+                trans->setParameter(paramName, StringBuffer().append('\'').append(params->queryProp(key)).append('\'').str());
+            }
+        }
+
+        trans->setResultTarget(filename);
+        trans->transform();
+    }
+
+public:
+    bool optGenerateAllIncludes;
+    bool optOutputExpandedXML;
+    StringAttr optHPCCCompFilesDir;
+};

+ 47 - 0
tools/esdlcmd/esdlcmd.cpp

@@ -0,0 +1,47 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include "jlog.hpp"
+#include "jfile.hpp"
+#include "jargv.hpp"
+
+#include "build-config.h"
+
+#include "esdlcmd.hpp"
+#include "esdlcmd_common.hpp"
+#include "esdlcmd_core.hpp"
+
+#define SYSTEMCONFDIR CONFIG_DIR
+#define SYSTEMCONFFILE ENV_CONF_FILE
+
+
+//=========================================================================================
+
+static int doMain(int argc, const char *argv[])
+{
+    EsdlCMDShell processor(argc, argv, createCoreEsdlCommand, BUILD_TAG, true);
+    return processor.run();
+}
+
+int main(int argc, const char *argv[])
+{
+    InitModuleObjects();
+    queryStderrLogMsgHandler()->setMessageFields(0);
+    unsigned exitCode = doMain(argc, argv);
+    releaseAtoms();
+    return exitCode;
+}

+ 54 - 0
tools/esdlcmd/esdlcmd.hpp

@@ -0,0 +1,54 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef ESDLCMD_HPP
+#define ESDLCMD_HPP
+
+#include "esdlcmd_common.hpp"
+
+class EsdlCMDShell
+{
+public:
+    EsdlCMDShell(int argc, const char *argv[], EsdlCommandFactory _factory, const char *_version, bool _runExternals=false)
+        : args(argc, argv), factory(_factory), version(_version), optHelp(false), runExternals(_runExternals)
+    {
+        splitFilename(argv[0], NULL, NULL, &name, NULL);
+    }
+
+    bool parseCommandLineOptions(ArgvIterator &iter);
+    void finalizeOptions(IProperties *globals);
+    int processCMD(ArgvIterator &iter);
+    int callExternal(ArgvIterator &iter);
+    int run();
+
+    virtual void usage();
+
+protected:
+    ArgvIterator args;
+    Owned<IProperties> globals;
+    EsdlCommandFactory factory;
+    StringBuffer name;
+    StringAttr cmd;
+    bool runExternals;
+
+    StringAttr version;
+
+    bool optHelp;
+    StringAttr optIniFilename;
+};
+
+#endif /* ESDLCMD_HPP */

+ 149 - 0
tools/esdlcmd/esdlcmd_common.cpp

@@ -0,0 +1,149 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include <stdio.h>
+#include "jlog.hpp"
+#include "jfile.hpp"
+#include "jargv.hpp"
+#include "junicode.hpp"
+#include "build-config.h"
+
+#include "esdlcmd_common.hpp"
+
+void outputMultiExceptions(const IMultiException &me)
+{
+    fprintf(stderr, "\nException(s):\n");
+    aindex_t count = me.ordinality();
+    for (aindex_t i=0; i<count; i++)
+    {
+        IException& e = me.item(i);
+        StringBuffer msg;
+        fprintf(stderr, "%d: %s\n", e.errorCode(), e.errorMessage(msg).str());
+    }
+    fprintf(stderr, "\n");
+}
+
+//=========================================================================================
+
+#define PE_OFFSET_LOCATION_IN_DOS_SECTION 0x3C
+
+esdlCmdOptionMatchIndicator EsdlCmdCommon::matchCommandLineOption(ArgvIterator &iter, bool finalAttempt)
+{
+    bool boolValue;
+    if (iter.matchFlag(boolValue, ESDLOPT_HELP))
+    {
+        usage();
+        return EsdlCmdOptionCompletion;
+    }
+    if (iter.matchFlag(boolValue, ESDLOPT_VERSION))
+    {
+        fprintf(stdout, "%s\n", BUILD_TAG);
+        return EsdlCmdOptionCompletion;
+    }
+
+    if (iter.matchFlag(optVerbose, ESDL_OPTION_VERBOSE) || iter.matchFlag(optVerbose, ESDL_OPT_VERBOSE))
+    {
+        return EsdlCmdOptionMatch;
+    }
+
+    StringAttr tempArg;
+    if (iter.matchOption(tempArg, "-brk"))
+    {
+#if defined(_WIN32) && defined(_DEBUG)
+        unsigned id = atoi(tempArg.sget());
+        if (id == 0)
+            DebugBreak();
+        else
+            _CrtSetBreakAlloc(id);
+#endif
+        return EsdlCmdOptionMatch;
+    }
+    if (finalAttempt)
+    {
+        fprintf(stderr, "\n%s option not recognized\n", iter.query());
+        usage();
+    }
+    return EsdlCmdOptionNoMatch;
+}
+
+bool EsdlCmdCommon::finalizeOptions(IProperties *globals)
+{
+    if (!optVerbose)
+    {
+        Owned<ILogMsgFilter> filter = getCategoryLogMsgFilter(MSGAUD_user, MSGCLS_error);
+        queryLogMsgManager()->changeMonitorFilter(queryStderrLogMsgHandler(), filter);
+    }
+
+    return true;
+}
+
+bool EsdlConvertCmd::parseCommandLineOptions(ArgvIterator &iter)
+{
+    if (iter.done())
+    {
+        usage();
+        return false;
+    }
+
+    for (; !iter.done(); iter.next())
+    {
+        if (parseCommandLineOption(iter))
+            return true;
+
+        if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+            return false;
+    }
+
+    return true;
+}
+
+bool EsdlConvertCmd::parseCommandLineOption(ArgvIterator &iter)
+{
+    if (iter.matchOption(optSource, ESDL_CONVERT_SOURCE))
+        return true;
+    if (iter.matchOption(optOutDirPath, ESDL_CONVERT_OUTDIR))
+        return true;
+
+    return false;
+}
+
+esdlCmdOptionMatchIndicator EsdlConvertCmd::matchCommandLineOption(ArgvIterator &iter, bool finalAttempt)
+{
+    if (iter.matchOption(optSource, ESDL_CONVERT_SOURCE))
+      return EsdlCmdOptionMatch;
+    if (iter.matchOption(optOutDirPath, ESDL_CONVERT_OUTDIR))
+      return EsdlCmdOptionMatch;
+
+    return EsdlCmdCommon::matchCommandLineOption(iter, true);
+}
+
+bool EsdlConvertCmd::finalizeOptions(IProperties *globals)
+{
+    if (optSource.isEmpty())
+    {
+        fprintf(stderr, "\nError: Source esdl parameter required\n");
+        return false;
+    }
+
+    if (optOutDirPath.isEmpty())
+    {
+        fprintf(stderr, "\nError: Target output directory path parameter required\n");
+        return false;
+    }
+
+    return EsdlCmdCommon::finalizeOptions(globals);
+}

+ 303 - 0
tools/esdlcmd/esdlcmd_common.hpp

@@ -0,0 +1,303 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef ESDLCMD_COMMON_HPP
+#define ESDLCMD_COMMON_HPP
+
+#include "jprop.hpp"
+#include "jargv.hpp"
+#include "common.hpp"
+#include "esdl_def.hpp"
+#include "esdl_def_helper.hpp"
+
+#include "ws_esdlconfig_esp.ipp"
+#include "esdl2xml.hpp"
+
+//=========================================================================================
+
+interface IEsdlCommand : extends IInterface
+{
+    virtual bool parseCommandLineOptions(ArgvIterator &iter)=0;
+    virtual bool finalizeOptions(IProperties *globals)=0;
+    virtual int processCMD()=0;
+    virtual void usage()=0;
+};
+
+typedef IEsdlCommand *(*EsdlCommandFactory)(const char *cmdname);
+
+#define ESDLOPT_HELP                    "--help"
+#define ESDLOPT_HELP_s                  "--?"
+#define ESDLARG_HELP                    "help"
+
+#define ESDL_OPTION_VERBOSE              "--verbose"
+#define ESDL_OPT_VERBOSE                 "-v"
+
+#define ESDL_CONVERT_SOURCE             "--source"
+#define ESDL_CONVERT_OUTDIR             "--outdir"
+
+#define ESDL_CONVERT_ALL                "--all"
+#define ESDL_CONVERT_EXPANDEDXML        "--expandedxml"
+#define ESDL_CONVERT_EXPANDEDXML_x      "-x"
+
+#define HPCC_COMPONENT_FILES_DIR        "--compfilesdir"
+#define HPCC_COMPONENT_FILES_DIR_CDE    "--CDE"
+
+#define ESDLOPT_XSLT_PATH               "--xslt"
+
+#define ESDLOPT_VERSION                 "--version"
+#define ESDLOPT_SERVICE                 "--service"
+#define ESDLOPT_METHOD                  "--method"
+#define ESDLOPT_PREPROCESS_OUT          "--preprocess-output"
+#define ESDLOPT_ANNOTATE                "--annotate"
+#define ESDLOPT_NO_OPTIONAL_ATTRIBUTES  "--noopt"
+#define ESDLOPT_OPT_PARAM_VAL           "-opt"
+#define ESDLOPT_OPTIONAL_PARAM_VAL      "--optional"
+#define ESDLOPT_TARGET_NS               "-tns"
+#define ESDLOPT_TARGET_NAMESPACE        "--target-namespace"
+#define ESDLOPT_NUMBER                  "-n"
+#define ESDLOPT_NO_COLLAPSE             "--show-inheritance"
+#define ESDLOPT_NO_ARRAYOF              "--no-arrayof"
+
+#define ESDLOPT_WSDL_ADDRESS            "--wsdl-address"
+
+#define ESDLBINDING_URN_BASE            "urn:hpccsystems:ws"
+#define ESDLOPTLIST_DELIMITER           ";"
+
+#define ESDL_OPT_SERVICE_SERVER         "-s"
+#define ESDL_OPTION_SERVICE_SERVER      "--server"
+#define ESDL_OPTION_SERVICE_PORT        "--port"
+#define ESDL_OPT_SERVICE_USER           "-u"
+#define ESDL_OPTION_SERVICE_USER        "--username"
+#define ESDL_OPTION_SERVICE_PORT        "--port"
+#define ESDL_OPT_SERVICE_PORT           "-p"
+#define ESDL_OPT_SERVICE_PASS           "-pw"
+#define ESDL_OPTION_SERVICE_PASS        "--password"
+
+#define ESDL_OPTION_ESP_PROC_NAME        "--esp-proc-name"
+#define ESDL_OPT_ESP_PROC_NAME           "-epn"
+#define ESDL_OPTION_TARGET_ESP_ADDRESS   "--esp-ip"
+#define ESDL_OPTION_TARGET_ESP_PORT      "--esp-port"
+#define ESDL_OPTION_CONFIG              "--config"
+#define ESDL_OPTION_OVERWRITE              "--overwrite"
+
+bool matchVariableOption(ArgvIterator &iter, const char prefix, IArrayOf<IEspNamedValue> &values);
+
+enum esdlCmdOptionMatchIndicator
+{
+    EsdlCmdOptionNoMatch=0,
+    EsdlCmdOptionMatch=1,
+    EsdlCmdOptionCompletion=2
+};
+
+class EsdlCmdCommon : public CInterface, implements IEsdlCommand
+{
+public:
+    IMPLEMENT_IINTERFACE;
+    EsdlCmdCommon() : optVerbose(false)
+    {}
+    virtual esdlCmdOptionMatchIndicator matchCommandLineOption(ArgvIterator &iter, bool finalAttempt=false);
+    virtual bool finalizeOptions(IProperties *globals);
+
+    virtual void usage()
+    {
+        fprintf(stdout,
+            "   --help                 display usage information for the given command\n"
+            "   -v,--verbose          output additional tracing information\n"
+        );
+    }
+public:
+    bool optVerbose;
+};
+
+class EsdlCmdHelper : public CInterface
+{
+protected:
+    Owned<IEsdlDefinition> esdlDef;
+    Owned<IEsdlDefinitionHelper> helper;
+    Owned<IFile> serviceDefFile;
+
+    EsdlCmdHelper()
+    {
+        esdlDef.set(createEsdlDefinition());
+        helper.set(createEsdlDefinitionHelper());
+    }
+
+public:
+    IMPLEMENT_IINTERFACE;
+
+    static EsdlCmdHelper * createEsdlHelper()
+    {
+        return new EsdlCmdHelper();
+    }
+
+    void getServiceESXDL(const char * sourceFileName, const char * serviceName, StringBuffer & xmlOut, double version, IProperties *opts=NULL, unsigned flags=0)
+    {
+        if (!esdlDef.get())
+            esdlDef.set(createEsdlDefinition());
+
+        if(!esdlDef->hasFileLoaded(sourceFileName))
+        {
+            StringBuffer extension;
+            StringBuffer filename;
+            splitFilename(sourceFileName, NULL, NULL, &filename, &extension);
+            if (stricmp(extension.str(),".ecm")==0)
+            {
+                StringBuffer esxml;
+                EsdlCmdHelper::convertECMtoESXDL(sourceFileName, filename.str(), esxml, true, true, false);
+                esdlDef->addDefinitionFromXML(esxml, serviceName, version);
+            }
+            else
+            {
+                loadEsdlDef(sourceFileName);
+            }
+        }
+
+        if (esdlDef)
+        {
+            IEsdlDefObjectIterator *deps = esdlDef->getDependencies(serviceName, "", version, opts, flags);
+
+            if( deps )
+            {
+                xmlOut.appendf( "<esxdl name=\"%s\">", serviceName);
+                helper->toXML( *deps, xmlOut, version, opts, flags );
+                xmlOut.append("</esxdl>");
+            }
+            else
+                throw( MakeStringException(0, "Could not get ESDL structure") );
+        }
+    }
+
+    static void convertECMtoESXDL(const char * filepath, const char * esxdlname, StringBuffer & esxml, bool recursive, bool verbose, bool outputincludes)
+    {
+        if (verbose)
+            fprintf(stdout,"Converting ecm file %s to XML\n", filepath);
+
+        Owned<Esdl2Esxdl> cmd = new Esdl2Esxdl(recursive, verbose);
+        esxml.setf( "<esxdl name=\"%s\">", esxdlname);
+        cmd->transform(filepath, "", &esxml, outputincludes); //output to buffer
+        esxml.append("</esxdl>");
+    }
+
+    static void outputMultiExceptions(const IMultiException &me)
+    {
+        fprintf(stderr, "\nException(s):\n");
+        aindex_t count = me.ordinality();
+        for (aindex_t i=0; i<count; i++)
+        {
+            IException& e = me.item(i);
+            StringBuffer msg;
+            fprintf(stderr, "%d: %s\n", e.errorCode(), e.errorMessage(msg).str());
+        }
+        fprintf(stderr, "\n");
+    }
+
+    static IClientWsESDLConfig * getWsESDLConfigSoapService(const char *server, const char *port, const char *username, const char *password)
+    {
+        if(server == NULL)
+            throw MakeStringException(-1, "Server url not specified");
+
+        VStringBuffer url("http://%s:%s/WsESDLConfig", server, port);
+
+        IClientWsESDLConfig * esdlConfigClient = createWsESDLConfigClient();
+        esdlConfigClient->addServiceUrl(url.str());
+        esdlConfigClient->setUsernameToken(username, password, NULL);
+
+        return esdlConfigClient;
+    }
+
+protected:
+
+    void loadEsdlDef(const char * sourceFileName)
+    {
+        serviceDefFile.setown( createIFile(sourceFileName) );
+        if( serviceDefFile->exists() )
+        {
+            if( serviceDefFile->isFile() )
+            {
+                if( serviceDefFile->size() > 0 )
+                {
+                    // Realized a subtle source of potential problems. Because there
+                    // can be multiple EsdlStruct definitions with the same name
+                    // in multiple files, you need to be careful that only those files
+                    // explicitly included by your service are loaded to the
+                    // EsdlDefinition object that you'll getDependencies() on. If not,
+                    // you could inadvertently getDependencies() from a different structure
+                    // with the same name. This means we can only reliably process one
+                    // Web Service at a time, and must load files by explicitly loading
+                    // only the top-level ws_<service> definition file, and allowing the
+                    // load code to handle loading only the minimal set of required includes
+                    esdlDef->addDefinitionsFromFile( serviceDefFile->queryFilename() );
+                }
+                else
+                {
+                    throw( MakeStringException(0, "ESDL definition file source %s is empty", sourceFileName) );
+                }
+
+            }
+            else
+            {
+                throw( MakeStringException(0, "ESDL definition file source %s is not a file", sourceFileName) );
+            }
+        }
+        else
+        {
+            throw( MakeStringException(0, "ESDL definition file source %s does not exist", sourceFileName) );
+        }
+    }
+};
+
+class EsdlConvertCmd : public EsdlCmdCommon
+{
+public:
+    EsdlConvertCmd() {}
+    virtual esdlCmdOptionMatchIndicator matchCommandLineOption(ArgvIterator &iter, bool finalAttempt=false);
+    virtual bool finalizeOptions(IProperties *globals);
+    virtual bool parseCommandLineOptions(ArgvIterator&);
+    virtual bool parseCommandLineOption(ArgvIterator&);
+    virtual void usage()
+    {
+        EsdlCmdCommon::usage();
+        puts("   --outdir=<out dir path> Location to generate output\n");
+    }
+
+public:
+    StringAttr optSource;
+    StringAttr optOutDirPath;
+};
+
+class EsdlHelperConvertCmd : public EsdlConvertCmd
+{
+protected:
+    Owned<IEsdlDefinition> esdlDef;
+    Owned<IEsdlDefinitionHelper> helper;
+public:
+    EsdlHelperConvertCmd()
+    {
+        esdlDef.set(createEsdlDefinition());
+        helper.set(createEsdlDefinitionHelper());
+    }
+
+    virtual void usage()
+    {
+        EsdlConvertCmd::usage();
+    }
+    virtual void doTransform(IEsdlDefObjectIterator& objs, StringBuffer &target, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )=0;
+    virtual void loadTransform( StringBuffer &xsltpath, IProperties *params )=0;
+    virtual void setTransformParams(IProperties *params )=0;
+};
+
+#endif

+ 626 - 0
tools/esdlcmd/esdlcmd_core.cpp

@@ -0,0 +1,626 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include <stdio.h>
+#include "jlog.hpp"
+#include "jfile.hpp"
+#include "jargv.hpp"
+#include "build-config.h"
+
+#include "esdlcmd_common.hpp"
+#include "esdlcmd_core.hpp"
+
+#include "esdl2ecl.cpp"
+#include "esdl-publish.cpp"
+
+class Esdl2XSDCmd : public EsdlHelperConvertCmd
+{
+public:
+    Esdl2XSDCmd() : optVersion(0), optAllAnnot(false), optNoAnnot(false),
+                    optEnforceOptional(true), optRawOutput(false), optXformTimes(1), optFlags(DEPFLAG_COLLAPSE|DEPFLAG_ARRAYOF),
+                    outfileext(".xsd")
+    {}
+
+    virtual bool parseCommandLineOptions(ArgvIterator &iter)
+    {
+
+        if (iter.done())
+        {
+            usage();
+            return false;
+        }
+
+        //First two parameters' order is fixed.
+        for (int par = 0; par < 2 && !iter.done(); par++)
+        {
+            const char *arg = iter.query();
+            if (*arg != '-')
+            {
+                if (optSource.isEmpty())
+                    optSource.set(arg);
+                else if (optService.isEmpty())
+                    optService.set(arg);
+                else
+                {
+                    fprintf(stderr, "\nunrecognized argument detected before required parameters: %s\n", arg);
+                    usage();
+                    return false;
+                }
+            }
+            else
+            {
+                fprintf(stderr, "\noption detected before required parameters: %s\n", arg);
+                usage();
+                return false;
+            }
+
+            iter.next();
+        }
+
+        for (; !iter.done(); iter.next())
+        {
+            if (parseCommandLineOption(iter))
+                continue;
+
+            if (matchCommandLineOption(iter, true)!=EsdlCmdOptionMatch)
+                return false;
+        }
+
+        return true;
+    }
+
+    virtual bool parseCommandLineOption(ArgvIterator &iter)
+    {
+        if (iter.matchOption(optVersionStr, ESDLOPT_VERSION))
+            return true;
+        if (iter.matchOption(optService, ESDLOPT_SERVICE))
+            return true;
+        if (iter.matchOption(optMethod, ESDLOPT_METHOD))
+            return true;
+        if (iter.matchOption(optXsltPath, ESDLOPT_XSLT_PATH))
+            return true;
+        if (iter.matchOption(optPreprocessOutputDir, ESDLOPT_PREPROCESS_OUT))
+            return true;
+        if (iter.matchOption(optAnnotate, ESDLOPT_ANNOTATE))
+            return true;
+        if (iter.matchOption(optTargetNamespace, ESDLOPT_TARGET_NAMESPACE) || iter.matchOption(optTargetNamespace, ESDLOPT_TARGET_NS))
+            return true;
+        if (iter.matchOption(optOptional, ESDLOPT_OPT_PARAM_VAL) || iter.matchOption(optOptional, ESDLOPT_OPTIONAL_PARAM_VAL))
+            return true;
+        if (iter.matchFlag(optEnforceOptional, ESDLOPT_NO_OPTIONAL_ATTRIBUTES))
+            return true;
+        if (iter.matchOption(optXformTimes, ESDLOPT_NUMBER))
+            return true;
+        if (iter.matchFlag(optNoCollapse, ESDLOPT_NO_COLLAPSE))
+            return true;
+        if (iter.matchFlag(optNoArrayOf, ESDLOPT_NO_ARRAYOF))
+            return true;
+
+        if (EsdlConvertCmd::parseCommandLineOption(iter))
+            return true;
+
+        return false;
+    }
+
+    esdlCmdOptionMatchIndicator matchCommandLineOption(ArgvIterator &iter, bool finalAttempt)
+    {
+        return EsdlConvertCmd::matchCommandLineOption(iter, true);
+    }
+
+    virtual bool finalizeOptions(IProperties *globals)
+    {
+        if (optSource.isEmpty())
+        {
+            usage();
+            throw( MakeStringException(0, "\nError: Source esdl parameter required\n"));
+        }
+
+        if( optService.isEmpty() )
+        {
+            usage();
+            throw( MakeStringException(0, "A service name must be provided") );
+        }
+
+        if (!optVersionStr.isEmpty())
+        {
+            optVersion = atof( optVersionStr.get() );
+            if( optVersion <= 0 )
+            {
+                throw MakeStringException( 0, "Version option must be followed by a real number > 0" );
+            }
+        }
+
+        if (optXsltPath.isEmpty())
+            optXsltPath.set(COMPONENTFILES_DIR);
+
+        fullxsltpath.set(optXsltPath);
+        fullxsltpath.append("/xslt/esxdl2xsd.xslt");
+
+        if (!optPreprocessOutputDir.isEmpty())
+            optRawOutput = true;
+
+        if (!optAnnotate.isEmpty())
+        {
+            if (strcmp (optAnnotate.get(), "all") ==0)
+            {
+                optAllAnnot = true;
+            }
+            else if (strcmp (optAnnotate.get(), "none") ==0)
+            {
+                optNoAnnot = true;
+            }
+            else
+            {
+                  throw MakeStringException( 0, "--annotate option must be followed by 'all' or 'none' " );
+            }
+        }
+
+        if (optNoCollapse)
+        {
+            unsetFlag(DEPFLAG_COLLAPSE);
+        }
+
+        if(optNoArrayOf)
+        {
+            unsetFlag(DEPFLAG_ARRAYOF);
+        }
+
+        if(optTargetNamespace.isEmpty())
+        {
+            optTargetNamespace.set(ESDLBINDING_URN_BASE);
+        }
+
+        return true;
+    }
+
+    virtual void doTransform(IEsdlDefObjectIterator& objs, StringBuffer &target, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )
+    {
+        TimeSection ts("transforming via XSLT");
+        helper->toXSD( objs, target, EsdlXslToXsd, optVersion, opts, NULL, optFlags );
+    }
+
+    virtual void loadTransform( StringBuffer &xsltpath, IProperties *params)
+    {
+        TimeSection ts("loading XSLT");
+        helper->loadTransform( xsltpath, params, EsdlXslToXsd );
+    }
+
+    virtual void setTransformParams(IProperties *params )
+    {
+        helper->setTransformParams(EsdlXslToXsd, params);
+    }
+
+    virtual int processCMD()
+    {
+        loadServiceDef();
+        createOptionals();
+
+        Owned<IEsdlDefObjectIterator> structs = esdlDef->getDependencies( optService.get(), optMethod.get(), ESDLOPTLIST_DELIMITER, optVersion, opts.get(), optFlags );
+
+        if( optRawOutput )
+        {
+            outputRaw(*structs);
+        }
+
+        if( !optXsltPath.isEmpty() )
+        {
+            createParams();
+
+            loadTransform( fullxsltpath, params);
+
+            for( int i=0; i < optXformTimes; i++ )
+            {
+                doTransform( *structs, outputBuffer, optVersion, opts.get(), NULL, optFlags );
+            }
+
+            outputToFile();
+
+            printf( "%s\n", outputBuffer.str() );
+        }
+        else
+        {
+            throw( MakeStringException(0, "Path to /xslt/esxdl2xsd.xslt is empty, cannot perform transform.") );
+        }
+
+        return 0;
+    }
+
+    void printOptions()
+    {
+        puts("Options:");
+        puts("  --version <version number> : Constrain to interface version\n");
+        puts("  --method <method name>[;<method name>]* : Constrain to list of specific method(s)\n" );
+        puts("  --xslt <xslt file path> : Path to '/xslt/esxdl2xsd.xslt' file to transform EsdlDef to XSD\n" );
+        puts("  --preprocess-output <raw output directory> : Output pre-processed xml file to specified directory before applying XSLT transform\n" );
+        puts("  --annotate <all | none> : Flag turning on either all annotations or none. By default annotations are generated " );
+        puts("                    for Enumerations. Setting the flag to 'none' will disable even those. Setting it" );
+        puts("                    to 'all' will enable additional annotations such as collapsed, cols, form_ui, html_head and rows.\n");
+        puts("  --noopt : Turns off the enforcement of 'optional' attributes on elements. If no -noopt is specified then all elements with an 'optional'" );
+        puts("       will be included in the output. By default 'optional' filtering is enforced.\n");
+        puts("  -opt,--optional <param value> : Value to use for optional tag filter when gathering dependencies" );
+        puts("                       An example: passing 'internal' when some Esdl definition objects have the attribute");
+        puts("                       optional(\"internal\") will ensure they appear in the XSD, otherwise they'd be filtered out\n");
+        puts("  -tns,--target-namespace <target namespace> : The target namespace, passed to the transform via the parameter 'tnsParam'\n" );
+        puts("                            used for the final output of the XSD. If not supplied will default to " );
+        puts("                            http://webservices.seisint.com/<service name>\n" );
+        puts("  -n <int>: Number of times to run transform after loading XSLT. Defaults to 1.\n" );
+        puts("  --show-inheritance : Turns off the collapse feature. Collapsing optimizes the XML output to strip out structures\n" );
+        puts("                        only used for inheritance, and collapses their elements into their child. That simplifies the\n" );
+        puts("                        stylesheet. By default this option is on.");
+        puts("  --no-arrayof : Supresses the use of the arrrayof element. arrayof optimizes the XML output to include 'ArrayOf...'\n" );
+        puts("                        structure definitions for those EsdlArray elements with no item_tag attribute. Works in conjuction\n" );
+        puts("                        with an optimized stylesheet that doesn't generate these itself. This defaults to on.");
+    }
+
+    virtual void usage()
+    {
+        puts("Usage:");
+        puts("esdl xsd sourcePath serviceName [options]\n" );
+        puts("\nsourcePath must be absolute path to the ESDL Definition file containing the" );
+        puts("EsdlService definition for the service you want to work with.\n" );
+        puts("serviceName EsdlService definition for the service you want to work with.\n" );
+
+        printOptions();
+        EsdlConvertCmd::usage();
+    }
+
+    virtual void outputRaw( IEsdlDefObjectIterator& obj)
+    {
+        if( optRawOutput )
+        {
+            StringBuffer xmlOut;
+            StringBuffer empty;
+
+            xmlOut.appendf( "<esxdl name=\"%s\">", optService.get());
+            helper->toXML( obj, xmlOut, optVersion, opts.get(), optFlags );
+            xmlOut.append("</esxdl>");
+
+            saveAsFile( optPreprocessOutputDir.get(), empty, xmlOut.str(), NULL );
+        }
+    }
+    virtual void createOptionals()
+    {
+        // 09jun2011 tja: We must ensure that the opts IProperties object is
+        // valid/non-null. This is because by passing null/invalid in to the
+        // getDependencies call we're indicating that we want to turn off
+        // optional filtering.
+
+        if( optEnforceOptional )
+        {
+            opts.setown(createProperties(false));
+            if( optOptional.length() )
+            {
+                opts->setProp(optOptional.get(), 1);
+            }
+        }
+    }
+
+    void createParams()
+    {
+        params.set(createProperties());
+
+        generateNamespace(tns);
+
+        params->setProp( "tnsParam", tns );
+        params->setProp( "optional", optOptional );
+
+        if( optAllAnnot )
+        {
+            params->setProp( "all_annot_Param", 1 );
+        }
+
+        if( optNoAnnot )
+        {
+            params->setProp( "no_annot_Param", 1 );
+        }
+    }
+
+    virtual void loadServiceDef()
+    {
+        serviceDef.setown( createIFile(optSource) );
+        if( serviceDef->exists() )
+        {
+            if( serviceDef->isFile() )
+            {
+                if( serviceDef->size() > 0 )
+                {
+                    // Realized a subtle source of potential problems. Because there
+                    // can be multiple EsdlStruct definitions with the same name
+                    // in multiple files, you need to be careful that only those files
+                    // explicitly included by your service are loaded to the
+                    // EsdlDefinition object that you'll getDependencies() on. If not,
+                    // you could inadvertently getDependencies() from a different structure
+                    // with the same name. This means we can only reliably process one
+                    // Web Service at a time, and must load files by explicitly loading
+                    // only the top-level ws_<service> definition file, and allowing the
+                    // load code to handle loading only the minimal set of required includes
+                    esdlDef->addDefinitionsFromFile( serviceDef->queryFilename() );
+                }
+                else
+                {
+                    throw( MakeStringException(0, "ESDL definition file source %s is empty", optSource.get()) );
+                }
+
+            }
+            else
+            {
+                throw( MakeStringException(0, "ESDL definition file source %s is not a file", optSource.get()) );
+            }
+        }
+        else
+        {
+            throw( MakeStringException(0, "ESDL definition file source %s does not exist", optSource.get()) );
+        }
+    }
+
+    virtual void outputToFile()
+    {
+        if (!optOutDirPath.isEmpty())
+        {
+            StringBuffer filename;
+            generateOutputFileName(filename);
+            saveAsFile(optOutDirPath.get(), filename, outputBuffer.str(), NULL);
+        }
+    }
+
+    StringBuffer & generateNamespace(StringBuffer &ns)
+    {
+       ns.appendf("%s:%s", optTargetNamespace.get(), optService.get());
+       //only add methodname if single method used.
+       if (!optMethod.isEmpty() && !strstr(optMethod.get(), ESDLOPTLIST_DELIMITER))
+           ns.append(':').append(optMethod.get());
+
+       //todo
+       /*
+       StringBuffer ns_optionals;
+       //IProperties *params = context.queryRequestParameters();
+       Owned<IPropertyIterator> esdl_optionals = esdlDef->queryOptionals()->getIterator();
+       ForEach(*esdl_optionals)
+       {
+           const char *key = esdl_optionals->getPropKey();
+           if (params->hasProp(key))
+           {
+               if (ns_optionals.length())
+                   ns_optionals.append(',');
+               ns_optionals.append(key);
+           }
+       }
+       if (ns_optionals.length())
+           ns.append('(').append(ns_optionals.str()).append(')');
+        */
+
+       if (optVersion > 0)
+        ns.append("@ver=").appendf("%g", optVersion);
+       return ns.toLowerCase();
+    }
+
+    virtual StringBuffer & generateOutputFileName( StringBuffer &filename)
+    {
+        filename.appendf("%s", optService.get());
+        if (!optMethod.isEmpty() && !strstr(optMethod.get(), ESDLOPTLIST_DELIMITER))
+            filename.append('-').append(optMethod.get());
+
+        filename.append(outfileext);
+
+        return filename.toLowerCase();
+    }
+
+    void saveAsFile(const char * dir, StringBuffer &outname, const char *text, const char *ext="")
+    {
+        StringBuffer path(dir);
+
+        if( outname.length()>0 && path.charAt(path.length()) != PATHSEPCHAR &&  outname.charAt(0) != PATHSEPCHAR)
+        {
+            path.append(PATHSEPCHAR);
+            path.append(outname);
+        }
+
+        if( ext && *ext )
+        {
+            path.append(ext);
+        }
+
+        Owned<IFile> file = createIFile(path.str());
+        Owned<IFileIO> io;
+        io.setown(file->open(IFOcreaterw));
+
+        DBGLOG("Writing to file %s", file->queryFilename());
+
+        if (io.get())
+            io->write(0, strlen(text), text);
+        else
+            DBGLOG("File %s can't be created", file->queryFilename());
+    }
+
+    void setFlag( unsigned f ) { optFlags |= f; }
+    void unsetFlag( unsigned f ) { optFlags &= ~f; }
+
+
+public:
+    StringAttr optService;
+    StringAttr optXsltPath;
+    StringAttr optMethod;
+    StringAttr optOptional;
+    bool optEnforceOptional;
+    StringAttr optAnnotate;
+    bool optAllAnnot, optNoAnnot;
+    StringAttr optTargetNamespace;
+    StringAttr optPreprocessOutputDir;
+    bool optRawOutput;
+    StringAttr optVersionStr;
+    double optVersion;
+    unsigned int optXformTimes;
+    unsigned optFlags;
+    bool optNoCollapse;
+    bool optNoArrayOf;
+
+protected:
+    Owned<IFile> serviceDef;
+    StringBuffer outputBuffer;
+    StringBuffer fullxsltpath;
+    Owned<IProperties> opts;
+    Owned<IProperties> params;
+    StringBuffer tns;
+    StringBuffer outfileext;
+};
+
+class Esdl2WSDLCmd : public Esdl2XSDCmd
+{
+public:
+    Esdl2WSDLCmd()
+    {
+         outfileext.set(".wsdl");
+    }
+    virtual bool parseCommandLineOption(ArgvIterator &iter)
+    {
+        if (iter.matchFlag(optWsdlAddress, ESDLOPT_WSDL_ADDRESS))
+            return true;
+
+        if (Esdl2XSDCmd::parseCommandLineOption(iter))
+            return true;
+
+        return false;
+    }
+
+    esdlCmdOptionMatchIndicator matchCommandLineOption(ArgvIterator &iter, bool finalAttempt)
+    {
+        return Esdl2XSDCmd::matchCommandLineOption(iter, true);
+    }
+
+    virtual bool finalizeOptions(IProperties *globals)
+    {
+        if (optWsdlAddress.isEmpty())
+            optWsdlAddress.set("localhost");
+
+        return Esdl2XSDCmd::finalizeOptions(globals);
+    }
+
+    virtual void doTransform(IEsdlDefObjectIterator& objs, StringBuffer &target, double version=0, IProperties *opts=NULL, const char *ns=NULL, unsigned flags=0 )
+    {
+        TimeSection ts("transforming via XSLT");
+        helper->toWSDL(objs, target, EsdlXslToWsdl, optVersion, opts, NULL, optFlags);
+    }
+
+    virtual void loadTransform( StringBuffer &xsltpath, IProperties *params)
+    {
+        TimeSection ts("loading XSLT");
+        helper->loadTransform( xsltpath, params, EsdlXslToWsdl );
+    }
+
+    virtual void setTransformParams(IProperties *params )
+    {
+        helper->setTransformParams(EsdlXslToWsdl, params);
+    }
+
+    virtual int processCMD()
+    {
+        loadServiceDef();
+        createOptionals();
+
+        Owned<IEsdlDefObjectIterator> structs = esdlDef->getDependencies( optService.get(), optMethod.get(), ESDLOPTLIST_DELIMITER, optVersion, opts.get(), optFlags );
+
+        if( optRawOutput )
+        {
+            outputRaw(*structs);
+        }
+
+        if( !optXsltPath.isEmpty() )
+        {
+            createParams();
+            loadTransform( fullxsltpath, params);
+
+            for( int i=0; i < optXformTimes; i++ )
+            {
+                doTransform( *structs, outputBuffer, optVersion, opts.get(), NULL, optFlags );
+            }
+
+            outputToFile();
+
+            printf( "%s\n", outputBuffer.str() );
+        }
+        else
+        {
+            throw( MakeStringException(0, "Path to /xslt/esxdl2xsd.xslt is empty, cannot perform transform.") );
+        }
+
+        return 0;
+    }
+
+    virtual void usage()
+    {
+        puts("Usage:");
+        puts("esdl wsdl sourcePath serviceName [options]\n" );
+        puts("\nsourcePath must be absolute path to the ESDL Definition file containing the" );
+        puts("EsdlService definition for the service you want to work with.\n" );
+        puts("serviceName EsdlService definition for the service you want to work with.\n" );
+
+        printOptions();
+        puts("  --wsdladdress  Defines the output WSDL's location address\n");
+        EsdlConvertCmd::usage();
+    }
+
+    virtual void createParams()
+    {
+        params.set(createProperties());
+        generateNamespace(tns);
+
+        params->setProp( "tnsParam", tns );
+        params->setProp( "optional", optOptional );
+
+        if( optAllAnnot )
+        {
+            params->setProp( "all_annot_Param", 1 );
+        }
+
+        if( optNoAnnot )
+        {
+            params->setProp( "no_annot_Param", 1 );
+        }
+
+        params->setProp( "create_wsdl", "true()" );
+        params->setProp( "location", optWsdlAddress.get());
+    }
+
+public:
+    StringAttr optWsdlAddress;
+};
+
+//=========================================================================================
+
+IEsdlCommand *createCoreEsdlCommand(const char *cmdname)
+{
+    if (!cmdname || !*cmdname)
+        return NULL;
+    if (strieq(cmdname, "XSD"))
+        return new Esdl2XSDCmd();
+    if (strieq(cmdname, "ECL"))
+        return new Esdl2EclCmd();
+    if (strieq(cmdname, "WSDL"))
+        return new Esdl2WSDLCmd();
+    if (strieq(cmdname, "PUBLISH"))
+        return new EsdlPublishCmd();
+    if (strieq(cmdname, "BIND-SERVICE"))
+        return new EsdlBindServiceCmd();
+    if (strieq(cmdname, "BIND-METHOD"))
+        return new EsdlBindMethodCmd();
+    if (strieq(cmdname, "GET-BINDING"))
+        return new EsdlGetBindingCmd();
+    if (strieq(cmdname, "GET-DEFINITION"))
+        return new EsdlGetDefinitionCmd();
+
+    return NULL;
+}

+ 25 - 0
tools/esdlcmd/esdlcmd_core.hpp

@@ -0,0 +1,25 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#ifndef ESDLCMD_CORE_HPP
+#define ESDLCMD_CORE_HPP
+
+#include "esdlcmd_common.hpp"
+
+IEsdlCommand *createCoreEsdlCommand(const char *cmdname);
+
+#endif

+ 189 - 0
tools/esdlcmd/esdlcmd_shell.cpp

@@ -0,0 +1,189 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#include <stdio.h>
+#include "jlog.hpp"
+#include "jfile.hpp"
+#include "jargv.hpp"
+#include "jprop.hpp"
+
+#include "build-config.h"
+
+#include "esdlcmd.hpp"
+#include "esdlcmd_core.hpp"
+
+
+//=========================================================================================
+
+#ifdef _WIN32
+#include "process.h"
+#endif
+
+int EsdlCMDShell::callExternal(ArgvIterator &iter)
+{
+    const char *argv[100];
+    StringBuffer cmdstr("esdl-");
+    cmdstr.append(cmd.sget());
+    int i=0;
+    argv[i++]=cmdstr.str();
+    if (optHelp)
+        argv[i++]="--help";
+    for (; !iter.done(); iter.next())
+        argv[i++]=iter.query();
+    argv[i]=NULL;
+//TODO - add common routine or use existing in jlib
+#ifdef _WIN32
+    if (_spawnvp(_P_WAIT, cmdstr.str(), const_cast<char **>(argv))==-1)
+#else
+    if (execvp(cmdstr.str(), const_cast<char **>(argv))==-1)
+#endif
+    {
+        switch(errno)
+        {
+        case ENOENT:
+            fprintf(stderr, "esdl '%s' command not found\n", cmd.sget());
+            usage();
+            return 1;
+        default:
+            fprintf(stderr, "esdl '%s' command error %d\n", cmd.sget(), errno);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+int EsdlCMDShell::processCMD(ArgvIterator &iter)
+{
+    Owned<IEsdlCommand> c = factory(cmd.get());
+    if (!c)
+    {
+        if (cmd.length())
+        {
+            if (runExternals)
+                return callExternal(iter);
+            fprintf(stderr, "esdl '%s' command not found\n", cmd.sget());
+        }
+        usage();
+        return 1;
+    }
+    if (optHelp)
+    {
+        c->usage();
+        return 0;
+    }
+    if (!c->parseCommandLineOptions(iter))
+        return 0;
+
+    if (!c->finalizeOptions(globals))
+        return 0;
+
+    return c->processCMD();
+}
+
+void EsdlCMDShell::finalizeOptions(IProperties *globals)
+{
+}
+
+int EsdlCMDShell::run()
+{
+    try
+    {
+        if (!parseCommandLineOptions(args))
+            return 1;
+
+        finalizeOptions(globals);
+
+        return processCMD(args);
+    }
+    catch (IException *E)
+    {
+        StringBuffer m;
+        fputs(E->errorMessage(m).newline().str(), stderr);
+        E->Release();
+        return 2;
+    }
+#ifndef _DEBUG
+    catch (...)
+    {
+        ERRLOG("Unexpected exception\n");
+        return 4;
+    }
+#endif
+    return 0;
+}
+
+//=========================================================================================
+
+bool EsdlCMDShell::parseCommandLineOptions(ArgvIterator &iter)
+{
+    if (iter.done())
+    {
+        usage();
+        return false;
+    }
+
+    bool boolValue;
+    for (; !iter.done(); iter.next())
+    {
+        const char * arg = iter.query();
+        if (iter.matchFlag(optHelp, ESDLARG_HELP) || iter.matchFlag(optHelp, ESDLOPT_HELP)) //users expect --help to work too
+            continue;
+        if (*arg!='-')
+        {
+            cmd.set(arg);
+            iter.next();
+            break;
+        }
+        if (iter.matchFlag(boolValue, "--version"))
+        {
+            fprintf(stdout, "%s\n", BUILD_TAG);
+            return false;
+        }
+        StringAttr tempArg;
+        if (iter.matchOption(tempArg, "-brk"))
+        {
+#if defined(_WIN32) && defined(_DEBUG)
+            unsigned id = atoi(tempArg.sget());
+            if (id == 0)
+                DebugBreak();
+            else
+                _CrtSetBreakAlloc(id);
+#endif
+        }
+    }
+    return true;
+}
+
+//=========================================================================================
+
+void EsdlCMDShell::usage()
+{
+    fprintf(stdout,"\nUsage:\n"
+        "    esdl [--version] <command> [<args>]\n\n"
+           "Commonly used commands:\n"
+           "   xml               Generate XML from ESDL definition.\n"
+           "   ecl               Generate ECL from ESDL definition.\n"
+           "   xsd               Generate XSD from ESDL definition.\n"
+           "   wsdl              Generate WSDL from ESDL definition.\n"
+           "   publish           Publish ESDL Definition for ESP use.\n"
+           "   bind-service      Configure ESDL based service on target ESP (with existing ESP Binding).\n"
+           "   new-bind-service  Configure ESDL based service on target ESP (binds with future ESP Binding).\n"
+           "   bind-method       Configure method associated with existing ESDL binding.\n"
+           "   get-binding       Get ESDL binding.\n"
+           "\nRun 'esdl help <command>' for more information on a specific command\n\n"
+    );
+}

+ 26 - 0
tools/esdlcmd/sourcedoc.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+################################################################################
+#    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+################################################################################
+-->
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+<section>
+    <title>tools/esdl</title>
+
+    <para>
+        The tools/esdl directory contains the sources for the esdl tool.
+    </para>
+</section>

+ 2 - 6
tools/esdlcomp/CMakeLists.txt

@@ -50,12 +50,8 @@ include_directories (
 ADD_DEFINITIONS( -D_CONSOLE -DESDLCOMP_EXPORTS -O0 )
 HPCC_ADD_LIBRARY ( esdlcomp SHARED ${SRCS} )
 
-# The library esdlcomp is built in HPCCPlatform as a build-time
-# pre-req. But it is not distributed in CE packages.
-if ("${BUILD_LEVEL}" STREQUAL "ENTERPRISE" OR "${BUILD_LEVEL}" STREQUAL "INTERNAL")
-    MESSAGE("----INSTALLING esdlcomp")
-    install ( TARGETS esdlcomp RUNTIME DESTINATION bin LIBRARY DESTINATION lib )
-endif()
+MESSAGE("----INSTALLING esdlcomp")
+install ( TARGETS esdlcomp RUNTIME DESTINATION bin LIBRARY DESTINATION lib )
 
 target_link_libraries ( esdlcomp
                    jlib )