Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Dejavu, the port of the java runtime packages

Dejavu is a replacement for the JRE packages. This is a reimplementation of this basic functionality in D using tango. Many of the classes have an equivalent in the tango library and the implementation is only a simple delegation. The skeletons of dejavu are generated with the TioPort and the methods have and

assert( false, "implementation is missing" );

in the body. This allows that everything can compile, but if a not implemented method is called, an assertion exception is thrown.

All implementations need to be done manually.

Why not using a port of the java original including the implementations?

Copyright

Why not using the GNU classpath?

The GNU Classpath has GPL + the "extension", in my understanding this is like the LGPL. Probably the licence is OK. Perhaps, i will switch Dejavu to a port of the GNU classpath or the upcoming free SUN jre - OpenJDK. In the start of the TioPort project it seemed to be more practical to do a manual implementation of the few classes SWT requires.

Objects and Interfaces

In Java and D, there is an root class. Every class derives directly or indirectly from "Object". In Java every interface is compatible to "Object" also. In D this is not true. To solve this, dejavu uses JObject as a root interface, and JObjectImpl as a root class.

If you want to implement such an interface, take care to also derive from JObjectImpl, or implement all missing function from JObject. Implementing those functions makes only sense if you need a certain base class. An example is the Throwable class. The ported version shall be derived from the D Exception class. Because of that the ported version derives from Exception and implements JObject.

Strings

TioPort and Dejavu use a String class in dejavu.lang.String to implement the String :) In D a string is one of char[],wchar[] or dchar[]. In D a character array is a string. In Java it isn't, there exist the char[] and the String class.

To Work with ported code, one needs to convert each d string to the String class. Because of ambiguity, the String class cannot have ctors for char[] and wchar[], because of that there are static creator methods:

   String j_str = String.fromUtf8( "hello" );
   char[] d_str = j_str.toUtf8();

Arrays

In D it is not possible to distinguish between an dynamic array with length zero and a null reference. In Java an array is an object. In can be null, or if not null, it can have length zero. So the ported code, need to make use of array objects.

Array of objects, and arrays of arrays are build with

  • JArrayJObject

Arrays of primitive types are build with one of

  • JArrayBoolean
  • JArrayChar
  • JArrayByte
  • JArrayShort
  • JArrayInt
  • JArrayLong
  • JArrayFloat
  • JArrayDouble

In the following we assume we have this alias, to avoid confusion with array declarations:

   alias char[] dstring;

To allocate a 1 dimensional array, on uses the appropriate array class and the createSimple method

   /// Create equivalent to new int[3];
   JArrayInt a1 = JArrayInt.createSimple( 3 );

   /// Create equivalent to new dstring[3];
   JArrayJObject a1 = JArrayJObject.createSimple( String.classinfo, 1, 3 );

For the string array, the classinfo of the member element and the depth of dimensions must be supplied. This information is needed for instanceof tests.

Allocation of multidimensional arrays:

   /// Create equivalent to new int[3][4];
   JArrayJObject a3 = JArrayInt.createRectangular( /*dims*/ 2, /*1. dim*/ 3, /*2. dim*/4 );

   /// Create equivalent to new dstring[3][4];
   JArrayJObject a4 = JArrayJObject.createRectangular( String.classinfo, /*dims*/ 2, /*1. dim*/ 3, /*2. dim*/4 );

The first parameter gives the overall dimension count. This is needed if some dimensions not be allocated. For non primitive membertype, again the classinfo is needed.

Create arrays from given members

   /// Create equivalent to [ 1, 2, 3 ]
   JArrayInt a1 = JArrayInt.createSimpleFromLiteral( 1, 2, 3 );

   /// Create equivalent to dstring[] = [ "foo", "bar" ]
   JArrayJObject a1 = JArrayJObject.createSimpleFromLiteral( String.classinfo, 1,
      String.fromUtf8( "foo" ),
      String.fromUtf8( "bar" ));

Create multidimensional arrays from given members:

   /// Create equivalent to int[][] = [ [ 1, 2 ], [3] ]
   JArrayJObject a1 = JArrayJObject.createSimpleFromLiteral(
      JArrayInt.createSimpleFromLiteral( 1, 2 ),
      JArrayInt.createSimpleFromLiteral( 3 )
      );
   /// Create equivalent to dstring[][] = [ [ "foo", "bar" ], [ "hello" ] ]
   JArrayJObject a1 = JArrayJObject.createSimpleFromLiteral( String.classinfo, 2,
      JArrayJObject.createSimpleFromLiteral(  String.classinfo, 1,
         String.fromUtf8( "foo" ),
         String.fromUtf8( "bar" )
      ),
      JArrayJObject.createSimpleFromLiteral(  String.classinfo, 1,
         String.fromUtf8( "hello" )
      )
   );

Hopefully someone can come up with a template magic to make this more compact

To access the members, the arrays have opIndex and opIndexAssign overloaded. The arrayclasses do only support on access level.

The JArrayJObject cannot return the member in the correct type, because it is always the same array class. This is the reason why the user needs to case the member to the right type manually.