(pronounced Jay-Res)
A Java Resource file compiler

by Richard Redpath, Gennaro (Jerry) Cuomo -IBM Software Solutions Division

Date: 8/2/96, Version: Draft 1.0

Background

At their simplest anatomical view, computer programs include logic and data portions. One type of data is known as resources. Resources include icons, cursors, text, menus, dialog boxes, audio clips, animation clips, etc. Resource are also commonly used to segment national language data apart from other data portions of a program. One can imagine that in today's graphical and multimedia intensive programs, resources are vital portions of these visual applications.

Resources and resource files, in which resources are typically contained, are treated separately and differently from other types of data. For example, when the Windows(tm) operating systems loads programs into memory for execution, such as those written in the C or C++ programming languages, it usually leaves the resources on disk. Typically, only when the Windows operating system needs a particular resource does it load the resource into memory.

Some object oriented languages treat resources files somewhat differently. For example, Smalltalk and ScriptX turn resources into data objects. These data objects are then placed into a resource pool for use by the application as necessary. Thus, resource data objects have still not obtained the status of a "class", and must be treated differently than regular object oriented classes in both Smalltalk and ScriptX.

This presents particular problems for applications used in conjunction with the Internet. Consider the Java programming language as an example. Java classes may be easily used over the Internet, with security being provided relative to the classes as they are loaded via the Internet. Additionally, Java classes are packaged such that they may be compressed for sending over the Internet. This speeds up the transfer of data and enhances performance. However, resource data utilized by Java programs are not maintained in a way that would take advantage of the network "savvy-ness" of a Java class. For example, Java applets typically access resources, like images and sound clips, as separately loaded files. This is highly inefficient.

Thus, there clearly is a need for a network-efficient and structured means of dealing with resources in Java. The following package introduces a technolgy called JRes (pronounced Jay-Res). JRes provides a solution to the problem of handling resources in a network "savvy" manner. Also see jresVisual, which is a tool for building JRes resource files, visually.

Introducing JRes

The JRes technology introduces the concept of a Java resource class. A Java resource class is an ordinary Java class containing encapsulated resources like strings, images, sounds, menus, etc. Java resource classes have several valuable attributes to a Java programmer. In particular, a Java resource class can be used for internationalizing Java based programs, allowing application independent interchange of strings, sounds and images. Java resource classes can also dramatically improve the performance of loading static resources.

The jres class

The ibm.jres class implements the Java resource file compiler. It takes a resource file name as a parameter and creates a Java class of the same name from the data contained in the resource file. The extension for jres resource files are assumed to be ".jrc". The following is a sample invocation of jres and compiles the Java resource files "myresource.jrc".




   java ibm.jres.jres myresource.jrc

Jres belongs to the package ibm.jres and is a standalone Java application. This is why we specify "ibm.jres.jres" as the class name to execute in the above example.

The Java Resource file- an example

Java resource file is designed to enable national language support by encapsulating the language dependent data in a Java class. Supported data types include; text strings, images, sounds, and menus. The best way to understand a Java resource file is to examine one. A sample resource file called animatedata.jrc is shown below. This file simply contains a set of numbered images. This resource file is used by animate.java to show an animation. The source for this example is in ibm.jres.demo.animate directory.


;-----------------------------------

; This is a comment

; animatedata.jrc

;-----------------------------------



PACKAGENAME sample



IMAGE   0   T1.GIF

IMAGE   1   T2.GIF

IMAGE   2   T3.GIF

IMAGE   3   T4.GIF

IMAGE   4   T5.GIF

IMAGE   5   T6.GIF

IMAGE   6   T7.GIF

IMAGE   7   T8.GIF

IMAGE   8   T9.GIF

IMAGE   9   T10.GIF

;---  blah, blah blah ...

IMAGE   28  T29.GIF

To compile this resource file into a Java class the jres compiler is used:




   java ibm.jres.jres animatedata.jrc



   
The result is a Java class called animatedata.class containing encapsulated images. animate.java is a sample Java applet which illustrates how to access the encapsulated images contained in animatedata.class. (The full source to animate.java can be found in Appendix A.) There are two key steps to accessing these resources. The first is to import the package containing the animagedata class. This is done at the top of animate.java via the Java import keyword.

import sample.animatedata;

Next, we access the image data. The animatedata.class is created to contain both encapsulated resource data and methods to retrieve the data. Hence, the animatedata class contains a method, LoadImage(), used to retreive image data. An example of how the animate sample accesses the image resources from animatedata follows:


   for (int i=0; i<29; i++) {

    image[i]= animatedata.LoadImage(i);

    mt.addImage(image[i],0);

   }

 
The resulting application is clean an compact. Only two class files are needed to reliably and efficiently run the Java animate application. All the images have been encapsulated into a Java Class. No specific URL paths are necessary to load images nor are the images available as separate files.

The Java Resource File- the Syntax

The resource file syntax is very simple and is directed by capitalized keywords. The currently supported keywords are: (The jresVisual builder will generate resource files that follow the following syntax.)

PACKAGENAME
INCLUDE
DEFINE
IMAGE
STRINGTABLE, ENDSTRINGTABLE
MENU, ENDMENU
MENUITEM, SEPARATOR
SUBMENU, ENDSUBMENU


PACKAGENAME

Syntax:

PACKAGENAME {java package name}

Description:

The PACKAGENAME keyword is not required but if it is used it must be the first non-comment keyword. This keyword enables the programmer to name the package of the

resultant Java class created from the resource file.

Example:




	; ----- MyRes.jrc

	; ----- A sample resource files

	;



	PACKAGENAME mypackage




INCLUDE

Syntax:

INCLUDE {java resource file}

Description:

The INCLUDE keyword enables the programmer to include another resource file. Usually this resource file is simply a translation file which defines macros for text string translations. See the DEFINE keyword.

Example:


	; ----- MyRes.jrc

	; ----- A sample resource

	;

	PACKAGENAME mypackage



	INCLUDE myapp.pii




DEFINE

Syntax:

DEFINE {alphanumeric ID} {text data }

Description:

The DEFINE keyword provides an id to point to text that will be used by resource file objects that require text.

The translation file extensions are typically ".pii". Translation files or PII files and resource files (.jrc) can be viewed/edited by the IBM Visual Resource File Builder java application ibm.jres.jresVisual. Please see documentation for jresVisual for creating resource files and translation files. It is not necessary to know the syntax of the jres compiler resource file if you have the visual builder.

Example:




	DEFINE	STR_INFO	"IBM JRes package"

	DEFINE	STR_BOZO 	"a clown"

	DEFINE 	STR_FILE	"file"




IMAGE

Syntax:

IMAGE {alphanumeric/numeric ID} {image filename}

Description:

The images that are supported are JPEG and GIF. The ID can be alphanumeric or numeric for convenience. Numeric IDs are useful for loops. To access an image the programmer uses the static Image LoadImage(..) method which is available from the created java class from the resource file.

Example:


	; ---- Sample.jrc

	IMAGE 	  100       rocket.gif

	IMAGE 	  rocket   rocket.gif



	// example of accessing images defined in above resource file

	// from java

	LoadImage(100);

	LoadString(rocket);



	// prototype of image access methods

	public static Image LoadImage(int id)

	public static Image LoadImage(String imagedata[])




STRINGTABLE, ENDSTRINGTABLE

Syntax:

STRINGTABLE




	     {alphanumeric/numeric ID}  {text data}/ID



                 :

                 :

                 :



	     {alphanumeric/numeric ID}  {text data}/ID



	ENDSTRINGTABLE

Description:

The keyword STRINGTABLE is a begin block for defining strings and is followed by ENDSTRINGTABLE to end a block. The programmer of the resource file can have more than one STRINGTABLE to organize common string areas if desired.

The text data can be an ID which was defined by a DEFINE keyword. This allows for indirection to a translation file which prevents the translation center in having any knowledge of resource file syntax.

Example:




	; Sample.jrc

	; a sample resource file containing a string table



	DEFINE STR_FILE  File

	DEFINE STR_SAVE  Save

	DEFINE STR_HELP  Help



	STRINGTABLE

	   100     IBM Copyright (c) 1996

	   HELP    Help is not available

	   200     STR_FILE

	   210     STR_SAVE

	   220     STR_HELP

	ENDSTRINGTABLE



	// sample java code to access the string table defined above

	LoadString(100)   // loads "IBM Copyright (c) 1996"

	LoadString(HELP); // loads "Help is not available"



	// prototypes of JRes methods used to access strings

	public static String LoadString(int id)

	public static String LoadString(String id);




MENU, ENDMENU

Syntax:


	MENU {alphanumeric/numeric ID}



	   :



	ENDMENU



The MENU keyword is a begin block for defining a menu. It is terminated by an ENDMENU. The resource file object menu can be loaded as a Menu or MenuBar. The method LoadMenu() and LoadMenuBar() are provided with the generated class file from the resource file. To define menu panes the MENUITEM keyword is used.

Example:




	; Resource file...

	MENU 10

	  MENUITEM 200 red

	  MENUITEM 300 blue

	ENDMENU



	// Java code

	LoadMenu(10)

	LoadMenuBar(10);



	// prototypes of menu methods

	public static Menu LoadMenu(int id)

	public static MenuBar LoadMenuBar(int id)

	public static Menu LoadMenu(String id)

	public static MenuBar LoadMenuBar(String id)




MENUITEM, SEPARATOR

Syntax:

MENUITEM {numeric ID} {text data}

Description:

The MENUITEM keyword provides a field for an ID to be defined. When a selection is encountered for the menu the ID can be obtained from the ACTION_EVENT which is numeric and independent of language.

A sample menu is shown below with a separator before the menu pane which has the word delete on it.

Example:




MENU main

  MENUITEM  1  red socks

  MENUITEM  2  blue socks

  MENUITEM  3  green socks

  SEPARATOR

  MENUITEM  4  Delete

ENDMENU


SUBMENU, ENDSUBMENU


SUBMENU  {numeric ID}  {text data}

   :

ENDMENU

To define submenus, the SUBMENU keyword is used.


MENU main

  SUBMENU  100  File

    MENUITEM  1  Open

    MENUITEM  2  Save

    MENUITEM  3  Save as

  ENDSUBMENU

  MENUITEM 200  Help

END

Summary

JRes produced resource file classes encapsulate data and provide a natural vehicle for national language support in Java.

The jres compiler is about 14K in size and also provides as the super class of the resource file class generated. The jres.class should be shipped with the resource file. There is unlimited license to use the jres compiler as a runtime library.

Appendix A




Animate.java



-------------animate.java------------------------------------



import java.awt.*;

import java.applet.Applet;

import sample.animatedata;





public class animate extends Applet implements Runnable {

   private Image image[]=new Image[30];

   private Thread animation=null;

   private int index=0;

   public animate() {



     MediaTracker mt=new MediaTracker(this);



     for (int i=0; i<29; i++) {

       image[i]= animatedata.LoadImage(i);

       mt.addImage(image[i],0);

     }



     try {

        mt.waitForAll();	

     } catch (Exception e) {

        System.out.println("media tracker exception ");

     }



     start();



   }



   public void run() {



     while (true) {

        try {

          Thread.sleep(200);              //about human speed

          repaint();

        } catch (InterruptedException e) {

            break;

        }

     }

   }



   public synchronized void paint(Graphics g) {



     g.drawImage(image[index++],0,0,this);

     if (index==29)

       index=1;

   }





   public void start() {



       animation = new Thread(this);

       animation.start();

   }



   public static void main(String args[]){



      Frame f = new Frame("animatedata");

      animate t = new animate();

      f.add("Center",t);

      f.resize(225,200);

      f.show();

   }



}