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