cgal/Packages/Developers_manual/java_demos.tex

415 lines
19 KiB
TeX

% =============================================================================
% The CGAL Developers' Manual
% Chapter: The CGAL Java Demo Server
% -----------------------------------------------------------------------------
% file : java_demos.tex
% authors: Francois Rebufat <Francois.Rebufat@sophia.inria.fr>
% -----------------------------------------------------------------------------
% $Revision$
% $Date$
% =============================================================================
\chapter{The \cgal\ Java Demo Server}
\label{chap:java_demos}
\ccChapterRelease{Chapter Version: 1.0} \\
\ccChapterAuthor{Fran\c cois Rebufat (\texttt{Francois.Rebufat@sophia.inria.fr})}
\ccIndexMainItemBegin{Java demo server}
The internet is one of the best ways to present, promote, and distribute
application software and libraries. Commonly, web sites
offer a textual description of the software product, online (or
downloadable) documentation, the possibility to download the software
itself, and sometimes a demo version (often limited in its features)
that interested users can download and install to test if the software
fulfills their needs.
To decide upon the applicability and usability of a software product,
a potential user generally has no other alternative than to download
the software and go though the sometimes difficult installation process.
This step often discourages users since installation frequently
does not work as it should.
The \cgal\ Java demo server presents an alternative method of
evaluating the library. The demo server provides a Java applet that accepts
input from the user, stores it, ships it to a local server, which performs the
desired computation on the data using \cgal, and then ships the results back
to the client web navigator where the results are displayed.
To achieve this, two obstacles must be overcome:
\begin{itemize}
\item enabling an interface between Java applets and programs written in
another language (\CC\ for \cgal)
\item distributing data through the web, between the Java applet and the
\cgal\ server.
\end{itemize}
Two new Java tools, \ccAnchor{http://java.sun.com/products/jdk/1.1/docs/guide/jni/}{Java Native Interface} (JNI) and \ccAnchor{http://java.sun.com/products/jdk/1.1/docs/guide/rmi/}{Remote Methods Invocation}
(RMI), were chosen as the means to overcome these obstacles.
In the following, we will briefly present these tools and describe in
detail how we built the online \cgal\ demo. We do not provide a
complete introduction to JNI and RMI and invite interested programmers
to have a look at the \ccAnchor{http://www.javasoft.com}{javasoft} reference
pages \lcTex{(\path|http://www.javasoft.com|)} for more details. The solutions
we chose and the structure we present are not unique and smart programmers will
probably find their own way through the JNI and RMI process.
\section{The Java tools : JNI and RMI}
\label{sec:jmi_and_rmi}
The JNI and RMI tools are parts of
\ccAnchor{http://java.sun.com/products/jdk/1.1/}{JDK-1.1}.
By using these tools, we simulate a multi-language
object distributed application through the web. Since the Java security
manager is enabled, security is guaranteed for the client and the server.
This kind of application could rapidly become messy and error
prone. For this reason, we describe with simple pseudo-code how to
deal with JNI and RMI before explaining the \cgal\ demo.
\subsection{The JNI part}
\label{sec:jni_part}
\ccIndexSubitemBegin{Java demo server}{JNI}
The JNI allows Java code that runs within a Java Virtual Machine
to operate with applications and libraries written in other languages,
such as C or \CC. For this, JNI defines standardized naming
and calling conventions used by the Java Virtual Machine to call
native methods and functions.
A minimal JNI application consists of five files :
\begin{description}
\item[{\tt foo\_prog.C}] A native-language (\eg, \CC) program
that implements, let's say, a function named \ccc{foo()}.
\item[{\tt N\_foo.java}] A Java class that declares the
Java function \ccc{cpp_foo()} as a native function. This class uses the
JNI loading method \ccc{System.loadLibrary("libfoo")} to establish that
the implementation of the native function is in the \texttt{libfoo.so}.
(We will see later how \texttt{libfoo.so} is built.)
\item[{\tt N\_0005ffoo.h}] An header file automatically obtained
from \ccc{N_foo.java} by compiling it with the \texttt{javah -jni}
command. This file declares, using the JNI naming convention, the
\ccc{Java_N_1foo()} function interface between the Java \ccc{cpp_foo()}
and the \CC\ \ccc{foo()} function.
\item[{\tt N\_implementation\_foo.C}] Implements the
\ccc{Java_N_1foo()} function that calls the \CC\ \ccc{foo()} function.
\item[{\tt libfoo.so}] A dynamic library that contains
the functions \ccc{foo()} defined in \texttt{foo\_prog.C} and
\ccc{N_implementation_foo.C}.
\end{description}
Figure~\ref{fig:jni_files} shows the five files and their
interdependencies.
\begin{figure}
\begin{ccTexOnly}
\begin{center}
\includegraphics[width=14cm]{jnis.eps}
\end{center}
\end{ccTexOnly}
\caption{The files of a minimal JNI application.
\label{fig:jni_files}}
\begin{ccHtmlOnly}
<CENTER>
<IMG BORDER=0 SRC="images/jnis.gif" ALIGN=center ALT="JNI files"> <BR>
</CENTER>
\end{ccHtmlOnly}
\end{figure}
In the main Java program (or applet), we will call the \ccc{cpp_foo()}
member function of the class \ccc{N_foo}. This function knows that it is a
native implementation and can find its definition in the \texttt{libfoo.so}
file.
All these functions and methods are parametrized and can exchange
their resulting values. We will explain in the case of the \cgal\ demo
how we chose to do that in Section~\ref{sec:cgal_demo}.
\ccIndexSubitemEnd{Java demo server}{JNI}
\subsection{The RMI part}
\label{sec:rmi_part}
\ccIndexSubitemBegin{Java demo server}{RMI}
\begin{quote}
RMI enables the programmer to create distributed Java-to-Java applications, in
which the methods of remote JavaTM objects can be invoked from other Java
virtual machines, possibly on different hosts. A Java technology program can
make a call on a remote object once it obtains a reference to the remote
object, either by looking up the remote object in the bootstrap-naming service
provided by RMI, or by receiving the reference as an argument or a return
value. A client can call a remote object in a server, and that server can also
be a client of other remote objects. RMI uses Object Serialization to marshal
and unmarshal parameters and does not truncate types, supporting true
object-oriented polymorphism.
\hspace*{\fill}{\em JDK documentation (Javasoft)}
\end{quote}
We will neither discuss nor explain the whole structure of RMI
mechanism here, since it is a fairly complicated thing (refer to the
the \ccAnchor{http://java.sun.com/products/jdk/1.1/docs/guide/rmi/}{javasoft
reference pages}\lcTex{\footnote{\path|http://www.javasoft.com/products/jdk/1.1/docs/guide/rmi/index.html|}}).
Globally RMI works as follows. An RMI
server is declared and bound to the httpd server of the local
server. A remote object, \texttt{Remote\_object}, that implements a
remote interface is declared on this server. \texttt{Remote\_object}
distributes data members
and methods between the server and the client sides by using
``stub'' and ``skeleton'' layers that are directly built
from \texttt{Remote\_object}. The stub is the client-side interface for
\texttt{Remote\_object}, while the skeleton is the server-side interface.
The following figure describes the general structure of RMI.
\begin{ccTexOnly}
\begin{center}
\includegraphics[width=14cm]{rmi.eps}
\end{center}
\end{ccTexOnly}
\begin{ccHtmlOnly}
<CENTER>
<img border=0 src="images/rmi.gif" align=center alt="RMI structure">
</CENTER>
\end{ccHtmlOnly}
The remote reference layer deals with the lower-level transport
interface. This layer is also responsible for carrying out a specific
remote reference protocol, which is independent of the client stubs and
server skeletons.
The transport layer deals with connections and listening for calls and
maintains a table of remote objects that reside in the address space.
As we did for the JNI part, we present here a set of files that illustrate
a minimal implementation using RMI. The programer has to write
three files: the applet itself, an interface for the remote object,
and the remote object itself. Two other files, the stub and the skeleton,
are generated from the remote object.
\begin{description}
\item[{\tt RemoteInterface.java}] A public Java interface that
declares all the functions used remotly by the remote object.
\item[{\tt RemoteObject.java}] A public Java class that
implements the RemoteInterface. The functions declared in the interface
are implemented and distributed object data members are defined. It
contains a main function to set an RMI security manager and to bind
the object to the RMI server.
\item[{\tt Myapplet.java}] An applet that declares objects of type
\ccc{RemoteInterface} and applies functions from the interface to them.
\item[{\tt RemoteObject\_Skel.class}, {\tt RemoteObject\_Stub.class}]
These two files are automatically obtained by using the RMI compiler
with the following command: {\tt rmic RemoteObject}.
\end{description}
The following picture shows the main content of the first three
files.
\begin{ccTexOnly}
\begin{center}
\includegraphics[width=13cm]{rmifile.eps}
\end{center}
\end{ccTexOnly}
\begin{ccHtmlOnly}
<CENTER>
<img border=0 src="images/rmifile.gif" align=center alt="RMI structure">
</CENTER>
\end{ccHtmlOnly}
\ccIndexSubitemEnd{Java demo server}{RMI}
\section{The \cgal\ demo}
\label{sec:cgal_demo}
You can see this demo and download the source files from
\path|http://cgal.inria.fr/|
As there are two separate parts, the JNI and RMI parts, we split the
demo files in two directories \texttt{jni} and \texttt{rmi}.
In the following two sections, we describe both these directories and
explain step by step how to build executable
files. Then, a simulation of the execution of the two parts will show
how calls are managed and objects and variables distributed.
\subsection{The \texttt{jni} directory}
\label{sec:jni_directory}
\index{Java\ demo\ server!\texttt{jni} directory|(}
The files contained in this directory are exactly the same as those
described in the Section~\ref{sec:jni_part}, except that there are more
\CC\ files -- one for each \cgal\ object shown in the demo.
The four files, \texttt{ConvexHull.C}, \texttt{cgal\_triangulation.C},
\texttt{polygons\_operations.C} and \texttt{triangulation\_operation.C}
define their own
objects and member functions that directly use \cgal\ objects and
functions.
For instance, \texttt{ConvexHull.C} implements a class \ccc{Cpp_Convexhull}
with three data members, two arrays of \ccc{long}s for the point set
$x$- and $y$-coordinates and one integer to store the total number of
points. It has one member function, \ccc{ConvexHull}, that computes the
convex hull of the point set, returns its size and stores the result
in two arrays.
The file \texttt{N\_Operation.java} declares the JNI interface functions and
loads their definitions in the \texttt{linjni.so} library.
The file \texttt{NimpOperations.C} implements these functions.
Arguments and results are passed by pointers (arrays).
\subsubsection{Adding functionality in the \texttt{jni} directory}
\label{sec:new_jni_functionality}
\index{Java\ demo\ server!adding functionality|(}
To add some functionality, you have to perform the following steps:
\begin{itemize}
\item Edit a new file, for instance \texttt{new\_object.C},
that defines and implements the class for the object you want to add
and the functionality on this object. Add \texttt{new\_object.o} to
the list of objects files in the makefile.
\item Edit \texttt{N\_Operations.java} and add a function
that corresponds to the one written in the \texttt{new\_object.C} file.
Compile \texttt{N\_Operations.java} using: \\
\centerline{\texttt{javac N\_Operations.java }}
\item Build the header \texttt{N\_0005fOperations.h}: \\
\centerline{\texttt{javah -jni N\_Operations}}
\item Edit the file \texttt{NimpOperations.C} and add the
definition of the function corresponding to the one you've added in
the \texttt{N\_Operations.java}. The syntax of this function must
correspond exactly to the one defined in the \texttt{N\_0005fOperations.h}
header file (copy and paste it).
\item Set your {\tt LD\_LIBRARY\_PATH} variable
\index{LD_LIBRARY_PATH variable@{\tt LD\_LIBRARY\_PATH} variable!for Java demo}
so it
contains the path of \texttt{libCGAL}, \texttt{libLEDA} (if \leda\ is
used) and the \texttt{jni} directory. Set the \texttt{CLASSPATH} variable
\index{CLASSPATH variable@{\tt CLASSPATH} variable}
as for any Java application.
Type {\tt make} to build all the ".o" files
and the \texttt{libjni.so} library.
\end{itemize}
\index{Java\ demo\ server!adding functionality|)}
\index{Java\ demo\ server!\texttt{jni} directory|)}
\subsection{The \texttt{rmi} directory}
\label{sec:rmi_directory}
\index{Java\ demo\ server!\texttt{rmi} directory|(}
We assume that the reader knows what an applet is and how events are
handled in Java. The \texttt{rmi} directory contains only Java files, so
knowing a little bit of Java is necessary to read the different files it
contains. The structure as described in Section~\ref{sec:rmi_part}.
The applet is named \texttt{CgalApplet} and contains the applet
itself, a class named \ccc{PointZone} that extends \ccc{Canvas} and deals
with the graphical part of the application, a class \ccc{Zone} that defines
remote objects, contains methods to build them, tries to look for the RMI
server and records remote objects. The \ccc{Zone} class also defines
functions that call remote functions and stores results and data into its
data members. Several classes, such as \ccc{MouseAdapter} and \ccc{Point_set}
are defined for convenience.
The two others files in this directory are \texttt{RemoteInterfaceOperations.java}
and \texttt{OperationsImpl.java}. They contain remote functions
to compute the several functionalities the demo offers and \ccc{get}
methods to send results to the applet.
All data are stored in arrays of integers that contain either $x$ or $y$
coordinates. Thus, a whole set of points is stored in two arrays. We
define four pairs of arrays :
{\bf Input arrays } : Store data (the user's set of points) that is
produced by clicking on the screen. The arrays \ccc{X} and \ccc{Y}
contain the base set of point, and the arrays \ccc{Xs} and \ccc{Ys} contain
special points such as segments extremities used for the line-face circulator.
{\bf Output arrays } : Store the results of computation. As for the input
arrays, there are two pairs of output arrays:
\ccc{X_c}, \ccc{Y_c} for the global
results (such as for convex hull, triangulation) and
\ccc{Xs_c}, \ccc{Ys_c} for additional results such as the faces
traversed by a line-face circulator.
\subsubsection{Adding functionality in the \texttt{rmi} directory}
\label{sec:new_rmi_functionality}
\index{Java\ demo\ server!adding functionality|(}
Adding only new events, or automatically generated sets of points does
not involve the RMI part. Only the applet and the event manager must
be completed and this is pure java programming. To add new
functionality (\eg, Voronoi diagrams) follow the steps outlined in
Section~\ref{sec:new_jni_functionality} to add the functionality to the
\texttt{jni} directory. Then proceed as follows :
\begin{itemize}
\item Edit the \texttt{RemoteInterfaceOperations.java} file
and add a new function. For the sake of example, let's call it
\ccc{voronoi}. Compile this file using the command: \\
\centerline{\texttt{javac RemoteInterfaceOperations.java}}
\item Edit the \texttt{OperationsImpl.java} file
and define the new \ccc{voronoi} function. The core of the
\ccc{voronoi} function will build a new object of type
\ccc{N_Operations} (JNI part) and call \ccc{cpp_voronoi}
defined in the \texttt{N\_Operation.java} file. Here is the link
between the JNI and the RMI parts. Compile \texttt{OperationsImpl.java}:
\\
\centerline{\texttt{javac OperationsImpl.java}}
The \texttt{LD\_LIBRARY\_PATH} and \texttt{CLASSPATH} must contain the
\index{LD_LIBRARY_PATH variable@{\tt LD\_LIBRARY\_PATH} variable!for Java demo}
\index{CLASSPATH variable@{\tt CLASSPATH} variable}
path of the JNI part in order for it to find the file
\texttt{N\_Operation.class}.
\item Build the stub and skeleton files: \\
\centerline{\texttt{rmic OperationsImpl}}
\item Edit the \texttt{CgalApplet.java} and add your new
functionnality in the menu, define how to draw your object, and use the
\ccc{Zone} constructor to build a new remote object. Compile the applet: \\
\centerline{\texttt{javac CgalApplet.java}}
\end{itemize}
Now that everything is compiled, you have to launch the RMI Bootstrap
Registry:
\\
\centerline{\texttt{rmiregistry \&}}
Then launch the code server:
\centerline{\texttt{java -Djava.rmi.server.codebase=http://cgal.inria.fr/DEMO/rmi/OperationsImpl \&}}
The server should answer: \texttt{server bound in registry}.
\index{Java\ demo\ server!adding functionality|)}
\index{Java\ demo\ server!\texttt{rmi} directory|)}
\subsubsection{Through the global process: A convex hull example}
\label{sec:java_demo_example}
We describe the entire process for the example when points are entered
with the mouse by the user and then "convex hull" is chosen from the
menu.
Each time the user presses the left mouse button in the graphic
canvas, $x$- and $y$-coordinates are sent and stored in \ccc{X}, \ccc{Y} arrays
(in class \ccc{Zone}). Selecting ``convex hull'' from the menu causes
the applet's \ccc{redraw} method to be called. The \ccc{redraw} method
chooses the \ccc{convex_hull} drawing method that
calls the \ccc{convex_hull} method in the class \ccc{Zone}.
The \ccc{convex_hull} method from the class \ccc{OperationsImpl.class}
is then called upon the \ccc{Zone} data member \ccc{convex_remote}.
An \ccc{N_Operations} object is built and the method
\ccc{cpp_convex_hull(X,Y,number_of_points,Xresult,Yresult)}
is executed on it. Here, \ccc{Xresult} and \ccc{YResult} will store the
results as member of the object \ccc{convex_remote}.
In the JNI part, \ccc{cpp_convex_hull} translates java arrays
to \CC\ arrays, builds an object of the class \ccc{Cpp_ConvexHull}
(defined in \texttt{Convex\_hull.C}) and applies \ccc{ConvexHull(X_c,Y_c)}
to it. The results are stored in the arguments of this function (\ccc{X_c}
and \ccc{Y_c}), then sent to the arguments corresponding to
\ccc{Xresult} and \ccc{Yresult} in the call to \ccc{cpp_convex_hull},
stored in the data members of the \ccc{convex_remote} object, and grabbed
by the Java applet by using the \ccc{getXresult} and \ccc{getYresult} methods.
The applet then displays what is stored in the \ccc{X_c} and \ccc{Y_c} arrays.
\ccIndexMainItemEnd{Java demo server}