KHtml

kjavaprocess.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2000 Richard Moore <[email protected]>
4  * 2000 Wynn Wilkes <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "kjavaprocess.h"
23 
24 #include "kjavaappletviewer_debug.h"
25 #include <kshell.h>
26 #include <kprotocolmanager.h>
27 
28 #include <QTextStream>
29 #include <QMap>
30 
31 class KJavaProcessPrivate
32 {
33  friend class KJavaProcess;
34 private:
35  QString jvmPath;
36  QString classPath;
37  QString mainClass;
38  QString extraArgs;
39  QString classArgs;
40  QMap<QString, QString> systemProps;
41 };
42 
43 KJavaProcess::KJavaProcess(QObject *parent)
44  : QProcess(parent),
45  d(new KJavaProcessPrivate)
46 
47 {
48  connect(this, SIGNAL(readyReadStandardOutput()),
49  this, SLOT(slotReceivedData()));
50  connect(this, SIGNAL(finished(int,QProcess::ExitStatus)),
51  this, SLOT(slotExited()));
52  connect(this, SIGNAL(error(QProcess::ProcessError)),
53  this, SLOT(slotExited()));
54 
55  d->jvmPath = "java";
56  d->mainClass = "-help";
57 }
58 
59 KJavaProcess::~KJavaProcess()
60 {
61  if (state() != NotRunning) {
62  // qCDebug(KJAVAAPPLETVIEWER_LOG) << "stopping java process";
63  stopJava();
64  }
65  delete d;
66 }
67 
68 bool KJavaProcess::isRunning()
69 {
70  return state() != NotRunning;
71 }
72 
73 bool KJavaProcess::startJava()
74 {
75  return invokeJVM();
76 }
77 
78 void KJavaProcess::stopJava()
79 {
80  killJVM();
81 }
82 
83 void KJavaProcess::setJVMPath(const QString &path)
84 {
85  d->jvmPath = path;
86 }
87 
88 void KJavaProcess::setClasspath(const QString &classpath)
89 {
90  d->classPath = classpath;
91 }
92 
93 void KJavaProcess::setSystemProperty(const QString &name,
94  const QString &value)
95 {
96  d->systemProps.insert(name, value);
97 }
98 
99 void KJavaProcess::setMainClass(const QString &className)
100 {
101  d->mainClass = className;
102 }
103 
104 void KJavaProcess::setExtraArgs(const QString &args)
105 {
106  d->extraArgs = args;
107 }
108 
109 void KJavaProcess::setClassArgs(const QString &args)
110 {
111  d->classArgs = args;
112 }
113 
114 //Private Utility Functions used by the two send() methods
115 QByteArray KJavaProcess::addArgs(char cmd_code, const QStringList &args)
116 {
117  //the buffer to store stuff, etc.
118  QByteArray buff;
119  QTextStream output(&buff, QIODevice::ReadWrite);
120  const char sep = 0;
121 
122  //make space for the command size: 8 characters...
123  const QByteArray space(" ");
124  output << space;
125 
126  //write command code
127  output << cmd_code;
128 
129  //store the arguments...
130  if (args.isEmpty()) {
131  output << sep;
132  } else {
133  QStringList::ConstIterator it = args.begin();
134  const QStringList::ConstIterator itEnd = args.end();
135  for (; it != itEnd; ++it) {
136  if (!(*it).isEmpty()) {
137  output << (*it).toLocal8Bit();
138  }
139  output << sep;
140  }
141  }
142 
143  return buff;
144 }
145 
146 void KJavaProcess::storeSize(QByteArray *buff)
147 {
148  const int size = buff->size() - 8; //subtract out the length of the size_str
149  const QString size_str = QString("%1").arg(size, 8);
150  // qCDebug(KJAVAAPPLETVIEWER_LOG) << "KJavaProcess::storeSize, size = " << size_str;
151 
152  for (int i = 0; i < 8; ++i) {
153  buff->data()[ i ] = size_str[i].toLatin1();
154  }
155 }
156 
157 void KJavaProcess::send(char cmd_code, const QStringList &args)
158 {
159  if (isRunning()) {
160  QByteArray buff = addArgs(cmd_code, args);
161  storeSize(&buff);
162  // qCDebug(KJAVAAPPLETVIEWER_LOG) << "<KJavaProcess::send " << (int)cmd_code;
163  write(buff);
164  }
165 }
166 
167 void KJavaProcess::send(char cmd_code, const QStringList &args,
168  const QByteArray &data)
169 {
170  if (isRunning()) {
171  // qCDebug(KJAVAAPPLETVIEWER_LOG) << "KJavaProcess::send, qbytearray is size = " << data.size();
172 
173  QByteArray buff = addArgs(cmd_code, args);
174  buff += data;
175 
176  storeSize(&buff);
177  write(buff);
178  }
179 }
180 
181 bool KJavaProcess::invokeJVM()
182 {
183  QStringList args;
184 
185  if (!d->classPath.isEmpty()) {
186  args << "-classpath";
187  args << d->classPath;
188  }
189 
190  //set the system properties, iterate through the qmap of system properties
191  QMap<QString, QString>::ConstIterator it = d->systemProps.constBegin();
192  const QMap<QString, QString>::ConstIterator itEnd = d->systemProps.constEnd();
193 
194  for (; it != itEnd; ++it) {
195  if (!it.key().isEmpty()) {
196  QString currarg = "-D" + it.key();
197  if (!it.value().isEmpty()) {
198  currarg += '=' + it.value();
199  }
200  args << currarg;
201  }
202  }
203 
204  //load the extra user-defined arguments
205  if (!d->extraArgs.isEmpty()) {
206  KShell::Errors err;
207  args += KShell::splitArgs(d->extraArgs, KShell::AbortOnMeta, &err);
208  if (err != KShell::NoError) {
209  qCWarning(KJAVAAPPLETVIEWER_LOG) << "Extra args for JVM cannot be parsed, arguments = " << d->extraArgs;
210  }
211 
212  }
213 
214  args << d->mainClass;
215 
216  if (!d->classArgs.isNull()) {
217  args << d->classArgs;
218  }
219 
220  // qCDebug(KJAVAAPPLETVIEWER_LOG) << "Invoking JVM" << d->jvmPath << "now...with arguments = " << KShell::joinArgs(args);
221 
222  setProcessChannelMode(QProcess::SeparateChannels);
223  start(d->jvmPath, args);
224 
225  return waitForStarted();
226 }
227 
228 void KJavaProcess::killJVM()
229 {
230  closeReadChannel(StandardOutput);
231  terminate();
232 }
233 
234 /* In this method, read one command and send it to the d->appletServer
235  * then return, so we don't block the event handling
236  */
237 void KJavaProcess::slotReceivedData()
238 {
239  //read out the length of the message,
240  //read the message and send it to the applet server
241  char length[9] = { 0 };
242  const int num_bytes = read(length, 8);
243  if (num_bytes == -1) {
244  qCCritical(KJAVAAPPLETVIEWER_LOG) << "could not read 8 characters for the message length!!!!";
245  return;
246  }
247 
248  const QString lengthstr(length);
249  bool ok;
250  const int num_len = lengthstr.toInt(&ok);
251  if (!ok) {
252  qCCritical(KJAVAAPPLETVIEWER_LOG) << "could not parse length out of: " << lengthstr;
253  return;
254  }
255 
256  //now parse out the rest of the message.
257  char *const msg = new char[num_len];
258  const int num_bytes_msg = read(msg, num_len);
259  if (num_bytes_msg == -1 || num_bytes_msg != num_len) {
260  qCCritical(KJAVAAPPLETVIEWER_LOG) << "could not read the msg, num_bytes_msg = " << num_bytes_msg;
261  delete[] msg;
262  return;
263  }
264 
265  emit received(QByteArray(msg, num_len));
266  delete[] msg;
267 }
268 
269 void KJavaProcess::slotExited()
270 {
271  int status = -1;
272  if (exitStatus() == NormalExit) {
273  status = exitCode();
274  }
275  // qCDebug(KJAVAAPPLETVIEWER_LOG) << "jvm exited with status " << status;
276  emit exited(status);
277 }
278 
QSize size() const const
bool isEmpty() const const
QVariant read(const QByteArray &data, int versionOverride=0)
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
KCOREADDONS_EXPORT QStringList splitArgs(const QString &cmd, Options flags=NoOptions, Errors *err=nullptr)
QList::iterator end()
const Key key(const T &value, const Key &defaultKey) const const
QByteArray toLatin1() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
typedef ConstIterator
char * data()
int size() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QList::iterator begin()
const T value(const Key &key, const T &defaultValue) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:47:56 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.