TypeMap;
TypeMap typesNeeded;
bool parenthesisOpened = false;
if (parent)
{
outs("\tif (!(flags & 0x10) || (flags & 0x100))\n");
outs("\t{\n");
parenthesisOpened = true;
outf("\t\tC%s::getXsdDefinition(context, request, schema, added, xns, wsns, 0x110);\n", parent);
typesNeeded[parent] = false;
}
for (pi=getParams();pi!=NULL;pi=pi->next)
{
// we still need to make it usable for the service writer
//if (pi->getMetaInt("hidden", 0) || pi->getMetaInt("hidden_soap", 0))
// continue;
std::string thisType;
const char *xsd_type=pi->getMetaXsdType();
if (xsd_type)
{
char* buf = strdup(xsd_type[0]=='"' ? xsd_type+1 : xsd_type);
size_t count= strlen(buf);
if (count>0 && buf[count-1]=='\"')
buf[count-1]=0;
char* typeName = getToBeDefinedType(buf);
if (typeName)
{
thisType = typeName;
free(typeName);
}
free(buf);
}
else if (pi->kind==TK_ESPSTRUCT || pi->kind==TK_ESPENUM)
{
if (pi->typname)
thisType = pi->typname;
else
outs("\t\t*** pi->typname is empty!!\n");
}
else if (pi->flags & PF_TEMPLATE)
{
if (strcmp(pi->templ, "ESParray")==0)
{
if (pi->typname && strcmp(pi->typname, "string")!=0 && strcmp(pi->typname, "EspTextFile")!=0)
thisType = pi->typname;
}
else
outf("\t\t// *** skip field: name=%s, type=%s\n", pi->name, pi->typname);
}
if (thisType.length() && strcmp(thisType.c_str(),name_)!=0)
{
TypeMap::const_iterator it = typesNeeded.find(thisType);
if (it==typesNeeded.end() || (*it).second & MIT_HasMap) // thisType is not in typesNeeded or it is there with version info
{
if (!parenthesisOpened)
{
outs("\tif (!(flags & 0x10) || (flags & 0x100))\n\t{\n");
parenthesisOpened = true;
}
if (pi->hasMapInfo())
{
outf("\t\tif (!context.suppressed(\"%s\",\"%s\"))\n\t", this->name_, pi->name);
typesNeeded[thisType] = (pi->kind==TK_ESPENUM) ? MIT_EnumTrue : MIT_StructTrue;
}
else
typesNeeded[thisType] = (pi->kind==TK_ESPENUM) ? MIT_EnumFalse : MIT_StructFalse;
if (pi->kind == TK_ESPENUM)
outf("\t\tCX%s::getXsdDefinition(context, request, schema, added);\n", thisType.c_str());
else
outf("\t\tC%s::getXsdDefinition(context, request, schema, added);\n", thisType.c_str());
}
}
}
if (parenthesisOpened)
outs("\t}\n");
// native arrays
for (EspNativeArrays::const_iterator it = nativeArrays.begin(); it!=nativeArrays.end(); it++)
{
outf("\tif (added.getValue(\"%s\")==NULL) {\n", (*it).second.c_str());
outf("\t\taddEspNativeArray(schema,\"%s\",\"%s\");\n", (*it).first.c_str(), (*it).second.c_str());
outf("\t\tadded.setValue(\"%s\",1);\n", (*it).second.c_str());
outf("\t}\n");
}
// struct arrays
for (EspStructArrays::const_iterator it2 = structArrays.begin(); it2!=structArrays.end(); it2++)
{
const char* type = (*it2).c_str();
outf("\tif (added.getValue(\"%s\") && added.getValue(\"ArrayOf%s\")==NULL) {\n", type, type);
outf("\t\tschema.append(\"\\n\");\n",type);
outf("\t\tschema.append(\"\\n\");\n");
outf("\t\tschema.append(\"\\n\");\n", type, type);
outf("\t\tschema.append(\" \\n\");\n");
outf("\t\tschema.append(\" \\n\");\n");
outf("\t\tadded.setValue(\"ArrayOf%s\",1);\n", type);
outf("\t}\n");
}
/*
//typesNeeded.erase(name_); // Do not include self: avoid recursive call
if (typesNeeded.size()>0)
{
outs("\tif (!(flags & 0x10))\n");
outs("\t{\n");
for (TypeMap::const_iterator it = typesNeeded.begin(); it!=typesNeeded.end(); ++it)
{
const char* type = (*it).first.c_str();
const char* fld = (*it).second.c_str();
if (fld[0] != 0)
{
outf("\t\tif (!context.suppressed(\"%s\",\"%s\"))\n\t", this->name_, fld);
outf("\t\t\tC%s::getXsdDefinition(context, request, schema, added);\n", type);
}
else
outf("\t\tC%s::getXsdDefinition(context, request, schema, added);\n", type);
}
outs("\t}\n");
}
*/
outs("\treturn schema;\n");
outs("}\n");
//=======================================================================================
//method ==> getMapInfo
outf("\nvoid C%s::getMapInfo(IMapInfo& info) { BoolHash added; getMapInfo(info, added); }\n",name_);
outf("\nvoid C%s::getMapInfo(IMapInfo& info, BoolHash& added)\n",name_);
outf("{\n");
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (pi->hasMapInfo())
{
StrBuffer ver;
bool hasVer = pi->getMetaVerInfo("min_ver",ver);
if (hasVer)
outf("\tinfo.addMinVersion(\"%s\",\"%s\",%s);\n", name_, pi->name, ver.str());
hasVer = pi->getMetaVerInfo("depr_ver",ver.clear());
if (hasVer)
outf("\tinfo.addDeprVersion(\"%s\",\"%s\",%s);\n", name_, pi->name, ver.str());
hasVer = pi->getMetaVerInfo("max_ver",ver.clear());
if (hasVer)
outf("\tinfo.addMaxVersion(\"%s\",\"%s\",%s);\n", name_, pi->name, ver.str());
const char* opt = pi->getMetaString("optional", NULL);
if (opt)
{
const char* quote = (*opt=='"' || *opt=='\'') ? "" : "\"";
outf("\tinfo.addOptional(\"%s\",\"%s\",%s%s%s);\n", name_, pi->name,quote,opt,quote);
}
}
}
if (typesNeeded.size()>0)
{
for (TypeMap::const_iterator it = typesNeeded.begin(); it!=typesNeeded.end(); ++it)
{
outf("\tif (!added.getValue(\"%s\"))\n", (*it).first.c_str());
outf("\t{\n");
outf("\t\tadded.setValue(\"%s\",1);\n", (*it).first.c_str());
outf("\t\tC%s%s::getMapInfo(info,added);\n",((*it).second & MIT_IsEnum)?"X":"",(*it).first.c_str());
outf("\t}\n");
}
}
outs("}\n");
//=======================================================================================
//method ==> getHtmlForm
//TODO: move includeFormTag into onGetForm() to reduce significant generated code
indentReset();
indentOutf("\nStringBuffer &C%s::getHtmlForm(IEspContext &context, CHttpRequest* request, const char *serv, const char *method, StringBuffer &form, bool includeFormTag, const char *prefix)\n", name_);
indentOuts("{\n");
indentOuts(1,"IProperties *props = request->queryParameters();\n");
bool hasAttachment=false;
for (pi=getParams();pi;pi=pi->next)
{
if (pi->typname && !stricmp("EspTextFile", pi->typname))
hasAttachment=true;
}
indentOuts("if (includeFormTag) {\n");
indentOutf(1,"StringBuffer params, versionTag;\n");
indentOuts("bool hasVersion = getUrlParams(props,params);\n");
indentOuts("if (!hasVersion) versionTag.appendf(\"%cver_=%g\",params.length()?'&':'?',context.getClientVersion());\n");
indentOutf("form.appendf(\"\\n\");\n");
indentOuts(-1,"return form;\n");
indentOuts(-1,"}\n");
//method ==> serializeHtml
outf("\nStringBuffer &C%s::serializeHtml(IEspContext &context, const char *serv, const char *method, StringBuffer &html)\n", name_);
outs("{\n");
if (getMetaInt("serialize_html"))
{
outs("\thtml.append(\"\");\n");
if (contentVar)
{
if (!(contentVar->flags & PF_TEMPLATE))
{
if (contentVar->typname!=NULL && strcmp(contentVar->typname, "EspResultSet")==0)
{
outf("\thtml.appendf(\"%s: \");\n", contentVar->name);
outf("\tEspHttpBinding::formatHtmlResultSet(context, serv, method, m_%s->str(), html);", contentVar->name);
}
else if (contentVar->typname==NULL || strcmp(contentVar->typname, "binary")!=0)
{
outf("\thtml.appendf(\"%s: \");\n", contentVar->name, contentVar->name, contentVar->name);
}
}
}
else
{
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (!(pi->flags & PF_TEMPLATE) && (pi->kind!=TK_ESPSTRUCT))
{
if (pi->typname!=NULL && strcmp(pi->typname, "EspResultSet")==0)
{
outf("\thtml.appendf(\"%s: \");\n", pi->name);
outf("\tEspHttpBinding::formatHtmlResultSet(context, serv, method, m_%s->str(), html);", pi->name);
}
else if (pi->typname==NULL || strcmp(pi->typname, "binary")!=0)
{
outf("\thtml.appendf(\"%s: \");\n", pi->name, pi->name, pi->name);
}
}
}
}
outs("\thtml.append(\"
\");\n");
}
outs("\treturn html;\n");
outs("}\n");
//method ==> serialize (IRpcMessage&)
outf("\nvoid C%s::serialize(IRpcMessage& rpc_resp)\n{\n", name_);
if (parent)
outf("\tC%s::serialize(rpc_resp);\n", parent);
// versioning
if (hasMapInfo())
{
outf("\tIEspContext* ctx = rpc_resp.queryContext();\n");
outf("\tdouble clientVer= ctx ? ctx->getClientVersion() : -1; /* no context gets everything */\n");
}
outf("\trpc_resp.set_ns(%s);\n", getMetaString("ns_var", "\"\""));
outs("\trpc_resp.set_name(m_msgName.str());\n");
const char *nsuri = getMetaString("ns_uri", NULL);
if (nsuri)
outf("\trpc_resp.set_nsuri(%s);\n\n", nsuri);
else
{
outs("\tStringBuffer nsuri;\n");
outs("\tnsuri.append(\"urn:hpccsystems:ws:\").appendLower(m_serviceName.length(), m_serviceName.str());\n");
outs("\trpc_resp.set_nsuri(nsuri.str());\n\n");
}
int soap_encode = getMetaInt("soap_encode", -1);
if (soap_encode ==-1)
soap_encode = getMetaInt("encode", 1);
if (soap_encode==0)
outs("\trpc_resp.setEncodeXml(false);\n");
if (espm_type_==espm_response)
{
outs(
"\tconst IMultiException& exceptions = getExceptions();\n"
"\tif (exceptions.ordinality() > 0)\n"
"\t{\n"
"\t\tStringBuffer xml;\n"
"\t\texceptions.serialize(xml, 0, true, false);\n"
"\t\trpc_resp.add_value(\"\", \"\", \"Exceptions\", \"\", xml.str(), false);\n"
"\t}\n"
"\telse\n"
"\t{\n");
}
//attributes first
int attrCount=0;
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (pi->getMetaInt("attribute"))
{
attrCount++;
if (attrCount==1)
outs(1, "Owned props=createProperties();\n");
outf(1, "if (!m_%s.is_nil())\n", pi->name);
outf(2, "props->setProp(\"%s\", m_%s.getValue());\n", pi->getXmlTag(), pi->name);
}
}
if (attrCount!=0)
outs(1, "rpc_resp.add_attr(NULL, NULL, NULL, *props.get());\n");
for (pi=getParams();pi!=NULL;pi=pi->next)
{
pi->write_esp_marshall(true,"rpc_resp", true, true, (espm_type_==espm_response)?2:1);
}
if (espm_type_==espm_response)
outs("\t}\n");
outs("}\n\n");
//method ==> copy
outf("\nvoid C%s::copy(C%s &from)\n{\n", name_, name_);
if (parent)
outf("\tC%s::copy(*dynamic_cast(&from));\n", parent, parent);
for (pi=getParams();pi!=NULL;pi=pi->next)
outf("\tm_%s.copy(from.m_%s);\n", pi->name, pi->name);
if (getMetaInt("element"))
outf("\tset_tag_value(from.get_tag_value());\n");
outs("}\n\n");
//method ==> copy from interface
outf("\nvoid C%s::copy(IConst%s &ifrom)\n{\n", name_, name_);
if (parent)
outf("\tC%s::copy(*dynamic_cast(&ifrom));\n", parent, parent);
for (pi=getParams();pi!=NULL;pi=pi->next)
{
char *uname=strdup(pi->name);
*uname=upperchar(*uname);
outf("\tset%s(ifrom.get%s());\n", uname, uname);
free(uname);
}
if (getMetaInt("element"))
outf("\tset_tag_value(ifrom.get_tag_value());\n");
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);
if (http_encode ==-1)
http_encode = getMetaInt("encode", 1);
bool encodeXML = http_encode==1;
if (espm_type_==espm_response)
{
outs(
"\tconst IMultiException& exceptions = getExceptions();\n"
"\tif (exceptions.ordinality() > 0)\n"
"\t\texceptions.serialize(buffer, 0, true);\n"
"\telse\n"
"\t{\n");
if (parent)
outf("\t\tC%s::serializeContent(ctx,buffer);\n", parent);
if (hasMapInfo())
outf("\t\tdouble clientVer = ctx ? ctx->getClientVersion() : -1;\n");
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (!pi->getMetaInt("attribute"))
pi->write_esp_marshall(false,"buffer", encodeXML,true,2);
}
outs("\t}\n");
}
else
{
if (parent)
outf("\tC%s::serializeContent(ctx,buffer);\n", parent);
if (hasMapInfo())
outf("\tdouble clientVer = ctx ? ctx->getClientVersion() : -1;\n");
//attributes first
int attrCount=0;
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (pi->getMetaInt("attribute"))
{
attrCount++;
if (attrCount==1)
{
outs(1, "if (pprops)\n");
outs(1, "{\n");
outs(2, "*pprops=NULL;\n");
}
outf(2, "if (!m_%s.is_nil())\n", pi->name);
outs(2, "{\n");
outs(3, "if (!*pprops)\n");
outs(4, "*pprops=createProperties();\n");
outf(3, "(*pprops)->setProp(\"%s\", m_%s.getValue());\n", pi->getXmlTag(), pi->name);
outs(2, "}\n");
}
}
if (attrCount!=0)
outs(1, "}\n");
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (!pi->getMetaInt("attribute"))
pi->write_esp_marshall(false,"buffer", encodeXML, true);
}
if (getMetaInt("element")!=0)
{
outs(1, "if (m_tag_value.length()) {\n");
outs(2, "StringBuffer encoded;\n");
outs(2, "encodeXML(m_tag_value, encoded);\n");
outs(2, "buffer.append(encoded);\n");
outs(1, "}\n");
}
}
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);
}
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(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_);
// attributes
int nAttrs = 0;
for (pi=getParams();pi!=NULL;pi=pi->next)
if (pi->getMetaInt("attribute"))
nAttrs++;
if (nAttrs)
{
outf(1,"if (keepRootTag)\n\t{\n");
outf(2,"buffer.append(\"<%s\");\n", name_);
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (pi->getMetaInt("attribute"))
{
char* fname = getFieldName(pi->name);
outf(2, "%sattr = src.get%s();\n", (pi==getParams())?"const char* ":"", fname);
free(fname);
outf(2, "if (attr && *attr) {\n");
outf(3, "StringBuffer encoded;\n");
outf(3, "encodeXML(attr,encoded);\n");
outf(3, "buffer.appendf(\" %s=\\\"%%s\\\"\",encoded.str());\n", pi->getXmlTag());
outf(2, "}\n");
}
}
outf(2,"buffer.append(\">\");\n");
outf(1,"}\n");
}
else
outf(1,"if (keepRootTag)\n\tbuffer.append(\"<%s>\");\n", name_);
if (parent)
{
outf("\tC%s::serializer(ctx,dynamic_cast(src),buffer,false);\n",parent,parent);
}
// -- versioning
if (hasMapInfo())
{
outf("\tdouble clientVer = ctx ? ctx->getClientVersion() : -1;\n");
}
#if 1
// not respecting nil_remove: backward compatible
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (pi->getMetaInt("attribute"))
continue;
outf("\t// field %s\n", pi->name);
char *uname=getFieldName(pi->name);
bool hasIf = false;
if (pi->hasMapInfo())
hasIf = pi->write_mapinfo_check(1,"ctx");
//if (hasIf) outs("\t{\n");
const char* ifIndent = hasIf?"\t":"";
if (pi->flags & PF_TEMPLATE) // array
{
outf("\t{\n");
if (pi->isPrimitiveArray())
{
const char *item_tag = pi->getMetaString("item_tag", "Item");
const char *type = pi->getArrayImplType();
outf("\t\t%s& v = src.get%s();\n",type,uname);
outf("\t\tif (v.length()>0)\n");
outf("\t\t\tbuffer.append(\"<%s>\");\n", pi->getXmlTag());
outf("\t\tfor (size32_t i=0;ikind)
{
case TK_BOOL:
case TK_SHORT:
case TK_INT: fmt = "d"; break;
case TK_UNSIGNED: fmt = "u"; break;
case TK_LONG: fmt = "ld"; break;
case TK_UNSIGNEDLONG: fmt = "lu"; break;
case TK_FLOAT:
case TK_DOUBLE: fmt = "g"; break;
case TK_null:
case TK_CHAR: fmt = "s"; break;
default:
{
char buf[128];
sprintf(buf,"Unhandled array type: %s (%s)", getTypeKindName(pi->kind), name_);
yyerror(buf);
}
}
outf("\t\t\tbuffer.appendf(\"<%s>%%%s%s>\",v.item(i));\n",item_tag,fmt,item_tag);
outf("\t\tif (v.length()>0)\n");
outf("\t\t\tbuffer.append(\"%s>\");\n", pi->getXmlTag());
}
else if (pi->typname)
{
if (pi->kind == TK_ESPENUM)
{
outf("\t\t%sArray& v = src.get%s();\n",pi->typname,uname);
outf("\t\tint size = v.length();\n");
const char *item_tag = pi->getMetaString("item_tag", "Item");
outf("\t\tif (size>0)\n");
outf("\t\t\tbuffer.append(\"<%s>\");\n", pi->getXmlTag());
outf("\t\tfor (int i=0;i%%s%s>\", CX%s::stringOf(v.item(i)));\n",item_tag, item_tag, pi->typname);
//outf("\t\t\tC%s::serializer(ctx,v.item(i),buffer,false);\n",pi->typname);
//outf("\t\t\tbuffer.append(\"%s>\");\n",item_tag);
//outf("\t\t}\n");
outf("\t\tif (size>0)\n");
outf("\t\t\tbuffer.append(\"%s>\");\n", pi->getXmlTag());
}
else if (pi->kind == TK_ESPSTRUCT || pi->kind == TK_null) // should be fixed at lex/yacc
{
outf("\t\tIArrayOf& v = src.get%s();\n",pi->typname,uname);
outf("\t\tint size = v.length();\n");
const char *item_tag = pi->getMetaString("item_tag", "Item");
outf("\t\tif (size>0)\n");
outf("\t\t\tbuffer.append(\"<%s>\");\n", pi->getXmlTag());
outf("\t\tfor (int i=0;i\");\n",item_tag);
outf("\t\t\tC%s::serializer(ctx,v.item(i),buffer,false);\n",pi->typname);
outf("\t\t\tbuffer.append(\"%s>\");\n",item_tag);
outf("\t\t}\n");
outf("\t\tif (size>0)\n");
outf("\t\t\tbuffer.append(\"%s>\");\n", pi->getXmlTag());
}
else
outf("\t\t**** TODO: unhandled array: kind=%s, type=%s, name=%s, xsd-type=%s\n", getTypeKindName(pi->kind), pi->typname, uname, pi->getXsdType());
}
else
{
outf("\t\t**** TODO: unhandled array: type=, name=%s, xsd-type=%s\n", uname, pi->getXsdType());
}
outf("\t}\n");
}
else if (pi->kind == TK_ESPSTRUCT)
{
outf("\t{\n");
outf("\t\tStringBuffer tmp;\n");
outf("\t\tC%s::serializer(ctx,src.get%s(), tmp, false);\n", pi->typname, uname);
outf("\t\tif (tmp.length()>0)\n");
const char* tag = pi->getXmlTag();
outf("\t\t\tbuffer.appendf(\"<%s>%%s%s>\",tmp.str());\n", tag, tag);
outf("\t}\n");
}
else if (pi->kind == TK_ESPENUM)
{
outs("\t{\n");
outf("\t\tconst char* s = src.get%sAsString();\n",uname);
outf("\t\tbuffer.append(\"<%s>\");\n",pi->getXmlTag());
outs("\t\tencodeUtf8XML(s,buffer);\n");
outf("\t\tbuffer.append(\"%s>\");\n",pi->getXmlTag());
outs("\t}\n");
}
else
{
esp_xlate_info* info = esp_xlat(pi);
switch(info->access_kind)
{
case TK_CHAR:
outf("\t{\n");
outf("\t\tconst char* s = src.get%s();\n", uname);
outf("\t\tif (s && *s)\n");
if (!getMetaInt("encode",1))
{
outf("\t\tbuffer.appendf(\"<%s>%%s%s>\",s);\n",pi->name,pi->name);
}
else
{
outf("\t\t{\n");
outf("\t\t\tbuffer.append(\"<%s>\");\n", pi->getXmlTag());
outf("\t\t\tencodeUtf8XML(s,buffer);\n");
outf("\t\t\tbuffer.append(\"%s>\");\n", pi->getXmlTag());
outf("\t\t}\n");
}
outf("\t}\n");
break;
case TK_INT:
case TK_SHORT:
{
outf("\t{\n");
outf("\t\t%s n = src.get%s();\n", esp_xlat(pi)->access_type, uname);
outf("\t\tif (n)\n");
const char* tag = pi->getXmlTag();
outf("\t\t\tbuffer.appendf(\"<%s>%%d%s>\", n);\n", tag, tag);
outf("\t}\n");
break;
}
case TK_LONG:
{
outf("\t{\n");
outf("\t\t%s n = src.get%s();\n", esp_xlat(pi)->access_type, uname);
outf("\t\tif (n)\n");
const char* tag = pi->getXmlTag();
outf("\t\t\tbuffer.appendf(\"<%s>%%\"I64F\"d%s>\", n);\n", tag, tag);
outf("\t}\n");
break;
}
case TK_BOOL:
{
outf("\t{\n");
outf("\t\t%s b = src.get%s();\n", esp_xlat(pi)->access_type, uname);
outf("\t\tif (b)\n");
const char* tag = pi->getXmlTag();
outf("\t\t\tbuffer.appendf(\"<%s>1%s>\");\n", tag, tag);
outf("\t}\n");
break;
}
default:
if (pi->kind == TK_STRUCT && info->eam_type == EAM_jmbin) // binary
{
//TODO: should we encode binary data?
outf("\t{\n");
outf("\t\tStringBuffer tmp;\n");
outf("\t\tJBASE64_Encode(src.get%s().toByteArray(), src.get%s().length(), tmp);\n", uname, uname);
outf("\t\tif (tmp.length()>0)\n");
const char* tag = pi->getXmlTag();
outf("\t\t\tbuffer.appendf(\"<%s>%%s%s>\",tmp.str());\n", tag, tag);
outf("\t}\n");
}
else
{
outf("\t{\n");
outf("\t\t//*** default kind: %s; type=%s, name=%s\n", getTypeKindName(pi->kind), pi->typname, uname);
outf("\t\tbuffer.append(\"<%s>\");\n", pi->getXmlTag());
outf("\t\tbuffer.append(src.get%s());\n", uname);
outf("\t\tbuffer.append(\"%s>\");\n", pi->getXmlTag());
outf("\t}\n");
}
break;
}
}
//if (hasIf) outs("\t}\n");
free(uname);
}
#else
// respect nil_remove: may cause backward compatibility problem
bool nilRemove = getMetaInt("nil_remove", 0)!=0;
indentReset(1);
for (pi=getParams();pi!=NULL;pi=pi->next)
{
char *uname=strdup(pi->name);
*uname = upperchar(*uname);
if (pi->hasMapInfo())
pi->write_mapinfo_check(1,"ctx");
if (pi->flags & PF_TEMPLATE) // array
{
indentOutf("{\n");
indentInc(1);
if (pi->isPrimitiveArray())
{
const char *item_tag = pi->getMetaString("item_tag", "Item");
const char *type = pi->getArrayImplType();
indentOutf("%s& v = src.get%s();\n",type,uname);
indentOutf("int size = v.length();\n");
if (nilRemove)
{
indentOutf("if (size>0)\n");
indentOutf1(1,"buffer.append(\"<%s>\");\n", pi->getXmlTag());
}
else
indentOutf("buffer.append(\"<%s>\");\n", pi->getXmlTag());
indentOuts("for (int i=0;ikind)
{
case TK_BOOL:
case TK_SHORT:
case TK_INT: fmt = "d"; break;
case TK_UNSIGNED: fmt = "u"; break;
case TK_LONG: fmt = "ld"; break;
case TK_UNSIGNEDLONG: fmt = "lu"; break;
case TK_FLOAT:
case TK_DOUBLE: fmt = "g"; break;
case TK_null:
case TK_CHAR: fmt = "s"; break;
default:
{
char buf[128];
sprintf(buf,"Unhandled array type: %s (%s)", getTypeKindName(pi->kind), name_);
yyerror(buf);
}
}
indentOutf1(1,"buffer.appendf(\"<%s>%%%s%s>\",v.item(i));\n",item_tag,fmt,item_tag);
if (nilRemove)
{
indentOutf("if (size>0)\n");
indentOutf1(1,"buffer.append(\"%s>\");\n", pi->getXmlTag());
}
else
indentOutf("buffer.append(\"%s>\");\n", pi->getXmlTag());
}
else if (pi->typname)
{
indentOutf("IArrayOf& v = src.get%s();\n",pi->typname,uname);
indentOuts("int size = v.length();\n");
const char *item_tag = pi->getMetaString("item_tag", pi->typname);
if (nilRemove)
{
indentOutf("if (size>0)\n");
indentOutf1(1,"buffer.append(\"<%s>\");\n", pi->getXmlTag());
}
else
indentOutf("buffer.append(\"<%s>\");\n", pi->getXmlTag());
indentOutf("for (int i=0;i\");\n",item_tag);
indentOutf("C%s::serializer(ctx,v.item(i),buffer,false);\n",pi->typname);
indentOutf("buffer.append(\"%s>\");\n",item_tag);
indentOutf(-1,"}\n");
if (nilRemove)
{
indentOutf("if (size>0)\n");
indentOutf1(1,"buffer.append(\"%s>\");\n", pi->getXmlTag());
}
else
indentOutf("buffer.append(\"%s>\");\n", pi->getXmlTag());
}
else
{
indentOutf("**** TODO: unhandled array: type=%s, name=%s, xsd-type=%s\n", pi->typname, uname, pi->getXsdType());
}
indentOutf(-1,"}\n");
}
else if (pi->kind == TK_ESPSTRUCT)
{
indentOutf("{\n");
indentInc(1);
if (nilRemove)
{
indentOutf("StringBuffer tmp;\n");
indentOutf("C%s::serializer(ctx,src.get%s(), tmp, false);\n", pi->typname, uname);
indentOutf("if (tmp.length()>0)\n");
const char* tag = pi->getXmlTag();
indentOutf1(1,"buffer.appendf(\"<%s>%%s%s>\",tmp.str());\n", tag, tag);
}
else
{
indentOutf("buffer.append(\"<%s>\");\n", pi->getXmlTag());
indentOutf("C%s::serializer(ctx,src.get%s(), buffer, false);\n", pi->typname, uname);
indentOutf("buffer.append(\"%s>\");\n", pi->getXmlTag());
}
indentOutf(-1,"}\n");
}
else
{
esp_xlate_info* info = esp_xlat(pi);
switch(info->access_kind)
{
case TK_CHAR:
indentOuts("{\n");
indentOutf(1,"const char* s = src.get%s();\n", uname);
if (nilRemove)
{
indentOutf("if (s && *s)\n");
indentInc(1);
}
if (!getMetaInt("encode",1))
{
indentOutf("buffer.appendf(\"<%s>%%s%s>\",s);\n",pi->name,pi->name);
}
else
{
if (nilRemove)
indentOutf1(-1,"{\n");
indentOutf("buffer.append(\"<%s>\");\n", pi->getXmlTag());
indentOutf("encodeUtf8XML(s,buffer);\n");
indentOutf("buffer.append(\"%s>\");\n", pi->getXmlTag());
if (nilRemove)
indentOutf1(-1,"}\n");
}
if (nilRemove)
indentInc(-1);
indentOuts(-1,"}\n");
break;
case TK_INT:
case TK_LONG:
case TK_SHORT:
indentOuts("{\n");
indentOutf(1,"%s n = src.get%s();\n", esp_xlat(pi)->access_type, uname);
if (nilRemove)
{
indentOuts("if (n)\n");
indentInc(1);
}
indentOutf("buffer.appendf(\"<%s>%%d%s>\", n);\n", pi->name,pi->name);
if (nilRemove)
indentInc(-1);
indentOuts(-1,"}\n");
break;
case TK_BOOL:
indentOuts("{\n");
indentOutf(1,"%s b = src.get%s();\n", esp_xlat(pi)->access_type, uname);
if (nilRemove)
{
indentOuts("if (b)\n");
indentInc(1);
}
const char* tag = pi->getXmlTag();
indentOutf("buffer.append(\"<%s>1%s>\");\n", tag,tag);
if (nilRemove)
indentInc(-1);
indentOuts(-1,"}\n");
break;
default:
if (pi->kind == TK_STRUCT && info->eam_type == EAM_jmbin) // binary
{
//TODO: should we encode binary data?
indentOuts("{\n");
if (nilRemove)
{
indentOutf(1,"StringBuffer tmp;\n");
indentOutf("JBASE64_Encode(src.get%s().toByteArray(), src.get%s().length(), tmp);\n", uname, uname);
indentOutf("if (tmp.length()>0)\n");
const char* tag = pi->getXmlTag();
indentOutf1(1,"buffer.appendf(\"<%s>%%s%s>\",tmp.str());\n", tag,tag);
}
else
{
indentOutf(1,"buffer.append(\"<%s>\");\n", pi->getXmlTag());
indentOutf("JBASE64_Encode(src.get%s().toByteArray(), src.get%s().length(), buffer);\n", uname, uname);
indentOutf("buffer.append(\"%s>\");\n", pi->getXmlTag());
}
indentOuts(-1,"}\n");
}
else
{
indentOuts("{\n");
if (nilRemove)
{
indentOutf(1,"//*** default kind: %s; type=%s, name=%s\n", getTypeKindName(pi->kind), pi->typname, uname);
indentOutf("StringBuffer tmp(src.get%s());\n",uname);
indentOutf("if (tmp.length()>0)\n");
indentOutf1(1,"buffer.appendf(\"<%s>%%s%s>\",tmp.str());\n", pi->name,pi->name);
}
else
{
indentOutf(1,"//*** default kind: %s; type=%s, name=%s\n", getTypeKindName(pi->kind), pi->typname, uname);
indentOutf("buffer.append(\"<%s>\");\n", pi->getXmlTag());
indentOutf("buffer.append(src.get%s());\n", uname);
indentOutf("buffer.append(\"%s>\");\n", pi->getXmlTag());
}
indentOuts(-1,"}\n");
}
break;
}
}
free(uname);
}
#endif
outf("\tif (keepRootTag)\n\t\tbuffer.append(\"%s>\");\n", name_);
outs("}\n");
//=============================================================================================================
//method ==> serialize (MemoryBuffer&, StringBuffer &)
outf("\nvoid C%s::serialize(IEspContext* ctx, MemoryBuffer& buffer, StringBuffer &mimetype)\n{\n", name_);
if (contentVar)
{
esp_xlate_info *xinfo = esp_xlat(contentVar);
if (strcmp(xinfo->store_type, "StringBuffer")!=0)
outf("\tbuffer.clear().append(m_%s.getValue());\n", contentVar->name);
else
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);
}
else
{
outs("\tStringBuffer strbuffer;\n");
outf("\tstrbuffer.append(\"\");\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_);
if (parent)
{
outf("\tbool hasValue = C%s::unserialize(rpc_request, tagname, basepath);\n", parent);
outf("\treturn hasValue | localUnserialize(rpc_request, tagname, basepath);\n");
outs("}\n");
//method: localUnserialize(IRcpMessage...)
outf("\nbool C%s::localUnserialize(IRpcMessage& rpc_request, const char *tagname, const char *basepath)\n{\n", name_);
}
outs("\trpc_request.setEncodeXml(false);\n");
outs("\tbool hasValue = false;\n");
if (espm_type_==espm_response)
{
outs(
"\tStringBuffer xml;\n"
"\trpc_request.get_value(\"Exceptions\", xml, false);\n\n"
"\tOwned me = MakeMultiException();\n"
"\tif(xml.length() > 0)\n"
"\t\tme->deserialize(xml.str());\n\n"
"\tif (me->ordinality() > 0 )\n"
"\t{\n"
"\t\tIArrayOf& exceptions = me->getArray();\n"
"\t\tForEachItemIn(i, exceptions)\n"
"\t\t\tnoteException(*LINK(&exceptions.item(i)));\n"
"\t}\n"
"\telse\n"
"\t{\n");
}
for (pi=getParams();pi!=NULL;pi=pi->next)
{
pi->write_esp_unmarshall("rpc_request", true, (espm_type_==espm_response)?2:1);
}
if (getMetaInt("element"))
{
outs(1, "hasValue |= rpc_request.get_value(basepath, m_tag_value);\n");
}
if (espm_type_==espm_response)
outs("\t}\n");
outs("\treturn hasValue;\n");
outs("}\n");
//=============================================================================================================
//method: unserialize(CSoapValue...)
if (parent)
{
outf("\nbool C%s::unserialize(IEspContext* ctx, CSoapValue& soapval, bool localOnly)\n{\n", name_);
outf("bool hasValue = false;\n");
outf("\tif(!localOnly)\n");
outf("\t\thasValue |= C%s::unserialize(ctx,soapval);\n", parent);
}
else
{
outf("\nbool C%s::unserialize(IEspContext* ctx, CSoapValue& soapval)\n{\n", name_);
outf("\tbool hasValue = false;\n");
}
for (pi=getParams();pi!=NULL;pi=pi->next)
{
pi->write_esp_unmarshall_soapval("soapval");
}
if (getMetaInt("element"))
outs(1, "hasValue |= soapval.get_value(\"\",m_tag_value);\n");
outs("\treturn hasValue;\n");
outs("}\n");
//=============================================================================================================
//method: unserialize(IProperties...)
if (parent)
{
outf("\nbool C%s::unserialize(IEspContext* ctx, IProperties& params, MapStrToBuf *attachments, const char *basepath, bool localOnly)\n{\n", name_);
outf("\tbool hasValue = false;\n");
outf("\tif(!localOnly)\n");
outf("\t\thasValue |= C%s::unserialize(ctx,params,attachments, basepath);\n", parent);
}
else
{
outf("\nbool C%s::unserialize(IEspContext* ctx, IProperties& params, MapStrToBuf *attachments, const char *basepath)\n{\n", name_);
outf("\tbool hasValue = false;\n");
}
for (pi=getParams();pi!=NULL;pi=pi->next)
{
if (pi->typname && !strcmp(pi->typname, "EspTextFile"))
{
pi->write_esp_unmarshall_attachments("params", "attachments");
indent(1);
outf("hasValue |= m_%s_name.unmarshall(ctx, params, attachments, \"%s\", basepath%s);\n", pi->name, pi->name, pi->getOptionalParam());
}
else
pi->write_esp_unmarshall_properties("params", "attachments");;
}
if (getMetaInt("element"))
{
outs(1, "const char* val = params.queryProp(basepath);\n");
outs(1, "if (val && *val) {\n");
outs(2, "m_tag_value.set(val);\n");
outs(2, "hasValue = true;\n");
outs(1, "}\n");
}
outs("\treturn hasValue;\n");
outs("}\n");
//outf("\n\tvoid C%s::unserialize(const char * msg)\n\t{\n", name_);
//for (pi=getParams();pi!=NULL;pi=pi->next)
//{
// pi->write_esp_unmarshall("msg");
//}
//outs("\t}\n\n");
outs("\n");
write_esp_methods();
//outs("};\n\n");
write_factory_impl();
}
void EspMessageInfo::write_clarion_methods(enum espaxm_type axstype)
{
ParamInfo *pi;
if (axstype!=espaxm_setters)
{
if (espm_type_==espm_response)
outs("queryClientStatus PROCEDURE(),LONG,PROC\n");
for (pi=getParams();pi!=NULL;pi=pi->next)
{
pi->write_clarion_attr_method(false);
}
}
if (axstype!=espaxm_getters)
{
for (pi=getParams();pi!=NULL;pi=pi->next)
{
pi->write_clarion_attr_method(true);
}
}
}
void EspMessageInfo::write_esp_mapinfo(bool isDecl)
{
#ifdef MAP_INFO
outs("\nstatic IEspMapInfo& getMapInfo();");
#endif
}
char* makeXsdType(const char* s)
{
if (!s)
return NULL;
if (*s == '"')
s++;
if (strncmp(s,"tns:",4)==0)
{
s+=4;
size_t len = strlen(s);
if (*(s+len-1)=='"')
len--;
char* t = (char*)malloc(len+1);
memcpy(t,s,len);
t[len] = 0;
return t;
}
else
return NULL;
}
void EspMessageInfo::write_esp_methods(enum espaxm_type axstype, bool isDecl, bool isPure)
{
ParamInfo *pi;
if (axstype!=espaxm_setters)
{
for (pi=getParams();pi!=NULL;pi=pi->next)
{
char* xsd = makeXsdType(pi->getMetaString("format_as",NULL));
pi->write_esp_attr_method(name_, false, getMetaInt("nil_remove")!=0, isDecl, isPure, getMetaInt("trim")!=0,xsd);
if (xsd)
free(xsd);
}
}
if (axstype!=espaxm_getters)
{
for (pi=getParams();pi!=NULL;pi=pi->next)
{
char* xsd = makeXsdType(pi->getMetaString("format_as",NULL));
pi->write_esp_attr_method(name_, true, getMetaInt("nil_remove")!=0, isDecl, isPure, getMetaInt("trim")!=0,xsd);
if (xsd)
free(xsd);
}
}
}
void EspMessageInfo::write_esp_parms(bool isClientImpl)
{
ParamInfo *pi=getParams();
if (pi)
{
if (isClientImpl)
pi->write_esp_client_impl();
else
pi->write_esp_param();
for (pi=pi->next;pi!=NULL;pi=pi->next)
{
if (isClientImpl)
pi->write_esp_client_impl();
else
{
outs(", ");
pi->write_esp_param();
}
}
}
}
void EspMessageInfo::write_esp_client_method(const char *serv, const char *respname, const char *methname, bool isDecl, bool isPure)
{
outs("\n");
if (isDecl)
outs("\tvirtual ");
outf("IClient%s *", respname);
if (!isDecl && !isPure)
outf("CClient%s::", serv);
outf("%sFn(", methname);
write_esp_parms(false);
outs(")");
if (isPure)
outs("=0");
if (isDecl)
outs(";\n");
else
{
outs("\n{\n");
outf("\tOwned req = create%sRequest();\n", name_, methname);
write_esp_parms(true);
outf("\treturn %s(req.get());\n", methname);
outs("}\n");
}
}
void EspMessageInfo::write_cpp_interfaces()
{
if (espm_type_ == espm_enum)
{
// C enum type
outf("enum C%s { %s_Undefined=-1,", name_, name_);
const char* base = getParentName();
bool isIntBase = strieq(base,"int") || strieq(base,"long") || strieq(base,"uint") || strieq(base,"short");
for (ParamInfo* pi=getParams();pi!=NULL;pi=pi->next)
{
outf("C%s_%s", name_, pi->name);
if (isIntBase) {
int v = pi->getMetaInt("enum",-1);
if (v==-1)
outf("*** invalid value of Enum type");
outf("=%d",v);
}
outs(", ");
}
outs("};\n");
// array
outf("MAKEValueArray(C%s, %sArray);\n", name_, name_);
return;
}
outf("interface IConst%s : extends ", name_);
switch (espm_type_)
{
case espm_request:
outs("IEspRequest\n{\n");
break;
case espm_response:
outs("IEspResponse\n{\n");
break;
case espm_struct:
outs("IEspStruct\n{\n");
break;
case espm_enum:
case espm_none:
assert(!"Code shouldn't be reached");
break;
}
write_esp_methods(espaxm_getters, true, true);
if (getMetaInt("element")!=0)
outs(1, "virtual const char * get_tag_value()=0;\n");
outs("};\n\n");
outf("interface IEsp%s : extends IConst%s\n{\n", name_, name_);
write_esp_methods(espaxm_setters, true, true);
outf("\tvirtual void copy(IConst%s &from)=0;\n", name_);
if (getMetaInt("element"))
outs(1, "virtual void set_tag_value(const char *value)=0;\n");
outs("};\n\n");
outf("interface IClient%s : extends IInterface\n", name_);
outs("{\n");
switch (espm_type_)
{
case espm_request:
write_esp_methods(espaxm_setters, true, true);
write_esp_mapinfo(true);
break;
case espm_response:
outs("\n\tvirtual int queryClientStatus()=0;\n");
write_esp_methods(espaxm_getters, true, true);
if (getMetaInt("exceptions_inline")!=0)
outs("\n\tvirtual const IMultiException& getExceptions()=0;\n");
write_esp_mapinfo(true);
break;
case espm_struct:
write_esp_methods(espaxm_setters, true, true);
write_esp_methods(espaxm_getters, true, true);
break;
case espm_enum:
case espm_none:
assert(!"Code shouldn't be reached");
break;
}
outs("};\n\n");
}
void EspMessageInfo::write_factory_decl()
{
switch (espm_type_)
{
case espm_struct:
outf("extern \"C\" %s IEsp%s *create%s(const char *serv=NULL, const char *msgname=NULL);\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_);
outf("extern \"C\" %s IClient%s *createClient%s(const char *serv=NULL, const char *msgname=NULL);\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_);
break;
case espm_request:
case espm_response:
outf("extern \"C\" %s IEsp%s *create%s(const char *serv=NULL);\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_);
outf("extern \"C\" %s IClient%s *createClient%s(const char *serv=NULL);\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_);
break;
case espm_enum:
// no factory for enum
return;
default:
assert(!"Unhandled espm type");
}
}
void EspMessageInfo::write_factory_impl()
{
switch (espm_type_)
{
case espm_struct:
outf("extern \"C\" %s IEsp%s *create%s(const char *serv, const char *msgname){return ((IEsp%s *)new C%s(serv /*, msgname*/));}\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_, name_, name_);
outf("extern \"C\" %s IClient%s *createClient%s(const char *serv, const char *msgname){return ((IClient%s *)new C%s(serv /*, msgname*/));}\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_, name_, name_);
break;
case espm_request:
case espm_response:
outf("extern \"C\" %s IEsp%s *create%s(const char *serv){return ((IEsp%s *)new C%s(serv));}\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_, name_, name_);
outf("extern \"C\" %s IClient%s *createClient%s(const char *serv){return ((IClient%s *)new C%s(serv));}\n", (esp_def_export_tag) ? esp_def_export_tag : "", name_, name_, name_, name_);
break;
case espm_enum:
break;
default:
assert(!"Unhandled espm type");
}
}
void EspMessageInfo::write_clarion_include_interface()
{
static char ifname[256];
strcpy(ifname, "cppClient");
strcat(ifname, name_);
outf("%s INTERFACE(cppInterface),COM\n", ifname);
if (espm_type_==espm_struct)
{
write_clarion_methods(espaxm_setters);
write_clarion_methods(espaxm_getters);
}
else if (espm_type_==espm_request)
write_clarion_methods(espaxm_setters);
else
write_clarion_methods(espaxm_getters);
outs(" END\n\n");
}
EspMessageInfo *EspMethodInfo::getRequestInfo()
{
EspMessageInfo *msg = hcp->msgs;
for(;msg!=NULL; msg=msg->next)
{
if (!strcmp(msg->getName(), request_))
return msg;
}
return NULL;
}
bool EspMethodInfo::write_mapinfo_check(const char* ctxvar)
{
StrBuffer minVer, maxVer;
bool hasMin = getMetaVerInfo("min_ver", minVer);
bool hasMax = getMetaVerInfo("max_ver", maxVer);
bool hasOutput = false;
if (hasMin || hasMax)
{
hasOutput = true;
indentOuts("if (");
if (hasMin && hasMax)
outf("(%s.getClientVersion()>=%s && %s.getClientVersion()<=%s)", ctxvar, minVer.str(), ctxvar, maxVer.str());
else if (hasMin)
outf("%s.getClientVersion()>=%s", ctxvar,minVer.str());
else
outf("%s.getClientVersion()<=%s", ctxvar,maxVer.str());
}
const char* optional = getMetaString("optional", NULL);
if (optional)
{
if (hasOutput)
outs(" && ");
else
{
indentOuts("if (");
hasOutput = true;
}
const char* quote = (*optional == '"') ? "":"\"";
outf("%s.checkOptional(%s%s%s)", ctxvar, quote,optional,quote);
}
if (hasOutput)
{
outs(") {\n");
indentInc(1);
}
return hasOutput;
}
void EspMethodInfo::write_esp_method(const char *serv, bool isDecl, bool isPure)
{
EspMessageInfo *req = getRequestInfo();
if (req)
{
req->write_esp_client_method(serv, getResp(), name_, isDecl, isPure);
}
}
void EspServInfo::write_factory_impl()
{
outs("extern \"C\"");
if (esp_def_export_tag)
outf(" %s", esp_def_export_tag);
outf(" IClient%s * create%sClient() { return new CClient%s(); }\n", name_, name_, name_);
}
void EspServInfo::write_esp_binding_ipp()
{
EspMethodInfo *mthi=NULL;
int useMethodName = getMetaInt("use_method_name", 0);
outf("\n\nclass C%sSoapBinding : public CHttpSoapBinding\n", name_);
outs("{\npublic:\n");
//dom
outf("\tC%sSoapBinding(http_soap_log_level level=hsl_none);\n", name_);
outf("\tC%sSoapBinding(IPropertyTree* cfg, const char *bindname=NULL, const char *procname=NULL, http_soap_log_level level=hsl_none);\n", name_);
outs("\tvirtual void init_strings();\n");
//method ==> processRequest
outs("\tvirtual int processRequest(IRpcMessage* rpc_call, IRpcMessage* rpc_response);\n");
//method ==> getXsdDefinition
outs("\tint getXsdDefinition(IEspContext &context, CHttpRequest* request, StringBuffer &content, const char *service, const char *method, bool mda);\n");
//method ==> getMethodHtmlForm
outs("\tvirtual int getMethodHtmlForm(IEspContext &context, CHttpRequest* request, const char *serv, const char *method, StringBuffer &page, bool bIncludeFormTag);\n");
//method ==> getQualifiedNames
outs("\tint getQualifiedNames(IEspContext& ctx, MethodInfoArray & methods);\n");
//method ==> getServiceName
outs("\tStringBuffer & getServiceName(StringBuffer &resp);\n");
//method ==> isValidServiceName
outs("\tbool isValidServiceName(IEspContext &context, const char *name);\n");
//method ==> qualifyMethodName
outs("\tbool qualifyMethodName(IEspContext &context, const char *methname, StringBuffer *methQName);\n");
//method ==> qualifyServiceName
outs("\tbool qualifyServiceName(IEspContext &context, const char *servname, const char *methname, StringBuffer &servQName, StringBuffer *methQName);\n");
//method ==> onGetFile
outs("\tvirtual int onGetFile(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *pathex);\n");
//Method ==> onGetForm
outs("\tvirtual int onGetForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method);\n");
//Method ==> onGetXForm
//if (getMetaInt("use_new_form",0))
outs("\tvirtual int onGetXForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method);\n");
//Method ==> supportGeneratedForms
if (getMetaInt("noforms", 0))
outs("\tvirtual bool supportGeneratedForms(){return false;}\n");
if (getMetaInt("no_ws_index", 0))
{
//Method ==> onGetIndex
outs("\tvirtual int onGetIndex(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service)\n");
outs("\t{\n");
outs("\t\treturn onGetNotFound(context, request, response, service);\n");
outs("\t}\n");
}
//Method ==> onGetService
outs("\tvirtual int onGetService(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method, const char *pathex);\n");
//Method ==> createReqBinding
outs(1, "virtual IRpcRequestBinding *createReqBinding(IEspContext &context, IHttpMessage* request, const char *service, const char *method);\n");
//Method ==> onGetInstantQuery
outs("\tvirtual int onGetInstantQuery(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method);\n");
//Method ==> xslTransform
if (needsXslt)
{
outs("\tvoid setXslProcessor(IInterface *xslp_){xslp.set(dynamic_cast(xslp_));}\n");
outs("private:\n");
outs("\tOwned xslp;\n");
outs("\tvoid xslTransform(const char* xml, const char* xslFile, StringBuffer& output, IProperties *params)\n"
"\t{\n"
"\t\tif (xslp)\n"
"\t\t{\n"
"\t\t\tOwned xform = xslp->createXslTransform();\n"
"\t\t\tStringBuffer xslpath;\n"
"\t\t\tif (!strnicmp(xslFile, \"/esp/xslt/\", 10))\n"
"\t\t\t\tif (!checkFileExists(xslpath.append(getCFD()).append(\"smc_xslt/\").append(xslFile+10).str()) && !checkFileExists(xslpath.append(getCFD()).append(\"xslt/\").append(xslFile+10).str()))\n"
"\t\t\t\t\treturn;\n"
"\t\t\txform->setXslSource((xslpath.length()) ? xslpath.str() : xslFile);\n"
"\t\t\txform->setXmlSource(xml, strlen(xml)+1);\n"
"\t\t\tif (params) xform->copyParameters(params);\n"
"\t\t\txform->transform(output.clear());\n"
"\t\t}\n"
"\t}\n");
}
else
outs("\tvoid setXslProcessor(IInterface *xslp){}\n");
outs("};\n\n");
}
void EspServInfo::write_esp_binding()
{
EspMethodInfo *mthi=NULL;
int useMethodName = getMetaInt("use_method_name", 0);
StrBuffer wsdlVer;
bool hasVersion = getMetaVerInfo(tags,"version",wsdlVer);
if (!hasVersion)
wsdlVer.append("1");
//comment
outs("\n//=======================================================");
outf("\n// class C%sSoapBinding Implementation", name_);
outs("\n//=======================================================");
outs("\n");
outf("\nC%sSoapBinding::C%sSoapBinding(http_soap_log_level level):CHttpSoapBinding(NULL, NULL, NULL, level)\n{\n\tinit_strings();\n\tsetWsdlVersion(%s);\n}\n", name_, name_, wsdlVer.str());
outf("\nC%sSoapBinding::C%sSoapBinding(IPropertyTree* cfg, const char *bindname, const char *procname, http_soap_log_level level):CHttpSoapBinding(cfg, bindname, procname, level)\n{\n\tinit_strings(); \n\tsetWsdlVersion(%s);\n}\n", name_, name_, wsdlVer.str());
outf("\nvoid C%sSoapBinding::init_strings()\n", name_);
outs("{\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
StrBuffer val;
mthi->getMetaStringValue(val,"description");
if (val.length()) {
StrBuffer tmp;
outf("\taddMethodDescription(\"%s\", \"%s\");\n", mthi->getName(), printfEncode(val.str(), tmp).str());
}
mthi->getMetaStringValue(val.clear(),"help");
if (val.length()) {
StrBuffer tmp;
outf("\taddMethodHelp(\"%s\", \"%s\");\n", mthi->getName(), printfEncode(val.str(), tmp).str());
}
}
outs("}\n");
outf("\nint C%sSoapBinding::processRequest(IRpcMessage* rpc_call, IRpcMessage* rpc_response)\n", name_);
outs("{\n");
outs("\tif(rpc_call == NULL || rpc_response == NULL)\n\t\treturn -1;\n\n");
outs(1, "IEspContext *ctx=rpc_call->queryContext();\n");
outs(1, "DBGLOG(\"Client version: %g\", ctx->getClientVersion());\n");
outs(1, "StringBuffer serviceName;\n");
outs(1, "double clientVer=(ctx) ? ctx->getClientVersion() : 0.0;\n");
outs(1, "qualifyServiceName(*ctx, ctx->queryServiceName(NULL), NULL, serviceName, NULL);\n");
outs(1, "CRpcCall* thecall = dynamic_cast(rpc_call);\n");
outs(1, "CRpcResponse* response = dynamic_cast(rpc_response);\n\n");
outf("\tOwned iserv = (IEsp%s*)getService();\n", name_, name_);
outs("\tif(iserv == NULL)\n");
outs("\t{\n");
outs("\t\tresponse->set_status(SOAP_SERVER_ERROR);\n");
outs("\t\tresponse->set_err(\"Service not available\");\n");
outs("\t\tDBGLOG(\"Service not available\");\n");
outs("\t\treturn -1;\n\t}\n");
outs("\tif (thecall->get_name() == NULL)\n");
outs("\t{\n");
outs("\t\tresponse->set_status(SOAP_CLIENT_ERROR);\n");
outs("\t\tresponse->set_err(\"No service method specified\");\n");
outs("\t\tERRLOG(\"No service method specified\");\n");
outs("\t\treturn -1;\n");
outs("\t}\n");
outs("\n\tIEspContext& context = *rpc_call->queryContext();\n\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\tif(!stricmp(thecall->get_name(), \"%s\")||!stricmp(thecall->get_name(), \"%s\"))\n", mthi->getName(), mthi->getReq());
outs("\t{\n");
//esp_request + esp_response can persist longer than the scope of this method
outf("\t\tOwned esp_request = new C%s(serviceName.str(), thecall);\n", mthi->getReq(), mthi->getReq());
outs("\t\tcheckRequest(context);\n");
outf("\t\tOwned esp_response = new C%s(serviceName.str());\n", mthi->getResp(), mthi->getResp());
StrBuffer minVer;
bool hasMinVer = mthi->getMetaVerInfo("min_ver", minVer);
bool bHandleExceptions = 0 != mthi->getMetaInt("exceptions_inline", 0);
if (!bHandleExceptions)
bHandleExceptions = 0 != getMetaInt("exceptions_inline", 0);
//begin try block
if (bHandleExceptions)
{
outs("\t\tStringBuffer source;\n");
outf("\t\tsource.appendf(\"%s::%%s()\", thecall->get_name());\n", name_);
outf("\t\tOwned me = MakeMultiException(source.str());\n");
outs("\t\ttry\n");
outs("\t\t{\n");
if (hasMinVer)
{
outf("\t\t\tif (clientVer!=-1.0 && clientVer<%s)\n", minVer.str());
outs("\t\t\t\tthrow MakeStringException(-1, \"Client version is too old, please update your client application.\");");
}
outs("\t\t\tresponse->set_status(SOAP_OK);\n");
outf("\t\t\tiserv->on%s(context, *esp_request, *esp_response);\n", mthi->getName());
outs("\t\t}\n");
write_catch_blocks(mthi, ct_soapresp, 2);
}
else
{
if (hasMinVer)
{
outf("\t\tif (clientVer!=-1.0 && clientVer<%s)\n", minVer.str());
outs("\t\t\tthrow MakeStringException(-1, \"Client version is too old (can't pass exception to client)\");\n");
}
if (mthi->getMetaInt("do_not_log",0))
outs("\t\tcontext.queryRequestParameters()->setProp(\"do_not_log\",1);\n");
outf("\t\tiserv->on%s(*rpc_call->queryContext(), *esp_request, *esp_response);\n", mthi->getName());
outs("\t\tresponse->set_status(SOAP_OK);\n");
}
outf("\t\tresponse->set_name(\"%s\");\n", mthi->getResp());
outs("\t\tesp_response->serialize(*response);\n");
outs("\t\treturn 0;\n\t}\n\n");
}
outs("\tresponse->set_status(SOAP_CLIENT_ERROR);\n");
outs("\tStringBuffer msg, svcName;\n");
outs("\tmsg.appendf(\"Method %s not available in service %s\",thecall->get_name(),getServiceName(svcName).str());\n");
outs("\tERRLOG(\"%s\", msg.str());\n");
outs("\tresponse->set_err(msg);\n");
outs("\treturn -1;\n");
outs("}\n");
//method ==> getXsdDefinition
outf("\nint C%sSoapBinding::getXsdDefinition(IEspContext &context, CHttpRequest* request, StringBuffer &content, const char *service, const char *method, bool mda)\n", name_);
outs("{\n");
outs("\tBoolHash added;\n");
// version
if (hasVersion)
{
outs("\tif (context.getClientVersion()<=0)\n");
outf("\t\tcontext.setClientVersion(%s);\n\n", wsdlVer.str());
}
outs("\tDBGLOG(\"Client version: %g\", context.getClientVersion());\n");
// kept for backward compatible
EspStructInfo *sti=NULL;
for (sti=structs;sti!=NULL;sti=sti->next)
{
outf("\tC%s::getXsdDefinition(context, request, content, added);\n", sti->getName());
}
indentReset(1);
outf(1, "bool fullservice = (!Utils::strcasecmp(service, \"%s\"));\n", name_);
indentOuts("bool allMethods = (method==NULL || *method==0);\n");
bool needPropsDeclare = true;
bool needAccessFlagDeclare = true;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
const char *requestName = (useMethodName) ? mthi->getName() : mthi->getReq();
const char *optional=mthi->getMetaString("optional", NULL);
const char *access=mthi->getMetaString("access", NULL);
if (optional)
{
if (needPropsDeclare)
{
indentOuts("IProperties *props = request->queryParameters();\n");
needPropsDeclare = false;
}
indentOutf("if (props && props->hasProp(%s)) {\n", optional);
indentInc(1);
}
if (access)
{
if (needAccessFlagDeclare)
{
indentOuts("SecAccessFlags acc;\n");
needAccessFlagDeclare = false;
}
indentOutf("if (context.authorizeFeature(%s, acc) && acc>=SecAccess_Read) {\n", access);
indentInc(1);
}
indentOutf("if ((allMethods&&(fullservice||isMethodInSubService(context, service, \"%s\"))) || Utils::strcasecmp(method, \"%s\")==0)\n", mthi->getName(), mthi->getName());
indentOuts("{\n");
indentInc(1);
bool hasMap = mthi->write_mapinfo_check("context");
indentOutf("C%s::getMapInfo(context.queryMapInfo());\n", mthi->getReq());
indentOutf("C%s::getMapInfo(context.queryMapInfo());\n", mthi->getResp());
indentOutf("C%s::getXsdDefinition(context, request, \"%s\", content, added);\n", mthi->getReq(), requestName);
indentOutf("C%s::getXsdDefinition(context, request, content, added);\n", mthi->getResp());
if (hasMap)
indentOuts(-1,"}\n");
indentOuts(-1,"}\n");
if (access)
indentOuts(-1,"}\n");
if (optional)
indentOuts(-1,"}\n");
}
indentOuts("return 0;\n");
indentOuts(-1,"}\n");
//method ==> getMethodHtmlForm
outf("\nint C%sSoapBinding::getMethodHtmlForm(IEspContext &context, CHttpRequest* request, const char *serv, const char *method, StringBuffer &page, bool bIncludeFormTag)\n", name_);
outs("{\n");
outf("\tDBGLOG(\"Client version: %%g\", context.getClientVersion());\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\tif (Utils::strcasecmp(method, \"%s\")==0)\n", mthi->getName());
outs("\t{\n");
outf("\t\tC%s::getHtmlForm(context, request, serv, method, page);\n", mthi->getReq());
outs("\t}\n");
}
outs("\treturn 0;\n");
outs("}\n");
//method ==> getQualifiedNames
outf("\nint C%sSoapBinding::getQualifiedNames(IEspContext& ctx, MethodInfoArray & methods)\n", name_);
outs("{\n");
outs(1, "double ver = ctx.getClientVersion();\n");
outs(1, "if (ver<=0)\n");
outs(2, "ver = getWsdlVersion();\n");
outs(1, "const char *servname=ctx.queryServiceName(NULL);\n");
outf(1, "bool fullservice = (!stricmp(servname, \"esp\")||!stricmp(servname, \"%s\"));\n", name_);
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
if (!mthi->getMetaInt("noform",0))
{
const char *optional=mthi->getMetaString("optional", "NULL");
const char *access=mthi->getMetaString("access", "NULL");
const char *method_name = (getMetaInt("use_method_name")!=0) ? mthi->getName() : mthi->getReq();
StrBuffer minVer, maxVer;
bool hasMinVer = mthi->getMetaVerInfo("min_ver",minVer);
bool hasMaxVer = mthi->getMetaVerInfo("max_ver",maxVer);
outf("\tif ((fullservice || isMethodInSubService(ctx, servname, \"%s\")) && ctx.isMethodAllowed(ver,%s, %s, %s, %s))\n",
mthi->getName(), optional, access, hasMinVer ? minVer.str() : "-1", hasMaxVer ? maxVer.str() : "-1");
outf("\t\tmethods.append(*new CMethodInfo(\"%s\", \"%s\", \"%s\"));\n", mthi->getName(), method_name, mthi->getResp());
}
}
outs("\treturn methods.ordinality();\n");
outs("}\n");
//method ==> getServiceName
outf("\nStringBuffer & C%sSoapBinding::getServiceName(StringBuffer &resp)\n", name_);
outs("{\n");
outf("\tresp.append(\"%s\");\n", name_);
outs("\treturn resp;\n");
outs("}\n");
//method ==> isValidServiceName
outf("\nbool C%sSoapBinding::isValidServiceName(IEspContext &context, const char *name)\n", name_);
outs("{\n");
outf(1, "if (!Utils::strcasecmp(name, \"%s\"))\n", name_);
outs(2, "return true;\n");
outs(1, "else\n");
outs(2, "return (hasSubService(context, name));\n");
outs("}\n");
//method ==> qualifyMethodName
outf("\nbool C%sSoapBinding::qualifyMethodName(IEspContext &context, const char *methname, StringBuffer *methQName)\n", name_);
outs("{\n");
outs("\tif (!methname || !*methname)\n");
outs("\t{\n");
outs("\t\tif (methQName!=NULL)\n");
outs("\t\t\tmethQName->clear();\n");
outs("\t\treturn true;\n");
outs("\t}\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\tif (Utils::strcasecmp(methname, \"%s\")==0)\n", mthi->getName());
outs("\t{\n");
outs("\t\tif (methQName!=NULL)\n");
outf("\t\t\tmethQName->set(\"%s\");\n", mthi->getName());
outs("\t\treturn true;\n");
outs("\t}\n");
}
outs("\treturn false;\n");
outs("}\n");
//method ==> qualifyServiceName
outf("\nbool C%sSoapBinding::qualifyServiceName(IEspContext &context, const char *servname, const char *methname, StringBuffer &servQName, StringBuffer *methQName)\n", name_);
outs("{\n");
outs(1, "servQName.clear();\n");
outf(1, "if (!Utils::strcasecmp(servname, \"%s\"))\n", name_);
outs(1, "{\n");
outf(2, "servQName.append(\"%s\");\n", name_);
outs(2, "return qualifyMethodName(context, methname, methQName);\n");
outs(1, "}\n");
outs(1, "return qualifySubServiceName(context, servname, methname, servQName, methQName);\n");
outs("}\n");
//method ==> onGetFile
outf("\nint C%sSoapBinding::onGetFile(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *pathex)\n", name_);
outs("{\n");
outs("\tif(request == NULL || response == NULL)\n");
outs("\t\treturn -1;\n");
outs("\tStringBuffer mimetype;\n");
outs("\tMemoryBuffer content;\n\n");
outs("\tStringBuffer filepath;\n");
outs("\tgetBaseFilePath(filepath);\n");
outs("\tif (strchr(\"\\\\/\", filepath.charAt(filepath.length()-1))==NULL)\n");
outs("\t\tfilepath.append(\"/\");\n");
outs("\tfilepath.append(pathex);\n");
outs("\tresponse->httpContentFromFile(filepath.str());\n");
outs("\tresponse->send();\n");
outs("\treturn 0;\n");
outs("}\n");
//Method ==> onGetForm
outf("\nint C%sSoapBinding::onGetForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method)\n", name_);
outs("{\n");
if (getMetaInt("noforms", 0))
{
outs("\treturn onGetNotFound(context, request, response, service);\n");
}
else
{
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
if (mthi->getMetaInt("noform", 0))
{
outf("\tif (!stricmp(\"%s\", method))\n", mthi->getName());
outs("\t\treturn onGetNotFound(context, request, response, service);\n");
}
else
{
const char *formHtmlPath = mthi->getMetaString("form_html", NULL);
if (formHtmlPath)
{
outf("\tif (!stricmp(\"%s\", method))\n", mthi->getName());
outs("\t{\n");
outf("\t\tresponse->httpContentFromFile(%s);\n", formHtmlPath);
outs("\t\tresponse->send();\n");
outs("\t\treturn 0;\n");
outs("\t}\n");
}
}
}
// normal test form
if (hasVersion)
{
outs("\tif (context.getClientVersion()<=0)\n");
outf("\t\tcontext.setClientVersion(%s);\n\n", wsdlVer.str());
}
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\tif (!stricmp(\"%s\", method)) {\n", mthi->getName());
if (mthi->getMetaInt("use_new_form",0))
outs("\t\treturn EspHttpBinding::onGetXForm(context, request, response, service, method);\n");
else {
outf("\t\tC%s::getMapInfo(context.queryMapInfo());\n", mthi->getReq());
outf("\t\tC%s::getMapInfo(context.queryMapInfo());\n", mthi->getResp());
}
outs("\t}\n");
}
outs("\n\treturn EspHttpBinding::onGetForm(context, request, response, service, method);\n");
}
outs("}\n");
// method ==> onGetXForm
outf("int C%sSoapBinding::onGetXForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method)\n", name_);
outs("{\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
if (mthi->getMetaInt("use_new_form",0))
{
outf("\tif (!stricmp(\"%s\", method))\n", mthi->getName());
outs("\t\treturn EspHttpBinding::onGetForm(context, request, response, service, method);\n");
}
}
outs("\treturn EspHttpBinding::onGetXForm(context, request, response, service, method);\n");
outs("}\n");
if (getMetaInt("no_ws_index", 0))
{
//Method ==> onGetIndex
outf("\nint C%sSoapBinding::onGetIndex(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service)\n", name_);
outs("{\n");
outs("\treturn onGetNotFound(context, request, response, service);\n");
outs("}\n");
}
//Method ==> onGetService
outf("\nint C%sSoapBinding::onGetService(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method, const char *pathex)\n", name_);
outs("{\n");
outs("\tif(request == NULL || response == NULL)\n");
outs("\t\treturn -1;\n");
EspMountInfo *mnt;
for (mnt=mounts;mnt!=NULL;mnt=mnt->next)
{
outs("\t");
if (mnt!=mounts)
outs("else ");
outf("if(!stricmp(method, \"%s\"))\n", mnt->getName());
outs("\t{\n");
outs("\t\tMemoryBuffer content;\n");
outs("\t\tStringBuffer mimetype;\n");
outf("\t\tStringBuffer filepath(%s);\n\n", mnt->getLocalPath());
outs("\t\tif (filepath.length()>0 && strchr(\"/\\\\\", filepath.charAt(filepath.length()-1))==NULL)\n");
outs("\t\t{\n");
outs("\t\t\tfilepath.append(\"/\");\n");
outs("\t\t}\n");
outs("\t\tfilepath.append((pathex!=NULL && *pathex!=0) ? pathex : \"index.html\");\n\n");
outs("\t\tif (!response->httpContentFromFile(filepath.str()))\n");
outs("\t\t{\n");
outs("\t\t\treturn onGetQuery(context, request, response, service, method);\n");
outs("\t\t}\n");
outs("\t\tresponse->send();\n");
outs("\t\treturn 0;\n");
outs("\t}\n");
}
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
int formIsDefault = mthi->getMetaInt("form_is_default");
if (formIsDefault)
{
outf("\tif (!stricmp(\"%s\", method))\n", mthi->getName());
outs("\t{\n");
outs("\treturn onGetForm(context, request, response, service, method);\n");
outs("\t}\n");
}
}
outs("\treturn onGetQuery(context, request, response, service, method);\n");
outs("}\n");
outf("\n IRpcRequestBinding *C%sSoapBinding::createReqBinding(IEspContext &context, IHttpMessage *ireq, const char *service, const char *method)\n", name_);
outs("{\n");
outs(1, "CHttpRequest *request=dynamic_cast(ireq);\n");
outs(1, "IProperties *props = (request) ? request->queryParameters() : NULL;\n\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf(1, "if (!stricmp(method, \"%s\") || !stricmp(method, \"%s\"))\n", mthi->getName(), mthi->getReq());
outf(2, "return new C%s(&context, \"%s\", props, NULL);\n", mthi->getReq(), name_);
}
outs(1, "return NULL;\n");
outs("}\n");
//Method ==> onGetInstantQuery
outf("\nint C%sSoapBinding::onGetInstantQuery(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method)\n", name_);
outs("{\n");
StrBuffer defVer;
bool hasDefVer = getMetaVerInfo(tags,"default_client_version",defVer);
if (hasDefVer)
{
outf("\tif (context.getClientVersion()<=0)\n");
outf("\t\tcontext.setClientVersion(%s);\n\n", defVer.str());
}
outs("\tif(request == NULL || response == NULL)\n");
outs("\t\treturn -1;\n");
outs("\tStringBuffer respStr;\n");
outf("\tOwned iserv = (IEsp%s*)getService();\n", name_, name_);
outs("\tif(iserv == NULL)\n");
outs("\t{\n");
outs("\t\trespStr.append(\"Service not available\");\n");
outs("\t\tresponse->setContent(respStr.str());\n");
outs("\t\tresponse->setContentType(\"text/html\");\n");
outs("\t\tresponse->send();\n");
outs("\t}\n");
outs("\telse\n");
outs("\t{\n");
#ifdef NEW_INSTANT_QUERY
outf("\t\tOwned 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;
const char *respXsl = mthi->getMetaString("resp_xsl_default", NULL);
const char *respContentType = mthi->getMetaString("http_content_type", "\"text/html\"");
if (!respXsl)
{
respXsl = mthi->getMetaString("client_xslt", NULL);
bClientXslt=(respXsl!=NULL);
}
bool bHandleExceptions = 0 != mthi->getMetaInt("exceptions_inline", 0) || mthi->getMetaInt("http_exceptions_inline", 0);
if (!bHandleExceptions)
bHandleExceptions = 0 != getMetaInt("exceptions_inline", 0) || getMetaInt("http_exceptions_inline", 0);
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");
outf("\t\t\tOwned esp_request = new C%s(&context, \"%s\", request->queryParameters(), request->queryAttachments());\n", mthi->getReq(), mthi->getReq(), name_);
outf("\t\t\tcheckRequest(context);\n");
outf("\t\t\tC%s* resp = new C%s(\"%s\");\n", mthi->getResp(), mthi->getResp(), name_);
outf("\t\t\tesp_response.setown(resp);\n");
if (bHandleExceptions)
{
outf("\t\t\tsource.setf(\"%s::%%s()\", method);\n", name_);
outf("\t\t\tOwned me = MakeMultiException(source.str());\n");
//begin try block
outs("\t\t\ttry\n");
outs("\t\t\t{\n");
if (mthi->getMetaInt("do_not_log",0))
outf("\t\t\t\tcontext.queryRequestParameters()->setProp(\"do_not_log\",1);\n");
outf("\t\t\t\tiserv->on%s(context, *esp_request.get(), *resp);\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(), *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 esp_request = new C%s(&context, \"%s\", request->queryParameters(), request->queryAttachments());\n", mthi->getReq(), mthi->getReq(), name_);
outf("\t\t\tOwned 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 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
{
outf("\t\tif(!stricmp(method, \"%s\")||!stricmp(method, \"%s\"))\n", mthi->getName(), mthi->getReq());
outs("\t\t{\n");
outf("\t\t\tOwned esp_request = new C%s(&context, \"%s\", request->queryParameters(), request->queryAttachments());\n", mthi->getReq(), mthi->getReq(), name_);
outf("\t\t\tcheckRequest(context);\n");
outf("\t\t\tOwned esp_response = new C%s(\"%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 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\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\tIProperties *props=request->queryParameters();\n");
outs("\t\t\t\tif (props && props->queryProp(\"rawxml_\")!=NULL)\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\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");
outs("\t\t\t\t}\n");
outs("\t\t\t\telse\n");
outs("\t\t\t\t{\n");
outs("\t\t\t\t\tStringBuffer xml;\n");
outs("\t\t\t\t\tStringBuffer sResponse;\n");
if (bClientXslt)
{
outs("\t\t\t\t\tif (request->supportClientXslt())\n");
outf("\t\t\t\t\t\txml.appendf(\"\", %s);\n", respXsl);
}
outs("\t\t\t\t\tesp_response->serialize(&context,xml);\n\n");
if (bClientXslt)
{
outs("\t\t\t\t\tif (request->supportClientXslt()){\n");
outs("\t\t\t\t\t\txml.swapWith(sResponse);\n");
outs("\t\t\t\t\t\tresponse->setContentType(\"text/xml\");\n");
outs("\t\t\t\t\t}else{\n");
}
if(respXsl[1] == '/')
{
outf("\t\t\t\t\txslTransform(xml.str(), %s, sResponse.clear(), context.queryXslParameters());\n", respXsl);
}
else
{
outf("\t\t\t\t\txslTransform(xml.str(), StringBuffer(getCFD()).append(%s).str(), sResponse.clear(), context.queryXslParameters());\n", respXsl);
}
outf("\t\t\t\t\tresponse->setContentType(%s);\n", respContentType);
needsXslt = true;
if (bClientXslt)
outs("\t\t\t\t\t}\n");
outs("\t\t\t\t\tresponse->setContent(sResponse.str());\n");
outs("\t\t\t\t}\n");
outs("\t\t\t\tresponse->send();\n");
outs("\t\t\t}\n");
outs("\t\t\treturn 0;\n");
outs("\t\t}\n");
}
}
#ifdef NEW_INSTANT_QUERY
outs("\n");
indentReset(2);
indentOuts("if (esp_response.get())\n");
indentOuts("{\n");
indentOuts(1,"if (esp_response->getRedirectUrl() && *esp_response->getRedirectUrl())\n");
indentOuts(1,"response->redirect(*request, esp_response->getRedirectUrl());\n");
indentOuts(-1,"else\n");
indentOuts("{\n");
indentOuts(1,"MemoryBuffer content;\n");
indentOuts("StringBuffer mimetype;\n");
indentOuts("esp_response->serialize(&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");
indentOuts("response->send();\n");
indentOuts(-1,"}\n");
indentOuts("return 0;\n");
indentOuts(-1,"}\n");
#endif
outs("\t}\n");
outs("\treturn onGetNotFound(context, request, response, service);\n");
outs("}\n");
}
//-------------------------------------------------------------------------------------------------------------
// class EspServInfo
void EspServInfo::write_catch_blocks(EspMethodInfo* mthi, catch_type ct, int indents)
{
const char* errorXslt=NULL;
if (ct==ct_httpresp)
{
errorXslt = mthi->getMetaString("exceptions_inline", NULL);
if (!errorXslt)
errorXslt = mthi->getMetaString("http_exceptions_inline", NULL);
if (!errorXslt)
errorXslt = getMetaString("exceptions_inline", NULL);
if (!errorXslt)
errorXslt = getMetaString("http_exceptions_inline", NULL);
}
outs(indents,"catch (IMultiException* mex)\n");
outs(indents,"{\n");
outs(indents+1,"me->append(*mex);\n");
outs(indents+1,"mex->Release();\n");
outs(indents,"}\n");
//catch IException
outs(indents,"catch (IException* e)\n");
outs(indents,"{\n");
outs(indents+1,"me->append(*e);\n");
outs(indents,"}\n");
//catch ...
outs(indents,"catch (...)\n");
outs(indents,"{\n");
outs(indents+1,"me->append(*MakeStringExceptionDirect(-1, \"Unknown Exception\"));\n");
outs(indents,"}\n");
//apply any xslt on the error(s), if it is specified in scm file
//
if (errorXslt)
{
if(errorXslt[1] == '/')
{
outf(indents, "if (response->handleExceptions(xslp, me, \"%s\", \"%s\", %s))\n", name_, mthi->getName(), errorXslt);
}
else
{
outf(indents, "if (response->handleExceptions(xslp, me, \"%s\", \"%s\", StringBuffer(getCFD()).append(%s).str()))\n", name_, mthi->getName(), errorXslt);
}
outs(indents+1, "return 0;\n");
needsXslt=true;
}
else
outf(indents, "esp_response->handleExceptions(me, \"%s\", \"%s\");\n", name_, mthi->getName());
}
void EspServInfo::write_esp_service_ipp()
{
outf("class C%s : public CInterface,\n", name_);
outf("\timplements IEsp%s\n", name_);
outs("{\n");
outs("private:\n");
outs("\tIEspContainer* m_container;\n");
outs("public:\n");
outs("\tIMPLEMENT_IINTERFACE;\n\n");
outf("\tC%s(){}\n\tvirtual ~C%s(){}\n", name_, name_);
outs("\tvirtual void init(IPropertyTree *cfg, const char *process, const char *service)\n\t{\n\t}\n");
outs("\tvirtual bool init(const char * service, const char * type, IPropertyTree * cfg, const char * process)\n\t{\n\t\treturn true;\n\t}\n");
outs("\tvirtual void setContainer(IEspContainer *c)\n\t{\n\t\tm_container = c;\n\t}\n");
outs("\tvirtual IEspContainer *queryContainer()\n\t{\n\t\treturn m_container;\n\t}\n");
outf("\tvirtual const char* getServiceType(){return \"%s\";}\n\n", name_);
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
bool stubbed = (findMetaTag(mthi->tags,"stubbed")!=NULL);
outf(1, "%sbool on%s(IEspContext &context, IEsp%s &req, IEsp%s &resp)\n", (stubbed) ? "" : "//", mthi->getName(), mthi->getReq(), mthi->getResp());
outf(1, "%s{\n", (stubbed) ? "" : "//");
outf(2, "%sreturn false;\n", (stubbed) ? "" : "//");
outf(1, "%s}\n", (stubbed) ? "" : "//");
}
outs("};\n\n");
}
void EspServInfo::write_esp_service()
{
}
void EspServInfo::write_esp_client_ipp()
{
int useMethodName = getMetaInt("use_method_name", 0);
outf("class CClient%s : public CInterface,\n", name_);
outf("\timplements IClient%s\n", name_);
outs("{\nprotected:\n");
outs("\tStringBuffer m_proxy;\n");
outs("\tStringBuffer m_url;\n");
//dom
outs("\tStringBuffer m_userid;\n");
outs("\tStringBuffer m_password;\n");
outs("\tStringBuffer m_realm;\n");
outs("\tStringBuffer m_action;\n");
outs("\tlong m_reqId;\n");
outs("\npublic:\n");
outs("\tIMPLEMENT_IINTERFACE;\n\n");
outf("\tCClient%s()\n\t{\n\t\tm_reqId=0;\n\t}\n\tvirtual ~CClient%s(){}\n", name_, name_);
outs("\tvirtual void setProxyAddress(const char *address)\n\t{\n\t\tm_proxy.set(address);\n\t}\n");
outs("\tvirtual void addServiceUrl(const char *url)\n\t{\n\t\tm_url.set(url);\n\t}\n");
outs("\tvirtual void removeServiceUrl(const char *url)\n\t{\n\t}\n");
//domsetUsernameToken
outs("\tvirtual void setUsernameToken(const char *userid,const char *password,const char *realm)\n\t{\n\t\tm_userid.set(userid);\n\t\tm_password.set(password);\n\t\tm_realm.set(realm);\n\t}\n");
outs("\tvirtual void setSoapAction(const char *action)\n\t{\n\t\tm_action.set(action);\n\t}\n");
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outs("\n");
outf("\tvirtual IClient%s * create%sRequest();\n", mthi->getReq(), mthi->getName());
outf("\tvirtual IClient%s * %s(IClient%s *request);\n", mthi->getResp(), mthi->getName(), mthi->getReq());
outf("\tvirtual void async_%s(IClient%s *request, IClient%sEvents *events,IInterface* state=0);\n", mthi->getName(), mthi->getReq(), name_);
mthi->write_esp_method(name_, true, false);
}
outs("\tstatic int transferThunkEvent(void *data);\n");
outs("#ifdef _WIN32\n");
outs("\tstatic void espWorkerThread(void* data);\n");
outs("#else\n");
outs("\tstatic void *espWorkerThread(void *data);\n");
outs("#endif\n");
outs("};\n\n");
}
void EspServInfo::write_esp_client()
{
int useMethodName = getMetaInt("use_method_name", 0);
//comment
outs("\n//=======================================================");
outs("\n// client util methods");
outs("\n//=======================================================");
outs("\n");
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\n//------ method %s ---------\n", mthi->getName());
outf("\nIClient%s * CClient%s::create%sRequest()\n", mthi->getReq(), name_, mthi->getName());
outf("{\n\tC%s* request = new C%s(\"%s\");\n", mthi->getReq(), mthi->getReq(), name_);
outs("\trequest->setProxyAddress(m_proxy.str());\n");
outs("\trequest->setUrl(m_url.str());\n");
if (useMethodName)
outf("\trequest->setMsgName(\"%s\");\n", mthi->getName());
outs("\treturn request;\n}\n");
outf("\nIClient%s * CClient%s::%s(IClient%s *request)\n", mthi->getResp(), name_, mthi->getName(), mthi->getReq());
outs("{\n");
outs("\tif(m_url.length()== 0){ throw MakeStringExceptionDirect(-1, \"url not set\"); }\n\n");
outf("\tC%s* esprequest = dynamic_cast(request);\n", mthi->getReq(), mthi->getReq());
outf("\tC%s* espresponse = new C%s(\"%s\");\n\n", mthi->getResp(), mthi->getResp(), name_);
outs("\tespresponse->setReqId(m_reqId++);\n");
//dom
outs("\tesprequest->setUserId(m_userid.str());\n");
outs("\tesprequest->setPassword(m_password.str());\n");
outs("\tesprequest->setRealm(m_realm.str());\n");
outs("\tconst char *soapaction=(m_action.length()) ? m_action.str() : NULL;\n");
outs("\tesprequest->post(m_proxy.str(), m_url.str(), *espresponse, soapaction);\n");
outs("\treturn espresponse;\n");
outs("}\n");
outf("\nvoid CClient%s::async_%s(IClient%s *request, IClient%sEvents *events,IInterface* state)\n", name_, mthi->getName(), mthi->getReq(), name_);
outs("{\n");
outs("\tif(m_url.length()==0){ throw MakeStringExceptionDirect(-1, \"url not set\"); }\n\n");
outf("\tC%s* esprequest = dynamic_cast(request);\n", mthi->getReq(), mthi->getReq());
outf("\tesprequest->setMethod(\"%s\");\n", mthi->getName());
outs("\tesprequest->setReqId(m_reqId++);\n");
outs("\tesprequest->setEventSink(events);\n");
outs("\tesprequest->setState(state);\n");
outs("\tesprequest->setUserId(m_userid.str());\n");
outs("\tesprequest->setPassword(m_password.str());\n");
outs("\tesprequest->setRealm(m_realm.str());\n");
outs("#ifdef USE_CLIENT_THREAD\n");
outs("\tesprequest->setThunkHandle(GetThunkingHandle());\n");
outs("#endif\n");
outs("\tesprequest->Link();\n\n");
outs("\tif(state!=NULL)\n");
outs("\t\tstate->Link();\n\n");
outs("#ifdef _WIN32\n");
outs("\t_beginthread(espWorkerThread, 0, (void *)(IRpcRequestBinding *)(esprequest));\n");
outs("#else\n");
outs("\tpthread_attr_t attr;\n");
outs("\tpthread_attr_init(&attr);\n");
outs("\tpthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);\n");
outs("\tpthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);\n");
outs("\tpthread_attr_setstacksize(&attr, 0x10000);\n");
outs("\tThreadId threadid;\n");
outs("\tint status;\n");
outs("\tdo\n");
outs("\t{\n");
outf("\t\tstatus = pthread_create(&threadid, &attr, CClient%s::espWorkerThread, (void *)(IRpcRequestBinding *)(esprequest));\n", name_);
outs("\t} while (0 != status && (errno == EINTR));\n");
outs("\tif (status) {\n");
outs("\t\tRelease();\n");
outs("\t\tthrow MakeOsException(errno);\n");
outs("\t}\n");
outs("#endif\n");
outs("}\n");
mthi->write_esp_method(name_, false, false);
}
outf("\nint CClient%s::transferThunkEvent(void *data)\n", name_);
outs("{\n");
outs("\tIRpcResponseBinding *response = (IRpcResponseBinding *)data;\n");
outs("\tif (response!=NULL)\n");
outs("\t{\n");
outf("\t\tIClient%sEvents *eventSink = (IClient%sEvents *)response->getEventSink();\n", name_, name_);
outs("\t\tresponse->lock();\n\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\t\tif (stricmp(response->getMethod(), \"%s\")==0)\n", mthi->getName());
outs("\t\t{\n\t\t\tif(response->getRpcState() == RPC_MESSAGE_OK)\n");
outf("\t\t\t\teventSink->on%sComplete(dynamic_cast(response),response->queryState());\n", mthi->getName(), mthi->getResp());
outf("\t\t\telse\n\t\t\t\teventSink->on%sError(dynamic_cast(response),response->queryState());\n", mthi->getName(), mthi->getResp());
outs("\t\t}\n");
}
outs("\t\tresponse->unlock();\n");
outs("\t}\n");
outs("\treturn 0;\n");
outs("}\n");
//=============================================================================
// method: espWorkerThread(void* data)
outf("\nstatic IRpcResponseBinding* create%sResponseObject(IRpcRequestBinding *request)\n",name_);
outs("{\n");
outs("\tconst char* method = request->getMethod();\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\tif (stricmp(method, \"%s\")==0)\n", mthi->getName());
outf("\t\treturn new C%s(\"%s\", request);\n", mthi->getResp(), name_);
}
outf("\treturn NULL;\n");
outs("}\n");
outf("\n#ifdef _WIN32\n");
outf("void CClient%s::espWorkerThread(void* data)\n", name_);
outf("#else\n");
outf("void *CClient%s::espWorkerThread(void *data)\n", name_);
outf("#endif\n");
outs("{\n");
outs("\tIRpcRequestBinding *request = (IRpcRequestBinding *) data;\n\n");
outs("\tif (request != NULL)\n");
outs("\t{\n");
outs("\t\trequest->lock();\n");
outf("\t\tIRpcResponseBinding *response=create%sResponseObject(request);\n",name_);
/*
const char *preif="";
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("\t\t%sif (stricmp(request->getMethod(), \"%s\")==0)\n\t\t{\n", preif, mthi->getName());
outf("\t\t\tresponse = new C%s(\"%s\", request);\n\t\t}\n", mthi->getResp(), name_);
preif="else ";
}
outf("\tresponse = createResponseObject(request);\n");
*/
outs(2, "if (response!=NULL)\n");
outs(2, "{\n");
outs(3, "try{\n");
outs(4, "request->post(*response);\n");
outs(3, "}\n");
outs(3, "catch(IException* ex){\n");
outs(4, "StringBuffer errorStr;\n");
outs(4, "ex->errorMessage(errorStr);\n");
outf(4, "ERRLOG(\"CClient%s::espWorkerThread(%%s)--Exception caught while posting async request: %%s\", request->getMethod(), errorStr.str());\n", name_);
outs(4, "ex->Release();\n");
outs(3, "}\n");
outs(3, "catch(...){\n");
outs(4, "ERRLOG(\"Unknown exception caught while posting async request\");\n");
outs(3, "}\n");
outs(2, "}\n");
outs("#ifdef USE_CLIENT_THREAD\n");
outs("\t\tThunkToClientThread(request->getThunkHandle(), transferThunkEvent, (void *)response);\n");
outs("#else\n");
outs("\t\ttransferThunkEvent((void *)response);\n");
outs("#endif\n");
outs("\t\trequest->unlock();\n");
outs("\t\tif(request->queryState()!=NULL)\n");
outs("\t\t\trequest->queryState()->Release();\n\n");
outs("\t\tif(response!=NULL)\n");
outs("\t\t\tresponse->Release();\n\n");
outs("\t\trequest->Release();\n");
outs("\t}\n");
outs("#if defined(_WIN32)\n");
outs("#else\n");
outs("\treturn (void *) 0 ;\n");
outs("#endif\n");
outs("}\n\n");
}
void EspServInfo::write_clarion_include_interface()
{
outf("cppClient%sEvents INTERFACE(cppInterface),COM\n", name_);
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("on%sComplete PROCEDURE(*cppClient%s resp),PROC\n", mthi->getName(), mthi->getResp());
outf("on%sError PROCEDURE(*cppClient%s resp),PROC\n", mthi->getName(), mthi->getResp());
}
outs("\n END\n\n");
outf("cppClient%s INTERFACE(cppInterface),COM\n", name_);
outs("setProxyAddress PROCEDURE(CONST *CSTRING address),PROC\n");
outs("addServiceUrl PROCEDURE(CONST *CSTRING url),PROC\n");
outs("removeServiceUrl PROCEDURE(CONST *CSTRING url),PROC\n");
outs("setUsernameToken PROCEDURE(CONST *CSTRING Username,CONST *CSTRING Password,CONST *CSTRING Realm ),PROC\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outf("create%sRequest PROCEDURE(),*cppClient%s,PROC\n", mthi->getName(), mthi->getReq());//mthi->getName());
outf("%s PROCEDURE(*cppClient%s request),*cppClient%s,PROC\n", mthi->getName(), mthi->getReq(), mthi->getResp());
outf("async_%s PROCEDURE(*cppClient%s request, *cppClient%sEvents events,*cppInterface State),PROC\n", mthi->getName(), mthi->getReq(), name_);
}
outs("\n END\n\n");
}
//interface IEspInstantEcl
void EspServInfo::write_event_interface()
{
outf("interface IClient%sEvents : extends IInterface\n", name_);
outs("{");
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outs("\n");
outf("\tvirtual int on%sComplete(IClient%s *resp,IInterface* state)=0;\n", mthi->getName(), mthi->getResp());
outf("\tvirtual int on%sError(IClient%s *resp,IInterface* state)=0;", mthi->getName(), mthi->getResp());
}
outs("\n};\n\n");
}
void EspServInfo::write_esp_interface()
{
outf("interface IEsp%s : extends IEspService\n", name_);
outs("{");
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outs("\n");
outf("\tvirtual bool on%s(IEspContext &context, IEsp%s &req, IEsp%s &resp)=0;", mthi->getName(), mthi->getReq(), mthi->getResp());
}
outs("\n};\n\n");
}
void EspServInfo::write_client_interface()
{
outf("interface IClient%s : extends IInterface\n", name_);
outs("{\n");
outs("\tvirtual void setProxyAddress(const char *address)=0;\n");
outs("\tvirtual void addServiceUrl(const char *url)=0;\n");
outs("\tvirtual void removeServiceUrl(const char *url)=0;\n");
outs("\tvirtual void setUsernameToken(const char *userName,const char *passWord,const char *realm)=0;\n");
outs("\tvirtual void setSoapAction(const char *action)=0;\n");
EspMethodInfo *mthi;
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
outs("\n");
outf("\tvirtual IClient%s * create%sRequest()=0;\n", mthi->getReq(), mthi->getName());
outf("\tvirtual IClient%s * %s(IClient%s *request)=0;\n", mthi->getResp(), mthi->getName(), mthi->getReq());
outf("\tvirtual void async_%s(IClient%s *request, IClient%sEvents *events,IInterface* state=0)=0;\n", mthi->getName(), mthi->getReq(), name_);
}
//add the new "flattened" client methods at the end
outs("\n");
for (mthi=methods;mthi!=NULL;mthi=mthi->next)
{
mthi->write_esp_method(name_, true, true);
}
outs("};\n\n");
}
static EspMethodInfo* sortMethods(EspMethodInfo* ms)
{
if (ms==NULL)
return ms;
// find the smallest node
EspMethodInfo* smallest = ms;
EspMethodInfo* prev = NULL; // the node right before the smallest node
for (EspMethodInfo* p = ms; p->next!=NULL; p = p->next)
{
if (strcmp(p->next->getName(), smallest->getName())<0)
{
prev = p;
smallest = p->next;
}
}
// move the smallest to the head
if (smallest != ms)
{
if (prev == ms)
{
ms->next = smallest->next;
smallest->next = ms;
}
else
{
EspMethodInfo* tmp = smallest->next;
smallest->next = ms->next;
prev->next = ms;
ms->next = tmp;
}
}
// recurively sort
smallest->next = sortMethods(smallest->next);
return smallest;
}
void EspServInfo::sortMethods()
{
methods = ::sortMethods(methods);
}
//-------------------------------------------------------------------------------------------------------------
// class HIDLcompiler
char* getTargetBase(const char* outDir, const char* src)
{
if (outDir && *outDir)
{
size_t dirlen = strlen(outDir);
size_t srclen = strlen(src);
char* buf = (char*)malloc(dirlen+srclen+5);
// get file name only
const char* p = src+srclen-1;
while(p>src && *p!='/' && *p!='\\') p--;
if (*p == '/' || *p == '\\') p++;
// absolute path
if (*outDir=='/' || *outDir=='\\' || outDir[1]==':')
{
// dir: outDir+'/'+fileName
strcpy(buf,outDir);
}
else // relative path
{
// dir: srcPath + '/' + outDir+'/'+fileName
size_t len = p-src;
if (len>0)
{
strncpy(buf,src,len);
if (buf[len-1]=='/' || buf[len-1]=='\\')
buf[len-1]='/';
else
buf[len++] = '/';
}
strcpy(buf+len,outDir);
}
size_t len = strlen(buf);
if (buf[len-1]=='/' || buf[len-1]=='\\')
{
buf[len-1]=0;
len--;
}
// now buf has the directory name for output: make the directory if not exist
createDirectory(buf);
// copy the file name
buf[len] = '/';
strcpy(buf+len+1, p);
//printf("src: %s. dir: %s.\n", src,outDir);
//printf("buf: %s\n", buf);
return buf;
}
else
return strdup(src);
}
HIDLcompiler::HIDLcompiler(const char * sourceFile,const char *outDir)
{
modules = NULL;
enums = NULL;
apis = NULL;
servs = NULL;
msgs = NULL;
includes = NULL;
filename = strdup(sourceFile);
size_t l = strlen(filename);
yyin = fopen(sourceFile, "rt");
if (!yyin) {
printf("Fatal Error: Cannot read %s\n",sourceFile);
exit(1);
}
packagename = gettail(sourceFile);
char* targetBase = getTargetBase(outDir, sourceFile);
ho = createFile(targetBase,"hpp");
cppo = createFile(targetBase, isSCM ? "ipp" : "cpp");
#if 0
xsvo = createFile(targetBase, "xsv");
#endif
clwo = createFile(targetBase, "int");
espx = isESP ? createFile(targetBase,"esp") : -1;
espng = isESPng ? createFile(targetBase,"_esp_ng", "ipp") : -1;
espngc= isESPng ? createFile(targetBase,"_esp_ng", "cpp") : -1;
espi= isESP ? createFile(targetBase, "_esp", "ipp") : -1;
espc= isESP ? createFile(targetBase, "_esp", "cpp") : -1;
free(targetBase);
}
HIDLcompiler::~HIDLcompiler()
{
fclose(yyin);
close(ho);
close(cppo);
//close(xsvo);
close(clwo);
free(packagename);
free(filename);
delete modules;
delete enums;
delete apis;
delete msgs;
delete servs;
delete includes;
}
void HIDLcompiler::Process()
{
hcp = this;
write_header_class_intro();
nCommentStartLine = -1;
yyparse();
if (nCommentStartLine > -1)
{
char tempBuf[256];
sprintf(tempBuf, "The comment that started at line %d is not ended yet", nCommentStartLine);
yyerror(tempBuf);
}
write_header_class_outro();
write_source_file_classes();
//write_example_implementation_module();
if (isESP)
{
write_esp();
write_esp_ex_ipp();
}
if (isESPng)
{
write_esp_ng();
write_esp_ng_cpp();
}
if (isSCM)
write_clarion_HRPC_interfaces();
}
void HIDLcompiler::write_esp()
{
//create the *.esp file
gOutfile = espx;
outf("// *** Source file generated by "HIDL" Version %s from %s.%s ***\n", HIDLVER, packagename, srcFileExt);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf("#ifndef %s_ESPGEN_INCLUDED\n", packagename);
outf("#define %s_ESPGEN_INCLUDED\n\n", packagename);
outf("#include \"%s_esp.ipp\"\n", packagename);
outs("\n");
outs("#ifdef _WIN32\n");
outs("#include \"edwin.h\"\n");
outs("#include \n");
outs("#endif\n");
outs("\n\n");
EspMessageInfo * mi;
for (mi=msgs;mi;mi=mi->next)
{
mi->write_esp();
}
EspServInfo *si;
for (si=servs;si;si=si->next)
{
si->write_esp_binding();
outs("\n\n");
si->write_esp_service();
outs("\n\n");
si->write_esp_client();
outs("\n\n");
si->write_factory_impl();
outs("\n\n");
}
outf("#endif //%s_ESPGEN_INCLUDED\n", packagename);
gOutfile = espc;
outf("// *** Source file generated by "HIDL" Version %s from %s.%s ***\n", HIDLVER, packagename, srcFileExt);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
//outf("#ifndef %s_ESPX_INCLUDED\n", packagename);
//outf("#define %s_ESPX_INCLUDED\n\n", packagename);
//if (esp_def_export_tag)
// outf("#include \"%s.esp\"\n", packagename);
outf("#include \"%s.esp\"\n", packagename);
outs("\n\n");
//outf("#endif //%s_ESPX_INCLUDED\n", packagename);
}
void HIDLcompiler::write_esp_ex_ipp()
{
gOutfile = espi;
outf("// *** Source file generated by "HIDL" Version %s from %s.%s ***\n", HIDLVER, packagename, srcFileExt);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf("#ifndef %s_EX_ESPGEN_INCLUDED\n", packagename);
outf("#define %s_EX_ESPGEN_INCLUDED\n\n", packagename);
outs("#pragma warning( disable : 4786)\n\n");
outs("//JLib\n");
outs("#include \"jliball.hpp\"\n");
outs("\n");
outs("//SCM Interfaces\n");
outs("#include \"esp.hpp\"\n");
outs("#include \"soapesp.hpp\"\n");
outf("#include \"%s.hpp\"\n", packagename);
outs("//ESP Bindings\n");
outs("#include \"SOAP/Platform/soapmessage.hpp\"\n");
outs("#include \"SOAP/Platform/soapmacro.hpp\"\n");
outs("#include \"SOAP/Platform/soapservice.hpp\"\n");
outs("#include \"SOAP/Platform/soapparam.hpp\"\n");
outs("#include \"SOAP/client/soapclient.hpp\"\n");
outs("\n\n");
outf("namespace %s\n{\n\n", packagename);
EspMessageInfo * mi;
for (mi=msgs;mi;mi=mi->next)
{
mi->write_esp_ipp();
}
EspServInfo *si;
for (si=servs;si;si=si->next)
{
si->write_esp_service_ipp();
outs("\n\n");
si->write_esp_binding_ipp();
outs("\n\n");
si->write_esp_client_ipp();
outs("\n\n");
}
outs("}\n");
outf("using namespace %s;\n\n", packagename);
outf("#endif //%s_ESPGEN_INCLUDED\n", packagename);
}
void HIDLcompiler::write_source_file_classes()
{
gOutfile = cppo;
outf("// *** Source file generated by "HIDL" Version %s from %s.%s ***\n", HIDLVER, packagename, srcFileExt);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf("#include \"%s.hpp\"\n\n",packagename);
ModuleInfo * mi;
for (mi=modules;mi;mi=mi->next)
{
if (isSCM) {
mi->write_clarion_scm_stub_class();
}
else {
mi->write_body_class();
mi->write_clarion_interface_class();
}
}
outs("//end\n"); // CR for Clarion
}
void HIDLcompiler::write_clarion_esp_interfaces()
{
gOutfile = clwo;
EspMessageInfo * mi;
for (mi=msgs;mi;mi=mi->next)
{
mi->write_clarion_include_interface();
outs("\n\n");
}
EspServInfo *si;
for (si=servs;si;si=si->next)
{
si->write_clarion_include_interface();
outs("\n\n");
}
}
void HIDLcompiler::write_clarion_HRPC_interfaces()
{
gOutfile = clwo;
if (isSCM)
outs("! Clarion SCM Interfaces\n");
else
{
// outs("! Clarion HRPC Interfaces\n");
outs("*** No longer generated\n");
return;
}
outf("! Include file generated by "HIDL" Version %s from %s.%s\n", HIDLVER, packagename, srcFileExt);
outs("! *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf(" OMIT('EndOfInclude',_%s_I_)\n",packagename);
outf("_%s_I_ EQUATE(1)\n\n",packagename);
if (isSCM)
{
outs(" INCLUDE('SCM.INT'),ONCE\n\n");
if (clarion.length())
{
outs(clarion.str());
outs("\n\n");
}
}
else
outs(" INCLUDE('HRPC.INC'),ONCE\n\n");
EnumInfo * ei;
for (ei=enums;ei;ei=ei->next)
{
ei->write_clarion_enum();
}
ModuleInfo * mi;
for (mi=modules;mi;mi=mi->next)
{
mi->write_clarion_include_module();
}
if (isESP)
{
write_clarion_esp_interfaces();
}
outs("\n");
outs(" MAP\n");
outf(" MODULE('%s')\n",packagename);
if (!isSCM)
{
for (mi=modules;mi;mi=mi->next)
{
outf(" HRPC_Make_%s(HRPCI_Clarion_Transport transport),*HRPCI_%s,PASCAL,NAME('_HRPC_Make_%s@4')\n",mi->name,mi->name,mi->name);
}
}
else
{
ApiInfo * fi;
for (fi=apis;fi;fi=fi->next)
{
fi->write_clarion_include_method();
}
}
outs(" END\n\n");
outs(" END\n\n");
outf("\nEndOfInclude\n");
}
void HIDLcompiler::write_example_implementation_module()
{
gOutfile = xsvo;
outs("// Example Server Implementation Template\n");
outf("// Source file generated by "HIDL" Version %s from %s.%s\n", HIDLVER, packagename, srcFileExt);
outs("// *** You should copy this file before changing, as it will be overwritten next time "HIDL" is run ***\n\n");
outs("#include \n");
outs("#include \n");
outs("#include \n\n");
outs("#include \"hrpcsock.hpp\"// default use TCP/IP sockets\n\n");
outs("// TBD - Add other includes here\n\n");
ModuleInfo * mi;
for (mi=modules;mi;mi=mi->next)
{
mi->write_define();
}
outf("#include \"%s.cpp\"\n\n",packagename);
for (mi=modules;mi;mi=mi->next)
{
mi->write_example_module();
}
}
void HIDLcompiler::write_header_class_intro()
{
gOutfile=ho;
outf("// *** Include file generated by "HIDL" Version %s from %s.%s ***\n", HIDLVER, packagename, srcFileExt);
outf("// *** Not to be hand edited (changes will be lost on re-generation) ***\n\n");
outf("#ifndef %s_%s_INCL\n",packagename,isSCM?"SCM":"HID");
outf("#define %s_%s_INCL\n\n",packagename,isSCM?"SCM":"HID");
if (isESP)
{
outf("#include \"esp.hpp\"\n\n");
}
else if (isSCM)
{
//outf("#include \"scm.hpp\"\n\n");
}
else
outf("#include \"hrpc.hpp\"\n\n");
}
void HIDLcompiler::write_header_class_outro()
{
outs("\n");
EspMessageInfo * mi;
for (mi=msgs;mi;mi=mi->next)
{
mi->write_factory_decl();
}
outs("\n");
outf("#endif // _%s_%s_INCL\n", packagename,isSCM?"SCM":"HID");
outs("//end\n"); // CR for Clarion
}
//-------------------------------------------------------------------------------------------------------------
// class EnumInfo
void EnumInfo::write_header_enum()
{
outf("enum %s\n{\n", name);
for (EnumValInfo *vi=vals;vi;vi=vi->next) {
outf("\t%s = %d",vi->name,vi->val);
if (vi->next)
outs(",\n");
else
outs("\n");
}
outs("};\n\n");
}
void EnumInfo::write_clarion_enum()
{
outf("%s EQUATE(UNSIGNED)\n", xlat(name));
outf(" ITEMIZE,PRE(%s)\n",xlat(name));
for (EnumValInfo *vi=vals;vi;vi=vi->next) {
outf("%s\tEQUATE(%d)\n",xlat(vi->name),vi->val);
}
outs("\tEND\n\n");
}
// end
//-------------------------------------------------------------------------------------------------------------