Browse Source

Add ESP support for JSON formatted responses

Refactors ESP message serialization code.  Encapsulates format
specific code. Adds support for JSON responses.

For now, desired format is specified in the request url by adding
an extension to the method name at the end of the path.

i.e. for XML:
http://host:8010/MyService/MyMethod.xml?Wuid=W20120621-123710

for JSON:
http://host:8010/MyService/MyMethod.json?Wuid=W20120621-123710

Fixes gh-2741.

Signed-off-by: Anthony Fishbeck <Anthony.Fishbeck@lexisnexis.com>
Anthony Fishbeck 13 years ago
parent
commit
03a131fa4f

+ 94 - 0
esp/bindings/SOAP/Platform/soapbind.cpp

@@ -266,6 +266,100 @@ void CSoapRequestBinding::post(const char *proxy, const char* url, IRpcResponseB
     }
 }
 
+void CSoapComplexType::appendContent(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer& mimetype)
+{
+    StringBuffer content;
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+    {
+        content.append('{');
+        serializeStruct(ctx, content, (const char *)NULL);
+        content.append('}');
+        mimetype.set("application/json; charset=UTF-8");
+    }
+    else
+    {
+        buffer.append(38, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+        serializeStruct(ctx, content, (const char *)NULL);
+        mimetype.set("text/xml; charset=UTF-8");
+    }
+
+    buffer.append(content.length(), content.str());
+}
+
+inline void open_element(IEspContext *ctx, StringBuffer &xml, const char *name, const char *uri, const char *prefix)
+{
+    if (!name || !*name)
+        return;
+    xml.append("<");
+    if (prefix && *prefix)
+        xml.append(prefix).append(':');
+    xml.append(name);
+    if (uri && *uri)
+    {
+        xml.append("xmlns");
+        if (prefix && *prefix)
+            xml.append(':').append(prefix);
+        xml.append("=\"").append(uri).append('\"');
+    }
+}
+
+inline void start_child_attributes(IEspContext *ctx, StringBuffer &xml, const char *name)
+{
+}
+
+inline void start_child_elements(IEspContext *ctx, StringBuffer &xml, const char *name)
+{
+    if (!name || !*name)
+        return;
+    xml.append('>');
+}
+
+inline void close_element(IEspContext *ctx, StringBuffer &xml, const char *name, const char *prefix)
+{
+    if (!name || !*name)
+        return;
+    xml.append("</");
+    if (prefix && *prefix)
+        xml.append(prefix).append(':');
+    xml.append(name).append('>');
+}
+
+void CSoapComplexType::serializeJSONStruct(IEspContext* ctx, StringBuffer& s, const char *name)
+{
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+    {
+        if (s.length() && !strchr("[{:", s.charAt(s.length()-1)))
+            s.append(", ");
+        if (name && *name)
+            s.append('\"').append(name).append("\": ");
+        s.append("{");
+        serializeContent(ctx, s);
+        s.append("}");
+        return;
+    }
+}
+
+void CSoapComplexType::serializeStruct(IEspContext* ctx, StringBuffer& s, const char *name)
+{
+    const char *tag = (name && *name) ? name : getRootName();
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return serializeJSONStruct(ctx, s, tag);
+
+    open_element(ctx, s, tag, getNsURI(), getNsPrefix());
+    start_child_attributes(ctx, s, name);
+    serializeAttributes(ctx, s);
+    start_child_elements(ctx, s, tag);
+    serializeContent(ctx, s);
+    close_element(ctx, s, tag, getNsPrefix());
+}
+
+void CSoapComplexType::serializeItem(IEspContext* ctx, StringBuffer& s, const char *name)
+{
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return serializeJSONStruct(ctx, s, NULL);
+    serializeStruct(ctx, s, name);
+}
+
 void CSoapResponseBinding::handleExceptions(IMultiException *me, const char *serv, const char *meth)
 {
     if (me->ordinality() > 0)

+ 29 - 46
esp/bindings/SOAP/Platform/soapbind.hpp

@@ -41,8 +41,8 @@
 #include "http/platform/httpbinding.hpp"
 
 
-class CSoapComplexType : public CInterface ,
-        implements IRpcSerializable
+class esp_http_decl CSoapComplexType : public CInterface,
+    implements IRpcSerializable
 {
 protected:
     unsigned clvalue_;
@@ -62,23 +62,28 @@ public:
     void setThunkHandle(void * val){thunk_=val;}
     void * getThunkHandle(){return thunk_;}
 
-    virtual void serialize(StringBuffer& buffer, const char *rootname)
-    { throw MakeStringException(-1,"serialize() unimplemented: needs to be overridden"); }
+    virtual void appendContent(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer& mimetype);
+    virtual void serializeJSONStruct(IEspContext* ctx, StringBuffer& s, const char *name);
+    virtual void serializeStruct(IEspContext * ctx, StringBuffer & buffer, const char * rootname=NULL);
+    virtual void serializeItem(IEspContext* ctx, StringBuffer& s, const char *name);
+    virtual void serializeAttributes(IEspContext* ctx, StringBuffer& s)=0;
+    virtual void serializeContent(IEspContext* ctx, StringBuffer& buffer, IProperties **pprops=NULL) = 0;
+    virtual void serialize(IEspContext * ctx, StringBuffer & buffer, const char * rootname=NULL)
+    {
+        serializeStruct(ctx, buffer, rootname);
+    }
 
-    virtual bool unserialize(IRpcMessage & rpc, const char * tagname, const char * basepath)
-    { throw MakeStringException(-1,"unserialize() unimplemented: needs to be overridden"); }
+    virtual const char *getNsURI()=0;
+    virtual const char *getNsPrefix()=0;
+    virtual const char *getRootName()=0;
 };
 
-class esp_http_decl CSoapResponseBinding : public CInterface,
+class esp_http_decl CSoapResponseBinding : public CSoapComplexType,
     implements IRpcResponseBinding,
-    implements IEspResponse,
-    implements IRpcSerializable
+    implements IEspResponse
 {
 private:
     RpcMessageState state_;
-    unsigned clvalue_;
-    unsigned msg_id_;
-    void *thunk_;
     StringBuffer redirectUrl_;
     Owned<IMultiException> exceptions_;
 
@@ -88,9 +93,6 @@ public:
     CSoapResponseBinding()
     {
         state_=RPC_MESSAGE_OK;
-        clvalue_=0;
-        msg_id_=0;
-        thunk_=NULL;
         exceptions_.setown(MakeMultiException("CSoapResponseBinding"));
     }
 
@@ -118,19 +120,13 @@ public:
     const char *getRedirectUrl()                   { return redirectUrl_.str();    }
     const IMultiException& getExceptions() { return *exceptions_;          }
     void  noteException(IException& e)     { exceptions_->append(e);          }
-
     void handleExceptions(IMultiException *me, const char *serv, const char *meth);
-    virtual void serialize(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer& mimetype) 
-    {
-        throw MakeStringException(-1,"Method unimplemented");
-    }
 };
 
 
-class esp_http_decl CSoapRequestBinding : public CInterface,
+class esp_http_decl CSoapRequestBinding : public CSoapComplexType,
     implements IRpcRequestBinding,
-    implements IEspRequest ,
-    implements IRpcSerializable
+    implements IEspRequest
 {
 private:
     StringBuffer url_;
@@ -138,19 +134,20 @@ private:
     StringBuffer userid_;
     StringBuffer password_;
     StringBuffer realm_;
-    unsigned clvalue_;
-    unsigned msg_id_;
-    void *thunk_;
 
 public:
     IMPLEMENT_IINTERFACE;
 
-    CSoapRequestBinding()
-    {
-        clvalue_=0;
-        msg_id_=0;
-        thunk_=NULL;
-    }
+    CSoapRequestBinding(){}
+
+    void setClientValue(unsigned val){clvalue_=val;}
+    unsigned getClientValue(){return clvalue_;}
+
+    void setMessageId(unsigned val){msg_id_=val;}
+    unsigned getMessageId(){return msg_id_;}
+
+    void setThunkHandle(void * val){thunk_=val;}
+    void * getThunkHandle(){return thunk_;}
 
     void setUrl(const char *url){url_.clear().append(url);} 
     const char * getUrl(){return url_.str();}
@@ -167,31 +164,17 @@ public:
     void setRealm(const char *realm){realm_.clear().append(realm);} 
     const char * getRealm(){return realm_.str();}
 
-    void setClientValue(unsigned val){clvalue_=val;}
-    unsigned getClientValue(){return clvalue_;}
-
-    void setThunkHandle(void * val){thunk_=val;}
-    void * getThunkHandle(){return thunk_;}
-
-    void setMessageId(unsigned val){msg_id_=val;}
-    unsigned getMessageId(){return msg_id_;}
-
     void post(const char *proxy, const char* url, IRpcResponseBinding& response, const char *action=NULL);
 
     void post(IRpcResponseBinding& response)
     {
         post(getProxyAddress(), getUrl(), response);
     }
-    
-    //virtual void serializeContent(StringBuffer& buffer) { }
-    virtual void serializeContent(IEspContext* ctx, StringBuffer& buffer, IProperties **pprops=NULL) = 0;
 
     virtual void serialize(IRpcMessage& rpc)
     {
         throw MakeStringException(-1,"Internal error: umimplmented function called: CSoapRequestBinding::serialize()");
     }
-    
-    //virtual void serialize(StringBuffer& buffer, const char *rootname){}  
 };
 
 

+ 663 - 0
esp/bindings/SOAP/Platform/soapparam.cpp

@@ -0,0 +1,663 @@
+/*##############################################################################
+
+    Copyright (C) 2011 HPCC Systems.
+
+    All rights reserved. This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as
+    published by the Free Software Foundation, either version 3 of the
+    License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+############################################################################## */
+
+#include "esphttp.hpp"
+
+#include "jstring.hpp"
+#include "jprop.hpp"
+
+#include "soapesp.hpp"
+#include "soapmessage.hpp"
+#include "soapparam.hpp"
+
+void BaseEspParam::toJSON(IEspContext *ctx, StringBuffer &s, const char *tagname)
+{
+    if (isNil && nilBH==nilRemove)
+        return;
+    appendJSONName(s, tagname);
+    toJSONValue(s);
+}
+
+void BaseEspParam::toXML(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *prefix, bool encode)
+{
+    if (isNil && nilBH==nilRemove)
+        return;
+    appendXMLOpenTag(s, tagname, prefix);
+    toXMLValue(s, encode);
+    appendXMLCloseTag(s, tagname, prefix);
+}
+
+void BaseEspParam::toStr(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *basepath, bool encode, const char *xsdtype, const char *prefix)
+{
+    if (isNil && nilBH!=nilIgnore)
+        return;
+
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return toJSON(ctx, s, tagname);
+    toXML(ctx, s, tagname, prefix, encode);
+}
+
+void BaseEspParam::marshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char *xsdtype, const char *prefix)
+{
+    addRpcValue(rpc_call, tagname, basepath, xsdtype, prefix, NULL);
+}
+
+bool BaseEspParam::unmarshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    StringBuffer path(basepath);
+    if (basepath!=NULL && basepath[0]!=0)
+        path.append("/");
+    path.append(tagname);
+
+    if (updateValue(rpc_call, path.str()))
+    {
+        if (optGroup && rpc_call.queryContext())
+            rpc_call.queryContext()->addOptGroup(optGroup);
+        isNil = false;
+    }
+    return isNil;
+}
+
+bool BaseEspParam::unmarshall(IEspContext* ctx, CSoapValue &soapval, const char *tagname, const char* optGroup)
+{
+    if (updateValue(soapval, tagname))
+    {
+        if (ctx && optGroup)
+            ctx->addOptGroup(optGroup);
+        isNil = false;
+    }
+    return isNil;
+}
+
+bool BaseEspParam::unmarshall(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    StringBuffer path;
+    if (basepath && *basepath)
+        path.append(basepath).append('.');
+    path.append(tagname);
+
+    if (updateValue(params.queryProp(path.str())))
+    {
+        isNil = false;
+        if (ctx && optGroup)
+            ctx->addOptGroup(optGroup);
+    }
+    return isNil;
+}
+
+void SoapStringParam::toXMLValue(StringBuffer &s, bool encode)
+{
+    if (!encode)
+        s.append(value);
+    else
+        encodeUtf8XML(value.str(), s, getEncodeNewlines() ? ENCODE_NEWLINES : 0);
+}
+
+void SoapStringParam::toJSONValue(StringBuffer &s)
+{
+    appendJSONValue(s, NULL, (isNil) ? NULL : value.str());
+}
+
+void SoapStringParam::addRpcValue(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char *xsdtype, const char *prefix, bool *encodex)
+{
+    if (!isNil || nilBH==nilIgnore)
+        rpc_call.add_value(basepath, prefix, tagname, xsdtype, value.str(), (!encodex) ? rpc_call.getEncodeXml() : *encodex);
+}
+
+bool SoapStringParam::updateValue(IRpcMessage &rpc_call, const char *path)
+{
+    StringBuffer tmp;
+    if (rpc_call.get_value(path, tmp))
+    {
+        value.set(tmp.str());
+        return true;
+    }
+    return false;
+}
+
+bool SoapStringParam::updateValue(CSoapValue &soapval, const char *tagname)
+{
+    return soapval.get_value(tagname, value.clear());
+}
+
+bool SoapStringParam::updateValue(const char *s)
+{
+    if (!s)
+        return false;
+    return esp_convert(s, value.clear());
+}
+
+bool SoapStringParam::unmarshallAttach(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    if(attachments)
+    {
+        StringBuffer key;
+        if (basepath && *basepath)
+            key.append(basepath).append(".");
+        key.append(tagname);
+
+        StringBuffer* data = attachments->getValue(key.str());
+        if (data)
+        {
+            StringBuffer path;
+            if (basepath && *basepath)
+                path.append(basepath).append(".");
+            path.append(tagname);
+            isNil=false;
+            value.clear().swapWith(*data);
+            if (ctx && optGroup)
+                ctx->addOptGroup(optGroup);
+            return true;
+        }
+    }
+    return false;
+}
+
+void BaseEspStruct::marshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char *xsdtype, const char *prefix)
+{
+    StringBuffer xml;
+    Owned<IProperties> props;
+    serializeContent(rpc_call.queryContext(), xml, props);
+
+    if (xml.length() || nilBH==nilIgnore || props)
+        rpc_call.add_value(basepath, prefix, tagname, xsdtype, xml.str(), false);
+    if (props)
+        rpc_call.add_attr(basepath, tagname, NULL, *props);
+}
+
+void BaseEspStruct::toJSON(IEspContext* ctx, StringBuffer &s, const char *tagname)
+{
+    size32_t start = s.length();
+    appendJSONName(s, tagname);
+    s.append('{');
+    size32_t check = s.length();
+    serializeContent(ctx, s);
+    if (s.length()==check)
+        s.setLength(start);
+    else
+        s.append('}');
+}
+
+void BaseEspStruct::toXML(IEspContext *ctx, StringBuffer &s, const char *tagname, const char *prefix, bool encode)
+{
+    size32_t start = s.length();
+    appendXMLOpenTag(s, tagname, prefix, false);
+    size32_t check = s.length();
+    serializeAttributes(ctx, s);
+    s.append('>');
+    serializeContent(ctx, s);
+    if (nilBH==nilIgnore || s.length()!=check+1)
+        appendXMLCloseTag(s, tagname, prefix);
+    else
+        s.setLength(start);
+}
+
+void BaseEspStruct::toStr(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *basepath, bool encode, const char *xsdtype, const char *prefix)
+{
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return toJSON(ctx, s, tagname);
+    toXML(ctx, s, tagname, prefix, encode);
+}
+
+bool BaseEspStruct::unmarshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    StringBuffer path;
+    if (basepath && *basepath)
+    {
+        path.append(basepath);
+        if (path.charAt(path.length()-1)!='/')
+            path.append("/");
+    }
+    path.append(tagname);
+    if (updateValue(rpc_call, path.str()))
+    {
+        if (optGroup && rpc_call.queryContext())
+            rpc_call.queryContext()->addOptGroup(optGroup);
+        return true;
+    }
+    return false;
+}
+
+bool BaseEspStruct::unmarshall(IEspContext* ctx, CSoapValue &soapval, const char *tagname, const char* optGroup)
+{
+    CSoapValue *sv = soapval.get_value(tagname);
+    if (sv)
+    {
+        updateValue(ctx, *sv);
+        if (ctx && optGroup)
+            ctx->addOptGroup(optGroup);
+        return true;
+    }
+    return false;
+}
+
+bool BaseEspStruct::unmarshall(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+   StringBuffer path;
+   if (basepath && *basepath)
+       path.append(basepath).append(".");
+   path.append(tagname);
+
+   if (updateValue(ctx, params, attachments, path.str()))
+   {
+       if (ctx && optGroup)
+           ctx->addOptGroup(optGroup);
+       return true;
+   }
+   return false;
+}
+
+void SoapParamBinary::marshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char *xsdtype, const char *prefix)
+{
+    StringBuffer sb64;
+    JBASE64_Encode(value.toByteArray(), value.length(), sb64);
+    rpc_call.add_value(basepath, prefix, tagname, xsdtype, sb64);
+}
+
+void SoapParamBinary::toJSON(IEspContext* ctx, StringBuffer &s, const char *tagname)
+{
+    if (s.length() && !strchr("{[:", s.charAt(s.length()-1)))
+        s.append(", ");
+    if (tagname && *tagname)
+        s.append('"').append(tagname).append("\": ");
+    s.append('"');
+    JBASE64_Encode(value.toByteArray(), value.length(), s);
+    s.append('"');
+    return;
+}
+
+void SoapParamBinary::toXML(IEspContext *ctx, StringBuffer &s, const char *tagname, const char *prefix, bool encode)
+{
+    appendXMLOpenTag(s, tagname, prefix);
+    JBASE64_Encode(value.toByteArray(), value.length(), s);
+    appendXMLCloseTag(s, tagname, prefix);
+}
+
+void SoapParamBinary::toStr(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *basepath, bool encode, const char *xsdtype, const char *prefix)
+{
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return toJSON(ctx, s, tagname);
+    toXML(ctx, s, tagname, prefix, encode);
+}
+
+bool SoapParamBinary::unmarshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    StringBuffer path(basepath);
+    if (basepath!=NULL && basepath[0]!=0)
+        path.append("/");
+    path.append(tagname);
+
+    StringBuffer sb64;
+    bool ret = rpc_call.get_value(path.str(), sb64);
+    if (ret && optGroup && rpc_call.queryContext())
+        rpc_call.queryContext()->addOptGroup(optGroup);
+
+    if(sb64.length())
+        JBASE64_Decode(sb64.str(), value);
+
+    return ret;
+}
+
+bool SoapParamBinary::unmarshall(IEspContext* ctx, CSoapValue &soapval, const char *tagname, const char* optGroup)
+{
+    return false;
+}
+
+bool SoapParamBinary::unmarshall(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    StringBuffer path;
+    if (basepath && *basepath)
+        path.append(basepath).append(".");
+    path.append(tagname);
+
+    const char* val = params.queryProp(path.str());
+    if(val)
+    {
+        if (ctx && optGroup)
+            ctx->addOptGroup(optGroup);
+        JBASE64_Decode(params.queryProp(path.str()), value);
+        return true;
+    }
+    return false;
+}
+
+
+void SoapAttachString::marshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char *xsdtype, const char *prefix)
+{
+    rpc_call.add_value(basepath, prefix, tagname, "Attachment", value);
+}
+
+void SoapAttachString::toJSON(IEspContext *ctx, StringBuffer &s, const char *tagname)
+{
+    appendJSONValue(s, tagname, value);
+}
+
+void SoapAttachString::toXML(IEspContext *ctx, StringBuffer &s, const char *tagname, const char *prefix, bool encode)
+{
+    appendXMLTag(s, tagname, value, prefix, ENCODE_NONE);
+}
+
+void SoapAttachString::toStr(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *basepath, bool encode, const char *xsdtype, const char *prefix)
+{
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return toJSON(ctx, s, tagname);
+    toXML(ctx, s, tagname, prefix, encode);
+}
+
+bool SoapAttachString::unmarshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char* optGroup,const char *xsdtype, const char *prefix)
+{
+    StringBuffer path(basepath);
+    if (basepath!=NULL && basepath[0]!=0)
+        path.append("/");
+    path.append(tagname);
+
+    if (rpc_call.get_value(path.str(), value)) {
+        if (optGroup && rpc_call.queryContext())
+            rpc_call.queryContext()->addOptGroup(optGroup);
+        return true;
+    }
+    return false;
+}
+
+bool SoapAttachString::unmarshall(IEspContext* ctx, CSoapValue &soapval, const char *tagname, const char* optGroup)
+{
+    return false;
+}
+
+bool SoapAttachString::unmarshall(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char *xsdtype, const char *prefix)
+{
+    return false;
+}
+
+StringBuffer &buildVarPath(StringBuffer &path, const char *tagname, const char *basepath, const char *item, const char *tail, int *idx)
+{
+    path.clear();
+    if (basepath)
+        path.append(basepath).append(".");
+    path.append(tagname);
+    if (item)
+        path.append(".").append(item);
+    if (tail)
+        path.append(".").append(tail);
+    if (idx)
+        path.append(".").append(*idx);
+    return path;
+}
+
+void EspBaseArrayParam::toJSON(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *itemname)
+{
+    unsigned count = getLength();
+    if (!count)
+    {
+        if (nilBH!=nilRemove)
+        {
+            if (s.length() && !strchr("{[:", s.charAt(s.length()-1)))
+                s.append(", ");
+            if (tagname && *tagname)
+                s.append('\"').append(tagname).append("\": ");
+            s.append("[]");
+        }
+        return;
+    }
+
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+    {
+        appendJSONName(s, tagname);
+        if (tagname && *tagname && itemname && *itemname)
+            s.append('{');
+        if (!itemname || !*itemname)
+            itemname = getItemTag(itemname);
+        appendJSONName(s, itemname);
+        s.append('[');
+        for (unsigned  i=0; i<count; i++)
+            toStrItem(ctx, s, i, itemname);
+        s.append(']');
+        if (tagname && *tagname && itemname && *itemname)
+            s.append('}');
+    }
+}
+
+void EspBaseArrayParam::toXML(IEspContext *ctx, StringBuffer &s, const char *tagname, const char *itemname, const char *prefix, bool encode)
+{
+    itemname = getItemTag(itemname);
+    unsigned count = getLength();
+    if (!count)
+    {
+        if (nilBH != nilRemove)
+            appendXMLOpenTag(s, tagname, prefix, true, true);
+        return;
+    }
+
+    appendXMLOpenTag(s, tagname, prefix);
+    for (unsigned  i=0; i<count; i++)
+        toStrItem(ctx, s, i, itemname);
+    appendXMLCloseTag(s, tagname, prefix);
+}
+
+void EspBaseArrayParam::toStr(IEspContext* ctx, StringBuffer &s, const char *tagname, const char *itemname, const char *elementtype, const char *basepath, const char *prefix)
+{
+    if (ctx->getResponseFormat()==ESPSerializationJSON)
+        return toJSON(ctx, s, tagname, itemname);
+    toXML(ctx, s, tagname, itemname, prefix, true);
+}
+
+bool EspBaseArrayParam::unmarshallItems(IEspContext* ctx, CSoapValue *sv, const char *itemname, const char *optGroup)
+{
+    if (!sv)
+        return false;
+
+    SoapValueArray* children = sv->query_children();
+    if (children)
+    {
+        if (ctx && optGroup)
+            ctx->addOptGroup(optGroup);
+        ForEachItemIn(i, *children)
+            append(ctx, children->item(i));
+        return true;
+    }
+    return false;
+}
+
+bool EspBaseArrayParam::unmarshall(IEspContext* ctx, CSoapValue &soapval, const char *tagname, const char* optGroup, const char *itemname)
+{
+    return unmarshallItems(ctx, soapval.get_value(tagname), itemname, optGroup);
+}
+
+bool EspBaseArrayParam::unmarshall(IRpcMessage &rpc_call, const char *tagname, const char *basepath, const char* optGroup, const char *prefix)
+{
+    StringBuffer path(basepath);
+    if (basepath!=NULL && basepath[0]!=0)
+        path.append("/");
+    path.append(tagname);
+
+    return unmarshallItems(rpc_call.queryContext(), dynamic_cast<CRpcMessage *>(&rpc_call)->get_value(path), NULL, optGroup);
+}
+
+bool EspBaseArrayParam::unmarshallAttach(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    bool hasValue = false;
+    if(attachments)
+    {
+        StringBuffer path;
+        buildVarPath(path, tagname, basepath, NULL, "itemlist", NULL);
+        if (params.hasProp(path.str()))
+        {
+            hasValue = true;
+            //sparse array encoding
+            char *itemlist = strdup(params.queryProp(path.str()));
+            char *delim=NULL;
+            if (itemlist)
+            {
+                for(char *finger=itemlist; finger; finger=(delim) ? delim+1 : NULL)
+                {
+                    if ((delim=strchr(finger, '+')))
+                        *delim=0;
+                    if (*finger)
+                    {
+                        buildVarPath(path, tagname, basepath, finger, NULL, NULL);
+                        StringBuffer* data = attachments->getValue(path.str());
+                        if (data)
+                            append(data->str());
+                    }
+                }
+                free(itemlist);
+            }
+        }
+        else
+        {
+            buildVarPath(path, tagname, basepath, NULL, "itemcount", NULL);
+            int count=params.getPropInt(path.str(), -1);
+            if (count>0)
+            {
+                hasValue = true;
+                for (int idx=0; idx<count; idx++)
+                {
+                    buildVarPath(path, tagname, basepath, NULL, NULL, &idx);
+                    StringBuffer* data = attachments->getValue(path.str());
+                    if (data)
+                        append(data->str());
+                }
+            }
+        }
+    }
+
+    if (hasValue && ctx && optGroup)
+        ctx->addOptGroup(optGroup);
+
+    return hasValue;
+}
+
+bool EspBaseArrayParam::unmarshall(IEspContext* ctx, IProperties &params, MapStrToBuf *attachments, const char *tagname, const char *basepath, const char* optGroup, const char *xsdtype, const char *prefix)
+{
+    if (unmarshallRawArray(params, tagname, basepath))
+    {
+        if (ctx && optGroup)
+            ctx->addOptGroup(optGroup);
+        return true;
+    }
+
+    StringBuffer path;
+    if (basepath && *basepath)
+       path.append(basepath).append(".");
+    path.append(tagname);
+    const char *pathstr=path.str();
+
+    bool hasValue = false;
+    Owned<IPropertyIterator> iter = params.getIterator();
+
+    if (pathstr && *pathstr && iter && iter->first())
+    {
+        int taglen = strlen(pathstr);
+        while (iter->isValid())
+        {
+            const char *keyname=iter->getPropKey();
+            if (strncmp(keyname, pathstr, taglen)==0)
+            {
+                if (strlen(keyname)==taglen || !strncmp(keyname+taglen, "_rd_", 4))
+                {
+                    const char *finger = params.queryProp(iter->getPropKey());
+                    StringBuffer itemval;
+                    while (*finger)
+                    {
+                        if (*finger=='\r')
+                            finger++;
+
+                        if (*finger=='\n')
+                        {
+                            if (itemval.length())
+                                append(itemval.str());
+                            itemval.clear();
+                        }
+                        else
+                        {
+                            itemval.append(*finger);
+                        }
+                        finger++;
+                    }
+                    if (itemval.length())
+                    {
+                        append(itemval.str());
+                        hasValue = true;
+                    }
+                }
+                else if (strncmp(keyname+taglen, "_v", 2)==0)
+                {
+                    if (params.getPropInt(keyname)) {
+                        append(keyname+taglen+2);
+                        hasValue = true;
+                    }
+                }
+                else if (strncmp(keyname+taglen, "_i", 2)==0)
+                {
+                    append(params.queryProp(iter->getPropKey()));
+                    hasValue = true;
+                }
+            }
+
+            iter->next();
+        }
+    }
+
+    if (hasValue && ctx && optGroup)
+        ctx->addOptGroup(optGroup);
+
+    return hasValue;
+}
+
+bool EspBaseArrayParam::unmarshallRawArray(IProperties &params, const char *tagname, const char *basepath)
+{
+    StringBuffer path;
+    buildVarPath(path, tagname, basepath, NULL, "itemlist", NULL);
+    if (params.hasProp(path.str()))
+    {
+        //sparse array encoding
+        char *itemlist=strdup(params.queryProp(path.str()));
+        char *delim=NULL;
+        if (itemlist)
+        {
+            for(char *finger=itemlist; finger; finger=(delim) ? delim+1 : NULL)
+            {
+                if ((delim=strchr(finger, '+')))
+                    *delim=0;
+                if (*finger)
+                {
+                    buildVarPath(path, tagname, basepath, finger, NULL, NULL);
+                    append(params.queryProp(path));
+                }
+            }
+            free(itemlist);
+            return true;
+        }
+    }
+    else
+    {
+        buildVarPath(path, tagname, basepath, NULL, "itemcount", NULL);
+        int count=params.getPropInt(path.str(), -1);
+        if (count>0)
+        {
+            for (int idx=0; idx<count; idx++)
+            {
+                buildVarPath(path, tagname, basepath, NULL, NULL, &idx);
+                append(params.queryProp(path));
+            }
+            return true;
+        }
+    }
+
+    return false;
+}

File diff suppressed because it is too large
+ 489 - 1217
esp/bindings/SOAP/Platform/soapparam.hpp


+ 6 - 93
esp/bindings/http/platform/httpbinding.cpp

@@ -1747,94 +1747,6 @@ int EspHttpBinding::onGetXForm(IEspContext &context, CHttpRequest* request, CHtt
     else
     {
         StringBuffer page;
-
-
-//#define CLIENT_SIDE_XSLT
-        
-#ifdef CLIENT_SIDE_XSLT
-
-#if 0
-        //TODO: how to pass parameters to the XSL?
-        //1. We can manually insert the parameters into the XSL, but that defeats the
-        //  the client cache on the XSL. We also need to modify esp to handle request
-        //  for xsl file with parameter.
-        page.append("<?xml version='1.0' encoding='UTF-8' ?>");
-        page.append("<?xml-stylesheet type='text/xsl' href='/esp/xslt/gen_form.xsl' ?>\n");
-        getSchema(page, context, request, serv, method, true);
-        response->setContentType("text/xml");
-
-        
-#else
-        // Try: use xslt processing on Client side
-
-        page.append(
-        "<html> <head> <script type='text/javascript'>\n"
-            "var xslt = new ActiveXObject('Msxml2.XSLTemplate');\n"
-            "var xslDoc = new ActiveXObject('Msxml2.FreeThreadedDOMDocument');\n"
-            "var xslProc;\n"
-            "xslDoc.async = false;\n"
-            "xslDoc.resolveExternals = false;\n"
-            "xslDoc.load('/esp/xslt/gen_form.xsl');\n"
-            "xslt.stylesheet = xslDoc;\n"
-            "var xmlDoc = new ActiveXObject('Msxml2.DOMDocument');\n"
-            "xmlDoc.async = false;\n"
-            "xmlDoc.resolveExternals = false;\n");
-
-        page.appendf("xmlDoc.load('%s/%s?xsd');\n", serviceQName.str(), methodQName.str());
-        page.append(
-            "xslProc = xslt.createProcessor();\n"
-            
-            "xslProc.input = xmlDoc;\n"
-            //"xslProc.addParameter("subj", "mathematics");\n"
-            "xslProc.transform();\n"
-            "document.write(xslProc.output);\n"
-            
-            "</script>  </head>  \n"
-            "<body>\n"
-            "</body>\n"
-            "</html>");
-        /*
-
-        page.append("<html><head>"
-            "<script language='JavaScript'>\n"
-            " function GenForm() {\n"
-            "  var xsltProcessor = new XSLTProcessor();\n"
-            "  // Load the xsl file using synchronous XMLHttpRequest\n"
-            "  var myXMLHTTPRequest = new XMLHttpRequest();\n"
-            "  myXMLHTTPRequest.open('GET', '/esp/xslt/gen_form.xsl', false);\n"
-            "  myXMLHTTPRequest.send(null);\n"
-            "  var xslRef = myXMLHTTPRequest.responseXML;\n"
-            "  alert(xslRef);\n"
-            "  // Finally import the .xsl\n"
-            "  xsltProcessor.importStylesheet(xslRef);\n"
-            "  // Load the schema file using synchronous XMLHttpRequest\n"
-            "  myXMLHTTPRequest = new XMLHttpRequest();\n");
-        
-        page.appendf("  myXMLHTTPRequest.open('GET', '%s/%s?xsd', false);\n", serviceQName.str(), methodQName.str());
-        page.append("  myXMLHTTPRequest.send(null);\n"
-            "  var xsdDoc = myXMLHTTPRequest.responseXML;\n"
-            "  var fragment = xsltProcessor.transformToFragment(xsdDoc, document);\n"
-            //"  var fragment = xsltProcessor.transformToDocument(xsdDoc);\n"
-            "  return fragment; \n"
-            "}\n"
-            "</script>\n"
-            "\n"
-            "<body>\n"
-            "<div id='main'></div>\n"
-            "<script language='JavaScript'>\n"
-            //"  document.write(GenForm())\n"
-            "  document.getElementById('main').appendChild(GenForm())"
-            //"  document.getElementById('main').appendChild('<h1>This is inserted</h1>')"
-            "</script>\n"
-            "</body>\n"
-            "</html>\n");
-        */
-
-        response->setContentType("text/html");
-#endif
-
-#else
-        
         IXslProcessor* xslp = getXmlLibXslProcessor();
 
         // get schema
@@ -1852,7 +1764,11 @@ int EspHttpBinding::onGetXForm(IEspContext &context, CHttpRequest* request, CHtt
         StringBuffer version;
         version.appendf("%g",context.getClientVersion());
         xform->setStringParameter("serviceVersion", version);
-        xform->setStringParameter("methodName", methodQName);
+
+        StringBuffer methodExt(methodQName);
+        if (context.queryRequestParameters()->hasProp("json"))
+            methodExt.append(".json");
+        xform->setStringParameter("methodName", methodExt);
 
         // pass params to form (excluding form and __querystring)
         StringBuffer params;
@@ -1900,12 +1816,9 @@ int EspHttpBinding::onGetXForm(IEspContext &context, CHttpRequest* request, CHtt
         }
         xform->transform(page);     
         response->setContentType("text/html");
-#endif
-
-        //DBGLOG(page);
         response->setContent(page.str());
     }
-    
+
     response->send();
 
     return 0;

+ 23 - 93
esp/bindings/http/platform/httptransport.cpp

@@ -460,96 +460,6 @@ bool CHttpMessage::supportClientXslt()
     return m_supportClientXslt==1;
 }
 
-/*
-void CHttpMessage::addRawXMLParameter(const char* path, IPropertyTree* tree)
-{
-    const char* name = tree->queryName();
-    if (stricmp(name, "RawArray")==0)
-    {
-        Owned<IPropertyTreeIterator> row = tree->getElements("Item");
-
-        int items = 0;
-        for (row->first(); row->isValid(); row->next())
-        {
-            IPropertyTree* pRow = &row->query();
-
-            StringBuffer newpath(path);
-            newpath.appendf(".%d",items);
-
-            const char* value = pRow->queryProp(NULL);
-
-            if (value)
-            {
-                if (*value)
-                    m_queryparams->setProp(newpath, value);
-            }
-            else
-            {
-                Owned<IPropertyTreeIterator> field = pRow->getElements("*");
-                int baseLen = newpath.length();
-                for (field->first(); field->isValid(); field->next())
-                {
-                    newpath.appendf(".%s", field->query().queryName());
-                    addRawXMLParameter(newpath, &field->query());
-                    newpath.setLength(baseLen);
-                }
-            }
-
-            items++;
-        }
-
-        if (items>0)
-        {
-            StringBuffer newpath(path),v;
-            newpath.append(".itemcount");
-            v.append(items);
-            m_queryparams->setProp(newpath, v);
-            m_paramCount++;
-        }
-    }
-    else
-    {
-        const char* value = tree->queryProp(NULL);
-
-        if (value)
-        {
-            if (*value)
-                m_queryparams->setProp(path, value);
-        }
-        else // subtree
-        {
-            Owned<IPropertyTreeIterator> field = tree->getElements("*");
-            for (field->first(); field->isValid(); field->next())
-            {
-                const char* fieldName = field->query().queryName();
-                StringBuffer newpath(path);
-                if (stricmp(fieldName, "RawArray")!=0)  
-                    newpath.appendf(".%s",field->query().queryName());
-                addRawXMLParameter(newpath, &field->query());
-            }
-        }
-
-    }
-}
-
-void CHttpMessage::addRawXMLParameter(const char* path, const char *value)
-{
-    Owned<IPropertyTree> tree;
-    try
-    {
-        tree.setown(createPTreeFromXMLString(value));
-    }
-    catch(IException* e)
-    {
-        StringBuffer msg;
-        e->errorMessage(msg);
-        ERRLOG("Error parsing struct array: %s", msg.str());
-        return;
-    }
-
-    addRawXMLParameter(path, tree);
-}
-*/
 
 void CHttpMessage::addParameter(const char* paramname, const char *value)
 {
@@ -1168,7 +1078,8 @@ bool CHttpMessage::isFormSubmission()
               CHttpRequest Implementation
 *******************************************************************************/
 
-CHttpRequest::CHttpRequest(ISocket& socket) : CHttpMessage(socket), m_pathIsParsed(false), m_sstype(sub_serv_unknown), m_MaxRequestEntityLength(0)
+CHttpRequest::CHttpRequest(ISocket& socket) : CHttpMessage(socket), m_pathIsParsed(false), 
+    m_sstype(sub_serv_unknown), m_MaxRequestEntityLength(0)
 {
 };
 
@@ -1431,6 +1342,16 @@ void CHttpRequest::parseCookieHeader(char* cookiestr)
     }
 }
 
+ESPSerializationFormat lookupResponseFormatByExtension(const char *ext)
+{
+    if (!ext || !*ext)
+        return ESPSerializationANY;
+    if (strieq(ext, ".xml"))
+        return ESPSerializationXML;
+    if (strieq(ext, ".json"))
+        return ESPSerializationJSON;
+    return ESPSerializationANY;
+}
 
 void CHttpRequest::parseEspPathInfo()
 {
@@ -1440,6 +1361,9 @@ void CHttpRequest::parseEspPathInfo()
         m_espMethodName.clear();
         m_espServiceName.clear();
 
+        if (queryParameters()->hasProp("rawxml_"))
+            m_context->setResponseFormat(ESPSerializationXML);
+
         size32_t pathlen=m_httpPath.length();
         if (!pathlen)
             m_sstype=(m_queryparams && m_queryparams->hasProp("main")) ? sub_serv_main : sub_serv_root;
@@ -1484,7 +1408,14 @@ void CHttpRequest::parseEspPathInfo()
                         }
                             
                         *thumb=0;
-                        m_espMethodName.append(thumb+1);
+                        m_espMethodName.append(++thumb);
+                        const char *tail = strrchr(thumb, '.');
+                        ESPSerializationFormat fmt = lookupResponseFormatByExtension(tail);
+                        if (fmt!=ESPSerializationANY)
+                        {
+                            m_context->setResponseFormat(fmt);
+                            m_espMethodName.setLength(tail-thumb);
+                        }
                     }
                     else 
                         missingTrailSlash = true; 
@@ -1738,7 +1669,6 @@ void CHttpRequest::updateContext()
         if(temp.length())
             m_context->setPeer(temp.str());
 
-        
         m_context->setRequestParameters(queryParameters());
 
         short servPort;

+ 6 - 3
esp/bindings/http/platform/httptransport.ipp

@@ -101,7 +101,6 @@ protected:
     StringArray  m_headers;
 
     Owned<IEspContext> m_context;
-
     IArrayOf<CEspCookie> m_cookies;
 
     Owned<CMimeMultiPart> m_multipart;
@@ -112,8 +111,6 @@ protected:
     int readContent();  
     int readContentTillSocketClosed();
     virtual void addParameter(const char* paramname, const char *value);
-//  void addRawXMLParameter(const char* paramname, const char *value);
-//  void addRawXMLParameter(const char* path, IPropertyTree* tree);
     virtual void addAttachment(const char* name, StringBuffer& value);
 
     virtual StringBuffer& constructHeaderBuffer(StringBuffer& headerbuf, bool inclLength);
@@ -318,6 +315,7 @@ private:
     sub_service     m_sstype;
     bool            m_authrequired;
     int             m_MaxRequestEntityLength;
+    ESPSerializationFormat respSerializationFormat;
 
     virtual int parseFirstLine(char* oneline);
     virtual StringBuffer& constructHeaderBuffer(StringBuffer& headerbuf, bool inclLen);
@@ -411,4 +409,9 @@ inline bool canRedirect(CHttpRequest &req)
     return !req.queryParameters()->hasProp("rawxml_");
 }
 
+inline bool skipXslt(IEspContext &context)
+{
+    return (context.getResponseFormat()!=ESPSerializationANY);  //for now
+}
+
 #endif

+ 6 - 0
esp/platform/espcontext.cpp

@@ -75,6 +75,8 @@ private:
     bool        m_hasException;
     int         m_exceptionCode;
 
+    ESPSerializationFormat respSerializationFormat;
+
 public:
     IMPLEMENT_IINTERFACE;
 
@@ -83,6 +85,7 @@ public:
         m_hasException =  false;
         m_creationTime = msTick();
         m_active=ActiveRequests::getCount();
+        respSerializationFormat=ESPSerializationANY;
     }
 
     ~CEspContext()
@@ -454,6 +457,9 @@ public:
 
         DBGLOG("TxSummary[%s]", logstr.str());
     }
+
+    virtual ESPSerializationFormat getResponseFormat(){return respSerializationFormat;}
+    virtual void setResponseFormat(ESPSerializationFormat fmt){respSerializationFormat = fmt;}
 };
 
 //---------------------------------------------------------

+ 1 - 0
esp/protocols/http/CMakeLists.txt

@@ -41,6 +41,7 @@ set (    SRCS
          ../../bindings/SOAP/Platform/soapbind.cpp 
          ../../bindings/SOAP/Platform/soapmessage.cpp 
          ../../bindings/SOAP/Platform/soapservice.cpp 
+         ../../bindings/SOAP/Platform/soapparam.cpp
          ../../platform/espcontext.cpp 
          ../../platform/espprotocol.cpp 
          ../../platform/espthread.cpp 

+ 8 - 53
esp/scm/esp.ecm

@@ -48,60 +48,12 @@ SCMinterface IHttpMessage (IInterface)
     StringBuffer& getContent(StringBuffer& buf);
 };
 
-/*
-XSCMinterface IEspContext(IInterface)
+typedef enum ESPSerializationFormat_
 {
-    void setUserID(const char* userid);
-    StringBuffer& getUserID(StringBuffer& userid);
-    const char *queryUserId();
-
-    void setPassword(const char* password);
-    StringBuffer& getPassword(StringBuffer& password);
-    const char *queryPassword();
-
-    void setRealm(const char* realm);
-    StringBuffer& getRealm(StringBuffer& realm);
-    const char *queryRealm();
-
-    void setUser(ISecUser* user);
-    ISecUser* queryUser();
-
-    void setResources(ISecResourceList* rlist);
-    ISecResourceList* queryResources();
-
-    void setSecManger(ISecManager* mgr);
-    ISecManager* querySecManager();
-
-    void setContextPath(const char *path);
-    const char * getContextPath();
-
-    void setBindingValue(void *value);
-    void * getBindingValue();
-
-    void setServiceValue(void *value);
-    void * getServiceValue();
-
-    void setToBeAuthenticated(bool val);
-    bool toBeAuthenticated();
-
-    void setPeer(const char* peer);
-    StringBuffer& getPeer(StringBuffer& peer);
-    void setFeatureAuthMap(IAuthMap* map);
-
-
-    IAuthMap* queryAuthMap();
-
-    bool authorizeFeature(const char* pszFeatureUrl, SecAccessFlags& access);
-    bool authorizeFeatures(StringArray& features, IEspStringIntMap& pmap);
-    
-
-    bool validateFeatureAccess(const char* pszFeatureUrl, unsigned required, bool throwExcpt);
-    void setServAddress(const char *host, short port);
-    void getServAddress(StringBuffer& host, short &port);
-    void AuditMessage(AuditType type, const char *filterType, const char *title, const char *parms);
-
-};
-*/
+    ESPSerializationANY,
+    ESPSerializationXML,
+    ESPSerializationJSON
+} ESPSerializationFormat;
 
 #define ESPCTX_NO_NAMESPACES    0x00000001
 #define ESPCTX_WSDL             0x00000010
@@ -196,6 +148,9 @@ interface IEspContext : extends IInterface
     virtual void addTraceSummaryValue(const char *name, int value)=0;
     virtual void addTraceSummaryTimeStamp(const char *name)=0;
     virtual void flushTraceSummary()=0;
+
+    virtual ESPSerializationFormat getResponseFormat()=0;
+    virtual void setResponseFormat(ESPSerializationFormat fmt)=0;
 };
 
 

+ 1 - 1
esp/services/WsDeploy/WsDeployEngine.cpp

@@ -136,7 +136,7 @@ m_version(1)
 
   StringBuffer xml;
   CDeployInfo& depInfo = dynamic_cast<CDeployInfo&>( deployInfo );
-  depInfo.serialize(ctx,xml);
+  depInfo.serializeStruct(ctx, xml);
 
   m_pResponseXml.setown( createPTreeFromXMLString(xml.str()) );
   m_pSelComps = m_pResponseXml->queryPropTree("Components");

+ 1 - 1
esp/services/WsDeploy/WsDeployService.cpp

@@ -5298,7 +5298,7 @@ bool CWsDeployFileInfo::deploy(IEspContext &context, IEspDeployRequest& req, IEs
   {
     resp.setStatus( "Please select at least one component to deploy!" );
     CDeployOptions& depOptions = dynamic_cast<CDeployOptions&>( depInfo.getOptions() );
-    depOptions.serialize(&context,deployResult, "Options");
+    depOptions.serializeStruct(&context,deployResult, "Options");
   }
   else
   {

+ 1 - 0
plugins/fileservices/CMakeLists.txt

@@ -69,6 +69,7 @@ target_link_libraries ( fileservices
          remote 
          dalibase 
          environment 
+         esphttp
          dllserver 
          nbcd 
          eclrtl  

+ 68 - 0
system/jlib/jstring.cpp

@@ -1793,6 +1793,74 @@ const char *decodeXML(const char *x, StringBuffer &ret, unsigned len, const char
     return x;
 }
 
+StringBuffer & appendXMLOpenTag(StringBuffer &xml, const char *tag, const char *prefix, bool complete, bool close, const char *uri)
+{
+    if (!tag || !*tag)
+        return xml;
+
+    xml.append('<');
+    appendXMLTagName(xml, tag, prefix);
+
+    if (uri && *uri)
+    {
+        xml.append(" xmlns");
+        if (prefix && *prefix)
+            xml.append(':').append(prefix);
+        xml.append("=\"").append(uri).append('\"');
+    }
+
+    if (complete)
+    {
+        if (close)
+            xml.append('/');
+        xml.append('>');
+    }
+    return xml;
+}
+
+jlib_decl StringBuffer &appendJSONName(StringBuffer &s, const char *name)
+{
+    if (!name || !*name)
+        return s;
+    if (s.length() && !strchr("{[:", s.charAt(s.length()-1)))
+        s.append(", ");
+    return encodeJSON(s.append('"'), name).append("\": ");
+}
+
+StringBuffer &encodeJSON(StringBuffer &s, const char *value)
+{
+    if (!value)
+        return s;
+    for (; *value; value++)
+    {
+        switch (*value)
+        {
+            case '\b':
+                s.append("\\b");
+                break;
+            case '\f':
+                s.append("\\f");
+                break;
+            case '\n':
+                s.append("\\n");
+                break;
+            case '\r':
+                s.append("\\r");
+                break;
+            case '\t':
+                s.append("\\t");
+                break;
+            case '\"':
+            case '\\':
+            case '/':
+                s.append('\\'); //fall through
+            default:
+                s.append(*value);
+        }
+    }
+    return s;
+}
+
 void decodeCppEscapeSequence(StringBuffer & out, const char * in, bool errorIfInvalid)
 {
     out.ensureCapacity((size32_t)strlen(in));

+ 64 - 12
system/jlib/jstring.hpp

@@ -346,6 +346,7 @@ public:
 #define ENCODE_SPACES 1
 #define ENCODE_NEWLINES 2
 #define ENCODE_WHITESPACE 3
+#define ENCODE_NONE 4
 
 interface IEntityHelper
 {
@@ -360,7 +361,7 @@ extern jlib_decl StringBuffer & appendStringAsSQL(StringBuffer & out, unsigned l
 extern jlib_decl StringBuffer & appendStringAsECL(StringBuffer & out, unsigned len, const char * src);
 extern jlib_decl StringBuffer & appendStringAsQuotedECL(StringBuffer &out, unsigned len, const char * src);
 
-extern jlib_decl void extractItem(StringBuffer & res, const char * src, const char * sep, int whichItem, bool caps);
+jlib_decl void extractItem(StringBuffer & res, const char * src, const char * sep, int whichItem, bool caps);
 extern jlib_decl const char *encodeXML(const char *x, StringBuffer &ret, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=false);
 extern jlib_decl const char *decodeXML(const char *x, StringBuffer &ret, unsigned len=(unsigned)-1, const char **errMark=NULL, IEntityHelper *entityHelper=NULL);
 extern jlib_decl const char *encodeXML(const char *x, IIOStream &out, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=false);
@@ -371,26 +372,77 @@ inline const char *encodeUtf8XML(const char *x, StringBuffer &ret, unsigned flag
     return encodeXML(x, ret, flags, len, true);
 }
 
-inline StringBuffer & appendXMLOpenTag(StringBuffer &xml, const char *tag)
+inline StringBuffer &appendXMLTagName(StringBuffer &xml, const char *tag, const char *prefix=NULL)
 {
-    if (tag && *tag)
-        xml.append('<').append(tag).append('>');
+    if (prefix && *prefix)
+        xml.append(prefix).append(':');
+    xml.append(tag);
     return xml;
 }
 
-inline StringBuffer & appendXMLCloseTag(StringBuffer &xml, const char *tag)
+extern jlib_decl StringBuffer & appendXMLOpenTag(StringBuffer &xml, const char *tag, const char *prefix=NULL, bool complete=true, bool close=false, const char *uri=NULL);
+
+inline StringBuffer & appendXMLCloseTag(StringBuffer &xml, const char *tag, const char *prefix=NULL)
 {
-    if (tag && *tag)
-        xml.append("</").append(tag).append('>');
-    return xml;
+    if (!tag || !*tag)
+        return xml;
+
+    xml.append("</");
+    return appendXMLTagName(xml, tag, prefix).append('>');
 }
 
-inline StringBuffer &appendXMLTag(StringBuffer &xml, const char *tag, const char *value, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=true)
+inline StringBuffer &appendXMLTag(StringBuffer &xml, const char *tag, const char *value, const char *prefix=NULL, unsigned flags=0, unsigned len=(unsigned)-1, bool utf8=true)
 {
-    appendXMLOpenTag(xml, tag);
+    appendXMLOpenTag(xml, tag, prefix);
     if (value && *value)
-        encodeXML(value, xml, flags, len, utf8);
-    return appendXMLCloseTag(xml, tag);
+    {
+        if (flags != ENCODE_NONE)
+            encodeXML(value, xml, flags, len, utf8);
+        else
+            xml.append(value);
+    }
+    return appendXMLCloseTag(xml, tag, prefix);
+}
+
+jlib_decl StringBuffer &encodeJSON(StringBuffer &s, const char *value);
+jlib_decl StringBuffer &appendJSONName(StringBuffer &s, const char *name);
+
+template <typename type>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, type value)
+{
+    appendJSONName(s, name);
+    return s.append(value);
+}
+
+//specialization
+template <>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, bool value)
+{
+    appendJSONName(s, name);
+    return s.append((value) ? "true" : "false");
+}
+
+template <>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, const char *value)
+{
+    appendJSONName(s, name);
+    if (!value)
+        return s.append("null");
+    return encodeJSON(s.append('"'), value).append('"');
+}
+
+template <>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, long value)
+{
+    appendJSONName(s, name);
+    return s.appendlong(value);
+}
+
+template <>
+inline StringBuffer &appendJSONValue(StringBuffer& s, const char *name, unsigned long value)
+{
+    appendJSONName(s, name);
+    s.appendulong(value);
 }
 
 extern jlib_decl void decodeCppEscapeSequence(StringBuffer & out, const char * in, bool errorIfInvalid);

+ 77 - 147
tools/hidl/hidlcomp.cpp

@@ -28,7 +28,6 @@
 #include <string>
 
 //-------------------------------------------------------------------------------------------------------------
-#define NEW_INSTANT_QUERY
 inline bool strieq(const char* s,const char* t) { return stricmp(s,t)==0; }
 
 //-------------------------------------------------------------------------------------------------------------
@@ -956,6 +955,18 @@ const char* ParamInfo::getArrayItemXsdType()
     }
 }
 
+const char* ParamInfo::getArrayItemTag()
+{
+    const char *item_tag = getMetaString("item_tag", NULL);
+    if (item_tag)
+        return item_tag;
+    if (!(flags & PF_TEMPLATE) || !streq(templ, "ESParray"))
+        return NULL;
+    if (isEspStringArray())
+        return "Item";
+    return typname;
+}
+
 void ParamInfo::write_esp_declaration()
 {
     char metatype[256];
@@ -1880,7 +1891,7 @@ bool ParamInfo::write_mapinfo_check(int indents, const char* ctxvar)
     return hasOutput;
 }
 
-void ParamInfo::write_esp_marshall(bool isRpc, const char * var, bool encodeXml, bool checkVer, int indents)
+void ParamInfo::write_esp_marshall(bool isRpc, bool encodeXml, bool checkVer, int indents)
 {
     const char *soap_path=getMetaString("soap_path", NULL);
     char *path = (soap_path!=NULL) ? strdup(soap_path) : NULL;
@@ -1890,7 +1901,7 @@ void ParamInfo::write_esp_marshall(bool isRpc, const char * var, bool encodeXml,
     {
         path[strlen(path)-1]=0;
         path++;
-        tagname=strrchr((char *)path, '/');
+        tagname=strrchr(path, '/');
         if (tagname)
         {
             *tagname=0;
@@ -1909,50 +1920,48 @@ void ParamInfo::write_esp_marshall(bool isRpc, const char * var, bool encodeXml,
             indents++;
     }
 
+    if (!isEspArrayOf() && getMetaInt("encode_newlines", -1)!=-1)
+    {
+        indent(indents);
+        outf("m_%s.setEncodeNewlines(true);\n", name);
+    }
+
     indent(indents);
+    if (isRpc)
+        outf("m_%s.marshall(rpc_resp, ", name);
+    else
+        outf("m_%s.toStr(ctx, buffer, ", name);
+
     if (isEspArrayOf())
     {
-        const char *item_tag = getMetaString("item_tag", (isEspStringArray()) ? "Item" : "");
         if (path)
-            outf("m_%s.marshall(%s%s, \"%s\", \"%s\", \"%s\");\n", name, isRpc?"":"ctx, ", var, tagname, item_tag, path);
+            outf("\"%s\", \"%s\", \"%s\");\n", tagname, getArrayItemTag(), path);
         else
-            outf("m_%s.marshall(%s%s, \"%s\", \"%s\");\n", name, isRpc?"":"ctx, ", var, getXmlTag(), item_tag);
+            outf("\"%s\", \"%s\");\n", getXmlTag(), getArrayItemTag());
     }
     else
     {
-        if(getMetaInt("encode_newlines", -1) != -1)
-        {
-            outf("m_%s.setEncodeNewlines(true);\n", name);
-            indent(indents);
-        }
-
-        const char *tail = (encodeXml)? "" : ",false";
+        const char *prefix = getMetaString("ns_var", "\"\"");
+        const char *encode = encodeXml ? "true" : "false";
         if (path)
         {
+            outf("\"%s\", \"%s\"", tagname, path);
             if (isRpc)
-                outf("m_%s.marshall(%s, \"%s\", \"%s\", \"\", %s);\n", name, var, tagname, path, getMetaString("ns_var", "\"\""));
-            else
-            {
-                if (kind==TK_ESPSTRUCT)
-                    outf("m_%s.marshall(ctx, %s, \"%s\", \"%s\");\n", name, var, tagname, path);
-                else
-                    outf("m_%s.marshall(ctx, %s, \"%s\", \"%s\", %s);\n", name, var, tagname, path, encodeXml ? "true":"false");
-            }
+                outf(", \"\", %s", prefix);
+            else if (kind!=TK_ESPSTRUCT)
+                outf(", %s", encode);
+            outs(");\n");
         }
-        else
+        else if (!getMetaInt("attribute"))
         {
-            if (!getMetaInt("attribute"))
-            {
-                if (isRpc)
-                    outf("m_%s.marshall(%s, \"%s\",\"\", \"\", %s);\n", name, var, getXmlTag(), getMetaString("ns_var", "\"\""));
-                else
-                {
-                    if (kind==TK_ESPSTRUCT)
-                        outf("m_%s.marshall(ctx, %s, \"%s\", \"\", \"\", false, %s);\n", name, var, getXmlTag(), getMetaString("ns_var", "\"\""));
-                    else
-                        outf("m_%s.marshall(ctx, %s, \"%s\",\"\", %s, \"\", %s);\n", name, var, getXmlTag(), encodeXml ? "true" : "false", getMetaString("ns_var", "\"\""));
-                }
-            }
+            outf("\"%s\", \"\", ", getXmlTag());
+            if (isRpc)
+                outf("\"\", ");
+            else if (kind==TK_ESPSTRUCT)
+                outf("\"\", false, ");
+            else
+                outf("%s, \"\", ", encode);
+            outf("%s);\n", prefix);
         }
     }
 }
@@ -3127,7 +3136,10 @@ void EspMessageInfo::write_esp_ipp()
         //IProperties constructor
         outf("\n\tC%s(IEspContext* ctx, const char *serviceName, IProperties *params, MapStrToBuf *attachments);", name_);
     }   
-    
+
+    outf("\n\tvirtual const char *getNsURI(){return %s;}\n", getMetaString("ns_uri", "NULL"));
+    outf("\n\tvirtual const char *getNsPrefix(){return %s;}\n", getMetaString("ns_var", "NULL"));
+    outs("\n\tvirtual const char *getRootName(){return m_msgName.str();}\n");
 
     outs("\n\tvoid setMsgName(const char *msgname)\n");
     outs("\t{\n");
@@ -3178,15 +3190,15 @@ void EspMessageInfo::write_esp_ipp()
     
     //method ==> serializeContent (StringBuffer&)
     outs("\n\tvoid serializeContent(IEspContext* ctx, StringBuffer& buffer, IProperties **pprops=NULL);\n");
+    outs("\n\tvoid serializeAttributes(IEspContext* ctx, StringBuffer& s);\n");
+    outs("\n\tvoid getAttributes(IProperties &attributes);\n");
 
     //method ==> serialize (StringBuffer&)
-    outs("\n\tvoid serialize(IEspContext* ctx, StringBuffer& buffer, const char *name=NULL);\n");
-    
-    //method ==> serialize (StringBuffer&)
     outf("\n\tstatic void serializer(IEspContext* ctx, IConst%s &ifrom, StringBuffer& buffer, bool keepRootTag=true);\n", name_);
     
     //method ==> serialize (MemoryBuffer&, StringBuffer &)
-    outs("\n\tvoid serialize(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer &mimetype);\n");
+    if (contentVar)
+        outs("\n\tvoid appendContent(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer &mimetype);\n");
     
     outs("\tvoid setEventSink(void * val){m_eventSink=val;}\n");
     outs("\tvoid * getEventSink(){return m_eventSink;}\n");
@@ -4229,7 +4241,7 @@ void EspMessageInfo::write_esp()
 
     for (pi=getParams();pi!=NULL;pi=pi->next)
     {
-        pi->write_esp_marshall(true,"rpc_resp", true, true, (espm_type_==espm_response)?2:1);
+        pi->write_esp_marshall(true, true, true, (espm_type_==espm_response)?2:1);
     }
     
     if (espm_type_==espm_response)
@@ -4263,7 +4275,15 @@ void EspMessageInfo::write_esp()
         outf("\tset_tag_value(ifrom.get_tag_value());\n");
     outs("}\n\n");
     
-    
+    //method ==> getAttributes (IProperties &attributes)
+    outf("\nvoid C%s::getAttributes(IProperties &attributes)\n{\n", name_);
+    for (pi=getParams(); pi!=NULL; pi=pi->next)
+    {
+        if (pi->getMetaInt("attribute"))
+            outf(2, "attributes.setProp(\"%s\", m_%s.getValue());\n", pi->getXmlTag(), pi->name);
+    }
+    outs("}\n\n");
+
     //method ==> serializeContent (StringBuffer&)
     outf("\nvoid C%s::serializeContent(IEspContext* ctx, StringBuffer& buffer, IProperties **pprops)\n{\n", name_);
     int http_encode = getMetaInt("http_encode", -1);
@@ -4286,7 +4306,7 @@ void EspMessageInfo::write_esp()
         for (pi=getParams();pi!=NULL;pi=pi->next)
         {
             if (!pi->getMetaInt("attribute"))
-                pi->write_esp_marshall(false,"buffer", encodeXML,true,2);
+                pi->write_esp_marshall(false, encodeXML, true, 2);
         }
         outs("\t}\n");
     }
@@ -4324,7 +4344,7 @@ void EspMessageInfo::write_esp()
         for (pi=getParams();pi!=NULL;pi=pi->next)
         {
             if (!pi->getMetaInt("attribute"))
-                pi->write_esp_marshall(false,"buffer", encodeXML, true);
+                pi->write_esp_marshall(false, encodeXML, true);
         }
 
         if (getMetaInt("element")!=0) 
@@ -4338,50 +4358,23 @@ void EspMessageInfo::write_esp()
     }
         
     outs("}\n\n");
-    
-    //method ==> serialize (StringBuffer&)
-    outf("\nvoid C%s::serialize(IEspContext* ctx, StringBuffer& buffer, const char *name)\n{\n", name_);
-
-    outs(1, "const char *tname = (name && *name) ? name : m_msgName.str();\n");
 
-    StrBuffer nsvar;
-    getMetaStringValue(nsvar, "ns_var");
-    const char *nuri=getMetaString("ns_uri", NULL);
-
-    outs(1, "buffer.append(\"<\");\n");
-    if (nsvar.length())
-        outf(1, "buffer.append(\"%s\").append(':');\n", nsvar.str());
-    outs(1, "buffer.appendf(\"%s\", tname);\n");
-
-    if (nuri)
-    {
-        outs(1, "buffer.append(\" xmlns\");\n");
-        if (nsvar.length())
-            outf(1, "buffer.append(':').append(\"%s\");\n", nsvar.str());
-        outf(1, "buffer.append(\"=\\\"\").append(%s).append('\\\"');\n", nuri);
-    }
+    //method ==> serialize (StringBuffer&)
+    outf("\nvoid C%s::serializeAttributes(IEspContext* ctx, StringBuffer& s)\n{\n", name_);
 
     for (pi=getParams();pi!=NULL;pi=pi->next)
     {
         if (pi->getMetaInt("attribute"))
         {
             outf(1, "if (!m_%s.is_nil()) {\n", pi->name);
-            outf(2, "StringBuffer encoded;\n");
-            outf(2, "encodeXML(m_%s.getValue(), encoded);\n", pi->name);
-            outf(2, "buffer.appendf(\" %s=\\\"%%s\\\"\", encoded.str());\n", pi->getXmlTag());
+            outf(2, "StringBuffer enc;\n");
+            outf(2, "encodeXML(m_%s.getValue(), enc);\n", pi->name);
+            outf(2, "s.appendf(\" %s=\\\"%%s\\\"\", enc.str());\n", pi->getXmlTag());
             outf(1, "}\n");
         }
     }
-    outs(1, "buffer.append(\">\");\n");
-
-    
-    outs(1, "serializeContent(ctx,buffer);\n");
-    outs(1, "buffer.append(\"</\");\n");
-    if (nsvar.length())
-        outf(1, "buffer.append(\"%s\").append(':');\n", nsvar.str());
-    outs(1, "buffer.appendf(\"%s>\", tname);\n");
     outs("}\n");
-    
+
     //method ==> serializer(IEspContext* ctx, ..., StringBuffer&, ...)
     outf("\nvoid C%s::serializer(IEspContext* ctx, IConst%s &src, StringBuffer& buffer, bool keepRootTag)\n{\n", name_, name_);
 
@@ -4863,9 +4856,9 @@ void EspMessageInfo::write_esp()
 
     //=============================================================================================================
     //method ==> serialize (MemoryBuffer&, StringBuffer &)
-    outf("\nvoid C%s::serialize(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer &mimetype)\n{\n", name_);
     if (contentVar)
     {
+        outf("\nvoid C%s::appendContent(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer &mimetype)\n{\n", name_);
         esp_xlate_info *xinfo = esp_xlat(contentVar);
         
         if (strcmp(xinfo->store_type, "StringBuffer")!=0)
@@ -4874,17 +4867,9 @@ void EspMessageInfo::write_esp()
             outf("\tbuffer.clear().append(m_%s.getValue().length(), m_%s.getValue().str());\n", contentVar->name, contentVar->name);
         
         outf("\tmimetype.set(m_%s_mimetype.str());\n", contentVar->name);
+        outs("}\n");
     }
-    else
-    {
-        outs("\tStringBuffer strbuffer;\n");
-        outf("\tstrbuffer.append(\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?>\");\n");
-        outf("\tserialize(ctx,strbuffer);\n");
-        outs("\tbuffer.append(strbuffer.length(), strbuffer.str());\n");
-        outs("\tmimetype.set(\"text/xml; charset=UTF-8\");\n");
-    }
-    outs("}\n");
-    
+
     //=============================================================================================================
     //method: unserialize(IRcpMessage...)
     outf("\nbool C%s::unserialize(IRpcMessage& rpc_request, const char *tagname, const char *basepath)\n{\n", name_);
@@ -5945,12 +5930,10 @@ void EspServInfo::write_esp_binding()
     outs("\telse\n");
     outs("\t{\n");
 
-#ifdef NEW_INSTANT_QUERY
     outf("\t\tOwned<CSoapResponseBinding> esp_response;\n");
     outf("\t\tStringBuffer source;\n");
     outf("\t\tIEspContext& context = *request->queryContext();\n");
-#endif
-                
+
     for (mthi=methods;mthi!=NULL;mthi=mthi->next)
     {
         bool bClientXslt=false;
@@ -5969,8 +5952,6 @@ void EspServInfo::write_esp_binding()
         
         if (respXsl==NULL)
         {
-#ifdef NEW_INSTANT_QUERY
-            //  reduce the code size significantly
             outf("\t\tif(!stricmp(method, \"%s\")||!stricmp(method, \"%s\"))\n", mthi->getName(), mthi->getReq());
             outs("\t\t{\n");
             
@@ -5998,54 +5979,6 @@ void EspServInfo::write_esp_binding()
                 outf("\t\t\tiserv->on%s(*request->queryContext(), *esp_request.get(), *resp);\n", mthi->getName());
             
             outs("\t\t}\n");
-#else
-            outf("\t\tif(!stricmp(method, \"%s\")||!stricmp(method, \"%s\"))\n", mthi->getName(), mthi->getReq());
-            outs("\t\t{\n");
-            
-            outs("\t\t\tMemoryBuffer content;\n");
-            outs("\t\t\tStringBuffer mimetype;\n");
-            
-            outf("\t\t\tOwned<C%s> esp_request = new C%s(&context, \"%s\", request->queryParameters(), request->queryAttachments());\n", mthi->getReq(), mthi->getReq(), name_);
-            outf("\t\t\tOwned<C%s> esp_response = new C%s(&context, \"%s\");\n", mthi->getResp(), mthi->getResp(), name_);
-            
-            if (bHandleExceptions)
-            {
-                outs("\t\t\tStringBuffer source;\n");
-                outf("\t\t\tsource.appendf(\"%s::%%s()\", method);\n", name_);
-                outf("\t\t\tOwned<IMultiException> me = MakeMultiException(source.str());\n");
-                
-                //begin try block
-                outs("\t\t\ttry\n");
-                outs("\t\t\t{\n");
-                outf("\t\t\t\tiserv->on%s(*request->queryContext(), *esp_request.get(), *esp_response.get());\n", mthi->getName());
-                outs("\t\t\t}\n");
-                
-                write_catch_blocks(mthi, ct_httpresp, 3);
-            }
-            else
-                outf("\t\t\tiserv->on%s(*request->queryContext(), *esp_request.get(), *esp_response.get());\n", mthi->getName());
-            
-            outs("\t\t\tif (esp_response->getRedirectUrl() && *esp_response->getRedirectUrl())\n");
-            outs("\t\t\t{\n");
-            outs("\t\t\t\tresponse->redirect(*request, esp_response->getRedirectUrl());\n");
-            outs("\t\t\t}\n");
-            outs("\t\t\telse\n");
-            outs("\t\t\t{\n");
-            
-            outs("\t\t\t\tStringBuffer resultsHtml;\n");
-            outs("\t\t\t\tStringBuffer htmlPage;\n");
-            
-            outs("\t\t\t\tIProperties *props=request->queryParameters();\n");
-            outs("\t\t\t\tesp_response->serialize(context, content, mimetype);\n");
-            outs("\t\t\t\onBeforeSendResponse(context,request,content,service,method);\n");
-            outs("\t\t\t\tresponse->setContent(content.length(), content.toByteArray());\n");
-            outs("\t\t\t\tresponse->setContentType(mimetype.str());\n");
-            
-            outs("\t\t\t\tresponse->send();\n");
-            outs("\t\t\t}\n");
-            outs("\t\t\treturn 0;\n");
-            outs("\t\t}\n");
-#endif
         }
         else
         {
@@ -6084,11 +6017,11 @@ void EspServInfo::write_esp_binding()
             outs("\t\t\t{\n");
             
             outs("\t\t\t\tIProperties *props=request->queryParameters();\n");
-            outs("\t\t\t\tif (props && props->queryProp(\"rawxml_\")!=NULL)\n");
+            outs("\t\t\t\tif (skipXslt(context))\n");
             outs("\t\t\t\t{\n");
             outs("\t\t\t\t\tMemoryBuffer content;\n");
             outs("\t\t\t\t\tStringBuffer mimetype;\n");
-            outs("\t\t\t\t\tesp_response->serialize(&context,content, mimetype);\n");
+            outs("\t\t\t\t\tesp_response->appendContent(&context,content, mimetype);\n");
             outs("\t\t\t\t\tonBeforeSendResponse(context,request,content,service,method);\n");
             outs("\t\t\t\t\tresponse->setContent(content.length(), content.toByteArray());\n");
             outs("\t\t\t\t\tresponse->setContentType(mimetype.str());\n");
@@ -6103,7 +6036,7 @@ void EspServInfo::write_esp_binding()
                 outs("\t\t\t\t\tif (request->supportClientXslt())\n");
                 outf("\t\t\t\t\t\txml.appendf(\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?><?xml-stylesheet type=\\\"text/xsl\\\" href=\\\"%%s\\\"?>\", %s);\n", respXsl);
             }
-            outs("\t\t\t\t\tesp_response->serialize(&context,xml);\n\n");
+            outs("\t\t\t\t\tesp_response->serializeStruct(&context, xml, NULL);\n\n");
             if (bClientXslt)
             {
                 
@@ -6138,7 +6071,6 @@ void EspServInfo::write_esp_binding()
         }
     }
 
-#ifdef NEW_INSTANT_QUERY
     outs("\n");
     indentReset(2);
     indentOuts("if (esp_response.get())\n");
@@ -6150,7 +6082,7 @@ void EspServInfo::write_esp_binding()
     
     indentOuts(1,"MemoryBuffer content;\n");
     indentOuts("StringBuffer mimetype;\n");
-    indentOuts("esp_response->serialize(&context,content, mimetype);\n");
+    indentOuts("esp_response->appendContent(&context,content, mimetype);\n");
     indentOuts("onBeforeSendResponse(context,request,content,service,method);\n");
     indentOuts("response->setContent(content.length(), content.toByteArray());\n");
     indentOuts("response->setContentType(mimetype.str());\n");
@@ -6159,8 +6091,6 @@ void EspServInfo::write_esp_binding()
     indentOuts(-1,"}\n");
     indentOuts("return 0;\n");
     indentOuts(-1,"}\n");
-#endif
-    
     outs("\t}\n");
     
     outs("\treturn onGetNotFound(context, request,  response, service);\n");

+ 2 - 2
tools/hidl/hidlcomp.h

@@ -443,7 +443,7 @@ public:
     void write_esp_declaration();
     void write_esp_ng_declaration(int pos);
     void write_esp_init(bool &isFirst, bool removeNil);
-    void write_esp_marshall(bool isRpc, const char *var, bool encodeXml, bool checkVer=false, int indent=1);
+    void write_esp_marshall(bool isRpc, bool encodeXml, bool checkVer=false, int indent=1);
     void write_esp_unmarshall(const char *rpcvar, bool useBasePath=false, int indents=1);
     void write_esp_unmarshall_properties(const char *propvar, const char *attachvar, int indents=1);
     void write_esp_unmarshall_soapval(const char *var, int indents=1);
@@ -485,8 +485,8 @@ public:
         return kind;
     }
 
+    const char* getArrayItemTag();
     const char* getArrayItemXsdType();
-
     const char* getArrayImplType();
 
     bool hasNameTag(){return (typname && !stricmp(typname, "EspTextFile"));}