   This file documents the Java-Like Library 2.

1 Java vs. C plus plus
**********************

1.1 Garbage Collection
======================

One of Java's most important features is automatic garbage collection
which is handled by the Java Virtual Machine. This allows the programmer
to create new objects without having to worry when to free or delete
them. From time to time the garbage collector goes through the whole
heap memory and frees all objects that are not referenced any longer.

   Unfortunately C or C++ does not provide an automatic garbage
collector. But there are garbage collector libraries out there that can
be used instead. Jakelib2 uses Hans-J. Boehm's garbage collector
(`http://www.hpl.hp.com/personal/Hans_Boehm/gc/').  So this garbage
collector library seems to be the limiting factor for jakelib's
protability: If the gc can be compiled and does work for a certain
platform, jakelib2 should also work. If not, one will have to find out
why and fix the issue!

   The gc provides a class named `gc_cleanup'. All classes derived from
this base class will be automatically garbage collected and their
destructor (finalizer) will be called before disposal. This is why
jakelib's counterpart to Java's `java.lang.Object' -
`jakelib::lang::Object' - is derived from `gc_cleanup', so that all of
jakelib's classes will be garbage collected.

   The garbage collector does not scan arrays allocated by the standard
`malloc' functions. Objects that are referenced only from such arrays
will probably be deleted by the gc. The new functions `GC_MALLOC',
`GC_REALLOC' and `GC_FREE' can be used to allocate and free memory that
the gc will scan. This is absolutely necessary when storing references
in an array like it is done in `jakelib::util::ArrayList'. On the other
hand, a byte buffer for IO operations can be allocated using standard
`malloc' since it will not contain any references to objects.

1.1.1 Problems
--------------

The gc will not guarantee that every single object will be freed if it
is not referenced any longer. However, it seems that the amount of
uncollected objects stays quite stable throughout a program's runtime.
Practice shows that we don't need to worry too much about this issue.
But one should keep in mind that there is no guarantee!  Thus it's
useful to provide some classes with methods like `destroy' or `close'
that allow to release the acquired resources explicitely (i.e. close a
file or free a large buffer).

   If a set of objects is referenced cyclically, the garbage collector
won't finalize (i.e. call the object's destructor) these objects before
disposing of them because there is no way to determine a safe order to
finalize and free the objects one by one.

1.2 Primitive data types
========================

Java offers a set of well defined primitive data types:

     Type name   size in bits
     boolean         1
     byte            8
     short           16
     int             32
     long            64
     float           32
     double          64
     char            16

   When programming in C or C++ the size of a certain primitive type
depends on the platform you are actually using. This is why jakelib
provides a set of typedefs that are defined in `include/jakelib2.h'.
The names of these typedefs all start with a lower case `j'. It depends
on the certain platform which types are used to represent a `jint' or a
`jlong'.

   On an Intel/Linux system the following substitutions are done:

     Type name   C type
     jboolean    int
     jbyte       char
     jshort      short
     jint        int
     jlong       long long
     jfloat      float
     jdouble     double
     jchar       unsigned short

   A `jboolean' variable should be assigned either `true' (`=1') or
`false' (`=0') only. `TRUE' and `FALSE' should not be used. `null' is
an alias for `NULL' and should be used instead.

1.3 Interfaces and Classes
==========================

In jakelib every class should be derived from `jakelib::lang::Object'
like all Java classes are derived from `java.lang.Object'. As C++ does
not know interfaces in opposition to real classes, jakelib uses
abstract classes as a substitution for Java's interfaces. These
interface classes are not derived from `jakelib::lang::Interface'.

1.4 Arrays
==========

To provide a portable way to work with typed arrays, Jakelib2 uses a
special class for every data type to be stored. Templates are not used
because they are known to cause problems on certain compilers. However,
the result would actually be quite the same.

1.4.1 Primitive data types
--------------------------

1-dimensional array classes are already implemented for all of
Jakelib2's primitive data types: `jchar', `jbyte', `jint', `jlong',
`jfloat', `jdouble', `jboolean' and `jshort'.

   The array classes have the name of the original data type with an
'`s'' append to express the plural: `jchars', `jbytes', `jints',
`jlongs', `jfloats', `jdoubles', `jbooleans' and `jshorts'.

   Example:
     jints* arr = new jints(10);

     for (int idx = 0; idx < arr->length(); idx++) {
       arr->set(idx, 100*idx);
     }
     for (int idx = 0; idx < arr->length(); idx++) {
       a = arr->get(idx);
     }

1.4.2 Objects
-------------

Jakelib2 provides two macros to declare and implement an array class for
a given `Object'-derivate: `JAKELIB2_DECLARE_ARRAY(classname)' declares
an array class (to be used in header files) and
`JAKELIB2_IMPLEMENT_ARRAY(classname)' implements the array class'
methods (to be used in `jlc'-files).

   These array classes provide the same operators and methods as those
for primitive data types.

   By now a 1-dimensional array for `String' objects has been
implemented. More classes will follow as needed.

1.5 Run Time Type Identification
================================

All classes derived from `jakelib::lang::Object' have extra type
information that allows RTTI (runtime type identification).

   Each Object provides a `.getClass()' method that returns its Class
object. `.instanceOf()' can be used to determine whether an object is
derived from a certian class.

   See API documentation for more details.

1.6 Exceptions
==============

In Jakelib all exceptions are created using `new' and thrown as
pointers. Example:
     try {
       ...
       throw new FileNotFoundException();
     }
     catch (Exception *ex) {
       System::out->println(ex);
     }

   The super-class for all exceptions should be
`jakelib::lang::Throwable'.

2 Compiling and Installing
**************************

Jakelib2 runs under GNU/Linux, Solaris, Win32 and probably some other
Unix-like systems.

   Jakelib depends on a couple of external libraries: Hans-J. Boehm's
garbage collector is absolutely needed to compile and use jakelib2.
Other libraries like pcre (Perl Compatible Regular Expressions) and
MySQL's client libs are optional.

2.1 The garbage collector
=========================

First thing to do is download version 6.0 of the garbage collector,
compile and install it. Hans-J. Boehm's garbage collector can be
downloaded directly from his own homepage
`http://www.hpl.hp.com/personal/Hans_Boehm/gc' or from
`http://www.jakelib.org'.

   Unpack the zipped tar archive:
       gunzip -c boehm-gc.tar.gz | tar x

   Cd into the extracted directory:
       cd gc6.0

   Configure, compile and install:
       ./configure --enable-threads=pthreads [--prefix=<GC_PREFIX>]
       make
       make install

   If you don't supply the `--prefix' option to `./configure', the
library files will be copied to `/usr/local/lib'.

2.2 Jakelib2
============

Now download the latest version of jakelib2 from
`http://www.jakelib.org'.

   Unpack the zipped archive:
     gunzip -c jakelib2-2.X.XX.tar.gz | tar x

   Cd into the extracted directory:
       cd jakelib2-2.X.XX

   Configure and compile:
       ./configure [--prefix=<JAKELIB_PREFIX>]
                   [--with-gc-dir=<GC_PREFIX>/lib]
       make

   If you don't supply the `--prefix' option to `./configure', the
library files will be copied to `/usr/lib' and include files will be
copied to `/usr/include'. If you didn't install the garbage collector
in the default location you'll need to supply the `--with-gc-dir'
option. Just set it to the directory where your `libgc.a' file is
located.

   If compilation succeeded, run
       make test

   to see if it works. The test program covers a wide range of
operations all across the library.

   Finally run
       make install
   to copy the library and include files to their target locations.

2.3 Additional external libraries
=================================

There are extension packages for Jakelib2 that make use of the following
libraries:

`pcre'
     Perl Compatible Regular Expressions (`http://www.pcre.org')

`mysqlclient'
     Client libraries for the MySQL data base (`http://www.mysql.org')

`GTK2'
     The Gimp Toolkit: A complete toolkit for GUI   programming.
     Intergration in Jakelib is not yet ready to be used!
     (`http://www.gtk.org')

3 Using Jakelib2
****************

Jakelib2 is a pure C++ library designed to be statically linked to C++
programs. To use Jakelib2 for your own projects, you need to have
several compiler options, include and library paths set. To simplify the
process of extending your makefiles accordingly, Jakelib2 provides the
`jakelib2-config' script.

   Just call `jakelib2-config' to see what options and actions are
supported.

   Examples:
`jakelib2-config --cppflags'
     Prints all compiler options including include directories to
     stdout.    The output of such a call of `jakelib2-config' is
     usually   appended to the `CPPFLAGS' variable in Makefiles.

`jakelib2-config --libs'
     Prints a list of all libraries to be linked to the user program.
     The output of such a call of `jakelib2-config' is usually
     appended to the `xxx_LDADD' variable in Makefiles.

`jakelib2-config --version'
     Prints the complete version number, like `2.0.0g'.

3.1 Starting a new project using Jakelib2
=========================================

Since Jakelib2 2.0.0j there is a simple but nice script called
`jakelib2-skeleton' that creates all files needed to compile and link a
program using Jakelib2.

   Just create a new directory, cd into it and run `jakelib2-skeleton
<projectname>'. If there were no errors you should be able to compile
your new project by running `make'. The linked executeable will be
called `src/<projectname>'.

   Edit the main source file to get a feeling for the whole thing:
`src/Main.jlc'.

   However, notice that `JAKELIB_INIT;' must be called in your program
(preferably in the `main()' function) before any other Jakelib2 object
is created or method called. `JAKELIB_INIT' is a macro that calls
`jakelib::lang::Object::initJakelib2()' which initializes several
classes (such as the default character conversion classes or the
standard input and output streams).

3.2 Debugging
=============

To debug your own programs written for Jakelib2 (or Jakelib itself ;-) )
I recommend using the famous GNU debugger gdb. You should have at least
gdb 5.2 since 5.0 (and prior) won't work when using pthreads.

   There are several GUIs providing an easier access to gdb:

`KDbg (1.2.5)'

`Data Display Debugger (DDD) 3.3'

4 Extending Jakelib2
********************

Jakelib uses `autoconf' and `automake' to create Makefiles and control
the compilation and linking process.

4.1 Understanding Jakelib
=========================

4.1.1 Directory structure
-------------------------

     jakelib2/
       +-- doc/
       |   +-- html/
       +-- include/
       |   +-- jakelib2/
       |       +-- gc/
       |       +-- gtk/
       |       +-- io/
       |       +-- lang/
       |       +-- lua/
       |       +-- net/
       |       +-- servlet/
       |       |   +-- http/
       |       +-- sql/
       |       +-- text/
       |       |   +-- enc/
       |       +-- util/
       |           +-- regex/
       +-- jlpp/
       |   +-- include/
       |   +-- lib/
       +-- src/
       |   +-- gtk/
       |   +-- io/
       |   +-- lang/
       |   +-- lua/
       |   +-- net/
       |   +-- servlet/
       |   |   +-- http/
       |   +-- sql/
       |   +-- test/
       |   +-- text/
       |   |   +-- enc/
       |   +-- util/
       |       +-- regex/
       +-- samples/

   The `include/jakelib2/' directory contains a subdirectory for each
`jakelib::' package. These subdirectories contain the header (`.h')
files, one for each class. Each subdirectory should also contain a
single header file that simply includes all header files in the
subdirectory (example: `include/jakelib2/util/all.h').

   The `src/' directory has a subdirectory for every package as well.
These subdirectories contain the source files: `.jlc' and `.cpp'. Each
class should have its own source file. If there is a `.jlc' file for a
certain class, this file will be automatically converted to `.cpp' by
the make process. In this case the `.cpp' file should not be modified
manually.

4.2 Coding style
================

4.2.1 Indentation
-----------------

Two spaces should be used as the unit of indentation. Avoid using tabs
whenever possible. However, tabs must be set exactly every 8 spaces
(not 4).

   If XEmacs is your text editor of choice, you won't have any problems
with this guidelines.

   Opening braces '`{'' should be set on the same code line where their
`if', `while', `for' or whatever statement is. Exception: braces after
class or method declarations. Closing braces should always be set on
their own empty line. Example:

     void foo(int n)
     {
       for (int idx = 0; idx < n; idx++) {
         if (doSomeThing(idx)) {
           ...
         }
         else {
           ...
         }
       }
     }

4.2.2 Naming conventions
------------------------

Classnames always start with a capital letter, method and variable names
start with a lower case letter. Underline characters (`_') are neither
used in class nor in method or variable names.

   Constant names are upper case and may contain underlines to make them
more readable.

4.2.3 Pointer operators
-----------------------

The pointer operator `*' should be written next to the variable name
rather than the type name:

     String *str = "aaaa";

   rather than

     String* str = "aaaa";

   The reason is that the pointer operator seems to belong to the
variable rather than to the type name as the following example
illustrates:

     String* str1, str2;

   This does not--as one might expect -- declare two pointer variables
*STR1 and *STR2 to `String'. It rather declares one pointer *STR1 and
one static instance STR2.  This is why you should write instead:

     String *str1, *str2;

4.3 Coding guide lines
======================

This section contains a set of rules that should be followed when
developing for Jakelib2. These rules are necessary to achieve a certain
level of platform independency.

   Some of the rules below are taken - or at least inspired by -
Mozilla's coding guide lines
(`http://www.mozilla.org/hacking/portable-cpp.html').

  1. Do not use C++ templates!

  2. Use pointers (`Object* obj') rather than C++ references (`Object&
     obj').

  3. We have a garbage collector! Methods may return `new' objects
     without worrying when to `delete' them.  See Garbage Collection.

  4. Don't use static initializers.  Code like this will definitely
     cause problems on one compiler or the other:

          Locale *MyClass::loc = Locale::getDefault();

     The problem is that the order in which such static initializers are
     called on program start-up is highly compiler-dependend. In this
     case the class `Locale' might not yet be initialized when
     `MyClass'' initializers are invoked.

  5. Every source file must have a unique name

4.4 Writing new classes
=======================

To add a new class to Jakelib, you should feel encouraged to follow
these steps:

4.4.1 Create a new header file
------------------------------

Create a new header file in the according package subdirectory in
`include/jakelib2/': The given file `include/jakelib2/template.h' can
serve as a template.

   The new header file should not contain more `#include' statements
than absolutely necessary. I.e., includes are necessary to make the
direct super class known. Classes that are just referenced as properties
or parameters for methods or constructors can be declared forward with
`class <classname>;'.

   Do not use `using namespace jakelib::...' to save time when typing
the class names! This should be done in the source files only. Instead
write the fully qualified class names if the desired class comes from a
different package, example: `jakelib::lang::String* text'.

   Example (header file `include/jakelib2/util/SampleClass.h' for class
`jakelib::util::SampleClass'):

     /*
      * Java-Like C++ Class Library
      * Copyright (C) 2001 Florian Wolff  (florian@donuz.de)
      * ...
      */

     #ifndef INCLUDE_JAKELIB2_UTIL_SAMPLECLASS_H
     # define INCLUDE_JAKELIB2_UTIL_SAMPLECLASS_H
     #include "../lang/Integer.h"

     namespace jakelib {
       namespace io {
         class OutputStream;
       }
       namespace util {
         class Iterator;

         /**
          * This class implements a streamable integer.
          * ...
          * @class SampleClass
          * @version $Id: jakelib2.texi,v 1.52 2006-02-18 12:25:28 florian Exp $
          * @author Your Name Here (email@foo.bar)
          */
         class SampleClass : public jakelib::lang::Integer
           {
           public:

             SampleClass(jakelib::lang::Integer* anInteger);

             jakelib::lang::String* toString();

             Iterator* iterator();

             jakelib::io::OutputStream* getOutputStream();

             JAKELIB_DECLARE_CLASS(SampleClass);
           };
       }
     }
     #endif

   Btw, `JAKELIB_DECLARE_CLASS' is a macro that declares a property and
a method used for run time type identification purposes.

   Now you should update the `Makefile.am' file that is located in the
same subdirectory: Add the name of your new file to the list of header
files (`pkginclude_HEADERS').

4.4.2 Create the source file
----------------------------

Create a new `.jlc' source file in the according package subdirectory
in `src/': The given file `src/template.jlc' can serve as a template.

   After that update the `Makefile.am' file that is located in the same
subdirectory: Add the name of your new file to the `EXTRA_DIST' list
and add the name of the according `.cpp' file to
`libjake2_<PACKAGENAME>_a_SOURCES'.

4.4.3 Documenting classes
-------------------------

4.4.4 Write a test program
--------------------------

5 Strings
*********

In Jakelib2 all strings should be represented by instances of
`jakelib::lang::String' rather than by standard `char*' arrays.

   An instance of `jakelib::lang::String' holds an immutable unicode
character sequence. Every character is represented by one 16-bit wide
`jchar' value. Thus, only the first 65535 unicode characters are
actually supported. Perhaps Jakelib will learn how to handle 32-bit wide
characters in the future. But it appears that you normally don't need
any of these strange characters.

5.1 Character Encoding
======================

Whenever strings are created from C-style `char*' arrays, read from
streams or written to streams, character encoding is necessary to
convert between the internal unicode representation and any other
character encoding.

   `jakelib::io::InputStreamReader' and
`jakelib::io::OutputStreamWriter' do these conversions for IO streams.

   The following character encodings are supported by now:

       ISO8859-1    (latin-1)
       ISO8859-2    (latin-2)
       ISO8859-3    (latin-3)
       ISO8859-4    (latin-4)
       ISO8859-5    (Cyrillic)
       ISO8859-6    (Arabic)
       ISO8859-7    (Greek)
       ISO8859-8    (Hebrew)
       ISO8859-9    (latin-5)
       ISO8859-10   (latin-6)
       ISO8859-11   (Thai)
       ISO8859-13   (latin-7)
       ISO8859-14   (latin-8)
       ISO8859-15   (latin-9)
       UTF-8        (Unicode)
       ASCII        (7-bit ASCII)
       CP1252       (Windows)
       CP437        (Windows, US)
       CP850        (Windows, latin1)

   The actual work of encoding is done by two groups of classes:
`jakelib::text::enc::ByteToChar<enc>' convert byte sequences to unicode
characters (input) and `jakelib::text::enc::CharToByte<enc>' convert
unicode characters to bytes (output).

5.2 Jakelib Preprocessor
========================

Jakelib2 has its own C++ preprocessor (`jlpp'). jlpp helps the
programmer as it allows writing more Java-like code. For now this means
that string handling is very much simplified.

   jlpp creates `cpp' files from `jlc' files. So, if you look at
Jakelib's sources, don't look at the `cpp' files. Instead look at the
`jlc' files wherever exsisting.

   Without the preprocessor one would have to write something like this:

       System::out->println(String("Just a lousy test: ").plus((jlong) 12345));

   In Java the same line of code would look like this:

       System.out.println("Just a lousy test: " + 12345);

   The disadvantage of the upper C++ version without jlpp is not just
that it looks quite ugly: For every invocation of this `println' method,
a new instance of the (constant) string `"Just a lousy test: "' is
created. This would not only cost memory but also some time because some
kind of character encoding needs to be done when creating strings from
C-style character arrays.

   To avoid this, jlpp replaces string literals by constant static
instances of `jakelib::lang::String'. This way every constant string
will be created only once. jlpp also offers the new `..' operator which
is a substitution for Java's string concatenation operator `+'. Example:

       System::out->println(`"Just a lousy test: "` .. (jlong) 12345);

   By default jlpp replaces only string literals that are enclosed in
back ticks ``' _and_ double quotes `"'. This is to stay downwards
compatible. Otherwise it would not be possible to call other library
functions that take `char*' as arguments.

   In source files that do not contain any function calls to non-jakelib
functions taking `char*' as arguments, the `javasyntax' pragma can be
used:

       #pragma javasyntax
       System::out->println("Just a lousy test: " .. (jlong) 12345);

   From the line of code downwards where the `javasyntax' pragma is
given, jlpp will replace string literals that are enclosed in back ticks
or double quotes. The `cppsyntax' pragma returns to the default mode.

       #pragma javasyntax
       System::out->println("Just a lousy test: " .. (jlong) 12345);
       #pragma cppsyntax
       printf("Returning to normal c++ syntax");

   For every string literal jlpp encounters, a static `jchar' array
called `chars_jakelib2_str_'n is inserted at the beginning of the `cpp'
file. This array contains the unicode characters of the string. The
string object itself will be created on-demand when it is actually used
for the first time. The string objects are stored in an array called
`jakelib2_strings[]'.

   Note: In multi-threaded applications it is not guaranteed that every
string object will be created only once. That is, the on-demand creation
of these strings is not synchronized!

6 Multi Threading
*****************

6.1 Synchronization
===================

In Java any object derived from `Object' can be used as a monitor.

   In Jakelib only classes implementing the
`jakelib::lang::Synchronizeable' interface can be used as a monitor.
This is simply to save system resources.

   By now only Java's `synchronized' keyword is implemented, `wait()'
and `notufy()' are yet to be implemented.

       class Sync : public Object, public Synchronizeable
       {
         public:
          Sync() {};

          void Sync::foo()
          {
            ...
            {
              JAKELIB_SYNCHRONIZED(this)

              // We are inside the synchronized block :-)
            }

            // End of synchronized block.
            ...
          }
       };

   Internally the `JAKELIB_SYNCHRONIZED' macro instantiates a `Sentry'
object on the stack. A `Sentry' locks a mutex in its constructor and
unlocks it in its destructor which is called when the `Sentry' object
runs out of scope.

7 License
*********

GNU Lesser General Public License Version 2.1, February 1999
Jakelib2 is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1, or any later version.

   This software is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
License along with this package; see the file `COPYING'.  If not, write
to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.

Copyright (C) 2000 - 2003 Florian Wolff <florian@jakelib.org>
Verbatim copying and distribution of this entire document is permitted
in any medium, provided this notice is preserved.