4aa33693611f25f85e4f4ffabadc4586c785c32f
[Evergreen.git] / OpenSRF / src / libstack / osrf_application.c
1 #include "osrf_application.h"
2 #include "osrf_log.h"
3 #include "objson/object.h"
4
5 osrfApplication* __osrfAppList = NULL; 
6
7
8 int osrfAppRegisterApplication( char* appName, char* soFile ) {
9         if(!appName || ! soFile) return -1;
10         char* error;
11
12         info_handler("Registering application %s with file %s", appName, soFile );
13
14         osrfApplication* app = safe_malloc(sizeof(osrfApplication));
15         app->handle = dlopen (soFile, RTLD_NOW);
16
17         if(!app->handle) {
18                 warning_handler("Failed to dlopen library file %s: %s", soFile, dlerror() );
19                 dlerror(); /* clear the error */
20                 free(app);
21                 return -1;
22         }
23
24         app->name = strdup(appName);
25
26         /* this has to be done before initting the application */
27         app->next = __osrfAppList;
28         __osrfAppList = app;
29
30
31         /* see if we can run the initialize method */
32         int (*init) (void);
33         *(void **) (&init) = dlsym(app->handle, "osrfAppInitialize");
34
35         if( (error = dlerror()) != NULL ) {
36                 warning_handler("! Unable to locate method symbol [osrfAppInitialize] for app %s: %s", appName, error );
37
38         } else {
39
40                 /* run the method */
41                 int ret;
42                 if( (ret = (*init)()) ) {
43                         warning_handler("Application %s returned non-zero value from "
44                                         "'osrfAppInitialize', not registering...", appName );
45                         //free(app->name); /* need a method to remove an application from the list */
46                         //free(app);
47                         return ret;
48                 }
49         }
50
51
52         info_handler("Application %s registered successfully", appName );
53
54
55         return 0;
56 }
57
58
59 int osrfAppRegisterMethod( char* appName, 
60                 char* methodName, char* symbolName, char* notes, int argc ) {
61         if( !appName || ! methodName || ! symbolName ) return -1;
62
63         osrfApplication* app = _osrfAppFindApplication(appName);
64         if(!app) return warning_handler("Unable to locate application %s", appName );
65
66         debug_handler("Registering method %s for app %s", appName, methodName );
67
68         osrfMethod* method = safe_malloc(sizeof(osrfMethod));
69         method->name = strdup(methodName);
70         method->symbol = strdup(symbolName);
71         if(notes) method->notes = strdup(notes);
72         method->argc = argc;
73
74         /* plug the method into the list of methods */
75         method->next = app->methods;
76         app->methods = method;
77         return 0;
78 }
79
80 osrfApplication* _osrfAppFindApplication( char* name ) {
81         if(!name) return NULL;
82         osrfApplication* app = __osrfAppList;
83         while(app) {
84                 if(!strcmp(app->name, name))
85                         return app;
86                 app = app->next;
87         }
88         return NULL;
89 }
90
91 osrfMethod* __osrfAppFindMethod( osrfApplication* app, char* methodName ) {
92         if(!app || ! methodName) return NULL;
93         osrfMethod* method = app->methods;
94         while(method) {
95                 if(!strcmp(method->name, methodName))
96                         return method;
97                 method = method->next;
98         }
99         return NULL;
100 }
101
102 osrfMethod* _osrfAppFindMethod( char* appName, char* methodName ) {
103         if(!appName || ! methodName) return NULL;
104         return __osrfAppFindMethod( _osrfAppFindApplication(appName), methodName );
105 }
106
107
108
109
110 int osrfAppRunMethod( char* appName, char* methodName, osrfAppSession* ses, int reqId, jsonObject* params ) {
111         if( !(appName && methodName && ses) ) return -1;
112
113         char* error;
114         osrfApplication* app;
115         osrfMethod* method;
116         osrfMethodContext context;
117
118         context.session = ses;
119         context.params = params;
120         context.request = reqId;
121
122         /* this is the method we're gonna run */
123         int (*meth) (osrfMethodContext*);       
124
125         info_handler("Running method [%s] for app [%s] with request id %d and "
126                         "thread trace %s", methodName, appName, reqId, ses->session_id );
127
128         if( !(app = _osrfAppFindApplication(appName)) )
129                 return warning_handler( "Application not found: %s", appName );
130
131         
132         if( !(method = __osrfAppFindMethod( app, methodName )) ) {
133                 /* see if the unfound method is a system method */
134                 info_handler("Method %s not found, checking to see if it's a system method...", methodName );
135                 osrfMethod meth;
136                 meth.name = methodName;
137                 context.method = &meth;
138                 int sysres = __osrfAppRunSystemMethod(&context);
139                 if(sysres == 0) return 0;
140                 if(sysres > 0) {
141                         osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  "osrfConnectStatus", reqId, "Request Complete" );
142                         return 0;
143                 }
144                 return warning_handler( "NOT FOUND: app %s / method %s", appName, methodName );
145         }
146
147
148         context.method = method;
149         
150         /* open the method */
151         *(void **) (&meth) = dlsym(app->handle, method->symbol);
152
153         if( (error = dlerror()) != NULL ) {
154                 return warning_handler("Unable to locate method symbol [%s] "
155                                 "for method %s and app %s", method->symbol, method->name, app->name );
156         }
157
158         /* run the method */
159         int ret = (*meth) (&context);
160
161         debug_handler("method returned %d", ret );
162
163         if(ret == -1) {
164                 osrfAppSessionStatus( ses, OSRF_STATUS_INTERNALSERVERERROR,  
165                         "Server Error", reqId, "An unknown server error occurred" );
166                 return -1;
167         }
168
169         if( ret > 0 ) 
170                 osrfAppSessionStatus( ses, OSRF_STATUS_COMPLETE,  "osrfConnectStatus", reqId, "Request Complete" );
171
172         return 0;
173 }
174
175
176
177 int __osrfAppRunSystemMethod(osrfMethodContext* ctx) {
178         OSRF_METHOD_VERIFY_CONTEXT(ctx);
179
180         if( !strcmp(ctx->method->name, OSRF_SYSMETHOD_INTROSPECT_ALL )) {
181
182                 jsonObject* resp = NULL;
183                 osrfApplication* app = _osrfAppFindApplication( ctx->session->remote_service );
184                 if(app) {
185                         osrfMethod* method = app->methods;
186                         while(method) {
187                                 resp = jsonNewObject(NULL);
188                                 jsonObjectSetKey(resp, "api_name", jsonNewObject(method->name));
189                                 jsonObjectSetKey(resp, "method", jsonNewObject(method->symbol));
190                                 jsonObjectSetKey(resp, "service", jsonNewObject(ctx->session->remote_service));
191                                 jsonObjectSetKey(resp, "notes", jsonNewObject(method->notes));
192                                 jsonObjectSetKey(resp, "argc", jsonNewNumberObject(method->argc));
193                                 osrfAppRequestRespond(ctx->session, ctx->request, resp);
194                                 method = method->next;
195                                 jsonObjectSetClass(resp, "method");
196                                 jsonObjectFree(resp);
197                         }
198                         return 1;
199                 }
200
201                 return -1;
202         }
203
204         return -1;
205 }
206
207
208
209