• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KHTML

kjavaprocess.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2000 Richard Moore <rich@kde.org>
00004  *               2000 Wynn Wilkes <wynnw@caldera.com>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public License
00017  * along with this library; see the file COPYING.LIB.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
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; //new KProcess();
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     //delete javaProcess;
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 //Private Utility Functions used by the two send() methods
00127 QByteArray* KJavaProcess::addArgs( char cmd_code, const QStringList& args )
00128 {
00129     //the buffer to store stuff, etc.
00130     QByteArray* const buff = new QByteArray();
00131     QTextOStream output( *buff );
00132     const char sep = 0;
00133 
00134     //make space for the command size: 8 characters...
00135     const QCString space( "        " );
00136     output << space;
00137 
00138     //write command code
00139     output << cmd_code;
00140 
00141     //store the arguments...
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;  //subtract out the length of the size_str
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 //        DEBUG stuff...
00218 //  kdDebug(6100) << "Sending buffer to java, buffer = >>";
00219 //        for( unsigned int i = 0; i < buf->size(); i++ )
00220 //        {
00221 //            if( buf->at(i) == (char)0 )
00222 //                kdDebug(6100) << "<SEP>";
00223 //            else if( buf->at(i) > 0 && buf->at(i) < 10 )
00224 //                kdDebug(6100) << "<CMD " << (int) buf->at(i) << ">";
00225 //            else
00226 //                kdDebug(6100) << buf->at(i);
00227 //        }
00228 //        kdDebug(6100) << "<<" << endl;
00229 
00230         //write the data
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     //do this here- we can't free the data until we know it went through
00242     d->BufferList.removeFirst();  //this should delete it since we setAutoDelete(true)
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     //set the system properties, iterate through the qmap of system properties
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     //load the extra user-defined arguments
00283     if( !d->extraArgs.isEmpty() )
00284     {
00285         // BUG HERE: if an argument contains space (-Dname="My name")
00286         // this parsing will fail. Need more sophisticated parsing -- use KShell?
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(); //start processing stdout on the java process
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();  //note: AutoDelete is true
00334     }
00335 }
00336 
00337 /*  In this method, read one command and send it to the d->appletServer
00338  *  then return, so we don't block the event handling
00339  */
00340 void KJavaProcess::slotReceivedData( int fd, int& len )
00341 {
00342     //read out the length of the message,
00343     //read the message and send it to the applet server
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     //now parse out the rest of the message.
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"

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal