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