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