~ubuntu-branches/ubuntu/trusty/mongodb/trusty-proposed

« back to all changes in this revision

Viewing changes to scripting/engine_java.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Antonin Kral
  • Date: 2010-01-29 19:48:45 UTC
  • Revision ID: james.westby@ubuntu.com-20100129194845-8wbmkf626fwcavc9
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// java.cpp
 
2
 
 
3
/*    Copyright 2009 10gen Inc.
 
4
 *
 
5
 *    Licensed under the Apache License, Version 2.0 (the "License");
 
6
 *    you may not use this file except in compliance with the License.
 
7
 *    You may obtain a copy of the License at
 
8
 *
 
9
 *    http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 *    Unless required by applicable law or agreed to in writing, software
 
12
 *    distributed under the License is distributed on an "AS IS" BASIS,
 
13
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 *    See the License for the specific language governing permissions and
 
15
 *    limitations under the License.
 
16
 */
 
17
 
 
18
 
 
19
#include "stdafx.h"
 
20
#include "engine_java.h"
 
21
#include <iostream>
 
22
#include <map>
 
23
#include <list>
 
24
 
 
25
#include "../db/jsobj.h"
 
26
#include "../db/db.h"
 
27
 
 
28
using namespace boost::filesystem;
 
29
 
 
30
namespace mongo {
 
31
 
 
32
//#define JNI_DEBUG 1
 
33
 
 
34
#ifdef JNI_DEBUG
 
35
#undef JNI_DEBUG
 
36
#define JNI_DEBUG(x) cout << x << endl
 
37
#else
 
38
#undef JNI_DEBUG
 
39
#define JNI_DEBUG(x)
 
40
#endif
 
41
 
 
42
} // namespace mongo
 
43
 
 
44
 
 
45
 
 
46
#include "../util/message.h"
 
47
#include "../db/db.h"
 
48
 
 
49
using namespace std;
 
50
 
 
51
namespace mongo {
 
52
 
 
53
#if defined(_WIN32)
 
54
    /* [dm] this being undefined without us adding it here means there is
 
55
            no tss cleanup on windows for boost lib?
 
56
            we don't care for now esp on windows only
 
57
 
 
58
                the boost source says:
 
59
 
 
60
                  This function's sole purpose is to cause a link error in cases where
 
61
                  automatic tss cleanup is not implemented by Boost.Threads as a
 
62
                  reminder that user code is responsible for calling the necessary
 
63
                  functions at the appropriate times (and for implementing an a
 
64
                  tss_cleanup_implemented() function to eliminate the linker's
 
65
                  missing symbol error).
 
66
 
 
67
                  If Boost.Threads later implements automatic tss cleanup in cases
 
68
                  where it currently doesn't (which is the plan), the duplicate
 
69
                  symbol error will warn the user that their custom solution is no
 
70
                  longer needed and can be removed.
 
71
    */
 
72
    extern "C" void tss_cleanup_implemented(void) {
 
73
        //out() << "tss_cleanup_implemented called" << endl;
 
74
    }
 
75
#endif
 
76
 
 
77
    JavaJSImpl * JavaJS = 0;
 
78
    extern string dbExecCommand;
 
79
 
 
80
#if !defined(NOJNI)
 
81
 
 
82
    void myJNIClean( JNIEnv * env ) {
 
83
        JavaJS->detach( env );
 
84
    }
 
85
 
 
86
#if defined(_WIN32)
 
87
    const char SYSTEM_COLON = ';';
 
88
#else
 
89
    const char SYSTEM_COLON = ':';
 
90
#endif
 
91
 
 
92
 
 
93
    void _addClassPath( const char * ed , stringstream & ss , const char * subdir ) {
 
94
        path includeDir(ed);
 
95
        includeDir /= subdir;
 
96
        directory_iterator end;
 
97
        try {
 
98
            directory_iterator i(includeDir);
 
99
            while ( i != end ) {
 
100
                path p = *i;
 
101
                ss << SYSTEM_COLON << p.string();
 
102
                i++;
 
103
            }
 
104
        }
 
105
        catch (...) {
 
106
            problem() << "exception looking for ed class path includeDir: " << includeDir.string() << endl;
 
107
            sleepsecs(3);
 
108
            dbexit( EXIT_JAVA );
 
109
        }
 
110
    }
 
111
 
 
112
 
 
113
    JavaJSImpl::JavaJSImpl(const char *appserverPath) {
 
114
        _jvm = 0;
 
115
        _mainEnv = 0;
 
116
        _dbhook = 0;
 
117
 
 
118
        stringstream ss;
 
119
        string edTemp;
 
120
 
 
121
        const char * ed = 0;
 
122
        ss << "-Djava.class.path=.";
 
123
 
 
124
        if ( appserverPath ) {
 
125
            ed = findEd(appserverPath);
 
126
            assert( ed );
 
127
 
 
128
            ss << SYSTEM_COLON << ed << "/build/";
 
129
 
 
130
            _addClassPath( ed , ss , "include" );
 
131
            _addClassPath( ed , ss , "include/jython/" );
 
132
            _addClassPath( ed , ss , "include/jython/javalib" );
 
133
        }
 
134
        else {
 
135
            const string jars = findJars();
 
136
            _addClassPath( jars.c_str() , ss , "jars" );
 
137
 
 
138
            edTemp += (string)jars + "/jars/mongojs-js.jar";
 
139
            ed = edTemp.c_str();
 
140
        }
 
141
 
 
142
 
 
143
 
 
144
#if defined(_WIN32)
 
145
        ss << SYSTEM_COLON << "C:\\Program Files\\Java\\jdk\\lib\\tools.jar";
 
146
#else
 
147
        ss << SYSTEM_COLON << "/opt/java/lib/tools.jar";
 
148
#endif
 
149
 
 
150
        if ( getenv( "CLASSPATH" ) )
 
151
            ss << SYSTEM_COLON << getenv( "CLASSPATH" );
 
152
 
 
153
        string s = ss.str();
 
154
        char * p = (char *)malloc( s.size() * 4 );
 
155
        strcpy( p , s.c_str() );
 
156
        char *q = p;
 
157
#if defined(_WIN32)
 
158
        while ( *p ) {
 
159
            if ( *p == '/' ) *p = '\\';
 
160
            p++;
 
161
        }
 
162
#endif
 
163
 
 
164
        log(1) << "classpath: " << q << endl;
 
165
 
 
166
        JavaVMOption * options = new JavaVMOption[4];
 
167
        options[0].optionString = q;
 
168
        options[1].optionString = (char*)"-Djava.awt.headless=true";
 
169
        options[2].optionString = (char*)"-Xmx300m";
 
170
 
 
171
        // Prevent JVM from using async signals internally, since on linux the pre-installed handlers for these
 
172
        // signals don't seem to be respected by JNI.
 
173
        options[3].optionString = (char*)"-Xrs";
 
174
        // -Xcheck:jni
 
175
 
 
176
        _vmArgs = new JavaVMInitArgs();
 
177
        _vmArgs->version = JNI_VERSION_1_4;
 
178
        _vmArgs->options = options;
 
179
        _vmArgs->nOptions = 4;
 
180
        _vmArgs->ignoreUnrecognized = JNI_FALSE;
 
181
 
 
182
        log(1) << "loading JVM" << endl;
 
183
        jint res = JNI_CreateJavaVM( &_jvm, (void**)&_mainEnv, _vmArgs );
 
184
 
 
185
        if ( res ) {
 
186
            log() << "using classpath: " << q << endl;
 
187
            log()
 
188
                << " res : " << (unsigned) res << " "
 
189
                << "_jvm : " << _jvm  << " "
 
190
                << "_env : " << _mainEnv << " "
 
191
                << endl;
 
192
            problem() << "Couldn't create JVM res:" << (int) res << " terminating" << endl;
 
193
            log() << "(try --nojni if you do not require that functionality)" << endl;
 
194
            exit(22);
 
195
        }
 
196
        jassert( res == 0 );
 
197
        jassert( _jvm > 0 );
 
198
        jassert( _mainEnv > 0 );
 
199
 
 
200
        _envs = new boost::thread_specific_ptr<JNIEnv>( myJNIClean );
 
201
        assert( ! _envs->get() );
 
202
        _envs->reset( _mainEnv );
 
203
 
 
204
        _dbhook = findClass( "ed/db/JSHook" );
 
205
        if ( _dbhook == 0 ) {
 
206
            log() << "using classpath: " << q << endl;
 
207
            printException();
 
208
        }
 
209
        jassert( _dbhook );
 
210
 
 
211
        if ( ed ) {
 
212
            jmethodID init = _mainEnv->GetStaticMethodID( _dbhook ,  "init" , "(Ljava/lang/String;)V" );
 
213
            jassert( init );
 
214
            _mainEnv->CallStaticVoidMethod( _dbhook , init , _getEnv()->NewStringUTF( ed ) );
 
215
        }
 
216
 
 
217
        _dbjni = findClass( "ed/db/DBJni" );
 
218
        jassert( _dbjni );
 
219
 
 
220
        _scopeCreate = _mainEnv->GetStaticMethodID( _dbhook , "scopeCreate" , "()J" );
 
221
        _scopeInit = _mainEnv->GetStaticMethodID( _dbhook , "scopeInit" , "(JLjava/nio/ByteBuffer;)Z" );
 
222
        _scopeSetThis = _mainEnv->GetStaticMethodID( _dbhook , "scopeSetThis" , "(JLjava/nio/ByteBuffer;)Z" );
 
223
        _scopeReset = _mainEnv->GetStaticMethodID( _dbhook , "scopeReset" , "(J)Z" );
 
224
        _scopeFree = _mainEnv->GetStaticMethodID( _dbhook , "scopeFree" , "(J)V" );
 
225
 
 
226
        _scopeGetNumber = _mainEnv->GetStaticMethodID( _dbhook , "scopeGetNumber" , "(JLjava/lang/String;)D" );
 
227
        _scopeGetString = _mainEnv->GetStaticMethodID( _dbhook , "scopeGetString" , "(JLjava/lang/String;)Ljava/lang/String;" );
 
228
        _scopeGetBoolean = _mainEnv->GetStaticMethodID( _dbhook , "scopeGetBoolean" , "(JLjava/lang/String;)Z" );
 
229
        _scopeGetType = _mainEnv->GetStaticMethodID( _dbhook , "scopeGetType" , "(JLjava/lang/String;)B" );
 
230
        _scopeGetObject = _mainEnv->GetStaticMethodID( _dbhook , "scopeGetObject" , "(JLjava/lang/String;Ljava/nio/ByteBuffer;)I" );
 
231
        _scopeGuessObjectSize = _mainEnv->GetStaticMethodID( _dbhook , "scopeGuessObjectSize" , "(JLjava/lang/String;)J" );
 
232
 
 
233
        _scopeSetNumber = _mainEnv->GetStaticMethodID( _dbhook , "scopeSetNumber" , "(JLjava/lang/String;D)Z" );
 
234
        _scopeSetBoolean = _mainEnv->GetStaticMethodID( _dbhook , "scopeSetBoolean" , "(JLjava/lang/String;Z)Z" );
 
235
        _scopeSetString = _mainEnv->GetStaticMethodID( _dbhook , "scopeSetString" , "(JLjava/lang/String;Ljava/lang/String;)Z" );
 
236
        _scopeSetObject = _mainEnv->GetStaticMethodID( _dbhook , "scopeSetObject" , "(JLjava/lang/String;Ljava/nio/ByteBuffer;)Z" );
 
237
 
 
238
        _functionCreate = _mainEnv->GetStaticMethodID( _dbhook , "functionCreate" , "(Ljava/lang/String;)J" );
 
239
        _invoke = _mainEnv->GetStaticMethodID( _dbhook , "invoke" , "(JJ)I" );
 
240
 
 
241
        jassert( _scopeCreate );
 
242
        jassert( _scopeInit );
 
243
        jassert( _scopeSetThis );
 
244
        jassert( _scopeReset );
 
245
        jassert( _scopeFree );
 
246
 
 
247
        jassert( _scopeGetNumber );
 
248
        jassert( _scopeGetString );
 
249
        jassert( _scopeGetObject );
 
250
        jassert( _scopeGetBoolean );
 
251
        jassert( _scopeGetType );
 
252
        jassert( _scopeGuessObjectSize );
 
253
 
 
254
        jassert( _scopeSetNumber );
 
255
        jassert( _scopeSetBoolean );
 
256
        jassert( _scopeSetString );
 
257
        jassert( _scopeSetObject );
 
258
 
 
259
        jassert( _functionCreate );
 
260
        jassert( _invoke );
 
261
 
 
262
        JNINativeMethod * nativeSay = new JNINativeMethod();
 
263
        nativeSay->name = (char*)"native_say";
 
264
        nativeSay->signature = (char*)"(Ljava/nio/ByteBuffer;)V";
 
265
        nativeSay->fnPtr = (void*)java_native_say;
 
266
        _mainEnv->RegisterNatives( _dbjni , nativeSay , 1 );
 
267
 
 
268
 
 
269
        JNINativeMethod * nativeCall = new JNINativeMethod();
 
270
        nativeCall->name = (char*)"native_call";
 
271
        nativeCall->signature = (char*)"(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I";
 
272
        nativeCall->fnPtr = (void*)java_native_call;
 
273
        _mainEnv->RegisterNatives( _dbjni , nativeCall , 1 );
 
274
 
 
275
    }
 
276
 
 
277
    JavaJSImpl::~JavaJSImpl() {
 
278
        if ( _jvm ) {
 
279
            _jvm->DestroyJavaVM();
 
280
            cout << "Destroying JVM" << endl;
 
281
        }
 
282
    }
 
283
 
 
284
// scope
 
285
 
 
286
    jlong JavaJSImpl::scopeCreate() {
 
287
        return _getEnv()->CallStaticLongMethod( _dbhook , _scopeCreate );
 
288
    }
 
289
 
 
290
    jboolean JavaJSImpl::scopeReset( jlong id ) {
 
291
        return _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeReset );
 
292
    }
 
293
 
 
294
    void JavaJSImpl::scopeFree( jlong id ) {
 
295
        _getEnv()->CallStaticVoidMethod( _dbhook , _scopeFree , id );
 
296
    }
 
297
 
 
298
// scope setters
 
299
 
 
300
    int JavaJSImpl::scopeSetBoolean( jlong id , const char * field , jboolean val ) {
 
301
        jstring fieldString = _getEnv()->NewStringUTF( field );
 
302
        int res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeSetNumber , id , fieldString  , val );
 
303
        _getEnv()->DeleteLocalRef( fieldString );
 
304
        return res;
 
305
    }
 
306
 
 
307
    int JavaJSImpl::scopeSetNumber( jlong id , const char * field , double val ) {
 
308
        jstring fieldString = _getEnv()->NewStringUTF( field );
 
309
        int res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeSetNumber , id , fieldString , val );
 
310
        _getEnv()->DeleteLocalRef( fieldString );
 
311
        return res;
 
312
    }
 
313
 
 
314
    int JavaJSImpl::scopeSetString( jlong id , const char * field , const char * val ) {
 
315
        jstring s1 = _getEnv()->NewStringUTF( field );
 
316
        jstring s2 = _getEnv()->NewStringUTF( val );
 
317
        int res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeSetString , id , s1 , s2 );
 
318
        _getEnv()->DeleteLocalRef( s1 );
 
319
        _getEnv()->DeleteLocalRef( s2 );
 
320
        return res;
 
321
    }
 
322
 
 
323
    int JavaJSImpl::scopeSetObject( jlong id , const char * field , const BSONObj * obj ) {
 
324
        jobject bb = 0;
 
325
        if ( obj ) {
 
326
            bb = _getEnv()->NewDirectByteBuffer( (void*)(obj->objdata()) , (jlong)(obj->objsize()) );
 
327
            jassert( bb );
 
328
        }
 
329
 
 
330
        jstring s1 = _getEnv()->NewStringUTF( field );
 
331
        int res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeSetObject , id , s1 , bb );
 
332
        _getEnv()->DeleteLocalRef( s1 );
 
333
        if ( bb )
 
334
            _getEnv()->DeleteLocalRef( bb );
 
335
 
 
336
        return res;
 
337
    }
 
338
 
 
339
    int JavaJSImpl::scopeInit( jlong id , const BSONObj * obj ) {
 
340
        if ( ! obj )
 
341
            return 0;
 
342
 
 
343
        jobject bb = _getEnv()->NewDirectByteBuffer( (void*)(obj->objdata()) , (jlong)(obj->objsize()) );
 
344
        jassert( bb );
 
345
 
 
346
        int res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeInit , id , bb );
 
347
        _getEnv()->DeleteLocalRef( bb );
 
348
        return res;
 
349
    }
 
350
 
 
351
    int JavaJSImpl::scopeSetThis( jlong id , const BSONObj * obj ) {
 
352
        if ( ! obj )
 
353
            return 0;
 
354
 
 
355
        jobject bb = _getEnv()->NewDirectByteBuffer( (void*)(obj->objdata()) , (jlong)(obj->objsize()) );
 
356
        jassert( bb );
 
357
 
 
358
        int res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeSetThis , id , bb );
 
359
        _getEnv()->DeleteLocalRef( bb );
 
360
        return res;
 
361
    }
 
362
 
 
363
// scope getters
 
364
 
 
365
    char JavaJSImpl::scopeGetType( jlong id , const char * field ) {
 
366
        jstring s1 = _getEnv()->NewStringUTF( field );
 
367
        int res =_getEnv()->CallStaticByteMethod( _dbhook , _scopeGetType , id , s1 );
 
368
        _getEnv()->DeleteLocalRef( s1 );
 
369
        return res;
 
370
    }
 
371
 
 
372
    double JavaJSImpl::scopeGetNumber( jlong id , const char * field ) {
 
373
        jstring s1 = _getEnv()->NewStringUTF( field );
 
374
        double res = _getEnv()->CallStaticDoubleMethod( _dbhook , _scopeGetNumber , id , s1 );
 
375
        _getEnv()->DeleteLocalRef( s1 );
 
376
        return res;
 
377
    }
 
378
 
 
379
    jboolean JavaJSImpl::scopeGetBoolean( jlong id , const char * field ) {
 
380
        jstring s1 = _getEnv()->NewStringUTF( field );
 
381
        jboolean res = _getEnv()->CallStaticBooleanMethod( _dbhook , _scopeGetBoolean , id , s1 );
 
382
        _getEnv()->DeleteLocalRef( s1 );
 
383
        return res;
 
384
    }
 
385
 
 
386
    string JavaJSImpl::scopeGetString( jlong id , const char * field ) {
 
387
        jstring s1 = _getEnv()->NewStringUTF( field );
 
388
        jstring s = (jstring)_getEnv()->CallStaticObjectMethod( _dbhook , _scopeGetString , id , s1 );
 
389
        _getEnv()->DeleteLocalRef( s1 );
 
390
 
 
391
        if ( ! s )
 
392
            return "";
 
393
 
 
394
        const char * c = _getEnv()->GetStringUTFChars( s , 0 );
 
395
        string retStr(c);
 
396
        _getEnv()->ReleaseStringUTFChars( s , c );
 
397
        return retStr;
 
398
    }
 
399
 
 
400
    BSONObj JavaJSImpl::scopeGetObject( jlong id , const char * field )
 
401
    {
 
402
        jstring s1 = _getEnv()->NewStringUTF( field );
 
403
        int guess = _getEnv()->CallStaticIntMethod( _dbhook , _scopeGuessObjectSize , id , _getEnv()->NewStringUTF( field ) );
 
404
        _getEnv()->DeleteLocalRef( s1 );
 
405
        
 
406
        if ( guess == 0 )
 
407
            return BSONObj();
 
408
 
 
409
        char * buf = (char *) malloc(guess);
 
410
        jobject bb = _getEnv()->NewDirectByteBuffer( (void*)buf , guess );
 
411
        jassert( bb );
 
412
 
 
413
        int len = _getEnv()->CallStaticIntMethod( _dbhook , _scopeGetObject , id , _getEnv()->NewStringUTF( field ) , bb );
 
414
        _getEnv()->DeleteLocalRef( bb );
 
415
        jassert( len > 0 && len < guess );
 
416
 
 
417
        BSONObj obj(buf, true);
 
418
        assert( obj.objsize() <= guess );
 
419
        return obj;
 
420
    }
 
421
 
 
422
// other
 
423
 
 
424
    jlong JavaJSImpl::functionCreate( const char * code ) {
 
425
        jstring s = _getEnv()->NewStringUTF( code );
 
426
        jassert( s );
 
427
        jlong id = _getEnv()->CallStaticLongMethod( _dbhook , _functionCreate , s );
 
428
        _getEnv()->DeleteLocalRef( s );
 
429
        return id;
 
430
    }
 
431
 
 
432
    int JavaJSImpl::invoke( jlong scope , jlong function ) {
 
433
        return _getEnv()->CallStaticIntMethod( _dbhook , _invoke , scope , function );
 
434
    }
 
435
 
 
436
// --- fun run method
 
437
 
 
438
    void JavaJSImpl::run( const char * js ) {
 
439
        jclass c = findClass( "ed/js/JS" );
 
440
        jassert( c );
 
441
 
 
442
        jmethodID m = _getEnv()->GetStaticMethodID( c , "eval" , "(Ljava/lang/String;)Ljava/lang/Object;" );
 
443
        jassert( m );
 
444
 
 
445
        jstring s = _getEnv()->NewStringUTF( js );
 
446
        log() << _getEnv()->CallStaticObjectMethod( c , m , s ) << endl;
 
447
        _getEnv()->DeleteLocalRef( s );
 
448
    }
 
449
 
 
450
    void JavaJSImpl::printException() {
 
451
        jthrowable exc = _getEnv()->ExceptionOccurred();
 
452
        if ( exc ) {
 
453
            _getEnv()->ExceptionDescribe();
 
454
            _getEnv()->ExceptionClear();
 
455
        }
 
456
 
 
457
    }
 
458
 
 
459
    JNIEnv * JavaJSImpl::_getEnv() {
 
460
        JNIEnv * env = _envs->get();
 
461
        if ( env )
 
462
            return env;
 
463
 
 
464
        int res = _jvm->AttachCurrentThread( (void**)&env , (void*)&_vmArgs );
 
465
        if ( res ) {
 
466
            out() << "ERROR javajs attachcurrentthread fails res:" << res << '\n';
 
467
            assert(false);
 
468
        }
 
469
 
 
470
        _envs->reset( env );
 
471
        return env;
 
472
    }
 
473
 
 
474
    Scope * JavaJSImpl::createScope(){
 
475
        return new JavaScope();
 
476
    }
 
477
 
 
478
    void ScriptEngine::setup(){
 
479
        if ( ! JavaJS ){
 
480
            JavaJS = new JavaJSImpl();
 
481
            globalScriptEngine = JavaJS;
 
482
        }
 
483
    }
 
484
 
 
485
    void jasserted(const char *msg, const char *file, unsigned line) {
 
486
        log() << "jassert failed " << msg << " " << file << " " << line << endl;
 
487
        if ( JavaJS ) JavaJS->printException();
 
488
        throw AssertionException();
 
489
    }
 
490
 
 
491
 
 
492
    const char* findEd(const char *path) {
 
493
 
 
494
#if defined(_WIN32)
 
495
 
 
496
        if (!path) {
 
497
            path = findEd();
 
498
        }
 
499
 
 
500
        // @TODO check validity
 
501
 
 
502
        return path;
 
503
#else
 
504
 
 
505
        if (!path) {
 
506
            return findEd();
 
507
        }
 
508
 
 
509
        log() << "Appserver location specified : " << path << endl;
 
510
 
 
511
        if (!path) {
 
512
            log() << "   invalid appserver location : " << path << " : terminating - prepare for bus error" << endl;
 
513
            return 0;
 
514
        }
 
515
 
 
516
        DIR *testDir = opendir(path);
 
517
 
 
518
        if (testDir) {
 
519
            log(1) << "   found directory for appserver : " << path << endl;
 
520
            closedir(testDir);
 
521
            return path;
 
522
        }
 
523
        else {
 
524
            log() << "   ERROR : not a directory for specified appserver location : " << path << " - prepare for bus error" << endl;
 
525
            return null;
 
526
        }
 
527
#endif
 
528
    }
 
529
 
 
530
    const char * findEd() {
 
531
 
 
532
#if defined(_WIN32)
 
533
        log() << "Appserver location will be WIN32 default : c:/l/ed/" << endl;
 
534
        return "c:/l/ed";
 
535
#else
 
536
 
 
537
        static list<const char*> possibleEdDirs;
 
538
        if ( ! possibleEdDirs.size() ) {
 
539
            possibleEdDirs.push_back( "../../ed/ed/" ); // this one for dwight dev box
 
540
            possibleEdDirs.push_back( "../ed/" );
 
541
            possibleEdDirs.push_back( "../../ed/" );
 
542
            possibleEdDirs.push_back( "../babble/" );
 
543
            possibleEdDirs.push_back( "../../babble/" );
 
544
        }
 
545
 
 
546
        for ( list<const char*>::iterator i = possibleEdDirs.begin() ; i != possibleEdDirs.end(); i++ ) {
 
547
            const char * temp = *i;
 
548
            DIR * test = opendir( temp );
 
549
            if ( ! test )
 
550
                continue;
 
551
 
 
552
            closedir( test );
 
553
            log(1) << "found directory for appserver : " << temp << endl;
 
554
            return temp;
 
555
        }
 
556
 
 
557
        return 0;
 
558
#endif
 
559
    };
 
560
 
 
561
    const string findJars() {
 
562
 
 
563
        static list<string> possible;
 
564
        if ( ! possible.size() ) {
 
565
            possible.push_back( "./" );
 
566
            possible.push_back( "../" );
 
567
            
 
568
            log(2) << "dbExecCommand: " << dbExecCommand << endl;
 
569
            
 
570
            string dbDir = dbExecCommand;
 
571
#ifdef WIN32
 
572
            if ( dbDir.find( "\\" ) != string::npos ){
 
573
                dbDir = dbDir.substr( 0 , dbDir.find_last_of( "\\" ) );
 
574
            }
 
575
            else {
 
576
                dbDir = ".";
 
577
            }
 
578
#else
 
579
            if ( dbDir.find( "/" ) != string::npos ){
 
580
                dbDir = dbDir.substr( 0 , dbDir.find_last_of( "/" ) );
 
581
            }
 
582
            else {
 
583
                bool found = false;
 
584
                
 
585
                if ( getenv( "PATH" ) ){
 
586
                    string s = getenv( "PATH" );
 
587
                    s += ":";
 
588
                    pcrecpp::StringPiece input( s );
 
589
                    string dir;
 
590
                    pcrecpp::RE re("(.*?):");
 
591
                    while ( re.Consume( &input, &dir ) ){
 
592
                        string test = dir + "/" + dbExecCommand;
 
593
                        if ( boost::filesystem::exists( test ) ){
 
594
                            while ( boost::filesystem::symbolic_link_exists( test ) ){
 
595
                                char tmp[2048];
 
596
                                int len = readlink( test.c_str() , tmp , 2048 );
 
597
                                tmp[len] = 0;
 
598
                                log(5) << " symlink " << test << "  -->> " << tmp << endl;
 
599
                                test = tmp;
 
600
                                
 
601
                                dir = test.substr( 0 , test.rfind( "/" ) );
 
602
                            }
 
603
                            dbDir = dir;
 
604
                            found = true;
 
605
                            break;
 
606
                        }
 
607
                    }
 
608
                }
 
609
                
 
610
                if ( ! found )
 
611
                    dbDir = ".";
 
612
            }
 
613
#endif
 
614
            
 
615
            log(2) << "dbDir [" << dbDir << "]" << endl;
 
616
            possible.push_back( ( dbDir + "/../lib/mongo/" ));
 
617
            possible.push_back( ( dbDir + "/../lib64/mongo/" ));
 
618
            possible.push_back( ( dbDir + "/../lib32/mongo/" ));
 
619
            possible.push_back( ( dbDir + "/" ));
 
620
            possible.push_back( ( dbDir + "/lib64/mongo/" ));
 
621
            possible.push_back( ( dbDir + "/lib32/mongo/" ));
 
622
        }
 
623
 
 
624
        for ( list<string>::iterator i = possible.begin() ; i != possible.end(); i++ ) {
 
625
            const string temp = *i;
 
626
            const string jarDir = ((string)temp) + "jars/";
 
627
            
 
628
            log(5) << "possible jarDir [" << jarDir << "]" << endl;
 
629
 
 
630
            path p(jarDir );
 
631
            if ( ! boost::filesystem::exists( p) )
 
632
                continue;
 
633
 
 
634
            log(1) << "found directory for jars : " << jarDir << endl;
 
635
            return temp;
 
636
        }
 
637
 
 
638
        problem() << "ERROR : can't find directory for jars - terminating" << endl;
 
639
        exit(44);
 
640
        return 0;
 
641
 
 
642
    };
 
643
 
 
644
    
 
645
// ---
 
646
 
 
647
    JNIEXPORT void JNICALL java_native_say(JNIEnv * env , jclass, jobject outBuffer ) {
 
648
        JNI_DEBUG( "native say called!" );
 
649
 
 
650
        Message out( env->GetDirectBufferAddress( outBuffer ) , false );
 
651
        Message in;
 
652
 
 
653
        jniCallback( out , in );
 
654
        assert( ! out.doIFreeIt() );
 
655
        curNs = 0;
 
656
    }
 
657
 
 
658
    JNIEXPORT jint JNICALL java_native_call(JNIEnv * env , jclass, jobject outBuffer , jobject inBuffer ) {
 
659
        JNI_DEBUG( "native call called!" );
 
660
 
 
661
        Message out( env->GetDirectBufferAddress( outBuffer ) , false );
 
662
        Message in;
 
663
 
 
664
        jniCallback( out , in );
 
665
        curNs = 0;
 
666
 
 
667
        JNI_DEBUG( "in.data : " << in.data );
 
668
        if ( in.data && in.data->len > 0 ) {
 
669
            JNI_DEBUG( "copying data of len :" << in.data->len );
 
670
            assert( env->GetDirectBufferCapacity( inBuffer ) >= in.data->len );
 
671
            memcpy( env->GetDirectBufferAddress( inBuffer ) , in.data , in.data->len );
 
672
 
 
673
            assert( ! out.doIFreeIt() );
 
674
            assert( in.doIFreeIt() );
 
675
            return in.data->len;
 
676
        }
 
677
 
 
678
        return 0;
 
679
    }
 
680
 
 
681
// ----
 
682
 
 
683
    void JavaJSImpl::runTest() {
 
684
 
 
685
        const int debug = 0;
 
686
 
 
687
        JavaJSImpl& JavaJS = *mongo::JavaJS;
 
688
 
 
689
        jlong scope = JavaJS.scopeCreate();
 
690
        jassert( scope );
 
691
        if ( debug ) out() << "got scope" << endl;
 
692
 
 
693
 
 
694
        jlong func1 = JavaJS.functionCreate( "foo = 5.6; bar = \"eliot\"; abc = { foo : 517 }; " );
 
695
         jassert( ! JavaJS.invoke( scope , func1 ) );
 
696
 
 
697
 
 
698
        if ( debug ) out() << "func3 start" << endl;
 
699
        jlong func3 = JavaJS.functionCreate( "function(){ z = true; } " );
 
700
        jassert( func3 );
 
701
        jassert( ! JavaJS.invoke( scope , func3 ) );
 
702
        jassert( JavaJS.scopeGetBoolean( scope , "z" ) );
 
703
        if ( debug ) out() << "func3 done" << endl;
 
704
 
 
705
        if ( debug ) out() << "going to get object" << endl;
 
706
        BSONObj obj = JavaJS.scopeGetObject( scope , "abc" );
 
707
        if ( debug ) out() << "done getting object" << endl;
 
708
 
 
709
        if ( debug ) {
 
710
            out() << "obj : " << obj.toString() << endl;
 
711
        }
 
712
 
 
713
        {
 
714
            time_t start = time(0);
 
715
            for ( int i=0; i<5000; i++ ) {
 
716
                JavaJS.scopeSetObject( scope , "obj" , &obj );
 
717
            }
 
718
            time_t end = time(0);
 
719
 
 
720
            if ( debug )
 
721
                out() << "time : " << (unsigned) ( end - start ) << endl;
 
722
        }
 
723
 
 
724
        if ( debug ) out() << "func4 start" << endl;
 
725
        JavaJS.scopeSetObject( scope , "obj" , &obj );
 
726
        if ( debug ) out() << "\t here 1" << endl;
 
727
        jlong func4 = JavaJS.functionCreate( "tojson( obj );" );
 
728
        if ( debug ) out() << "\t here 2" << endl;
 
729
        jassert( ! JavaJS.invoke( scope , func4 ) );
 
730
        if ( debug ) out() << "func4 end" << endl;
 
731
 
 
732
        if ( debug ) out() << "func5 start" << endl;
 
733
        jassert( JavaJS.scopeSetObject( scope , "c" , &obj ) );
 
734
        jlong func5 = JavaJS.functionCreate( "assert.eq( 517 , c.foo );" );
 
735
        jassert( func5 );
 
736
        jassert( ! JavaJS.invoke( scope , func5 ) );
 
737
        if ( debug ) out() << "func5 done" << endl;
 
738
 
 
739
        if ( debug ) out() << "func6 start" << endl;
 
740
        for ( int i=0; i<100; i++ ) {
 
741
            double val = i + 5;
 
742
            JavaJS.scopeSetNumber( scope , "zzz" , val );
 
743
            jlong func6 = JavaJS.functionCreate( " xxx = zzz; " );
 
744
            jassert( ! JavaJS.invoke( scope , func6 ) );
 
745
            double n = JavaJS.scopeGetNumber( scope , "xxx" );
 
746
            jassert( val == n );
 
747
        }
 
748
        if ( debug ) out() << "func6 done" << endl;
 
749
 
 
750
        jlong func7 = JavaJS.functionCreate( "return 11;" );
 
751
        jassert( ! JavaJS.invoke( scope , func7 ) );
 
752
        assert( 11 == JavaJS.scopeGetNumber( scope , "return" ) );
 
753
 
 
754
        scope = JavaJS.scopeCreate();
 
755
        jlong func8 = JavaJS.functionCreate( "function(){ return 12; }" );
 
756
        jassert( ! JavaJS.invoke( scope , func8 ) );
 
757
        assert( 12 == JavaJS.scopeGetNumber( scope , "return" ) );
 
758
 
 
759
    }
 
760
    
 
761
#endif
 
762
 
 
763
} // namespace mongo