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
format_int(int n)39 format_int(int n)
40 {
41 char str[20];
42 sprintf(str, "%d", n);
43 return string(str);
44 }
45
46 static string
class_name_leaf(const string & str)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
results_class_name(const string & n)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
results_method_name(const string & n)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
push_method_name(const string & n)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
DispatcherClass(const interface_type * iface,Expression * target)108 DispatcherClass::DispatcherClass(const interface_type* iface, Expression* target)
109 :Class(),
110 dispatchIfStatement(NULL),
111 targetExpression(target)
112 {
113 generate_process();
114 }
115
~DispatcherClass()116 DispatcherClass::~DispatcherClass()
117 {
118 }
119
120 void
generate_process()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
AddMethod(const method_type * method)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
DoneWithMethods()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
RpcProxyClass(const interface_type * iface,InterfaceType * interfaceType)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
~RpcProxyClass()321 RpcProxyClass::~RpcProxyClass()
322 {
323 }
324
325 void
generate_ctor()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
generate_get_endpoint_info()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*
generate_get_listener_expression(Type * cast)369 generate_get_listener_expression(Type* cast)
370 {
371 return new Cast(cast, new MethodCall(THIS_VALUE, "getView"));
372 }
373
EventListenerClass(const interface_type * iface,Type * listenerType)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
~EventListenerClass()391 EventListenerClass::~EventListenerClass()
392 {
393 }
394
395 void
generate_ctor()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
ListenerClass(const interface_type * iface)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
~ListenerClass()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
EndpointBaseClass(const interface_type * iface)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
~EndpointBaseClass()471 EndpointBaseClass::~EndpointBaseClass()
472 {
473 }
474
475 void
generate_ctor()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
ResultDispatcherClass()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
~ResultDispatcherClass()534 ResultDispatcherClass::~ResultDispatcherClass()
535 {
536 }
537
538 void
generate_ctor()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
generate_onResult()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
AddMethod(int index,const string & name,Method ** method,Variable ** param)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
generate_new_array(Type * t,StatementBlock * addTo,Variable * v,Variable * from)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
generate_create_from_data(Type * t,StatementBlock * addTo,const string & key,Variable * v,Variable * data,Variable ** cl)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
generate_write_to_data(Type * t,StatementBlock * addTo,Expression * k,Variable * v,Variable * data)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*
generate_results_method(const method_type * method,RpcProxyClass * proxyClass)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
generate_proxy_method(const method_type * method,RpcProxyClass * proxyClass,ResultDispatcherClass * resultsDispatcherClass,Type * resultsInterfaceType,int index)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
generate_result_dispatcher_method(const method_type * method,ResultDispatcherClass * resultsDispatcherClass,Type * resultsInterfaceType,int index)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
generate_regular_method(const method_type * method,RpcProxyClass * proxyClass,EndpointBaseClass * serviceBaseClass,ResultDispatcherClass * resultsDispatcherClass,int index)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
generate_event_method(const method_type * method,RpcProxyClass * proxyClass,EndpointBaseClass * serviceBaseClass,ListenerClass * listenerClass,EventListenerClass * presenterClass,int index)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
generate_listener_methods(RpcProxyClass * proxyClass,Type * presenterType,Type * listenerType)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*
generate_rpc_interface_class(const interface_type * iface)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