generate_java_rpc.cpp revision 20e0cef180397d9d98a51f1a6b8f14d6d4e83ab2
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("android.support.place.connector", 11 "EventListener", Type::BUILT_IN, false, false, false); 12Type* PRESENTER_LISTENER_BASE_TYPE = new Type("android.support.place.connector", 13 "EventListener.Listener", Type::BUILT_IN, false, false, false); 14Type* RPC_BROKER_TYPE = new Type("android.support.place.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("android.support.place.connector", "Connector", 18 Type::BUILT_IN, false, false, false); 19Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("android.support.place.rpc", 20 "EndpointInfo", true, __FILE__, __LINE__); 21Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("android.support.place.rpc", "RpcResultHandler", 22 true, __FILE__, __LINE__); 23Type* RPC_ERROR_LISTENER_TYPE = new Type("android.support.place.rpc", "RpcErrorHandler", 24 Type::BUILT_IN, false, false, false); 25Type* RPC_CONTEXT_TYPE = new UserDataType("android.support.place.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 void generate_get_endpoint_info(); 295}; 296 297RpcProxyClass::RpcProxyClass(const interface_type* iface, InterfaceType* interfaceType) 298 :Class() 299{ 300 this->comment = gather_comments(iface->comments_token->extra); 301 this->modifiers = PUBLIC; 302 this->what = Class::CLASS; 303 this->type = interfaceType; 304 305 // broker 306 this->broker = new Variable(RPC_BROKER_TYPE, "_broker"); 307 this->elements.push_back(new Field(PRIVATE, this->broker)); 308 // endpoint 309 this->endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "_endpoint"); 310 this->elements.push_back(new Field(PRIVATE, this->endpoint)); 311 312 // methods 313 generate_ctor(); 314 generate_get_endpoint_info(); 315} 316 317RpcProxyClass::~RpcProxyClass() 318{ 319} 320 321void 322RpcProxyClass::generate_ctor() 323{ 324 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); 325 Variable* endpoint = new Variable(RPC_ENDPOINT_INFO_TYPE, "endpoint"); 326 Method* ctor = new Method; 327 ctor->modifiers = PUBLIC; 328 ctor->name = class_name_leaf(this->type->Name()); 329 ctor->statements = new StatementBlock; 330 ctor->parameters.push_back(broker); 331 ctor->parameters.push_back(endpoint); 332 this->elements.push_back(ctor); 333 334 ctor->statements->Add(new Assignment(this->broker, broker)); 335 ctor->statements->Add(new Assignment(this->endpoint, endpoint)); 336} 337 338void 339RpcProxyClass::generate_get_endpoint_info() 340{ 341 Method* get = new Method; 342 get->modifiers = PUBLIC; 343 get->returnType = RPC_ENDPOINT_INFO_TYPE; 344 get->name = "getEndpointInfo"; 345 get->statements = new StatementBlock; 346 this->elements.push_back(get); 347 348 get->statements->Add(new ReturnStatement(this->endpoint)); 349} 350 351// ================================================= 352class EventListenerClass : public DispatcherClass 353{ 354public: 355 EventListenerClass(const interface_type* iface, Type* listenerType); 356 virtual ~EventListenerClass(); 357 358 Variable* _listener; 359 360private: 361 void generate_ctor(); 362}; 363 364Expression* 365generate_get_listener_expression(Type* cast) 366{ 367 return new Cast(cast, new MethodCall(THIS_VALUE, "getView")); 368} 369 370EventListenerClass::EventListenerClass(const interface_type* iface, Type* listenerType) 371 :DispatcherClass(iface, new FieldVariable(THIS_VALUE, "_listener")) 372{ 373 this->modifiers = PRIVATE; 374 this->what = Class::CLASS; 375 this->type = new Type(iface->package ? iface->package : "", 376 append(iface->name.data, ".Presenter"), 377 Type::GENERATED, false, false, false); 378 this->extends = PRESENTER_BASE_TYPE; 379 380 this->_listener = new Variable(listenerType, "_listener"); 381 this->elements.push_back(new Field(PRIVATE, this->_listener)); 382 383 // methods 384 generate_ctor(); 385} 386 387EventListenerClass::~EventListenerClass() 388{ 389} 390 391void 392EventListenerClass::generate_ctor() 393{ 394 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); 395 Variable* listener = new Variable(this->_listener->type, "listener"); 396 Method* ctor = new Method; 397 ctor->modifiers = PUBLIC; 398 ctor->name = class_name_leaf(this->type->Name()); 399 ctor->statements = new StatementBlock; 400 ctor->parameters.push_back(broker); 401 ctor->parameters.push_back(listener); 402 this->elements.push_back(ctor); 403 404 ctor->statements->Add(new MethodCall("super", 2, broker, listener)); 405 ctor->statements->Add(new Assignment(this->_listener, listener)); 406} 407 408// ================================================= 409class ListenerClass : public Class 410{ 411public: 412 ListenerClass(const interface_type* iface); 413 virtual ~ListenerClass(); 414 415 bool needed; 416 417private: 418 void generate_ctor(); 419}; 420 421ListenerClass::ListenerClass(const interface_type* iface) 422 :Class(), 423 needed(false) 424{ 425 this->comment = "/** Extend this to listen to the events from this class. */"; 426 this->modifiers = STATIC | PUBLIC ; 427 this->what = Class::CLASS; 428 this->type = new Type(iface->package ? iface->package : "", 429 append(iface->name.data, ".Listener"), 430 Type::GENERATED, false, false, false); 431 this->extends = PRESENTER_LISTENER_BASE_TYPE; 432} 433 434ListenerClass::~ListenerClass() 435{ 436} 437 438// ================================================= 439class EndpointBaseClass : public DispatcherClass 440{ 441public: 442 EndpointBaseClass(const interface_type* iface); 443 virtual ~EndpointBaseClass(); 444 445 bool needed; 446 447private: 448 void generate_ctor(); 449}; 450 451EndpointBaseClass::EndpointBaseClass(const interface_type* iface) 452 :DispatcherClass(iface, THIS_VALUE), 453 needed(false) 454{ 455 this->comment = "/** Extend this to implement a link service. */"; 456 this->modifiers = STATIC | PUBLIC | ABSTRACT; 457 this->what = Class::CLASS; 458 this->type = new Type(iface->package ? iface->package : "", 459 append(iface->name.data, ".EndpointBase"), 460 Type::GENERATED, false, false, false); 461 this->extends = RPC_CONNECTOR_TYPE; 462 463 // methods 464 generate_ctor(); 465} 466 467EndpointBaseClass::~EndpointBaseClass() 468{ 469} 470 471void 472EndpointBaseClass::generate_ctor() 473{ 474 Variable* container = new Variable(ANDROID_CONTEXT_TYPE, "context"); 475 Variable* broker = new Variable(RPC_BROKER_TYPE, "broker"); 476 Method* ctor = new Method; 477 ctor->modifiers = PUBLIC; 478 ctor->name = class_name_leaf(this->type->Name()); 479 ctor->statements = new StatementBlock; 480 ctor->parameters.push_back(container); 481 ctor->parameters.push_back(broker); 482 this->elements.push_back(ctor); 483 484 ctor->statements->Add(new MethodCall("super", 2, container, broker)); 485} 486 487// ================================================= 488class ResultDispatcherClass : public Class 489{ 490public: 491 ResultDispatcherClass(); 492 virtual ~ResultDispatcherClass(); 493 494 void AddMethod(int index, const string& name, Method** method, Variable** param); 495 496 bool needed; 497 Variable* methodId; 498 Variable* callback; 499 Method* onResultMethod; 500 Variable* resultParam; 501 SwitchStatement* methodSwitch; 502 503private: 504 void generate_ctor(); 505 void generate_onResult(); 506}; 507 508ResultDispatcherClass::ResultDispatcherClass() 509 :Class(), 510 needed(false) 511{ 512 this->modifiers = PRIVATE | FINAL; 513 this->what = Class::CLASS; 514 this->type = new Type("_ResultDispatcher", Type::GENERATED, false, false, false); 515 this->interfaces.push_back(RPC_RESULT_HANDLER_TYPE); 516 517 // methodId 518 this->methodId = new Variable(INT_TYPE, "methodId"); 519 this->elements.push_back(new Field(PRIVATE, this->methodId)); 520 this->callback = new Variable(OBJECT_TYPE, "callback"); 521 this->elements.push_back(new Field(PRIVATE, this->callback)); 522 523 // methods 524 generate_ctor(); 525 generate_onResult(); 526} 527 528ResultDispatcherClass::~ResultDispatcherClass() 529{ 530} 531 532void 533ResultDispatcherClass::generate_ctor() 534{ 535 Variable* methodIdParam = new Variable(INT_TYPE, "methId"); 536 Variable* callbackParam = new Variable(OBJECT_TYPE, "cbObj"); 537 Method* ctor = new Method; 538 ctor->modifiers = PUBLIC; 539 ctor->name = class_name_leaf(this->type->Name()); 540 ctor->statements = new StatementBlock; 541 ctor->parameters.push_back(methodIdParam); 542 ctor->parameters.push_back(callbackParam); 543 this->elements.push_back(ctor); 544 545 ctor->statements->Add(new Assignment(this->methodId, methodIdParam)); 546 ctor->statements->Add(new Assignment(this->callback, callbackParam)); 547} 548 549void 550ResultDispatcherClass::generate_onResult() 551{ 552 this->onResultMethod = new Method; 553 this->onResultMethod->modifiers = PUBLIC; 554 this->onResultMethod->returnType = VOID_TYPE; 555 this->onResultMethod->returnTypeDimension = 0; 556 this->onResultMethod->name = "onResult"; 557 this->onResultMethod->statements = new StatementBlock; 558 this->elements.push_back(this->onResultMethod); 559 560 this->resultParam = new Variable(BYTE_TYPE, "result", 1); 561 this->onResultMethod->parameters.push_back(this->resultParam); 562 563 this->methodSwitch = new SwitchStatement(this->methodId); 564 this->onResultMethod->statements->Add(this->methodSwitch); 565} 566 567void 568ResultDispatcherClass::AddMethod(int index, const string& name, Method** method, Variable** param) 569{ 570 Method* m = new Method; 571 m->modifiers = PUBLIC; 572 m->returnType = VOID_TYPE; 573 m->returnTypeDimension = 0; 574 m->name = name; 575 m->statements = new StatementBlock; 576 *param = new Variable(BYTE_TYPE, "result", 1); 577 m->parameters.push_back(*param); 578 this->elements.push_back(m); 579 *method = m; 580 581 Case* c = new Case(format_int(index)); 582 c->statements->Add(new MethodCall(new LiteralExpression("this"), name, 1, this->resultParam)); 583 c->statements->Add(new Break()); 584 585 this->methodSwitch->cases.push_back(c); 586} 587 588// ================================================= 589static void 590generate_new_array(Type* t, StatementBlock* addTo, Variable* v, Variable* from) 591{ 592 fprintf(stderr, "aidl: implement generate_new_array %s:%d\n", __FILE__, __LINE__); 593 exit(1); 594} 595 596static void 597generate_create_from_data(Type* t, StatementBlock* addTo, const string& key, Variable* v, 598 Variable* data, Variable** cl) 599{ 600 Expression* k = new StringLiteralExpression(key); 601 if (v->dimension == 0) { 602 t->CreateFromRpcData(addTo, k, v, data, cl); 603 } 604 if (v->dimension == 1) { 605 //t->ReadArrayFromRpcData(addTo, v, data, cl); 606 fprintf(stderr, "aidl: implement generate_create_from_data for arrays%s:%d\n", 607 __FILE__, __LINE__); 608 } 609} 610 611static void 612generate_write_to_data(Type* t, StatementBlock* addTo, Expression* k, Variable* v, Variable* data) 613{ 614 if (v->dimension == 0) { 615 t->WriteToRpcData(addTo, k, v, data, 0); 616 } 617 if (v->dimension == 1) { 618 //t->WriteArrayToParcel(addTo, v, data); 619 fprintf(stderr, "aidl: implement generate_write_to_data for arrays%s:%d\n", 620 __FILE__, __LINE__); 621 } 622} 623 624// ================================================= 625static Type* 626generate_results_method(const method_type* method, RpcProxyClass* proxyClass) 627{ 628 arg_type* arg; 629 630 string resultsMethodName = results_method_name(method->name.data); 631 Type* resultsInterfaceType = new Type(results_class_name(method->name.data), 632 Type::GENERATED, false, false, false); 633 634 if (!method->oneway) { 635 Class* resultsClass = new Class; 636 resultsClass->modifiers = STATIC | PUBLIC; 637 resultsClass->what = Class::INTERFACE; 638 resultsClass->type = resultsInterfaceType; 639 640 Method* resultMethod = new Method; 641 resultMethod->comment = gather_comments(method->comments_token->extra); 642 resultMethod->modifiers = PUBLIC; 643 resultMethod->returnType = VOID_TYPE; 644 resultMethod->returnTypeDimension = 0; 645 resultMethod->name = resultsMethodName; 646 if (0 != strcmp("void", method->type.type.data)) { 647 resultMethod->parameters.push_back(new Variable(NAMES.Search(method->type.type.data), 648 "_result", method->type.dimension)); 649 } 650 arg = method->args; 651 while (arg != NULL) { 652 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 653 resultMethod->parameters.push_back(new Variable( 654 NAMES.Search(arg->type.type.data), arg->name.data, 655 arg->type.dimension)); 656 } 657 arg = arg->next; 658 } 659 resultsClass->elements.push_back(resultMethod); 660 661 if (resultMethod->parameters.size() > 0) { 662 proxyClass->elements.push_back(resultsClass); 663 return resultsInterfaceType; 664 } 665 } 666 //delete resultsInterfaceType; 667 return NULL; 668} 669 670static void 671generate_proxy_method(const method_type* method, RpcProxyClass* proxyClass, 672 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 673{ 674 arg_type* arg; 675 Method* proxyMethod = new Method; 676 proxyMethod->comment = gather_comments(method->comments_token->extra); 677 proxyMethod->modifiers = PUBLIC; 678 proxyMethod->returnType = VOID_TYPE; 679 proxyMethod->returnTypeDimension = 0; 680 proxyMethod->name = method->name.data; 681 proxyMethod->statements = new StatementBlock; 682 proxyClass->elements.push_back(proxyMethod); 683 684 // The local variables 685 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 686 proxyMethod->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 687 688 // Add the arguments 689 arg = method->args; 690 while (arg != NULL) { 691 if (convert_direction(arg->direction.data) & IN_PARAMETER) { 692 // Function signature 693 Type* t = NAMES.Search(arg->type.type.data); 694 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 695 proxyMethod->parameters.push_back(v); 696 697 // Input parameter marshalling 698 generate_write_to_data(t, proxyMethod->statements, 699 new StringLiteralExpression(arg->name.data), v, _data); 700 } 701 arg = arg->next; 702 } 703 704 // If there is a results interface for this class 705 Expression* resultParameter; 706 if (resultsInterfaceType != NULL) { 707 // Result interface parameter 708 Variable* resultListener = new Variable(resultsInterfaceType, "_result"); 709 proxyMethod->parameters.push_back(resultListener); 710 711 // Add the results dispatcher callback 712 resultsDispatcherClass->needed = true; 713 resultParameter = new NewExpression(resultsDispatcherClass->type, 2, 714 new LiteralExpression(format_int(index)), resultListener); 715 } else { 716 resultParameter = NULL_VALUE; 717 } 718 719 // All proxy methods take an error parameter 720 Variable* errorListener = new Variable(RPC_ERROR_LISTENER_TYPE, "_errors"); 721 proxyMethod->parameters.push_back(errorListener); 722 723 // Call the broker 724 proxyMethod->statements->Add(new MethodCall(new FieldVariable(THIS_VALUE, "_broker"), 725 "sendRpc", 5, 726 proxyClass->endpoint, 727 new StringLiteralExpression(method->name.data), 728 new MethodCall(_data, "serialize"), 729 resultParameter, 730 errorListener)); 731} 732 733static void 734generate_result_dispatcher_method(const method_type* method, 735 ResultDispatcherClass* resultsDispatcherClass, Type* resultsInterfaceType, int index) 736{ 737 arg_type* arg; 738 Method* dispatchMethod; 739 Variable* dispatchParam; 740 resultsDispatcherClass->AddMethod(index, method->name.data, &dispatchMethod, &dispatchParam); 741 742 Variable* classLoader = NULL; 743 Variable* resultData = new Variable(RPC_DATA_TYPE, "resultData"); 744 dispatchMethod->statements->Add(new VariableDeclaration(resultData, 745 new NewExpression(RPC_DATA_TYPE, 1, dispatchParam))); 746 747 // The callback method itself 748 MethodCall* realCall = new MethodCall( 749 new Cast(resultsInterfaceType, new FieldVariable(THIS_VALUE, "callback")), 750 results_method_name(method->name.data)); 751 752 // The return value 753 { 754 Type* t = NAMES.Search(method->type.type.data); 755 if (t != VOID_TYPE) { 756 Variable* rv = new Variable(t, "rv"); 757 dispatchMethod->statements->Add(new VariableDeclaration(rv)); 758 generate_create_from_data(t, dispatchMethod->statements, "_result", rv, 759 resultData, &classLoader); 760 realCall->arguments.push_back(rv); 761 } 762 } 763 764 VariableFactory stubArgs("arg"); 765 arg = method->args; 766 while (arg != NULL) { 767 if (convert_direction(arg->direction.data) & OUT_PARAMETER) { 768 // Unmarshall the results 769 Type* t = NAMES.Search(arg->type.type.data); 770 Variable* v = stubArgs.Get(t); 771 dispatchMethod->statements->Add(new VariableDeclaration(v)); 772 773 generate_create_from_data(t, dispatchMethod->statements, arg->name.data, v, 774 resultData, &classLoader); 775 776 // Add the argument to the callback 777 realCall->arguments.push_back(v); 778 } 779 arg = arg->next; 780 } 781 782 // Call the callback method 783 dispatchMethod->statements->Add(realCall); 784} 785 786static void 787generate_regular_method(const method_type* method, RpcProxyClass* proxyClass, 788 EndpointBaseClass* serviceBaseClass, ResultDispatcherClass* resultsDispatcherClass, 789 int index) 790{ 791 arg_type* arg; 792 793 // == the callback interface for results ================================ 794 // the service base class 795 Type* resultsInterfaceType = generate_results_method(method, proxyClass); 796 797 // == the method in the proxy class ===================================== 798 generate_proxy_method(method, proxyClass, resultsDispatcherClass, resultsInterfaceType, index); 799 800 // == the method in the result dispatcher class ========================= 801 if (resultsInterfaceType != NULL) { 802 generate_result_dispatcher_method(method, resultsDispatcherClass, resultsInterfaceType, 803 index); 804 } 805 806 // == The abstract method that the service developers implement ========== 807 Method* decl = new Method; 808 decl->comment = gather_comments(method->comments_token->extra); 809 decl->modifiers = PUBLIC | ABSTRACT; 810 decl->returnType = NAMES.Search(method->type.type.data); 811 decl->returnTypeDimension = method->type.dimension; 812 decl->name = method->name.data; 813 arg = method->args; 814 while (arg != NULL) { 815 decl->parameters.push_back(new Variable( 816 NAMES.Search(arg->type.type.data), arg->name.data, 817 arg->type.dimension)); 818 arg = arg->next; 819 } 820 821 // Add the default RpcContext param to all methods 822 decl->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); 823 824 serviceBaseClass->elements.push_back(decl); 825 826 827 // == the dispatch method in the service base class ====================== 828 serviceBaseClass->AddMethod(method); 829} 830 831static void 832generate_event_method(const method_type* method, RpcProxyClass* proxyClass, 833 EndpointBaseClass* serviceBaseClass, ListenerClass* listenerClass, 834 EventListenerClass* presenterClass, int index) 835{ 836 arg_type* arg; 837 listenerClass->needed = true; 838 839 // == the push method in the service base class ========================= 840 Method* push = new Method; 841 push->modifiers = PUBLIC; 842 push->name = push_method_name(method->name.data); 843 push->statements = new StatementBlock; 844 push->returnType = VOID_TYPE; 845 serviceBaseClass->elements.push_back(push); 846 847 // The local variables 848 Variable* _data = new Variable(RPC_DATA_TYPE, "_data"); 849 push->statements->Add(new VariableDeclaration(_data, new NewExpression(RPC_DATA_TYPE))); 850 851 // Add the arguments 852 arg = method->args; 853 while (arg != NULL) { 854 // Function signature 855 Type* t = NAMES.Search(arg->type.type.data); 856 Variable* v = new Variable(t, arg->name.data, arg->type.dimension); 857 push->parameters.push_back(v); 858 859 // Input parameter marshalling 860 generate_write_to_data(t, push->statements, 861 new StringLiteralExpression(arg->name.data), v, _data); 862 863 arg = arg->next; 864 } 865 866 // Send the notifications 867 push->statements->Add(new MethodCall("pushEvent", 2, 868 new StringLiteralExpression(method->name.data), 869 new MethodCall(_data, "serialize"))); 870 871 // == the event callback dispatcher method ==================================== 872 presenterClass->AddMethod(method); 873 874 // == the event method in the listener base class ===================== 875 Method* event = new Method; 876 event->modifiers = PUBLIC; 877 event->name = method->name.data; 878 event->statements = new StatementBlock; 879 event->returnType = VOID_TYPE; 880 listenerClass->elements.push_back(event); 881 arg = method->args; 882 while (arg != NULL) { 883 event->parameters.push_back(new Variable( 884 NAMES.Search(arg->type.type.data), arg->name.data, 885 arg->type.dimension)); 886 arg = arg->next; 887 } 888 889 // Add a final parameter: RpcContext. Contains data about 890 // incoming request (e.g., certificate) 891 event->parameters.push_back(new Variable(RPC_CONTEXT_TYPE, "context", 0)); 892} 893 894static void 895generate_listener_methods(RpcProxyClass* proxyClass, Type* presenterType, Type* listenerType) 896{ 897 // AndroidAtHomePresenter _presenter; 898 // void startListening(Listener listener) { 899 // stopListening(); 900 // _presenter = new Presenter(_broker, listener); 901 // _presenter.startListening(_endpoint); 902 // } 903 // void stopListening() { 904 // if (_presenter != null) { 905 // _presenter.stopListening(); 906 // } 907 // } 908 909 Variable* _presenter = new Variable(presenterType, "_presenter"); 910 proxyClass->elements.push_back(new Field(PRIVATE, _presenter)); 911 912 Variable* listener = new Variable(listenerType, "listener"); 913 914 Method* startListeningMethod = new Method; 915 startListeningMethod->modifiers = PUBLIC; 916 startListeningMethod->returnType = VOID_TYPE; 917 startListeningMethod->name = "startListening"; 918 startListeningMethod->statements = new StatementBlock; 919 startListeningMethod->parameters.push_back(listener); 920 proxyClass->elements.push_back(startListeningMethod); 921 922 startListeningMethod->statements->Add(new MethodCall(THIS_VALUE, "stopListening")); 923 startListeningMethod->statements->Add(new Assignment(_presenter, 924 new NewExpression(presenterType, 2, proxyClass->broker, listener))); 925 startListeningMethod->statements->Add(new MethodCall(_presenter, 926 "startListening", 1, proxyClass->endpoint)); 927 928 Method* stopListeningMethod = new Method; 929 stopListeningMethod->modifiers = PUBLIC; 930 stopListeningMethod->returnType = VOID_TYPE; 931 stopListeningMethod->name = "stopListening"; 932 stopListeningMethod->statements = new StatementBlock; 933 proxyClass->elements.push_back(stopListeningMethod); 934 935 IfStatement* ifst = new IfStatement; 936 ifst->expression = new Comparison(_presenter, "!=", NULL_VALUE); 937 stopListeningMethod->statements->Add(ifst); 938 939 ifst->statements->Add(new MethodCall(_presenter, "stopListening")); 940 ifst->statements->Add(new Assignment(_presenter, NULL_VALUE)); 941} 942 943Class* 944generate_rpc_interface_class(const interface_type* iface) 945{ 946 // the proxy class 947 InterfaceType* interfaceType = static_cast<InterfaceType*>( 948 NAMES.Find(iface->package, iface->name.data)); 949 RpcProxyClass* proxy = new RpcProxyClass(iface, interfaceType); 950 951 // the listener class 952 ListenerClass* listener = new ListenerClass(iface); 953 954 // the presenter class 955 EventListenerClass* presenter = new EventListenerClass(iface, listener->type); 956 957 // the service base class 958 EndpointBaseClass* base = new EndpointBaseClass(iface); 959 proxy->elements.push_back(base); 960 961 // the result dispatcher 962 ResultDispatcherClass* results = new ResultDispatcherClass(); 963 964 // all the declared methods of the proxy 965 int index = 0; 966 interface_item_type* item = iface->interface_items; 967 while (item != NULL) { 968 if (item->item_type == METHOD_TYPE) { 969 if (NAMES.Search(((method_type*)item)->type.type.data) == EVENT_FAKE_TYPE) { 970 generate_event_method((method_type*)item, proxy, base, listener, presenter, index); 971 } else { 972 generate_regular_method((method_type*)item, proxy, base, results, index); 973 } 974 } 975 item = item->next; 976 index++; 977 } 978 presenter->DoneWithMethods(); 979 base->DoneWithMethods(); 980 981 // only add this if there are methods with results / out parameters 982 if (results->needed) { 983 proxy->elements.push_back(results); 984 } 985 if (listener->needed) { 986 proxy->elements.push_back(listener); 987 proxy->elements.push_back(presenter); 988 generate_listener_methods(proxy, presenter->type, listener->type); 989 } 990 991 return proxy; 992} 993