generate_java_rpc.cpp revision 9a7822497fa38539fdf9dacc6860c436e2925251
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* ANDROID_CONTEXT_TYPE = new Type("android.content", 9 "Context", Type::BUILT_IN, false, false, false); 10Type* PRESENTER_BASE_TYPE = new Type("com.android.athome.connector", 11 "EventListener", Type::BUILT_IN, false, false, false); 12Type* PRESENTER_LISTENER_BASE_TYPE = new Type("com.android.athome.connector", 13 "EventListener.Listener", Type::BUILT_IN, false, false, false); 14Type* RPC_BROKER_TYPE = new Type("com.android.athome.connector", "Broker", 15 Type::BUILT_IN, false, false, false); 16// TODO: Just use Endpoint, so this works for all endpoints. 17Type* RPC_CONNECTOR_TYPE = new Type("com.android.athome.connector", "Connector", 18 Type::BUILT_IN, false, false, false); 19Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("com.android.athome.rpc", 20 "EndpointInfo", true, __FILE__, __LINE__); 21Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("com.android.athome.rpc", "RpcResultHandler", 22 true, __FILE__, __LINE__); 23Type* RPC_ERROR_LISTENER_TYPE = new Type("com.android.athome.rpc", "RpcErrorHandler", 24 Type::BUILT_IN, false, false, false); 25Type* RPC_CONTEXT_TYPE = new UserDataType("com.android.athome.rpc", "RpcContext", true, 26 __FILE__, __LINE__); 27 28static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, 29 Variable* v, Variable* data, Variable** cl); 30static void generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from); 31static void generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, 32 Variable* data); 33 34static string 35format_int(int n) 36{ 37 char str[20]; 38 sprintf(str, "%d", n); 39 return string(str); 40} 41 42static string 43class_name_leaf(const string& str) 44{ 45 string::size_type pos = str.rfind('.'); 46 if (pos == string::npos) { 47 return str; 48 } else { 49 return string(str, pos+1); 50 } 51} 52 53static string 54results_class_name(const string& n) 55{ 56 string str = n; 57 str[0] = toupper(str[0]); 58 str.insert(0, "On"); 59 return str; 60} 61 62static string 63results_method_name(const string& n) 64{ 65 string str = n; 66 str[0] = toupper(str[0]); 67 str.insert(0, "on"); 68 return str; 69} 70 71static string 72push_method_name(const string& n) 73{ 74 string str = n; 75 str[0] = toupper(str[0]); 76 str.insert(0, "push"); 77 return str; 78} 79 80// ================================================= 81class DispatcherClass : public Class 82{ 83public: 84 DispatcherClass(const interface_type* iface, Expression* target); 85 virtual ~DispatcherClass(); 86 87 void AddMethod(const method_type* method); 88 void DoneWithMethods(); 89 90 Method* processMethod; 91 Variable* actionParam; 92 Variable* requestParam; 93 Variable* rpcContextParam; 94 Variable* errorParam; 95 Variable* requestData; 96 Variable* resultData; 97 IfStatement* dispatchIfStatement; 98 Expression* targetExpression; 99 100private: 101 void generate_process(); 102}; 103 104DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target) 105 :Class(), 106 dispatchIfStatement(NULL), 107 targetExpression(target) 108{ 109 generate_process(); 110} 111 112DispatcherClass::~DispatcherClass() 113{ 114} 115 116void 117DispatcherClass::generate_process() 118{ 119 // byte[] process(String action, byte[] params, RpcContext context, RpcError status) 120 this->processMethod = new Method; 121 this->processMethod->modifiers = PUBLIC; 122 this->processMethod->returnType = BYTE_TYPE; 123 this->processMethod->returnTypeDimension = 1; 124 this->processMethod->name = "process"; 125 this->processMethod->statements = new StatementBlock; 126 127 this->actionParam = new Variable(STRING_TYPE, "action"); 128 this->processMethod->parameters.push_back(this->actionParam); 129 130 this->requestParam = new Variable(BYTE_TYPE, "requestParam", 1); 131 this->processMethod->parameters.push_back(this->requestParam); 132 133 this->rpcContextParam = new Variable(RPC_CONTEXT_TYPE, "context", 0); 134 this->processMethod->parameters.push_back(this->rpcContextParam); 135 136 this->errorParam = new Variable(RPC_ERROR_TYPE, "errorParam", 0); 137 this->processMethod->parameters.push_back(this->errorParam); 138 139 this->requestData = new Variable(RPC_DATA_TYPE, "request"); 140 this->processMethod->statements->Add(new VariableDeclaration(requestData, 141 new NewExpression(RPC_DATA_TYPE, 1, this->requestParam))); 142 143 this->resultData = new Variable(RPC_DATA_TYPE, "resultData"); 144 this->processMethod->statements->Add(new VariableDeclaration(this->resultData, 145 NULL_VALUE)); 146} 147 148void 149DispatcherClass::AddMethod(const method_type* method) 150{ 151 arg_type* arg; 152 153 // The if/switch statement 154 IfStatement* ifs = new IfStatement(); 155 ifs->expression = new MethodCall(new StringLiteralExpression(method->name.data), "equals", 156 1, this->actionParam); 157 StatementBlock* block = ifs->statements = new StatementBlock; 158 if (this->dispatchIfStatement == NULL) { 159 this->dispatchIfStatement = ifs; 160 this->processMethod->statements->Add(dispatchIfStatement); 161 } else { 162 this->dispatchIfStatement->elseif = ifs; 163 this->dispatchIfStatement = ifs; 164 } 165 166 // The call to decl (from above) 167 MethodCall* realCall = new MethodCall(this->targetExpression, method->name.data); 168 169 // args 170 Variable* classLoader = NULL; 171 VariableFactory stubArgs("_arg"); 172 arg = method->args; 173 while (arg != NULL) { 174 Type* t = NAMES.Search(arg->type.type.data); 175 Variable* v = stubArgs.Get(t); 176 v->dimension = arg->type.dimension; 177 178 // Unmarshall the parameter 179 block->Add(new VariableDeclaration(v)); 180 if (convert_direction(arg->direction.data) & IN_PARAMETER) { 181 generate_create_from_data(t, block, arg->name.data, v, 182 this->requestData, &classLoader); 183 } else { 184 if (arg->type.dimension == 0) { 185 block->Add(new Assignment(v, new NewExpression(v->type))); 186 } 187 else if (arg->type.dimension == 1) { 188 generate_new_array(v->type, block, v, this->requestData); 189 } 190 else { 191 fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, 192 __LINE__); 193 } 194 } 195 196 // Add that parameter to the method call 197 realCall->arguments.push_back(v); 198 199 arg = arg->next; 200 } 201 202 // Add a final parameter: RpcContext. Contains data about 203 // incoming request (e.g., certificate) 204 realCall->arguments.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); 205 206 Type* returnType = NAMES.Search(method->type.type.data); 207 if (returnType == EVENT_FAKE_TYPE) { 208 returnType = VOID_TYPE; 209 } 210 211 // the real call 212 bool first = true; 213 Variable* _result = NULL; 214 if (returnType == VOID_TYPE) { 215 block->Add(realCall); 216 } else { 217 _result = new Variable(returnType, "_result", 218 method->type.dimension); 219 block->Add(new VariableDeclaration(_result, realCall)); 220 221 // need the result RpcData 222 if (first) { 223 block->Add(new Assignment(this->resultData, 224 new NewExpression(RPC_DATA_TYPE))); 225 first = false; 226 } 227 228 // marshall the return value 229 generate_write_to_data(returnType, block, 230 new StringLiteralExpression("_result"), _result, this->resultData); 231 } 232 233 // out parameters 234 int i = 0; 235 arg = method->args; 236 while (arg != NULL) { 237 Type* t = NAMES.Search(arg->type.type.data); 238 Variable* v = stubArgs.Get(i++); 239 240 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 241 // need the result RpcData 242 if (first) { 243 block->Add(new Assignment(this->resultData, new NewExpression(RPC_DATA_TYPE))); 244 first = false; 245 } 246 247 generate_write_to_data(t, block, new StringLiteralExpression(arg->name.data), 248 v, this->resultData); 249 } 250 251 arg = arg->next; 252 } 253} 254 255void 256DispatcherClass::DoneWithMethods() 257{ 258 if (this->dispatchIfStatement == NULL) { 259 return; 260 } 261 262 this->elements.push_back(this->processMethod); 263 264 IfStatement* fallthrough = new IfStatement(); 265 fallthrough->statements = new StatementBlock; 266 fallthrough->statements->Add(new ReturnStatement( 267 new MethodCall(SUPER_VALUE, "process", 4, 268 this->actionParam, this->requestParam, 269 this->rpcContextParam, 270 this->errorParam))); 271 this->dispatchIfStatement->elseif = fallthrough; 272 IfStatement* s = new IfStatement; 273 s->statements = new StatementBlock; 274 this->processMethod->statements->Add(s); 275 s->expression = new Comparison(this->resultData, "!=", NULL_VALUE); 276 s->statements->Add(new ReturnStatement(new MethodCall(this->resultData, "serialize"))); 277 s->elseif = new IfStatement; 278 s = s->elseif; 279 s->statements->Add(new ReturnStatement(NULL_VALUE)); 280} 281 282// ================================================= 283class RpcProxyClass : public Class 284{ 285public: 286 RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType); 287 virtual ~RpcProxyClass(); 288 289 Variable* endpoint; 290 Variable* broker; 291 292private: 293 void generate_ctor(); 294}; 295 296RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType) 297 :Class() 298{ 299 this->comment = gather_comments(iface->comments_token->extra); 300 this->modifiers = PUBLIC; 301 this->what = Class::CLASS; 302 this->type = interfaceType; 303 304 // broker 305 this->broker = new Variable(RPC_BROKER_TYPE, "_broker"); 306 this->elements.push_back(new Field(PRIVATE, this->broker)); 307 // endpoint 308 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint"); 309 this->elements.push_back(new Field(PRIVATE, this->endpoint)); 310 311 // methods 312 generate_ctor(); 313} 314 315RpcProxyClass::~RpcProxyClass() 316{ 317} 318 319void 320RpcProxyClass::generate_ctor() 321{ 322 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); 323 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint"); 324 Method* ctor = new Method; 325 ctor->modifiers = PUBLIC; 326 ctor->name = class_name_leaf(this->type->Name()); 327 ctor->statements = new StatementBlock; 328 ctor->parameters.push_back(broker); 329 ctor->parameters.push_back(endpoint); 330 this->elements.push_back(ctor); 331 332 ctor->statements->Add(new Assignment(this->broker, broker)); 333 ctor->statements->Add(new Assignment(this->endpoint, endpoint)); 334} 335 336// ================================================= 337class EventListenerClass : public DispatcherClass 338{ 339public: 340 EventListenerClass(const interface_type* iface, Type* listenerType); 341 virtual ~EventListenerClass(); 342 343 Variable* _listener; 344 345private: 346 void generate_ctor(); 347}; 348 349Expression* 350generate_get_listener_expression(Type* cast) 351{ 352 return new Cast(cast, new MethodCall(THIS_VALUE, "getView")); 353} 354 355EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType) 356 :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener")) 357{ 358 this->modifiers = PRIVATE; 359 this->what = Class::CLASS; 360 this->type = new Type(iface->package ? iface->package : "", 361 append(iface->name.data, ".Presenter"), 362 Type::GENERATED, false, false, false); 363 this->extends = PRESENTER_BASE_TYPE; 364 365 this->_listener = new Variable(listenerType, "_listener"); 366 this->elements.push_back(new Field(PRIVATE, this->_listener)); 367 368 // methods 369 generate_ctor(); 370} 371 372EventListenerClass::~EventListenerClass() 373{ 374} 375 376void 377EventListenerClass::generate_ctor() 378{ 379 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); 380 Variable* listener = new Variable(this->_listener->type, "listener"); 381 Method* ctor = new Method; 382 ctor->modifiers = PUBLIC; 383 ctor->name = class_name_leaf(this->type->Name()); 384 ctor->statements = new StatementBlock; 385 ctor->parameters.push_back(broker); 386 ctor->parameters.push_back(listener); 387 this->elements.push_back(ctor); 388 389 ctor->statements->Add(new MethodCall("super", 2, broker, listener)); 390 ctor->statements->Add(new Assignment(this->_listener, listener)); 391} 392 393// ================================================= 394class ListenerClass : public Class 395{ 396public: 397 ListenerClass(const interface_type* iface); 398 virtual ~ListenerClass(); 399 400 bool needed; 401 402private: 403 void generate_ctor(); 404}; 405 406ListenerClass::ListenerClass(const interface_type* iface) 407 :Class(), 408 needed(false) 409{ 410 this->comment = "/** Extend this to listen to the events from this class. */"; 411 this->modifiers = STATIC | PUBLIC ; 412 this->what = Class::CLASS; 413 this->type = new Type(iface->package ? iface->package : "", 414 append(iface->name.data, ".Listener"), 415 Type::GENERATED, false, false, false); 416 this->extends = PRESENTER_LISTENER_BASE_TYPE; 417} 418 419ListenerClass::~ListenerClass() 420{ 421} 422 423// ================================================= 424class EndpointBaseClass : public DispatcherClass 425{ 426public: 427 EndpointBaseClass(const interface_type* iface); 428 virtual ~EndpointBaseClass(); 429 430 bool needed; 431 432private: 433 void generate_ctor(); 434}; 435 436EndpointBaseClass::EndpointBaseClass(const interface_type* iface) 437 :DispatcherClass(iface, THIS_VALUE), 438 needed(false) 439{ 440 this->comment = "/** Extend this to implement a link service. */"; 441 this->modifiers = STATIC | PUBLIC | ABSTRACT; 442 this->what = Class::CLASS; 443 this->type = new Type(iface->package ? iface->package : "", 444 append(iface->name.data, ".EndpointBase"), 445 Type::GENERATED, false, false, false); 446 this->extends = RPC_CONNECTOR_TYPE; 447 448 // methods 449 generate_ctor(); 450} 451 452EndpointBaseClass::~EndpointBaseClass() 453{ 454} 455 456void 457EndpointBaseClass::generate_ctor() 458{ 459 Variable* container = new Variable(ANDROID_CONTEXT_TYPE, "context"); 460 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); 461 Method* ctor = new Method; 462 ctor->modifiers = PUBLIC; 463 ctor->name = class_name_leaf(this->type->Name()); 464 ctor->statements = new StatementBlock; 465 ctor->parameters.push_back(container); 466 ctor->parameters.push_back(broker); 467 this->elements.push_back(ctor); 468 469 ctor->statements->Add(new MethodCall("super", 2, container, broker)); 470} 471 472// ================================================= 473class ResultDispatcherClass : public Class 474{ 475public: 476 ResultDispatcherClass(); 477 virtual ~ResultDispatcherClass(); 478 479 void AddMethod(int index, const string& name, Method** method, Variable** param); 480 481 bool needed; 482 Variable* methodId; 483 Variable* callback; 484 Method* onResultMethod; 485 Variable* resultParam; 486 SwitchStatement* methodSwitch; 487 488private: 489 void generate_ctor(); 490 void generate_onResult(); 491}; 492 493ResultDispatcherClass::ResultDispatcherClass() 494 :Class(), 495 needed(false) 496{ 497 this->modifiers = PRIVATE | FINAL; 498 this->what = Class::CLASS; 499 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false); 500 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE); 501 502 // methodId 503 this->methodId = new Variable(INT_TYPE, "methodId"); 504 this->elements.push_back(new Field(PRIVATE, this->methodId)); 505 this->callback = new Variable(OBJECT_TYPE, "callback"); 506 this->elements.push_back(new Field(PRIVATE, this->callback)); 507 508 // methods 509 generate_ctor(); 510 generate_onResult(); 511} 512 513ResultDispatcherClass::~ResultDispatcherClass() 514{ 515} 516 517void 518ResultDispatcherClass::generate_ctor() 519{ 520 Variable* methodIdParam = new Variable(INT_TYPE, "methId"); 521 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj"); 522 Method* ctor = new Method; 523 ctor->modifiers = PUBLIC; 524 ctor->name = class_name_leaf(this->type->Name()); 525 ctor->statements = new StatementBlock; 526 ctor->parameters.push_back(methodIdParam); 527 ctor->parameters.push_back(callbackParam); 528 this->elements.push_back(ctor); 529 530 ctor->statements->Add(new Assignment(this->methodId, methodIdParam)); 531 ctor->statements->Add(new Assignment(this->callback, callbackParam)); 532} 533 534void 535ResultDispatcherClass::generate_onResult() 536{ 537 this->onResultMethod = new Method; 538 this->onResultMethod->modifiers = PUBLIC; 539 this->onResultMethod->returnType = VOID_TYPE; 540 this->onResultMethod->returnTypeDimension = 0; 541 this->onResultMethod->name = "onResult"; 542 this->onResultMethod->statements = new StatementBlock; 543 this->elements.push_back(this->onResultMethod); 544 545 this->resultParam = new Variable(BYTE_TYPE, "result", 1); 546 this->onResultMethod->parameters.push_back(this->resultParam); 547 548 this->methodSwitch = new SwitchStatement(this->methodId); 549 this->onResultMethod->statements->Add(this->methodSwitch); 550} 551 552void 553ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param) 554{ 555 Method* m = new Method; 556 m->modifiers = PUBLIC; 557 m->returnType = VOID_TYPE; 558 m->returnTypeDimension = 0; 559 m->name = name; 560 m->statements = new StatementBlock; 561 *param = new Variable(BYTE_TYPE, "result", 1); 562 m->parameters.push_back(*param); 563 this->elements.push_back(m); 564 *method = m; 565 566 Case* c = new Case(format_int(index)); 567 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam)); 568 c->statements->Add(new Break()); 569 570 this->methodSwitch->cases.push_back(c); 571} 572 573// ================================================= 574static void 575generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from) 576{ 577 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__); 578 exit(1); 579} 580 581static void 582generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v, 583 Variable* data, Variable** cl) 584{ 585 Expression* k = new StringLiteralExpression(key); 586 if (v->dimension == 0) { 587 t->CreateFromRpcData(addTo, k, v, data, cl); 588 } 589 if (v->dimension == 1) { 590 //t->ReadArrayFromRpcData(addTo, v, data, cl); 591 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n", 592 __FILE__, __LINE__); 593 } 594} 595 596static void 597generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data) 598{ 599 if (v->dimension == 0) { 600 t->WriteToRpcData(addTo, k, v, data, 0); 601 } 602 if (v->dimension == 1) { 603 //t->WriteArrayToParcel(addTo, v, data); 604 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n", 605 __FILE__, __LINE__); 606 } 607} 608 609// ================================================= 610static Type* 611generate_results_method(const method_type* method, RpcProxyClass* proxyClass) 612{ 613 arg_type* arg; 614 615 string resultsMethodName = results_method_name(method->name.data); 616 Type* resultsInterfaceType = new Type(results_class_name(method->name.data), 617 Type::GENERATED, false, false, false); 618 619 if (!method->oneway) { 620 Class* resultsClass = new Class; 621 resultsClass->modifiers = STATIC | PUBLIC; 622 resultsClass->what = Class::INTERFACE; 623 resultsClass->type = resultsInterfaceType; 624 625 Method* resultMethod = new Method; 626 resultMethod->comment = gather_comments(method->comments_token->extra); 627 resultMethod->modifiers = PUBLIC; 628 resultMethod->returnType = VOID_TYPE; 629 resultMethod->returnTypeDimension = 0; 630 resultMethod->name = resultsMethodName; 631 if (0 != strcmp("void", method->type.type.data)) { 632 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data), 633 "_result", method->type.dimension)); 634 } 635 arg = method->args; 636 while (arg != NULL) { 637 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 638 resultMethod->parameters.push_back(new Variable( 639 NAMES.Search(arg->type.type.data), arg->name.data, 640 arg->type.dimension)); 641 } 642 arg = arg->next; 643 } 644 resultsClass->elements.push_back(resultMethod); 645 646 if (resultMethod->parameters.size() > 0) { 647 proxyClass->elements.push_back(resultsClass); 648 return resultsInterfaceType; 649 } 650 } 651 //delete resultsInterfaceType; 652 return NULL; 653} 654 655static void 656generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass, 657 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 658{ 659 arg_type* arg; 660 Method* proxyMethod = new Method; 661 proxyMethod->comment = gather_comments(method->comments_token->extra); 662 proxyMethod->modifiers = PUBLIC; 663 proxyMethod->returnType = VOID_TYPE; 664 proxyMethod->returnTypeDimension = 0; 665 proxyMethod->name = method->name.data; 666 proxyMethod->statements = new StatementBlock; 667 proxyClass->elements.push_back(proxyMethod); 668 669 // The local variables 670 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 671 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 672 673 // Add the arguments 674 arg = method->args; 675 while (arg != NULL) { 676 if (convert_direction(arg->direction.data) & IN_PARAMETER) { 677 // Function signature 678 Type* t = NAMES.Search(arg->type.type.data); 679 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 680 proxyMethod->parameters.push_back(v); 681 682 // Input parameter marshalling 683 generate_write_to_data(t, proxyMethod->statements, 684 new StringLiteralExpression(arg->name.data), v, _data); 685 } 686 arg = arg->next; 687 } 688 689 // If there is a results interface for this class 690 Expression* resultParameter; 691 if (resultsInterfaceType != NULL) { 692 // Result interface parameter 693 Variable* resultListener = new Variable(resultsInterfaceType, "_result"); 694 proxyMethod->parameters.push_back(resultListener); 695 696 // Add the results dispatcher callback 697 resultsDispatcherClass->needed = true; 698 resultParameter = new NewExpression(resultsDispatcherClass->type, 2, 699 new LiteralExpression(format_int(index)), resultListener); 700 } else { 701 resultParameter = NULL_VALUE; 702 } 703 704 // All proxy methods take an error parameter 705 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors"); 706 proxyMethod->parameters.push_back(errorListener); 707 708 // Call the broker 709 proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"), 710 "sendRpc", 5, 711 proxyClass->endpoint, 712 new StringLiteralExpression(method->name.data), 713 new MethodCall(_data, "serialize"), 714 resultParameter, 715 errorListener)); 716} 717 718static void 719generate_result_dispatcher_method(const method_type* method, 720 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 721{ 722 arg_type* arg; 723 Method* dispatchMethod; 724 Variable* dispatchParam; 725 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam); 726 727 Variable* classLoader = NULL; 728 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData"); 729 dispatchMethod->statements->Add(new VariableDeclaration(resultData, 730 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam))); 731 732 // The callback method itself 733 MethodCall* realCall = new MethodCall( 734 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")), 735 results_method_name(method->name.data)); 736 737 // The return value 738 { 739 Type* t = NAMES.Search(method->type.type.data); 740 Variable* rv = new Variable(t, "rv"); 741 dispatchMethod->statements->Add(new VariableDeclaration(rv)); 742 generate_create_from_data(t, dispatchMethod->statements, "_result", rv, 743 resultData, &classLoader); 744 realCall->arguments.push_back(rv); 745 } 746 747 VariableFactory stubArgs("arg"); 748 arg = method->args; 749 while (arg != NULL) { 750 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 751 // Unmarshall the results 752 Type* t = NAMES.Search(arg->type.type.data); 753 Variable* v = stubArgs.Get(t); 754 dispatchMethod->statements->Add(new VariableDeclaration(v)); 755 756 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v, 757 resultData, &classLoader); 758 759 // Add the argument to the callback 760 realCall->arguments.push_back(v); 761 } 762 arg = arg->next; 763 } 764 765 // Call the callback method 766 dispatchMethod->statements->Add(realCall); 767} 768 769static void 770generate_regular_method(const method_type* method, RpcProxyClass* proxyClass, 771 EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass, 772 int index) 773{ 774 arg_type* arg; 775 776 // == the callback interface for results ================================ 777 // the service base class 778 Type* resultsInterfaceType = generate_results_method(method, proxyClass); 779 780 // == the method in the proxy class ===================================== 781 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index); 782 783 // == the method in the result dispatcher class ========================= 784 if (resultsInterfaceType != NULL) { 785 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType, 786 index); 787 } 788 789 // == The abstract method that the service developers implement ========== 790 Method* decl = new Method; 791 decl->comment = gather_comments(method->comments_token->extra); 792 decl->modifiers = PUBLIC | ABSTRACT; 793 decl->returnType = NAMES.Search(method->type.type.data); 794 decl->returnTypeDimension = method->type.dimension; 795 decl->name = method->name.data; 796 arg = method->args; 797 while (arg != NULL) { 798 decl->parameters.push_back(new Variable( 799 NAMES.Search(arg->type.type.data), arg->name.data, 800 arg->type.dimension)); 801 arg = arg->next; 802 } 803 804 // Add the default RpcContext param to all methods 805 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); 806 807 serviceBaseClass->elements.push_back(decl); 808 809 810 // == the dispatch method in the service base class ====================== 811 serviceBaseClass->AddMethod(method); 812} 813 814static void 815generate_event_method(const method_type* method, RpcProxyClass* proxyClass, 816 EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass, 817 EventListenerClass* presenterClass, int index) 818{ 819 arg_type* arg; 820 listenerClass->needed = true; 821 822 // == the push method in the service base class ========================= 823 Method* push = new Method; 824 push->modifiers = PUBLIC; 825 push->name = push_method_name(method->name.data); 826 push->statements = new StatementBlock; 827 push->returnType = VOID_TYPE; 828 serviceBaseClass->elements.push_back(push); 829 830 // The local variables 831 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 832 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 833 834 // Add the arguments 835 arg = method->args; 836 while (arg != NULL) { 837 // Function signature 838 Type* t = NAMES.Search(arg->type.type.data); 839 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 840 push->parameters.push_back(v); 841 842 // Input parameter marshalling 843 generate_write_to_data(t, push->statements, 844 new StringLiteralExpression(arg->name.data), v, _data); 845 846 arg = arg->next; 847 } 848 849 // Send the notifications 850 push->statements->Add(new MethodCall("pushEvent", 2, 851 new StringLiteralExpression(method->name.data), 852 new MethodCall(_data, "serialize"))); 853 854 // == the event callback dispatcher method ==================================== 855 presenterClass->AddMethod(method); 856 857 // == the event method in the listener base class ===================== 858 Method* event = new Method; 859 event->modifiers = PUBLIC; 860 event->name = method->name.data; 861 event->statements = new StatementBlock; 862 event->returnType = VOID_TYPE; 863 listenerClass->elements.push_back(event); 864 arg = method->args; 865 while (arg != NULL) { 866 event->parameters.push_back(new Variable( 867 NAMES.Search(arg->type.type.data), arg->name.data, 868 arg->type.dimension)); 869 arg = arg->next; 870 } 871 872 // Add a final parameter: RpcContext. Contains data about 873 // incoming request (e.g., certificate) 874 event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); 875} 876 877static void 878generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType) 879{ 880 // AndroidAtHomePresenter _presenter; 881 // void startListening(Listener listener) { 882 // stopListening(); 883 // _presenter = new Presenter(_broker, listener); 884 // _presenter.startListening(_endpoint); 885 // } 886 // void stopListening() { 887 // if (_presenter != null) { 888 // _presenter.stopListening(); 889 // } 890 // } 891 892 Variable* _presenter = new Variable(presenterType, "_presenter"); 893 proxyClass->elements.push_back(new Field(PRIVATE, _presenter)); 894 895 Variable* listener = new Variable(listenerType, "listener"); 896 897 Method* startListeningMethod = new Method; 898 startListeningMethod->modifiers = PUBLIC; 899 startListeningMethod->returnType = VOID_TYPE; 900 startListeningMethod->name = "startListening"; 901 startListeningMethod->statements = new StatementBlock; 902 startListeningMethod->parameters.push_back(listener); 903 proxyClass->elements.push_back(startListeningMethod); 904 905 startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening")); 906 startListeningMethod->statements->Add(new Assignment(_presenter, 907 new NewExpression(presenterType, 2, proxyClass->broker, listener))); 908 startListeningMethod->statements->Add(new MethodCall(_presenter, 909 "startListening", 1, proxyClass->endpoint)); 910 911 Method* stopListeningMethod = new Method; 912 stopListeningMethod->modifiers = PUBLIC; 913 stopListeningMethod->returnType = VOID_TYPE; 914 stopListeningMethod->name = "stopListening"; 915 stopListeningMethod->statements = new StatementBlock; 916 proxyClass->elements.push_back(stopListeningMethod); 917 918 IfStatement* ifst = new IfStatement; 919 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE); 920 stopListeningMethod->statements->Add(ifst); 921 922 ifst->statements->Add(new MethodCall(_presenter, "stopListening")); 923 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE)); 924} 925 926Class* 927generate_rpc_interface_class(const interface_type* iface) 928{ 929 // the proxy class 930 InterfaceType* interfaceType = static_cast<InterfaceType*>( 931 NAMES.Find(iface->package, iface->name.data)); 932 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType); 933 934 // the listener class 935 ListenerClass* listener = new ListenerClass(iface); 936 937 // the presenter class 938 EventListenerClass* presenter = new EventListenerClass(iface, listener->type); 939 940 // the service base class 941 EndpointBaseClass* base = new EndpointBaseClass(iface); 942 proxy->elements.push_back(base); 943 944 // the result dispatcher 945 ResultDispatcherClass* results = new ResultDispatcherClass(); 946 947 // all the declared methods of the proxy 948 int index = 0; 949 interface_item_type* item = iface->interface_items; 950 while (item != NULL) { 951 if (item->item_type == METHOD_TYPE) { 952 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) { 953 generate_event_method((method_type*)item, proxy, base, listener, presenter, index); 954 } else { 955 generate_regular_method((method_type*)item, proxy, base, results, index); 956 } 957 } 958 item = item->next; 959 index++; 960 } 961 presenter->DoneWithMethods(); 962 base->DoneWithMethods(); 963 964 // only add this if there are methods with results / out parameters 965 if (results->needed) { 966 proxy->elements.push_back(results); 967 } 968 if (listener->needed) { 969 proxy->elements.push_back(listener); 970 proxy->elements.push_back(presenter); 971 generate_listener_methods(proxy, presenter->type, listener->type); 972 } 973 974 return proxy; 975} 976