generate_java_rpc.cpp revision 7add83bbb52d8783be9c3c68dc3dd4d7f2fead54
1#include "generate_java.h" 2#include "Type.h" 3#include <string.h> 4#include <stdio.h> 5#include <stdlib.h> 6#include <string.h> 7 8Type* SERVICE_CONTAINER_TYPE = new Type("com.android.athome.service", 9 "AndroidAtHomeServiceContainer", Type::BUILT_IN, false, false); 10 11static string 12format_int(int n) 13{ 14 char str[20]; 15 sprintf(str, "%d", n); 16 return string(str); 17} 18 19static string 20class_name_leaf(const string& str) 21{ 22 string::size_type pos = str.rfind('.'); 23 if (pos == string::npos) { 24 return str; 25 } else { 26 return string(str, pos+1); 27 } 28} 29 30// ================================================= 31class RpcProxyClass : public Class 32{ 33public: 34 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType); 35 virtual ~RpcProxyClass(); 36 37 Variable* endpoint; 38 Variable* context; 39 40private: 41 void generate_ctor(); 42}; 43 44RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType) 45 :Class() 46{ 47 this->comment = gather_comments(iface->comments_token->extra); 48 this->modifiers = PUBLIC; 49 this->what = Class::CLASS; 50 this->type = interfaceType; 51 52 // context 53 this->context = new Variable(CONTEXT_TYPE, "_context"); 54 this->elements.push_back(new Field(PRIVATE, this->context)); 55 // endpoint 56 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint"); 57 this->elements.push_back(new Field(PRIVATE, this->endpoint)); 58 59 // methods 60 generate_ctor(); 61} 62 63RpcProxyClass::~RpcProxyClass() 64{ 65} 66 67void 68RpcProxyClass::generate_ctor() 69{ 70 Variable* context = new Variable(CONTEXT_TYPE, "context"); 71 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint"); 72 Method* ctor = new Method; 73 ctor->modifiers = PUBLIC; 74 ctor->name = this->type->Name(); 75 ctor->statements = new StatementBlock; 76 ctor->parameters.push_back(context); 77 ctor->parameters.push_back(endpoint); 78 this->elements.push_back(ctor); 79 80 ctor->statements->Add(new Assignment(this->context, context)); 81 ctor->statements->Add(new Assignment(this->endpoint, endpoint)); 82} 83 84// ================================================= 85class ServiceBaseClass : public Class 86{ 87public: 88 ServiceBaseClass(const interface_type* iface); 89 virtual ~ServiceBaseClass(); 90 91 void AddMethod(const string& methodName, StatementBlock** statements); 92 void DoneWithMethods(); 93 94 bool needed; 95 Method* processMethod; 96 Variable* actionParam; 97 Variable* errorParam; 98 Variable* requestData; 99 Variable* resultData; 100 IfStatement* dispatchIfStatement; 101 102private: 103 void generate_ctor(); 104 void generate_process(); 105}; 106 107ServiceBaseClass::ServiceBaseClass(const interface_type* iface) 108 :Class(), 109 needed(false), 110 dispatchIfStatement(NULL) 111{ 112 this->comment = "/** Extend this to implement a link service. */"; 113 this->modifiers = STATIC | PUBLIC | ABSTRACT; 114 this->what = Class::CLASS; 115 this->type = NAMES.Find(iface->package, append(iface->name.data, ".ServiceBase").c_str()); 116 this->extends = RPC_SERVICE_BASE_TYPE; 117 118 // methods 119 generate_ctor(); 120 generate_process(); 121} 122 123ServiceBaseClass::~ServiceBaseClass() 124{ 125} 126 127void 128ServiceBaseClass::generate_ctor() 129{ 130 Variable* container = new Variable(SERVICE_CONTAINER_TYPE, "container"); 131 Variable* name = new Variable(STRING_TYPE, "name"); 132 Variable* type = new Variable(STRING_TYPE, "type"); 133 Variable* version = new Variable(INT_TYPE, "version"); 134 Method* ctor = new Method; 135 ctor->modifiers = PUBLIC; 136 ctor->name = class_name_leaf(this->type->Name()); 137 ctor->statements = new StatementBlock; 138 ctor->parameters.push_back(container); 139 ctor->parameters.push_back(name); 140 ctor->parameters.push_back(type); 141 ctor->parameters.push_back(version); 142 this->elements.push_back(ctor); 143 144 ctor->statements->Add(new MethodCall("super", 4, container, name, type, version)); 145} 146 147void 148ServiceBaseClass::generate_process() 149{ 150 // byte[] process(String action, byte[] params, RpcError status) 151 this->processMethod = new Method; 152 this->processMethod->modifiers = PUBLIC; 153 this->processMethod->returnType = BYTE_TYPE; 154 this->processMethod->returnTypeDimension = 1; 155 this->processMethod->name = "process"; 156 this->processMethod->statements = new StatementBlock; 157 this->elements.push_back(this->processMethod); 158 159 this->actionParam = new Variable(STRING_TYPE, "action"); 160 this->processMethod->parameters.push_back(this->actionParam); 161 162 Variable* requestParam = new Variable(BYTE_TYPE, "requestParam", 1); 163 this->processMethod->parameters.push_back(requestParam); 164 165 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0); 166 this->processMethod->parameters.push_back(this->errorParam); 167 168 this->requestData = new Variable(RPC_DATA_TYPE, "request"); 169 this->processMethod->statements->Add(new VariableDeclaration(requestData, 170 new NewExpression(RPC_DATA_TYPE, 1, requestParam))); 171 172 this->resultData = new Variable(RPC_DATA_TYPE, "response"); 173 this->processMethod->statements->Add(new VariableDeclaration(this->resultData, 174 NULL_VALUE)); 175} 176 177void 178ServiceBaseClass::AddMethod(const string& methodName, StatementBlock** statements) 179{ 180 IfStatement* ifs = new IfStatement(); 181 ifs->expression = new MethodCall(new StringLiteralExpression(methodName), "equals", 1, 182 this->actionParam); 183 ifs->statements = *statements = new StatementBlock; 184 if (this->dispatchIfStatement == NULL) { 185 this->dispatchIfStatement = ifs; 186 this->processMethod->statements->Add(dispatchIfStatement); 187 } else { 188 this->dispatchIfStatement->elseif = ifs; 189 this->dispatchIfStatement = ifs; 190 } 191} 192 193void 194ServiceBaseClass::DoneWithMethods() 195{ 196 IfStatement* s = new IfStatement; 197 s->statements = new StatementBlock; 198 this->processMethod->statements->Add(s); 199 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE); 200 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize"))); 201 s->elseif = new IfStatement; 202 s = s->elseif; 203 s->statements->Add(new ReturnStatement(NULL_VALUE)); 204} 205 206// ================================================= 207class ResultDispatcherClass : public Class 208{ 209public: 210 ResultDispatcherClass(); 211 virtual ~ResultDispatcherClass(); 212 213 void AddMethod(int index, const string& name, Method** method, Variable** param); 214 215 bool needed; 216 Variable* methodId; 217 Variable* callback; 218 Method* onResultMethod; 219 Variable* resultParam; 220 SwitchStatement* methodSwitch; 221 222private: 223 void generate_ctor(); 224 void generate_onResult(); 225}; 226 227ResultDispatcherClass::ResultDispatcherClass() 228 :Class(), 229 needed(false) 230{ 231 this->modifiers = PRIVATE | FINAL; 232 this->what = Class::CLASS; 233 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false); 234 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE); 235 236 // methodId 237 this->methodId = new Variable(INT_TYPE, "methodId"); 238 this->elements.push_back(new Field(PRIVATE, this->methodId)); 239 this->callback = new Variable(OBJECT_TYPE, "callback"); 240 this->elements.push_back(new Field(PRIVATE, this->callback)); 241 242 // methods 243 generate_ctor(); 244 generate_onResult(); 245} 246 247ResultDispatcherClass::~ResultDispatcherClass() 248{ 249} 250 251void 252ResultDispatcherClass::generate_ctor() 253{ 254 Variable* methodIdParam = new Variable(INT_TYPE, "methId"); 255 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj"); 256 Method* ctor = new Method; 257 ctor->modifiers = PUBLIC; 258 ctor->name = this->type->Name(); 259 ctor->statements = new StatementBlock; 260 ctor->parameters.push_back(methodIdParam); 261 ctor->parameters.push_back(callbackParam); 262 this->elements.push_back(ctor); 263 264 ctor->statements->Add(new Assignment(this->methodId, methodIdParam)); 265 ctor->statements->Add(new Assignment(this->callback, callbackParam)); 266} 267 268void 269ResultDispatcherClass::generate_onResult() 270{ 271 this->onResultMethod = new Method; 272 this->onResultMethod->modifiers = PUBLIC; 273 this->onResultMethod->returnType = VOID_TYPE; 274 this->onResultMethod->returnTypeDimension = 0; 275 this->onResultMethod->name = "onResult"; 276 this->onResultMethod->statements = new StatementBlock; 277 this->elements.push_back(this->onResultMethod); 278 279 this->resultParam = new Variable(BYTE_TYPE, "result", 1); 280 this->onResultMethod->parameters.push_back(this->resultParam); 281 282 this->methodSwitch = new SwitchStatement(this->methodId); 283 this->onResultMethod->statements->Add(this->methodSwitch); 284} 285 286void 287ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param) 288{ 289 Method* m = new Method; 290 m->modifiers = PUBLIC; 291 m->returnType = VOID_TYPE; 292 m->returnTypeDimension = 0; 293 m->name = name; 294 m->statements = new StatementBlock; 295 *param = new Variable(BYTE_TYPE, "result", 1); 296 m->parameters.push_back(*param); 297 this->elements.push_back(m); 298 *method = m; 299 300 Case* c = new Case(format_int(index)); 301 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam)); 302 303 this->methodSwitch->cases.push_back(c); 304} 305 306// ================================================= 307static void 308generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from) 309{ 310 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__); 311 exit(1); 312} 313 314static void 315generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v, 316 Variable* data, Variable** cl) 317{ 318 Expression* k = new StringLiteralExpression(key); 319 if (v->dimension == 0) { 320 t->CreateFromRpcData(addTo, k, v, data, cl); 321 } 322 if (v->dimension == 1) { 323 //t->ReadArrayFromRpcData(addTo, v, data, cl); 324 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n", 325 __FILE__, __LINE__); 326 } 327} 328 329static void 330generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data) 331{ 332 if (v->dimension == 0) { 333 t->WriteToRpcData(addTo, k, v, data, 0); 334 } 335 if (v->dimension == 1) { 336 //t->WriteArrayToParcel(addTo, v, data); 337 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n", 338 __FILE__, __LINE__); 339 } 340} 341 342// ================================================= 343static string 344results_class_name(const string& n) 345{ 346 string str = n; 347 str[0] = toupper(str[0]); 348 str.insert(0, "On"); 349 return str; 350} 351 352static string 353results_method_name(const string& n) 354{ 355 string str = n; 356 str[0] = toupper(str[0]); 357 str.insert(0, "on"); 358 return str; 359} 360 361static Type* 362generate_results_method(const method_type* method, RpcProxyClass* proxyClass) 363{ 364 arg_type* arg; 365 366 string resultsMethodName = results_method_name(method->name.data); 367 Type* resultsInterfaceType = new Type(results_class_name(method->name.data), 368 Type::GENERATED, false, false); 369 370 if (!method->oneway) { 371 Class* resultsClass = new Class; 372 resultsClass->modifiers = STATIC | PUBLIC; 373 resultsClass->what = Class::INTERFACE; 374 resultsClass->type = resultsInterfaceType; 375 376 Method* resultMethod = new Method; 377 resultMethod->comment = gather_comments(method->comments_token->extra); 378 resultMethod->modifiers = PUBLIC; 379 resultMethod->returnType = VOID_TYPE; 380 resultMethod->returnTypeDimension = 0; 381 resultMethod->name = resultsMethodName; 382 if (0 != strcmp("void", method->type.type.data)) { 383 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data), 384 "_result", method->type.dimension)); 385 } 386 arg = method->args; 387 while (arg != NULL) { 388 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 389 resultMethod->parameters.push_back(new Variable( 390 NAMES.Search(arg->type.type.data), arg->name.data, 391 arg->type.dimension)); 392 } 393 arg = arg->next; 394 } 395 resultsClass->elements.push_back(resultMethod); 396 397 if (resultMethod->parameters.size() > 0) { 398 proxyClass->elements.push_back(resultsClass); 399 return resultsInterfaceType; 400 } 401 } 402 //delete resultsInterfaceType; 403 return NULL; 404} 405 406static void 407generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass, 408 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 409{ 410 arg_type* arg; 411 Method* proxyMethod = new Method; 412 proxyMethod->comment = gather_comments(method->comments_token->extra); 413 proxyMethod->modifiers = PUBLIC; 414 proxyMethod->returnType = VOID_TYPE; 415 proxyMethod->returnTypeDimension = 0; 416 proxyMethod->name = method->name.data; 417 proxyMethod->statements = new StatementBlock; 418 proxyClass->elements.push_back(proxyMethod); 419 420 // The local variables 421 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 422 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 423 424 // Add the arguments 425 arg = method->args; 426 while (arg != NULL) { 427 if (convert_direction(arg->direction.data) & IN_PARAMETER) { 428 // Function signature 429 Type* t = NAMES.Search(arg->type.type.data); 430 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 431 proxyMethod->parameters.push_back(v); 432 433 // Input parameter marshalling 434 generate_write_to_data(t, proxyMethod->statements, 435 new StringLiteralExpression(arg->name.data), v, _data); 436 } 437 arg = arg->next; 438 } 439 440 // If there is a results interface for this class 441 Expression* resultParameter; 442 if (resultsInterfaceType != NULL) { 443 // Result interface parameter 444 Variable* resultListener = new Variable(resultsInterfaceType, "_result"); 445 proxyMethod->parameters.push_back(resultListener); 446 447 // Add the results dispatcher callback 448 resultsDispatcherClass->needed = true; 449 resultParameter = new NewExpression(resultsDispatcherClass->type, 2, 450 new LiteralExpression(format_int(index)), resultListener); 451 } else { 452 resultParameter = NULL_VALUE; 453 } 454 455 // All proxy methods take an error parameter 456 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors"); 457 proxyMethod->parameters.push_back(errorListener); 458 459 // Call the broker 460 proxyMethod->statements->Add(new MethodCall(RPC_BROKER_TYPE, "sendRequest", 6, 461 new FieldVariable(THIS_VALUE, "_context"), 462 new StringLiteralExpression(method->name.data), 463 proxyClass->endpoint, 464 new MethodCall(_data, "serialize"), 465 resultParameter, 466 errorListener)); 467} 468 469static void 470generate_result_dispatcher_method(const method_type* method, 471 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 472{ 473 arg_type* arg; 474 Method* dispatchMethod; 475 Variable* dispatchParam; 476 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam); 477 478 Variable* classLoader = NULL; 479 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData"); 480 dispatchMethod->statements->Add(new VariableDeclaration(resultData, 481 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam))); 482 483 // The callback method itself 484 MethodCall* realCall = new MethodCall( 485 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")), 486 results_method_name(method->name.data)); 487 488 // The return value 489 { 490 Type* t = NAMES.Search(method->type.type.data); 491 Variable* rv = new Variable(t, "rv"); 492 dispatchMethod->statements->Add(new VariableDeclaration(rv)); 493 generate_create_from_data(t, dispatchMethod->statements, "_result", rv, 494 resultData, &classLoader); 495 realCall->arguments.push_back(rv); 496 } 497 498 VariableFactory stubArgs("arg"); 499 arg = method->args; 500 while (arg != NULL) { 501 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 502 // Unmarshall the results 503 Type* t = NAMES.Search(arg->type.type.data); 504 Variable* v = stubArgs.Get(t); 505 dispatchMethod->statements->Add(new VariableDeclaration(v)); 506 507 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v, 508 resultData, &classLoader); 509 510 // Add the argument to the callback 511 realCall->arguments.push_back(v); 512 } 513 arg = arg->next; 514 } 515 516 // Call the callback method 517 dispatchMethod->statements->Add(realCall); 518} 519 520static void 521generate_service_base_methods(const method_type* method, ServiceBaseClass* serviceBaseClass) 522{ 523 arg_type* arg; 524 StatementBlock* block; 525 serviceBaseClass->AddMethod(method->name.data, &block); 526 527 // The abstract method that the service developers implement 528 Method* decl = new Method; 529 decl->comment = gather_comments(method->comments_token->extra); 530 decl->modifiers = PUBLIC | ABSTRACT; 531 decl->returnType = NAMES.Search(method->type.type.data); 532 decl->returnTypeDimension = method->type.dimension; 533 decl->name = method->name.data; 534 535 arg = method->args; 536 while (arg != NULL) { 537 decl->parameters.push_back(new Variable( 538 NAMES.Search(arg->type.type.data), arg->name.data, 539 arg->type.dimension)); 540 arg = arg->next; 541 } 542 543 serviceBaseClass->elements.push_back(decl); 544 545 // The call to decl (from above) 546 MethodCall* realCall = new MethodCall(THIS_VALUE, method->name.data); 547 548 // args 549 Variable* classLoader = NULL; 550 VariableFactory stubArgs("_arg"); 551 arg = method->args; 552 while (arg != NULL) { 553 Type* t = NAMES.Search(arg->type.type.data); 554 Variable* v = stubArgs.Get(t); 555 v->dimension = arg->type.dimension; 556 557 // Unmarshall the parameter 558 block->Add(new VariableDeclaration(v)); 559 if (convert_direction(arg->direction.data) & IN_PARAMETER) { 560 generate_create_from_data(t, block, arg->name.data, v, 561 serviceBaseClass->requestData, &classLoader); 562 } else { 563 if (arg->type.dimension == 0) { 564 block->Add(new Assignment(v, new NewExpression(v->type))); 565 } 566 else if (arg->type.dimension == 1) { 567 generate_new_array(v->type, block, v, serviceBaseClass->requestData); 568 } 569 else { 570 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, 571 __LINE__); 572 } 573 } 574 575 // Add that parameter to the method call 576 realCall->arguments.push_back(v); 577 578 arg = arg->next; 579 } 580 581 // the real call 582 Variable* _result = NULL; 583 if (0 == strcmp(method->type.type.data, "void")) { 584 block->Add(realCall); 585 } else { 586 _result = new Variable(decl->returnType, "_result", 587 decl->returnTypeDimension); 588 block->Add(new VariableDeclaration(_result, realCall)); 589 590 // marshall the return value 591 generate_write_to_data(decl->returnType, block, 592 new StringLiteralExpression("_result"), _result, serviceBaseClass->resultData); 593 } 594 595 // out parameters 596 int i = 0; 597 arg = method->args; 598 while (arg != NULL) { 599 Type* t = NAMES.Search(arg->type.type.data); 600 Variable* v = stubArgs.Get(i++); 601 602 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 603 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data), 604 v, serviceBaseClass->resultData); 605 } 606 607 arg = arg->next; 608 } 609} 610 611static void 612generate_method(const method_type* method, RpcProxyClass* proxyClass, 613 ServiceBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass, 614 int index) 615{ 616 // == the callback interface for results ================================= 617 // the service base class 618 Type* resultsInterfaceType = generate_results_method(method, proxyClass); 619 620 // == the method in the proxy class ===================================== 621 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index); 622 623 // == the method in the result dispatcher class ========================= 624 if (resultsInterfaceType != NULL) { 625 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType, 626 index); 627 } 628 629 // == the dispatch method in the service base class ====================== 630 generate_service_base_methods(method, serviceBaseClass); 631} 632 633Class* 634generate_rpc_interface_class(const interface_type* iface) 635{ 636 // the proxy class 637 InterfaceType* interfaceType = static_cast<InterfaceType*>( 638 NAMES.Find(iface->package, iface->name.data)); 639 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType); 640 641 // the service base class 642 ServiceBaseClass* base = new ServiceBaseClass(iface); 643 proxy->elements.push_back(base); 644 645 // the result dispatcher 646 ResultDispatcherClass* results = new ResultDispatcherClass(); 647 648 // all the declared methods of the proxy 649 int index = 0; 650 interface_item_type* item = iface->interface_items; 651 while (item != NULL) { 652 if (item->item_type == METHOD_TYPE) { 653 generate_method((method_type*)item, proxy, base, results, index); 654 } 655 item = item->next; 656 index++; 657 } 658 base->DoneWithMethods(); 659 660 // only add this if there are methods with results / out parameters 661 if (results->needed) { 662 proxy->elements.push_back(results); 663 } 664 665 return proxy; 666} 667 668