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