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
void KJavaProcess::flushBuffers()
00323 {
00324
while ( !d->BufferList.isEmpty() )
00325 slotSendData(0);
00326 }
00327
00328
00329
00330
00331
void KJavaProcess::slotReceivedData(
int fd,
int& len )
00332 {
00333
00334
00335
char length[9] = { 0 };
00336
int num_bytes = ::read( fd, length, 8 );
00337
if( !num_bytes )
00338 {
00339 len = 0;
00340
return;
00341 }
00342
if( num_bytes == -1 )
00343 {
00344
kdError(6100) <<
"could not read 8 characters for the message length!!!!" <<
endl;
00345 len = 0;
00346
return;
00347 }
00348
00349
QString lengthstr( length );
00350
bool ok;
00351
int num_len = lengthstr.toInt( &ok );
00352
if( !ok )
00353 {
00354
kdError(6100) <<
"could not parse length out of: " << lengthstr <<
endl;
00355 len = num_bytes;
00356
return;
00357 }
00358
00359
00360
char* msg =
new char[num_len];
00361
int num_bytes_msg = ::read( fd, msg, num_len );
00362
if( num_bytes_msg == -1 || num_bytes_msg != num_len )
00363 {
00364
kdError(6100) <<
"could not read the msg, num_bytes_msg = " << num_bytes_msg <<
endl;
00365
delete[] msg;
00366 len = num_bytes;
00367
return;
00368 }
00369
00370
QByteArray qb;
00371 emit received( qb.duplicate( msg, num_len ) );
00372
delete[] msg;
00373 len = num_bytes + num_bytes_msg;
00374 }
00375
00376
void KJavaProcess::slotExited( KProcess *process )
00377 {
00378
if (process == javaProcess) {
00379
int status = -1;
00380
if (!d->processKilled) {
00381 status = javaProcess->exitStatus();
00382 }
00383
kdDebug(6100) <<
"jvm exited with status " << status <<
endl;
00384 emit exited(status);
00385 }
00386 }
00387
00388
#include "kjavaprocess.moc"