external_objects_java: fix crash on ScilabJavaEnvironment when used as a local variable
[scilab.git] / scilab / modules / external_objects_java / src / cpp / ScilabJavaEnvironment.hxx
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #ifndef __SCILABPYTHONENVIRNOMENT_HXX__
14 #define __SCILABPYTHONENVIRNOMENT_HXX__
15
16 #ifdef _MSC_VER
17 #define PATHSEPARATOR ";"
18 #else
19 #define PATHSEPARATOR ":"
20 #endif
21
22 extern "C"
23 {
24 #include "dynlib_external_objects_java_scilab.h"
25 #include <jni.h>
26 #ifdef _MSC_VER
27 #include <Windows.h>
28 #include "strdup_windows.h"
29 #endif
30 }
31
32 //#include "PythonVariablesScope.hxx"
33 #include "ScilabAbstractEnvironment.hxx"
34 #include "ScilabEnvironments.hxx"
35 #include "ScilabJavaException.hxx"
36 #include "ScilabJavaEnvironmentWrapper.hxx"
37 // #include "ScilabPythonInvokers.hxx"
38 #include "JavaOptionsHelper.hxx"
39 #include "ScilabStream.hxx"
40 //#include "ScilabPythonOStream.hxx"
41
42 #include <sstream>
43 #include <iostream>
44 #include <fstream>
45 #include <map>
46 #include <vector>
47 #include <string>
48
49
50 // #if defined(PIMS_EXPORTS)
51 // #pragma message("defined(PIMS_EXPORTS)")
52 // #else
53 // #pragma message("Houston !")
54 // #endif
55 #define LOG_BUFFER_SIZE 4096
56
57 using namespace org_modules_external_objects;
58
59 namespace org_scilab_modules_external_objects_java
60 {
61
62 class EXTERNAL_OBJECTS_JAVA_SCILAB_IMPEXP ScilabJavaEnvironment : public ScilabAbstractEnvironment
63 {
64     static const std::string environmentName;
65     static int envId;
66     static ScilabJavaEnvironment * instance;
67     static bool usable;
68
69     //    PythonVariablesScope & scope;
70     bool traceEnabled;
71     bool isInit;
72     ScilabStream & scilabStream;
73     JavaOptionsHelper & helper;
74     ScilabGatewayOptions & gwOptions;
75     ScilabJavaEnvironmentWrapper & wrapper;
76
77 public :
78
79     ScilabJavaEnvironment();
80
81     ~ScilabJavaEnvironment();
82     /*
83         ScilabJavaTupleInvoker getTupleInvoker()
84         {
85             return ScilabJavaTupleInvoker(scope);
86         }
87
88         ScilabJavaDictionaryInvoker getDictionaryInvoker()
89         {
90             return ScilabJavaDictionaryInvoker(scope);
91         }
92
93         ScilabJavaListInvoker getListInvoker()
94         {
95             return ScilabJavaListInvoker(scope);
96         }
97
98         ScilabJavaSetInvoker getSetInvoker()
99         {
100             return ScilabJavaSetInvoker(scope);
101         }
102
103         ScilabJavaGetAttrInvoker getGetAttrInvoker()
104         {
105             return ScilabJavaGetAttrInvoker(scope);
106         }
107
108         ScilabJavaInvokeInvoker getInvokeInvoker()
109         {
110             return ScilabJavaInvokeInvoker(scope);
111         }
112
113         ScilabJavaBuiltinInvoker getBuiltinInvoker(const std::string & name)
114         {
115             return ScilabJavaBuiltinInvoker(scope, name);
116         }
117
118         ScilabJavaModuleInvoker getModuleInvoker(const std::string & name)
119         {
120             return ScilabJavaModuleInvoker(scope, name);
121             }*/
122
123     void Initialize();
124
125     void Finalize();
126
127     static int start();
128
129     static void finish();
130
131     static ScilabJavaEnvironment* getInstance()
132     {
133         return instance;
134     }
135
136     JavaOptionsHelper & getOptionsHelper();
137
138     ScilabGatewayOptions & getGatewayOptions();
139
140     ScilabAbstractEnvironmentWrapper & getWrapper();
141
142     const std::string & getEnvironmentName();
143
144     int extract(int id, int * args, int argsSize);
145
146     void insert(int id, int * args, int argsSize);
147
148     void addNamedVariable(int id, const char * varName);
149
150     int getNamedVariable(const char * varName);
151
152     void evalString(const char ** code, int nbLines, ScilabStringStackAllocator * allocator);
153
154     void getEnvironmentInfos(const ScilabStringStackAllocator & allocator);
155
156     void garbagecollect();
157
158     void addtoclasspath(const char * path);
159
160     void getclasspath(const ScilabStringStackAllocator & allocator);
161
162     int createarray(char * className, int * dims, int len);
163
164     int loadclass(char * className, char * currentSciPath, bool isNamedVarCreated, bool allowReload);
165
166     void getrepresentation(int id, const ScilabStringStackAllocator & allocator);
167
168     std::string getrepresentation(int id);
169
170     bool isvalidobject(int id);
171
172     int newinstance(int id, int * args, int argsSize);
173
174     int operation(int idA, int idB, const OperatorsType type);
175
176     int * invoke(int id, const char * methodName, int * args, int argsSize);
177
178     void setfield(int id, const char * fieldName, int idarg);
179
180     int getfield(int id, const char * fieldName);
181
182     int getfieldtype(int id, const char * fieldName);
183
184     int getarrayelement(int id, int * index, int length);
185
186     void setarrayelement(int id, int * index, int length, int idArg);
187
188     int cast(int id, char * className);
189
190     int castwithid(int id, int classId);
191
192     void removeobject(int id);
193
194     void removeobject(const int * id, const int length);
195
196     void autoremoveobject(int id);
197
198     void getaccessiblemethods(int id, const ScilabStringStackAllocator & allocator);
199
200     void getaccessiblefields(int id, const ScilabStringStackAllocator & allocator);
201
202     std::vector<std::string> getCompletion(int id, char ** fieldPath, const int fieldPathLen);
203
204     std::string getclassname(int id);
205
206     VariableType isunwrappable(int id);
207
208     int compilecode(char * className, char ** code, int size);
209
210     void enabletrace(const char * filename);
211
212     void disabletrace();
213
214     void writeLog(const std::string & fun, const std::string str, ...) const;
215
216     inline int getEnvId() const
217     {
218         return envId;
219     }
220
221     inline bool isTraceEnabled() const
222     {
223         return traceEnabled;
224     }
225
226     /*    static inline std::wstring getWString(PyObject * obj)
227           {
228             if (PyString_Check(obj))
229             {
230                 int len = PyString_GET_SIZE(obj);
231                 char * str = PyString_AsString(obj);
232
233                 return std::wstring(str, str + len);
234             }
235             else if (PyUnicode_Check(obj))
236             {
237                 return std::wstring(reinterpret_cast<const wchar_t *>(PyUnicode_AS_DATA(obj)));
238             }
239
240             throw ScilabJavaException(__LINE__, __FILE__, gettext("Cannot convert in a wide string"));
241             } */
242
243 private:
244
245     //    static void initNumpy();
246
247     void getMethodResult(JavaVM * jvm_, const char * const methodName, int id, const ScilabStringStackAllocator & allocator);
248
249     // template <typename T, typename U, class V> void unwrapMat(JavaVM * jvm_, const bool methodOfConv, const int javaID, const ScilabStringStackAllocator & allocator);
250     // template <typename T, typename U, class V> void unwrapRow(JavaVM * jvm_, const bool methodOfConv, const int javaID, const ScilabStringStackAllocator & allocator);
251     // template <typename T, typename U, class V> void unwrapSingle(JavaVM * jvm_, const bool methodOfConv, const int javaID, const ScilabStringStackAllocator & allocator);
252
253
254     inline void getAccessibleFields(int id, const ScilabStringStackAllocator & allocator, const bool isField)
255     {
256
257         /*
258                 PyObject * obj = scope.getObject(id);
259                 if (!obj)
260                 {
261                     throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid object with id %d"), id);
262                 }
263
264                 PyObject * dir = PyObject_Dir(obj);
265                 if (!dir || PyList_Size(dir) == 0)
266                 {
267                     allocator.allocate(0, 0, static_cast<char **>(0));
268                     return;
269                 }
270
271                 int size = PyList_Size(dir);
272                 int j = 0;
273                 char ** arr = new char*[size];
274
275                 for (int i = 0; i < size; i++)
276                 {
277                     PyObject * fieldName = PyList_GetItem(dir, i);
278                     char * _field = PyString_AsString(fieldName);
279                     if (helper.getShowPrivate() || _field[0] != '_')
280                     {
281                         PyObject * field = PyObject_GetAttr(obj, fieldName);
282                         if (isField && !PyCallable_Check(field))
283                         {
284                             arr[j++] = _field;
285                         }
286                         else if (!isField && PyCallable_Check(field))
287                         {
288                             arr[j++] = _field;
289                         }
290                     }
291                 }
292
293                 allocator.allocate(j, 1, arr);
294                 delete[] arr;
295         */
296     }
297
298     // TODO => Ici
299     /*
300         static inline PyObject * createMultiList(const int * dims, const int len)
301         {
302             if (len == 0)
303             {
304                 return PyList_New(0);
305             }
306
307             if (len == 1)
308             {
309                 return PyList_New(dims[0]);
310             }
311
312             PyObject * list = PyList_New(dims[0]);
313             for (int i = 0; i < dims[0]; i++)
314             {
315                 PyList_SetItem(list, i, createMultiList(dims + 1, len - 1));
316             }
317
318             return list;
319         }
320     */
321
322     static inline std::vector<char *> breakInLines(const std::string & str)
323     {
324         std::vector<char *> buf;
325         std::size_t prev(0);
326         std::size_t pos = str.find_first_of("\n");
327         while (pos != std::string::npos)
328         {
329             buf.push_back(strdup(str.substr(prev, pos - prev).c_str()));
330             prev = pos + 1;
331             pos = str.find_first_of("\n", prev);
332         }
333         buf.push_back(strdup(str.substr(prev).c_str()));
334
335         std::vector<char *>::iterator last = buf.end();
336         for (std::vector<char *>::iterator i = buf.end() - 1; i >= buf.begin(); i--)
337         {
338             if (strlen(*i) == 0)
339             {
340                 last = i;
341                 free(*i);
342             }
343             else
344             {
345                 break;
346             }
347         }
348         buf.erase(last, buf.end());
349
350         return buf;
351     }
352
353     static inline const char * getOpNameFromType(const OperatorsType type)
354     {
355         switch (type)
356         {
357             case Transp :
358                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: \'"));
359             case Add :
360                 return "add";
361             case Sub :
362                 return "sub";
363             case Mul :
364                 return "mul";
365             case Div :
366                 return "div";
367             case Backslash :
368                 return "truediv";
369             case Pow :
370                 return "pow";
371             case DotMul :
372                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: .*"));
373             case DotDiv :
374                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: ./"));
375             case DotBackslash :
376                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: .\\"));
377             case DotMulDot :
378                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: .*."));
379             case DotDivDot :
380                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: ./."));
381             case DotBackslashDot :
382                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: .\\."));
383             case Eq :
384                 return "eq";
385             case Neq :
386                 return "ne";
387             case Or :
388                 return "or";
389             case And :
390                 return "and";
391             case DotPow :
392                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: .^"));
393             case Not :
394                 return "not_";
395             case DotTransp :
396                 throw ScilabJavaException(__LINE__, __FILE__, gettext("Invalid operator: .\'"));
397             case Lt :
398                 return "lt";
399             case Gt :
400                 return "gt";
401             case Leq :
402                 return "le";
403             case Geq :
404                 return "ge";
405         }
406
407         return "";
408     }
409 };
410
411 }
412
413 #endif // __SCILABJAVAENVIRONMENT_HXX__