SciCo is a package of Collaborative tools aimed at scientific
Problem Solving Environments.
It started by writing down a chat using serialized messages objects, therefore
allowing a much more scalable infrastructure than only string
messages.
A general view of the system can be seen on the following picture:
Because of the nature of this architecture, getting the
ObjectInputStreams and ObjectOutputStreams to work was a little bit of
a hassle;
the server sender thread (SSender_Thread, that calls the ObjectInputStream) is started before
the server receiver thread (SReceiver_Thread, that calls the
ObjectOutputStream) but is put on wait by the call to getting the next
object off the ObjectQueue that has not yet notified until the
receiver thread gets the name of the user from the receiver
thread.
This made the declaration of a single ObjectOutput/InputStream work
very unreliably (but some testing needs to be done since the
modification of the ObjectQueue semaphores).
Therefore, the communication calls a new ObjectIn/OutputStream at each
request on both sides and never closes it (because when a call is
blocked on a readObject, it is pulling from the InputStream expecting
the Object's header, if the stream is closed, it generates a type
unknown exception for what is received from the readObject.
WhiteBoard objects and event handling
Drawing on a background image is done by :
1- creating an off-sreen image
2- painting the image (only once) on the off-screen image graphics context
3- performing any additional drawing on the off-screen image
4- painting the off-screen image to the screen's graphical context.
Here is some code for it:
constructor()
{
imageJPG=Toolkit.getDefaultToolkit("myimage.jpg");
MediaTracker media = new MediaTracker(this);
media.addImage(imageJPG,0);
}
void initialize()
{
image=createImage(width,height);
IG=image.getGraphics();
}
void paint(Graphics g)
{
if(!IS_BACKGROUND_PAINTED)
{
initialize();
IG.drawImage(imageJPG,0,0,this);
while(!media.checkID(0)) {IS_BACKGROUND_PAINTED=false;return;}
IS_BACKGROUND_PAINTED=true;
}
g.drawImage(image,0,0,this);
}
The whiteboard tools:
Pen,Line,Box,Text
Running the Server as a Service
Before running the SciCo server as a service the system outs and errs
should be redirected to a log file.
File log = new File("/path/to/log");
FileOutputStream out = new FileOutputStream(file);
System.setOut(out);
System.setErr(out);
FireDaemon (at
http://www.firedaemon.com is a
free utility that does the same job as Windows resource kit's
srvany/instsrv.
The service can be added by writing a Batch file:
@echo on
set SCICOSRV_HOME=e:\Vincent\work\SciCo\Server\class\
set JAVA_HOME=D:\JDK1.2.2
set JAVA_BIN=%JAVA_HOME%\bin
set _CLASSPATH=%CLASSPATH%
set _PATH=%PATH%
set CLASSPATH=%CLASSPATH%;%JAVA_HOME%\lib\tools.jar
set CLASSPATH=%CLASSPATH%;%SCICOSRV_HOME%
set PATH=%PATH%;%JAVA_BIN%
%JAVA_BIN%\java.exe SciCo_Server
set CLASSPATH=%_CLASSPATH%
set PATH=%_PATH%
And adding this batch file as the actual executable in
firedaemon.
The problem of this procedure is that the java process is
orphaned.
Another more robust way to start the service is from the command
line:
FireDaemon -i SciCoSrv \
e:\Vincent\work\SciCo\Server\class d:\jdk1.2.2\bin\java.exe "-cp \
e:\Vincent\work\SciCo\Server\class SciCo_Server" Y 1 0 Y N
Where the sequence Y 1 0 Y N stands for:
Restart ?
Mask (0-14)
Priority (0-3)
Interact ?
Autostart ?
Selecting the background image in the Canvas
Because of the security restrictions of Java applets, this feature can
only be made available in the application version; (unless the applet
gets signed.
The idea is to choose an image recognizable by Java Graphics
(JPEG,GIF, or PNG) from the FileDialog, and send it to the server as
a serialized object
Sending the File object directly to the client unfortunately won't work (the client will not get the content of the file but only information on where to access the file on his local filesystem).
So in order to share the image, it has to be read byte by byte, sent accross to the server who will broadcast it to all the clients.
Upon receiving the file, each client will create a file from the raw data and display it as a background.
From the client selecting the file:
int length=theSelectedFile.length();
FileInputStream freader = new FileInputStream(theSelectedFile);
Serial_File sfile = new Serial_File(length,theSelectedFile.getName());
while((c=freader.read())!=-1)
sfile.write(c);
sfile.write(-1);
freader.close();
SciCo_Client.sendObject(sfile);
At this point the Serial_File is sent to the server; who then broadcasts it to each client who in turn request to show it as a background image:
(Serial_File theReceivedFile)
File newfile = new File(theReceivedFile.getName());
FileOutputStream fwriter = new FileOutputStream(newfile);
while((c=theReceivedFile.read())!=-1)
fwriter.write(c);
Image image=Toolkit.getDefaultToolkit().getImage(newfile.getName());
displayIt();
The newfile creates a new file every time a file is received because apparently Toolkit's implementation of getImage somehow caches an image of a certain name so reusing the same name for evvery new file (saving space) did not work but this point needs to be clarified.
Another point is that the use of an FileInputStream/OutputStream as opposed to a FileReader/Writer not only allows this code to work (not corrupting the data) but is also much faster (because it is a bytestream).
Bugs & TODO
While running as an applet: Once the client disconnects he/she cannot reconnect yet,he/she has to
refresh the browser by clearing the cache (Ctrl-Refresh)
The tools do not always respond properly to a selection action in the
tools Panel (unknown reason)