2008/04/22

Some detailes about code

Sources are available to download as an archive on sourceforge (fcshWrapper-src.0.1.2.tgz). Or can be checked out from CSV.

Unfortunately I made the wrapper to run only on Windows because is all that I need. But it can be easily modified to run on other platforms (Windows specific is jdic from dev.java.net that makes the app available in system tray and some hardcoded calls to fcsh.exe).

If the LoggingFrame is made abstract and an implementation redirect the fcsh output to a file and then the TaskbarStatusArea is removed or is made to be a generic notification system on errors, the wrapper can be made available to an OS without a graphical user interface.

As I see now, in java 6, there is a built in support for system tray, but i don't see any jvm 6 for Mac. And jdic has support only for Windows/Linux/Solaris. So, sorry for Mac users (maybe a version without sys tray).

Classes:

AntTaskGateway.java
CommandArg.java
CommandsHistory.java
FcshCommandHandler.java
FcshCommandListener.java
FcshProcessWrapper.java
FcshTask.java
LoggingFrame.java
Main.java
TaskbarStatusArea.java
WrapperCreator.java

This is the story:

ANT calls FcshTask's execute() method that instantiate an AntTaskGateway ant call his send(command, args) function.

AntTaskGateway first tries to create a socket connection on localhost (initConnection() method that calls connect()), then it simply serialize to the socket the command and his arguments and wait for the response from fcsh.exe.

If initConnection() fails, the build fails. If the first call to the connect() fails, initConnection() creates a WrapperCreator ant calls the method startAndWaitForInit().

WrapperCreator.startAndWaitForInit() start the ro.arhinet.fcshwrapper.wrapper.Main (that is a main class) in a separate process. Then capture the subprocess output and wait for a signal that all is initialized OK. If something goes wrong the build fail.

That's almost all for the first part. The ANT process exits, but the lunched subprocess stays up and listen for upcoming compile commands.

The main class of the wcshWrapper process is ro.arhinet.fcshwrapper.wrapper.Main that luches 4 services:

public class Main{
    public static void main(String args[]) throws Exception {
        LoggingFrame.initUI();
        TaskbarStatusArea.initSysTray();
        FcshProcessWrapper.startFcshProcess();
        FcshCommandListener.startServer();
        System.out.println("[FCSH initalized]");
    }
}

A little to many singletons in a package wint 5 classes. But i look at these classes as services and services must be available anywhere via static calls.

LoggingFrame maintains history with issued command, the output from the fcsh and any other errors/messages. The service can be accessed via:

    public void logMessage(String content, String color)
    public void logMessage(String content)
    public void logError(String content)
    public void logFcshCommand(String content)
    public void logWarning(String content)
    public void logSystemError(String content, Throwable error)
    public void clearLog()

TaskbarStatusArea controls the visibility of the LoggingFrame and displays notification balloons. Services exposed:
    public static void reportErrorInSysTray(String title, String error)
    public static void reportErrorInSysTray(String title, Throwable error)
    public static void reportErrorInSysTray(Throwable error)

FcshProcessWrapper start the fcsh.exe subprocess on the time of his static initialization. It knows how to handle the subprocess output that redirects it to LoggingFrame and how to execute a command on the fcsh.exe.

FcshCommandListener listen for incoming connections and for each request create an instance of FcshCommandHandler that manage the communication with the client.

FcshCommandHandler works with other service: CommandsHistory that maintains a HashMap of issued fcsh commands using the md5 of the command (+args.) for hash keys. Each entry in the HashMap contains the id allocated by the fcsh.exe for that command.

0 Comments: