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