views:

77

answers:

2

Here is the error:

Exception in thread "main" java.lang.NoClassDefFoundError: org/alicebot/server/net/AliceServer
Caused by: java.lang.ClassNotFoundException: org.alicebot.server.net.AliceServer
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

This is the server.sh file:

#!/bin/sh
echo Starting Jarvis Program D.
cd "`dirname \"$0\"`"
export ALICE_HOME=.
export SERVLET_LIB=lib/servlet.jar
export ALICE_LIB=lib/aliceserver.jar
export JS_LIB=lib/js.jar

# Set SQL_LIB to the location of your database driver.
export SQL_LIB=lib/mysql_comp.jar

# These are for Jetty; you will want to change these if you are using a different http server.
export HTTP_SERVER_LIBS=lib/org.mortbay.jetty.jar

export PROGRAMD_CLASSPATH=$SERVLET_LIB:$ALICE_LIB:$JS_LIB:$SQL_LIB:$HTTP_SERVER_LIBS
exec java -classpath $PROGRAMD_CLASSPATH -Xms64m -Xmx128m org.alicebot.server.net.AliceServer $1

Here is the NSTask code:

NSString *shstring = [NSString stringWithFormat:
                          @"%@ %@ %@", 
                          @"source", 
                          @"server.sh", 
                          @"| /usr/bin/sed '/Jarvis>/q'"
                          ];

NSTask *sh = [NSTask new];
    NSPipe *outputPipe = [NSPipe new];

    [sh setLaunchPath:@"/bin/sh"];
    [sh setArguments:[NSArray arrayWithObjects: @"-c", shstring, nil ]];
    [sh setCurrentDirectoryPath:@"/applications/jarvis/brain"];
    [sh setStandardInput:[NSPipe new]];
    [sh setStandardError:outputPipe];
    [sh setStandardOutput:outputPipe];
    [sh launch];

    NSMutableString *outputString = [NSMutableString string];
    while ([outputString rangeOfString:@"Jarvis>"].location == NSNotFound) {
        [outputString appendString:[[[NSString alloc] initWithData:[[outputPipe fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding] autorelease]];
        NSRunAlertPanel(@"", outputString, @"", @"", @"");
    }

When ever I run this script through NSTask and I check the error pipe, that error comes up and only prints the echo.

Any ideas?

A: 

It much look like that the working directory is not what you expect it is. You're defining relative paths in the classpath argument. They are relative to the current working directory. Likely the current working directory doesn't know about a lib/aliceserver.jar file. Do a pwd to learn about the current working directory.

BalusC
can you show an example of using pwd?
Elijah W.
Oh, were it all copypastes? Given the code in the question I'd expect that you're a bit familiar with shell commands. It's just a shell command like `echo`, `dirname` and so on :) Here's a [related question](http://stackoverflow.com/questions/59895/can-a-bash-script-tell-what-directory-its-in), it might help you further.
BalusC
PWN printed /bin, I don't think is correct. When I put "applications/jarvis/brain/" (which is where the main ALICE folder is), my code freezes. I'm lost. Can you please take a look at the code I posted and see if you can find anything?
Elijah W.
A: 

Replace relative with absolute paths in server.sh, then run server.sh with complete path (do not source server.sh in your NSTask code if server.sh has the shebang line and always check the exit code of the cd command).

Here's my server.sh file:

#!/bin/sh
# cat ~/Desktop/charliebot/server.sh

# code from: http://sourceforge.net/projects/charliebot/

# also adapt the following files if necessary:
# ~/Desktop/charliebot/console.sh
# ~/Desktop/charliebot/targeting.sh
# ~/Desktop/charliebot/tester.sh

echo Starting Alicebot Program D.
ALICE_HOME="${HOME}/Desktop/charliebot"

cd "${ALICE_HOME}" || { echo "Could not cd to: ${ALICE_HOME}"; exit 1; }

SERVLET_LIB="${ALICE_HOME}/lib/servlet.jar"
ALICE_LIB="${ALICE_HOME}/lib/aliceserver.jar"
JS_LIB="${ALICE_HOME}/lib/js.jar"

# Set SQL_LIB to the location of your database driver.
SQL_LIB="${ALICE_HOME}/lib/mysql_comp.jar"

# These are for Jetty; you will want to change these if you are using a different http server.
HTTP_SERVER_LIBS="${ALICE_HOME}/lib/org.mortbay.jetty.jar"

PROGRAMD_CLASSPATH="${SERVLET_LIB}:${ALICE_LIB}:${JS_LIB}:${SQL_LIB}:${HTTP_SERVER_LIBS}"

export ALICE_HOME SERVLET_LIB ALICE_LIB JS_LIB HTTP_SERVER_LIBS PROGRAMD_CLASSPATH

#printf "\n\n\nPROGRAMD_CLASSPATH\n%s\n\n\n"  "$PROGRAMD_CLASSPATH" | tr ':' '\n'

exec java -classpath "$PROGRAMD_CLASSPATH" -Xms64m -Xmx128m org.alicebot.server.net.AliceServer $1

This works for me without the slightest hiccup.

# in Terminal.app
~/Desktop/charliebot/server.sh

I don't think the argument $1 to server.sh is obligatory. If that were the case, server.sh (i.e. exec java -classpath ...$1) would complain about it. But yes, it would be nice to know what kind of argument could be passed as $1 to server.sh (... reading man 1 java ...)!

All this, of course, does not remove your Objective-C while loop deadlock (NSNotFound). You have to implement an asynchronous stdout pipe reading mechanism instead of a while loop. (See, for example, Apple's "Dashboard Programming Topics" on asynchronous operations for such an approach.)

greg