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*
const buff =
new QByteArray();
00131
QTextOStream output( *buff );
00132
const char sep = 0;
00133
00134
00135
const 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 QStringList::ConstIterator it = args.begin();
00149
const QStringList::ConstIterator itEnd = args.end();
00150
for( ; it != itEnd; ++it )
00151 {
00152
if( !(*it).isEmpty() )
00153 {
00154 output << (*it).local8Bit();
00155 }
00156 output << sep;
00157 }
00158 }
00159
00160
return buff;
00161 }
00162
00163
void KJavaProcess::storeSize(
QByteArray* buff )
00164 {
00165
const int size = buff->size() - 8;
00166
const QString size_str =
QString(
"%1").arg( size, 8 );
00167
kdDebug(6100) <<
"KJavaProcess::storeSize, size = " << size_str <<
endl;
00168
00169
const char* size_ptr = size_str.latin1();
00170
for(
int i = 0; i < 8; ++i )
00171 buff->at(i) = size_ptr[i];
00172 }
00173
00174
void KJavaProcess::sendBuffer(
QByteArray* buff )
00175 {
00176 d->BufferList.append( buff );
00177
if( d->BufferList.count() == 1)
00178 {
00179 popBuffer();
00180 }
00181 }
00182
00183
void KJavaProcess::send(
char cmd_code,
const QStringList& args )
00184 {
00185
if( isRunning() )
00186 {
00187
QByteArray*
const buff = addArgs( cmd_code, args );
00188 storeSize( buff );
00189
kdDebug(6100) <<
"<KJavaProcess::send " << (
int)cmd_code <<
endl;
00190 sendBuffer( buff );
00191 }
00192 }
00193
00194
void KJavaProcess::send(
char cmd_code,
const QStringList& args,
00195
const QByteArray& data )
00196 {
00197
if( isRunning() )
00198 {
00199
kdDebug(6100) <<
"KJavaProcess::send, qbytearray is size = " << data.size() <<
endl;
00200
00201
QByteArray*
const buff = addArgs( cmd_code, args );
00202
const int cur_size = buff->size();
00203
const int data_size = data.size();
00204 buff->resize( cur_size + data_size );
00205 memcpy( buff->data() + cur_size, data.data(), data_size );
00206
00207 storeSize( buff );
00208 sendBuffer( buff );
00209 }
00210 }
00211
00212
void KJavaProcess::popBuffer()
00213 {
00214
QByteArray*
const buf = d->BufferList.first();
00215
if( buf )
00216 {
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
if ( !javaProcess->writeStdin( buf->data(),
00232 buf->size() ) )
00233 {
00234
kdError(6100) <<
"Could not write command" <<
endl;
00235 }
00236 }
00237 }
00238
00239
void KJavaProcess::slotWroteData( )
00240 {
00241
00242 d->BufferList.removeFirst();
00243
kdDebug(6100) <<
"slotWroteData " << d->BufferList.count() <<
endl;
00244
00245
if ( !d->BufferList.isEmpty() )
00246 {
00247 popBuffer();
00248 }
00249 }
00250
00251
00252
bool KJavaProcess::invokeJVM()
00253 {
00254
00255 *javaProcess << d->jvmPath;
00256
00257
if( !d->classPath.isEmpty() )
00258 {
00259 *javaProcess <<
"-classpath";
00260 *javaProcess << d->classPath;
00261 }
00262
00263
00264
QMap<QString,QString>::ConstIterator it = d->systemProps.begin();
00265
const QMap<QString,QString>::ConstIterator itEnd = d->systemProps.end();
00266
00267
for( ; it != itEnd; ++it )
00268 {
00269
QString currarg;
00270
00271
if( !it.key().isEmpty() )
00272 {
00273 currarg =
"-D" + it.key();
00274
if( !it.data().isEmpty() )
00275 currarg +=
"=" + it.data();
00276 }
00277
00278
if( !currarg.isEmpty() )
00279 *javaProcess << currarg;
00280 }
00281
00282
00283
if( !d->extraArgs.isEmpty() )
00284 {
00285
00286
00287
const QStringList args = QStringList::split(
" ", d->extraArgs );
00288 QStringList::ConstIterator it = args.begin();
00289
const QStringList::ConstIterator itEnd = args.end();
00290
for ( ; it != itEnd; ++it )
00291 *javaProcess << *it;
00292 }
00293
00294 *javaProcess << d->mainClass;
00295
00296
if ( !d->classArgs.isNull() )
00297 *javaProcess << d->classArgs;
00298
00299
kdDebug(6100) <<
"Invoking JVM now...with arguments = " <<
endl;
00300
QString argStr;
00301
QTextOStream stream( &argStr );
00302
const QValueList<QCString> args = javaProcess->args();
00303 qCopy( args.begin(), args.end(), QTextOStreamIterator<QCString>( stream,
" " ) );
00304
kdDebug(6100) << argStr <<
endl;
00305
00306
KProcess::Communication flags = (
KProcess::Communication)
00307 (KProcess::Stdin | KProcess::Stdout |
00308 KProcess::NoRead);
00309
00310
const bool rval = javaProcess->start( KProcess::NotifyOnExit, flags );
00311
if( rval )
00312 javaProcess->resume();
00313
else
00314 killJVM();
00315
00316
return rval;
00317 }
00318
00319
void KJavaProcess::killJVM()
00320 {
00321 d->processKilled =
true;
00322 disconnect( javaProcess, SIGNAL( receivedStdout(
int,
int& ) ),
00323
this, SLOT( slotReceivedData(
int,
int&) ) );
00324 javaProcess->kill();
00325 }
00326
00327
void KJavaProcess::flushBuffers()
00328 {
00329
while ( !d->BufferList.isEmpty() ) {
00330
if (innot)
00331 slotSendData(0);
00332
else
00333 d->BufferList.removeFirst();
00334 }
00335 }
00336
00337
00338
00339
00340
void KJavaProcess::slotReceivedData(
int fd,
int& len )
00341 {
00342
00343
00344
char length[9] = { 0 };
00345
const int num_bytes = ::read( fd, length, 8 );
00346
if( !num_bytes )
00347 {
00348 len = 0;
00349
return;
00350 }
00351
if( num_bytes == -1 )
00352 {
00353
kdError(6100) <<
"could not read 8 characters for the message length!!!!" <<
endl;
00354 len = 0;
00355
return;
00356 }
00357
00358
const QString lengthstr( length );
00359
bool ok;
00360
const int num_len = lengthstr.toInt( &ok );
00361
if( !ok )
00362 {
00363
kdError(6100) <<
"could not parse length out of: " << lengthstr <<
endl;
00364 len = num_bytes;
00365
return;
00366 }
00367
00368
00369
char*
const msg =
new char[num_len];
00370
const int num_bytes_msg = ::read( fd, msg, num_len );
00371
if( num_bytes_msg == -1 || num_bytes_msg != num_len )
00372 {
00373
kdError(6100) <<
"could not read the msg, num_bytes_msg = " << num_bytes_msg <<
endl;
00374
delete[] msg;
00375 len = num_bytes;
00376
return;
00377 }
00378
00379
QByteArray qb;
00380 emit received( qb.duplicate( msg, num_len ) );
00381
delete[] msg;
00382 len = num_bytes + num_bytes_msg;
00383 }
00384
00385
void KJavaProcess::slotExited( KProcess *process )
00386 {
00387
if (process == javaProcess) {
00388
int status = -1;
00389
if (!d->processKilled) {
00390 status = javaProcess->exitStatus();
00391 }
00392
kdDebug(6100) <<
"jvm exited with status " << status <<
endl;
00393 emit exited(status);
00394 }
00395 }
00396
00397
#include "kjavaprocess.moc"