001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.xtest.plugin.jvm;
042:
043: import java.io.File;
044: import java.io.FileReader;
045: import java.io.IOException;
046: import java.io.LineNumberReader;
047: import java.util.Calendar;
048: import org.apache.tools.ant.Project;
049: import org.apache.tools.ant.taskdefs.ExecuteWatchdog;
050: import org.apache.tools.ant.util.Watchdog;
051: import org.netbeans.xtest.util.NativeKill;
052:
053: /** Watchdog used in JVMTestRunnerTask. If timeout expires, it kills JVM
054: * in which tests run. PID of process is passed in file ${xtest.workdir}/jvm.pid
055: * from JUnitTestRunnerLauncher class.
056: */
057: public class JVMExecuteWatchdog extends ExecuteWatchdog {
058:
059: protected long timeout;
060: protected Project antProject;
061:
062: /** Creates a new instance of IdeExecWatchdog */
063: public JVMExecuteWatchdog(long timeout, Project project) {
064: super (timeout);
065: //super(90000); System.out.println("Got timeout "+timeout+", but using 90 seconds for testing purposes");
066: if (project == null) {
067: throw new IllegalArgumentException(
068: "Ant's Project is not set");
069: }
070: this .antProject = project;
071: this .timeout = timeout;
072: project.log("JVMExecWatchdog created with timeout " + timeout,
073: Project.MSG_VERBOSE);
074: }
075:
076: public synchronized void timeoutOccured(Watchdog w) {
077: antProject.log(" XTest: Hard timeout " + timeout
078: + "ms occured - trying to kill JVM - "
079: + Calendar.getInstance().getTime());
080: this .killJVM();
081: antProject.log("XTest: JVM killed.");
082: super .timeoutOccured(w);
083: }
084:
085: /** Kill JVM process running tests with PID from ${xtest.workdir}/jvm.pid file.
086: */
087: public boolean killJVM() {
088: String workdir = antProject.getProperty("xtest.workdir");
089: if (workdir != null) {
090: // create flag file indicating running tests
091: File jvmPID = new File(workdir, "jvm.pid");
092: if (jvmPID.exists()) {
093: try {
094: LineNumberReader reader = new LineNumberReader(
095: new FileReader(jvmPID));
096: String line = reader.readLine();
097: if (line != null) {
098: try {
099: long pid = Long.parseLong(line);
100: // xtest.home used in NativeKill class
101: System.setProperty("xtest.home", antProject
102: .getProperty("xtest.home"));
103: antProject
104: .log("Requesting thread dump on process with PID="
105: + pid);
106: NativeKill.dumpProcess(pid);
107: // sleep a bit, so resources can be released
108: Thread.sleep(2000);
109: antProject.log("Killing process with PID="
110: + pid);
111: boolean result = NativeKill
112: .killProcess(pid);
113: // sleep a bit, so resources can be released
114: Thread.sleep(2000);
115: return result;
116: } catch (NumberFormatException nfe) {
117: antProject
118: .log("Cannot parse PID written in the ide.flag file: "
119: + line + " - not killing");
120: }
121: }
122: } catch (IOException ioe) {
123: antProject
124: .log("Cannot kill. IOException when reading PID from file: "
125: + jvmPID);
126: antProject.log(ioe.toString());
127: } catch (Exception e) {
128: antProject.log("Exception when trying to kill IDE");
129: antProject.log(e.toString());
130: }
131: } else {
132: antProject
133: .log("Cannot kill. Cannot find file containing PID: "
134: + jvmPID);
135: }
136: } else {
137: antProject
138: .log("xtest.workdir property is not specified - cannot kill");
139: }
140: return false;
141: }
142: }
|