00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "inspectorj/client/connectionmanager.h"
00028
00029 using namespace inspectorj::client;
00030 using namespace inspectorj::jdwp;
00031
00036 ConnectionManager::ConnectionManager(QObject *prnt, QMap<QString, SessionProfile> &profiles, QProcess &process)
00037 : parent(prnt), profiles(profiles), javaAppProcess(process), handler(tcpSocket), attached(false)
00038 {
00039 this->setParent(parent);
00040 connect(&tcpSocket, SIGNAL(connected()), this, SLOT(sendHandshake()));
00041 connect(&tcpSocket, SIGNAL(delayedCloseFinished()),
00042 this, SLOT(connectionClosedByServer()));
00043 connect(&tcpSocket, SIGNAL(readyRead()), this, SLOT(readPacket()));
00044 connect(&tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
00045 this, SLOT(error(QAbstractSocket::SocketError)));
00046 }
00047
00051 bool ConnectionManager::isAttached()
00052 {
00053 return attached;
00054 }
00055
00062 void ConnectionManager::sendRequest(JDWPCommand *cmd, QList<JDWPAction*> &actions) {
00063 handler.sendJDWPCommand(cmd, actions);
00064 }
00065
00066
00073 void ConnectionManager::sendRequest(JDWPCommand *cmd, JDWPAction* action) {
00074 QList<JDWPAction*> actions;
00075 actions << action;
00076 sendRequest(cmd, actions);
00077 }
00078
00079
00084 void ConnectionManager::readPacket()
00085 {
00086 if (attached)
00087 {
00088 handler.readJDWPPacket();
00089 }
00090 else
00091 {
00092 receiveHandshake();
00093 }
00094 }
00095
00099 bool ConnectionManager::okToLaunch()
00100 {
00101 QProcess::ProcessState state = javaAppProcess.state();
00102 if (state == QProcess::Starting || state == QProcess::Running) {
00103 QString peerName = tcpSocket.peerName();
00104 QString peerPort;
00105 peerPort.setNum(tcpSocket.peerPort());
00106 QString msg = "You are currently connected to a running process on ";
00107 msg.append(peerName).append(":").append(peerPort);
00108 msg.append("\nDo you want to disconnect and terminate this process?");
00109
00110 int result = QMessageBox::information(dynamic_cast<QWidget*>(parent), "inspectorJ Launch", msg,
00111 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No);
00112 if (result == QMessageBox::Yes) {
00113 closeConnection();
00114 javaAppProcess.terminate();
00115 while (javaAppProcess.state() != QProcess::NotRunning) {
00116 javaAppProcess.waitForFinished(500);
00117 }
00118 return true;
00119 } else {
00120 return false;
00121 }
00122 } else {
00123 return okToConnect();
00124 }
00125
00126 }
00127
00131 bool ConnectionManager::okToConnect()
00132 {
00133
00134 if (tcpSocket.state() == QAbstractSocket::ConnectedState) {
00135 QString peerName = tcpSocket.peerName();
00136 QString peerPort;
00137 peerPort.setNum(tcpSocket.peerPort());
00138 QString msg = "You are currently connected to ";
00139 msg.append(peerName).append(":").append(peerPort);
00140 msg.append("\nDo you want to disconnect?");
00141
00142 int result = QMessageBox::information(dynamic_cast<QWidget*>(parent), "inspectorJ Connection", msg,
00143 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No);
00144 if (result == QMessageBox::Yes) {
00145 closeConnection();
00146 return true;
00147 } else {
00148 return false;
00149 }
00150 } else {
00151 return true;
00152 }
00153 }
00154
00158 bool ConnectionManager::attachToServer()
00159 {
00160
00161
00162 QAction *action = qobject_cast<QAction *>(sender());
00163 if (action) {
00164
00165
00166 if ( !okToConnect()) {
00167 return false;
00168 }
00169
00170 QStringList actionData = action->data().toStringList();
00171 QString profileName;
00172 QString host;
00173 QString port;
00174 profileName = actionData[0];
00175 host = actionData[1];
00176 port = actionData[2];
00177 bool ok;
00178 int portNum = port.toInt(&ok, 10);
00179 tcpSocket.connectToHost(host, portNum);
00180 return true;
00181 }
00182 return false;
00183 }
00184
00188 void ConnectionManager::attachToLaunchedServer()
00189 {
00190 bool ok;
00191 int portNum = connection.port.toInt(&ok, 10);
00192 tcpSocket.connectToHost(connection.host, portNum);
00193 }
00194
00201 bool ConnectionManager::startAttachTimer(int mills, ijConnection conn)
00202 {
00203
00204 if ( !okToConnect()) {
00205 return false;
00206 }
00207
00208 this->connection = conn;
00209 QTimer::singleShot(mills, this, SLOT(attachToLaunchedServer()));
00210 return true;
00211 }
00212
00213
00217 void ConnectionManager::launchJavaApp()
00218 {
00219
00220
00221 QAction *action = qobject_cast<QAction *>(sender());
00222 if (action) {
00223
00224
00225 if ( !okToLaunch()) {
00226 return;
00227 }
00228
00229 QStringList actionData = action->data().toStringList();
00230 QString profileName;
00231 profileName = actionData[0];
00232
00233 QString profileDir;
00234 profileDir = actionData[1];
00235 QString cmd = buildCmdString(profiles[profileName], profileDir);
00236
00237 javaAppProcess.setWorkingDirectory(QDir::currentPath());
00238 javaAppProcess.start(cmd);
00239 }
00240 }
00241
00242 bool isWindows()
00243 {
00244 return QDir::separator().toAscii() == '\\';
00245 }
00246
00254 QString ConnectionManager::buildCmdString(SessionProfile &profile, QString&
00255 profileDir)
00256 {
00257
00258 QChar sep = QDir::separator();
00259
00260
00261 QChar pathSep;
00262
00263 if (isWindows()) {
00264 pathSep = QChar(';');
00265 } else {
00266 pathSep = QChar(':');
00267 }
00268
00269
00270 QString path = QDir::currentPath();
00271 QString javaExec;
00272
00273
00274 if (profile.isTomcatApp()) {
00275 javaExec = profile.getApplicationEntry();
00276 if (!javaExec.endsWith(sep)) {
00277 javaExec += sep;
00278 }
00279 javaExec.append("bin").append(sep).append("catalina.");
00280 if (isWindows()) {
00281 javaExec.prepend("\"");
00282 javaExec.append("bat\"");
00283 } else {
00284 javaExec.append("sh");
00285 }
00286 javaExec.append(" run");
00287 } else {
00288 javaExec = profile.getJreHome();
00289 if (!javaExec.endsWith(sep)) {
00290 javaExec += sep;
00291 }
00292 javaExec.append("bin").append(sep).append("java");
00293 if (isWindows()) {
00294 javaExec.prepend("\"");
00295 javaExec.append(".exe\"");
00296 }
00297 }
00298
00299
00300 QString args;
00301 QString javaOptions = profile.getJavaOptions();
00302 if (!javaOptions.isEmpty()) {
00303 args.append(javaOptions);
00304 }
00305
00306 args.append(" -Xbootclasspath/a:\"");
00307 args.append(path).append(sep).append("mtrace.jar\" ");
00308
00309
00310 QStringList classpaths = profile.getClassPath();
00311 if (classpaths.size() > 0) {
00312 args.append("-classpath ");
00313 for (int i = 0; i < classpaths.size(); i++) {
00314 args.append(classpaths.at(i));
00315
00316 if (i < classpaths.size() - 1) {
00317 args.append(pathSep);
00318 }
00319 }
00320 }
00321
00322 QString agentLibOption(" -agentpath:\"");
00323 agentLibOption.append(path).append(sep);
00324 if (!isWindows()) {
00325 agentLibOption.append("lib");
00326 }
00327 agentLibOption.append("ij_agent.");
00328
00329
00330 if (isWindows()) {
00331 agentLibOption.append("dll");
00332 } else {
00333 agentLibOption.append("so");
00334 }
00335 agentLibOption.append("\"=profile=\"");
00336 agentLibOption.append(profileDir);
00337 if (!profileDir.endsWith(sep)) {
00338 agentLibOption += sep;
00339 }
00340 agentLibOption.append(profile.getFileName()).append("\"");
00341 agentLibOption.append(",loglevel=99 ");
00342 args.append(agentLibOption);
00343
00344 if (profile.isJarFile()) {
00345 if (javaOptions.isEmpty() || !javaOptions.contains("-jar")) {
00346 args.append(" -jar ");
00347 }
00348 }
00349
00350 if (profile.isTomcatApp()) {
00351 QStringList env = QProcess::systemEnvironment();
00352 QString javaOpts ("JAVA_OPTS=");
00353 javaOpts.append(args);
00354 env << javaOpts;
00355 QString catalinaHome("CATALINA_HOME=");
00356 catalinaHome.append(profile.getApplicationEntry());
00357 env << catalinaHome;
00358 if (!profile.getJreHome().isEmpty()) {
00359 QString javaHome("JAVA_HOME=");
00360 javaHome.append(profile.getJreHome());
00361 env << javaHome;
00362 }
00363 javaAppProcess.setEnvironment(env);
00364 } else {
00365 if (profile.isJarFile()) {
00366 args.append("\"");
00367 }
00368 args.append(profile.getApplicationEntry());
00369 if (profile.isJarFile()) {
00370 args.append("\"");
00371 }
00372 args.append(" ");
00373
00374 QString appArgs = profile.getApplicationArgs();
00375 if (!appArgs.isEmpty()) {
00376 args.append(appArgs);
00377 }
00378
00379 javaExec.append(args);
00380 }
00381 return javaExec;
00382 }
00383
00384 void ConnectionManager::setExiting(bool exit)
00385 {
00386 this->exiting = exit;
00387 }
00388
00389
00393 void ConnectionManager::sendHandshake()
00394 {
00395 tcpSocket.write(JDWP_HANDSHAKE, (qint64)14);
00396 }
00397
00401 void ConnectionManager::receiveHandshake()
00402 {
00403 QString msg;
00404 handler.getHandshake(attached, msg);
00405 if (!msg.isEmpty()) {
00406 if (attached) {
00407 emit connected(attached, msg);
00408 } else {
00409
00410 QMessageBox::warning( dynamic_cast<QWidget*>(parent), "inspectorJ Connection",
00411 msg, QMessageBox::Ok | QMessageBox::Default);
00412 }
00413 } else {
00414
00415 QMessageBox::warning( dynamic_cast<QWidget*>(parent), "inspectorJ Connection",
00416 "An unexpected error has occurred!",
00417 QMessageBox::Ok | QMessageBox::Default);
00418 }
00419 }
00420
00424 void ConnectionManager::connectionClosedByServer()
00425 {
00426 closeConnection();
00427 }
00428
00432 void ConnectionManager::closeConnection()
00433 {
00434 QAction *action = qobject_cast<QAction *>(sender());
00435 if (action && action->text() == "&Disconnect") {
00436 QString msg = "Are you sure you want to disconnect?";
00437 int result = QMessageBox::information(dynamic_cast<QWidget*>(parent),
00438 "inspectorJ Connection", msg,
00439 QMessageBox::Yes | QMessageBox::Default,
00440 QMessageBox::No);
00441
00442 if (result != QMessageBox::Yes) {
00443 return;
00444 }
00445 }
00446
00447 if (!attached) {
00448 return;
00449 }
00450 QAbstractSocket::SocketState state = tcpSocket.state();
00451 if (state != QAbstractSocket::ClosingState && state != QAbstractSocket::UnconnectedState) {
00452 JDWPCommand *cmd = JDWPCommand::newCommand(IJ_DISCONNECT);
00453 sendRequest(cmd, NULL);
00454 tcpSocket.close();
00455 }
00456 attached = false;
00457 QString msg = "Disconnected";
00458 emit connected(attached, msg);
00459 }
00460
00461 void ConnectionManager::stopJavaApp()
00462 {
00463 QString msg = "Are you sure you want to terminate the launched process?";
00464 int result = QMessageBox::information(dynamic_cast<QWidget*>(parent),
00465 "inspectorJ - Stop Java Application", msg,
00466 QMessageBox::Yes | QMessageBox::Default,
00467 QMessageBox::No);
00468
00469 if (result != QMessageBox::Yes) {
00470 return;
00471 }
00472
00473 QAbstractSocket::SocketState state = tcpSocket.state();
00474 if (state != QAbstractSocket::ClosingState && state != QAbstractSocket::UnconnectedState) {
00475 JDWPCommand *cmd = JDWPCommand::newCommand(IJ_EXIT);
00476 sendRequest(cmd, NULL);
00477 tcpSocket.close();
00478 }
00479 attached = false;
00480 msg = "Disconnected";
00481 emit connected(attached, msg);
00482
00483 javaAppProcess.kill();
00484 }
00485
00492 void ConnectionManager::getJDWPError(int errCode, QString &s)
00493 {
00494 ClientPacketHandler::getJDWPError(errCode, s);
00495 }
00496
00501 void ConnectionManager::error(QAbstractSocket::SocketError error)
00502 {
00503 if (!exiting) {
00504 closeConnection();
00505 QString errMsg;
00506 handler.getSocketError(error, errMsg);
00507 QMessageBox::warning( dynamic_cast<QWidget*>(parent), "inspectorJ Connection", errMsg,
00508 QMessageBox::Ok | QMessageBox::Default);
00509 }
00510 }