Explorar o código

Merge pull request #2895 from afishbeck/json_esp_response

Add ESP support for Json formatted response

Reviewed-by: Gavin Halliday <ghalliday@hpccsystems.com>
Gavin Halliday %!s(int64=13) %!d(string=hai) anos
pai
achega
8378ce61c5

+ 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){}  
 };
 
 

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

@@ -0,0 +1,661 @@
+/*##############################################################################
+
+    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)
+{
+    delimitJSON(s);
+    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)
+        {
+            delimitJSON(s);
+            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;
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 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  

+ 67 - 0
system/jlib/jstring.cpp

@@ -1793,6 +1793,73 @@ 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;
+    delimitJSON(s);
+    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));

+ 71 - 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,84 @@ 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);
+}
+
+inline StringBuffer &delimitJSON(StringBuffer &s)
+{
+    if (s.length() && !strchr("{[:", s.charAt(s.length()-1)))
+        s.append(", ");
+    return s;
+}
+
+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"));}