views:

46

answers:

0

Hi all,

I try to launch a java program in a eclipse plugin, but failed.

What I try to do is to let the example from "Contribution to eclipse" to work.
In the example, the plugin contribute an menu item to eclipse,
when you select a test class, you can use the menu to run test cases in the class.

To run the test case, there are two class TestRunner and SocketTestRunner.
TestRunner launch the SocketTestRunner as a seperate java program, and communicate
through socket.

Code of TestRunner related to launch java program:

final String MAIN_CLASS = "org.eclipse.contribution.junit.SocketTestRunner";
public TestRunner() {
}

public void run(IType type) throws CoreException {
    project = type.getJavaProject();
    run(new IType[] { type });
}

public void run(IType[] classes) throws CoreException {
    IVMInstall vmInstall = JavaRuntime.getVMInstall(project);
    if (vmInstall == null)
        vmInstall = JavaRuntime.getDefaultVMInstall();
    if (vmInstall == null)
        return;

    IVMRunner vmRunner = vmInstall.getVMRunner(ILaunchManager.RUN_MODE);
    if (vmRunner == null)
        return;

    String[] classPath = computeClasspath();

    // prepare arguments:
    // Argument[0] = port
    // Argument[1-n] = types
    port = SocketUtil.findFreePort();
    String[] args = new String[classes.length + 1];
    args[0] = Integer.toString(port);
    for (int i = 0; i < classes.length; i++) {
        args[1 + i] = classes[i].getFullyQualifiedName();
    }
    VMRunnerConfiguration vmConfig = new VMRunnerConfiguration(MAIN_CLASS,
            classPath);
    vmConfig.setProgramArguments(args);     

    ILaunch launch = new Launch(null, ILaunchManager.RUN_MODE, null);
    vmRunner.run(vmConfig, launch, null);

    connect();
}

Code of SocketTestRunner:

public static void main(String[] args) {
    try {
        logger = new PrintWriter(new FileWriter("log.txt"), true);

        logger.println("main");
        for (int i = 0; i < args.length; i++) {
            logger.println(args[i]);
        }

        new SocketTestRunner().runTests(args);          
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (logger != null) {
            logger.close();
        }
    }
}

private void runTests(String[] args) {      
    port = Integer.parseInt(args[0]);
    logger.println("port: " + port);
    openClientSocket();
    try {
        logger.println("Befor new TestSuite");
        TestSuite suite = new TestSuite();
        for (int i = 1; i < args.length; i++) {
            logger.println("add TestSuite");
            suite.addTestSuite(Class.forName(args[i]).asSubclass(TestCase.class));
        }

        logger.println("starting tests " + suite.countTestCases());         
        //writer.println("starting tests " + suite.countTestCases());

        logger.println("Before TestResult");
        TestResult result = new TestResult();
        logger.println("After TestResult");
        result.addListener(this);
        suite.run(result);
        //writer.println("ending tests ");
        logger.println("ending tests ");
    } catch (Exception e) {
        logger.println("exception: " + e.getMessage());
        logger.println(e.toString());
        e.printStackTrace(logger);
        e.printStackTrace();
    } finally {
        closeClientSocket();
    }
}

private void closeClientSocket() {
    logger.println("closeClientSocket");
    if (writer != null) {
        writer.close();
    }

    try {
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void openClientSocket() {
    logger.println("openClientSocket");
    try {
        socket = new Socket("localhost", port);
        writer = new PrintWriter(socket.getOutputStream(), true);
        return;
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

When I test in eclipse(3.6.0 HELIOS), I create a simple JUnit test case in runtime eclipse,
select the test class and click the menu item in context menu,
then the runtime eclipse will not response any further interaction,
let the ServerSocket still keep listening, and no test log I add for debug.

And I can get the command line which eclipse used to launch the SocketTestRunner:

"C:\Program Files\Java\jre6\bin\javaw.exe" -classpath C:\Users\User\workspace\org.eclipse.contribution.junit\bin;C:\Users\User\workspace\org.eclipse.contribution.junit\plugins\org.eclipse.contribution.junit_1.0.0.201009102354.jar;C:\Users\User\runtime-EclipseApplication\Hello\bin;C:\Users\User\workspace\org.junit\junit.jar;"C:\Program Files\eclipse\plugins\org.hamcrest.core_1.1.0.v20090501071000.jar" org.eclipse.contribution.junit.SocketTestRunner 41872 org.eclipse.contribution.hello.HelloTest

When I use this command manually, I can run the test case succeed(after comments the socket related writer), as I can get test log.

main
41872
org.eclipse.contribution.hello.HelloTest
port: 41872
openClientSocket
Befor new TestSuite
add TestSuite
starting tests 1
Before TestResult
After TestResult
starting test testSayHi(org.eclipse.contribution.hello.HelloTest)
failing test testSayHi(org.eclipse.contribution.hello.HelloTest)
END TRACE
ending tests 
closeClientSocket

Any advise will be appreciated, Thanks.

Finally I get this plugin to run.
You should set working directory.

vmConfig.setWorkingDirectory("C:\\Users\\User");

When I try to get working directory, I get null.

You can't set breakpoint at the line which invoke connect() function.

private void connect() {
    try {
        ServerSocket server = new ServerSocket(port);
        try {
            Socket socket = server.accept();
            try {
                readMessage(socket);
            } finally {
                socket.close();
            }
        } finally {
            server.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

But I don't know why, any advise will be appreciated.