kjavaprocess.cpp
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include "kjavaprocess.h"
00023 
00024 #include <kdebug.h>
00025 #include <kio/kprotocolmanager.h>
00026 
00027 #include <qtextstream.h>
00028 #include <qmap.h>
00029 
00030 #include <config.h>
00031 
00032 #include <unistd.h>
00033 #include <qptrlist.h>
00034 
00035 class KJavaProcessPrivate
00036 {
00037 friend class KJavaProcess;
00038 private:
00039     QString jvmPath;
00040     QString classPath;
00041     QString mainClass;
00042     QString extraArgs;
00043     QString classArgs;
00044     QPtrList<QByteArray> BufferList;
00045     QMap<QString, QString> systemProps;
00046     bool processKilled;
00047 };
00048 
00049 KJavaProcess::KJavaProcess() : KProcess()
00050 {
00051     d = new KJavaProcessPrivate;
00052     d->BufferList.setAutoDelete( true );
00053     d->processKilled = false;
00054 
00055     javaProcess = this; 
00056 
00057     connect( javaProcess, SIGNAL( wroteStdin( KProcess * ) ),
00058              this, SLOT( slotWroteData() ) );
00059     connect( javaProcess, SIGNAL( receivedStdout( int, int& ) ),
00060              this, SLOT( slotReceivedData(int, int&) ) );
00061     connect( javaProcess, SIGNAL( processExited (KProcess *) ),
00062              this, SLOT( slotExited (KProcess *) ) );
00063 
00064     d->jvmPath = "java";
00065     d->mainClass = "-help";
00066 }
00067 
00068 KJavaProcess::~KJavaProcess()
00069 {
00070     if ( isRunning() )
00071     {
00072         kdDebug(6100) << "stopping java process" << endl;
00073         stopJava();
00074     }
00075 
00076     
00077     delete d;
00078 }
00079 
00080 bool KJavaProcess::isRunning()
00081 {
00082    return javaProcess->isRunning();
00083 }
00084 
00085 bool KJavaProcess::startJava()
00086 {
00087    return invokeJVM();
00088 }
00089 
00090 void KJavaProcess::stopJava()
00091 {
00092    killJVM();
00093 }
00094 
00095 void KJavaProcess::setJVMPath( const QString& path )
00096 {
00097    d->jvmPath = path;
00098 }
00099 
00100 void KJavaProcess::setClasspath( const QString& classpath )
00101 {
00102     d->classPath = classpath;
00103 }
00104 
00105 void KJavaProcess::setSystemProperty( const QString& name,
00106                                       const QString& value )
00107 {
00108    d->systemProps.insert( name, value );
00109 }
00110 
00111 void KJavaProcess::setMainClass( const QString& className )
00112 {
00113    d->mainClass = className;
00114 }
00115 
00116 void KJavaProcess::setExtraArgs( const QString& args )
00117 {
00118    d->extraArgs = args;
00119 }
00120 
00121 void KJavaProcess::setClassArgs( const QString& args )
00122 {
00123    d->classArgs = args;
00124 }
00125 
00126 
00127 QByteArray* KJavaProcess::addArgs( char cmd_code, const QStringList& args )
00128 {
00129     
00130     QByteArray* buff = new QByteArray();
00131     QTextOStream output( *buff );
00132     char sep = 0;
00133 
00134     
00135     QCString space( "        " );
00136     output << space;
00137 
00138     
00139     output << cmd_code;
00140 
00141     
00142     if( args.isEmpty() )
00143     {
00144         output << sep;
00145     }
00146     else
00147     {
00148         for( QStringList::ConstIterator it = args.begin();
00149              it != args.end(); ++it )
00150         {
00151             if( !(*it).isEmpty() )
00152             {
00153                 output << (*it).local8Bit();
00154             }
00155             output << sep;
00156         }
00157     }
00158 
00159     return buff;
00160 }
00161 
00162 void KJavaProcess::storeSize( QByteArray* buff )
00163 {
00164     int size = buff->size() - 8;  
00165     QString size_str = QString("%1").arg( size, 8 );
00166     kdDebug(6100) << "KJavaProcess::storeSize, size = " << size_str << endl;
00167 
00168     const char* size_ptr = size_str.latin1();
00169     for( int i = 0; i < 8; i++ )
00170         buff->at(i) = size_ptr[i];
00171 }
00172 
00173 void KJavaProcess::sendBuffer( QByteArray* buff )
00174 {
00175     d->BufferList.append( buff );
00176     if( d->BufferList.count() == 1)
00177     {
00178         popBuffer();
00179     }
00180 }
00181 
00182 void KJavaProcess::send( char cmd_code, const QStringList& args )
00183 {
00184     if( isRunning() )
00185     {
00186         QByteArray* buff = addArgs( cmd_code, args );
00187         storeSize( buff );
00188         kdDebug(6100) << "<KJavaProcess::send " << (int)cmd_code << endl;
00189         sendBuffer( buff );
00190     }
00191 }
00192 
00193 void KJavaProcess::send( char cmd_code, const QStringList& args,
00194                          const QByteArray& data )
00195 {
00196     if( isRunning() )
00197     {
00198         kdDebug(6100) << "KJavaProcess::send, qbytearray is size = " << data.size() << endl;
00199 
00200         QByteArray* buff = addArgs( cmd_code, args );
00201         int cur_size = buff->size();
00202         int data_size = data.size();
00203         buff->resize( cur_size + data_size );
00204         memcpy( buff->data() + cur_size, data.data(), data_size );
00205 
00206         storeSize( buff );
00207         sendBuffer( buff );
00208     }
00209 }
00210 
00211 void KJavaProcess::popBuffer()
00212 {
00213     QByteArray* buf = d->BufferList.first();
00214     if( buf )
00215     {
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229         
00230         if ( !javaProcess->writeStdin( buf->data(),
00231                                        buf->size() ) )
00232         {
00233             kdError(6100) << "Could not write command" << endl;
00234         }
00235     }
00236 }
00237 
00238 void KJavaProcess::slotWroteData( )
00239 {
00240     
00241     d->BufferList.removeFirst();  
00242     kdDebug(6100) << "slotWroteData " << d->BufferList.count() << endl;
00243 
00244     if ( !d->BufferList.isEmpty() )
00245     {
00246         popBuffer();
00247     }
00248 }
00249 
00250 
00251 bool KJavaProcess::invokeJVM()
00252 {
00253     
00254     *javaProcess << d->jvmPath;
00255 
00256     if( !d->classPath.isEmpty() )
00257     {
00258         *javaProcess << "-classpath";
00259         *javaProcess << d->classPath;
00260     }
00261 
00262     
00263     for( QMap<QString,QString>::Iterator it = d->systemProps.begin();
00264          it != d->systemProps.end(); ++it )
00265     {
00266         QString currarg;
00267 
00268         if( !it.key().isEmpty() )
00269         {
00270             currarg = "-D" + it.key();
00271             if( !it.data().isEmpty() )
00272                 currarg += "=" + it.data();
00273         }
00274 
00275         if( !currarg.isEmpty() )
00276             *javaProcess << currarg;
00277     }
00278 
00279     
00280     if( !d->extraArgs.isEmpty() )
00281     {
00282         
00283         
00284         QStringList args = QStringList::split( " ", d->extraArgs );
00285         for ( QStringList::Iterator it = args.begin(); it != args.end(); ++it )
00286             *javaProcess << *it;
00287     }
00288 
00289     *javaProcess << d->mainClass;
00290 
00291     if ( !d->classArgs.isNull() )
00292         *javaProcess << d->classArgs;
00293 
00294     kdDebug(6100) << "Invoking JVM now...with arguments = " << endl;
00295     QString argStr;
00296     QTextOStream stream( &argStr );
00297     QValueList<QCString> args = javaProcess->args();
00298     qCopy( args.begin(), args.end(), QTextOStreamIterator<QCString>( stream, " " ) );
00299     kdDebug(6100) << argStr << endl;
00300 
00301     KProcess::Communication flags =  (KProcess::Communication)
00302                                      (KProcess::Stdin | KProcess::Stdout |
00303                                       KProcess::NoRead);
00304 
00305     bool rval = javaProcess->start( KProcess::NotifyOnExit, flags );
00306     if( rval )
00307         javaProcess->resume(); 
00308     else
00309         killJVM();
00310 
00311     return rval;
00312 }
00313 
00314 void KJavaProcess::killJVM()
00315 {
00316    d->processKilled = true;
00317    disconnect( javaProcess, SIGNAL( receivedStdout( int, int& ) ),
00318                this, SLOT( slotReceivedData(int, int&) ) );
00319    javaProcess->kill();
00320 }
00321 
00322 
00323 
00324 
00325 void KJavaProcess::slotReceivedData( int fd, int& len )
00326 {
00327     
00328     
00329     char length[9] = { 0 };
00330     int num_bytes = ::read( fd, length, 8 );
00331     if( !num_bytes )
00332     {
00333         len = 0;
00334         return;
00335     }
00336     if( num_bytes == -1 )
00337     {
00338         kdError(6100) << "could not read 8 characters for the message length!!!!" << endl;
00339         len = 0;
00340         return;
00341     }
00342 
00343     QString lengthstr( length );
00344     bool ok;
00345     int num_len = lengthstr.toInt( &ok );
00346     if( !ok )
00347     {
00348         kdError(6100) << "could not parse length out of: " << lengthstr << endl;
00349         len = num_bytes;
00350         return;
00351     }
00352 
00353     
00354     char* msg = new char[num_len];
00355     int num_bytes_msg = ::read( fd, msg, num_len );
00356     if( num_bytes_msg == -1 || num_bytes_msg != num_len )
00357     {
00358         kdError(6100) << "could not read the msg, num_bytes_msg = " << num_bytes_msg << endl;
00359         delete[] msg;
00360         len = num_bytes;
00361         return;
00362     }
00363 
00364     QByteArray qb;
00365     emit received( qb.duplicate( msg, num_len ) );
00366     delete[] msg;
00367     len = num_bytes + num_bytes_msg;
00368 }
00369 
00370 void KJavaProcess::slotExited( KProcess *process )
00371 {
00372   if (process == javaProcess) {
00373     int status = -1;
00374     if (!d->processKilled) {
00375      status = javaProcess->exitStatus();
00376     }
00377     kdDebug(6100) << "jvm exited with status " << status << endl; 
00378     emit exited(status);
00379   }
00380 }
00381 
00382 #include "kjavaprocess.moc"
 
This file is part of the documentation for khtml Library Version 3.2.0.