00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include "kjavaappletserver.h"
00024 #include "kjavaappletcontext.h"
00025 #include "kjavaprocess.h"
00026 #include "kjavadownloader.h"
00027
00028 #include <kdebug.h>
00029 #include <kconfig.h>
00030 #include <klocale.h>
00031 #include <kparts/browserextension.h>
00032 #include <kapplication.h>
00033 #include <kstandarddirs.h>
00034
00035 #include <kio/job.h>
00036 #include <kio/kprotocolmanager.h>
00037
00038 #include <qtimer.h>
00039 #include <qguardedptr.h>
00040 #include <qdir.h>
00041
00042 #include <stdlib.h>
00043
00044 #define KJAS_CREATE_CONTEXT (char)1
00045 #define KJAS_DESTROY_CONTEXT (char)2
00046 #define KJAS_CREATE_APPLET (char)3
00047 #define KJAS_DESTROY_APPLET (char)4
00048 #define KJAS_START_APPLET (char)5
00049 #define KJAS_STOP_APPLET (char)6
00050 #define KJAS_INIT_APPLET (char)7
00051 #define KJAS_SHOW_DOCUMENT (char)8
00052 #define KJAS_SHOW_URLINFRAME (char)9
00053 #define KJAS_SHOW_STATUS (char)10
00054 #define KJAS_RESIZE_APPLET (char)11
00055 #define KJAS_GET_URLDATA (char)12
00056 #define KJAS_URLDATA (char)13
00057 #define KJAS_SHUTDOWN_SERVER (char)14
00058 #define KJAS_JAVASCRIPT_EVENT (char)15
00059 #define KJAS_GET_MEMBER (char)16
00060 #define KJAS_CALL_MEMBER (char)17
00061 #define KJAS_PUT_MEMBER (char)18
00062 #define KJAS_DEREF_OBJECT (char)19
00063 #define KJAS_AUDIOCLIP_PLAY (char)20
00064 #define KJAS_AUDIOCLIP_LOOP (char)21
00065 #define KJAS_AUDIOCLIP_STOP (char)22
00066 #define KJAS_APPLET_STATE (char)23
00067 #define KJAS_APPLET_FAILED (char)24
00068
00069
00070 class JSStackNode {
00071 public:
00072 JSStackNode(JSStackNode *u) : ready(false), size(u ? u->size+1: 1), up(u) {}
00073 bool ready;
00074 QStringList args;
00075 int size;
00076 JSStackNode *up;
00077 };
00078
00079
00080 class KJavaAppletServerPrivate
00081 {
00082 friend class KJavaAppletServer;
00083 private:
00084 int counter;
00085 QMap< int, QGuardedPtr<KJavaAppletContext> > contexts;
00086 QString appletLabel;
00087 JSStackNode *jsstack;
00088 };
00089
00090 static KJavaAppletServer* self = 0;
00091
00092 KJavaAppletServer::KJavaAppletServer()
00093 {
00094 d = new KJavaAppletServerPrivate;
00095 d->jsstack = 0L;
00096 process = new KJavaProcess();
00097
00098 connect( process, SIGNAL(received(const QByteArray&)),
00099 this, SLOT(slotJavaRequest(const QByteArray&)) );
00100
00101 setupJava( process );
00102
00103 if( process->startJava() )
00104 d->appletLabel = i18n( "Loading Applet" );
00105 else
00106 d->appletLabel = i18n( "Error: java executable not found" );
00107
00108 }
00109
00110 KJavaAppletServer::~KJavaAppletServer()
00111 {
00112 quit();
00113
00114 delete process;
00115 delete d;
00116 }
00117
00118 QString KJavaAppletServer::getAppletLabel()
00119 {
00120 if( self )
00121 return self->appletLabel();
00122 else
00123 return QString::null;
00124 }
00125
00126 QString KJavaAppletServer::appletLabel()
00127 {
00128 return d->appletLabel;
00129 }
00130
00131 KJavaAppletServer* KJavaAppletServer::allocateJavaServer()
00132 {
00133 if( self == 0 )
00134 {
00135 self = new KJavaAppletServer();
00136 self->d->counter = 0;
00137 }
00138
00139 self->d->counter++;
00140 return self;
00141 }
00142
00143 void KJavaAppletServer::freeJavaServer()
00144 {
00145 self->d->counter--;
00146
00147 if( self->d->counter == 0 )
00148 {
00149
00150
00151
00152 KConfig config( "konquerorrc", true );
00153 config.setGroup( "Java/JavaScript Settings" );
00154 if( config.readBoolEntry( "ShutdownAppletServer", true ) )
00155 {
00156 int value = config.readNumEntry( "AppletServerTimeout", 60 );
00157 QTimer::singleShot( value*1000, self, SLOT( checkShutdown() ) );
00158 }
00159 }
00160 }
00161
00162 void KJavaAppletServer::checkShutdown()
00163 {
00164 if( self->d->counter == 0 )
00165 {
00166 delete self;
00167 self = 0;
00168 }
00169 }
00170
00171 void KJavaAppletServer::setupJava( KJavaProcess *p )
00172 {
00173 KConfig config ( "konquerorrc", true );
00174 config.setGroup( "Java/JavaScript Settings" );
00175
00176 QString jvm_path = "java";
00177
00178 QString jPath = config.readEntry( "JavaPath" );
00179 if ( !jPath.isEmpty() && jPath != "java" )
00180 {
00181
00182 if( jPath[jPath.length()-1] == '/' )
00183 jPath.remove(jPath.length()-1, 1);
00184
00185 QDir dir( jPath );
00186 if( dir.exists( "bin/java" ) )
00187 {
00188 jvm_path = jPath + "/bin/java";
00189 }
00190 else if (dir.exists( "/jre/bin/java" ) )
00191 {
00192 jvm_path = jPath + "/jre/bin/java";
00193 }
00194 else if( QFile::exists(jPath) )
00195 {
00196
00197 jvm_path = jPath;
00198 }
00199 }
00200
00201
00202 p->setJVMPath( jvm_path );
00203
00204
00205 QString kjava_class = locate("data", "kjava/kjava.jar");
00206 kdDebug(6100) << "kjava_class = " << kjava_class << endl;
00207 if( kjava_class.isNull() )
00208 return;
00209
00210 QDir dir( kjava_class );
00211 dir.cdUp();
00212 kdDebug(6100) << "dir = " << dir.absPath() << endl;
00213
00214 QStringList entries = dir.entryList( "*.jar" );
00215 kdDebug(6100) << "entries = " << entries.join( ":" ) << endl;
00216
00217 QString classes;
00218 for( QStringList::Iterator it = entries.begin();
00219 it != entries.end(); it++ )
00220 {
00221 if( !classes.isEmpty() )
00222 classes += ":";
00223 classes += dir.absFilePath( *it );
00224 }
00225 p->setClasspath( classes );
00226
00227
00228 QString extraArgs = config.readEntry( "JavaArgs", "" );
00229 p->setExtraArgs( extraArgs );
00230
00231 if( config.readBoolEntry( "ShowJavaConsole", false) )
00232 {
00233 p->setSystemProperty( "kjas.showConsole", QString::null );
00234 }
00235
00236 if( config.readBoolEntry( "UseSecurityManager", true ) )
00237 {
00238 QString class_file = locate( "data", "kjava/kjava.policy" );
00239 p->setSystemProperty( "java.security.policy", class_file );
00240
00241 p->setSystemProperty( "java.security.manager",
00242 "org.kde.kjas.server.KJASSecurityManager" );
00243 }
00244
00245
00246 if( KProtocolManager::useProxy() )
00247 {
00248
00249
00250
00251
00252 KURL dummyURL( "http://www.kde.org/" );
00253 QString httpProxy = KProtocolManager::proxyForURL(dummyURL);
00254 kdDebug(6100) << "httpProxy is " << httpProxy << endl;
00255
00256 KURL url( httpProxy );
00257 p->setSystemProperty( "http.proxyHost", url.host() );
00258 p->setSystemProperty( "http.proxyPort", QString::number( url.port() ) );
00259 }
00260
00261
00262 p->setMainClass( "org.kde.kjas.server.Main" );
00263 }
00264
00265 void KJavaAppletServer::createContext( int contextId, KJavaAppletContext* context )
00266 {
00267
00268 d->contexts.insert( contextId, context );
00269
00270 QStringList args;
00271 args.append( QString::number( contextId ) );
00272 process->send( KJAS_CREATE_CONTEXT, args );
00273 }
00274
00275 void KJavaAppletServer::destroyContext( int contextId )
00276 {
00277
00278 d->contexts.remove( contextId );
00279
00280 QStringList args;
00281 args.append( QString::number( contextId ) );
00282 process->send( KJAS_DESTROY_CONTEXT, args );
00283 }
00284
00285 void KJavaAppletServer::createApplet( int contextId, int appletId,
00286 const QString name, const QString clazzName,
00287 const QString baseURL, const QString codeBase,
00288 const QString jarFile, QSize size,
00289 const QMap<QString,QString>& params,
00290 const QString windowTitle )
00291 {
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 QStringList args;
00303 args.append( QString::number( contextId ) );
00304 args.append( QString::number( appletId ) );
00305
00306
00307 args.append( name );
00308 args.append( clazzName );
00309 args.append( baseURL );
00310 args.append( codeBase );
00311 args.append( jarFile );
00312
00313 args.append( QString::number( size.width() ) );
00314 args.append( QString::number( size.height() ) );
00315
00316 args.append( windowTitle );
00317
00318
00319 int num = params.count();
00320 QString num_params = QString("%1").arg( num, 8 );
00321 args.append( num_params );
00322
00323 QMap< QString, QString >::ConstIterator it;
00324
00325 for( it = params.begin(); it != params.end(); ++it )
00326 {
00327 args.append( it.key() );
00328 args.append( it.data() );
00329 }
00330
00331 process->send( KJAS_CREATE_APPLET, args );
00332 }
00333
00334 void KJavaAppletServer::initApplet( int contextId, int appletId )
00335 {
00336 QStringList args;
00337 args.append( QString::number( contextId ) );
00338 args.append( QString::number( appletId ) );
00339
00340 process->send( KJAS_INIT_APPLET, args );
00341 }
00342
00343 void KJavaAppletServer::destroyApplet( int contextId, int appletId )
00344 {
00345 QStringList args;
00346 args.append( QString::number(contextId) );
00347 args.append( QString::number(appletId) );
00348
00349 process->send( KJAS_DESTROY_APPLET, args );
00350 }
00351
00352 void KJavaAppletServer::startApplet( int contextId, int appletId )
00353 {
00354 QStringList args;
00355 args.append( QString::number(contextId) );
00356 args.append( QString::number(appletId) );
00357
00358 process->send( KJAS_START_APPLET, args );
00359 }
00360
00361 void KJavaAppletServer::stopApplet( int contextId, int appletId )
00362 {
00363 QStringList args;
00364 args.append( QString::number(contextId) );
00365 args.append( QString::number(appletId) );
00366
00367 process->send( KJAS_STOP_APPLET, args );
00368 }
00369
00370 void KJavaAppletServer::sendURLData( const QString& loaderID,
00371 const QString& url,
00372 const QByteArray& data )
00373 {
00374 QStringList args;
00375 args.append( loaderID );
00376 args.append( url );
00377
00378 process->send( KJAS_URLDATA, args, data );
00379
00380 }
00381
00382 void KJavaAppletServer::quit()
00383 {
00384 QStringList args;
00385
00386 process->send( KJAS_SHUTDOWN_SERVER, args );
00387 }
00388
00389 void KJavaAppletServer::slotJavaRequest( const QByteArray& qb )
00390 {
00391
00392
00393 QString cmd;
00394 QStringList args;
00395 int index = 0;
00396 int qb_size = qb.size();
00397
00398
00399 char cmd_code = qb[ index++ ];
00400 ++index;
00401
00402
00403 QString contextID;
00404 while( qb[index] != 0 && index < qb_size )
00405 {
00406 contextID += qb[ index++ ];
00407 }
00408 ++index;
00409
00410
00411 while( index < qb_size )
00412 {
00413 QString tmp;
00414 while( qb[index] != 0 )
00415 tmp += qb[ index++ ];
00416
00417 kdDebug(6100) << "KJavaAppletServer::slotJavaRequest: "<< tmp << endl;
00418 args.append( tmp );
00419
00420 ++index;
00421 }
00422
00423
00424 switch( cmd_code )
00425 {
00426 case KJAS_SHOW_DOCUMENT:
00427 cmd = QString::fromLatin1( "showdocument" );
00428 break;
00429
00430 case KJAS_SHOW_URLINFRAME:
00431 cmd = QString::fromLatin1( "showurlinframe" );
00432 break;
00433
00434 case KJAS_SHOW_STATUS:
00435 cmd = QString::fromLatin1( "showstatus" );
00436 break;
00437
00438 case KJAS_RESIZE_APPLET:
00439 cmd = QString::fromLatin1( "resizeapplet" );
00440 break;
00441
00442 case KJAS_GET_URLDATA:
00443
00444 kdDebug(6100) << "GetURLData from classloader: "<< contextID
00445 << " for url: " << args[0] << endl;
00446 break;
00447 case KJAS_JAVASCRIPT_EVENT:
00448 cmd = QString::fromLatin1( "JS_Event" );
00449 kdDebug(6100) << "Javascript request: "<< contextID
00450 << " code: " << args[0] << endl;
00451 break;
00452 case KJAS_GET_MEMBER:
00453 case KJAS_PUT_MEMBER:
00454 case KJAS_CALL_MEMBER:
00455 if (d->jsstack) {
00456 d->jsstack->args = args;
00457 d->jsstack->ready = true;
00458 d->jsstack = d->jsstack->up;
00459 process->syncCommandReceived();
00460 } else
00461 kdDebug(6100) << "Error: Missed return member data" << endl;
00462 return;
00463 case KJAS_AUDIOCLIP_PLAY:
00464 cmd = QString::fromLatin1( "audioclip_play" );
00465 kdDebug(6100) << "Audio Play: url=" << args[0] << endl;
00466 break;
00467 case KJAS_AUDIOCLIP_LOOP:
00468 cmd = QString::fromLatin1( "audioclip_loop" );
00469 kdDebug(6100) << "Audio Loop: url=" << args[0] << endl;
00470 break;
00471 case KJAS_AUDIOCLIP_STOP:
00472 cmd = QString::fromLatin1( "audioclip_stop" );
00473 kdDebug(6100) << "Audio Stop: url=" << args[0] << endl;
00474 break;
00475 case KJAS_APPLET_STATE:
00476 kdDebug(6100) << "Applet State Notification for Applet " << args[0] << ". New state=" << args[1] << endl;
00477 cmd = QString::fromLatin1( "AppletStateNotification" );
00478 break;
00479 case KJAS_APPLET_FAILED:
00480 kdDebug(6100) << "Applet " << args[0] << " Failed: " << args[1] << endl;
00481 cmd = QString::fromLatin1( "AppletFailed" );
00482 break;
00483 default:
00484 return;
00485 break;
00486 }
00487
00488 if( cmd_code == KJAS_GET_URLDATA )
00489 {
00490 new KJavaDownloader( contextID, args[0] );
00491 }
00492 else
00493 {
00494 bool ok;
00495 int contextID_num = contextID.toInt( &ok );
00496
00497 if( !ok )
00498 {
00499 kdError(6100) << "could not parse out contextID to call command on" << endl;
00500 return;
00501 }
00502
00503 KJavaAppletContext* context = d->contexts[ contextID_num ];
00504 if( context )
00505 context->processCmd( cmd, args );
00506 else if (cmd != "AppletStateNotification")
00507 kdError(6100) << "no context object for this id" << endl;
00508 }
00509 }
00510
00511 bool KJavaAppletServer::getMember(int contextId, int appletId, const unsigned long objid, const QString & name, int & type, unsigned long & rid, QString & value) {
00512 QStringList args;
00513 args.append( QString::number(contextId) );
00514 args.append( QString::number(appletId) );
00515 args.append( QString::number(objid) );
00516 args.append( name );
00517
00518 JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack);
00519
00520 kdDebug(6100) << "KJavaAppletServer::getMember " << name << endl;
00521 process->sendSync( KJAS_GET_MEMBER, args );
00522
00523 bool retval = frame->ready;
00524 if (retval) {
00525 type = frame->args[0].toInt(&retval);
00526 if (retval && type >= 0) {
00527 rid = frame->args[1].toInt(&retval);
00528 value = frame->args[2];
00529 } else
00530 retval = false;
00531 } else {
00532 kdError(6100) << "getMember: timeout" << endl;
00533 d->jsstack = frame->up;
00534 }
00535
00536 delete frame;
00537
00538 return retval;
00539 }
00540
00541 bool KJavaAppletServer::putMember(int contextId, int appletId, const unsigned long objid, const QString & name, const QString & value) {
00542 QStringList args;
00543 args.append( QString::number(contextId) );
00544 args.append( QString::number(appletId) );
00545 args.append( QString::number(objid) );
00546 args.append( name );
00547 args.append( value );
00548
00549 kdDebug(6100) << "KJavaAppletServer::putMember " << name << endl;
00550 JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack);
00551
00552 process->sendSync( KJAS_PUT_MEMBER, args );
00553
00554 bool retval = frame->ready;
00555 if (retval) {
00556 retval = frame->args[0].toInt(&retval);
00557 } else {
00558 kdError(6100) << "putMember: timeout" << endl;
00559 d->jsstack = frame->up;
00560 }
00561
00562 delete frame;
00563
00564 return retval;
00565 }
00566
00567 bool KJavaAppletServer::callMember(int contextId, int appletId, const unsigned long objid, const QString & name, const QStringList & fargs, int & type, unsigned long & rid, QString & value) {
00568 QStringList args;
00569 args.append( QString::number(contextId) );
00570 args.append( QString::number(appletId) );
00571 args.append( QString::number(objid) );
00572 args.append( name );
00573 for (QStringList::const_iterator it = fargs.begin(); it != fargs.end(); it++)
00574 args.append(*it);
00575
00576 JSStackNode * frame = d->jsstack = new JSStackNode(d->jsstack);
00577
00578 kdDebug(6100) << "KJavaAppletServer::callMember " << name << endl;
00579 process->sendSync( KJAS_CALL_MEMBER, args );
00580
00581 bool retval = frame->ready;
00582 if (retval) {
00583 type = frame->args[0].toInt(&retval);
00584 if (retval && type > -1) {
00585 rid = frame->args[1].toInt(&retval);
00586 if (retval)
00587 value = frame->args[2];
00588 } else
00589 retval = false;
00590 } else {
00591 kdError(6100) << "callMember: timeout return data" << endl;
00592 d->jsstack = frame->up;
00593 }
00594
00595 delete frame;
00596
00597 return retval;
00598 }
00599
00600 void KJavaAppletServer::derefObject(int contextId, int appletId, const unsigned long objid) {
00601 QStringList args;
00602 args.append( QString::number(contextId) );
00603 args.append( QString::number(appletId) );
00604 args.append( QString::number(objid) );
00605
00606 process->send( KJAS_DEREF_OBJECT, args );
00607 }
00608 #include "kjavaappletserver.moc"