How is Java going to help in software distribution? How is it going to relieve the IS manager from the burden of shared drives and fixed media?
Software distribution, especially in the corporate environment, is an issue that has vexed IS managers since the advent of the PC. IS managers worry constantly about working in multiple operating system environments, detecting and eradicating viruses, and distributing fixes and updates. The Java language solves two of these problems โ operating system independence and virus control. However, this still leaves the problem of distribution.
When IS managers need to distribute software, they want it to be easy, convenient, and not affect the productivity of their users. In addition, it should be easy to distribute both new versions of software and software updates.
Currently, there are a number of distribution techniques. Two common techniques include fixed-media (CD-ROM, diskette, tape) and shared-access distribution. Everyone knows how fixed-media distribution works. Shared-access distribution means files and applications are stored in a location that gives access to a group of users. Both of these methods have inherent problems.
In the case of fixed media, either the media has to be handed to each user, or IS personnel have to go to each machine and install the software. Not only is this time-consuming and disruptive to the users and IS people, but very often the location of the distribution media itself is not known. Furthermore, the medium itself can be costly.
Software installed on network drives or file servers still has all the problems that normal software has. Updates and fixes usually mean a complete reinstallation of the software to the network drive. Very often each user then has to reinstall pieces of this โsharedโ software to his or her local machine.
However, there is hope in sight. With the advent of Java, many of the problems so far encountered by the battered IS manager may be on the way out. As mentioned before, Java solves the multi-platform and virus problems. But, how can it help with distribution? How can it relieve the IS manager from the burden of shared drives and fixed media?
Java has solved the fragile superclass problem. Therefore, the actual placement of functions in memory is not done until the Java application is loaded by the Java interpreter. This is a great boon for software distribution. A single object, containing a bug fix, can be distributed alone with no repercussions. Software does not have to be recompiled whenever function entry points change. When it comes to updates and fixes, only the pieces changed need to be distributed.
Following is the outline of two different software-distribution systems. Each of these systems has advantages and disadvantages. The first of these systems is a distribution system based on the use of Web servers (http daemons). The second is based on writing a proprietary distribution server. The purpose of the servers is to allow distribution of Java applications to users in a fast and convenient method that solves the problems in current distribution systems.
HTTP server example
The http distribution server is based on exclusive use of an http daemon. This server relies heavily on configuration files to control distribution. Most of the intelligence for this system resides in the client code.
Configuration files must be created that contain all of the information relevant to the distributed applications. From now on, all of the code, files, and pieces that must be distributed to a client machine will be referred to as an application bundle.
Now, each file in a bundle must contain certain base information for the distribution class to work with. For this example, the following information will be contained in the configuration file for each piece in the bundle.
File name โ Name of the file
- Revision level โ Revision level of the file
A file with the name of the bundle will be created that contains a listing of files and revisions. This file will reside on the http server.
A class must be created that handles pulling the configuration information from the http server, compares it to the local configuration, and pulls down any new files. This class will need to know the name of the bundle that it is going to check, and the address of the http server where the bundle resides. Following are the public members of this class.
Class : AutoDistribute
Public Members : Constructor (String http_server_address)
boolean getClasses(String bundlename)
Every new application written now includes the AutoDistribute class as the first class in the Main. They instantiate the class and give it the address of the http server that contains the configuration information. Next, they call getClasses() and pass it the name of the bundle. If any classes are returned, then the member returns true.
The constructor goes to the http server and pulls the configuration file for the bundle. When getClasses() is called, it checks the local disk for the bundles configuration file. It compares the revisions of each file in the bundle, and pulls down any file that has a newer revision. It would be nice here to use an overloaded class loader. However, there seems to be a problem in the code. The objects pulled in via the class loader are not used by the program; only the versions of the classes on the disk at the time of application instantiation are used. This means that if the program has new classes, it must be restarted before the changes will take affect.
The class classLoader was not meant to replace any already-loaded classes. The interpreter first tries to load a class from the classpath and local directory. Then any new classLoaders are called. It would be nice if we could drop any loaded classes from the Hashtable, and reload with the new class from the server. Then a program would not have to be restarted after new classes are distributed to it.
The code used to pull files from the http server and store to disk is:
URL swopURL = new URL(urladdress+filename);
// Open the connection to the object
URLConnection swopURLConn = swopURL.openConnection();
// Check to see if this is a text/plain type of file
if(swopURLConn.getContentType().equals("text/plain"))
{
String newclass = (String)swopURL.getContent();
int datalen = swopURLConn.getContentLength();
byte data[] = new byte[datalen];
newclass.getBytes(0,datalen,data,0);
FileOutputStream fos = new
FileOutputStream(newelem.classname+".class");
fos.write(data);
fos.close();
return true;
}
The advantage of this system is its ability to use current http servers in its implementation, and it only requires the development of a single class on the client side. In addition, to release a piece of software for the first time, only the main class and the distribution class need to be on the client machine. However, the disadvantage is trying to keep a configuration file in sync with all of the files in a bundle. This could become an onerous task, and if things get mixed up, it could create a lot of havoc. In addition, if any class files are downloaded, the program needs to be restarted to take advantage of them. Because of the loadClass problem, classLoader does not solve this problem and allow us to dynamically load classes that have already been loaded into memory.
Proprietary server example
The proprietary server has more functionality than the http method and does not require the existence of a costly Web server. The purpose of this server is to feed files to client modules across the Internet, for the use of distribution and updates. The server can process various commands from client objects. The following commands are the minimum needed.
- GetBundleList(String bundlename);
- GetFile(String fileName);
When the server receives the GetBundleList command, it reads in the versions of each file associated with the bundle. This can be done in various ways. Easiest is the creation of a configuration file, similar to the configuration file used in the http server. To create a more dynamic system that does not require updating a configuration file each time a file has changed, the following method could be used.
A base class called DistributeClass is created. This class looks like
public class DistributeClass
{
public float revision = 0.0;
} // end class DistributeClass
Each distributed class inherits this class and sets the revision to the current revision of the file. In addition, all files for a bundle are placed into a directory with the bundleโs name. When the server gets a request for a bundle, it goes to the directory and creates the bundle list array by loading in each class in the directory using classLoader. At this time it overloads the returned object to a DistributeClass type, and gets the revision of the object. This is placed in the bundle list array. The entire array is then passed back to the client program.
The client program compares the bundle list array to one created for its own bundle. This is done in the same way as the server, searching a given directory for all of its class files, loading them with classLoader, and getting the revision.
One problem with this method is that it only works with Java classes. GIFs, bitmaps, and other files cannot be distributed automatically this way. However, it makes distribution of new files a breeze. The developer creates a new revision of a class, tests it, debugs it, gets it approved, and then the class is placed into the bundle directory. It will then automatically propagate out to all clients.
Since there is only single inheritance in Java, this could pose a problem if all your classes now need to inherit this base class. However, there does not seem to be a way around this in the current release of Java. If Java had a dynamic โnew (class)โ, where a class could be created on the fly and methods called, then the inheritance would not be needed.
For example:
String classname = recvName();
Object o = new (classname);
float revision = o.revision;<
This code will not work in current Java implementation. The documentation for JDK 1.0 says the following will snippet should work.
b=new("Class"+"A")
This code actually flags an unsupported feature error in the compiler.
What should work is overloading the class loader to read in from a local file. For an example of this, see https://www.digitalfocus.com/digitalfocus/faq/VM.html#VM_2. The class is loaded using the class loader, the object cast to the base class, and the revision checked.
SampClassLoader loader = new SampClassLoader();
Class testclass = loader.loadClass("DistTest",true);
Object test = testclass.newInstance();
DistributeClass distclass = (DistributeClass)test;
revision = distclass.revision;
Another problem with the current methods is the need to restart the application once new files have been downloaded. This is caused by the Java security classes. When the Java interpreter looks for a class reference, it goes to its classLoader first, which looks at the files on disk. Then it goes to any user-created classLoaders. Because of this, classes referenced within the application that donโt explicitly call the classLoader and newInstance, use the old versions. This enables a fair amount of security; however, it also forces us to restart newly distributed applications.
This method is more complicated than the http server method. However, it saves the cost of an http server, and is much more extensible. Commands can be easily added to the server, and the functionality increased. In addition, with emerging standards for Java and fixes for some of the current problems, this process might become much easier to implement. If Sun placed a revision variable directly into the Object base class, this system would be a breeze to create.
Conclusion
Clean, convenient, and simple software distribution is not only a goal, but a necessity. With software systems gaining complexity, better distribution methods are needed. Automatic software distribution should help with many of the problems associated with these complex software systems. A simple bug fix will no longer mean reinstalling an entire software package. Distributing this fix will not be a lengthy process that disrupts the normal work flow. Put your fix on a server, and let it go. With the advent of Java, this goal can finally be realized.


