Login| Sign Up| Help| Contact|

Patent Searching and Data


Title:
ITINERARY BASED AGENT MOBILITY INCLUDING MOBILITY OF EXECUTABLE CODE
Document Type and Number:
WIPO Patent Application WO/1998/021662
Kind Code:
A1
Abstract:
In accordance with the present invention, a mobile agent object (10) executes a first method (18) on a first computer (12), migrates from the first computer (12) to a second computer (14), and executes a second method (20) on the second computer (14). The first and second methods and first and second computers are designated in an itinerary (28). The agent includes both data (22) and executable code (24, 26) which are serialized for transmission from the first computer to the second computer as data. The data containing the agent is then deserialized in the second computer to regenerate the agent in the form of an object. The executable code portion of the agent can be supplemented with code from a home codebase located on another computer.

Inventors:
WALSH THOMAS C
Application Number:
PCT/US1997/020232
Publication Date:
May 22, 1998
Filing Date:
November 12, 1997
Export Citation:
Click for automatic bibliography generation   Help
Assignee:
MITSUBISHI ELECTRIC INF TECH (US)
International Classes:
G06F15/16; G06F9/44; G06F9/46; G06F9/50; G06F13/00; G06N5/04; H04L29/08; (IPC1-7): G06F13/00
Foreign References:
US5499364A1996-03-12
Other References:
IEEE, August 1996, BERGHOFF et al., "Agent-Based Configuration Management of Distributed Applications", pages 52-59.
See also references of EP 1021766A4
Attorney, Agent or Firm:
Tendler, Robert K. (Boston, MA, US)
Download PDF:
Claims:
CLAIMS What is claimed is:
1. In a computer network including at least a first computer and a second computer, an apparatus for performing a task in a second computer, comprising: a routine that generates a mobile agent object in the first computer, the mobile agent including both data and executable code; a protocol for transmission of the mobile agent from the first computer to the second computer, wherein execution of the mobile agent in the second computer following such transmission prompts the task to be performed in the second computer; and an itinerary containing a reference to each destination computer to which the mobile agent is designated to migrate and a reference to a method associated with each respective destination computer reference, the respective method being invoked when the mobile agent is present on the respective destination computer.
2. The apparatus of claim 1 wherein the transmission protocol includes a routine in the first computer for serializing the mobile agent to generate a stream of data therefrom.
3. The apparatus of claim 2 wherein the transmission protocol includes a routine in the second computer for deserializing the stream of bytes to regenerate the mobile agent therefrom.
4. The apparatus of claim 1 wherein the task is data gathering, and wherein the mobile agent is transmitted back to the first computer from the second computer following completion of such data gathering.
5. The apparatus of claim 1 wherein the mobile agent migrates to a plurality of destination computers within the computer network.
6. The apparatus of claim 1 wherein at least one destination computer reference is a Uniform Resource Locator.
7. The apparatus of claim 1 wherein at least a portion of the executable code required for invoking the method is retrieved from a mobile codebase portion of the executable code included in the mobile agent.
8. The apparatus of claim 7 wherein the mobile agent includes a reference to a home codebase located on the first computer, the reference being employed to retrieve required executable code which is not present in the mobile codebase.
9. The apparatus of claim 8 wherein required executable code is sought first in the computer on which the mobile agent is executing, then in the mobile codebase, and finally on the home codebase.
10. The apparatus of claim 8 wherein a new thread is formed for execution of the mobile agent in the destination computer following receipt of the mobile agent, and wherein a security feature prevents the mobile agent from operating outside a scope assigned to such thread.
11. The apparatus of claim 8 wherein the mobile agent further includes subobjects.
12. The apparatus of claim 1 wherein a persistent local copy of the mobile agent is stored following receipt of the mobile agent, and wherein such copy is overwritten with an updated persistent copy following agent execution.
13. In a computer network including at least a first computer and a second computer, a method for performing a task in a second computer, comprising the steps of: generating a mobile agent object in the first computer, the mobile agent including both data and executable code; transmitting the mobile agent from the first computer to the second computer; receiving the mobile agent in the second computer; and executing the mobile agent in the second computer in accordance with an itinerary which contains a reference to each destination computer to which the mobile agent is designated to migrate and a reference to a method associated with each respective destination computer reference, the method associated with the second computer being invoked when the mobile agent is present on the second computer.
14. The method of claim 13 including the further step of serializing the mobile agent to generate a stream of data therefrom in the first computer.
15. The method of claim 14 including the further step of deserializing the stream of bytes to regenerate the mobile agent therefrom in the second computer.
16. The method of claim 13 wherein the task is data gathering, and including the further step of transmitting the mobile agent back to the first computer from the second computer following completion of such data gathering.
17. The method of claim 13 including the further step of causing the mobile agent to sequentially migrate to a plurality of destination computers within the computer network.
18. The method of claim 13 including the further step of employing a Uniform Resource Locator as one of the at least one destination computer reference.
19. The method of claim 13 including the further step of retrieving at least a portion of the executable code required for invoking the method from a mobile codebase portion of the executable code included in the mobile agent.
20. The method of claim 19 wherein the mobile agent includes a reference to a home codebase located on the first computer, and including the further step of employing the reference to retrieve required executable code which is not present in the mobile codebase.
21. The method of claim 20 including the further step of searching for required executable code first in the computer on which the mobile agent is executing, then in the mobile codebase, and finally on the home codebase.
22. The method of claim 21 including the further step of forming a new thread in the destination computer for execution of the mobile agent following receipt thereof, and wherein a security feature prevents the mobile agent from operating outside a scope assigned to such thread.
23. The method of claim 21 including the further step of inserting subobjects into the mobile agent.
24. The method of claim 13 including the further step of storing a persistent local copy of the mobile agent following receipt thereof, and overwriting such copy with an updated persistent copy following agent execution.
25. In a computer network including at least a first computer and a second computer, an apparatus for performing a task in a second computer, comprising: a routine that generates a mobile agent object in the first computer, the mobile agent including both data and executable code; a protocol for transmission of the mobile agent from the first computer to the second computer, wherein execution of the mobile agent in the second computer following such transmission prompts the task to be performed in the second computer, at least a portion of the executable code required for execution being retrieved from a mobile codebase portion of the executable code included in the mobile agent; and a reference to a home codebase located on the first computer, the reference being employed to retrieve required executable code which is not present in the mobile codebase.
26. The apparatus of claim 25 wherein the transmission protocol includes a routine in the first computer for serializing the mobile agent to generate a stream of data therefrom.
27. The apparatus of claim 26 wherein the transmission protocol includes a routine in the second computer for deserializing the stream of bytes to regenerate the mobile agent therefrom.
28. The apparatus of claim 25 wherein the task is data gathering, and wherein the mobile agent is transmitted back to the first computer from the second computer following completion of such data gathering.
29. The apparatus of claim 25 wherein the mobile agent migrates to a plurality of destination computers within the computer network.
30. The apparatus of claim 29 wherein the mobile agent further includes an itinerary containing a reference to each destination computer to which the agent is designated to migrate and a reference to a method associated with each respective destination computer reference, the respective method being invoked when the mobile agent is present on the respective destination computer.
31. The apparatus of claim 30 wherein at least one destination computer reference is a Uniform Resource Locator.
32. The apparatus of claim 25 wherein required executable code is sought first in the computer on which the mobile agent is executing, then in the mobile codebase, and finally on the home codebase.
33. The apparatus of claim 25 wherein a new thread is formed for execution of the mobile agent in the destination computer following receipt of the mobile agent, and wherein a security feature prevents the mobile agent from operating outside a scope assigned to such thread.
34. The apparatus of claim 25 wherein the mobile agent further includes subobjects.
35. The apparatus of claim 30 wherein a persistent local copy of the mobile agent is stored following receipt of the mobile agent, and wherein such copy is overwritten with an updated persistent copy following agent execution.
36. In a computer network including at least a first computer and a second computer, a method for performing a task in a second computer, comprising the steps of: generating a mobile agent object in the first computer, the mobile agent including both data and executable code; transmitting the mobile agent from the first computer to the second computer; receiving the mobile agent in the second computer; retrieving at least a portion of the executable code required for invoking the method from a mobile codebase portion of the executable code included in the mobile agent; employing a reference to a home codebase located on the first computer to retrieve required executable code which is not present in the mobile codebase; and executing the mobile agent in the second computer such that the mobile agent prompts the task to be performed in the second computer.
37. The method of claim 36 including the further step of serializing the mobile agent to generate a stream of data therefrom in the first computer.
38. The method of claim 37 including the further step of deserializing the stream of bytes to regenerate the mobile agent therefrom in the second computer.
39. The method of claim 36 wherein the task is data gathering, and including the further step of transmitting the mobile agent back to the first computer from the second computer following completion of such data gathering.
40. The method of claim 36 including the further step of causing the mobile agent to sequentially migrate to a plurality of destination computers within the computer network.
41. The method of claim 40 wherein the mobile agent further includes an itinerary which contains a reference to each destination computer to which the agent is designated to migrate and a reference to a method associated with each respective destination computer reference, and including the further step of invoking the method associated with the respective destination computer when the mobile agent is present on the respective destination computer.
42. The method of claim 41 including the further step of employing a Uniform Resource Locator as one of the at least one destination computer reference.
43. The method of claim 36 including the further step of searching for required executable code first in the computer on which the mobile agent is executing, then in the mobile codebase, and finally on the home codebase.
44. The method of claim 36 including the further step of forming a new thread in the destination computer for execution of the mobile agent following receipt thereof, and wherein a security feature prevents the mobile agent from operating outside a scope assigned to such thread.
45. The method of claim 36 including the further step of inserting subobjects into the mobile agent.
46. The method of claim 41 including the further step of storing a persistent local copy of the mobile agent following receipt thereof, and overwriting such copy with an updated persistent copy following agent execution.
Description:
TITLE OF THE INVENTION ITINERARY BASED AGENT MOBILITY INCLUDING MOBILITY OF EXECUTABLE CODE CROSS REFERENCE TO RELATED APPLICATIONS A claim of priority is made to U.S. provisional patent application Serial Number 60/030,906, entitled USE AND COLLABORATION OF MOBILE AGENTS IN A COMPUTER NETWORK, filed November 14, 1996.

STATEMENT REGARDING FEDERALLY SPONSORED RESEARCH OR DEVELOPMENT Not applicable BACKGROUND OF THE INVENTION The present invention is generally related to network computing, and more particularly to mobile objects.

Mobile objects that are transmitted across a computer network are known. Mobile objects are comprised of code and data, both of which are transmitted across the computer network. Technologies such as client-server protocols, remote procedure call protocols, and distributed object technologies are employed to transmit mobile objects across the computer network. These technologies implement either a "push" model or a "pull" model, both of which have drawbacks.

In a "pull" model the code for an executing object is downloaded from a network source such as a web server. When a particular portion of code becomes necessary for operation, that portion of code is first sought on the local filesystem.

If the local filesystem does not include that portion of the code, a network request is sent to another computer in the network in order to prompt transmission of that portion of code to the local computer. However, as different classes of sub-objects are created, a separate network request must

be sent to retrieve code for each class. In the case of a Hyper-Text Transfer Protocol ("HTTP") request, each request must re-establish a Transmission Control Protocol/Internet Protocol ("TCP/IP") socket connection to the web server.

Thus, when downloading a large number of classes, a large number of connections must be established and a large amount of network overhead is incurred.

Another drawback associated with the pull model is that as an object travels, the code which enables the object to operate must be re-downloaded at each computer. More particularly, when the object arrives at each a destination computer, the object downloads any code which is required but not present on the local filesystem, even if that code was downloaded at the previous destination computer. Previously downloaded code is not cached. Network overhead is incurred as a consequence.

In a "push" model the code for an executing object is carried with the mobile object. Prior to launching the mobile object, all of the code that will be needed by the object is identified. The code is packaged with the agent and pushed around the network to each destination computer.

While the push model reduces network requests in comparison with the pull model, network overhead is still incurred because of the relatively large amount of code that is pushed to every destination computer. In some cases the object will push code for classes that are no longer needed. For example, an agent may create an instance of a particular class of object only in very exceptional circumstances. In such a case it is inefficient for the object to push the code for this class.

Another limitation of known mobile objects is difficulty in examining and predicting destination information. Known mobile objects initiate travel by performing a subroutine call. The method is sometimes given a name such as "go" or "moveTo," and the caller is responsible for specifying a name or Uniform Resource Locator ("URL") indicating the destination computer for the mobile object. When the travel method is called, the execution of the mobile object is

halted and the mobile object is converted into a network transmittable form. On the destination computer the mobile object is restored from the network form and restarted. This restart can either occur on the instruction directly following the call to the travel method, or at the beginning of some known method.

BRIEF SUMMARY OF THE INVENTION In order to provide efficient mobility of code for a mobile agent object ("agent"), a "mobile codebase" object is constructed. The mobile codebase travels with the agent and serves as a repository of code for classes that facilitate agent operation. When the agent is launched, the launcher specifies a list of related classes. These classes are retained in the mobile codebase. The launcher also specifies a Uniform Resource Locator ("URL") that points to a network source ("home codebase") from which code can be downloaded.

If the agent is required to instantiate an object comprising code that is not in the mobile codebase, a network request is sent to the home codebase to retrieve that code. Code that is downloaded in this manner is retained in the mobile codebase.

The combination of the mobile codebase and home codebase improve agent operation and reduce network overhead. In a preferred embodiment an agent is launched with a mobile codebase that is preloaded with classes which are certain to be needed. Classes that are unlikely to be needed are stored in the home codebase. Thus the agent with mobile codebase and home codebase provide the desirable features of the push and pull models without the undesirable network overhead incurred by transmitting unneeded classes around the network or re-downloading code.

Agent travels are defined by an itinerary data structure. The itinerary is composed of a list of destinations, each of which includes: (1) the hostname of a destination computer on the network to which the agent should travel, and (2) the name of a method that the agent should

execute when the agent arrives at the destination computer.

An agent is allowed to modify its itinerary. When an agent modifies its itinerary, the agent owner is automatically notified, thus allowing the owner to "follow" the agent wherever it may travel.

The itinerary provides advantages related to agent and network management. Inspection of the agent itinerary reveals where the agent has travelled and where the agent may travel in the future. Since the itinerary is a standard data structure, an observer can depend on it to be present.

Further, since the itinerary is a separate data structure from the agent, the observer does not need special knowledge of the internal structure of the agent in order to examine the itinerary.

BRIEF DESCRIPTION OF THE DRAWING The invention will be more fully understood from the following Detailed Description of the Invention, in conjunction with the Drawing, of which: Fig. 1 is a block diagram which illustrates agent migration; Fig. 2 is a block diagram which illustrates agent execution in conjunction with agent migration; Fig. 3 is a block diagram of an agent; Fig. 4 is a block diagram of agent interaction with agent managers on multiple computers in a network; Fig. 5 is a flow chart which illustrates agent mobility; Fig. 6 is a block diagram which illustrates agent operation according to an itinerary; Fig. 7 is a block diagram which illustrates the agent runtime environment; and Fig. 8 is a flow chart which illustrates agent deserialization.

DETAILED DESCRIPTION OF THE INVENTION Referring to Fig. 1, an agent 10 comprises a mobile

object which can travel from a first computer 12 to a second computer 14 in a computer network 16. The agent is generated and stored in memory on the first computer for a specific purpose, and includes both data and executable code. The agent executes on the first computer and then migrates to the second computer by being transmitted across the network. The agent then resumes execution on the second computer. When the agent completes execution on the second computer, the agent acts in accordance with an agent itinerary. For example, the agent will migrate to another computer if the itinerary so indicates.

Referring now to Figs. 1 and 2, the agent executes a sequence of instructions during operation. In particular, a first method 18 is executed on the first computer 12 and a second method 20 is executed on the second computer 14.

As a result, migration between computers is transparent from the perspective of the agent.

Referring to Fig. 4, agent mobility is preferably facilitated through use of JAVA agent manager Objects 32 and an Object Serialization facility (a product of Sun Microsystems which is known in the art). Object Serialization operates to serialize objects such that a representative stream of bytes, i.e., data, is generated therefrom. Object Serialization facilitates transmission of an agent across the network by serializing the agent 10 into a format that is suitable for network transmission.

Serialization of the agent may also include serialization of sub-objects which are contained within member variables of the agent. In accordance with the present invention, the serialization process involves the serialization of executable code, data, and an itinerary as hereinafter discussed in greater detail. Once the agent has been serialized, a communication socket to the second computer is opened and the resulting stream of bytes is transmitted to the second computer along the socket.

The serialized agent is regenerated in the second computer 14 upon arrival. In particular, the stream of bytes transmitted along the socket is deserialized in the second

computer. Deserialization regenerates the agent in the form in which the agent existed prior to migration, i.e., an object. Following deserialization, the agent executes a predetermined method specified by its itinerary. The predetermined method may prompt interaction with another object 34 located on the second computer. When the method has been executed, the agent is serialized and transmitted to yet another computer, or possibly back to the first computer. The agent is therein deserialized upon arrival and proceeds to execute another predetermined method and interact with that computer. In the case of the agent migrating back to the first computer, such interaction could be with a host application 36 through which an information query was entered. The agent continues migrating across the network in this manner as execution requires. Eventually, the agent is terminated when execution of the itinerary is complete.

It should be noted that the agent need not necessarily migrate to the initial host (first) computer after executing on a remote (second) computer. The agent could travel to multiple computers, and may not return to the initial host computer.

Referring to Fig. 3, each agent may include data 22, code 24, sub-objects 26 and an itinerary 28. The data portion 22 includes internal state information associated with the agent. The code portion 24 includes executable code associated with operation of the agent. The itinerary portion 28 specifies destinations for the agent. Sub-objects 26 include code of distinct objects contained within the agent. The agent carries the code for these sub-objects.

The code 24 portion of the agent 10 includes a mobile codebase and a reference pointer to a home codebase. The mobile codebase comprises executable code which is retained as part of the agent. When the agent migrates, the mobile codebase is transmitted along with the data, sub-objects and itinerary to the destination. The home codebase is executable code which resides on the computer which originally created and launched the agent or a suitable network server (such as a web server). The reference pointer

to the home codebase is a Uniform Resource Locator ("URL") that allows remote access to the home codebase from other computers in the network. If the agent requires code that is not present in the mobile codebase during execution, the agent retrieves the required code from the home codebase and retains such retrieved code in the mobile codebase.

Referring to Figs. 3 and 6, the itinerary 28 is a data structure which defines agent migration parameters. The itinerary is composed of a list of destinations and the name of a method associated with each such destination. In a preferred embodiment, each destination entry contains the Transmission Control Protocol/Internet Protocol ("TCP/IP") host name of a computer on the network to which the agent is designated to migrate. The method associated with the respective destination is invoked upon arrival at that destination. Hence, each destination represents a location and a task to be performed at the location.

Figs. 4 and 5 illustrate agent mobility. When the determination is made that the agent should migrate, the agent manager 30 examines the itinerary 28 to ascertain the next destination to which the agent 10 is designated to migrate. The agent manager 30 establishes a network connection to the agent manager 32 at the destination computer 14. The agent manager 30 passes the agent and related travel information to the destination agent manager 32. The agent manager 30 then deletes the local copy of the agent, terminates any execution threads which were being used by the agent, and performs other appropriate clean up activities.

From the perspective of the destination computer, the agent arrives at the destination computer as illustrated in step 38. As previously described, the agent arrives in the form of data which includes the code, sub-objects, itinerary and other data. Java/Object Serialization assists the de- serialization and reconstruction of the agent as depicted in step 40. The server then spawns a new thread in which the agent will execute as shown in step 42. A persistent local copy of the agent is then made as illustrated in step 44.

As depicted in step 46 the agent manager invokes the proper method of the agent for execution in the spawned thread at this node. The itinerary contains information indicating which method should be invoked at each designated destination computer. The agent then executes as illustrated in step 50.

When the agent has completed execution of the indicated method, another persistent copy of the agent is stored on the local disk as depicted in step 52 in order to prevent redundant execution in the event that the computer malfunctions before the agent migrates. The agent manager then examines the agent itinerary as illustrated in decision step 54. If the itinerary does not indicate any further destinations then agent execution is deemed complete as shown in step 56. However, if the itinerary indicates further destinations, then the agent manager determines whether the next destination is associated with another computer in decision step 58. If the next destination is not another computer, flow returns to step 44, thereby bypassing network traffic. However, if the next destination is associated with a different agent manager then a network connection to the indicated agent manager is established as depicted in step 60. The destination contains a string which indicates where to travel. The string contains either the name (host name) of a computer or a URL to a distributed object. The agent is then serialized as illustrated in Step 62 and subsequently transmitted to the next agent manager as depicted in Step 64.

Migration in accordance with the itinerary 28 is further illustrated in Fig. 6. The itinerary includes a listing including identification of each agent manager 66 to which the agent is configured to migrate and identification of a method 68 to execute at each respective agent manager. The agent migrates through the agent managers listed in the itinerary sequentially in the order in which the servers are listed, invoking each respective method upon arrival. Such method could be, for example, querying or updating a database on the destination computer.

Fig. 7 illustrates the agent runtime environment. Each

computer 70 on the network includes a Java Virtual Machine 72 running therein. A agent manager 74 runs on each respective Virtual Machine 72. The agent manager includes a plurality of threads 76, each thread having an agent 78 associated therewith. In particular, a new thread is formed when a new agent arrives at the server, and the agent executes on that thread. Security mechanisms prevent each agent from operating outside the scope of the associated thread. When agent execution completes, the agent migrates to the next destination identified in the itinerary.

In order for migration and execution to function properly, the agent manager modifies the mechanism by which Java loads classes. The Java standard library provides an object called a "ClassLoader" which can be subclassed by a programmer to modify the rules that Java follows to load classes. The ClassLoader class allows web browsers to download "applets" from a web server. The agent manager provides a specialized ClassLoader which allows the executable code for mobile agents to travel with the agent.

During a typical execution of a Java program, a Java interpreter loads classes as needed for execution from a logical file system on the local computer. However, agents become separated from the home computer and the home codebase during migration, i.e., agents are separated from the directory or directories on the filesystem of the home computer where the code is stored. Further, sub-objects sometimes need to be created as the agent executes, either as member variables or as temporary variables within the methods. These sub-objects could be instances of classes which are part of the standard Java packages or they could be instances of new classes written by the programmer of the agent. However, since the agent is executing on a different computer than the home computer following migration, the Java virtual machine may not be able to directly retrieve the code for the particular sub-object. To allow agents to properly load classes and construct objects when remote from the home computer, a special ClassLoader is employed by the agent manager whenever an agent attempts to construct an object.

The ClassLoader object first attempts to locate a class on the local file system of the computer. If the class is not on the local file system, the ClassLoader searches the mobile codebase. If such attempt fails, the ClassLoader sends a request back to the home machine of the agent. The agent's travel information contains a reference such as a URL which refers back to the home codebase on the home computer, and by accessing the URL the ClassLoader can retrieve classes from the home computer.

Agent deserialization is illustrated in Fig. 8. As depicted in step 80 the serialized agent arrives as a stream of data. Java Development Kit Object Serialization classes then call an agent manager related method to perform deserialization as shown in step 82. The method reads agent related objects from the object stream as depicted in step 84. In particular, the mobile codebase, itinerary and codebase URL are read by the method. A custom Classloader and ObjectInputStream are constructed as shown in step 86.

Object Serialization then reads the agent and other objects from the input stream as depicted in step 88 and step 90, respectively. When the related objects are read, the ClassLoader retrieves the classes which comprise the agent as illustrated in step 92.

The new object's class is loaded once the classes are retrieved. As depicted in step 94, if the class is determined to have been previously loaded then the previously loaded class instance is employed (step 96) and the object is instantiated using the loaded class object as shown in step 98. However, if the class has not been previously loaded as determined in inquiry step 94, then inquiry is made as to whether the class is on the local class path of the destination computer as illustrated in decision step 100.

If the class is present on the local machine then the class is loaded therefrom as shown in step 102 and the object is instantiated using the loaded class object as depicted in step 98. However, if the class is not found on a local class path as shown in step 100 then an inquiry is made as to whether the class is in the mobile codebase as shown in step

104. If the class is located in the mobile codebase then the class is loaded therefrom as shown in step 106 and the object is instantiated using the loaded class object as shown in step 98. However, if the class is not located in the mobile codebase in decision step 104 then the class is loaded by accessing the home codebase as shown in step 108. If the codebase pointer is an Internet type pointer such as a Hyper- Text Transfer Protocol ("HTTP") URL, as determined in inquiry step 110, then an HTTP request is sent to the local web server as shown in step 112 and the retrieved class is added to the Mobile CodeBase as depicted in step 114. However, if the codebase URL is not a HTTP URL then a remote method request is sent to a RemoteClassLoader object as shown in step 116 and the class is added to the mobile codebase as shown in step 114. In either case, the object is instantiated using the loaded class object as shown in step 98. If more objects exist in the stream to be retrieved, as determined in decision step 118, then another object is read from the input stream as illustrated in step 90. If there are no more objects to be retrieved, flow terminates.

Having described the preferred embodiments of the invention, other embodiments which incorporate concepts of the invention will now become apparent to one of skill in the art. Therefore, the invention should not be viewed as limited to the disclosed embodiments but rather should be viewed as limited only by the spirit and scope of the appended claims.

A program listing follows in the attached APPENDIX.

1 /* $Header: /com/meitca/hsl/zonesjagents/shared/Agent.java 13 9/30/96 6:23p Walsh $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Base class for mobile Agent<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/shared/Agent.java $<BR> 13 *<BR> 14 * 13 9/30/96 6:23o Walsh<BR> 15 * clean up javadoc comments<BR> 16 *<BR> 17 * 12 9/29/96 4:09p Walsh<BR> 18 * Give Agent access to AgentPackage information<BR> 19 *<BR> 20 * 11 9/28/96 6:57p Walsh<BR> 21 * Comment out debug println<BR> 22 *<BR> 23 * 10 9/09/96 4.58p Walsh<BR> 24 * Add prepareForTransport, completedTransport methods<BR> 25 *<BR> 26 * 9 9/04/96 3:18p Noemi<BR> 27 * Added static initialzed Moved functionality related to collaboration<BR> 28 * to new CollaboratorAgent subclass<BR> 29 *<BR> 30 * 8 8/30/96 4:30p Noemi<BR> 31 * Changed constructors and finalizer to operate on AgentGroup references<BR> 32 * (rather than AgentGroupImpl references)<BR> 33 *<BR> 34 * 7 8/28/96 2:45p Noemi<BR> 35 * Removed SourcesSafe conflict garbage.<BR> <P>36 *<BR> 37 * 6 8/28/96 2:20p Noemi<BR> 38 * Added support for AgentGroups.<BR> <P>39 *<BR> 40 * 5 8/23/96 3:52p Walsh<BR> 41 * Remove live method (superceded by ad-hoc invocation)<BR> 42 *<BR> 43 * 4 8/22/96 6:36p Walsh<BR> 44 * Remove parameter to live method<BR> 45 *<BR> 46 * 3 8/13/96 2:23p Walsh<BR> 47 * Add some comments & documentation 48 *<BR> 49 * 2 8/09/96 4:49p Walsh<BR> 50 */<BR> 51 package com.meitca.hsl.zonesjagents.shared;<BR> 52<BR> 53 import java.util.*;<BR> 54 import java.net.InetAddress,<BR> 55<BR> 56 import com.meitca.hsl.zonesjagents.conduit.*;<BR> 57<BR> 58<BR> 59 /**<BR> 60 * A base class representing a traveling agent program. All user defined<BR> 61 * agents should be derived from the class Agent. An agent<BR> 62 * travels from machine to machine as dictated by its Itinerary. At each stop,<BR> 63 * a specified method will be invoked. After the method completes, the Agent<BR> 64 * will be sent to the next host on the itinerary. To develop an agent, a<BR> 65 * programmer should derive a class from Agent.<BR> <P>66 * @see ConduitServer<BR> 67 * @see AgentGroup<BR> 68 * @author Noemi Paciorek<BR> 69 * @author Thomas Walsh<BR> 70 */<BR> 71 public abstract class Agent {<BR> 72<BR> 73 // Class variables<BR> 74 /** A counter used to generate the Agent's ID */<BR> 75 protected static int agentNum = 0; // counter for agents started on a system<BR> 76<BR> 77 /** A unique ID representing the host the agent was initiated from*/<BR> 78 protected static String host; // unique host ID<BR> 79<BR> 80 // Instance variables<BR> 81 /** A unique ID representing the Agent */<BR> 82 protected String agentID; // unique agent ID<BR> 83<BR> 84 // A reference to the Agent's AgentPackage. This reference will only be<BR> 85 // valid when the Agent is actually tavelling. Prior to travel, this<BR> 86 // will be a null reference (for example the reference will be null<BR> 87 // when the Agents constructor is executing)<BR> 88 private AgentPackage itsPackage;<BR> 89<BR> 90 // Static initializer<BR> 91 static {<BR> 92 /*<BR> 93 * Try to obtain the host's name and IP address. If this fails,<BR> 94 * construct a pseudo-random name and hope for the best! (Of course, 95 * this should never happen.)<BR> 96 */<BR> 97 try {<BR> 98 host = InetAddress.getLocalHost().toString();<BR> 99 } catch (Exception e) {<BR> 100 host = "~FOSTID~" + new Random().nextLong();<BR> 101 }<BR> 102 }<BR> 103<BR> 104 // Constructors<BR> 105 /** Constructs an Agent */<BR> 106 public Agent() {<BR> 107 /*<BR> 108 * Assign a unique agent ID.<BR> <P>109 */<BR> 110 try {<BR> 111 agentID = host + "/agent" + nextAgentNum();<BR> 112 //System.out.println("Agent ID = " + agentID);<BR> 113 } catch (Exception e) {<BR> 114 System.out.println("Agent constructor error: " + e.getMessage());<BR> 115 e.printStackTrace();<BR> 116<BR> 117 }<BR> 118<BR> 119 itsPackage = null;<BR> 120 }<BR> 121<BR> 122 // Class methods<BR> 123 private final synchronized int nextAgentNum() {<BR> 124 return ++agentNum;<BR> 125 }<BR> 126<BR> 127 // Instance methods<BR> 128 /**<BR> 129 * Retrieves the Agent's ID. AnAgentID is a unique String<BR> 130 * which identifies a particular instance of an Agent.<BR> <P>131 * @return The Agent's ID.<BR> <P>132 */<BR> 133 public final String getAgentID() {<BR> 134 return agentID;<BR> 135 }<BR> 136<BR> 137 /**<BR> 138 * Converts an Agent to a String. Implementation simply<BR> 139 * returns the AgentID.<BR> <P>140 * @return A String representation of the Agent.<BR> <P>141 */ 142 public final String toString() {<BR> 143 return getAgentID();<BR> 144 }<BR> 145<BR> 146 /**<BR> 147 * This is called by the ConduitServer immediatley prior to<BR> 148 * the agent being transported to its next destination. Derived<BR> 149 * Agents can be override this method to perform any final processing<BR> 150 * needed before transport<BR> 151 */<BR> 152 public void prepareForTransport() {<BR> 153 }<BR> 154<BR> 155 /**<BR> 156 * This is called by the ConduitServer when the Agent arrives at<BR> 157 * its new destination. Derived Agents can override this method<BR> 158 * to perform any processing needed on arrival<BR> 159 */<BR> 160 public void completedTransport() {<BR> 161 }<BR> 162<BR> 163 /**<BR> 164 * Returns a reference to the Agents Itinerary. The Itinerary<BR> 165 * is only available when the Agent is traveling. It is not<BR> 166 * available during the Agent's constructor. If the Itinerary<BR> 167 * is not available, this method returns null.<BR> <P>168 * @ The Agents Itinerary or null if the itinerary is<BR> 169 * not available<BR> 170 */<BR> 171 public Itinerary getItinerary() {<BR> 172 if (itsPackage != null) {<BR> 173 return itsPackage.getIinerary();<BR> 174 } else {<BR> 175 return null;<BR> 176 }<BR> 177 }<BR> 178<BR> 179 /**<BR> 180 * Returns a URL pointing to the Agent's codebase on it home machine.<BR> <P>181 * This URL is used in conjunction with the AgentCodebase class to<BR> 182 * retrieve the bytecodes of the Agent and it related classes.<BR> <P>183 * The URL available when the Agent is traveling. It is not<BR> 184 * available during the Agent's constructor. If the URL<BR> 185 * is not available, this method returns null.<BR> <P>186 * @ The URL of the Agents codebase or null if the URL is<BR> 187 * not available<BR> 188 */ 189 public String getHomeCodebaseURL() {<BR> 190 if (itsPackage != null) {<BR> 191 return itsPackage.getHomeCodebaseURL();<BR> 192 } else {<BR> 193 return null;<BR> 194 }<BR> 195 }<BR> 196<BR> 197 /**<BR> 198 * This Method is called internally by the ConduitServer to<BR> 199 * provide the Agents with a reference to its package.<BR> <P>200 */<BR> 201 public void setPackage(AgentPackage agentPackage) {<BR> 202 itsPackage = agentPackage;<BR> 203 }<BR> 204<BR> 205 } 1 /* $Header: /com/meitca/hsl/zonesjagents/shared/AgentCodebase.java 3 11/11/96 5:25p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Class providing accessability to the home codebase of the agent<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/shared/AgentCodebase.java $<BR> 13 *<BR> 14 * 3 11/11/96 5:25p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 2 9/30/96 6:23p Walsh<BR> 18 * clean up javadoc comments<BR> 19 *<BR> 20 * 1 9/28/96 6:35p Walsh<BR> 21 * initial version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca.hsl.zonesjagents.shared;<BR> 25<BR> 26 import java.net *;<BR> 27 import java.io.*<BR> 28 import sun.net.www.MeteredStream;<BR> 29<BR> 30 import com.meitca hsl.zonesjagents.remoteloader *;<BR> 31<BR> 32 /**<BR> 33 * The AgentCodebase class provides accessability to the "home<BR> 34 * codebase" of an agent As an agent travels, it may construct<BR> 35 * an object whose bytecodes may not be installed on the machine<BR> 36 * to which it has travelled. In some cases, the agent may have<BR> 37 * already constructed another instance of the same class or, the<BR> 38 * user or programmer may have specified that this class was a<BR> 39 * "related class" when launching the agent. In both of these<BR> 40 * cases, the bytecodes for the class should have already been<BR> 41 * loaded into the Agent's MobileCodebase. If the bytecodes for<BR> 42 * the new object HAVE NOT already been loaded into the MobileCodebase.<BR> <P>43 * the CoduitServer needs a mechanism for finding an retrieving<BR> 44 * these bytecodes. The AgentCodebase provides an mechanism through<BR> 45 * which Agents can retrieve code from their home locations.<BR> <P>46 * @see Agent<BR> 47 * @see MobileCodebase 48 * @author Thomas Walsh<BR> 49 */<BR> 50 public class AgentCodebase {<BR> 51 /**<BR> 52 * these constants identify the protocols that<BR> 53 * can be used to retrieve bytecodes from an<BR> 54 * agents codebase.<BR> <P>55 */<BR> 56 static final int UNKNOWN = -1;<BR> 57 static final int RMI = 0;<BR> 58 static final int HTTP = 1;<BR> 59 static final int FILE = 2;<BR> 60<BR> 61 /**<BR> 62 * The protocol to use to retrieve bytecodes from the<BR> 63 * AgentCodebase<BR> 64 */<BR> 65 int itsProtocol;<BR> 66<BR> 67 /** An URL pointing back to the AgentCodebase */<BR> 68 String itsURL;<BR> 69<BR> 70 /**<BR> 71 * A ClassFileLoader object which may be used to<BR> 72 * retrieve agent bytecodes from the local filesystem<BR> 73 * (when a file: url is used to identify the codebase<BR> 71 */<BR> 75 ClassFileLoader itsClassFileLoader.<BR> <P>76<BR> 77 /**<BR> 78 * Constructs an AgentCodebase from the given URL.<BR> <P>79 * @param url An URL pointing to the AgentCodebase. This<BR> 80 * URL can be;<br><BR> 81 <ul> 82 * <li>An HTTP url pointing to a location on a web server<BR> 83 * (such as <b>http://host/directory</b>)<BR> 84 * <li>An RMI url pointing to a RemoteClassLoader<BR> 85 * server (such as <b>rmi://host/RemoteClassLoader/directory</b>)&l t;BR> 86 * <li>A FILE url pointing to a local directory<BR> 87 * (such as <b>file:C:\directory</b>)<BR> 88 * <li>An empty string or null which indicates that the agents code<BR> 89 * is on the CLASSPATH of this machine.<BR> <P>90 * </ul><BR> 91 * @exception MalformedURLException If the url passed in was invalid<BR> 92 */<BR> 93 public AgentCodebase(String url) throws MalformedURLException {<BR> 94 itsProtocol = -1; 95 itsURL = null;<BR> 96 itsClassFileLoader= null;<BR> 97 parseURL(url);<BR> 98<BR> 99 if (itsProtocol == FILE)<BR> 100 itsClassFileLoader = new ClassFileLoader();<BR> 101 }<BR> 102<BR> 103 /**<BR> 104 * Retrieve the bytecodes for the given class<BR> 105 * @param classname The name of the class whose bytecodes to<BR> 106 * retrieve<BR> 107 * @return The classes bytecodes in the form of a byte array<BR> 108 * @exception ClassNotFoundException If the class could not be loaded<BR> 109 */<BR> 110 public byte[] retrieveCode(String classname) throws ClassNotFoundException {<BR> 111 switch (itsProtocol) {<BR> 112 case RMI:<BR> 113 return RemoteClassLoaderImpl.retrieveRemoteClass(itsURL, classname);<BR> 114 case HTTP:<BR> 115 return retrieveHTTPClass(classname);<BR> 116 case FILE:<BR> 117 return itsClassFileLoader.loadClassFileFromDirectory(itsURL, classname);<BR> 118 default:<BR> 119 throw new ClassNotFoundException("Unsupported protocol");<BR> 120 }<BR> 121 }<BR> 122<BR> 123 /* Used internally to parse URL passes into ctor */<BR> 124 private void parseURL(String url) throws MalformedURLException {<BR> 125 if (url != null) {<BR> 126 int sep = url indexOf(' ');<BR> 127<BR> 128 if (sep != -1) {<BR> 129 String protocol = url.substring(0, sep);<BR> 130 if (protocol.equals("rmi")) {<BR> 131 itsProtocol = RMI;<BR> 132 itsURL = url;<BR> 133 } else if (protocol.equals("http")) {<BR> 134 itsProtocol = HTTP;<BR> 135 itsURL = url;<BR> 136 if (itsURL.endsWith("/")) {<BR> 137 itsURL = itsURL.substring(0, itsURL.length()-1);<BR> 138 }<BR> 139 } else if (protocol.equals("file")) {<BR> 140 itsProtocol = FILE;<BR> 141 142 // strip off the file: portion so all we are left with is<BR> 143 // the directory spec of the codebase.<BR> <P>144 itsURL = url.substring(sep+1, url.length());<BR> 145<BR> 146 } else }<BR> 147 // we will assume file since the user might be trying to specify a<BR> 148 // DOS style filename (ie C:\WINNT)<BR> 149 itsProtocol = FILE;<BR> 150 itsURL = url;<BR> 151 }<BR> 152 } else {<BR> 153 // assume file<BR> 154 itsProtocol = FILE;<BR> 155 itsURL = url;<BR> 156 }<BR> 157 } else {<BR> 158 // the URL was null. This means that the Agents code is located somewhere on<BR> 159 // the class path of this machine. We will set the protocol to FILE and leave<BR> 160 // the url as null<BR> 161 itsProtocol = FILE;<BR> 162 }<BR> 163 }<BR> 164<BR> 165 /* Used internally to retrieve .class files from a web server */<BR> 166 private byte[] retrieveHTTPClass(String classname) throws ClassNotFoundException {<BR> 167 try {<BR> 168 // first we will try to load the agent using its fully qualified class<BR> 169 // name. If the HTTP URL was http://host/Agents and the class name<BR> 170 // was test.TestAgent, we will build an URL like the following:<BR> 171 // htp://host/Agents/test/TestAgent.class<BR> 172 URL classUrl = new URL(itsURL + "/" + classname.replace(' ', '/') + ".class");<BR> 173<BR> 174 MeteredStream stream = (MeteredStream)classUrl.getContent();<BR> 175 int length = stream.available();<BR> 176 byte data[] = new byte[length];<BR> 177<BR> 178 stream.read(data);<BR> 179 return data;<BR> 180 } catch (IOException ioerror) {<BR> 181 // The fully qualified class name didn't work, so lets try to<BR> 182 // strip off all of the pacakge names and search for just the<BR> 183 // class name. If the HTTP URL was http://host/Agents and the class name<BR> 184 // was test.TestAgent, we will build an URL like the following;<BR> 185 // htpp://host/Agents/TestAgent.class<BR> 186 int lastSep = classname.lastIndexOf('.');<BR> 187 if (lastSep != -1) {<BR> 188 try { 189 URL classUrl = new URL(itsURL + "/" + classname.substring(lastSe<BR> + 1, classname.length() + ".class");<BR> 190<BR> 191 MeteredStream stream = (MeteredStream)classUrl.getContent();<BR> 192 int length = stream.available();<BR> 193 byte data[] = new byte[length];<BR> 194<BR> 195 stream.read(data);<BR> 196 return data;<BR> 197 catch (Exception error) {<BR> 198 throw new ClassNotFoundException("Could not load class " + classname + "from<BR> " + itsURL);<BR> 199 }<BR> 200 } else {<BR> 201 throw new ClassNotFoundException("Could not load class " + classname + "from" + its<BR> RL);<BR> 202 }<BR> 203 } catch (Exception error) {<BR> 204 throw new ClassNotFoundException("Could not load class " + classname + "from " + itsURL);<BR> 205 }<BR> 206 }<BR> 207 } 1 /* $Header: /com/meitca/hsl/zonesjagents/shared/AgentConstants.java 2 11/11/96 5:25p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRITPION<BR> 10 * Constants used by Java Agents system.<BR> <P>11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/shared/AgentConstants.java $<BR> 13 *<BR> 14 * 2 11/11/96 5:25p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 1 10/10/96 5:50p Walsh<BR> 18 * initial version<BR> 19 *<BR> 20 */<BR> 21 package com.meitca.hsl.zonesjagents.shared;<BR> 22<BR> 23 import hava.io.FIle;<BR> 24<BR> 25 /**<BR> 26 * Class contains constants used within the Java Agent System.<BR> <P>27 */<BR> 28 public class AgentConstants {<BR> 29 /**<BR> 30 * Contains the value of the "zones.home" property (which<BR> 31 * points to the Zones installation directory)<BR> 32 */<BR> 33 public static String ZONES~HOME;<BR> 34<BR> 35 /**<BR> 36 * Contains the value of the "zones.user.home" property (which<BR> 37 * points to the Zones user specific directory)<BR> 38 */<BR> 39 public static String ZONES~USER~HOME;<BR> 40<BR> 41 /**<BR> 42 * Contains the path of the images subdirectory of the Zones<BR> 43 * installation directory.<BR> <P>44 */<BR> 45 public static String IMAGE~DIR;<BR> 46<BR> 47 /** 48 * Contains the path of the Agent subdirectory of the Zones<BR> 49 * installation directory.<BR> <P>50 */<BR> 51 public static String AGENT~DIR;<BR> 53 /**<BR> 54 * Contains the path of the lib subdirectory of the Zones/Agents<BR> 55 * installation directory.<BR> <P>56 */<BR> 57 public static String AGENT~LIB~DIR;<BR> 58<BR> 59 /**<BR> 60 * Contains the path of the Agent subdirectory of the Zones<BR> 61 * installation directory.<BR> <P>62 */<BR> 63 public static String USER~AGENT~DIR;<BR> 64<BR> 65<BR> 66 /** Static Intializer is used to initialize some of the CONSTANTS */<BR> 67 static {<BR> 68 ZONES~HOME = System.getProperty("zones.home", File.separator + "Zones");<BR> 69 if (ZONES~HOME != null) {<BR> 70 // terminate the directory name with a separator if<BR> 71 // it's not already terminated<BR> 72 if (!ZONES~HOME.endsWith(File.separator))<BR> 73 ZONES~HOME += File.separator;<BR> 74<BR> 75 IMAGE~DIR = ZONES~HOME + "images" + File.separator;<BR> 76 AGENT~DIR = ZONES~HOME + "Agents" + File.separator;<BR> 77 AGENT~LIB~DIR = AGENT~DIR + "lib" + File separator;<BR> 78 }<BR> 79<BR> 80 ZONES~USER~HOME = System.getProperty("zones.user.home");<BR> 81 if (ZONES~USER~HOME == null) {<BR> 82 // the zones.user.home Property was not defined.<BR> <P>83 // try the user.home Property<BR> 84 ZONES~USER~HOME = System.getProperty("user.home"," ");<BR> 85 if (ZONES~USER~HOME != null) {<BR> 86 // terminate the directory name with a separator if<BR> 87 // it's not already terminated<BR> 88 if (!ZONES~USER~HOME.endsWidth(File.separator))<BR> 89 ZONES~USER~HOME += File.separator;<BR> 90<BR> 91 ZONES~USER~HOME += ".Zones";<BR> 92 }<BR> 93 }<BR> 94 95 if (ZONES~USER~HOME != null) {<BR> 96 // terminate the directory name with a separator if<BR> 97 // it's not already terminated<BR> 98 if (!ZONES~USER~HOME.endsWidth(File.separator))<BR> 99 ZONES~USER~HOME += File.separator;<BR> 100<BR> 101 USER~AGENT~DIR = ZONES~USER~HOME + "Agents" + File.separator;<BR> 102 }<BR> 103 }<BR> 104 } 1 /* $Header: /com/meitca/hsl/zonesjagents/shared/ClassFileLoader.java 3 11/11/96 5:25p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Loads a ".class" file off of the local filesystem.<BR> <P>11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/shared/ClassFileLoader.java $<BR> 13 *<BR> 14 * 3 11/11/96 5:25p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 2 9/30/96 6:23p Walsh<BR> 18 * clean up javadoc comments<BR> 19 *<BR> 20 * 1 9/28/96 6:35p Walsh<BR> 21 * intial version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca.hsl.zonesjagents.shared;<BR> 25<BR> 26 import sun.tools.java.*;<BR> 27 import java.io.*,<BR> 28<BR> 29 /**<BR> 30 * The ClassFileLoader class loads a Classes bytecodes off of the<BR> 31 * local filesystem. The user can either specify a particular directory<BR> 32 * from which the bytecodes should be retieved, have the ClassFileLoader<BR> 33 * search the system CLASSPATH or specify a custom Class Path which should<BR> 34 * be searched for the bytecodes.<BR> <P>35 * @author Thomas Walsh<BR> 36 */<BR> 37 public class ClassFileLoader {<BR> 38 /**<BR> 39 * The ClassPath which should be searched for ClassFiles. This could<BR> 40 * represent the system CLASSPATH, or a custom ClassPath sepcified by the<BR> 41 * user.<BR> <P>42 */.<BR> <P>43 ClassPath itsClassPath;<BR> 44<BR> 45 /**<BR> 46 * Constructs a ClassFileLoader object. This constructor sets the<BR> 47 * ClassFileLoader up so that it will search the system's CLASSPATH.

48 */<BR> 49 public ClassFileLoader() {<BR> 50 itsClassPath = new ClassPath(System.getProperty("java.class.path"));<BR> 51 }<BR> 52<BR> 53 /**<BR> 54 * Constructs a ClassFileLoader object. The pathstr parameter specifies<BR> 55 * a custom ClassPath from which bytecodes are to be retrieved.<BR> <P>56 * @param pathstr A custom ClassPath from which bytecodes are to be<BR> 57 * retrieved<BR> 58 */<BR> 59 public ClassFileLoader(String pathstr) {<BR> 60 itsClassPath = new ClassPath(pathstr);<BR> 61 }<BR> 62<BR> 63 /**<BR> 64 * Loads a class from the objects class path. Depending on which<BR> 65 * version of the constructor was used, this could mean that the<BR> 66 * system's CLASSPATH is searched or that a custom user-defined<BR> 67 * ClassPath is searched.<BR> <P>68 * @param classname The fully qualified class name of the class to<BR> 69 * be loaded.<BR> <P>70 * @return The bytecodes for the requested class in the form of a<BR> 71 * byte array<BR> 72 * @exception ClassNotFoundException If the class could not be located on<BR> 73 * the ClassPath<BR> 74 */<BR> 75 public byte[] loadClassFileFromClassPath(String classname) throws ClassNotFoundException {<BR> 76 String filename = classname.replace('.', File.separatorChar) + ".class";<BR> 77 ClasFile file = itsClassPath.getFile(filename);<BR> 78<BR> 79 if (file != null) {<BR> 80 try {<BR> 81 long length = file.length();<BR> 82 InputStream stream = file.getInputSteam();<BR> 83 byte data[] = new byte[(int)length];<BR> 84<BR> 85 stream.read(data);<BR> 86 return data;<BR> 87 } catch (IOException e) {<BR> 88 throw new ClassNotFoundException(e.getMessage());<BR> 89 }<BR> 90 } else {<BR> 91 throw new ClassNotFoundException("ClassFile not found on ClassPath: " + classname);<BR> 92 }<BR> 93 }<BR> 94 1 /* $Header: /com/meitca/hsl/zonesjagents/shared/JASProperties.java 4 11/11/96 5:25p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center of America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Zones Agent Property File implementation.<BR> <P>11 * $Log: /com/meitca/hsl/zonesjagents/shared/JASProperties java $<BR> 12 *<BR> 13 * 4 11/11/96 5:25p Billp<BR> 14 * Made correction to company name<BR> 15 *<BR> 15 * 3 10/10/96 5:56p Walsh<BR> 17 * Make use of constants in AgentConstants class<BR> 18 *<BR> 19 * 2 10/10/96 2:30p Walsh<BR> 20 * Add default constructor<BR> 21 *<BR> 22 * 1 10/07/96 5.07p Walsh<BR> 23 * intial versions<BR> 24 *<BR> 25 */<BR> 26 package com.meitca.hsl.zonesjagents.shared;<BR> 27<BR> 28 import java.io.*;<BR> 29 import java.util.*;<BR> 30<BR> 31 /**<BR> 32 * The JASProperties supports the storage of<BR> 33 * user specific and server specific properties.<BR> <P>34 * <ul><BR> 35 * <li>User specific properties are stored in<BR> 36 * zones.user.home\Agents directory. If the<BR> 37 * zones.user.home System property is not defined,<BR> 38 * user properties are stored in the<BR> 39 * user.home\.Zones\Agents directory<BR> 40 * <li>Server specific properties are stored in<BR> 41 * zones.home\Agents\Lib<BR> 42 * </ul><BR> 43 * @see Properties<BR> 44 * @author Joe DiCelie<BR> 45 * @author Tom Walsh<BR> 46 */<BR> 47 public class JASProperties extends PropertyFIle { 141 return data;<BR> 142 } else {<BR> 143 throw new ClassNotFoundException ("Could not find " + classname +<BR> 144 " in directory " + dir);<BR> 145 }<BR> 146 }<BR> 147 } catch (IOException e) {<BR> 148 throw new ClassNotFoundException ("Could not load " + classname +<BR> 149 " . Error: " + e getMessage());<BR> 150 }<BR> 151 }<BR> 152 } 95 /**<BR> 96 * Loads a class a particular directory.<BR> <P>97 * @param dir The directory from which to retireve the class. If<BR> 98 * this parameter is null or an empty string, the ClassPath<BR> 99 * is searched for the class<BR> 100 * @param classname The fully qualified class name of the class to<BR> 101 * be loaded.<BR> <P>102 * @returns The bytecodes for the requested class in the form of a<BR> 103 * byte array<BR> 104 * @exception ClassNotFoundException If the class could not be located on<BR> 105 * the ClassPath<BR> 106 */<BR> 107 public byte[] loadClassFileFromDirectory(String dir, String classname) throws ClassNotFoundException {<BR> 108 // if a null or an empty string was passed in for dir, fall back to<BR> 109 // searching the class path for the class<BR> 110 if ((dir == null) || (dir.length() == 0))<BR> 111 return ioadClassFileFromClassPath(classname);<BR> 112<BR> 113 // place a sperator char on the end of the directory specification<BR> 114 // if it does not already have one<BR> 115 if (!dir.endWich(File.separator)) {<BR> 116 dir = dir + File.separator;<BR> 117 }<BR> 118<BR> 119 String fullFilename = dir + classname.replace('.', File.separatorChar) + ".class";<BR> 120<BR> 121 try {<BR> 122 File file = new File (fullFilename);<BR> 123<BR> 124 if (file.exists()) {<BR> 125 long length = file.length();<BR> 126 FileInputStream stream = new FileInputStream(file);<BR> 127 byte data[] = new byte[(int)length];<BR> 128<BR> 129 stream.read(data);<BR> 130 return data;<BR> 131 } else {<BR> 132 int lastSep = classname.lastIndexOf('.');<BR> 133 if (lastSep != -1) {<BR> 134 String filename = dir + classname.substring(lastSep + 1, classname.length()<BR> + ".class";<BR> 135 file = new File(filename);<BR> 136 long length = file.length();<BR> 137 FileInputStream stream = new FileInputStream(file);<BR> 138 byte data[] = new byte[(int)length]; .<BR> <P>139<BR> 140 stream.read(data); 48<BR> 49 /**<BR> 50 * This constant should be passed into constructor to<BR> 51 * specify that this object will contain <b>Server</b><BR> 52 * specific properties.<BR> <P>53 */<BR> 54 public static final int SERVER = 0;<BR> 55<BR> 56 /**<BR> 57 * This constant should be passed into constructor to<BR> 58 * specify that this object will contain <b>User</b><BR> 59 * specific properties.<BR> <P>60 */<BR> 61 public static final int USER = 1;<BR> 62<BR> 63 private static final String PROP~FILE~SUFFIX = ".properties";<BR> 64 private static final String DEFAULT~DESC = "Zones Property File";<BR> 65<BR> 66 /**<BR> 67 * Opens a Properties file and constructs a JASProperties object.<BR> <P>68 * @param appName A unique name used to identify the application.<BR> <P>69 * The <i>appName</i> is used in constructing the name of the<BR> 70 * filename of the corresponding properties file. The<BR> 71 * properties file will have a name of the form<BR> 72 * "appName.properties"<BR> 73 * @param type Idientifies the type of properties file to open.<BR> <P>74 * This parameter can have the value <b>JASProperties.USER</b><BR> 75 * or <b>JASProperties.SERVER</b>. The <i>type</i> parameter<BR> 76 * controls where the proerties file is opened from.<BR> <P>77 * <ul><BR> 78 * <li>User specific properties are stored in<BR> 79 * zones.user.home\Agents directory. If the<BR> 80 * zones.user.home System property is not defined,<BR> 81 * user properties are stored in the<BR> 82 * user.home\.Zones\Agents directory<BR> 83 * <li>Server specific properties are stored in<BR> 84 * zones.home\Agents\Lib<BR> 85 * </ul><BR> 86 * @param description A description of this JASProperties object.<BR> <P>87 * The description will be written to the header of the<BR> 88 * Properties file if the save method is called<BR> 89 * @param createIfNecessary If set to true, the JASProperties will<BR> 90 * create the Properties file if it does not already<BR> 91 * exist. If set to false, then the constructor will<BR> 92 * throw a FileNotFoundException if the Properties file<BR> 93 * does not exists.<BR> <P>94 * @exception FileNotFoundException If the Properties file could not 95 * be found and the createIfNecessary parameter is false.<BR> <P>96 * @exception IOException If an error occured while attempting to<BR> 97 * access the Properties file<BR> 98 * @exception IllegalArgumentException If the value passes into the<BR> 99 * type argument was not valid.<BR> <P>100 */<BR> 101 public JASProperties(String appName, int type, String description,<BR> 102 boolean createIfNecessary)<BR> 103 thorws FileNotFoundException, IOException, IllegalArgumentException {<BR> 104<BR> 105 itsDescription = (description != null) ? description : DEFAULT~DESC;<BR> 106<BR> 107 // Open the default JAS security properties file.<BR> <P>108 itsFile = locatePropertiesFile (appName, type, createIfNecessary);<BR> 109<BR> 110 loadProperties ();<BR> 111 }<BR> 112<BR> 113 /**<BR> 114 * Builds an "empty" Properties object. This method can be used<BR> 115 * to construct a Properties object which returns only default values.<BR> <P>116 * This behavior may be desired if the Properties file can not be found<BR> 117 * and the program wishes to continue execution using its default values<BR> 118 * for preferences.<BR> <P>119 */<BR> 120 public JASProperties () {<BR> 121<BR> 122 }<BR> 123<BR> 124 /*<BR> 125 * Builds a prperties filename based on the appName and properties<BR> 126 * file type<BR> 127 */<BR> 128 private File locatePropertiesFile (String appName, int type,<BR> 129 boolean createIfNecessary)<BR> 130 throws IllegalArgumentException, FileNotFoundException, IOException {<BR> 131<BR> 132 String propDirName;<BR> 133 if (type == SERVER) {<BR> 134 // We are accessing a server properties file.<BR> <P>135 // Server specific properties are stored in<BR> 136 // the directory zones.home\Agents\Lib.<BR> <P>137<BR> 138 propDirName = AgentConstants.AGENT~LIB~DIR;<BR> 139 } else if (type == USER) {<BR> 140 propDirName = AgentConstants.USER~AGENT~DIR;<BR> 141 } else { 142 throw new IllegalArgumentException ("Bad Properties File Type: " + type);<BR> 143 }<BR> 144<BR> 145<BR> 146 // See if the propperties directory exists<BR> 147 File propDir = new File (propDirName);<BR> 148 if (!propDir.exists()) {<BR> 149 // The directory does not exists.<BR> <P>150 // See if we should create it.<BR> <P>151 if (createIfNecessary) {<BR> 152 if (!propDir.mkdirs()) {<BR> 153 // We could not create the directory.<BR> <P>154 // Throw an IOException<BR> 155 throw new IOException ("Could create properties directory "<BR> 156 + propDir.toString()<BR> 157 }<BR> 158 } else {<BR> 159 // The directory did not exists.<BR> <P>160 // Throw a FileNotFoundException<BR> 161 throw new FileNotFoundException ("Properties directory "<BR> 162 + propDir.toString() + " did not exists");<BR> 163 }<BR> 164 }<BR> 165<BR> 166 // see if the properties file exists<BR> 167 File propFile = new File (propDirName + File.separator +<BR> 168 appName + PROP~FILE~SUFFIX);<BR> 169 if (!propFile.exists()) {<BR> 170 // The directory does not exist.<BR> <P>171 // See if we should create it.<BR> <P>172 if (createIfNecessary) {<BR> 173 // create the file.<BR> <P>174 FileOutputStream out = new FileOutputStream(propFile);<BR> 175 PrintStream print = new PrintStream(out);<BR> 176 print.println ("&num " + its Description);<BR> 177 print.close();<BR> 178 // That should have created the file<BR> 179 } else {<BR> 180 // The properties file did not exists.<BR> <P>181 // Throw a FileNotFoundException<BR> 182 throw new FileNotFoundException ("Properties file "<BR> 183 + propFile.toString() + " did not exists");<BR> 184 }<BR> 185 }<BR> 186 return propFile;<BR> 187 } 188 }<BR> 189<BR> 190<BR> 191<BR> 192 1 /* $Header: /com/meitca/hsl/zonesjagents/shared/PropertyFile.java 2 11/11/96 5:25p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Properties (Preference) File object.<BR> <P>11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/shared/PropertyFile.java $<BR> 13 *<BR> 14 * 2 11/11/96 5:25p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 1 10/07/96 5:07p Walsh<BR> 18 * initial versions<BR> 19 *<BR> 20 */<BR> 21 package com.meitca.hsl.zonesjagents.shared;<BR> 22<BR> 23 import java.io.*;<BR> 24 import java.util.*;<BR> 25<BR> 26 /**<BR> 27 * The PropertyFile object extends the behavior of the Properties class<BR> 28 * by associating the Properties with a disk file. The PropertyFile<BR> 29 * object automatically loads the Proeprties out of the file (using the<BR> 30 * Properties.load method) and supplies a method for saving of any updated<BR> 31 * Properties back to disk, called saveProperties.<BR> <P>32 * @see Properties<BR> 33 * @author Joe DiCelie<BR> 34 * @author Tom Walsh<BR> 35 */<BR> 36 public class PropertyFile extends Properties {<BR> 37<BR> 38 /** The name of the properties file corresponding to this Properties object */<BR> 39 protected File itsFile;<BR> 40<BR> 41 /** A description of this Properties object. */<BR> 42 protected String itsDescription;<BR> 43<BR> 44<BR> 45 /**<BR> 46 * Opens the specified Properties file and constructs a<BR> 47 * JASProperties object.

48 * @param propertiesFileName Name of the Properties file to open<BR> 49 * @param description A description of this JASProperties object.<BR> <P>50 * The description will be written to the header of the<BR> 51 * Properties file if the save method is called<BR> 52 * @exception FileNotFoundException If the Properties file could not<BR> 53 * be found and the createIfNecessary parameter is false.<BR> <P>54 * @exception IOException If an error occurred while attempting to<BR> 55 * access the Properties file<BR> 56 */<BR> 57 public PropertyFile(String propertiesFileName, String description)<BR> 58 throws FileNotFoundException, IOException {<BR> 59<BR> 60 itsFil = new File(propertiesFileName);<BR> 61 itsDescription = description;<BR> 62 loadProperties();<BR> 63 }<BR> 64<BR> 65 /**<BR> 66 * Protected constructor that can be used by derived classes.<BR> <P>67 */<BR> 68 protected PropertyFile() {<BR> 69 itsFile = null;<BR> 70 itsDescription = null;<BR> 71 // The actual work of loading properties will be<BR> 72 // done by derived class<BR> 73 }<BR> 74<BR> 75<BR> 76 // loads Properties from the Properties File<BR> 77 protected void loadProperties()<BR> 78 throws FileNotFoundException, IOException {<BR> 79<BR> 80 // open an input stream to the file specified<BR> 81 FileInputStream in = new FileInputStream(itsFile);<BR> 82<BR> 83 // load the properties<BR> 84 load(in);<BR> 85 }<BR> 86<BR> 87 /**<BR> 88 * Saves the Properties to the corresponding Properties File<BR> 89 * @exception FileNotFoundException if the Properties file could not be<BR> 90 * located<BR> 91 * @exception IOException if an error occurs while accessing the<BR> 92 * properties file<BR> 93 */<BR> 94 public void saveProperties() 95 throws FileNotFoundException, IOException {<BR> 96<BR> 97 // open an input stream to the file specified<BR> 98 FileOutputStream out = new FileOutputStream(itsFile);<BR> 99<BR> 100 // load the properties<BR> 101 save(out, itsDescription);<BR> 102 }<BR> 103<BR> 104 /**<BR> 105 * Refreshes the Properties object by re-reading the Properties File. Any<BR> 106 * changes made to the Properties object will be lost.<BR> <P>107 * @exception FileNetFoundException if the Properties file could not be<BR> 108 * locatetd<BR> 109 * @exception IOException if an error occurs while accessing the<BR> 110 * properties file<BR> 111 */<BR> 112 public void refresProperties()<BR> 113 throws FileNotFoundException, IOException {<BR> 114 loadProperties();<BR> 115 }<BR> 116<BR> 117<BR> 118 }<BR> 119<BR> 120<BR> 121<BR> 122 1 /* $Header: /com/mei@ca/hsl/zonesjagents/bootstrap/AgentClassInfoGathere r.java 5 11/11/96 5 13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * AgentClassInfoGatherer class peeks into an agents .class file to<BR> 11 * retrieve information needed for agent launching.<BR> <P>12 *<BR> 13 * $Log. /com/mertca/hsl/zonesjagents/bootstrap/AgentClassInfoGathere r.java $<BR> 14 *<BR> 15 * 5 11/11/96 5:13p Billp<BR> 16 * Made correction to company name.<BR> <P>17 *<BR> 18 * 4 9/30/96 6:35p Walsh<BR> 19 * fix up javadoc comments<BR> 20 *<BR> 21 * 3 9/27/96 6:10p Dicelie<BR> 22 * Minor change to loop which verified that the class to be launched was<BR> 23 * subclasses from Agent.<BR> <P>24 *<BR> 25 * 2 9/10/96 11 46a Walsh<BR> 26 * remove bogus imports that javac considers illegal<BR> 27 *<BR> 28 * 1 8/29/96 5.20p Walsh<BR> 29 * initial version<BR> 30 *<BR> 31 */<BR> 32 package com.meitca.hsl zonesjagents.bootstrap;<BR> 33<BR> 34 import java.io *;<BR> 35 import com.meitca.hsl zonesjagents conduit AgentSkeleton;<BR> 36<BR> 37 /**<BR> 38 * This object peeks into the .class file of an agent to retrieve<BR> 39 * some information needed for launching the agent.<BR> <P>40 * AgentClassInfoGatherer verifies that the .class file indicated<BR> 41 * does contain a class derived from Agent and then it verifies the<BR> 42 * existance of the agent's invocation skeleton and finally loads<BR> 43 * the skeleton class into memory and retreives a list of the<BR> 44 * agents methods from the skeleton.<BR> <P>45 * @see Agent<BR> 46 * @see BootStrap<BR> 47 * @see AgentLaunchWizard 48 * @author Thomas Walsh<BR> 49 */<BR> 50 public class AgentClassInfoGatherer {<BR> 51 /** The names of the agents methods */<BR> 52 String[] itsAgentsMethods;<BR> 53<BR> 54<BR> 55 **/<BR> 56 * Constructs a AgentClassInfoGatherer object Loads the agent<BR> 57 * and its skeleton. Retrieves a list of the agent's methods<BR> 58 * @param agentDir The directory containing the agent's<BR> 59 * class file<BR> 60 * @param agentFilename The name of the agent's .class file<BR> 61 * @exception FileNotFoundException Thrown if the class specified<BR> 62 * could not be opened<BR> 63 * @exception IOException If an IO error occurs while teying to<BR> 64 * access the agent's class file<BR> 65 * @exception ClassFormatError If the agent's class file does<BR> 66 * not contain a valid class.<BR> <P>67 * @exception NotAgentException If the agent's class file does<BR> 68 * not contain an agent<BR> 69 * @exception ClassNotFoundException If an error occured while<BR> 70 * trying to access the agents .class file<BR> 71 * @exception NoAgentSkeletonException If the agent's invocation<BR> 72 * skeleton could not be found.<BR> <P>73 */<BR> 74 public AgentClassInfoGatherer(String agentDir, String agentFilename)<BR> 75 throws FileNotFoundException, IOException, ClassFormatError,<BR> 76 NotAgentException, ClassNotFoundException,<BR> 77 NoAgentSkeletonException {<BR> 78 // let the loadAgentClassInfo method do all of the real work<BR> 79 @cadAgentClassInfo (agentDir, agentFilename);<BR> 80 }<BR> 81<BR> 82 /**<BR> 83 * Verifies the existence and correctness of the agent .class file<BR> 84 * and the agent's skeleton. Retrieves a list of the agent's methods<BR> 85 * Called @nternally by the constructor<BR> 86 * @param agentDir The directory containing the agent's<BR> 87 * class file.<BR> <P>88 * @param agentFilename The name of the agents's .class file.<BR> <P>89 * @exception FileNotFoundException Thrown if the agent's class<BR> 90 * did not exist.<BR> <P>91 * @exception IOException If an IO error occurs while teying to<BR> 92 * access the agent's .class file.<BR> <P>93 * @exception ClassFormatError If the agent's .class file does<BR> 94 * not contain a valid class.

95 * @exception NotAgentException If the agent's .class file does<BR> 96 * not contain an agent.<BR> <P>97 * @exception ClassNotFoundException If an error occured while<BR> 98 * trying to access the agents .class file.<BR> <P>99 * @exception NoAgentSkeletonException If the agent's invocation<BR> 100 * skeleton could not be found.<BR> <P>101 */<BR> 102 private void loadAgentClassInfo (String agentDir, String agentFilename)<BR> 103 throws FileNotFoundException, IOException, ClassFormatError,<BR> 104 NotAgentException, ClassNotFoundException,<BR> 105 NoAgentSkeletonException {<BR> 106<BR> 107// load the Agent class<BR> 108 BootStrapClassLoader classLoader = new BootStrapClassLoader (agentDir);<BR> 109 Class agent = classLoader.loadAgentClassFromFile (agentFilanem, true);<BR> 110<BR> 111 // verify that it is actually an Agent<BR> 112 Class superClass = agent getSuperclass ();<BR> 113<BR> 114 // STABILITY: Any way to get these hard coded strings out of here?<BR> 115 String superClassName;<BR> 116 do<BR> 117 {<BR> 118 superClassName = superClass getName ();<BR> 119 if (superClassName.equals ("java.lang.Object")) {<BR> 120 throw new NotAgentException (agentFilename + "does not contain an agent");<BR> 121 }<BR> 122<BR> 123 superClass = superClass getSuperclass ();<BR> 124<BR> 125 } while (!superClassName equals ("com.meitca.hsl zonesjagents shared.Agent"));<BR> 126<BR> 127 // ok, we have an agent ...<BR> <P>128 // lets try to load the skeleton<BR> 129 try {<BR> 130 // first lets strip the " class" from the filename<BR> 131 STABILITY: Any way to get these hard coded strings out of here?<BR> 132 String skelClassFileName = agentFilaname.substring (0,<BR> 133 agentFilename.length () - ".class" length ());<BR> 134<BR> 135 // append on the ~Skel<BR> 136 skelClassFileName = skelClassFileName + "~Skel.class";<BR> 137<BR> 138 // now try to load the skeleton class<BR> 139 Class skelClass = classLoader.loadAgentClassFromFile (skelClassFileName, true);<BR> 140<BR> 141 // finally retrieve the agents methods.

142 AgentSkeleton skel = (AgentSkeleton)skelClass.newInstance();<BR> 143 itsAgentsMethods = skel.getMethods ();<BR> 144 } catch (Exception e) {<BR> 145 throw new ClassNotFoundException ("Could not find skeleton for agent " + agentFilename);<BR> 146 }<BR> 147 }<BR> 148<BR> 149 /**<BR> 150 * Retrieves a list of the agents methods. The list is used<BR> 151 * by the Agent Launch GUI in order to present the user with<BR> 152 * a drop down list containing the eligible methods of the agent.<BR> <P>153 */<BR> 154 public String[] getAgentMethods() {<BR> 155 return itsAgentsMethods;<BR> 156 }<BR> 157 } 1 /* $Header: /com/meitca/hsj/zonesjagents/bootstrap/AgentLaunchInformatio n.java 4 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory.<BR> <P>4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBICHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * AgentLaunchInformation encapsulates the information needed to<BR> 11 * bootstrap the agent into the system.<BR> <P>12 *<BR> 13 * $Log /com/meitca/hsi/zonesjagents/bootstrap/AgentLaunchInformatio n.java $<BR> 14 *<BR> 15 * 4 11/11/96 5:13p Billp<BR> 16 * Made correction to company name.<BR> <P>17 *<BR> 18 * 3 9/30/96 6:35p Walsh<BR> 19 * fix up javadoc comments<BR> 20 *<BR> 21 * 2 9/11/96 4:46p Walsh<BR> 22 * add itsAgent member<BR> 23 *<BR> 24 * 1 8/29 96 5:21p Walsh<BR> 25 * initial version<BR> 26 *<BR> 27 */<BR> 28 package com.meitca.hsl zonesjagents bootstrap;<BR> 29<BR> 30 import com.meitca.hsl.zonesjagents.conduit Itinerary;<BR> 31 import com.meitca.hls.zonesjagents.shared.Agent;<BR> 32<BR> 33<BR> 34 /**<BR> 35 * The AgentLaunchInformation class encapsulates the information<BR> 36 * needed by the BootStrap class in order to launch and Agent.<BR> <P>37 * This class is used internally by the AgentLaunchWizard and<BR> 38 * the Agent command line launch tool<BR> 39 * @see Agent<BR> 40 * @see BootStrap<BR> 41 * @see AgentLaunchWizard<BR> 42 * @author Thomas Walsh<BR> 43 */<BR> 44 public class AgentLaunchInformation {<BR> 45 /**<BR> 46 * The directory (on the local host) containing the agent's<BR> 47 * .class file as well as the .class files of any related 48 * classes.<BR> <P>49 */<BR> 50 public String itsAgentDirectory;<BR> 51<BR> 52 /** The agent's .class file */<BR> 53 public String its AgentFile;<BR> 54<BR> 55 /**<BR> 56 * An array containing the filenames of any other classes<BR> 57 * that should be sent along with the agent. The ConduitServer<BR> 58 * has the ability to communicate back to the agents home machine<BR> 59 * to retrieve classes needed at runtime (if the RemoteLoader server<BR> 60 * is running) With this parameter a programmer can bypass this<BR> 61 * and send any needed classes up front.<BR> <P>62 */<BR> 63 public String[] itsRelatedClasses;<BR> 64<BR> 65 /** The agents Itinerary */<BR> 66 public Itinerary itsItinerary;<BR> 67<BR> 68 /**<BR> 69 * The agent itself This member on needs to be filled in if the<BR> 70 * ca@@er wants to call a method on the agent other than the default<BR> 71 * constructor. If this field is left blank, then the<BR> 72 * BootStrap.launchAgent method will constuct the Agent contained in<BR> 73 * the file itsAgentDirectory by calling its default constructor.<BR> <P>74 * This method gives the programmer the option of constructing an<BR> 75 * agent with a ctor other than the default<BR> 76 */<BR> 77 publ.c Agent itsAgent;<BR> 78<BR> 79 /**<BR> 80 * A listing of the agents methods This member variable need not<BR> 81 * be filled in in order to launch the agent, but is used internally<BR> 82 * by the AgentLaunchWizard<BR> 83 */<BR> 84 public String[] itsMethods;<BR> 85<BR> 86 /** Constructs an empty AgentLaunchInformation object */<BR> 87 public AgentLaunchInformation() {<BR> 88 itsAgentDirectory = new String("");<BR> 89 itsAgentFile = new String ("");<BR> 90 itsItinerary = new Itinerary();<BR> 91 itsAgent = null;<BR> 92 }<BR> 93 } 1 /* $Header: /ccm/meitca/hsl/zonesjagents/bootstrap/AgentLaunchWizard.jav a 10 11/11/96 5 13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * GUI tool for launcing agents into system<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/AgentLaunchWizard java $<BR> 13 *<BR> 14 * 10 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 9 10/10/96 5:57p Walsh<BR> 18 * Make use of properties in AgentConstants class<BR> 19 *<BR> 20 * 8 10/08/96 10:21a Walsh<BR> 21 * Fix name collision between bootstrap StringResources and<BR> 22 * util.StringResources<BR> 23 *<BR> 24 * 7 10 07/96 4:44p Walsh<BR> 25 * Save name a location of last agent launched. Restart Wizard pointing<BR> 26 * at same agent<BR> 27 *<BR> 28 * 6 10 07/96 3 55p Walsh<BR> 29 * Set up code to look in zones.home\images for GIP file<BR> 30 *<BR> 31 * 5 9/30/96 6:35p Walsh<BR> 32 * fix up javadoc comments<BR> 33 *<BR> 34 * 4 9/27/96 11:52a Walsh<BR> 35 * print exception to stderr on LaunchException<BR> 36 *<BR> 37 * 3 9/09/96 3:46p Walsh<BR> 38 * replace gjt.MessageDialog with com.meitca.hsl.util.InfoDialog. Create<BR> 39 * Security Manager in main<BR> 40 *<BR> 41 * 2 9/04/96 12:34p Walsh<BR> 42 * Pop up dialog on any problems launching the agent<BR> 43 *<BR> 44 * 1 8/29/96 5:21p Walsh<BR> 45 * initial version<BR> 46 *<BR> 47 */ 48 package com.meitca.hsl.zonesjagents.bootstrap;<BR> 49<BR> 50 import java.awt.*;<BR> 51 import java.io.*;<BR> 52 import java.util.*;<BR> 53<BR> 54 import com.meitca.hsl.util.*;<BR> 55 import com.meitca.hsl.zonesjagents.security.*;<BR> 56 import com.meitca.hsl.zonesjagents.shared.*;<BR> 57<BR> 58 /**<BR> 59 * The AgentLaunchWizard provides a wizard-like GUI for launching<BR> 60 * Java Agents into the system<BR> 61 * @see Agent<BR> 62 * @see BootStrap<BR> 63 * @see AgentLaunchInformation<BR> 64 * @see Wizard<BR> 65 * @author Thomas Walsh<BR> 66 */<BR> 67 public class AgentLaunchWizard extends Wizard {<BR> 68 /** The launch information */<BR> 69 AgentLaunchInformation itsAgentInfo;<BR> 70<BR> 71 /** The filename of the GIF */<BR> 72 static final String GIF~FILENAME = AgentConstants.IMAGE~DIR + "AgentLaunchWizard.gif";<BR> 73<BR> 74 /** Properties (Preference) object */<BR> 75 JASProperties itsProperties;<BR> 76<BR> 77 static final String LAST~AGENT~DIR="zones.agent.bootstrap.LastAgentDir";<BR&g t; 78 static final String LAST~AGENT~FILE="zones.agent.bootstrap.LastAgentFile";<BR > 79 // Static initializer<BR> 80<BR> 81 /**<BR> 82 * Constructs an AgentLaunchWizard object. Brings up the GUI and<BR> 83 * sets up the first panel.<BR> <P>84 */<BR> 85 public AgentLaunchWizard() {<BR> 86 super(com.meitca.hsl.zonesjagents.bootstrap.StringResources. WIZARD~TITLE,<BR> 87 GIF~FILENAME);<BR> 88 itsAgentInfo = new AgentLaunchInformation();<BR> 89<BR> 90 try {<BR> 91 itsProperties = new JASProperties (<BR> 92 com.meitca.hsl.zonesjagents.bootstrap.StringResources.WIZARD ~APPNAME,<BR> 93 JASProperties.USER,<BR> 94 com.meitca.hsl.zonesjagents.bootstrap.StringResources.PROP~D ESC, 95 true);<BR> 96 } catch (Exception e) {<BR> 97 itsProperties = null;<BR> 98 }<BR> 99<BR> 100 if (itsProperties != null) {<BR> 101 itsAgentInfo.itsAgentDirectory = itsProperties.getProperty(LAST~AGENT~DIR, " ");<BR> 102 itsAgentInfo.itsAgentFile = itsProperties.getProperty(LAST~AGENT~FILE, " ");<BR> 103 }<BR> 104<BR> 105 buildPanels();<BR> 106 firstPanel();<BR> 107<BR> 108 resize(570, 370);<BR> 109 show();<BR> 110 }<BR> 111<BR> 112 /**<BR> 113 * Builds the panels of the wizard. The AgentLaunchWizard<BR> 114 * contains three panels 1) a panel for specifying the agnet's .class<BR> 115 * file (names FindFilePanel), 2) a panel for specifying the related<BR> 116 * class files for sending with the agent (called RelatedFilesPanel) and<BR> 117 * 3) a panel for setting up the agents itinerary (called ItineraryPanel)<BR> 118 */<BR> 119 protected void buildPanels() {<BR> 120 FindFilePanel panel1 = new FindFilePanel(this, itsAgentInfo);<BR> 121 RelatedFilesPanel panel2 = new RelatedFilesPanel(this, itsAgentInfo);<BR> 122 ItineraryPanel panel3 = new ItineraryPanel(this, itsAgentInfo);<BR> 123 }<BR> 124<BR> 125 /**<BR> 126 * The finish method is called by the Wizard base class when the<BR> 127 * user has successfully filled all the necessary information<BR> 128 * into all the panels and has pressed the "Finish" button. We now<BR> 129 * have all of the information we need so we'll try to launch the agent<BR> 130 /*<BR> 131 protected void finish() {<BR> 132 try {<BR> 133 // launch the agent<BR> 134 BootStrap.launchAgent(itsAgentInfo);<BR> 135<BR> 136 if (itsProperties != null) {<BR> 137 try {<BR> 138 itsProperties.put(LAST~AGENT~DIR, itsAgentInfo.itsAgentDirectory)<BR> 139 itsProperties.put(LAST~AGENT~FILE, itsAgentInfo.itsAgentFile);<BR> 140 itsProperties.saveProperties();<BR> 141 } catch (Exception e) { 142 }<BR> 143 }<BR> 144<BR> 145 // shutdown.<BR> <P>146 cancel();<BR> 147 } catch (LaunchException e) {<BR> 148 InfoDialog info = new InfoDialog(this,<BR> 149 com.meitca.hsl.zonesjagents.bootstrap.StringResources.LAUNCH ~ERROR~TITLE,<BR> 150 com.meitca.hsl.zonesjagents.bootstrap.StringResources.LAUNCH ~ERROR);<BR> 151 info setBackground(Color.lightGray);<BR> 152 info show();<BR> 153<BR> 154 System.err.println(e.getMessage());<BR> 155 e.printStackTrace();<BR> 156 }<BR> 157 }<BR> 158<BR> 159 /**<BR> 160 * main routine supplied so that AgentLaunchWizard can be initiated<BR> 161 * from the command line<BR> 162 */<BR> 163 public static void main(String args[]) {<BR> 164 // Create and install the security manager<BR> 165 System.setSecurityManager(new InsecurityManager());<BR> 166<BR> 167 AgentLaunchWizard gui = new AgentLaunchWizard();<BR> 168 }<BR> 169<BR> 170 } 1 /* $Header. /com/meitca/hsl/zonesjagents/bootstrap/AgentLaunchWizardPane l.java 4 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * A subclass of WizardPanel for use in the AgentLaunchWizard<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/AgentLaunchWizardPane l java $<BR> 13 *<BR> 14 * 4 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 3 9/30/96 6:35p Walsh<BR> 18 * fix up javadoc comments<BR> 19 *<BR> 20 * 2 9/10/96 11:46a Walsh<BR> 21 * remove bogus imports that javac considers illegal<BR> 22 *<BR> 23 * 1 8/29/96 5:21p Walsh<BR> 24 * initial version<BR> 25 *<BR> 26 */<BR> 27 package com.meitca.hsl.zonesjagents.bootstrap;<BR> 28<BR> 29 import java.awt.*;<BR> 30<BR> 31 import com.meitca.hsl.util.Wizard;<BR> 32 import com.meitca.hsl.util.WizardPanel;<BR> 33<BR> 34<BR> 35 /**<BR> 36 * AgentLaunchWizardPanel is a base class for the panels of the<BR> 37 * AgentLaunchWizard. All of the panels in the launch wizard need<BR> 38 * shered access to the AgentLaunchInformation object describing the<BR> 39 * parameters of the launch. This base class provides that<BR> 40 * access.<BR> <P>41 * @see Agent<BR> 42 * @see BootStrap<BR> 43 * @see AgentLaunchInformation<BR> 44 * @see AgentLaunchWizard<BR> 45 * @author Thomas Walsh<BR> 46 */<BR> 47 public class AgentLaunchWizardPanel extends WizardPanel { 48 /** The launch parameters of the Wizard*/<BR> 49 protected AgentLaunchInformation itsAgentInfo;<BR> 50<BR> 51 /**<BR> 52 * Constructs an AgentLaunchWizardPanel<BR> 53 * @param wizard The Wizard owing this panel (needed by super)<BR> 54 * @param info The (shared) reference to the agent launch infomarion<BR> 55 */<BR> 56 public AgentLaunchWizardPanel(Wizard wizard, AgentLaunchInformation info) {<BR> 57 super(wizard);<BR> 58 itsAgentInfo =info;<BR> 59 }<BR> 60 }<BR> 61 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/BootStrap.java 11 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Misubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MISUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Module for boot strapping agents into the system<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/BootStrap.java $<BR> 13 *<BR> 14 * 11 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 10 10/01/96 10:39a Walsh<BR> 18 * fix @exception javadoc tag<BR> 19 *<BR> 20 * 9 9/30/96 7:33p Walsh<BR> 21 * and more javadoc<BR> 22 *<BR> 23 * 8 9/28/96 6:56p Walsh<BR> 24 * Add new version of launchAgent<BR> 25 *<BR> 26 * 7 9/11/96 4:59p Walsh<BR> 27 * allow launchInfo.itsRelatedClasses to be null<BR> 28 *<BR> 29 * 6 9/11/96 4:46p Walsh<BR> 30 * if caller specified LaunchInfo itsAgent, use that rather than<BR> 31 * constructing a new one.<BR> <P>32 *<BR> 33 * 5 9/10/96 11:46a Walsh<BR> 34 * remove bogus imports that javac considers illegal<BR> 35 *<BR> 36 * 4 9/09/96 3:46p Walsh<BR> 37 * Move creation of SecurityManager to main to prevent error on multiple<BR> 38 * calls to Launch<BR> 39 *<BR> 40 * 3 9/05/96 6:38p Walsh<BR> 41 * Add a main method to handle command line agent luaunching<BR> 42 *<BR> 43 * 2 9/04/96 12:35p Walsh<BR> 44 * Add some exception handling. Let ConduitServer handle details of<BR> 45 * launching agent. Let RemoteLoader build up the home codebase URL<BR> 46 *<BR> 47 *1 8/29/96 5:21p Walsh 48 * initial version<BR> 49 *<BR> 50 */<BR> 51 * package com.meitca.hsl.zonesjagents.bootstrap;<BR> 52<BR> 53 import java.rmi.Naming;<BR> 54 import java.rmi.server.StubSecurityManager;<BR> 55 import java.rmi.server.MarshalOutputStream;<BR> 56 import java.net.InetAddress<BR> 57 import java.util.*;<BR> 58 import java.io.*;<BR> 59<BR> 60 import com.meitca.hsl.zonesjagents.shared.+;<BR> 61 import com.meitca.hsl.zonesjagents.conduit.ConduitServer;<BR> 62 import com.meitca.hsl.zonesjagents.conduit.AgentPackage;<BR> 63 import com.meitca.hsl.zonesjagents.conduit.Itinerary;<BR> 64 import com.meitca.hsl.zonesjagents.conduit.MobileCodebase;<BR> ; 65 import com.meitca.hsl.zonesjagents.conduit.ConduitObjectOutputStrea m;<BR> 66 import com.meitca.hsl.zonesjagents.conduit.Destination;<BR> 67 import com.meitca.hsl.zonesjagents.conduit.ConduitServerImpl;<BR > 68 import com.meitca.hsl.zonesjagents.remoteloader.RemoteClassLoaderIm pl;<BR> 69 import com.meitca.hsl.zonesjagents.security.InsecurityManager;<B R> 70<BR> 71<BR> 72<BR> 73 /**<BR> 74 * BootStrap provides a mechanism for boot strapping (launching) agents<BR> 75 * into the system. The calling program must provide the launch parameters<BR> 76 * in the form the AgentLaunchInformation object. BootStrap takes this<BR> 77 * information and provides the necessary steps to launch the indicated agents;<BR> 78 * This includes building creating the MobileCodebase, loading any needed<BR> 79 * classes (including the agent) into the MobileCodebase, constructing the<BR> 80 * AgentPackage, contacting the initial ConduitServer and sending the agent.<BR> <P>81 * @see Agent<BR> 82 * @see AgentLaunchInformation<BR> 83 * @author Thomas Walsh<BR> 84 */<BR> 85 public class BootStrap {<BR> 86 /**<BR> 87 * Launches an agent.<BR> <P>88 * @param agent The agent to launch<BR> 89 * @param itinerary The agent's itinerary<BR> 90 * @param agentCodebaseURL An URL pointing to the codebase of the agent.<BR> <P>91 * This URL can take the following forms;<BR> 92 * <ul><BR> 93 * <li>A file URL like <b>file:C:\agents</b> - which indicates that the<BR> 94 * agent's code is located on the local machine in the directory 95 * <b>C:\agent</b><BR> 96 * <li>An HTTP URL like <b>http:/hostname/agents</b> - which indicates a<BR> 97 * location on a web server from which the agents code can be<BR> 98 * retrieved (This is very similar to the codebase modifier<BR> 99 * which can be added to an HTML <b><applet></b> tag)<BR> 100 * <li>An RMI URL like <b>rmi:/hostname/RemoteClassLoader</b> pointing<BR> 101 * to a RemoteClassLoader object which can retrieve the agents code.<br><BR> 102 * This RMI URL could also look like<BR> 103 * <b>rmi /hostname/RemoteClassLoader/C:\agents</b> which indicates that<BR> 104 * the RemoteClassLoader on hostname should be used to retrieve<BR> 105 * the classes and that the agents code is located in the <b>C \agents</b><BR> 106 * directory.<BR> <P>107 * </ul><BR> 107 * @param relatedClasses An array of fully qualified classnames of classes which this agent makes<BR> 109 * use of. These classes will be set up to travel with the agent.<BR> <P>110 * @exception LaunchException is the agent could notbe launched.<BR> <P>111 */<BR> 112 public static void launchAgent(Agent agent, Itinerary itinerary, String agentCodebaseURL,<BR> 113 String[] relatedClasses) throws LaunchExcept<BR> on {<BR> 114 try {<BR> 115 MobileCodebase agentCode = new MobileCodebase();<BR> 116 BootStrapClassLoader bootStrap = new BootStrapClassLoader(agentCodebaseURL,<BR> 117<BR> agentCode);<BR> 118 bootStrap.loadAgentClass(agent getClass() getName(), false);<BR> 119<BR> 120 if (relatedClasses != null) {<BR> 121 for (int i=0; i<relatedClasses.length; i++)<BR> 122 Class related = bootStrap.loadAgentClass(relatedClasses[i], false);<BR> 123 }<BR> 124<BR> 125 String absoluteCodebaseURL;<BR> 126 if (agentCodebaseURL!= null) {<BR> 127 if (!agentCodebaseURL.startWith("rmi.") && !agentCodebaseURL.startsWith("http:"))<BR> 128 if (agentCodebaseURL startsWith("file:")) {<BR> 129 absoluteCodebaseURL = RemoteClassLoaderImpl.buildCodebaseURL(<BR> 130 InetAddress.getLoca~<BR> ost() .getHostName(),<BR> 131 agentCodebaseURL sul<BR> tring (5, agentCodebaseURL, length()));<BR> 132 } else {<BR> 133 absoluteCodebaseURL = RemoteClassLoaderImpl.buildCodebaseURL(<BR> 134 InetAddress getLoca.<BR> ost().getHostName(),<BR> 135 agentCodebaseURL);<BR> 136 } 137 } else {<BR> 138 absoluteCodebaseURL = agentCodebaseURL;<BR> 139 }<BR> 140 } else {<BR> 141 absoluteCodebaseURL = RemoteClassLoaderImpl.buildRmiURL(<BR> 142 InetAddress.getLocalHost() g<BR> tHostName());<BR> 143 }<BR> 144<BR> 145 AgentPackage agentPackage = new AgentPackage(agent ,<BR> 146 agent<BR> Code,<BR> 147 iti<BR> rary,<BR> 148 absol<BR> uteCodebaseURL);<BR> 149<BR> 150<BR> 151 // pass the agent along<BR> 152 ConduitServerImpl.sendPackage(agentPackage);<BR> 153<BR> 154 } catch (Exception error) {<BR> 155 throw new LaunchException("LaunchException: " + error.getMessage());<BR> 156 }<BR> 157 }<BR> 158<BR> 159 /**<BR> 160 * Launches an agent based on the given launch parameters<BR> 161 * ¶m launchInfo The launch parameters<BR> 162 */<BR> 163 public static void launchAgent(AgentLaunchInformation launchInfo) throws LaunchException {<BR> 164<BR> 165 try {<BR> 166 MobileCodebase agentCode = new MobileCodebase();<BR> 167 BootStrapClassLoader bootStrap = new BootStrapClassLoader(launchInfo.itsAgentDirectory,<BR> 168<BR> agentCode);<BR> 169 Class agentClass = bootStrap.loadAgentClassFromFile(launchInfo.itsAgentFile, true);<BR> 170<BR> 171 if (launchInfo.itsRelatedClasses != null ) {<BR> 172 for (int i=0; i<launchInfo itsRelatedClasses.length; i++)<BR> 173 Class related = bootStrap.loadAgentClassFromFile(launchInfo itsRelatedClasse<BR> [i], true);<BR> 174 }<BR> 175<BR> 176 String codebaseURL = RemoteClassLoaderImpl.buildCodebaseURL(<BR> 177 InetAddress.getLocalHost().getHostNa e(),<BR> 178 launchInfo.itsAgentDirectory);<BR> 179<BR> 180<BR> 181 Agent agent;<BR> 182 if (launchInfo.itsInfo.itsAgent == null) {<BR> 183 agent = (Agent)agentClass.newInstance();<BR> 184 } else {<BR> 185 agent = launchInfo.itsAgent;<BR> 186 }<BR> 187 AgentPackage agentPackage = new AgentPackage(agent ,<BR> 188 agen<BR> Code,<BR> 189 lau.<BR> hInfo.itsItinerary,<BR> 190 code.<BR> aseURL);<BR> 191<BR> 192<BR> 193 // pass the agent along<BR> 194 ConduitServerImpl sendPackage(agentPackage);<BR> 195<BR> 196 } catch (Exception error) {<BR> 197 throw new LaunchException("LaunchException: " + error.getMessage());<BR> 198 }<BR> 199 }<BR> 200<BR> 201 /**<BR> 202 * This method gets invoked when a user tries to launch an Agent from<BR> 203 * the command line. The command line should look something like the<BR> 204 * following;<br><BR> 205 * <pre><BR> 206 *<BR> 207 * Usage: bootstrap [-d hostname,method] [-f relatedfile.class] [-h] agentfile.class<BR> 208 *<BR> 209 * </pre><br><BR> 210 * The user specifies the agent class file as the last parameter to<BR> 211 * the command. The destiantions for the Agent are specified with the<BR> 212 * <b>-d</b> option A destination is specified by the hostname follows by a<BR> 213 * comma (no space) followed by the name of the method to invoke.<BR> <P>214 * This could look something like the following; <b>-d host1,agentMethod1</b>.<BR> <P>215 * The user specifies related class files that should be sent with the<BR> 216 * agent using the <b>-f</b> option. Finally, the <b>-h</b> option brings up<BR> 217 * some command line help.<BR> <P>218 */<BR> 219 public static void main(String args[]) {<BR> 220 // Create and install the security manager 221 System.setSecurityManager(new InsecurityManager());<BR> 222<BR> 223 // We start by doing some rather brute force parsing of the<BR> 224 // command line. The command line args are used to build up<BR> 225 // an agentLaunchInformation data structure.<BR> <P>226 AgentLaunchInformation launchInfo = new AgentLaunchInformation();<BR> 227 Vector destinationStrings = new Vector();<BR> 228 Vector relatedFiles = new Vector();<BR> 229 String agentFile = null;<BR> 230<BR> 231 for (int i=0; i<args.length; i++ ) {<BR> 232 if (args[i].equals("-d")) {<BR> 233 String destinationString = args[++i];<BR> 234 destinationStrings.addElement(destinationString);<BR> 235 continue;<BR> 236 } else if (args[i].equals("-f")) {<BR> 237 String fileName = args[++i];<BR> 238 relatedFiles.addElement(fileName);<BR> 239 continue;<BR> 240 } else if (args[i].equals("-h")) {<BR> 241 System.out.println(StringResources.USAGE);<BR> 242 return;<BR> 243 } else {<BR> 244 if (args[i].charAt(0) == '-') {<BR> 245 System.out.println(StringResources.ILLEGAL~OPTN + args[i]);<BR> 246 System.out.println(StringResources.USAGE);<BR> 247 return;<BR> 248 } else {<BR> 249 agentFile = args[i];<BR> 250 }<BR> 251 }<BR> 252 }<BR> 253<BR> 254 // first lets verify that we have a valid agent file.<BR> <P>255 if (agentFile == null) {<BR> 256 System.out.println(StringResources.NO~AGENT);<BR> 257 System.out.println.(StringResources.USAGE);<BR> 258 return;<BR> 259 }<BR> 260<BR> 261 if (!agentFile.endsWith(".class")) {<BR> 262 System.out.println(StringResources.ILLEGAL~AGENT + agentFile);<BR> 263 System.out.println(StringResources.AGENT~HELP);<BR> 264 return;<BR> 265 }<BR> 266<BR> 267 launchInfo.itsAgentDirectory = new String(" "); 268 launchInfo.itsAgentFile = agentFile;<BR> 269<BR> 270 for (int i=agentFile.length()-1; i>=0; i--) {<BR> 271 if (agentFile.charAt(i) == File.separatorChar ) {<BR> 272 launchInfo.itsAgentDirectory = agentFile.substring(0, i+1);<BR> 273 launchInfo.itsAgentFile = agentFile.substring(i+1, agentFile.length());<BR> 274 break;<BR> 275 }<BR> 276 }<BR> 277<BR> 278 // Now let the AgentClassInfoGatherer verify the existence of the file,<BR> 279 // that the file contains a valid Java Agent and that the skeleton<BR> 280 // exists.<BR> <P>281 try {<BR> 282 AgentClassInfoGatherer agentInfoGatherer = new AgentClassInfoGatherer(<BR> 283 launchInfo.itsAgentDirectory, launchInfo.itsAgentFile);<BR> 284<BR> 285 launchInfo.itsMethods = agentInfoGatherer.getAgentMethods();<BR> 286 } catch (FileNotFoundException e1) {<BR> 287 System.out.println(StringResources.ILLEGAL~AGENT + agentFile);<BR> 288 System.out.println("\t" + StringResources.FILE~NOTFOUND);<BR> 289 return;<BR> 290 } catch (IOException e1) {<BR> 291 System.out.println(StringResources.ILLEGAL~AGENT + agentFile);<BR> 292 System.out.println("\t" + StringResources.IOERROR);<BR> 293 return;<BR> 294 } catch (ClassFormatError e1) {<BR> 295 System.out.println(StringResources ILLEGAL~AGENT + agentFile);<BR> 296 System.out.println("\t" + StringResources.BAD~CLASS~FORMAT);<BR> 297 return;<BR> 298 } catch (NotAgentException e1) {<BR> 299 System.out.println(StringResource.ILLEGAL~AGENT + agentFile);<BR> 300 System.out.println("\t" + StringResource.NOT~AGENT);<BR> 301 return;<BR> 302 } catch (ClassNotFoundException e1) {<BR> 303 System.out.println(StringResources.ILLEGAL~AGENT + agentFile);<BR> 304 System.out.println("\t" + StringResources.BAD~CLASS~FORMAT);<BR> 305 return;<BR> 306 } catch (NoAgentSkeletonException e1) {<BR> 307 System.out.println(StringResources.ILLEGAL~AGENT + agentFile);<BR> 308 System.out.println("\t" + StringResources.NO~SKELETON);<BR> 309 return;<BR> 310 }<BR> 311<BR> 312 // Lets take a look at the related files<BR> 313 launchInfo.itsRelatedClasses = new String[relatedFiles.size()];<BR> 314 for (int i=0; i< relatedFiles.size(); i++) { 315 String fileName = (String)relatedFiles.elementAt(i);<BR> 316 if (fileName.endsWith(".class")) {<BR> 317 launchInfo.itsRelatedClasses[i] = fileName;<BR> 318 } else {<BR> 319 System.out.println(StringResources.ILLEGAL~RELFILE + fileName);<BR> 320 System.out.println(StringResources.RELFILE~HELP);<BR> 321 return;<BR> 322 }<BR> 323 }<BR> 324<BR> 325 // Finally, lets take a look at those destinations<BR> 326 if (destinationString.size() == 0) {<BR> 327 System.out.println(StringResources.NO~DEST);<BR> 328 return;<BR> 329 }<BR> 330<BR> 331 for (int i=0; i<destinationStrings.size(); i++) {<BR> 332 String destinationString = (String) destinationString.elementAt(i);<BR> 333 StringTokenizer tokenizer = new StringTokenizer (destinationStrin, ",");<BR> 334<BR> 335 if (tokenizer.countTokens() != 2) {<BR> 336 System.out.println(StringResources.ILLEGAL~DEST + destinationString);<BR> 337 System.out.println(StringResources.USAGE);<BR> 338 }<BR> 339<BR> 340 String hostname = tokenizer.nextToken();<BR> 341 String methodname = tokenizer nextToken();<BR> 342<BR> 343 // find out if the methodname actually point to one of the methods<BR> 344 // in the Agent<BR> 345 int methodId = -1;<BR> 346 for(int j=0; j<launchInfo.itsMethods.length; j++) {<BR> 347 if (launchInfo.itsMethods[j].equals(methodname)) {<BR> 348 methodId = j;<BR> 349 }<BR> 350 }<BR> 351<BR> 352 if (methodId == -1) {<BR> 353 System.out.println(StringResources.ILLEGAL~METHOD + methodname);<BR> 354 System.out.println(StringResources.USAGE);<BR> 355 return;<BR> 356 } else {<BR> 357 launchInfo.itsItinerary.addDestination(new Destination(hostname, methodId));<BR> 358 }<BR> 359 }<BR> 360<BR> 361 // now that we have parsed the command line and built up the 362 // launchInfo, we will actually attempt to launch the agent.<BR> <P>363 try {<BR> 364 launchAgent(launchInfo);<BR> 365 } catch (LaunchException e) {<BR> 366 System.out.println(StringResources.LAUNCH~ERROR + ": " + e.getMessage());<BR> 367 e.printStackTrace();<BR> 368 }<BR> 369 }<BR> 370 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/BootStrapClassLoader. java 3 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * ClassLoader used in agent bootstrap process.<BR> <P>11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/BootStrapClassLoader. java $<BR> 13 *<BR> 14 * 3 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 2 9/28/96 6:56p Walsh<BR> 18 * Use AgentCodebase object to retrieve bytecodes.<BR> <P>19 *<BR> 20 * 1 8/29/96 5:21p Walsh<BR> 21 * intial version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca.hsl.zonesjagents.bootstrap;<BR> 25<BR> 26 import java.io.*;<BR> 27 import java.net.*;<BR> 28 import java.rmi.Naming;<BR> 29<BR> 30 import com.meitca.hsl.zonesjagents.conduit.*;<BR> 31 import com.meitca.hsl.zonesjagents.shared.*;<BR> 32 import com.meitca.hsl.zonesjagents.remoteloader *;<BR> 33<BR> 34<BR> 35 /**<BR> 36 * BootStrapClassLoader is used internally by the BootStrap<BR> 37 * class to load agent related classes<BR> 38 * @see Agent<BR> 39 * @see BootStrap<BR> 40 * @see MobileCodebase<BR> 41 * @author Thomas Walsh<BR> 42 */<BR> 43 public class BootStrapClassLoader extends ClassLoader {<BR> 44 /** An URL pointing to the cobease from which class files should be retrived */<BR> 45 String itsHomeCodebaseURL;<BR> 46<BR> 47 /** An object representing the home codebase of the agent */ 48. AgentCodebase itsHomeCodebase;<BR> 49<BR> 50 /** The mobile code base into which to load classes */<BR> 51 MobileCodebase itsMobileCodebase;<BR> 52<BR> 53 /**<BR> 54 * object which actually handles the dirty work or retrieving .class<BR> 55 * files for a given class.<BR> <P>56 */<BR> 57 ClassFileLoader itsClassFileLoader;<BR> 58<BR> 59<BR> 60/**<BR> 61 * Constructs a BootStrapClassLoader.<BR> <P>62 * @param url The directory from which this ClassLoader should<BR> 63 * retrieve .class files<BR> 64 */<BR> 65 public BootStrapClassLoader(String url) throws MalformedURLException (<BR> 66 itsHomeCodebaseURL = url;<BR> 67 itsHomeCodebase = new AgentCodebase(url);<BR> 68 itsMobileCodebase = null;<BR> 69 itsClassFileLoader = new ClassFileLoader(url) ();<BR> 70 }<BR> 71<BR> 72 /**<BR> 73 * Constructs a BootStrapClassLoader. When this consturctor is<BR> 74 * called, the ClassLoader realizes that their is an associated<BR> 75 * MobileCodebase object. As .class files are read from disk,<BR> 76 * they are also written into the MobileCodebase. Once they are<BR> 77 * loaded into the MobileCodebase, they are ready to travel.<BR> <P>78 * @param dir The directory from which this ClassLoader should<BR> 79 * retrieve .class files<BR> 80 * @param codebase The associated MobileCodbase object<BR> 81 */<BR> 82 public BootStrapClassLoader(String url, MobileCodebase codebase) throws MalformedURLException (<BR> 83 this(url);<BR> 84 itsMobileCodebase = codebase;<BR> 85 }<BR> 86<BR> 87 /**<BR> 88 * Load a class. The classes .class file must be in the directory<BR> 89 * that was specified in the constructor. If a MobileCodebase<BR> 90 * was specified in the constructor, the class will also be loaded<BR> 91 * into that codebase.<BR> <P>92 * @param name The class name<BR> 93 * @param resolve True if resolveClass should be called<BR> 94 */ 95 public Class loadAgentClass(String name, boolean resolve) throws ClassNotFoundException (<BR> 96<BR> 97 byte[] bytecodes = itsHomeCodebase.retrieveCode (name);<BR> 98<BR> 99 Class c = defineClass(bytecodes, 0, bytecodes.length);<BR> 100 if (resolve)<BR> 101 resolveClass(c);<BR> 102<BR> 103 if (itsMobileCodebase != null)<BR> 104 itsMobileCodebase.storeCode(c.getName(), bytecodes);<BR> 105<BR> 106 return c;<BR> 107 }<BR> 108<BR> 109 /**<BR> 110 * Load a class from the specified file. The file must be in the<BR> 111 * directory that was specified in the constructor. If a<BR> 112 * MobileCodebase was specified in the constructor, the class will<BR> 113 * also be loaded into that codebase.<BR> <P>114 * @param name The class filename<BR> 115 * @param resolve True if resolveClass should be called<BR> 116 */<BR> 117 //STABILITY: Integrate this method with loadAgentClass<BR> 118 public Class loadAgentClassFromFile(String fileName, boolean resolve)<BR> 119 throws FileNotFoundException, IOException, ClassNotFoundException , ClassFormatError (<BR> 120<BR> 121 File file = new File(itsHomeCodebaseURL, fileName);<BR> 122 long length = file.length();<BR> 123 FileInputStream stream = new FileInputStream(file);<BR> 124 byte data[] = new byte[(int)length];<BR> 125<BR> 126 stream.read(data);<BR> 127 Class c = defineClass(data, 0, (int)length);<BR> 128 if (resolve) {<BR> 129 resolveClass(c);<BR> 130 }<BR> 131<BR> 132 if (itsMobileCodebase != null)<BR> 133 itsMobileCodebase.storeCode(c.getName(), data);<BR> 134 return c;<BR> 135 }<BR> 136<BR> 137 /**<BR> 138 * The java.lang.ClassLoader version of loadClass.<BR> <P>139 * First looks for a standard system class, and then looks for an<BR> 140 * agent class in the directory that was specified in the constructor.<BR> <P>141 * If the class is an Agent related class, then its bytecodes are 142 * loaded into the MobilCodebase<BR> 143 * @param name The class name<BR> 144 * @param resolve True if resolveClass should be called<BR> 145 */<BR> 146 protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException {<BR> 147 try {<BR> 148 Class c = findSystemClass(name);<BR> 149 if (resolve) {<BR> 150 resolveClass (c);<BR> 151 }<BR> 152 return c;<BR> 153 } catch (ClassNotFoundException e1) {<BR> 154 try {<BR> 155 return loadAgentClass (name, resolve);<BR> 156 } catch (Exception e2) {<BR> 157 throw new ClassNotFoundException ("Could not load " + name);<BR> 158 }<BR> 159 }<BR> 160 }<BR> 161 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/FindFilePanel.java 5 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * The FindFilePanel of the AgentLaunchWizard<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/FindFilePanel java $<BR> 13 *<BR> 14 * 5 11/11/96 5:13p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 4 10/07/96 4:44p Walsh<BR> 18 * Save name & location of last agent launched Restart Wizard pointing<BR> 19 * at same agent<BR> 20 *<BR> 21 * 3 9/10/96 11:46a Walsh<BR> 22 * remove bogus imports that javac considers illegal<BR> 23 *<BR> 24 * 2 9/09/96 3:45p Walsh<BR> 25 * replace gjt MessageDialog w/ com.meitca.hsl.util InfoDialog<BR> 26 *<BR> 27 * 1 8/29/96 5 21p Walsh<BR> 28 * initial version<BR> 29 *<BR> 30 */<BR> 31 package com.meitca.hsl zonesjagents bootstrap;<BR> 32<BR> 33 import java.awt.*;<BR> 34 import java io.*;<BR> 35 import gjt.Util;<BR> 36<BR> 37 import com.meitca.hsl util Wizard;<BR> 38 import com.meitca.hsl.util.WizardPanel;<BR> 39 import com.meitca.hsl.util InfoDialog;<BR> 40<BR> 41 /**<BR> 42 * the first panel of the AgentLaunchWizard. This panel allows the user<BR> 43 * to specify the filename of the class file containing the agent<BR> 44 * @see Agent<BR> 45 * @see AgentLaunchWizardPanel<BR> 46 * @see AgentLaunchWizard<BR> 47 * @author Thomas Walsh 48 */<BR> 49 public class FindFilePanel extends AgentLaunchWizardPanel {<BR> 50 /** The edit field */<BR> 51 TextField itsFileBrowseField;<BR> 52<BR> 53 /** The "Browse. " button */<BR> 54 Button itsFileBrowseButton;<BR> 55<BR> 56 /**<BR> 57 * Construct the FindFilePanel and all of its components<BR> 58 * @param Wizard The wizard to which this panel belongs (needed by<BR> 59 * super)<BR> 60 * @param wiinfozard The AgentLaunchInformation descringing this<BR> 61 * agent launch (needed by super)<BR> 62 */<BR> 63 public FindFilePanel (Wizard wizard, AgentLaunchInformation info) {<BR> 64 super (wizard, info);<BR> 65 buildPanel();<BR> 66 }<BR> 67<BR> 68 /**<BR> 69 * Verify that the information entered into the panel is valid. Called<BR> 70 * after the "Next >" button is pressed<BR> 71 *<BR> 72 * The method validates the following things ..<BR> <P>73 * 1) A class file name is specified<BR> 74 * 2) The file name ends with " class"<BR> 75 * 3) The file exists<BR> 76 * 4) The file contains valid Java bytecodes<BR> 77 * 5) The file contains a class derived from Agent<BR> 78 * 6) An invocation skeleton is available<BR> 79 * @returns true if the panel contains valid info, false if not<BR> 80 */<BR> 81 public boolean validatePanel() {<BR> 82 // we want to break the full filename up into the directory portion<BR> 83 // and the filename portion. Find the last occurrence of the<BR> 84 // directory seperator character<BR> 85 String fullName = itsFileBrowseField getText();<BR> 86<BR> 87 // Verify that someone typed something into the edit control and that<BR> 88 // what they typed in ends with class<BR> 89 if (fullName.length() == 0) {<BR> 90 InfoDialog info = new InfoDialog (itsWizard,<BR> 91 StringResources.LAUNCH~ERROR~TITLE,<BR> 92 StringResources.NO~FILENAME);<BR> 93 info.setBackground(Color.lightGray);<BR> 94 info show(); 95 return false;<BR> 96 }<BR> 97<BR> 98 if (!fullName.endsWith(".class")) {<BR> 99 InfoDialog info = new InfoDialog(itsWizard,<BR> 100 StringResources.LAUNCH~ERROR~TITLE,<BR> 101 StringResources.ENDSWITH~CLASS);<BR> 102 info.setBackground (Color.lightGray);<BR> 103 info.show();<BR> 104 return false;<BR> 105 }<BR> 106<BR> 107 itsAgentInfo itsAgentDirectory = new String("");<BR> 108 itsAgentInfo itsAgentDirectory = fullName,<BR> 109<BR> 110 for (int i=fullName.length()-1; i>=0; i--) {<BR> 111 if (fullName charAt(i) == File.separatorChar ) {<BR> 112 itsAgentInfo.itsAgentDirectory = fullName.substring (0, i+1);<BR> 113 itsAgentInfo.itsAgentFile = fullName.substring(i+1, fullName length()};<BR> 114 break;<BR> 115 }<BR> 116 }<BR> 117<BR> 118 // Now let the AgentClassInfoGatherer verify the existance of the file,<BR> 119 // that the file contains a valid Java Agent and that the skeleton<BR> 120 // exists<BR> 121 try {<BR> 122 AgentClassInfoGatherer agentInfoGatherer = new AgentClassInfoGatherer (<BR> 123 itsAgentInfo itsAgentDirectory, itsAgentInfo itsAgentFile);<BR> 124<BR> 125 itsAgentInfo itsMethods = agentInfoGatherer.getAgentMethods();<BR> 126 return true;<BR> 127 } catch (FileNotFoundException e1) {<BR> 128 InfoDialog info = new InfoDialog (itsWizard,<BR> 129 StringResources.LAUNCH~ERROR~TITLE,<BR> 130 StringResources.FILE~NOTFOUND);<BR> 131 info.setBackground (Color.lightGray);<BR> 132 info.show();<BR> 133 return false;<BR> 134 } catch (IOException e1) {<BR> 135 InfoDialog info = new InfoDialog (itsWizard,<BR> 136 StringResources.LAUNCH~ERROR~TITLE,<BR> 137 StringResources.IOERROR);<BR> 138 info.setBackground (Color.lightGray);<BR> 139 info.show();<BR> 140 return false;<BR> 141 } catch (ClassFormatError e1) { 142 InfoDialog info = new InfoDialog(itsWizard,<BR> 143 StringResources.LAUNCH~ERROR~TITLE,<BR> 144 StringResources.BAD~CLASS~FORMAT);<BR> 145 info.setBackground (Color.lightGray);<BR> 146 info show();<BR> 147 return false;<BR> 148 } catch (NotAgentException e1) {<BR> 149 InfoDialog info = new InfoDialog (itsWizard,<BR> 150 StringResources.LAUNCH~ERROR~TITLE,<BR> 151 StringResources NOT~AGENT);<BR> 152 info setBackground (Color lightGray);<BR> 153 info.show();<BR> 154 return false;<BR> 155 } catch (ClassNotFoundException e1) {<BR> 156 InfoDialog info = new InfoDialog (itsWizard,<BR> 157 StringResources LAUNCH~ERROR~TITLE,<BR> 158 StringResources:BAD~CLASS~FORMAT);<BR> 159 info setBackground (Color.lightGray);<BR> 160 info show();<BR> 161 return false;<BR> 162 } catch (NoAgentSkeletonException e1) {<BR> 163 InfoDialog info = new InfoDialog (itsWizard,<BR> 164 StringResources.LAUNCH~ERROR~TITLE,<BR> 165 StringResources:NO~SKELETON);<BR> 166 info.setBackground (Color.lightGray);<BR> 167 info.show();<BR> 168 return false;<BR> 169 }<BR> 170 }<BR> 171<BR> 172 /**<BR> 173 * Builds the GUI Components for this panel<BR> 174 */<BR> 175 private void buildPanel() {<BR> 176 setLayout (new GridBagLayout());<BR> 177<BR> 178 Label labell = new Label (StringResources FF~TEXT1, Label.LEFT);<BR> 179 constrain (this, labell,<BR> 180 0, 0, 1, 1,<BR> 181 GridBagConstraints HORIZONTAL, GridBagConstraints.NORTHWEST, 0 0, 0<BR> 182 0,0,0,0);<BR> 183<BR> 184 Label label2 = new Label (StringResources FF~TEXT2, Label.LEFT);<BR> 185 constrain(this, label2,<BR> 186 0, 1, 1, 1,<BR> 187 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0,<BR> 188 0,0,0,0); 189<BR> 190 Label label3 = new Label (StringResources.FF~TEXT3, Label.LEFT);<BR> 191 constrain (this, label3,<BR> 192 0, 2, 1, 1,<BR> 193 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 194 0,0,0,0);<BR> 195<BR> 196 Label label4 = new Label (StringResources.FF~TEXT4, Label.LEFT);<BR> 197 constrain(this, label4,<BR> 198 0, 3, 1, 1,<BR> 199 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 200 0,0,0,0);<BR> 201<BR> 202 Panel browsePanel = new Panel();<BR> 203 constrain(this, browsePanel,<BR> 204 0, 4, 1, 1,<BR> 205 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 1.0, 1.0,<BR> 206 0,0,0,0);<BR> 207<BR> 208 browsePanel.setLayout (new GridBagLayout());<BR> 209 Label findFileLabel = new Label (stringResources.FF~FIELD~LABEL, Label.LEFT);<BR> 210 constrain(browsePanel, findFileLabel,<BR> 211 1, 0, 1, 1,<BR> 212 GridBagConstraints.NONE, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 213 0,0,0,0);<BR> 214<BR> 215 itsFileBrowseField = new TextField(25);<BR> 216 constrain(browsePanel, itsFileBrowseField,<BR> 217 2, 0, 1, 1,<BR> 218 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 1.0, 1.0,<BR> 219 0, 0, 0, 0);<BR> 220<BR> 221 itsFileBrowseButton = new Button (StringResources.FF~BROWSE~BUTTON);<BR> 222 constrain(browsePanel, itsFileBrowseButton,<BR> 223 3, 0, 1, 1,<BR> 224 GridBagConstraints.NONE, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 225 0,0,0,0);<BR> 226<BR> 227 }<BR> 228<BR> 229 /** Derived from Component.action */<BR> 230 public boolean action (Event event, Object what) {<BR> 231 if (event.target == itsFileBrowseButton) {<BR> 232 doBrowse();<BR> 233 return true;<BR> 234 }<BR> 235 return false; 236 }<BR> 237<BR> 238 /**<BR> 239 * Called in response to selecting the Panel's "Browse. button. Brings up<BR> 240 * a Open File Dialog<BR> 241 */<BR> 242 private void doBrowse() {<BR> 243 FileDialog browse = new FileDialog(Util.getFrame(this), StringResources.BROWSE~DLG~TITLE);<BR> 244 browse setFile("* class");<BR> 245<BR> 246 if (itsAgentInfo.itsAgentDirectory != null) {<BR> 247 if (itsAgentInfo itsAgentDirectory.length() != 0) {<BR> 248 browse.setDirectory(itsAgentInfo.itsAgentDirectory);<BR&g t; 249 }<BR> 250 }<BR> 251<BR> 252 browse.show();<BR> 253<BR> 254 String fullFileName = new String("");<BR> 255<BR> 256 if (browse getDirectory() != null) {<BR> 257 if (browse.getDirectory() length() != 0) {<BR> 258 fullFileName = browse getDirectory();<BR> 259 }<BR> 260 }<BR> 261<BR> 262 if (browse getFile() != null) {<BR> 263 if (browse.getFile() length() != 0) {<BR> 264 fullFileName = fullFileName + browse.getFile();<BR> 265 }<BR> 266 }<BR> 267<BR> 268 if (fullFileName.length() != 0)<BR> 269 itsFileBrowseFiled setText(fullFileName);<BR> 270 }<BR> 271<BR> 272 /**<BR> 273 * Initializes the Panel for display<BR> 274 */<BR> 275 public void displayPanel() {<BR> 276 String fullFileName = "";<BR> 277<BR> 278 if (itsAgentInfo.itsAgentDirectory != null) {<BR> 279 if (itsAgentInfo.itsAgentDirectory.length() != 0) {<BR> 280 fullFileName = itsAgentInfo itsAgentDirectory;<BR> 281<BR> 282 if (!fullFileName.endsWith(File.separator)) { 283 fullFileName += File.separator;<BR> 284 }<BR> 285 }<BR> 286 }<BR> 287<BR> 288<BR> 289 if (itsAgentInfo itsAgentFile != null) {<BR> 290 if (itsAgentInfo itsAgentFile length() != 0) {<BR> 291 fullFileName += itsAgentInfo.itsAgentFile;<BR> 292 }<BR> 293 }<BR> 294<BR> 295 if (fullFileName.length() != C)<BR> 296 itsFileBrowseFiled.setText(fullFileName);<BR> 297 }<BR> 298<BR> 299<BR> 300 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/ItineraryGridDataMode l.java 3 11/11/96 5:13p<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory.<BR> <P>4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * A Data Model class for use in conjuction wih the Rogue Wave<BR> 11 * Grig class<BR> 12 *<BR> 13 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/ItineraryGridDataMode l.java $<BR> 14 *<BR> 15 * 3 11/11/96 5:13p Billp<BR> 16 * Made correction to company name<BR> 17 *<BR> 18 * 2 9/04/96 12:36p Walsh<BR> 19 * Propogate changes to Destination terminology<BR> 20 *<BR> 21 * 1 8/29/96 5:21p Walsh<BR> 22 * initial version<BR> 23 *<BR> 24 */<BR> 25 package com.meitca.hsl.zonesjagents.bootstrap;<BR> 26<BR> 27 import com.roguewave widgets *;<BR> 28 import com.reguewave.widgets grid *;<BR> 29 import java.util Vector;<BR> 30 import java util Enumeration<BR> 31<BR> 32 import com.meitca.hsl zonesjagents.conduit.Destination;<BR> 33 import com.meitca.hsl zonesjagents.conduit Itinerary;<BR> 34<BR> 35 /**<BR> 36 * Implements a the necessary com.rogue.widgets grid.* interfaces to<BR> 37 * support the display of a Grid object. This class is tied to the<BR> 38 * Grid control on the ItineraryPanel of the AgentLaunchWizard. The<BR> 39 * grid is used to specify the Itinerary of the Agent to launch<BR> 40 * @see Itinerary<BR> 41 * @see ItineraryPanel<BR> 42 * @see AgentLaunchWizard<BR> 43 * @author Thomas Walsh<BR> 44 */<BR> 45 public class ItineraryGridDataModel extends SelectionGridModel (<BR> 46 /** The rows displayed in the grid */<BR> 47 Vector itsRows; 48<BR> 49 /** The ItineraryPanel this object is tied to. */<BR> 50 ItineraryPanel itsPanel;<BR> 51<BR> 52 /**<BR> 53 * Construct a ItineraryGridDataModel<BR> 54 * @param panel The ItineraryPanel this object is tied to.<BR> <P>55 */<BR> 56 public ItineraryGridDataModel(ItineraryPanel panel) {<BR> 57 itsRows = new Vector();<BR> 58 itsPanel = panel;<BR> 59 }<BR> 60<BR> 61 /** derived from SelectionGridModel.fetchString */<BR> 62 public String fetchString(int row, int column) {<BR> 63 try {<BR> 64 // vectors are zero based .Grids are one based, so we need to<BR> 65 // substract one<BR> 66 Destination aRow = (Destination)itsRows.elementAt(row-1);<BR> 67 switch (column) {<BR> 68 case 1<BR> 69 return aRow.getDestinationHost();<BR> 70 default<BR> 71 return "";<BR> 72 }<BR> 73 } catch (ArrayIndexOutOfBoundsException e) {<BR> 74 return "";<BR> 75 }<BR> 76 }<BR> 77<BR> 78 /** derived from SelectionGridModel.fetchInteger */<BR> 79 public int fetchInteger (int row, int column) {<BR> 80 try {<BR> 81 // vectors are zero based. .Gids are one based, so we need to<BR> 82 // substract one<BR> 83 Destination aRow = (Destination)itsRows elementAt(row-1);<BR> 84 switch (column) {<BR> 85 case 2:<BR> 86 return aRow.getMethodID() + 1;<BR> 87 default :<BR> 88 return 0;<BR> 89 }<BR> 90 } catch (ArrayIndexOutOfBoundsException e) {<BR> 91 return 0;<BR> 92 }<BR> 93 }<BR> 94 95 /* derived from SelectionGridModel.update */<BR> 96 public boolean update (int row, int column, String value) {<BR> 97 Destination aRow;<BR> 98<BR> 99 try {<BR> 100 // vectors are zero based Grids are one based, so we need to<BR> 101 // subtract one<BR> 102 aRow = (Destination)itsRows.elementAt(row-1);<BR> 103 } catch (ArrayIndexOutOfBoundsException e) {<BR> 104 aRow = new Destination();<BR> 105 itsRows insertElementAt(aRow, row-1);<BR> 106<BR> 107 // a new destination has been added to the Itinerary. Lets add<BR> 108 // a new blank row to the Grid so that the user has space to type any<BR> 109 // more destinations<BR> 110 itsPanel.addRow();<BR> 111 }<BR> 112<BR> 113 switch (column) {<BR> 114 case 1<BR> 115 aRow.setDestinationHost(value);<BR> 116 break;<BR> 117 default;<BR> 118 break;<BR> 119 }<BR> 120 return true,<BR> 121 }<BR> 122<BR> 123 /** derived from SelectionGridModel update */<BR> 124 public boolean update (int row, int column, int value) {<BR> 125 Destination aRow;<BR> 126<BR> 127 try {<BR> 128 // vectors are zero based Grids are one based, so we need to<BR> 129 // substract one<BR> 130 aRow = (Destination)itsRows.elementAt(row-1);<BR> 131 } catch (ArrayIndexOutOfBoundsException e) {<BR> 132 aRow = new Destination();<BR> 133 itsRows insertElementAt(aROw, row-1);<BR> 134<BR> 135 // a new destination has been added to the Itinerary. Lets add<BR> 136 // a new blank row to the Grid so that the user has space to type any<BR> 137 // more destinations<BR> 138 itsPanel.addRow();<BR> 139 }<BR> 140<BR> 141 switch (column) { 142 case 2:<BR> 143 aRow.setMethodID(value - 1);<BR> 144 break;<BR> 145 default;<BR> 146 break;<BR> 147 }<BR> 148 return true;<BR> 149 }<BR> 150<BR> 151 /*<BR> 152 * Retreives the Itinerary which has been specifed by the user.<BR> <P>153 */<BR> 154 public Itinerary getItinerary() {<BR> 155 Itinerary itinerary = new Itinerary();<BR> 156 Enumeration enum = itsRows elements()<BR> 157<BR> 158 while (enum.basMoreElements()) {<BR> 159 Destination destination = (Destination)enum nextElement();<BR> 160 itinerary.addDestination(destination);<BR> 161 }<BR> 162 return itinerary;<BR> 163 }<BR> 164 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/ItineraryPanel.java 3 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * The ItineraryPanel of the AgentLaunchWizard<BR> 11 *<BR> 12 * $Log. /com/meitca/hsl/zonesjagents/bootstrap/ItineraryPanel java $<BR> 13 *<BR> 14 * 3 11/11/96 5:13p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 2 9/10/96 11.46a Walsh<BR> 18 * remove bogus imports that javac considers illegal<BR> 19 *<BR> 20 * 1 8/29/96 5:21p Walsh<BR> 21 * initial version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca.hsl zonesjagents.bootstrap;<BR> 25 import java.awt.*;<BR> 26 import java.io.*;<BR> 27 import com.roguewave.widgets.grid *;<BR> 28<BR> 29 import com.meitca.hsl.util.Wizard;<BR> 30 import com.meitca.hsl.util.WizardPanel;<BR> 31<BR> 32<BR> 33 /**<BR> 34 * The third panel of the AgentLaunchWizard. This panel allows the user<BR> 35 * to specify the Itinerary of the agent<BR> 36 * @see Itinerary<BR> 37 * @see AgentLaunchWizardPanel<BR> 38 * @see AgentLaunchWizard<BR> 39 * @author Thomas Walsh<BR> 40 */<BR> 41 public class ItineraryPanel extends AgentLaunchWizardPanel {<BR> 42 /** The grid control on the panel */<BR> 43 Grid itsGrid<BR> 44<BR> 45 /** The data model object used in conjunction with itsGrid */<BR> 46 ItineraryGridDataModel itsDataModel;<BR> 47 48 /**<BR> 49 * Construct the ItineraryPanel and all of its components.<BR> <P>50 * @param wizard The wizard to which this panel belongs (needed by<BR> 51 * super)<BR> 52 * @param wiinfozard The AgentLaunchInformation descringing this<BR> 53 * agent launch (needed by super)<BR> 54 */<BR> 55 public ItineraryPanel(Wizard wizard, AgentLaunchInformation info) {<BR> 56 super(wizard, info);<BR> 57 buildPanel();<BR> 58 }<BR> 59<BR> 60 /**<BR> 61 * The Wizard calls this method right before it is going to display<BR> 62 * the panel In this case, the Panel needs to recreate the Grid<BR> 63 * so that the ChoiseColumn of the grid contains the names of the<BR> 64 * available methods of the currently selected Agent<BR> 65 */<BR> 66 public void displayPanel() {<BR> 67 remove(itsGrid);<BR> 68<BR> 69 // Crate a new grid model<BR> 70 itsDataModel = new ItineraryGridDataModel (this);<BR> 71 // Crate a new Grid in spreadsheed mode<BR> 72 itsGrid = new Grid(Grid TABLE~MODE,itsDataModel,itsDataModel,itsDataModel,itsDataMod el);<BR> 73 itsGrid getCellPanel() setVertLineColor(Color gray);<BR> 74 itsGrid.getCellPanel().setHortzLineColor(Color gray);<BR> 75 itsGrid editable = true;<BR> 76<BR> 77 // Set the grid column heating panel's attributes //<BR> 78 itsGrid.setColumnHeadingPanel(new ColumnHeadingPanel());<BR> 79 itsGrid.getColumnHeadingPanel() setBackground(Color.lightGray);<BR> 80 itsGrid.getColumnHeadingPanel() .setForeground(Color.black);<BR> 81 itsGrid.getColumnHeadingPanel() .setThreeDStyle(Grid.THREED~RAISED);<BR> 82 itsGrid.getColumnHeadingPanel() .setHorzLines(true);<BR> 83 itsGrid.getColumnHeadingPanel() .setTextLines(1);<BR> 84<BR> 85 // Add a text field column to the grid //<BR> 86 TextFieldColumnAttribute col1;<BR> 87 col1 = new TextFieldColumnAttribute();<BR> 88 col1.setTitle(StringResources.DEST~COL~TITLE);<BR> 89 col1.setWidth(150);<BR> 90 ((TableColumnCollection) itsGrid getColumnCollection()).add(col1);<BR> 91<BR> 92 ChoiceColumnAttribute choiseColumn = new ChoiceColumnAttribute();<BR> 93 choiseColumn.setTitle(StringResources.ACTION~COL~TITLE);< BR> 94 choiseColumn setWidth(150); 95 ((TableColumnCollection) itsGrid.getColumnCollection()).add(choiceColumn);<BR> 96<BR> 97<BR> 98 // Set the grid to have 1 row. //<BR> 99 (itsGrid.getRowCollection()) setRows(1);<BR> 100<BR> 101 constrain(this, itsGrid,<BR> 102 0, 6, 1, 1,<BR> 103 GridBagConstraints BOTH, GridBagConstraints.NORTHWEST, 1 0, 1 0,<BR> 104 0,0,0,0);<BR> 105<BR> 106<BR> 107 choiceColumn.addItem("");<BR> 108 for(int i=0; i<itsAgentInfo.itsMethods length; i++) {<BR> 109 choiceColumn addItem(itsAgentInfo itsMethods[i]);<BR> 110 }<BR> 111<BR> 112 invalidate();<BR> 113 validate();<BR> 114 }<BR> 115<BR> 116 /**<BR> 117 * Verify that the information entered into the panel is valid. Called<BR> 118 * after the "Next >" button is pressed.<BR> <P>119 * There is no actual verification necessary. This method simply<BR> 120 * retireves the Itinerary from the data model and stuffs it into<BR> 121 * the AgentLaunchInfo.<BR> <P>122 * @returns true if the panel contains valid info, false if not<BR> 123 */<BR> 124 public boolen validatePanel() {<BR> 125 itsAgentInfo itsItinerary = itsDataModel getItinerary();<BR> 126 return true;<BR> 127 }<BR> 128<BR> 129 /**<BR> 130 * Builds the GUI Components for this panel<BR> 131 */<BR> 132 private void buildPanel() {<BR> 133 setLayout(new GridBagLayout());<BR> 134<BR> 135 Label label1 = new Label (StringResources ITIN~TEXT1, Label.LEFT);<BR> 136 contrain(this, label1,<BR> 137 0, 0, 1, 1,<BR> 138 GridBagConstraints HORIZONTAL, GridBagConstraints.NORTHWEST,0.0, 0<BR> 139 0,0,0,0);<BR> 140<BR> 141 Label label2 = new Label (StringResources ITIN~TEXT2, Label.LEFT); 142 constrain(this, label2,<BR> 143 0, 1, 1, 1,<BR> 144 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 145 0,0,0,0);<BR> 146<BR> 147<BR> 148 Label label3 = new Label (StringResources.ITIN~TEXT3, Label.LEFT);<BR> 149 constrain(this, label3,<BR> 150 0, 2, 1, 1,<BR> 151 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 152 0,0,0,0);<BR> 153<BR> 154<BR> 155 Label label4 = new Label (StringResources.ITIN~TEXT4, Label.LEFT);<BR> 156 constrain(this, label4,<BR> 157 0, 3, 1, 1,<BR> 158 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 159 0,0,0,0);<BR> 160<BR> 161 Label label5 = new Label (StringResources.ITIN~TEXT5, Label.LEFT);<BR> 162 constrain(this, label5,<BR> 163 0, 4, 1, 1,<BR> 164 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 165 0,0,0,0);<BR> 166<BR> 167 Label label6 = new Label (StringResources.ITIN~TEXT6, Label.LEFT);<BR> 168 constrain(this, label6,<BR> 169 0, 5, 1, 1,<BR> 170 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 171 0,0,0,0);<BR> 172<BR> 173 // Crate a new grid model<BR> 174 itsDataModel= new ItineraryGridDataModel(this);<BR> 175 // Crate a new Grid in spreadsheed mode.<BR> <P>176 itsGrid = new Grid(Grid.TABLE~MODE,itsDataModel,itsDataModel,itsDataModel, itsDataModel);<BR> 177 itsGrid.getCellPanel().setVertLineColor(Color.gray);<BR&g t; 178 itsGrid.getCellPanel().setHorzLineColor(Color.gray);<BR&g t; 179 itsGrid.editable = true;<BR> 180<BR> 181 // Set the grid column heading panel's attributes //<BR> 182 itsGrid.setColumnHeadingPanel(new ColumnHeadingPanel());<BR> 183 itsGrid.getColumnHeadingPanel().setBackground(Color.lightGra y);<BR> 184 itsGrid.getColumnHeadingPanel().setForeground(Color.black);& lt;BR> 185 itsGrid.getColumnHeadingPanel().setThreeDStyle(Grid.THREED~R AISED);<BR> 186 itsGrid.getColumnHeadingPanel().setHorzLines(true);<BR> ; 187 itsGrid.getColumnHeadingPanel().setTextLines(1);<BR> 188 189 // Add a text field column to the grid //<BR> 190 TextFieldColumnAttribute col1;<BR> 191 col1 = new TextFieldColumnAttribute();<BR> 192 col1 setTitle(StringResources DEST~COL~TITLE);<BR> 193 col1.setWidth(150);<BR> 194 ((TableColumnCollection) itsGrid getColumnCollection()) add(col1);<BR> 195<BR> 196 ChoiceColumnAttribute choiceColumn = new ChoiceColumnAttribute();<BR> 197 choiceColumn.setTitle(StringResources.ACTION~COL~TITLE);< BR> 198 choiceColumn setWidth(150);<BR> 199 ((TableColumnCollection) itsGrid getColumnCollection()) .add(choiceColumn);<BR> 200<BR> 201<BR> 202 // Set the grid to have 1 row. //<BR> 203 (itsGrid getRowCollection()) setRows(1);<BR> 204<BR> 205 constrain(this, itsGrid,<BR> 206 0, 6, 1, 1,<BR> 207 GridBagConstraints BOTH, GridBagConstraints.NORTHWEST, 1 0, 1.0,<BR> 208 0,0,0,0);<BR> 209<BR> 210<BR> 211 }<BR> 212<BR> 213 /**<BR> 214 * called by the ItineraryGridDataModel to signify that a new row should be<BR> 215 * added to the Grid<BR> 216 */<BR> 217 protected void addRow() {<BR> 218 itsGrid.getRowCollection() setRows(itsGrid getRowCollection() .count()+1);<BR> 219 }<BR> 220 } 189 // Add a text field column to the grid //<BR> 190 TextFieldColumnAttribute col1;<BR> 191 col1 = new TextFieldColumnAttribute();<BR> 192 col1 setTitle(StringResources.DEST~COL~TITLE);<BR> 193 col1.setWidth(150);<BR> 194 ((TableColumnCollection) itsGrid getColumnCollection()) .add(col1);<BR> 195<BR> 196 ChoiceColumnAttribute choiceColumn = new ChoiceColumnAttribute();<BR> 197 choiceColumn.setTitle(StringResources.ACTION~COL~TITLE);< BR> 198 choiceColumn setWidth(150);<BR> 199 ((TableColumnCollection) itsGrid getColumnCollection()) .add(choiceColumn);<BR> 200<BR> 201<BR> 202 // Set the grid to have 1 row. //<BR> 203 (itsGrid getRowCollection()) .setRows(1);<BR> 204<BR> 205 constrain(this, itsGrid,<BR> 206 0, 6, 1, 1,<BR> 207 GridBagConstraints.BOTH, GridBagConstraints.NORTHWEST, 1 0, 1.0,<BR> 208 0,0,0,0);<BR> 209<BR> 210<BR> 211 }<BR> 212<BR> 213 /**<BR> 214 * called by the ItineraryGridDataModel to signify that a new row should be<BR> 215 * added to the Grid<BR> 216 */<BR> 217 protected void addRow() {<BR> 218 itsGrid.getRowCollection() setRows(itsGrid.getRowCollection().count()+1);<BR> 219 }<BR> 220 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/NoAgentSkeletonExcept ion.java 2 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Exception indicating that Agent invocation Skeleton is missing.<BR> <P>11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/NoAgentSkeletonExcept ion java $<BR> 13 *<BR> 14 * 2 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 1 8/29/96 5:21p Walsh<BR> 18 * initial version<BR> 19 *<BR> 20 */<BR> 21 package com.meitca.hsl zonesjagents bootstrap;<BR> 22<BR> 23 /**<BR> 24 * Exception indicates that the system could not locate the Agent<BR> 25 * method invocation skeleton. This skeleton is used by the conduit<BR> 26 * server to invoke the proper method on the Agent when it arrives<BR> 27 * at a destination. The skeleton is generated by the Agent Skeleton<BR> 28 * Generator.<BR> <P>29 * @see Agent<BR> 30 * @see AgentSkeleton<BR> 31 * @author Thomas Walsh<BR> 32 */<BR> 33 public class NoAgentSkeletonException extends Exception {<BR> 34 public NoAgentSkeletonException() {<BR> 35 super();<BR> 36 }<BR> 37<BR> 38 public NoAgentSkeletonException(String s) {<BR> 39 super(s);<BR> 40 }<BR> 41 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/NotAgentException.jav a 3 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Exception indicating that a .class File does not contain ah Agent.<BR> <P>11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/bootstrap/NotAgentException java $<BR> 13 *<BR> 14 * 3 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 2 9/30/96 6:35p Walsh<BR> 18 * fix up javadoc comments<BR> 19 *<BR> 20 * 1 8/29/96 5:21p Walsh<BR> 21 * initial version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca.hsl zonesjagents.bootstrap;<BR> 25<BR> 26 /**<BR> 27 * Exception indicates the class File specified did not contain<BR> 28 * a Java class derived from Agent.<BR> <P>29 * @see Agent<BR> 30 * @author Thomas Walsh<BR> 31 */<BR> 32 public class NotAgentException extends Exception {<BR> 33 public NotAgentException() {<BR> 34 super();<BR> 35 }<BR> 36<BR> 37 public NotAgentException(String s) {<BR> 38 super(s);<BR> 39 }<BR> 40 } 1 /* $Header /com/meitca/hsl/zonesjagents/bootstrap/RelatedFilesPanel.jav a 3 11/11/96 5 13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * The RelatedFilesPanel of the AgentLaunchWizard<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/bootstrap/RelatedFilesPanel.jav a $<BR> 13 *<BR> 14 * 3 11/11/96 5:13p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 2 9/10/96 11:46a Walsh<BR> 18 * remove bogous imports that javac considers illegal<BR> 19 *<BR> 20 * 1 8/29/96 5 21p Walsh<BR> 21 * initial version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca.hsl zonesjagents.bootstrap;<BR> 25<BR> 26 import java.awt *;<BR> 27 import java.io *;<BR> 28<BR> 29 import com.meitca hsl util Wizard;<BR> 30 import com.meitca.hsl.util.WizardPanel;<BR> 31<BR> 32<BR> 33 /**<BR> 34 * The second panel of the AgentLaunchWizard. This panel allows the user<BR> 35 * to specify the filenames of classes that should be sent with the agent.<BR> <P>36 * @see Agent<BR> 37 * @see AgentLaunchWizardPanel<BR> 38 * @see AgentLaunchWizard<BR> 39 * @author Thomas Walsh<BR> 40 */<BR> 41 public class RelatedFilesPanel extends,AgentLaunchWizardPanel {<BR> 42 /** The list control form which the user selects files */<BR> 43 List itsRelatedClassesList;<BR> 44<BR> 45<BR> 46 /**<BR> 47 * Construct the FindFilePanel and all of its components.

48 * @param wizard The wizard to which this panel belongs (needed by<BR> 49 * super)<BR> 50 * @param wiinfozard The AgentLaunchInformation descringing this<BR> 51 * agent launch (needed by super)<BR> 52 */<BR> 53 public RelatedFilesPanel(Wizard wizard, AgentLaunchInformation info) {<BR> 54 super(wizard, info);<BR> 55 buildPanel();<BR> 56 }<BR> 57<BR> 58 /**<BR> 59 * The Wizard calls this method right before it is going to display<BR> 60 * the panel In this case, the Panel needs to fill the List<BR> 61 * with the names of all the .class files in the same directory as<BR> 62 * the Agent<BR> 63 */<BR> 64 public void displayPanel() {<BR> 65 File agentDir = new File(itsAgentInfo.itsAgentDirectory);<BR> 66 String[] files = agentDir list(new ClassFileFilter());<BR> 67<BR> 68 itsRelatedClassesList clear();<BR> 69 for (int i=0; i<files.length; i++) {<BR> 70 if (!files[i].equals(itsAgentInfo.itsAgentFile))<BR> 71 itsRelatedClassesList.addItem(files[i]);<BR> 72 }<BR> 73<BR> 74 }<BR> 75<BR> 76 /**<BR> 77 * Verify that the information entered into the panel is valid Called<BR> 78 * after the "Next >" button is pressed<BR> 79 * There is no actual verification necessary. This method simply<BR> 80 * retireves the list of classes and stuffs them into the<BR> 81 * AgentLaunchInfo<BR> 82 * @returns true if the panel contains valid info, false if not<BR> 83 */<BR> 84 public boolean validatePanel() {<BR> 85 itsAgentInfo.itsRelatedClasses = itsRelatedClassesList.getSelectedItems();<BR> 86 return true;<BR> 87 }<BR> 88<BR> 89 /**<BR> 90 * Builds the GUI Components for this panel<BR> 91 */<BR> 92 private void buildPanel() {<BR> 93 setLayout(new GridBagLayout());<BR> 94 95 Label label1 = new Label(StringResources.RF~TEXT1, Label.LEFT);<BR> 96 constrain(this, label1,<BR> 97 0, 0, 1, 1,<BR> 98 GridBagConstraints HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 99 0,0,0,0);<BR> 100<BR> 101 Label label2 = new Label(StringResources.RF~TEXT2, Label.LEFT);<BR> 102 constrain(this, label2,<BR> 103 0, 1, 1, 1,<BR> 104 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 105 0,0,0,0);<BR> 106<BR> 107<BR> 108 Label label3 = new Label(StringResources.RF~TEXT3, Label.LEFT);<BR> 109 constrain(this, label3,<BR> 110 0, 2, 1, 1,<BR> 111 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 112 0,0,0,0);<BR> 113<BR> 114<BR> 115 Label label4 = new Label(StringResources.RF~TEXT4, Label.LEFT);<BR> 116 constrain(this, label4,<BR> 117 0, 3, 1, 1,<BR> 118 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 119 0,0,0,0);<BR> 120<BR> 121 Label label5 = new Label(StringResources.RF~TEXT5, Label.LEFT);<BR> 122 constrain(this, label5,<BR> 123 0, 4, 1, 1,<BR> 124 GridBagConstraints.HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 125 0,0,0,0);<BR> 126<BR> 127 Label label6 = new Label(StringResources.RF~TEXT6, Label.LEFT);<BR> 128 constrain(this, label6,<BR> 129 0, 5, 1, 1,<BR> 130 GridBagConstraints HORIZONTAL, GridBagConstraints.NORTHWEST, 0.0, 0.0,<BR> 131 0,0,0,0);<BR> 132<BR> 133 itsRelatedClassesList = new List(7, true);<BR> 134 constrain(this, itsRelatedClassesList,<BR> 135 0, 6, 1, GridBagConstraints.REMAINEDR,<BR> 136 GridBagConstraints.BOTH, GridBagConstraints.NORTHWEST, 1.0, 1.0,<BR> 137 0,0,0,0);<BR> 138 }<BR> 139 }<BR> 140<BR> 141 /** 142 * A FilenameFilter object than scans for file ending in .class<BR> 143 */<BR> 144 class ClassFileFilter implements FilenameFilter {<BR> 145 public boolean accept(File dir, String name) {<BR> 146 return (name endsWith(" class"));<BR> 147 }<BR> 148 } 1 /* $Header: /com/meitca/hsl/zonesjagents/bootstrap/StringResources java 7 11/11/96 5:13p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * The String Resources for the bootstap package<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/bootstrap/StringResources.java $<BR> 13 *<BR> 14 * 7 11/11/96 5:13p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 6 10/07/96 4 44p Walsh<BR> 18 * Save name & location of last agent launched Restart Wizard pointing<BR> 19 * at same agent<BR> 20 *<BR> 21 * 5 9/15/96 5:11p Walsh<BR> 22 * Fix spelling mistakes<BR> 23 *<BR> 24 * 4 9/09/96 5:59p Walsh<BR> 25 * Make constants final<BR> 26 *<BR> 27 * 3 9/05/96 6:37p Walsh<BR> 28 * Add some string constants associated with the command line launch<BR> 29 * utility<BR> 30 *<BR> 31 * 2 9/04/96 12:36p Walsh<BR> 32 * Add launch error message<BR> 33 *<BR> 34 * 1 8/29/96 5:21p Walsh<BR> 35 * initial version<BR> 36 *<BR> 37 */<BR> 38 package com.meitca hsl zonesjagents.bootstrap;<BR> 39<BR> 40 class StringResources {<BR> 41<BR> 42 // AgentLaunchWizard.java<BR> 43 public static String WIZARD~TITLE = "Agent Launch Wizard";<BR> 44 public static String WIZARD~APPNAME = "Agent Launch Wizard";<BR> 45 public static String PROP~DESC = "Properties file for Zones Agent Launch Wizard";<BR> 46<BR> 47 // FindFilePanel java 48 public static final String LAUNCH~ERROR~TITLE = "Launch Error";<BR> 49 public static final String NO~FILENAME = "You must specify the filename of the .class file containing the<BR> nt.";<BR> 50 public static final String ENDSWITH~CLASS = "You must specify a file ending with .class .";<BR> 51 public static final String FF~TEXT1 = "This wizard will assist you in launching Agents";<BR> 52 public static final String FF~TEXT2 = "Please select the .class file containing the ";<BR> 53 public static final String FF~TEXT3 = "agent you would like to launch.";<BR> 54 public static final String FF~TEXT4 = "<BR> 55 public static final String FF~FIELD~LABEL = "Class File: ";<BR> 56 public static final String FF~BROWSE~BUTTON = "Browse...";<BR> 57 public static final String BROWSE~DLG~TITLE = "Open Agent Class File";<BR> 58<BR> 59 //ItineraryPanel.java<BR> 60 public static final String DEST~COL~TITLE = "Destination";<BR> 61 public static final String ACTION~COL~TITLE = "Action";<BR> 62 public static final String ITIN~TEXT1 = "An agent's itinerary specifies where an agent travels to and";<BR> 63 public static final String ITIN~TEXT2 = "what operations the agent performs as it travels. Please ";<BR> 64 public static final String ITIN~TEXT3 = "specify the itinerary below. You should enter the host- ";<BR> 65 public static final String ITIN~TEXT4 = "names of the machines you would like your agent to travel ";<BR> 66 public static final String ITIN~TEXT5 = "to as well as the methods you would like called at each stop.";<BR> 67 public static final String ITIN~TEXT6 = "<BR> 68<BR> 69 // RelatedFilesPanel.java<BR> 70 public static final String RF~TEXT1 = "You may specify a list of classes which should be sent with";<BR> 71 public static final String RF~TEXT2 = "the Agent. These should be classes which the Agent is likely";<BR> 72 public static final String RF~TEXT3 = "to use while it is travelling. ";<BR> 73 public static final String RF~TEXT4 = " ";<BR> 74 public static final String RF~TEXT5 = "Please select any classes you would like sent with the agent.";<BR> 75 public static final String RF~TEXT6 = " ";<BR> 76<BR> 77 // BootStrap.java<BR> 78 public static final String USAGE = "Usage: bootstrap [-d hostname,method] [-f relatedfile.class]\n\t[-b] ag<BR> tfile.class";<BR> 79 public static final String ILLEGAL~OPTN = "bootstrap: illegal option -- ";<BR> 80 public static final String SYNTAX~ERROR = "bootstrap: syntax error -- ";<BR> 81 public static final String ILLEGAL~AGENT = "bootstrap: Illegal agent file -- ";<BR> 82 public static final String NO~AGENT = "bootstrap: No agent specified";<BR> 83 public static final String AGENT~HELP = "\tThe agent file must be valid Java class file\n\tand must end wi<BR> class";<BR> 84 public static final String ILLEGAL~RELFILE = "bootstrap: Illegal related filename -- ";<BR> 85 public static final String RELFILE~HELP = "\tThe related files specified by the -f option\n\tmust be valid<BR> va class files and must end\n\twith class";<BR> 86 public static final String ILLEGAL~DEST = "bootstrap: Illegal destination specification -- ";<BR> 87 public static final String ILLEGAL~METHOD = "bootstrap: Illegal method name -- ";<BR> 88 public static final String NO~DEST = "bootstrap: You must specify at least destination";<BR> 89<BR> 90 // shared strings 91 public static final String FILE~NOTFOUND = "Could not find the file specified.";<BR> 92 public static final String IOERROR = "An error occurred while trying to access the file specified.<BR> <P>93 public static final String BAD~CLASS~FORMAT = "The file specified did not contain a valid Java cla<BR> 94 public static final String NOT~AGENT = "The file specified did not contain a Java Agent ";<BR> 95 public static final String NO~SKELETON = "Could not locate the Agent's skeleton.";<BR> 96 public static final String LAUNCH~ERROR = "An error occurred while attempting to launch the Agent.";<BR> 97<BR> 98 } 1 /* $Header: /com/meitca/hsl/zonesjagent/conduit/AgentPackage.java 18 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent transportation package object<BR> 11 *<BR> 12 * $Log. /com/meitca/hsl/zonesjagents/conduit/AgentPackage.java $<BR> 13 *<BR> 14 * 18 11/11/96 5:15p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 17 10/28/96 6.31p Walsh<BR> 18 * Add more debugging info<BR> 19 * 16 10/24/96 5.15p Walsh<BR> 21 * add some debugging information related to memory usage<BR> 22 *<BR> 23 * 15 10/23/96 2.22p Walsh<BR> 24 * add more Debug.println's<BR> 25 *<BR> 26 * 14 10/11/96 9 26a Walsh<BR> 27 * fix compiler bug<BR> 28 *<BR> 29 * 13 10/10/96 6 02p Walsh<BR> 30 * Add persistence support<BR> 31 *<BR> 32 * 12 9/30/96 7:06p Walsh<BR> 33 * clean up javadoc comments<BR> 34 *<BR> 35 * 11 9/29/96 4.08p Walsh<BR> 36 * Allow Destination methods to be specified by name<BR> 37 * Give Agent access to AgentPackage information<BR> 38 *<BR> 39 * 10 9/11/96 12:24p Walsh<BR> 40 * remove uneeded import of CollaboratorAgent<BR> 41 *<BR> 42 * 9 9/09/96 4.59p Walsh<BR> 43 * Call Agent prepareForTransport, completedTransport methods<BR> 44 *<BR> 45 * 8 8/23/96 3 58p Walsh<BR> 46 * Add support for ad-hoc method invocation<BR> 47 * 48 * 7 8/22/96 5:45p Walsh<BR> 49 * Move the custom marshalling of the agent into the AgentPackage class<BR> 50 *<BR> 51 * 6 8/19/96 5:26p Walsh<BR> 52 * Add support for remote class loading<BR> 53 *<BR> 54 * 5 8/09/96 4.38p Walsh<BR> 55 * Setting up file headers<BR> 56 */<BR> 57<BR> 58 package com.meitca hsl zonesjagents conduit;<BR> 59<BR> 60 import java.ic.*;<BR> 61 import java.net.*;<BR> 62 import java.rmi.server MarshalException,<BR> 63<BR> 64<BR> 65 import com.meitca.hsl.zonesjagents.shared.Agent;<BR> 66 import com.meitca.hsl util *;<BR> 67<BR> 68<BR> 69 /**<BR> 70 * An AgentPackage contains an Agent, its MobileCodebase and<BR> 71 * its Itinerary The AgentPackage is passes between ConduitServers<BR> 72 * when the Agent travels<BR> 73 * @see ConduitServerImp1<BR> 74 * @author Thomas Walsh<BR> 75 */<BR> 76 public class AgentPackage {<BR> 77 Agent itsAgent;<BR> 78 MobileCodebase itsMobileCodebase;<BR> 79 Itinerary itsItinerary;<BR> 80 String itsHomeCodebaseURL;<BR> 81 int itsOID;<BR> 82<BR> 83<BR> 84<BR> 85 /**<BR> 86 * Constructs an AgentPackage<BR> 87 * @param agent The Agent<BR> 88 * @param code The Agent's mobile codebase<BR> 89 * @param itinerary The Agents itinerary<BR> 90 * @param homeCodebaseURL The URL of the Agent's codebase<BR> 91 */<BR> 92 public AgentPackage(Agent agent, MobileCodebase codebase,<BR> 93 Itinerary itinerary, String homeCodebaseURL) {<BR> 94 Debug.println("conduit.memory", 3, "AgentPackage " + this + " created"); 95 itsAgent = agent;<BR> 96 itsMobileCodebase = codebase;<BR> 97 itsItinerary = itinerary;<BR> 98 itsHomeCodebaseURL = homeCodebaseURL;<BR> 99 itsOID = 0;<BR> 100 }<BR> 101<BR> 102 protected void finalize() throws Throwable {<BR> 103 Debug.println("conduit memory", 3, "AgentPackage " + this + " finalized");<BR> 104 super finalize();<BR> 105 }<BR> 106<BR> 107 /** Retrieves the Agent from the package */<BR> 108 public Agent getAgent() {<BR> 109 return itsAgent;<BR> 110 }<BR> 111<BR> 112 /** Retrieves the Agent's Mobile Codebase from the package */<BR> 113 public MobileCodebase getMobileCodebase() {<BR> 114 return itsMobileCodebase;<BR> 115 }<BR> 116<BR> 117 /** Retrieves the Agent's itinerary from the package */<BR> 118 public Itinerary getItinerary() {<BR> 119 return itsItinerary;<BR> 120 }<BR> 121<BR> 122 /** Retrieves the Agent's codebase URL from the package */<BR> 123 public String getHomeCodebaseURL() {<BR> 124 return itsHomeCodebaseURL;<BR> 125 }<BR> 126<BR> 127 /**<BR> 128 * Prepares the Agent package for network transmission This method<BR> 129 * performs the conversion of the Agent to a network transmission<BR> 130 * format This method also calls the Agent's prepareForTransport<BR> 131 * method.<BR> <P>132 */<BR> 133 public void prepareForTransport() {<BR> 134 Debug.println("conduit", 2, "AgentPackage.prepareForTransport called");<BR> 135<BR> 136 // give the agent a chance to do any work in preparation<BR> 137 // for transport<BR> 138 itsAgent.prepareForTransport();<BR> 139 }<BR> 140<BR> 141 /** 142 * Restores the Agent package for network transmissionfrom its<BR> 143 * network transmission format. This method also calls the Agent's<BR> 144 * completedTransport method.<BR> <P>145 */<BR> 146 public void restoreFromTransportForm() {<BR> 147 Debug.println("conduit", 2, "AgentPackage.restoreFromTransportForm called");<BR> 148<BR> 149 // give the agent a chance to do any work in preperation<BR> 150 // for arrival at destination<BR> 151 itsAgent.completedTransport();<BR> 152 }<BR> 153<BR> 154 private void readObject(ObjectInputStream stream)<BR> 155 throws IOException, ClassNotFoundException {<BR> 156 Debug.println("conduit" 2, " AgentPackage.readObject called");<BR> 157<BR> 158itsMobileCodebase = (MobileCodebase)stream.readObject();<BR> 159 Debug.println("conduit", 4, " read MobileCodebase. " + itsMobileCodebase);<BR> 160<BR> 161itsItinerary = (Itinerary)stream.readObject();<BR> 162 Debug.println("conduit", 4, " read Itinerary: " + itsItinerary);<BR> 163<BR> 164 itsHomeCodebaseURL = (String)stream.readObject();<BR> 165 Debug.println("conduit", 4, " read Codebase URL: " + itsHomeCodebaseURL);<BR> 166<BR> 167 // do the special deserialization of the Agent using the<BR> 168 // ConduitObjectInputStream class<BR> 169 ConduitServerClassLoader classLoader = new ConduitServerClassLoader(itsMobileCodebase, itsHomeCodeb-<BR> eURL);<BR> 170<BR> 171 // unmarshal the agent, build the AgentPackage and then pass it along receiveAgent<BR> 172 byte[] serializedAgent = (byte[])stream.readObject();<BR> 173 ByteArrayInputStream byteInStream = new ByteArrayInputStream(serializedAgent);<BR> 174 ConduitObjectInputStream marshalInput = new ConduitObjectStream(byteInStream, classLoad-<BR> );<BR> 175<BR> 176 Debug.println("conduit", 4, " about to read Agent");<BR> 177 itsAgent = (Agent)marshalInput.readObject();<BR> 178 Debug.println("conduit", 4, " read Agent: " + itsAgent);<BR> 179<BR> 180 //Restore the Agents reference to its Package will be<BR> 181 // restored when the agent arrives at the Destination<BR> 182 itsAgent.setPackage(this);<BR> 183 }<BR> 184<BR> 185 private void writeObject(ObjectOutputStream stream)<BR> 186 throws IOException { 187 Debug.println("conduit", 2, "AgentPackage.writeObject called");<BR> 188<BR> 189 stream.writeObject(itsMobileCodebase);<BR> 190 stream.writeObject(itsItinerary);<BR> 191 stream.writeObject(itsHomeCodebaseURL);<BR> 192<BR> 193 // do the special deserialization of the Agent using the<BR> 194 // ConduitObjectOutputStream class<BR> 195<BR> 196 // null out the Agents pointer to the AgentPackage. We have to<BR> 197 // do this because Java object persistence does not support<BR> 198 // isomorphic persistence. Since the AgentPackage has a<BR> 199 // reference to the Agent and the Agent has a reference<BR> 200 // to the AgentPackage we have a circular reference.<BR> <P>201 // Without isomorphic persistence, this circular reference<BR> 202 // would cause the object serialization code to go into an<BR> 203 // infinite loop The reference to itsPackage will be<BR> 204 // restored when the agent arrives at the Destination<BR> 204 itsAgent setPackage(null);<BR> 206<BR> 207 ByteArrayOutputStream bytePutStream = new ByteArrayOutputStream();<BR> 208 ConduitObjectOutputStream marshalOutput = new ConduitObjectOutputStream(byteOutStream);<BR> 209<BR> 210 // use object serialization to stream the agent to a byte array<BR> 211 marshalOutput.writeObject(itsAgent);<BR> 212 byte[] serializedAgent = byteOutStream.toByteArray();<BR> 213<BR> 214 // finally write the serialized agent to the original output stream<BR> 215 stream.writeObject(serializedAgent);<BR> 216 }<BR> 217<BR> 218 /** Retrieves the AgentSkeleton object corresponding to the Agent. */<BR> 219 AgentSkeleton getAgentSkeleton() throws ClassNotFoundException, InstantiationException, IllegalAccessExce<BR> {<BR> 220 String agentClassname = itsAgent.getClass() getName();<BR> 221 String skelClassname = agentClassname + "~Skel";<BR> 222 ConduitServerClassLoader classLoader = (ConduitServerClassLoader)itsAgent.getClass().getClassLoader <BR> 223 if (classLoader != null)<BR> 224 return (AgentSkeleton) (classLoader.loadClass(skelClassname).newInstance());<BR& gt; 225 else<BR> 226 return (AgentSkeleton) (Class forName(skelClassname).newInstance());<BR> 227 ]<BR> 228<BR> 229 void setOID(int oid); {<BR> 230 itsOID = oid;<BR> 231 } 232<BR> 233 int getOID() {<BR> 234 return itsOID;<BR> 235 }<BR> 236 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/AgentSkeleton.java 3 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent method invocation skeleton interface<BR> 11 *<BR> 12 * $Log. /com/meitca/hsl/zonesjagents/conduit/AgentSkeleton.jawa $<BR> 13 *<BR> 14 * 3 11/11/96 5:15p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 2 8/29/96 5:15p Walsh<BR> 18 * Add getMethods method<BR> 19 *<BR> 20 * 1 8/23/96 3 50p Walsh<BR> 21 * Initial versions<BR> 22 */<BR> 23 package com.meitca hsl zonesjagents conduit;<BR> 24<BR> 25 import com.meitca.hsl zonesjagents shared Agent;<BR> 26<BR> 27 /**<BR> 28 * An interface representing an Agent ad-hoc method invocation skeleton<BR> 29 * The skeleton allows the ConduitServer to make a call to any method within<BR> 30 * the Agent At runtime, the ConduitServer looks at the Agent's Itinerary<BR> 31 * and determines what method should be called at the current location. The<BR> 32 * skeleton allows the Conduit Server to call the method<BR> 33 * @see Agent<BR> 34 * @see ConduitServer<BR> 35 * @author Thomas Walsh<BR> 36 */<BR> 37 public interface AgentSkeleton {<BR> 38<BR> 39 /**<BR> 40 * Invokes a method on an agent<BR> 41 * @param agent The agent whose method to invoke.<BR> <P>42 * @param i The method ID number of the method to invoke<BR> 43 */<BR> 44 public void invoke(Agent agent, int i) throws IllegalAccessException;<BR> 45<BR> 46 /**<BR> 47 * Retrieves a list of the agent methods which can be invoked by 48 * the skeleton<BR> 49 */<BR> 50 public String[] getMethods(),<BR> 51<BR> 52 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/AgentThread.java 4 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * provides the thread in which an Agent will executes<BR> 11 *<BR> 12 * $Log. /com/meitca/hsl/zonesjagents/conduit/AgentTheread java $<BR> 13 *<BR> 14 * 4 11/11/96 5:15p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 3 10/29/96 5.28p Walsh<BR> 18 * Use ErrorLog class to report errors<BR> 19 *<BR> 20 * 2 10/28/96 6.31p Walsh<BR> 21 * Add more debugging info<BR> 22 *<BR> 23 * 1 10/25/96 5 02p Walsh<BR> 24 * Make AgentThread public<BR> 25 *<BR> 26 */<BR> 27 package com meitca hsl zonesjagents conduit;<BR> 28<BR> 29 import java util *;<BR> 30<BR> 31 import com.meitca.hsl zonesjagents shared *;<BR> 32 import com.meitca hsl util *<BR> 33<BR> 34 /**<BR> 35 * A subclass of Thread AgentThread provides the thread in which an Agent will<BR> 36 * execute<BR> 37 * @see Agent<BR> 38 * @see ConduitServer<BR> 39 * @author Thomas Walsh<BR> 40 */<BR> 41 public class AgentThread extends Thread {<BR> 42 AgentPackage itsPackage;<BR> 43<BR> 44 /**<BR> 45 * Constructs an AgentThread<BR> 46 * @param agentPackage The package containing the agent, its code and<BR> 47 * its itinerary.

48 */<BR> 49 public AgentThreadPackage agentPackage) {<BR> 50 Debug.println("conduit.memory", 3, "AgentThread " + this + " created");<BR> 51 itsPackage = agentPackage;<BR> 52 this.start();<BR> 53 }<BR> 54<BR> 55 protected void finalize() throws Throwable {<BR> 56 Debug println("conduit memory", 3, "AgentThread " + this + " finalized");<BR> 57 super final.ze();<BR> 58 }<BR> 59<BR> 60 /**<BR> 61 * Retrieves a reference to the Agent which is executing within this<BR> 62 * AgentThread<BR> 63 */<BR> 64 public Agent getAgent() {<BR> 65 return itsPackage.getAgent();<BR> 66 }<BR> 67<BR> 68 /**<BR> 69 * Retrieves a reference to the AgentPackage contained within this<BR> 70 * AgentThread<BR> 71 */<BR> 72 public AgentPackage getAgentPackage() {<BR> 73 return itsPackage;<BR> 74 }<BR> 75<BR> 76 /**<BR> 77 * Begins the Agent's execution<BR> 78 */<BR> 79 public void run() {<BR> 80 try {<BR> 81 ConduitServerImpl.getPersistenceStore().addToStore(itsPackag e);<BR> 82 AgentSkeleton skel = itsPackage.getAgentSkeleton();<BR> 83 Destination current = itsPackage getItinerary().getCurrentLocation();<BR> 84<BR> 85 if (current.getMethodID() == Destination.UNKNOWN~METHOD~ID) {<BR> 86 current convertNameToId(skel);<BR> 87 }<BR> 88<BR> 89 skel invoke(itsPackage getAgent().<BR> <P>90 current.getMethodID());<BR> 91 itsPackage getItinerary().getCurrentLocation().setCompleted();<BR> ; 92 ConduitServerImpl.getPersistenceStore().updateStore(itsPacka ge);<BR> 93 } catch (Exception error) {<BR> 94 ErrorLog.println("conduit AgentThread", 95 ErrorLog.SEVERITY~ERROR,<BR> 96 "An error occurred while executing Agent.",<BR> 97 error);<BR> 98 }<BR> 99<BR> 100 ConduitServerImpl.decrementAgentCounters();<BR> 101<BR> 102 try {<BR> 103 // pass the agent along.<BR> <P>104 ConduitServerImpl sendPackage(itsPackage);<BR> 105 } catch (NoSuchElementException done) {<BR> 106 Debug.println("conduit", 1, "AgentThread.run.No more destinations for Agent " +<BR> 107 itsPackage.getAgent().get<BR> tID()):<BR> 108 } catch (Exception error) {<BR> 109 ErrorLog.println("conduit.AgentThread",<BR> 110 ErrorLog.SEVERITY~ERROR,<BR> 111 "An error occurred while transporting Agent:",<BR> 112 error);<BR> 113 }<BR> 114<BR> 115 // remove the agent from the persistence store<BR> 116 ConduitServerImpl.getPersitenceStore().removeFromStore(itsPa ckage);<BR> 117 }<BR> 118 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/ConduitObjectInputStrea m.java 9 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Specialized ObjectInputStream used for agent deserialization<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/ConduitObjectInputStrea m.java $<BR> 13 *<BR> 14 * 9 11/11/96 5:15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 8 11/01/96 5:32p Walsh<BR> 18 * Modify debugging levels of debug output<BR> 19 *<BR> 20 * 7 10/21/96 4:26p Walsh<BR> 21 * Add debug logging<BR> 22 *<BR> 23 * 6 9/30/96 7:06p Walsh<BR> 24 * clean up javadoc comments<BR> 25 *<BR> 26 * 5 9/11/96 6:40p Walsh<BR> 27 * fix complier error<BR> 28 *<BR> 29 * 4 9/11/96 6 33p Walsh<BR> 30 * derive from Marshal*Stream<BR> 31 *<BR> 32 * 3 8/22/96 2 19p Walsh<BR> 33 * Clean up code a little<BR> 34 *<BR> 35 * 2 8/13/96 5:09p Walsh<BR> 36 * Added comments & documentation. resolveClass now uses<BR> 37 * ConduitServerClassLoader<BR> 38 *<BR> 39 * 1 8/12/96 7:17p Walsh<BR> 40 * Initial versions<BR> 41 */<BR> 42 package com.meitca.hsl.zonesjagents.conduit;<BR> 43<BR> 44 import java.io.InputStream;<BR> 45 import java.io.IOException;<BR> 46 import java.io.StreamCorruptedException;<BR> 47 import java.lang.ClassNotFoundException; 1 /* $Header. /com/meitca/hsl/zonesjagents/conduit/ConduitObjectOutputStre am.java 7 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Specialized MershalInputStream used for agent deserialization<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/ConduitObjectOutputStre am.java $<BR> 13 *<BR> 14 * 7 11/11/96 5:15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 6 11/01/96 5:32p Walsh<BR> 18 * Modify debugging levels of debug output<BR> 19 *<BR> 20 * 5 10/21/96 4:26p Walsh<BR> 21 * Add debug logging<BR> 22 *<BR> 23 * 4 9/30/96 7:06p Walsh<BR> 24 * clean up javadoc comments<BR> 25 *<BR> 26 * 3 9/11/96 6:33p Walsh<BR> 27 * derive from Marshal*Stream<BR> 28 *<BR> 29 * 2 8/22/96 2:19p Walsh<BR> 30 * Clean up code a little<BR> 31 *<BR> 32 * 1 8/12/96 7:17p Walsh<BR> 33 * Initial versions<BR> 34 */<BR> 35 package com.meitca.hsl.zonesjagents.conduit;<BR> 36<BR> 37 import java.io.OutputStream;<BR> 38 import java.io.IOException;<BR> 39 import java.io.StreamCorruptedException;<BR> 40 import java.lang.ClassNotFoundException;<BR> 41 import java.rmi.server.MarshalOutputStream;<BR> 42<BR> 43 import com.meitca.hsl.util.*;<BR> 44<BR> 45 public class ConduitObjectOutputStream<BR> 46 extends MarshalOutputStream {<BR> 47 95 Debug.println("conduit classload", 3, "ConduitObjectInputStream.resolveClass called for " + classn<BR> }:<BR> 96<BR> 97 return itsClassLoader.loadClass(classname);<BR> 98 }<BR> 99 } 48 import java.rmi.server.MarshalInputStream;<BR> 49 import java.net.MalformedURLException;<BR> 50 import java.net.URL;<BR> 51 import java.rmi.server.StubClassLoader;<BR> 52<BR> 53 import com.meitca.hsl.util *;<BR> 54<BR> 55 /**<BR> 56 * A subclass of ObjectInputStream which is used to handle deserialization<BR> 57 * of Agent objects ConduitObjectInputStream overrides the<BR> 58 * ObjectInputStream.resolveClass method As the deserialization process<BR> 59 * encounters object contained within the agent, resolveClass is called for<BR> 60 * each unique class. resolveClass makes use of a ConduitServerClassLoader<BR> 61 * object to search the agents MobileCodebase for class bytecodes.<BR> <P>62 * @see Agent<BR> 63 * @see ConduitServerClassLoader<BR> 64 * @see ObjectInputStream<BR> 65 * @see MobileCodebase<BR> 66 * @author Thomas Walsh<BR> 67 */<BR> 68 class ConduitObjectInputStream<BR> 69 extends MarshalInputStream {<BR> 70<BR> 71 /** Class loader object used for deserializing an agent. /*<BR> 72 ConduitServerClassLoader itsClassLoader;<BR> 73<BR> 74 /**<BR> 75 * Constructs a ConduitObjectInputStream<BR> 76 * @param is The InputStream containing the Agent object<BR> 77 * @param classLoader A ConduitServerClassLoader capable of loading<BR> 78 * classes from the Agent's MobileCodebase<BR> 79 */<BR> 80 public ConduitObjectInputStream(InputStream is, ConduitServerClassLoader classLoader)<BR> 81 throws IOException, StreamCorruptedException {<BR> 82 super(is);<BR> 83<BR> 84 itsClassLoader = classLoader;<BR> 85 }<BR> 86<BR> 87 /**<BR> 88 * Resolves a fully qualified class name to a Class object. resolveClass uses a<BR> 89 * ConduitServerClassLoader to actually perform the class loading.<BR> <P>90 * @param classname The classes fully qualified class name<BR> 91 */<BR> 92 protected Class resolveClass(String classname)<BR> 93 throws IOEXception, ClassNotFoundException {<BR> 94 48 public ConduitObjectOutputStream(OutputStream is)<BR> 49 throws IOException {<BR> 50 super(is);<BR> 51 }<BR> 52<BR> 53<BR> 54 protected void annotateClass(Class cl) throws IOException {<BR> 55 Debug.println("conduit.classload", 3, "ConduitObjectOutputStream.annotateClass called for " + cl);<BR> 56 }<BR> 57 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/ConduitServer.java 9 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRITPTION<BR> 10 * Conduit Server distributed interface<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/ConduitServer java $<BR> 13 *<BR> 14 * 9 11/11/96 5:15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 8 9/30/96 7:06p Walsh<BR> 18 * clean up javadoc comments<BR> 19 *<BR> 20 * 7 8/27/96 3:51p Walsh<BR> 21 * remove getConduitName method from ConduitServer interface<BR> 22 *<BR> 23 * 6 8/22/96 5.45p Walsh<BR> 24 * Move the custom marshalling of the agent into the AgentPackage class<BR> 25 *<BR> 26 * 5 8/19/96 5 26p Walsh<BR> 27 * Add support for remote class loading<BR> 28 *<BR> 29 * 4 8/13/96 11 47a Walsh<BR> 30 * Add documentation a comments Change signature of receivePackage<BR> 31 * method.<BR> <P>32 *<BR> 33 * 3 8/12/96 7 15p Walsh<BR> 34 * ConduitServer now performs Marshalling<BR> 35 *<BR> 36 * 2 8/09/96 4.38p Walsh<BR> 37 * Setting up file headers<BR> 38 */<BR> 39<BR> 40 package com.meitca.hsl zonesjagents.conduit;<BR> 41<BR> 42 import java.rmi.Remote;<BR> 43 import java.rmi.RemoteException;<BR> 44<BR> 45 import com.meitca.hsl zonesjagents.conduit.AgentPackage;<BR> 46 import com.meitca hsl zonesjagents conduit. MobileCodebase;<BR> 47 48<BR> 49 /**<BR> 50 * ConduitServer is an RMI distributed interface It provides some RMI glue<BR> 51 * that allows conduit servers to communicate. ConduitServer is implemented<BR> 52 * by the ConduitServerImpl class Conduit servers provide for Agent travel<BR> 53 * and execution<BR> 54 * @see ConduitServerImpl<BR> 55 * @author Thomas Walsh<BR> 56 */<BR> 57 public interface ConduitServer extends Remote {<BR> 58<BR> 59 /**<BR> 60 * Receive an Agent from the previous conduit server in its Itinerary.<BR> <P>61 * @param aPackage The package containing the agents, its mobile<BR> 62 * codebase and it itinerary<BR> 63 * @exception RemoteException If a communication error occurs<BR> 64 */<BR> 65 public void receivePackage(AgentPackage aPackage)<BR> 66 throws RemoteException;<BR> 67 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/ConduitServerClassLoade r.java 12 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Conduit Server ClassLoader subclass<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/ConduitServerClassLoade r.java $<BR> 13 *<BR> 14 * 12 11/11/96 5:15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 11 11/01/96 5:32p Walsh<BR> 18 * Modify debugging levels of debug output<BR> 19 *<BR> 20 * 10 10/24/96 5:15p Walsh<BR> 21 * add some debugging information related to memory usage.<BR> <P>22 *<BR> 23 * 9 10/21/96 4:26p Walsh<BR> 24 * Add debug logging<BR> 25 *<BR> 26 * 8 9/30/96 7:06p Walsh<BR> 27 * clean up javadoc comments<BR> 28 *<BR> 29 * 7 9/28/96 6.37p Walsh<BR> 30 * use the AgentCodebase class to retrieve bytecodes<BR> 31 *<BR> 32 * 6 8/22/96 5:42p Walsh<BR> 33 * Cache Classes we define<BR> 34 *<BR> 35 * 5 8/19/96 5:25p Walsh<BR> 36 *<BR> 37 * 4 8/13/96 5:09p Walsh<BR> 38 * Added comments & docmentation. loadClass now looks in MobileCodebase.<BR> <P>39 *<BR> 40 * 3 8/13/96 11:19a Walsh<BR> 41 * remove obsolete loadMobileClasses method<BR> 42 *<BR> 43 * 2 8/09/96 4:38p Walsh<BR> 44 * Setting up file headers<BR> 45 */<BR> 46<BR> 47 package com.meitca.hsl.zonesjagents.conduit; 48<BR> 49 import java.rmi.Naming;<BR> 50 import java.io.*;<BR> 51 import java.net.*;<BR> 52 import java.util *;<BR> 53<BR> 54 import com.meitca.hsl zonesjagents shared *;<BR> 55 import com.meitca hsl util *;<BR> 56<BR> 57 /**<BR> 58 * A specialized ClassLoader object used by the conduit server to manage agent<BR> 59 * creation, deserialization, and sub-object creation ConduitServerClassLoader<BR> 60 * extends the base system class loading behavior by allowing for classes to be<BR> 61 * loaded from the MobileCodebase of an Agent. For example, an Agent object might<BR> 62 * be created on one particular server on a network When it is created, its<BR> 63 * bytecodes are added to the MobileCodebase The agent now travels to a new<BR> 64 * server The bytecodes for this particular agent have not been installed on the<BR> 65 * new server Under normal circumstances, when the object deserialization code<BR> 66 * attempts to reconstruct the agent, a ClassNotFoundException would result since<BR> 67 * the agents code does not exist anywhere on the new server<BR> 68 * ConduitServerClassLoader allows the Java virtual machine to look for an Agents<BR> 69 * code in the MobileCodebase which allows Agent object to travel and pull their<BR> 70 * code with them<BR> 71 * @see Agent<BR> 72 * @see ConduitServer<BR> 73 * @see MobileCodebase<BR> 74 * @see ClassLoader<BR> 75 * @author Thomas Walsh<BR> 76 */<BR> 77 public class ConduitServerClassLoader<BR> 78 extends ClassLoader {<BR> 79<BR> 80 /** The MobileCodebase corresponding to the Agent being managed */<BR> 81 MobileCodebase itsMobileCodebase.<BR> <P>82<BR> 83 /** An URL back to the coebase of this agent on its home machine */<BR> 84 AgentCodebase itsHomeCodebase;<BR> 85<BR> 86 /**<BR> 87 * A hashtable containing the Class objects we have already<BR> 88 * defined during the serialization process<BR> 89 /*<BR> 90 Hashtable itsPreviouslyDefinedClasses;<BR> 91<BR> 92 /**<BR> 93 * Constructs a CondutiServerClassLoader<BR> 94 * @param codebase The MobileCodebase corresponding to the 95 * Agent being managed<BR> 96 * @param homeCodebaseURL An URL back to the codebase of this<BR> 97 * agent on its home machine.<BR> <P>98 * @exception MalformedURLException if the URL passesd in as the<BR> 99 * homeCodebaseURL parameter is invalid.<BR> <P>100 */<BR> 101 public ConduitServerClassLoader(MobileCodebase codebase, String homeCodebaseURL)<BR> 102 throws MalformedURLException {<BR> 103 Debug println("conduit memory", 3, "ConduitServerClassLoader " + this + " created");<BR> 104 itsMobileCodebase = codebase;<BR> 105 itshomeCodebase = new AgentCodebase(homeCodebaseURL);<BR> 106 itsPreviouslyDefinedClasses = new Hashtable();<BR> 107 }<BR> 108<BR> 109 protected void finalize() throws Throwable {<BR> 110 Debug.println("conduit.memory", 3, "ConduitServerClassLoader " + this + " finalized");<BR> 111 super finalize();<BR> 112 }<BR> 113<BR> 114<BR> 115 /**<BR> 116 * Loads a class. First check on the local system and then looks in the<BR> 117 * MobileCodebase<BR> 118 * @param name Fully qualified name of the class to be loaded (ie <b><BR> 119 * "java lang String"</b>)<BR> 120 */<BR> 121 public Class loadClass(String name)<BR> 122 throws ClassNotFoundException {<BR> 123 return loadClass(name, true);<BR> 124 }<BR> 125<BR> 126 /**<BR> 127 * Loads a class Inherited from ClassLoader. First check on the local<BR> 128 * system and then looks in the MobileCodebase<BR> 129 * @param name Fully qualified name of the class to be loaded (ie<BR> 130 * java lang.String.<BR> <P>131 * @param resolve boolean value indicating wether or not the class<BR> 132 * should be resolved via the ClassLoader.resolveClass method<BR> 133 */<BR> 134 protected Class loadClass(String name, boolean resolve)<BR> 135 throws ClassNotFoundException {<BR> 136<BR> 137 Debug println("conduit classload", 2, "ConduitServerClassLoader.loadClass called for " + nam<BR> 38 Debug println("conduit classload", 2, "resolve is " + resolve);<BR> 139<BR> 140 // first check the cache to see if we have encountered this class<BR> 141 // before Note A ClassLoader object should always do something 142 // like this In order for Java's type checking to work properly,<BR> 143 // everytime a loadClass is called for a particular class name, the<BR> 144 // EXACT SAME Class object must be returned.<BR> <P>145 Class cache = (Class)itsPreviouslyDefinedClasses.get(name);<BR> 146 if (cache != null) {<BR> 147 Debug.println("conduit classload", 3, "Class found in cache");<BR> 148 return cache;<BR> 149 }<BR> 150<BR> 151 try {<BR> 152 // first check this system<BR> 153 Class c = findSystemClass(name);<BR> 154 Debug println("conduit classload", 3, "Class found on system");<BR> 155 if (resolve) {<BR> 156 resolveClass(c);<BR> 157 }<BR> 158 return c;<BR> 159 } catch (ClassNotfoundException e) {<BR> 160 // wasn't found on this system Check the MobileCodebase.<BR> <P>161 byte@] bytecodes = itsMobileCodebase getCode(name);<BR> 162<BR> 163 if (bytecodes != null) {<BR> 164 Debug println("conduit classload", 3, "Class found in MobileCodbase");<BR> 165<BR> 166 // bytecodes for the class were found in the MobileCodebase<BR> 167 // Try to define a class from them<BR> 168 Class c = defineClass(bytecodes, 0, bytecodes length);<BR> 169 if (resolve) {<BR> 170 resolveClass(c);<BR> 171<BR> 172 // store this class in the cache<BR> 173 itsPreviouslyDefinedClass put(name, c);<BR> 174 }<BR> 175 return c<BR> 176 } else {<BR> 177 Debug.println("conduit classload", 3, "Looking in home codebase");<BR> 178 return loadClassFromHomeCodebase(name, resolve);<BR> 179 }<BR> 180 }<BR> 181 }<BR> 182<BR> 183<BR> 184 /**<BR> 185 * Loads a class using the remote class loader<BR> 186 * @param name Fully qualified name of the class to be loaded (ie<BR> 187 * java lang String<BR> 188 * @param resolve boolean value indicating wether or not the class 189 * should be resolved via the ClassLoader.resolveClass method<BR> 190 */<BR> 191 protected Class loadClassFromHomeCodebase(String name, boolean resolve)<BR> 192 throws ClassNotFoundException {<BR> 193<BR> 194 Debug.println("conduit.classload", 2, "ConduitServerClassLoader.loadClassFromHomeCodebass called fo<BR> " + name);<BR> 195 Debug.println("conduit classload", 2, "resolve is " + resolve);<BR> 196<BR> 197 byte[] bytecodes = itsHomeCodebase retrieveCode(name);<BR> 198<BR> 199 // bytecodes for the class were found in at remote location.<BR> <P>200 // store them in the MobileCodebase for future reference<BR> 201 itsMobileCodebase storeCode(name, bytecodes);<BR> 202<BR> 203<BR> 204 // Try to define a class from them.<BR> <P>205 Class c = defineClass(bytecodes, 0, bytecodes length);<BR> 206 if (resolve) {<BR> 207 resolveClass(c);<BR> 208<BR> 209 // store this clas in the cache<BR> 210 itsPreviouslyDefinedClasses.put(name, c);<BR> 211 }<BR> 212 return c;<BR> 213 }<BR> 214 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/ConduitServerImpl java 23 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 8 * DESCRIPTION<BR> 10 * Conduit Server implementation<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/ConduitServerImpl java $<BR> 13 *<BR> 14 * 23 11/11/96 5:15p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 22 10/30/96 2:52p Walsh<BR> 18 * Allow Debug and ErrorLog settings to be set in properties file<BR> 19 *<BR> 20 * 21 10/29/96 5:28p Walsh<BR> 21 * Use ErrorLog class to report errors<BR> 22 *<BR> 23 * 20 10/28/96 6.31p Walsh<BR> 24 * Add more debugging info<BR> 25 *<BR> 26 * 19 10/25/96 5 02p Walsh<BR> 27 * Make AgentThread public Move to own source file<BR> 28 *<BR> 29 * 18 10/24/96 5 15p Walsh<BR> 30 * add some debugging information related to memory usage<BR> 31 *<BR> 32 * 17 10/23/96 2 22p Walsh<BR> 33 * add more Debug println's<BR> 34 *<BR> 35 * 16 10/21/96 4:26p Walsh<BR> 36 * Add debug logging<BR> 37 *<BR> 38 * 15 10/11/96 2 20p Walsh<BR> 39 * remove restarted agents from persistance store<BR> 40 *<BR> 41 * 14 10/10/96 6.02p Walsh<BR> 42 * Add persistance support<BR> 43 *<BR> 44 * 13 9/29/96 4 08p Walsh<BR> 45 * Allow Destination methods to be specified by name<BR> 46 * Give Agent access to AgentPackage information<BR> 47 * 48 * 12 9/09/96 6:02p Walsh<BR> 49 * make constant final<BR> 50 *<BR> 51 * 11 9/04/96 12 32p Walsh<BR> 52 * Centralize manipulation of ConduitServer's RMI URL<BR> 53 * Move test security manager out of this file<BR> 54 *<BR> 55 * 10 8/30/96 3 53p Walsh<BR> 56 * null out itsPackage (in AgentThread run) to try to nudge the garbage<BR> 57 * collector<BR> 58 *<BR> 59 * 9 8/23/96 3 58p Walsh<BR> 60 * Add support for ad-hoc method invocation<BR> 61 *<BR> 62 * 8 8/22/96 6.36p Walsh<BR> 63 * Add static reference to the one ConduitServer that exists<BR> 64 *<BR> 65 * 7 8/22/96 5 45p Walsh<BR> 66 * Move the custom marshalling of the agent into the AgentPackage class<BR> 67 *<BR> 68 * 6 8/19/96 5 26p Walsh<BR> 69 * Add support for remote class loading<BR> 70 *<BR> 71 * 5 8/13/96 5 12p Walsh<BR> 72 * Changed signature of receivePackage Changed marshalling,<BR> 73 * un-marshalling code to marshal only Agent and not entire AgentPackage<BR> 74 *<BR> 75 * 4 8/13/96 10 35a Walsh<BR> 76 * Add some comments and documentation<BR> 77 *<BR> 78 * 3 8/12/96 7 16p Walsh<BR> 79 * ConduitServer now performs Marshalling<BR> 80 *<BR> 81 * 2 8/09/96 4.38p Walsh<BR> 82 * Setting up file headers<BR> 83 */<BR> 84 package com.meitca hsl zonesjagents conduit;<BR> 85<BR> 86 import java.rmi.server.UnicastRemoteServer;<BR> 87 import java.rmi.RemoteException;<BR> 88 import java.rmi.Naming;<BR> 89 import java.rmi.NotBoundException;<BR> 90 import java.net.*;<BR> 91 import java.io.*;<BR> 92 import java.util.*;<BR> 93<BR> 94 import com.meitca.hsl zonesjagents shared *; 95 import com.meitca.hsl.util.*;<BR> 96 import com.meitca hsl zonesjagents security.InsecurityManager;<BR> 97<BR> 98 /**<BR> 99 * An RMI distributed object which provides for Agent travel and execution<BR> 100 * ConduitServerImpl implements the ConduitServer interface ConduitServer<BR> 101 * is an RMI distributed interface. ConduitServerImpl is responsible for<BR> 102 * receiving incoming agents, providing for execution of agents, and for<BR> 103 * transmitting agents to other destinations<BR> 104 * @see Agent<BR> 105 * @see ConduitServer<BR> 106 * @author Thomas Walsh<BR> 107 */<BR> 108 public class ConduitServerImpl<BR> 109 extends UnicastRemoteServer<BR> 110 implements ConduitServer {<BR> 111<BR> 112 /**<BR> 113 * The conduit server is a Sentinel object There will only be one of<BR> 114 * them running within a given Java vertual machine The static member<BR> 115 * theServer is a pointer to that one ConduitServerImpl object<BR> 116 */<BR> 117 static ConduitServerImpl theServer;<BR> 118<BR> 119 /** The conduit servers name */<BR> 120 String itsName;<BR> 121<BR> 122 /** The conduit servers properties file */<BR> 123 JASProperties itsProperties;<BR> 124<BR> 125 /** An object representing the servers persistence store */<BR> 126 ConduitServerPersistenceStore itsPersistenceStore<BR> 127<BR> 128 /** String constants */<BR> 129 /**The name to which a conduit server is bound in the RMI Registry */<BR> 130 static final String RMI~NAME = "ConduitServer";<BR> 131 static final String PROP~DESC= "Properties File for Conduit Server";<BR> 132<BR> 133<BR> 134 /*<BR> 135 * The following member variables store some statistical information<BR> 136 * about the performance of the Conduit Server<BR> 137 */<BR> 138 /** The date and time when this Conduit Server was started */<BR> 139 Date itsStartTime;<BR> 140<BR> 141 /** The number of Agents currently in the system */ 142 long itsCurrentAgentCount;<BR> 143<BR> 144 /**<BR> 145 * The total number of Agents to travel through the system<BR> 146 * since startup<BR> 147 */<BR> 148 long itsTotalAgentCount;<BR> 149<BR> 150 /**<BR> 151 * The largest number of Agent to be in the system at any one time<BR> 152 */<BR> 153 long itsPeakAgentCount;<BR> 154<BR> 155<BR> 156<BR> 157 /**<BR> 158 * Constructs a conduit server<BR> 159 * @param name The servers name<BR> 160 * @exception RemoteException If an error occurs setting up network<BR> 161 * communications<BR> 162 */<BR> 163 public ConduitServerImpl(String name) throws RemoteException {<BR> 164 itsName = new String(name);<BR> 165 theServer = this;<BR> 166<BR> 167 // initialize the counters<BR> 168 itsTotalAgentCount = 0;<BR> 169 itsCurrentAgentCount = 0;<BR> 170 itsPeakAgentCount = 0;<BR> .71<BR> 172 try {<BR> 173 itsProperties = new JASProperties(RMI~NAME,<BR> 174 JASProperties SERVER,<BR> 175 PROP~DESC,<BR> 176 false);<BR> 177 } catch (Exception e) {<BR> 178 ErrorLog println("conduit.ConduitServerImpl", ErrorLog.SEVERITY~WARNING,<BR> 179 "Could not access Properties file for Conduit Server<BR> 180 ErrorLog println ("conduit.ConduitServerImpl", ErrorLog.SEVERITY~WARNING,<BR> 181 "Continuing with defaults ", e);<BR> 182<BR> 183 // Construct an empty Properties object<BR> 184 itsProperties = new JASProperties();<BR> 185 }<BR> 186<BR> 187 // Set up the debug and error logging facilities using the<BR> 188 // Conduit Server specific properties 189 Debug.enable(itsProperties);<BR> 190 ErrorLog.initialize(itsProperties);<BR> 191<BR> 192 itsPersistenceStore = new ConduitServerPersistenceStore();<BR> 193 }<BR> 194<BR> 195<BR> 196 /**<BR> 197 * Send the Agent on to next conduit server in its Itinerary.<BR> <P>198 * @param agentPackage The Agent Package containing the Agent.<BR> <P>199 * @exception NoSuchElementException If the agent has completed its<BR> 200 * Itinerary.<BR> <P>201 * @exception RemoteException If an error occurs communicating with<BR> 202 * the next server.<BR> <P>203 * @exception NotBoundException If the server name indicated as the<BR> 204 * next destination in the Itinerary cannot be found on the<BR> 205 * network<BR> 206 */<BR> 207 public static void sendPackage(AgentPackage agentPackage)<BR> 208 throws NoSuchElementException, IOException,<BR> 209 RemoteException, NotBoundException{<BR> 210<BR> 211 // retrieve a remote reference to the next destination<BR> 212 ConduitServer nextConduit = (ConduitServer)Naming.lookup(<BR> 213 buildRmiURL(agentPackage.getItinerary() .nextDestination() .getDestinationHost<BR> )));<BR> 214<BR> 215 agentPackage.prepareForTransport();<BR> 216<BR> 217 // pass the agent along<BR> 218 nextConduit.receivePackage(agentPackage);<BR> 219 }<BR> 220<BR> 221<BR> 222 /**<BR> 223 * Receive an Agent from the previous conduit server in its Itinerary.<BR> <P>224 * @param agentData A stream of bytes containing the serialized<BR> 225 * agent<BR> 226 * @param codebase The agents MobileCodebase<BR> 227 * @param itinerary The agents Itinerary<BR> 228 * @exception RemoteException If an error occurs communicating with<BR> 229 * the prior server.<BR> <P>230 */<BR> 231 public void receivePackage(AgentPackage agentPackage)<BR> 232 throws RemoteException {<BR> 233 Debug.println("conduit", 2, "ConduitServerImpl.receivePackage called");<BR> 234 agentPackage.restoreFromTransportForm(); 235 Debug.println("conduit", 1, "Agent " + agentPackage.getAgent() .getAgentID() +" has arrived");<BR> 236<BR> 237 incrementAgentCounters();<BR> 238<BR> 239 AgentThread newThread = new AgentThread(agentPackage);<BR> 240 }<BR> 241<BR> 242 static public void restartAgent(AgentPackage agentPackage) {<BR> 243 Debug.println("conduit", 1, "Restarting Agent " + agentPackage.getAgent() .getAgentID());<BR> 244<BR> 245 incrementAgentCounters();<BR> 246<BR> 247 try {<BR> 248 if (agentPackage.getItinerary() .getCurrentLocation() .hasCompleted()) {<BR> 249 Debug.println("conduit", 1, "\tAgent had completed execution on this Conduit Server<BR> 250 Debug.println("conduit", 1, "\tSending Agent to next Destination");<BR> 251<BR> 252 decrementAgentCounters();<BR> 253 sendPackage(agentPackage);<BR> 254<BR> 255 // remove the agent from the persistence store<BR> 256 getPersistenceStore() .removeFromStore(agentPackage);<BR> 257 } else {<BR> 258 Debug println("conduit", 1, "\tAgent had not completed execution on this Conduit Se@<BR> er");<BR> 259 Debug println("conduit", 1, "\tRestarting execution");<BR> 260 AgentThread newThread = new AgentThread(agentPackage);<BR> 261 }<BR> 262 } catch (Exception e) {<BR> 263 ErrorLog.println("conduit.ConduitServerImpl",<BR> 264 ErrorLog.SEVERITY~ERROR,<BR> 265 "An error occurred while restarting agent:",<BR> 266 e);<BR> 267 }<BR> 268<BR> 269 }<BR> 270<BR> 271 /**<BR> 272 * REtrieves a property from the Conduit Server<BR> 273 * @param key The name of the propery to retrieve<BR> 274 * @param def A default value which will be returned if<BR> 275 * the property cannot be found<BR> 276 * @return the propery value (a string)<BR> 277 */<BR> 278 public static String getProperty(String key, String def) {<BR> 279 return theServer.itsProperties.getProperty(key, def); 280 }<BR> 281<BR> 282 /**<BR> 283 * Returns the conduit servers name.<BR> <P>284 * @exception RemoteException If any network error occurs<BR> 285 */<BR> 286 public static String getConduitName() throws RemoteException {<BR> 287 return theServer.itsName;<BR> 288 }<BR> 289<BR> 290<BR> 291 /**<BR> 292 * This method is used internally to build a full RMI URL for a conduit<BR> 293 * server on the given host<BR> 294 */<BR> 295 protected static String buildRmiURL(String hostname) {<BR> 296 return new String("rmi://" + hostname + "/" + RMI~NAME);<BR> 297 }<BR> 298<BR> 299<BR> 300 /**<BR> 301 * Returns a refernece to the conduit servers persitence store<BR> 302 */<BR> 303 public static ConduitServerPersistenceStore getPersistenceStore() {<BR> 304 return theServer itsPersistenceStore;<BR> 305 }<BR> 306<BR> 307 /**<BR> 308 *Returns the startup time of this conduit server<BR> 309 */<BR> 310 public static Date getStartupTime() {<BR> 311 return theServer itsStartTime;<BR> 312 }<BR> 313<BR> 314 /**<BR> 315 * Returns the uptime of this conduit server (in milliseconds)<BR> 316 */<BR> 317 public static long getUpTime() {<BR> 318 return (System.currentTimeMillis() - theServer itsStartTime.getTime());<BR> 319 }<BR> 320<BR> 321 /**<BR> 322 * Returns the total number of agents to pass through this<BR> 323 * Conduit Server since it was started<BR> 324 */<BR> 325 public static long getTotalAgentCount() {<BR> 326 return theServer istTotalAgentCount; 327 }<BR> 328<BR> 329 /**<BR> 330 * Returns the number of agents currently executing<BR> 331 * in this Conduit Server<BR> 332 * /<BR> 333 public static long getCurrentAgentCount() {<BR> 334 return theServer itsCurrentAgentCount;<BR> 335 }<BR> 336<BR> 337 /**<BR> 338 * Returns the maximum number of agents to be executing<BR> 339 * at any one time in this Conduit Server.<BR> <P>340 */<BR> 341 public static long getPeakAgentCount() {<BR> 342 return theServer.itsPeakAgentCount;<BR> 343 }<BR> 344<BR> 345<BR> 346 /**<BR> 347 *<BR> 348 */<BR> 349 public static synchronized void incrementAgentCounters() {<BR> 350 if (theServer != null) {<BR> 351 theServer itsTotalAgentCount++;<BR> 352 theServer.itsCurrentAgentCount++;<BR> 353 if (theServer itsCurrentAgentCount > theServer.itsPeakAgentCount)<BR> 354 theServer itsPeakAgentCount = theServer.itsCurrentAgentCount;<BR> 355 }<BR> 356 }<BR> 357<BR> 358 /**<BR> 359 *<BR> 360 */<BR> 361 public static synchronized void decrementAgentCounters() {<BR> 362 if (theServer != null) {<BR> 363 theServer.itsCurrentAgentCount--;<BR> 364 }<BR> 365 }<BR> 366<BR> 367 /**<BR> 368 * Performs server startup tasks<BR> 369 */<BR> 370 void startup() {<BR> 371 itsPersistenceStore.restorePersistedObjects();<BR> 372<BR> 373 // Monitor memory if conduit.memory facility is set to 374 // debug level 4<BR> 375 if (Debug.enabled("conduit.memory.watch", 4)) {<BR> 376 MemoryWatch watch = new MemoryWatch();<BR> 377 }<BR> 378<BR> 379 itsStartTime = new Date();<BR> 380 )<BR> 381<BR> 382 /**<BR> 383 * A simple bootstrap which brings the conduit server into existence,<BR> 384 * registers it name with the RMI naming service and begins listening<BR> 385 * for Agent requests The main routine allows ConduitServerImpl to<BR> 386 * be intiated from the command line via the java command.<BR> <P>387 */<BR> 338 public static void main(String args[]) {<BR> 389 //Create and install the security manager<BR> 390 //System.setSecurityManager(new StubSecurityManager());<BR> 391 System.setSecurityManager(new InsecurityManager());<BR> 392<BR> 393 try {<BR> 394 // construct the server and register it with the RMI Naming service<BR> 395 Debug println("conduit", 1, "Create an Conduit Server");<BR> 396 String url = buildRmiURL(InetAddress.getLocalHost() .getHostName());<BR> 397<BR> 398 ConduitServerImpl server = new ConduitServerImpl(url);<BR> 399<BR> 400 Debug.println("conduit", 1, "Bind it to name: " + RMI~NAME);<BR> 401 Naming rebind(RMI~NAME, server)<BR> 402<BR> 403 server startup(),<BR> 404 Debug.println("conduit", 1, "Conduit Server ready ")<BR> 405 } catch (Exception e) {<BR> 406 ErrorLog println("conduitmain", ErrorLog.SEVERITY~FATAL,<BR> 407 "an exception occured during startup:", e);<BR> 408 }<BR> 409 }<BR> 410 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/ConduitServerPersistenc eStore.java 6 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Conduit Server persistence Store<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/ConduitServerPersistenc eStore.java $<BR> 13 *<BR> 14 * 6 11/11/96 5:15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 5 10/29/96 5:29p Walsh<BR> 18 * Use ErrorLog class to report errors<BR> 19 *<BR> 20 * 4 10/21/96 4:26p Walsh<BR> 21 * Add debug logging<BR> 22 *<BR> 23 * 3 10/21/96 11:38a Walsh<BR> 24 * mirror change in Persistence API<BR> 25 *<BR> 26 * 2 10/18/96 10 58a Walsh<BR> 27 * synch with change to findObject API<BR> 28 *<BR> 29 * 1 10/10/96 6 01p Walsh<BR> 30 * initial version<BR> 31 *<BR> 32 */<BR> 33 package com.meitca.hsl.zonesjagents conduit;<BR> 34<BR> 35 import java.io.File;<BR> 36 import java.util.*;<BR> 37<BR> 38 import com.meitca.hsl.zonesjagents.persistence *;<BR> 39 import com.meitca.hsl.zonesjagents.shared.*;<BR> 40 import com.meitca.hsl.util.*;<BR> 41<BR> 42 /**<BR> 43 * Conduit Server Persistence Store<BR> 44 * @see ConduitServerImpl<BR> 45 * @author Thomas Walsh<BR> 46 */<BR> 47 class ConduitServerPersistenceStore { 48 // String constants representing the propery names of<BR> 49 // two properties of interest<BR> 50 private static final String ENABLE~PERSISTENCE = "conduit.persistence.Enable";<BR> 51 private static final String PERSISTENCE~FILE = "conduit.persistence.FileName";<BR> 52 private static final String DEFAULT~FILENAME = "persist store";<BR> 53<BR> 54 /** The PersistentStoreManager object used to manager the persistence store */<BR> 55 PersistentStoreManager itsStore;<BR> 56<BR> 57 /**<BR> 58 * Constructs the PersistenceStore. Persistence will be enabled only<BR> 59 * if the conduit.persistence.Enable Property is set to "true". The<BR> 60 * PersistenceStore will be stored in the file named in the<BR> 61 * conduit.persistence.FileName property. If this Property is not set,<BR> 62 * the store will be placed in the file "zones.home/Agent/persist.store"<BR> 63 * only<BR> 64 */<BR> 65 ConduitServerPersistenceStore() {<BR> 66 if (new Boolean(ConduitServerImpl.getProperty(ENABLE~PERSISTENCE, "false")) .booleanValue()) {<BR> 67 Debug.println("conduit.persistence", 1, "Persistence enabled.");<BR> 68<BR> 69 String filename = ConduitServerImpl.getProperty(PERSISTENCE~FILE, " ");<BR> 70 Debug println("conduit.persistence", 3, "conduit.persistence.FileName property set to " + fi<BR> ename);<BR> 71<BR> 72 if (filename.length() == 0) {<BR> 73 filename = AgentConstants.Agent~DIR + DEFAULT~FILENAME;<BR> 74 }<BR> 75<BR> 76 try {<BR> 77 // construct the PersistentStoreManager<BR> 78 Debug.println("conduit.persistence", 2, "Persistence filename is " + filename);<BR> 79 itsStore = new PersistentStoreManager(filename);<BR> 80 } catch (PersistentStoreException e) {<BR> 81 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ERROR,<BR> 82 "An error occurred constructing the persiste<BR> ce store.", e);<BR> 83 ErrorLog println("conduit Persistence", ErrorLog.SEVERITY~WARNING;<BR> 84 "Continuing without persistence.");<BR> 85<BR> 86 // null out the itsStore reference. We will continue<BR> 87 // executing with persistence disabled<BR> 88 itsStore = null;<BR> 89 }<BR> 90<BR> 91 } else {<BR> 92 // null out the itsStore reference. This will 93 // disable persistence<BR> 94 itsStore = null;<BR> 95 }<BR> 96<BR> 97 }<BR> 98<BR> 99 /**<BR> 100 * Adds an AgentPackage to the persistence store.<BR> <P>101 * @param a Package The package to add.<BR> <P>102 */<BR> 103 void addToStore(AgentPackage aPackage) {<BR> 104 if (itsStore != null) {<BR> 105 if (aPackage.getOID() == 0) {<BR> 106 Debug.println("conduit.persistence", 3, "Adding agent to persistence store: " + aPa<BR> age);<BR> 107<BR> 108 try {<BR> 109 int oid = itsStore.insertObject(aPackage);<BR> 110 Debug.println("conduit.persistence", 4, "Agent's oid is " + oid);<BR> 111 aPackage.setOID(oid);<BR> 112 } catch (PersistentStoreDuplicateObjectException e1) {<BR> 113 try {<BR> 114 Debug.println("conduit.persistence", 4, "Agent already in store try@<BR> g update");<BR> 115 int oid = itsStore.findObject(aPackage);<BR> 116<BR> 117 if (oid != PersistentStoreManager.INVALID~OID) {<BR> 118 Debug.println("conduit.persistence", 4, "Agent found in stor<BR> oid: " + oid);<BR> 119 itsStore updateObject(oid, aPackage);<BR> 120 aPackage.setOID(oid);<BR> 121 } else {<BR> 122 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ER<BR> OR,<BR> 123 "An error occurred adding agent " + aPackage<BR> getAgent() .getAgentID() +<BR> 124 " to the persistence store.");<BR> 125<BR> 126 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ER<BR> OR,<BR> 127 "PersistentStoreManager.findObject returned<BR> ull even though " +<BR> 128 "PersistentStoreManager.insertObject threw a<BR> " +<BR> 129 "PersistentStoreDuplicateObjectException.")<BR> 130<BR> 131 ErrorLog.println("conduit.Persistence", ErrorLog. SEVERITY~WAR NING,<BR> 132 "Continuing without persistence.");<BR> 133<BR> 134 // null out the itsStore reference. We will continue<BR> 135 // executing with persistence disabled<BR> 136 itsStore = null;<BR> 137 }<BR> 138 } catch (PersistentStoreException e2) {<BR> 139 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ERROR,<BR> 140 "An error occurred adding agent " + aPackage<BR> getAgent() .getAgentID() +<BR> 141 "to the persistence store ", e2);<BR> 142<BR> 143 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~WARNING,<BR> 144 "Continuing without persistence.");<BR> 145<BR> 146 // null out the itsStore reference. We will continue<BR> 147 // executing with persistence disabled<BR> 148 itsStore = null;<BR> 149 }<BR> 150 } catch (PersistentStoreException e3) {<BR> 151 ErrorLog println("conduit.Persistence", ErrorLog SEVERITY~ERROR,<BR> 152 "An error occurred adding agent " + aPackage.getAgent<BR> () .getAgentID() +<BR> 153 " to the persistence store ", e3);<BR> 154<BR> 155 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~WARNING,<BR> 156 "Continuing without persistence.");<BR> 157<BR> 158 // null out the itsStore reference. We will continue<BR> 159 // executing with persistence disabled<BR> 160 itsStore = null;<BR> 161 }<BR> 162 }<BR> 163 }<BR> 164 }<BR> 165<BR> 166 /**<BR> 167 * Updates an AgentPackage in the persistence store<BR> 168 * @param aPackage The package to add.<BR> <P>169 */<BR> 170 void updateStore(AgentPackage aPackage) {<BR> 171 if (itsStore != null) {<BR> 172 Debug.println("conduit.persistence", 3, "Updating agent in persistence store: " + aPackage);<BR> 173 Debug.println("conduit.persistence", 3, "Agent's oid is : " + aPackage.getOID());<BR> 174<BR> 175 try { 176 itsStore.updateObject(aPackage.getOid(), aPackage);<BR> 177 } catch (PersistentStoreException e2) {<BR> 178 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ERROR;<BR> 179 "An error occurred updating agent " + aPackage.getAgent() .ge<BR> AgentID() +<BR> 180 " in the persistence store.", e2);<BR> 181<BR> 182 ErrorLog println("conduit Persistence", ErrorLog.SEVERITY~WARNING,<BR> 183 "Continuing without persistence.");<BR> 184<BR> 185 // null out the itsStore reference. We will continue<BR> 186 // executing with persistence disabled<BR> 187 itsStore = null;<BR> 188 }<BR> 189 }<BR> 190<BR> 191 }<BR> 192<BR> 193 /**<BR> 194 * Removes an AgentPackage to the persistence store.<BR> <P>195 * @param aPackage The Package to remove<BR> 196 */<BR> 197 void removeFromStore(AgentPackage aPackage) {<BR> 198 if (itsStore != null) {<BR> 199 Debug.println("conduit persistence", 3, "Removing agent from persistence store: " + aPackage<BR> 200 Debug.println("conduit.persistence", 3, "Agent's oid is : " + aPackage.getOID());<BR> 201<BR> 202 try {<BR> 203 itsStore.deleteObject(aPackage.getOID());<BR> 204 } catch (PersistentStoreException e) {<BR> 205 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ERROR,<BR> 206 "An error occurred removing agent " + aPackage.getAgent() .ge<BR> AgentID() +<BR> 207 "from the persistence store.", e);<BR> 208<BR> 209 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~WARNING,<BR> 210 "Continuing without persistence.");<BR> 211<BR> 212 // null out the itsStore reference. We will continue<BR> 213 // executing with persistence disabled<BR> 214 itsStore = null;<BR> 215 }<BR> 216 }<BR> 217 }<BR> 218<BR> 219 /** 220 * Restores all Agents in the Persistence Store and<BR> 221 * passes them into the ConduitServerImpl.restartAgent method<BR> 222 * so that they are restarted.<BR> <P>223 */<BR> 224 void restorePersistedObjects() {<BR> 225 if (itsStore != null) {<BR> 226 Debug.println("conduit.persistence", 3, "Restoring all persisted Agents");<BR> 227<BR> 228 Enumeration enum = itsStore.getOIDs();<BR> 229<BR> 230 while (enum.hasMoreElements()) {<BR> 231 ObjectID objectID = (ObjectID)enum.nextElement();<BR> 232 int oid = objectID.getOID();<BR> 233<BR> 234 Debug.println("conduit.persistence", 4, "Restoring Agent Oid is : " + oid);<BR> 235<BR> 236 if (oid != 0) {<BR> 237 try {<BR> 238 AgentPackage aPackage = (AgentPackage)itsStore.fetchObject(oid);<BR> 239 Debug.println("conduit.persistence", 4, "Agent Package is : " + aPac<BR> age);<BR> 240 aPackage.setOID(oid);<BR> 241 ConduitServerImpl.restartAgent(aPackage);<BR> 242 } catch (PersistentStoreException e) {<BR> 243 ErrorLog.println("conduit.Persistence", ErrorLog.SEVERITY~ERROR,<BR> 244 "An error occurred restoring persisted Agents<BR> ", e);<BR> 245<BR> 246 ErrorLog.println("conduit Persistence", ErrorLog.SEVERITY~WARNING,<BR> 247 "Continuing without persistence.");<BR> 248<BR> 249 // null out the itsStore reference. We will continue<BR> 250 // executing with persistence disabled<BR> 251 itsStore = null;<BR> 252 }<BR> 253 }<BR> 254<BR> 255 }<BR> 256 }<BR> 257 }<BR> 258 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/Destination.java 7 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All Rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * An agents destination. Containts RMI URL of conduit server, and<BR> 11 * method id of method to invoke at that location<BR> 12 *<BR> 13 * $Log: /com/meitca/hsl/zonesjagents/conduit/Destination.java $<BR> 14 *<BR> 15 * 7 11/11/96 5:15p Billp<BR> 16 * Made correction to company name.<BR> <P>17 *<BR> 18 * 6 10/10/96 6:02p Walsh<BR> 19 * Add persistence support<BR> 20 *<BR> 21 * 5 9/30/96 7:06p Walsh<BR> 22 * clean up javadoc comments<BR> 23 *<BR> 24 * 4 9/29/96 4 08p Walsh<BR> 25 * Allow Destination methods to be specified by name<BR> 26 * Give Agent access to AgentPackage information<BR> 27 *<BR> 28 * 3 9/04/96 12.31p Walsh<BR> 29 * Destination now holds only the hostname of the ConduitServer, not the<BR> 30 * entire RMI URL<BR> 31 *<BR> 32 * 2 8/29/96 5:16p Walsh<BR> 33 * add default constructor and set* methods<BR> 34 *<BR> 35 * 1 8/23/96 3:50p Walsh<BR> 36 * Initial versions<BR> 37 */<BR> 38 package com.meitca.hsl zonesjagents coduit;<BR> 39<BR> 40 import com.meitca.hsl zonesjagents coduit InvalidMethodNameException;<BR> 41<BR> 42 /**<BR> 43 * An object representing a Destination in an Agents Itinerary The<BR> 44 * Destination is composed of two parts; <br><BR> 45 * <ol><BR> 46 * <li>the hostname of the conduit server in which to travel<BR> 47 * <li> An identifer indicating the method of the agent to call 48 * at that ConduitServer. This identifier can either be an<BR> 49 * number representing a (zero based) ID of the method or the<BR> 50 name of the method in the form of a String.<BR> <P>51 * </ol><BR> 52 * @see Agent<BR> 53 * @see ConduitServer<BR> 54 * @see Itinerary<BR> 55 * &num author Thomas Walsh<BR> 56 */<BR> 57 public class Destination implements Cloneable {<BR> 58 static final int UNKNOWN~METHOD~ID = -1;<BR> 59<BR> 60 /** The hostname of the Conduit Server in which to travel */<BR> 61 String itsHostName:<BR> 62<BR> 63 /** The method ID number of the method to invoke */<BR> 64 int itsMethodID;<BR> 65<BR> 66 /** The name of the method to invoke */<BR> 67 String itsMethodName;<BR> 68<BR> 69 /**<BR> 70 * A boolean indicating wether execution at this destination<BR> 71 * has completed.<BR> <P>72 */<BR> 73 boolean itsHasCompleted;<BR> 74<BR> 75 /**<BR> 76 * Constructs a Destination object.<BR> <P>77 * @param hostname The hostname of the conduit server in which to<BR> 78 * travel<BR> 79 * @param methodName The name of the method to invoke<BR> 80 */<BR> 81 public Destination(String hostname, String methodName) {<BR> 82 itsHostName = hostname;<BR> 83 itsMethodID = UNKNOWN~METHOD~ID;<BR> 84 itsMethodName = methodName;<BR> 85 itsHasCompleted = false;<BR> 86 }<BR> 87<BR> 88<BR> 89 /**<BR> 90 * Constructs a Destination object This constructor is used<BR> 91 * internally to construct a Destination<BR> 92 * @param hostname The hostname of the conduit server in which to<BR> 93 * travel<BR> 94 * @param method the method ID number of the method to invoke 95 */<BR> 96 public Destination(String hostname, int method) {<BR> 97 itsHostname = hostname;<BR> 98 itsMethodID = method;<BR> 99 its MethodName = null;<BR> 100 itsHasCompleted = false;<BR> 101 }<BR> 102<BR> 103 /**<BR> 104 * Construction an empty Destination object<BR> 105 */<BR> 106 public Destination() {<BR> 107 itsHostName = new String ("");<BR> 108 itsMethodID = UNKNOWN~METHOD~ID;<BR> 109 itsMethodName = null;<BR> 110 itsHasCompleted = false;<BR> 111 }<BR> 112<BR> 113 /**<BR> 114 * Retrieves the hostname of the conduit server in which to travel<BR> 115 */<BR> 116 public String getDestinationHost() {<BR> 117 return itsHostName;<BR> 118 }<BR> 119<BR> 120 /**<BR> 121 * Retrieves the method ID number of the method to invoke<BR> 122 */<BR> 123 public int getMethodID() {<BR> 124 return itsMethodID;<BR> 125 }<BR> 126<BR> 127 /**<BR> 128 * Sets the URL of the conduit server in which to travel<BR> 129 */<BR> 130 public void setDestinationHost(String hostname) {<BR> 131 itsHostName = hostname;<BR> 132 }<BR> 133<BR> 134 /**<BR> 135 * Sets the method ID number of the method to invoke<BR> 136 */<BR> 137 public void setMethodID(int id) {<BR> 138 itsMethodName = null;<BR> 139 itsMethodID = id;<BR> 140 }<BR> 141 142 /**<BR> 143 * Retrieves the method name of the method to invoke<BR> 144 */<BR> 145 public String getMethodName() {<BR> 146 return itsMethodName;<BR> 147 }<BR> 148<BR> 149 /**<BR> 150 * Makes a clone of the Destination object<BR> 151 */<BR> 152 public Destination cloneDestination() {<BR> 153 Destination clone = new Destination()<BR> 154 clone itsHostName = itsHostName;<BR> 155 clone itsMethodID = itsMethodID;<BR> 156 clone itsMethodName = itsMethodName;<BR> 157 return clone<BR> 158 }<BR> 159<BR> 160 /**<BR> 161 * Sets the internal state of the Destination to<BR> 162 * indicate that execution has been completed<BR> 163 */<BR> 164 void setCompleted() {<BR> 165 itsHasCompleted = true;<BR> 166 }<BR> 167<BR> 168 /**<BR> 169 * Checks the internal state of the Destination to<BR> 170 * see if execution has been completed<BR> 171 */<BR> 172 boolean hasCompleted() {<BR> 173 return itsHasCompleted;<BR> 174 }<BR> 175<BR> 176 /** Used internally to convert a method name into a method id */<BR> 177 protected void convertNameToId(AgentSkeleton skel)<BR> 178 throws InvalidMethodNameException {<BR> 179<BR> 180 if (itsMethodName == null) {<BR> 181 throw new InvalidMethodNameException("No name specified for destination");<BR> 182 }<BR> 183<BR> 184 String[] methods = skel.getMethods();<BR> 185 for(int i=0; i<methods.length; i++) {<BR> 186 if (itsMethodName.equals(methods [i])) {<BR> 187 itsMethodID = i;<BR> 188 itsMethodName = null; 189 return;<BR> 190 }<BR> 191 }<BR> 192 throw new InvalidMethodNameException("Method name + itsMethodName + "does not match any methods of<BR> agent");<BR> 193 }<BR> 194 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/InvalidMethodNameExcept ion.java 3 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon System Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Exception indicating that Method Name specifed in a Destination<BR> 11 * is not a valid name<BR> 12 *<BR> 13 * $Log: /com/meitca/hsl/zonesjagents/conduit/InvalidMethodNameExcept ion.java $<BR> 14 *<BR> 15 * 3 11/11/96 5:15p Billp<BR> 16 * Made correction to company name.<BR> <P>17 *<BR> 18 * 2 9/30/96 7:06p Walsh<BR> 19 * clean up javadoc comments<BR> 20 *<BR> 21 * 1 9/29/96 4:07p Walsh<BR> 22 * initial version<BR> 23 *<BR> 24 */<BR> 25 package com.meitca.hsl zonesjagents.conduit;<BR> 26<BR> 27 /**<BR> 28 * An exception which indicates that the method name that was specified<BR> 29 * in a Destination was not the name of a method of the agent which<BR> 30 * is travelling.<BR> <P>31 * @see Agent<BR> 32 * @see AgentSkeleton<BR> 33 * @author Thomas Walsh<BR> 34 */<BR> 35 public class InvalidMethodNameException extends Exception {<BR> 36 public InvalidMethodNameException() {<BR> 37 super();<BR> 38 }<BR> 39<BR> 40 public InvalidMethodNameException(String s) {<BR> 41 super(s);<BR> 42 }<BR> 43 } 1 /* $Header: /com/meitca/hsl/zonesjagents/conduit/Itinerary.java 5 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent itinerary object<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/conduit/Itinerary java $<BR> 13 *<BR> 14 * 5 11/11/96 5:15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 4 9/29/96 4:08p Walsh<BR> 18 * Allow Destination methods to be specified by name<BR> 19 * Give Agent access to AgentPackage Information<BR> 20 *<BR> 21 * 3 8/23/96 3 58p Walsh<BR> 22 * Add support for ad-hoc method invocation<BR> 23 *<BR> 24 * 2 8/09/96 4 38p Walsh<BR> 25 * Setting up file headers<BR> 26 */<BR> 27 package com.meitca hsl zonesjagents conduit;<BR> 28<BR> 29 import java util *;<BR> 30<BR> 31 /**<BR> 32 * An object representing an Agent's Itinerary. The Itinerary<BR> 33 * indicated WHERE an agent should travel and indicated WHAT<BR> 34 * the Agent should do at each stop<BR> 35 * @see Agent<BR> 36 * @see ConduitServer<BR> 37 * @see Destination<BR> 38 * @author Thomas Walsh<BR> 39 */<BR> 40 public class Itinerary {<BR> 41 Vector itsDestinations;<BR> 42 int itsCurrentStop;<BR> 43<BR> 44 /**<BR> 45 * Constructs an Itinerary object<BR> 46 */<BR> 47 public Itinerary() { 48 itsDestinations = new Vector();<BR> 49 itsCurrentStop = -1;<BR> 50 }<BR> 51<BR> 52 /**<BR> 53 * Adds a new destination to the end of the Agents Itinerary.<BR> <P>54 * @param destination The new destination<BR> 55 */<BR> 56 public void addDestination(Destination destination) {<BR> 57 itsDestinations addElement(destination);<BR> 58 }<BR> 59<BR> 60 /**<BR> 61 * Clears all destinations from the Agents Itinerary<BR> 62 */<BR> 63 public void clearItinerary() {<BR> 64 itsDestinations removeAllElements();<BR> 65 }<BR> 66<BR> 67 /**<BR> 68 * Resets the Itinerary back to the initial Destination.<BR> <P>69 * This method could be used to force an Agent to restart<BR> 70 * its Itinerary and revisit all Destinations<BR> 71 */<BR> 72 public void resetItinerary() {<BR> 73 itsCurrentStop = -1<BR> 74 }<BR> 75<BR> 76<BR> 77 **<BR> 78 * Retrieves the destination object identifying the current<BR> 79 * location of the Agent<BR> 80 * @returns The Agent's current location<BR> 81 * @exception NoSuchElementException If the Agent has not<BR> 82 * travelled<BR> 83 */<BR> 84 public Destination getCurrentLocation() throws NoSuchElementException {<BR> 85 try {<BR> 86 return (Destination) itsDestinations elementAt(itsCurrentStop);<BR> 87 } catch (ArrayIndexOutOfBoundsException boundError) {<BR> 88 throw new NoSuchElementException()<BR> 89 }<BR> 90 }<BR> 91<BR> 92 /**<BR> 93 * Retrieves the destination object identifying the current<BR> 94 * location of the Agent 95 * @returns The Agent's next destination<BR> 96 * @exception NoSuchElementException If the Agent has not<BR> 97 * travelled<BR> 98 */<BR> 99 public Destination getNextDestination() throws NoSuchElementException {<BR> 100 try {<BR> 101 return (Destination)itsDestinations elementAt(itsCurrentStop+1);<BR> 102 } catch (ArrayIndexOutOfBoundsException boundError) {<BR> 103 throw new NoSuchElementException()<BR> 104 }<BR> 105 }<BR> 106<BR> 107 /**<BR> 108 * Retrieves an enumeration of all of the Destinations in the<BR> 109 * Itinerary<BR> 110 * @returns An enumeration of all of the Destinations in the<BR> 111 * Itinerary.<BR> <P>112 */<BR> 113 public Enumeration destinations() {<BR> 114 return itsDestinations elements();<BR> 115 }<BR> 116<BR> 117 /**<BR> 118 * Makes a clone of the Itinerary If the reset parameter is true<BR> 119 * then the new Itinerary is reset to the first destination If<BR> 120 * reset is false, then the new itinerary is set such that its next<BR> 121 * destination is the same as that of the original<BR> 122 * @param reset true if the new itinerary should be reset to<BR> 123 * the first destination<BR> 124 * @returns A clone of the original Itinerary<BR> 125 */<BR> 126 public Itinerary cloneItinerary(boolean reset) {<BR> 127 Itinerary clone =new Itinerary();<BR> 128<BR> 129 Enumeration enum = itsDestinations elements();<BR> 130 while (enum hasMoreElements()) {<BR> 131 Destination original = (Destination)enum.nextElement();<BR> 132 Destination cloneDest = (Destination)original.cloneDestination();<BR> 133 clone addDestination(cloneDest);<BR> 134 }<BR> 135<BR> 136 if (!reset)<BR> 137 clone itsCurrentStop = itsCurrentStop;<BR> 138<BR> 139 return clone;<BR> 140 }<BR> 141 142 /**<BR> 143 * Retrieves the next destination to which an Agent should<BR> 144 * travel and increments the Itineraries internal state to<BR> 145 * the next destination This method is called internally<BR> 146 * by the ConduitServer when it is preparing to transport<BR> 147 * the Agent to its next destination.<BR> <P>148 */<BR> 149 protected Destination nextDestination() throws NoSuchElementException {<BR> 150 try {<BR> 151 return (Destination)itsDestinations elementAt(++itsCurrentStop);<BR> 152<BR> 153 } catch (ArrayIndexOutOfBoundsException boundError) {<BR> 154 throw new NoSouchElementException();<BR> 155 }<BR> 156 }<BR> 157 } 1 /* $Header /com/meitca/hsl/zonesjagents/conduit/MemoryWatch.java 3 11/11/96 5:15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Conduit Server implementation<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/conduit/MemoryWatch java $<BR> 13 *<BR> 14 * 3 11/11/96 5 15p Billp<BR> 15 * Made correction to company name.<BR> <P>16 *<BR> 17 * 2 10/28/96 6 31p Walsh<BR> 18 * Add more debugging info<BR> 19 *<BR> 20 * 1 10/24/96 5 12p Walsh<BR> 21 * Initial Version<BR> 22 *<BR> 23 */<BR> 24 package com.meitca hsl zonesjagents.conduit;<BR> 25<BR> 26 import java.util *;<BR> 27<BR> 28 import com.meitca.hsl util *;<BR> 29<BR> 30 /**<BR> 31 * The memory watch class provides an minimum priority thread which<BR> 32 * reports the total amount of memory allocated to the Java VM as<BR> 33 * well as the amount of free memory currently available<BR> 34 *<BR> 35 * To enable the MemoryWatch, the Conduit Server should be started<BR> 36 * up with the following switch passed into java exe<BR> 37 * -DDebug="conduit.memory.watch=4"<BR> 38 * @author Thomas Walsh<BR> 39 */<BR> 40 class MemoryWatch extends Thread {<BR> 41<BR> 42 /** The number of milliseconds between polls of the VM */<BR> 43 static int pollingInterval = 5000; // in millisec<BR> 44<BR> 45 /** Constructs a MemoryWatch object */<BR> 46 MemoryWatch() {<BR> 47 Debug println("conduit memory.watch", 1, "Memory Watch thread starting "); 48 setPriority(Thread.MIN~PRIORITY);<BR> 49 start();<BR> 50 }<BR> 51<BR> 52 /** Performs memory polling */<BR> 53 public void run() {<BR> 54 while (true) {<BR> 55 Debug.println("conduit.memory.watch", 4, "");<BR> 56 Debug.println("conduit.memory.watch", 4, "Server up since: " + ConduitServerImpl.getStartup@<BR> me());<BR> 57<BR> 58 long uptime = ConduitServerImpl.getUpTime();<BR> 59 Date up~date = new Date(uptime);<BR> 60 Date bigBang = new Date(0);<BR> 61 Debug.println("conduit.memory.watch", 4, "Server uptime: " +<BR> 62 (up~date.getYear() - bigBang.getYear()) + " years, " +<BR> 63 (up~date.getMonth() - bigBang.getMonth()) + " months, " +<BR> 64 (up~date.getDate() - bigBang.getDate()) + " days, " +<BR> 65 (up~date.getHours() - bigBang.getHours()) + " hours, " +<BR> 66 (up~date.getMinutes() - bigBang.getMinutes()) + " minutes,<BR> +<BR> 67 (up~date.getSeconds() - bigBang.getSeconds()) + " seconds<BR> ;<BR> 68<BR> 69 Debug.println("conduit.memory.watch", 4, "Total number of Agents \t\t\t" + ConduitServerImpl<BR> getTotalAgentCount());<BR> 70 Debug.println("conduit.memory.watch", 4, "Current number of Agents \t\t" + ConduitServerImpl<BR> getCurrentAgentCount());<BR> 71 Debug.println("conduit.memory watch", 4, "Peak number of Agents.\t\t\t" + ConduitServerImpl<BR> etPeakAgentCount());<BR> 72 Debug.println("conduit.memory.watch", 4, "Total memory allocated to system:\t" + Runtime.ge<BR> untime() .totalMemory());<BR> 73 Debug.println("conduit.memory.watch", 4, "Total free memory available:\t\t" + Runtime.getRun<BR> ime() .freeMemory());<BR> 74 Debug.println("conduit.memory.watch", 4, "");<BR> 75 try {<BR> 76 sleep(pollingInterval);<BR> 77 } catch (InterruptedException e) {<BR> 78 Debug println("conduit.memory.watch", 4, "Some thread interrupted the MemoryWatch du<BR> ing sleep. Continuing");<BR> 79 }<BR> 80 }<BR> 81 }<BR> 82<BR> 83 } 1 /* $Header /com/meitca/hsl/zonesjagents/conduit/MobileCodebase.java 5 11/11/96 5.15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent Mobile codebase object<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/conduit/MobileCodebase.java $<BR> 13 *<BR> 14 * 5 11/11/96 5.15p Billp<BR> 15 * Made correction to comany name.<BR> <P>16 *<BR> 17 * 4 9/30/96 7:06p Walsh<BR> 18 * clean up javadoc comments<BR> 19 *<BR> 20 * 3 8/13/96 11:18a Walsh<BR> 21 * Add documentation & comments Set up use of HashTable for bytecode<BR> 22 * storage.<BR> <P>23 *<BR> 24 * 2 8/09/96 4 38p Walsh<BR> 25 * Setting up file headers<BR> 26 */<BR> 27 package com.meitca.hsl zonesjagents conduit;<BR> 28<BR> 29 import java util.Hashtable;<BR> 30<BR> 31<BR> 32 /**<BR> 33 * Contains the bytecodes for the objects that travel with an Agent<BR> 34 * @see Agent<BR> 35 * @author Thomas Walsh<BR> 36 */<BR> 37 public class MobileCodebase {<BR> 38 /**<BR> 39 * Provides for easy storage and retrieval of bytecodes. Bytecodes<BR> 40 * are stored in a Hastable and are accessible by fully qualified<BR> 41 * Class name (ie "java.lang.String")<BR> 42 */<BR> 43 Hashtable itsByteCodes;<BR> 44<BR> 45 /**<BR> 45 * Constructs a MobileCodebase object<BR> 47 */ 48 public MobileCodebase() {<BR> 49 itsByteCodes = new Hashtable();<BR> 50 }<BR> 51<BR> 52 /**<BR> 53 * Stores an objects bytecodes into the MobileCodebase.<BR> <P>54 * @param name The fully qualified Class name (ie<BR> 55 * <b>"java.lang String"</b>)<BR> 56 * @param code The Class's bytecodes<BR> 57 */<BR> 58 public void storeCode(String name, byte[] code) {<BR> 59 itsByteCodes put(name, code);<BR> 60 }<BR> 61<BR> 62 /**<BR> 63 * Retrieves an objects bytecodes from the MobileCodebase<BR> 64 * @param name The fully qualified Class name (ie<BR> 65 * <b>"java lang String"</b>)<BR> 66 */<BR> 67 public byte[] getCode(String name) {<BR> 68 return (byte[]) itsByteCodes get(name);<BR> 69 }<BR> 70 } 1 /* $Header: /com/meitca/hsl/zonesjagents/remoteloader/RemoteClassLoader java 4 11/11/96 5 15p Billp<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsibishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Remote class loader distributed interface<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/remoteloader/RemoteClassLoader java $<BR> 13 *<BR> 14 * 4 11/11/96 5 15p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 3 9/28/96 6:39p Walsh<BR> 18 * Add new parameter to retrieveClass method<BR> 19 *<BR> 20 * 2 8/27/96 4 10p Walsh<BR> 21 * retrieveClass throws ClassNotFoundException (compiler games)<BR> 22 *<BR> 23 * 1 8/19/96 5 28p Walsh<BR> 24 * Initial version<BR> 25 */<BR> 26 package com.meitca hsl zonesjagents remoteloader;<BR> 27<BR> 28 import java rmi.Remote;<BR> 29 import java rmi.RemoteException;<BR> 30<BR> 31<BR> 32 /**<BR> 33 * RemoteClassLoader is an RMI distributed interface It provides a<BR> 34 * mechanism by which conduit servers can retrieve bytecodes for classes<BR> 35 * that exist on machines other than the one on which conduit<BR> 36 * server is loading<BR> 37 * @see ConduitServer<BR> 38 * @author Thomas Walsh<BR> 39 */<BR> 40 public interface RemoteClassLoader extends Remote {<BR> 41<BR> 42 /**<BR> 43 * Retrieve the bytecodes for the specified class<BR> 44 * @param classURL An URL specifying the class to be loaded<BR> 45 * This should be of the form /directory~path/classname<BR> 46 * @return The bytecodes for the class<BR> 47 * @exception RemoteException If an error occurs communicating 48 */<BR> 49 public bytel[] retrieveClass(String codebaseURL, String className) throws RemoteException,<BR> 50 ClassNotFoundException,<BR> 51 } 1 /* $Header: /com/meitca/hsl/zonesjagents/remoteloader/RemoteClassLoaderI mpl.java 8 11/11/96 5.15p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Remote class loader implementation<BR> 11 *<BR> 12 * $Log. /com/meitca/hsl/zonesjagents/remoteloader/RemoteClassLoaderI mpl.java $<BR> 13 *<BR> 14 * 8 11/11/96 5 15p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 7 10/29/96 5 31p Walsh<BR> 18 * Use ErrorLog class to report errors<BR> 19 *<BR> 20 * 6 10/21/96 1.26p Walsh<BR> 21 * Add some debug output<BR> 22 *<BR> 23 * 5 9/28/96 6.40p Walsh<BR> 24 * Use AgentCodebase class to load byte codes<BR> 25 * Add retrieveRemoteClass to encapsulate RMI code<BR> 26 *<BR> 27 * 4 9/04/96 12.33p Walsh<BR> 28 * Centralize manipulation or RMI URL. Use the test security manager<BR> 29 *<BR> 30 * 3 8/27/96 4.18p Walsh<BR> 31 * Add silly constructor (because Sun compiler wants it)<BR> 32 *<BR> 33 * 2 8/23/96 3.59p Walsh<BR> 34 * Add logging message<BR> 35 *<BR> 36 * 1 8/19/96 5.28p Walsh<BR> 3 * Initial version<BR> 38 */<BR> 39 package com.meitca.hsl.zonesjagents remoteloader;<BR> 40<BR> 41 import java.rmi.Remote;<BR> 42 import java.rmi.RemoteException;<BR> 43 import java.rmi.server.UnicastRemoteServer;<BR> 44 import java.rmi.server.StubSecurityManager;<BR> 45 import java.rmi.Naming;<BR> 46 import java.io.*;<BR> 47 import java.lang ClassNotFoundException; 48<BR> 49<BR> 50 import com.meitca.hsl zonesjagents security.*;<BR> 51 import com.meitca hsl zonesjagents shared *;<BR> 52 import com.meitca hsl util *;<BR> 53<BR> 54 /**<BR> 55 * An RMI distributed object which provides for remote retrieval of class<BR> 56 * bytecodes RemoteClassLoaderImpl implements the RemoteClassLoader interface<BR> 57 * @see RemoteClassLoader<BR> 58 * @author Thomas Walsh<BR> 59 */<BR> 60 public class RemoteClassLoaderImpl<BR> 61 extends UnicastRemoteServer<BR> 62 implements RemoteClassLoader {<BR> 63<BR> 64 /**The name to which a conduit server is bound in the RMI Registry */<BR> 65 static String RMI~NAME = "RemoteClassLoader";<BR> 66<BR> 67 /**<BR> 68 * object which actually handles the dirty work or retrieving .class<BR> 69 * files for a given class<BR> 70 */<BR> 71 ClassFileLoader itsClassFileLoader;<BR> 72<BR> 73<BR> 74 public RemoteClassLoaderImpl() throws RemoteException {<BR> 75 itsClassFileLoader = new ClassFileLoader();<BR> 76 }<BR> 77<BR> 78 /**<BR> 79 * Retrieve the bytecodes for the specified class This method is invoked<BR> 80 * by RMI The calling program on the other side of the RMI connection<BR> 81 * usually invokes the RMI by calling the<BR> 82 * RemoteClassLoader retrieveRemoteClass method below.<BR> <P>83 * @param classURL An URL specifying the class to be loaded<BR> 84 * This should be of the form /directory~path/classname<BR> 85 * @return The bytecodes for the class<BR> 86 * @exception RemoteException If an error occurs communicating<BR> 87 */<BR> 88 public byte[] retrieveClass(String codebase~dir, String className)<BR> 89 throws RemoteException, ClassNotFoundException {<BR> 90 Debug println("remoteloader", 2, "loading " +<BR> 91 className + " from " + codebase~dir);<BR> 92<BR> 93 if ((codebase~dir == nul) || (codebase~dir length() == 0)) {<BR> 94 Debug println("remoteloader" @ "loading from CLASSPATH"); 95 return itsClassFileLoader.loadClassFilerFromClassPath(className);&l t;BR> 96 } else {<BR> 97 Debug println("remoteloader", 3, "loading from directory");<BR> 98 return itsClassFileLoader loadClassFileFromDirectory(codebase~dir, className)<BR> 99 }<BR> 100 }<BR> 101<BR> 102 /**<BR> 103 * Retrieve the bytecodes for the specified class from the remote<BR> 104 * codebase specified by codebase~URL This method is called internally<BR> 105 * by the Java agent system whenever an object wants to retrieve code<BR> 106 * from a RemoteClassLoader This method hides the details of the RMI<BR> 107 * @param codebase~URL An URL specifying the class to be loaded.<BR> <P>108 * This should be of the form /directory~path/classname<BR> 109 * @param className The fully qualified class name of the class whose<BR> 110 * bytecode should be retrieved.<BR> <P>111 * @return The bytecodes for the class<BR> 112 * @exception RemoteException If an error occurs communicating<BR> 113 */<BR> 114 public static byte[] retrieveRemoteClass(String codebase~URL, String className)<BR> 115 throws ClassNotFoundException {<BR> 116<BR> 117 Debug println("remoteloader", 2, "retrieveRemoteClass: loading " +<BR> 118 className + " from " + codebase~URL);<BR> 119<BR> 120 int count = 0;<BR> 121 int index = 0;<BR> 122 while (count < 4) {<BR> 123 index = codebase~URL indexOf( , index);<BR> 124 if (index == -1)<BR> 125 break;<BR> 126<BR> 127 count++;<BR> 128 index++;<BR> 129 }<BR> 130<BR> 131 String rmiURL;<BR> 132 String code~dir;<BR> 133<BR> 134 if (index != -1) {<BR> 135 rmiURL = codebase~URL substring(0, (index -1));<BR> 136 code~dir = codebase~URL substring(index, codebase~URL length());<BR> 137 } else {<BR> 138 rmiURL = codebase~URL;<BR> 139 code~dir = null;<BR> 140 }<BR> 141 142 Debug println("remoteloader", 3, "remote object URL: " + rmiURL);<BR> 143 Debug.println("remoteloader", 3, "remote code dir " + code~dir);<BR> 144<BR> 145 try {<BR> 146 RemoteClassLoader remote = (RemoteClassLoader)Naming.lookup(rmiURL);<BR> 147<BR> 148 return remote retrieveClass(code~dir, className);<BR> 149<BR> 150 } catch (Exception e) {<BR> 151 throw new ClassNotFoundException("Cound not load " + className + e.getMessage());<BR> 152 }<BR> 153 }<BR> 154<BR> 155<BR> 156 /**<BR> 157 * This method is used internally to build a full RMI URL for a remote<BR> 158 * class loader on the given host<BR> 159 */<BR> 160 public static String buildRmiURL(String hostname) {<BR> 161 return new String("rmi //" + hostname + "/" + RMI~NAME);<BR> 162 }<BR> 163<BR> 164 /**<BR> 165 * This method is used internally to build a full RMI URL for a remote<BR> 166 * codebase on the given host<BR> 167 */<BR> 168 public static String buildCodebaseURL(String hostname, String codeDir) {<BR> 169 return new String(buildRmiURL(hostname) + "/" + codeDir);<BR> 170 }<BR> 171<BR> 172 /**<BR> 173 * A simple bootstrap which brings the remote class loader into existence,<BR> 174 * registers it name with the RMI naming service and begins listening<BR> 175 * for requests The main routine allows RemoteClassLoaderImpl to<BR> 176 * be initiated from the command line via the java command<BR> 177 */<BR> 178 public static void main(String args[]) {<BR> 179 // Create and install the security manager<BR> 180 System.setSecurityManager(new InsecurityManager());<BR> 181<BR> 182 try {<BR> 183 // construct the server and register it with the RMI Naming service<BR> 184 Debug.println("remoteloader", 1, "Create an RemoteClassLoader");<BR> 185 RemoteClassLoaderImpl loader = new RemoteClassLoaderImpl();<BR> 186<BR> 187 Debug.println("remoteloader", 1, "Bind it to name " + RMI~NAME);<BR> 188 Naming rebind(RMI~NAME, loader); 189<BR> 190 Debug println("remoteloader", 1, "RemoteClassLoaderImpl ready "),<BR> 191 } catch (Exception e) {<BR> 192 ErrorLog println("remoteloader.main", ErrorLog.SEVERITY~FATAL,<BR> 193 "an exception occurred during startup:", e),<BR> 194 }<BR> 195 }<BR> 196<BR> 197 } 1 /* $Header: /com/meitca/hsl/zonesjagents/skeleton/Generator.java 5 11/11/96 5:16p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent Skeleton Generator<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/skeleton/Generator java $<BR> 13 *<BR> 14 * 5 11/11/96 5:16p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 4 9/30/96 7 20p Walsh<BR> 18 * add javadoc comments<BR> 19 *<BR> 20 * 3 9/29/96 4 32p Walsh<BR> 21 * Allow agents to be in packages<BR> 22 *<BR> 23 * 2 9/12/96 11:00a Walsh<BR> 24 * Automatically compile the skeleton file<BR> 25 *<BR> 26 * 1 9/06/96 4 54p Walsh<BR> 27 *<BR> 28 */<BR> 29 package com.meitca hsl zonesjagents skeleton;<BR> 30<BR> 31 import sun tools java *;<BR> 32 import sun.tools.javac *;<BR> 33 import java io.*;<BR> 34 import java util *;<BR> 35<BR> 36<BR> 37 /**<BR> 38 * The Generator class generates an Method Invocation Skelton for an<BR> 39 * Agent A Method Invocation Skelton allows the ConduitServer to<BR> 40 * dynamically invoke any method of an Agent The Skeleton serves a<BR> 41 * similar purpose as does an RMI skeleton or an RPC server side stub<BR> 42 * Before any Agent can travel, it is requires that a Skeleton be<BR> 43 * generated by it A programmer can generate a skeleton by executing<BR> 44 * Generator with a command line like the following; <br><BR> 45 *<pre><BR> 46 * java com.meitca hsl zonesjagents skeleton.Generator agentclassname<BR> 47 * </pre> 48 * The agentclassname paramter should be the fully qualified class<BR> 49 * name of the agent.<BR> <P>50 * @see ConduitServer<BR> 51 * @see Agent<BR> 52 * @see AgentSkeleton<BR> 53 * @author Thomas Walsh<BR> 54 */<BR> 55 public class Generator {<BR> 56 /**<BR> 57 * the main method allows Generator to be called from the command<BR> 58 * line.<BR> <P>59 */<BR> 60 public static void main (String[] args) {<BR> 61 // Sanity check the command line arguments<BR> 62 if (args length < 1) {<BR> 63 System.err.println(StringResources.NO~AGENT);<BR> 64 System.err.println(StringResources USAGE);<BR> 65 return;<BR> 66 }<BR> 67<BR> 68 if (args length > 1) {<BR> 69 System err println(StringResources TOO~MANY)<BR> 70 System.err println(StringResources USAGE);<BR> 71 return;<BR> 72 }<BR> 73<BR> 74 String agentClassName = args[0]<BR> 75 String packageName;<BR> 76 String shortClassName;<BR> 77<BR> 78 int lastSep = agentClassName lastOf(' ');<BR> 79 if (lastSep != -1) {<BR> 80 packageName = agentClassName substring(0, lastSep);<BR> 81 shortClassName = agentClassName substring(lastSep + 1, agentClassName length());<BR> 82 } else {<BR> 83 packageName = null;<BR> 84 shortClassName = agentClassName;<BR> 85<BR> 86 }<BR> 87<BR> 88 String skelFileName = shortClassName + "~Skel java";<BR> 89<BR> 90<BR> 91 try {<BR> 92 String[] methods = findAgentMethods(agentClassName);<BR> 93 PrintStream out = new PrintStream(new FileOutputStream(skelFileName));<BR> 94 95<BR> 96 generateSkel(agentClassName, packageName, shortClassName, methods, out);<BR> 97 compileSkel(skelFileName);<BR> 98 } catch (ClassNotFound e1) {<BR> 99 System.err println(StringResources NOT~FOUND + agentClassName);<BR> 100 } catch (IOException e2) {<BR> 101 System.err println(StringResources IO~ERROR + skelFileName);<BR> 102 System.err.println(e2 getMessage());<BR> 103 e2.printStackTrace();<BR> 104 }<BR> 105 }<BR> 106<BR> 107 static void generateSkel(String agentClassName,<BR> 108 String packageName,<BR> 109 String shortClassName,<BR> 110 String[] methods,<BR> 111 PrintStream stream) {<BR> 112<BR> 113 // Ok This is going to be a fairly brute force approach<BR> 114 // First lets put a comment on the file<BR> 115 stream println("//Skeleton for " + agentClassName);<BR> 116 stream println("//Generated by com meitca hsl zonesjagents skeleton.Generator");<BR> 117<BR> 118 // The package statement<BR> 119 if (packageName != null)<BR> 120 stream.println("package " + packageName + " ; ");<BR> 121<BR> 122 stream.println(" ");<BR> 123<BR> 124 // Now some imports<BR> 125 stream println("import java lang IllegalAccessException;");<BR> 126 stream.println("import com meitca hsl zonesjagents shared Agent;");<BR> 127 stream.println("import com.meitca hsl zonesjagents conduit.AgentSkeleton;");<BR> 128 stream.println("import " + agentClassName + " ; ");<BR> 129 stream.println(" ");<BR> 130<BR> 131 //now the class itself<BR> 132 stream.println("public final class " + shortClassName + "~Skel implements AgentSkeleton (")<BR> 133<BR> 134<BR> 135<BR> 136 / define the static member variable containing the names of<BR> 137 // the objects methods<BR> 138 String methodsMember = "\tstatic public String methods[] = { ";<BR> 139 for (int i=0; i<methods length; i++) {<BR> 140 if (i ! = 0) {<BR> 141 methodsMember = methodsMember + ", "; 142 }<BR> 143 methodsMember = methodsMember + "new String(\" " + methods[i] + "\")";<BR> 144 }<BR> 145 methodsMember = methodsMember + " );";<BR> 146 stream.println(methodsMember);<BR> 147 stream.println(" ");<BR> 148<BR> 149<BR> 150 // now the invoke method<BR> 151 stream.println("\tpublic void invoke(Agent agent, int i) throws IllegalAccessException (");<BR> 152 stream.println("\t\tswitch (i) {");<BR> 153 for (int i=0; i<methods length; i++) {<BR> 154 stream.println("\t\t\tcase " + i + " ";<BR> 155 stream.println("\t\t\t\t((" + shortClassName + ")agent) " + methods[i] + "();");<BR> 156 stream.println("\t\t\t\tbreak;");<BR> 157 }<BR> 158 stream.println("\t\t\tdefault ")<BR> 159 stream.println("\t\t\t\tthrow new IllegalAccessException(\"Method \" + i + \" out of range \");");<BR> 160<BR> 161 // close the switch<BR> 162 stream.println("\t\t}");<BR> 163<BR> 164 // close the invoke method<BR> 165 stream.println("\t}");<BR> 166 stream.println(" ");<BR> 167<BR> 168 // now the getMethods method<BR> 169 stream.println("\tpublic String[] getMethods() {");<BR> 170 stream.println("\t\treturn methods;");<BR> 171 // close the getMethods method<BR> 172 stream.println("\t}");<BR> 173<BR> 174 // close the class definition<BR> 175 strean.println("}");<BR> 176 }<BR> 177<BR> 178 static String[] findAgentMethods(String agentClassName) throws ClassNotFound {<BR> 179 ClassDeclaration classDecl = new ClassDeclaration(Identifier.lookup(agentClassName));<BR&g t; 180 BatchEnvironment env = new BatchEnvironment(new ClassPath(System.getProperty("java.class.pat)<BR> )));<BR> 181 ClassDefinition classDef = classDecl getClassDefinition(env);<BR> 182 Vector agentMethods = new Vector();<BR> 183<BR> 184 FieldDefinition fieldDef = classDef.getFirstField();<BR> 185 while (fieldDef != null) {<BR> 186 if (fieldDef.isMethod() && !fieldDef.isConstructor() && fieldDef.isPublic()) {<BR> 187 Type argTypes[] = fieldDef.getType() .getArgumentTypes(); 188 if (argTypes.length == 0) {<BR> 189 if (fieldDef.getType() .getReturnType() == Type.tVoid) {<BR> 190 agentMethods.addElement(fieldDef.getName() toString());<BR> 191 }<BR> 192 }<BR> 193 }<BR> 194 fieldDef = fieldDef getNextField();<BR> 195 }<BR> 196<BR> 197 //turn it into an array<BR> 198 String[] array = new String[agentMethods size()];<BR> 199 for (int i=0; i<agentMethods.size(); i++) {<BR> 200 array[i] = (String)agentMethods elementAt(i);<BR> 201 }<BR> 202<BR> 203 return array;<BR> 204 }<BR> 205<BR> 206 static void compileSkel(String skelFileName) {<BR> 207 Main compiler = new Main(System.out, "javac");<BR> 208 String[] params = new String[1];<BR> 209 params[0] = skelFileName;<BR> 210 if (!compiler.compile(params)) {<BR> 211 System.err println(StringResources COMPILE~ERROR + skelFileName);<BR> 212 }<BR> 213 }<BR> 214 } 1 /* $Header. /com/meitca/hsl/zonesjagents/skeleton/StringResources.java 3 11/11/96 5:16p Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory,<BR> 4 * Mitsubishi Electric Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTON<BR> 10 * The String Resources for the skeleton package<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/skeleton/StringResources java $<BR> 13 *<BR> 14 * 3 11/11/96 5:16p Billp<BR> 15 * Made correction to company name<BR> 16 *<BR> 17 * 2 9/12/96 11:00a Walsh<BR> 18 * Automatically compile the skeleton file<BR> 19 *<BR> 20 * 1 9/06/96 4:54p Walsh<BR> 21 *<BR> 22 */<BR> 23 package com.meitca.hsl zonesjagents.skeleton;<BR> 24<BR> 25 class StringResources [<BR> 26<BR> 27 // Generator java<BR> 28 public static String USAGE = "Usage generator agentclassname"<BR> 29 public static String NO~AGENT = "generator You must specify an agent class name ";<BR> 30 public static String TOO~MANY = "generator Too many parameters specified.";<BR> 31 public static String NOT~FOUND = "generator Agent class not found -- ";<BR> 32 public static String IO~ERROR = "generator IO error while attempting to write the skeleton file -- ";<BR> 33 public static String COMPILE~ERROR = "generator: Anb error while attempting to compile the skeleton file --<BR> 34 } Mitsubishi Electric ITA Patent Disclosure for Dynamic Synchronous Collaboration Framework for Mobile Agents November 12, 1996 Horizon Systems Laboratory Mitsubishi Electric ITA 1432 Main Street Waltham, MA 02154 Patent Disclosure for Dynamic Synchronous Collaboration Framework for Mobile Agents 1. Introduction This document serves as a patent disclosure on the invention entitledDynamic Synchronous Collaboration Framework for Mobile Agents. This document includes a discussion of: prior art. problems with prior art. details oi the invention. and improvements ol this inventioli over prior art.

2. Prior Art "Agent" is one of the most overused terms in the software industry today. Although the term may be used in a wide variety of contexts, softawre Agents can be classified into two major categories: Intelligent Agents and Mobile Agents. Althouggh the two differ in scope and capabilities, both types of Agents are able to perform work asynchronously and autonomously on behalf of their owners. Intelligent Agents are endowed with some degree of rcasoning and learned behavior and may make decisions on behalf of their owners. Thcse Agents are generally stationary and execute on a single system. Mobile Agents. on the other hand, may be transported across nodes in a network. performing computations as they migrate.

The original concept for agents stems from the Artificial Intelligence community. The behavior of Intelligent Agents may be determined by programming or by dccisions made by the Agents on behalf of their owners. As an example. an Intelligent Agent may scarch a database for unusual outdoor scenery, making its own decisions as to wheter or not each scene meets the specified criteria.

Intelligent Agents generally employ both synchronous and synchronous modes of communication. Agent communication may take the form of queries or collaborative computations. In the realm of Agent computing collaboration may be defined as "the coordination of the computations of multiple Agents to achieve a desired result" (e.g., to solve a complex problem). Collaboration often results from discovcry (i.c. the need to collaborale wilh a specific Agent regarding a cerlain subject is not known a priori, but is, rather. determined as a result of the Agent's Luniputations.

Both tlic interaction between these Agents and ihe context in which tlley execute must bc formally specified. Standardization has not yet been achieved for these objectives.

1-lowever, the prevalent mcans for accomplishing these results is via implementing a user model and specifying queries and assertions by using a knowledge representation language, the most popular of which is currently Knowledge Query Manipulation Language (KQML), and by developing Ontologies, or vocabularies of common terms to be utilized by interacting Agents. KQML is comprised of both a language, with a syntax unlike procedural of or object-oriented languages. and a communications protocol. An Ontology is defined as "an explicit specification of a conceptualization" The syntax and semantics of an Ontology are generally extensions of a first-order predicate calculus. typically the Knowledge Interface Format (KIF).

The combination ol' KQML. KIF. and Ontology development is a complex task. Some implementations utilizing these mechanisms are being developed in the Artificial Intelligence community. But this approach has not caught on in other software applications.

In contrast Lo Intelligent Agents Mobile Agents are usually explicitly programmed to accomplish a specific task. As an example. a Mobile Agent could migrate to travel agencies on the World Wide Wcb and detennine the lowest cost air fare between two cities. In this casc. there is llO need for learned behavior or complex rcasoning.

However, the amount of information accessible on distributed systems, including databases. the Internet and Intrancts. is growing at a staggering pace and much of it is available in incompatible storage formats. The need to filtcr information and make decisions based on its content is increasing, and with it. the need for increased collaboration among Mobile Agents.

The need for collaboration is illustrated by extending the above travel agency example. A Mobile Agent may need to clone itself and instruct each of its counterparts to migrate to a different travel agency site Lo obtain the best package for a trip to one or more ski resorts meeting certain parameters, including air free, lodging, meals. lift tickets, and car rental.

Furthermore, the information may, itself, be stored in different formats (database, etc.). necessitating some amount of filtering and data reformatting. Once the Agents have obtained their information, they need to collaborate with each other to correlate their results and determine the best package available at each resort for diferent travel dates and the overall best deal.

Mobile agents are evolving to include increased intelligence and collaboration. Some research organizations have begun incorporating KQML and Ontologies into Mobile Agent implementations, while other utilize different knowledge representation languages to implement Agent collllllunication. Still, o:t1ers use proprietaiy object languages.

.3,. Problems with Prior Art the KQML/Ontology mechanism and other knowledge representation languages are ill- suited for general-purposes software applications. They require programmers to learn multiple languages to formally specify communications and to develop complex dictionaries of terms - a task that is currently ill-defined. The knowledge representation languages are also extremely unlike the procedural and object-oriented languages utilized in building business and general-purpose software applications.

The need to support asynchronous collaboration adds significant complexity t() Agent systems implemented via knowledge representation languages (e.g. KQML,) and Ontologies. Furthermore. there exists a class of Mobile Agents which solely require synchronous collaboration, e.g., the travel agency application described above. This type of Agent application essentially subdivides a larger task into smaller pieces and creates Agents to migrate throughout the nclwork to accomplish it. For these Agents, there is no benefit in the added complexity of coding in multiple languages and developing Ontologies, nor in the support for asynchr(onoos communication. A synchronous collaboration framework in tlic Agent's laioguage is the best mcans for these Agents to coordinate their results and implement adaptive behavior.

4. Some Details of the Invention The dynamic synchronous collaboration framework utilizes a distributed synchronization point plus object-oriented abstractions to provide synchronous collaboration for Mobile Agents in a distributed system. The framework simplifies collaboration for applications which subdivide a complcx problem into several picccs and larm out the work to multiple Mobile Agents.

This framework enables Mobile Agents within an application to perform synchronous collaboration with one or more affiliated Agents in the application's native language. This is accomplished via theAgent Group abstraction. Agents wishing to collaborate with each other must belong to one (or no ore) ol the same Agent Groups. The fundamental principle behind Agent Group collaboration is (hat Mobile Agents performing sub-computations, possibly on different nodcs in a distributed system, will need to periodically correlate their results. and potentially adapt thcir behavior basel on the results of the correlation. The Agent Group acts as a distributed synchronization point for this type of synchronous collaboration.

The dynamic nature of the Agent Group enables Agents to join and leave the group at will. Hence no a priori knowledge ol the actual Agents comprising a group is required and group membership may change over time.

A distributed name space maintains a reference to each Agent Group. Hence. Agent Groups may he located via their cniiy tlie name space. When an Agent Group is created. it is automatically added to tbe name space.

The Agent Group's primary rcsponsibility is (o facilitate synchronous collaboration for Mobile Agents. 1-lowever. it also serves as a central point for distributing asynchronous eventS to Agents in the group. A typical event may he tlic termination of a particular Agent. As a sitle effect, the Agent Group also tracks the travels of its constituent Agents throughout the network.

The travel agency example illustrates the function of Agent GRoups. The problem to be solved can be stated as follows: A user wishes to determine the best package for a trip to a ski resort. The Agent must determine the best travel date and time (e.g. any week in February starting on a Saturday, and flying before noon) and loadging must meet certain criteria (e.g., a two-bedroom condominium). The trip includes all expenses (e.g., air fare. lodging, mcals, transportation. and lift tickets). The user ulay also specify several possible travel destinations.

This applicatioii is composed of multiple Agents -- each is responsible for querying one or more data sources (in perhaps different formats) for specific information (e.g., searching a particluar travel agency's database of promotional trips to determine if any meet the criteria specified by the user.) Some Agents may query Icgacy database systems. whereas others may search ODBC compliant database. (The actual mechanisms for handling different data sources is beyond the scope of this invention.) Before the Agents are transported throughout the network they join a new Agent Group.

The Agent Group tracks its Agents travels throughout tile network. At any point, an Agent may be in one of several states. Figure 1 depicts three Agents in an Agent Group performing computations and one Agent in-transit betwecn nodes.

At diffrent points during their migration. Agents may wish to correlate then results, and potentially change their migration plans of behavior. Suppose each Agent migrates to a local travel agency. Before migrating to travel agencies iii different cities, the Agents may wish to correlate their results and potentially adjust their behavior. Suppose one of the Agents determines that a particular ski resort, say Taos, has no two-bedroom condominiums available during February. The Agent in the group may wish to drop all further queries about trips to Taos.

Agent Group collaboration is implemented via a distributed synchronization point (also known as a collaboration point) and a software routine to analyze the results of each Agent's computalion. Tlic Agent Group abstraction provides the distributed synchronization point. Each application need only provide its own software method to analyze (he results and potentially allow each Agent to atlapt its behavior.

The distributed synchronization scheme requires that each Agent arrive at the collaboration point before collaboration may commcncc. I-lencc, it is best suited to applications that subdivide a complex problem into many sub-tasks that need to conclatc their results. As each Agent arrives at the collaboration point. it posts the results of its computations to the Agent Group. and blocks until all the other Agents in the group arrive. Figure 2 depicts one Agent in the group waiting to collaborate while three othcrs are still performing computations.

The Agent Group collects tlic results of each Agent's sub-computation. When all Agents have arrived at the collaboration point. as shown in Figure 3, the Agent Group notifies them that collaboration may commence. When it unblocks the waiting Agents, the Agent Group passes tl0e collected results t() each Agent. Each Agent then calls the application- specific method to analy;'.e tlte results and potentially adapt its behavior. Figure 4 shows that all Agents have arrived at the collaboration point and are now in the analysis stage.

The synchronous collaboration framework supports both parallel and serialized collaboration analysis. Figure 4 depicts a parallel analysis implementation; Figure 5 illustrates a serialized collaboration analysis. in which one Agent is in the Analysis statc. while the rest remain waiting in the Collaborate state.

The distributed collaboration point may be implemented via an object transport or by an RPC mechanism. It may also be implemented in any procedural or object-oriented language. Object-oriented languages simplify tlie implementation. as the application need only subclass the Agent Group abstraction and provide a concrete method to analyze the results and potentially adapt the Agent's future behavior.

The Agent Group ensures that all Agents in the group arrive at the synchronization point by tracking the Agent's migration through the network. In the current implementation. as part of a mobile Agent system. a server (known as the Conduit Scrvcr) on each node manages the Agent' 5 migration and informs each of its Agent Groups when the Agent arrives atid departs. Should all Agent fail t) arrive at a ci'.! collaboration point in a pre- determined, configurable length of time. the Agent Group will "ping" the Agent by sending a message to ensure that it is still alive, as shown in Figure 6. (In the current implementation, this is performed via the Conduit Server on the node where the Agent is executing.) II the Agent fails to respond to tloc ping, the Agent Group notifies the other Incmbcrs of the group by distributing a Collaboration Failed asynchronous event to them that indicates that a particular Agent is not responding. The Agents may then indicate whether or not they wish to proceed with tloe collaboration. Figure 7 depicts the Agent Group's distribution of a Collaboration Failcd event followed by the remaining Agents indicating that they wish to conlinue the collaboration Alternatively. the Agents could decide to abort the collaboration.

The Agent Group also implements deadlock detection by means of the time-out mechanism and Agent ping described above. The ping actually returns the state of the Agent in question (via the Conduit Server). if the Agent is already in the Collaborate state but has not arrived at this collaboration point. a deadlock has occurred. This is shown in Figure 8. In the case, the Agent Group will abort the collaboration and notify the Agents in the group of the deadlock by sending them a Deadlock Event, as shown in Figure 9.

Note that since Agent Group collaboration is designed for closely coordinated Agents, the existence of a deadlock is generally a result of a programming error. Hence, the Agent Group does not need to cmploy a more sophisticated scheme ior deadlock detection or avoidancc.

Agent Groups provide reliability by saving the state of each Agent in the group to persistent storage. if the Agent Group should terminate unexpectedly, it is restarted and reads the state of the group members Irom persistent storage. The Agent Group's restart is transparent to the Agents. They actually communicate with an Agent Group Proxy (instead of an Agent Group), which shiclds them from Agent Group failures.

Figure 11 illustrates the flow of a typical collaborating Mobile Agent. Each Agent creates an Agent Group Peroxy for each Agent group it wishes to joint. The proxy's primary responsibility is to maintain an active connection to its associated Agent Group and to rc- establish the connection or re-create the Agent Group. as ncedcd. during Agent Group failures.

When the Agent Group Proxy is initialized, it establishes a connection with the appropriate Agent Group. it first attempts to find a reference to il in tile name spacc. if this fails, it creates the Agent Group and enters a reference to it into the name spacc. The algorithm guarantees the atomicity Of this operation.

After the proxy has crcatcd the Agent Group or established a connection t() it, the Agent continues its computations and migrations. Eventually, it may attempt to collaborate its results. This is accomplished by means of the Agent Group Proxy. If the Agent Group has failed or is in a unknown state, the proxy will be unable to contact it. If this occurs, the Agent Group Proxy retries the communication. If, at this point, the proxy is still unable to communicate with the Agent Group, it recreates it and updates Ihe name space with a reference to the new Agent Group. The re-creation of the Agent Group is scrializcd to prevent multiple Agent Group Proxies from simultaneously doing so. If a proxy determines that the Agent Group is in the process nf being n-created. it simply waits until it can find a reference to the new group in the name space. One the Agent GRoup has been re-created. the proxy retries the collaboration.

As mentioned earlier. Agent Groups provide a distributed events mechanism in addition to the synchronous collaboration framework. The distributed events mechanism enables the Agent Group to notify members of the group of outstanding events, such as the termination ol an Agent. of the detection ul a collaboration deadlock. Agents may build on this mechanism to forward application-generated events to other nicm bcrs in the group Hence. if an Agent catches ail application-generated exception it may notify the other Agents in the group before terminating. Figure 10 illustrates how the Agent Group forwards an Exception Event, generated by one of its Agents, to the rest to the group.

Currently, the Agent Group handles distributed events by maintaining a (possibly remote) reference to an event queue associated with each Agent. The Agent Group forwards all events it receives to the other members of the group by enqueuing it. The Agent Group may be implemented without a remote referencing capability. but this would add significant complexity. In the curreilt implementation, each Agent contains an events thread which is respoi)sible for dequeuing the event and calling the application-specific event handler. (This thread could easily be a process, if threads were not available.) In addition to forwarding events to members of the group. the Agent Group may generate its own events and distribute those to the group members. As an example, the Agent Group distributes a Deadlock Event to the group members when its detects a deadlock situation. as illustrated in Figure 9.

As mentioned earlier. Agent Groups track the migrations of their constituent Agents. with help from the Conduit Server (in the current implementation), If an Agent is in transit when the Agent Group is forwarding events. il queues the events locally. as shown in Figure 10. Once the Agent OlTives at its destillatioll. it notifies the Agent Group. via the Conduit Server. The Agent Group tloen flushes the events it stored locally for that Agent.

Agent Groups implement varying levels of persistence, as defined by the actual configuration. Memberships and Agent slates are updated infrewuently, so they are <BR> <BR> generally written to persistent storage. However. local queues maintained on behalf 1' of in- transit Agents may also be saved in persistent storage, if desired.

Implementation of the Agent Group in an object.oriented language enables applications to extend its functionality. it required, by subclassing tloe Agent Group object.

5. Benefits of the invention The work described above provides several benefits. It greatly simplifies the implementation of synchronous collaborating Mobile Agents, especially for applications that subdivide a complex task into a scrics of related sub-tasks. There is no need for application developers to learn knowledge query representation languages. such as KQML, or to develop complex Ontologies. The dynamic synchronous collaboration framework provides a natural programmatic implementation that may be programmed in a number of languages. An added benefit of this scheme is that collaboration is implemented as part of the application. programmed in the same language as the rest of the application. The current implementation in on object-oriented language (Java) also enables the technology to be easily extended so that more complex intelligence schemes may be supported.

Agent Groups facilitate Mobile Agent tracking and may also be queried by tools that monitor Agents. In addition, collaboration may be performed trough discovery, as with many knowledge representation languages.

Agent Groups also offer reliability by providing persistent Agent Group membership and Agent state information. Furhermore, Agent Group Proxies shield Agents from the effects of Agent Group failures. They detect an Agent Group's failure and atitoniatically restart the failed Agent Group (which then restores the state of its membership from persistent storage) and retry the current operation (e.g.. collaboration) The algorithm also guarantees the atomicity ol Agent Group creation and re-creation.

An Agent Group also detects Agent failures and deadlocks and forwardws this information to the other members of the group via its distributed events mechanism. Furthermore, this mechanism allows Mobile Agents to asynchronously notify associated Agents of relevant events, such as the catching ((f an exception.

Implementation of Agent Groups in an object-oriented language also enables additional application-specific functionality to be easily added via inheritance and polymorphism.

6. Figures I (olc S < (lom pu te Acnt (Notle A) I'enl (Node I) :cnr(;roup (NodL ) j T I('ompure F/ 7 I / Y In-lr;lllsll (omr)txlc r Acnl (Nodc I)) Agent (Nodc I>) Figure I: Agents in Compute and In-transit State (:ompule Aenr (Node A) Acnt (Node II) I Agent (iroup (Node A) J - I Agelll (N,)dc (') !\L't'fl) (Node - Figure 2: Agents in Compute and Collaboration Wait States (oii;jhor;it' ('.II,iIxaL' (ollaheriltc X < (ollabor:llc Agent (Node A) Agc'it(NdeJ3) Agclll (iroup (Nodc /c) ,n;,l,or;lte (oiihor.'tte Agent (Nodc () Agent (Node D) Figure 3: Agents in Collaboration Wait State Axulysis <1 Anollysis Agent (Node A) \ / Agenl (Node 1)) l l Aclll (iroul) (Nodc A) Analysis | | Analysis Agelll (Node C?) Agent (Node 1)) Figure 4: Agents in Parallel Analysis State 1 Ageni (Node D) Agenl (Nodc A) \ / Agelll (Node 13) I l I Ageiii (il'O lp (Node A) ( ollab°mte 1v \~<3 Agellt (Nodc C) Agent (Node 1)) Ageiii (Node fl) Figure 5: One Agent in Serialized Analysis State, Others in Collaboration Wait State Agent (Notle A) Agent (Node 13) ('ollahorate Unkllowll i;iI)g l ItcSp(lSc )ri\)iiP)i?;\L1i (11 I Agent (iroup (Node A) l (>olìaborillc ( 'ollah()rillc Agent (Node (?) Agent (Node I)) Figure 6: Agent Group Pings Agent After Collaboration Times Out Agent (Node A) Agent (Node I)) ( 'ontinti'; Collaboratc Unkllown . ' (ollill)oriltioll ~ ('olhlhor;ltio i:,Ijlcd 1 1,,)1t.,1 1 vent M Are (k,urinuc (?ott'jlor'jtion ( 'otl;ihor,'itioi' (?onti'iuc Iriicd livca :oll:tbor;lte L1 Colìaborilte l l ('ollilborale Agent (Notlc(') Agent (Nodc I) Figure 7 Continued Collaboration Despite the Failure of An Agent to Respond Agent (Nodc A) Agent (Nodc 131 Agollt (Notle A) Agellt (Nodc () (ollabolate | | ( ollablar.lxc> | ('ollal)oriltc | | ('ollilhoril c L Agenr(iroop I (Node A) rllnbocrre GDII;jhofl'i(c (x,llahomre Agent (Node (') Agent (Node I)) Agent (Node D) Figure 8: Collaboration Deadlock (Part1) Agent (Node A) Agent (N),Ie 13) Agent (Nodc A) Agent (Node (') I:aile(l ('(Illill)ol-iltc ( ('ollill)orilte (:oll;tborarL I)c;ldlock I )e;dIoek invent iivcn( Agent Group I (Node A) Agent (group 2 (Node (,') ()e;tdi(k up2(Node() Deidloek i;vent event I oll:rbowte Tailed I:ililcd Collahorille Agent (Node (') Agent (Node I)) Agent (Node D) Figure 9: Collaboration Deadlock (Part2) Agent (Node A) Agent (Node (3) AjiL'nr (Nodo I)) Conipuic 1'i-tr;nsji f tr;lllsit t I lixccplion I:vent enr <roup (NodL ) Uueued1 I-xcepdon Ivcnr I I.uception ccprion I-vent cnl pure 7 rlixccglil,s 7 (ompute X l XCCptiOI) Agent (Node (?) Agent (Node I)) Figure 10: Exception Propagation via Agent Group Distributed Events (?oinpute aìld Agent hlicl Ntigriltc w s '!I;tt'r;itc Hcsults ('re;ite Agent / / An.llyoc Rcslllts (iroup l'roxy Ye. I;'iIed No Agent Group i?nnutjc,'jtjo? 1! None Sp;tce? 0 lo Agent Retries ( gcnl iroup tJpd;ite Notte I)pdate Ni"ll,: / n Space litilcd No v Yes |m; llc Af cnt (;roup W Ilpdale Nime Space Figure 11: A Typical Agent Application Mitshubishi Electric ITA Design Specification for Java Agent Coordination Version 0.2 November 12, 1996 Horizon Systems Laboratory Mitsubishi Electric ITA 1432 Main Street Waltham, MA 02154 Desing Specification for Java Agent Coordination Version 0.2' 1. Introduction Java agents have the capability of coordinating their activities. This coordination takes two mam forms: syncronized collaboration and asynchronous notifications. These modes of communication complement each other and their implementations are related.

Collaboration The collaboration paradigm is implemented as follows: . multiple agents perform computations at different nodes in the network; . after performing all or a subset of their operations, agents wait at a distributed syncronization point until all agents have "arrived"; . agents coordinate by potentially serialized execution of a synchronized method.

Coodination can take the form of performing computations on intermediate results and/or updating agent itineraries.

Notification The notification scheme uses a distributed events mechanism to communicate agent state changes that occur asynchronously. It is mainly utilized for distributed exception handling, but may also be used to notify related agents of events, such as another's termination.

As described above, agent coordination utilizes distributed synchronization and event handling. However, Java possesses neither of these. Actually, its syncronization primitives are limited to critical sections on a single system and a notification scheme that can only handle a single type of event. Hence, a great deal of the complexity in the task of agent coordination is comprised of implementing mechanisms to overcome Java's unsuitability for distributed processing. These mechanisms are described in the remainder of this document, along yith the new objects that implement them Revision History: 07/26/96 Version 0.1 Initial revision.

11/12/96 Version 0.2 Major changes to Notifications and Exceptions and Collaboration sections to reflect actual implementation. Removed Events section.

2 Synchronization As mentioned above, agent coordination requires distributed syncronization mechanisms, such as locks and events. Since Java does not provide any distributed locking, we are faced with the following choice: 1. Utilize a centralized locking a scheme.

2. Ilevelop our own distributed locking paradigms.

3. Use Java's native methods to interface with the operating system's synchronization primitives.

The latter choice is unacceptable because it compromises the portabilily ol our agent infrastructure, whereas the first option may potentially introduce considerable network overhead. The second alternative also requires signifcant development effort even to implement a well-known solution to the problem.

In the interest of expediency (as required by the tightness of our schedule), the initial Java agent infrastructure utilizes RMI to implement a centralized locking scheme. Locking is implemented via method invocations on a potentially remote object (called an AgentGroup.

See Section 3 for details.) Agent coordination is implemented by (remote) invocations on a method which requires sychronized access. (See Section 3.) 3. CollaboratorAgent and AgentGroup Agents that may wish to collaborate their results subclass CollaboratorAgent, an abstract, class derived from Agent. CollaboratorAgent contains a minimum of two threads - one to perform computation and to travel and another to handle asynchronous event notifications.

Applications that contain collaborating agents subclass. CollaboratorAgent and, of course, these derived classes may implement several computation threads.

Each collaborating agent belongs to one or more agent groups, which are described by Agent Group objects. Agent Group is actualy a distributed RMI object. AgentGroup defines the interface; AgentGroupImpl, an abstract base class derived from PersistentEventGroupImpl, provides the implementation. (See Design Specification for Distributed Java Events for a description of PersistentEventGroupImpl.) An AgentGroup is essentially a unit of coordination. Hence agents may coordinate with all the other agents in an AgentGroup. They may also create new AgentGroups on demand, and join and leave groups at will. (In practice, AgentGroup must be subclassed to implement agent collaboration. However, this document does not distinguish between the base class and ils derived classed and refers lo them collectively as AgentGroups.) An AgentGroup is an object that is essentially shared among the members of an agent coordination group. It is owned by the Agent that initially creates the group (an agent group is created by instantiating AgentGroup) and accessed via a potentially remote RMI reference.

The relationship between CollaboratorAgent and AgentGroup is similar to that of Thread and ThreadGroup: A ThreadGroup maintains references to the Threads composing the group; an AgentGroup maintains a similar list of its CollaboratorAgents. Both ThreadGroups aitd Ageiit(iroups form a hierarchy and each contains a reference to its parent group. Thread's constructors are either passed 1 reference to a ThreadGroup or they save a reference to die parent's Thread's group. Likewise, ColaboratorAgent's constructors may be passed one or more AgentGroups or s;ive a reference to AgentGroup of its parent, il' it exists.

However, there is one noticeable difference between the two types of groups. A Thread may only belong to one ThreadGroup at a time, whereas a CollaboratorAgent may simultaneously be a member of several AgentGroups, which constitute a hierarchy. Hence, Threads contain a reference to their associated ThreadGroup, but CollaboratorAgents maintain a list of references to their AgentGroups.

Support for multiple AgentGroups facilitates coordination among related groups of agents and also enables the creation of an AgentGroup hierarchy through which communication may be propagated. The pilot application may utilize multiple agent groups, as shown in Figure I.

This figure portrays an example of two AgentGroups: AgentGroup A consists of three agents - one on each LAN iii lie system, whercils AgentGroup B cont;iilis agents on multiple nodes on LAN 3. A distributed application running on a configuration such as this typically creates multiple AgentGroups when it needs to traverse the WAN. In this case,3 agents are created in AgentGroup A, one for each LAN. Once they arrive on a node, these agents clone themselves, creating more agents to be distributed across nodes on the LAN (e.g., AgentGroup B). This approach minimizez network traffic over the WAN and forms a multi- level hierarchy of AgentGroups. Agents in the intra-LAN groups (e.g., AgentGroup B)can communicate their results, which can then be coordinated with the inter-LAN group (i.e., AgentGroup A). o im u LAN 1 \WnN ,2/ , '\1AN X WAN B B m Fx AgentGnitip A gentGroup I,/ ¼L½y\\\AefliGrou B,' X Figure I: Multiple AgentGroups By default, RMI passes all local objects by copy. However, the above scheme requires that each Agent actually maintain (remote) references to its AgentGroups. Hence, the agent infrastructure overrides some of RMI's object serialization methods to generate the required references.

4. Notification and Exceptions Both asynchronous notification and collaboration are implemented via the associated AgentGroup object. The following description serves as an example of asynchronous notification bandling via distributed events. (See Design Specification for Distributed Java Events for more details on event handling.) 1. An agent catches an exception and wishes to notify the other members of the group.

2. The agent posts an AgentExceptionEvent to the AgentGroup via the group's postEvent method. The AgentExceptionalEvent indicates the type of exception that occurred.

3. The AgentGroup posts the AgentExceptionalEvent to the other agents in the group.

4. Each agent's Event Handler performs application-specific handling of the ExceptionEvent.

If the agent that caught the exception wishes to notify another associated Agent Group, it repeats the above procedure with the next AgentGroup object.

Occasionally, the Agent Group may generate events that it directly forwards to a member of the group (e.g., to "ping" it after it fails to arrive at a collaboration point) or others that it "multicasts" to its members (e.g., an Agent's failure to reply to a ping).

5. Collaboration Agent collaboration is more complicated than asynchronous notifications. It is implemented as follows: 1. An agent performs some computation and arrives at a synchronization point.

2. The agent performs a (remote) invocation of the AgentGroup's collaborate method, passing it an AgentStatus object.

3. If no collaboration is in-progress (i.e., this is the first agent that has requested collaboration, collaborate calls its syncronized beginCollaborate method, which initializes the number of agents to wait for before collaboration may begin (i.e., n-1 for an n-agent group.) (Race conditions are handled by checking if the agent count has been initialized (i.e., it is non-zero) befor continuing. A race implies that two agents are attempting to initiate the same collaboration. Otherwise the application is semantically incorrect.) This routine saves the requesting agent's unique II (obtained from the AgentStatus object) and starts a collaboration timer (with sufficient time for agents to arrive across the WAN) by passing a configurable time-out value to the AgentGroup's wait method.

4. Otherwise (i.e., if a collaboration is in progress), collaborate calls the synchronized decrementCollaborate method to add the requesting agent's unique ID to the list of agents arriving at the collaboration point and to decrement the waiting agent counter. If the counter is non-zero, this method blocks with no time-out value. Otherwise, the Agent Group awakens the other threads waiting for collaboration to commence.

5. If the timer expires, all agents did not arrive at the collaboration point in time. This may occur because an agent received an uncaught exception and terminated unexpectedly or because a deadlock condition exists. (Since agents may belong to multiple groups, overlapping collaborations could result in deadlock. Howewer, a properly coded application will not generate deadlocks because the collaboration points must be known a prori and must be executed in the same order among collaborating agents, i.e., collaboration must first handled at the leaf Agent Group and propageted up the hierarchy.) If a time-out occurs, the Agent Group thread initiating the collaboration (on behalf of its associated CollaboratorAgent) is awakened and performs the following: . It calls the AgentGroup's checkCollaborate method which returns the collaboration state (either CollaborationSucceded or CollaborationFailed, depending on the value of the waiting agent count).

. If the collaboration failed, the collaborate method calls recoverCollaborate This method attempts to communicate with the agents that did not arrive at the collaboration point by "pinging" them. (It determines these agents by comparing the list of arrived agents with (tic group membership.) The ping is actually performed via a message to the Conduit Server on ilie tioxle where each agent was lasl known to be executing. If the agents are located and any of them is in the Collaborate state and but has not arrived at this collaboration point, a collaboration deadlock has occured and the collaboration state is set to CollaborationDeadlock. If any of the agents cannot be located, the collaboration state is set to CollaborationFailed.

Otherwise, it is set to CollaborationRetry and the AgentGroup thread retries the collaboration up to a configurable number of times (after which the state will be set to CollaborationFailed if the collaboration still times out.) . The initiating Agent Group thread wakes up the other blocked threads by calling notifyAll on the Agent Group.

6. Once all the collaborating Agent Group threads have been awakened, (either because the counter has dropped to 0 or a time-out occurred), they call the Agent Group's checkCollaborate method. If this method returns a state other the CollaborationSucceded, each thread returns the appropriate exception (i.e., either CollaborationFailedException or CollaborationDeadlockException) to its invoking CollaboratorAgent.

7. If the collaboration state is CollaborationSucceded, collaboration commences by executing a potentially synchronized application-specific method, analyzeResults, to perform the collaboration. analyzeResults is an abstract AgentGroup method that must be implemented by derived classes to perform application-specific collaboration. As a result of collaboration, agent itineraries may be updated.

8. As each thread completes its collaboration, it replies to the remote collaborate invocation, passing any state specified by the implementation, (e.g., updated itineraries).

9. The agents then continue execution on their current mode and travel as required by their itincraries.

As described above, collaboration requires complex mccllallisllls. However, most of these are necessitated by the limited synchronization primitives provided by Java.

Mitsubishi Electric ITA Design Specification for Distributed Java Events Version 0.2 November 12, 1996 Horizon Systems Laboratory Mitsubishi Electric ITA 1432 Main Street Waltham, MA 02154 Design Specification for Distributed Java Events Version ().2 1. Introduction This document describes a general-purpose solution to distributed event management.

2. Overview This section provides a high-level description of the object that implement the distributed events framework.

2.1. Objects Events Events are described by classes that derive from EventType Each EventType object includes: a unique ID (a String) generated by the constructiors and a description of the event (a String) optionally passed to the constructors.

Event Handler The EventHandler interface specifies the handleEvent() method which implements an Event Handler. Each application must provide its own Event Handler to perform application- specific event management.

Event Notification The EventPost interface specifies the postEvent() method which implements event notification. Several of the classes described below implement this interface.

Event Queue Any object receiving notification of events must own an livent Queue and an associated threared that manages the queue. The Event Queue's constructor is passed an EventHandler stub. It instantiates an EventQueueThread (a protected class derived from Thread) to manage the queue and passes the EventHandler stub to its constructor. The EventQueueThread's run() method removes events from Ille queue and calls Ihe handleEvent() method.

Reversion History: 09/26/96 Version 0.1 Initial revision.

11/12/96 Version 0.2 Expanded discussion of Event Manager and Event Group. Added Reliability Features and Garbage Colleclion seclions.

An Event Queue is a distributed RMI object. EventQueueImpl implements the EventPost interface by appending the specified EventType object to the queue and calling the associated EventQueueThread's notify() method. This action wakes up the EventQueueThread (if it was blocked). The thread then proceeds to dequeue each pending event and pass it to the handleEvent() method Event Manager The Event Mananger handles the registration, posting, and notification of events. When objects request notification of specific event types, they must pass the Event Manager a reference to their EventPost interface. The Event Maneger saves the reference in a hash table that it uses to map event types to their notification requests. When an object posts an event (via the Event Manager's postEvent() method), the Event Manager obtains the list of objects to notify from the hash table and calls each of their postEvent() methods.

The Event Maneger also maintains a list of objects that have requested notification of all events. Whenever it receives an event, the Event Manager also forwards it to these objects, by calling each of their postEvent() methods.

EventManager is an RMI distributed object. EventManager describes the interface, whereas EventManagerImpl provides the implementation. EventManager defines methods to manage event registrations (e.g., add and delete registrations).

EventManagerImpl also implements the EventPost interface. Its postEvent() method is passed an event from its originator and notifies the recipients of the event by invoking their postEvent() methods.

At most one Event Manager runs on each node in the Agent system. A reference to it can be obtained via the RMI Registry.

Event Group A group of objects interesed in a common set of notifications may form an Event Group.

EventGroup is a distributed RMI bject: EventGroup defines the interface; EventGroupImpl consists of the implementation. EventGroup defines methods that manage the group (e.g., add and remove members).

Whereas the Event Manager filters posted events on behalf of its clients, forwarding them only the events they requested, the Event Group performs no filtering. EventGroupImpl implements the EventPost interface. However, its postEvent() method forwards each event it receives to every member of the group (by calling their postEvent() methods).

In practice, Event Groups should be used sparingly because they could allow an abusive application to generate unwanted notifications. The Agent framework does utilize this mechanism, but it verifies that all events generted by a group member and it only utilizes the Event Group for some well-known events, such as the termination of an Agent.

Each Event Group is identified by a unique name either passed to its constructor or assigned by it. Objects may obtain a handle to a particular Event Group by presenting the RMI registry with this unique name.

2.2. Reliability Features The Distributed Events framework incorporates several reliability features. These generally take the form persistent state and proxy objects.

Event Manager The Distributed Events framework shields objects from zhe effects of Event Manager failures in two ways: . by saving its state (i.e., event registrations) to persistent storage, and . by encapsulating its functionality in a proxy object.

The Event Manager saves the following items in the persistent store: . the hash table mapping specific event types to the objects registered to receive them and the list of objects to he notified 1)1 all events Each time an object either registers or "unregisters" its intrest in receiving any (or all) events, the Event Manager writes the updated event registrations (i.e., either the bash table or the list of objects, but not both) to persistent storage via the Persistent Storage Manager.

These are fairly infrequent operations, so the performance impact of this process should be negligible. (See Design Specification for Java Agent Persistance Package for details on the Persistent Store Manager.) Whenever the Event Manager is started, its initialization code attempts to recover any existing event registrations from persistent storage. Hence, registrations are not lost when tlie event Manager fails.

In addition, the Event Manager Proxy also prevents Objects from experiencing the effects of Event Manager failures. It acts as a wrapper object for the Event Maneger. Each Object wishing to communicate when the Event Manager must first create an EventManagerProxy object. The proxy obtains a reference to the Event Manager via the RMI Registry. If, at any point, the proxy is unable to communicate with the Event Manager, it will attempt to obtain a new reference from the registry. It will retry this operation several times before throwing an exception.

Furthermore, if the Event Manager should fail, it will automatically be re-started by the Java Agent System Persistent Event Group The Distributed Events framework provides a general-purpose implementation or Event Groups (i.e., EventGoups), as described above. However, it also provides a reliable implementation or Event Groups: Persistent Event Groups. Persistent Event Group is a distributed RMI object that extends EventGroup: the interface is defined by PersistentEventGroup and the implamentation is provided by PersistentEventGrouplmpt, a subclass of EventGroupImpl Persistent Event Group utilizes persistent storage in much the same manner as the Event Manager. Whenever an Object joins or leaves the group, it saves a reference to It in persistent storage.

Each Persistent Event Group is also encapsulated in a proxy object: PersistentEventGroupProxy. This proxy operates somewhat differently than the Event Manager Proxy, depending ott Ilow il is constructed. In some cases, it will attempt to locate a named l'crslstenl Event (;roup io the RMI registry. If a name is not supplied to the constructor, il will create a new Persistent Event Group and register it.

Since Event Groups are temporary objects, unlike the Event Manger, which is a persistent server, their proxies cannot expect their associated Persistent Even Groups to be automatically re-started upon failure. Hence, a proxy may re-create the group if it is unable to obtain a reference to it after sufficient retries.

This, however, introduces a race condition wherein multiple proxy objects may simultaneously attempt to re-create the Persistent Event Group. This is handled by the following mechanism: . If the owner of the Persistent Event Group detects the failure, it re-creates the group. (The owner is defined as the proxy that initially created the group).

. If the owner does not detect the failure in a configurable length of time, other proxies may attempt to re-create it.

. The Persistent Event Group is re-created via the following steps: . Attempt to create a temporary binding in the RMI name space with a well-known name derived from the Persistent Event Group's unique name.

. If the binding does not return an AlreadyBoundException, proceed to re-create the PersistentEventGroup and then remove the temporary binding. (Otherwise, another proxy is re-creating it. So wait for its completion).

2.3. Garbage Collection Both the Event Manager and Event Group objects must be prepared to garbage collect state references. This simply performed by deleting any objects (i.e.,EventPost stubs) that it cannot communicate with. Hence their postEvent() methods handle garbage collection after notifying all interested objects of the event.

3. Changes to Agent Implementation CollaboratorAgent The CollaboratorAgent class contains a reference to an event queue (i.e., an EventQucueImpl object), which is installated by its constructors.

The Event Queue does not persist across an Agent's travels. Hence, its prepareForTransit() method flushes the queue and voids the Agent's reference to the queue before it travels. Its associted Agent (Groups save any events that occur while the Agent is in-transit. The completedTransport() method, called after the Agent arrives as its destination, constructs a new EventQueueImpl object and flushes any events saved by the associated Agent Groups while the Agent was in-transit.

AgentStatus The AgentStatus class contains a reference to the EventPost interface implemented by the CollaboratorAgent's Event Queue. It also contains an Agent's unique ID and current status.

Hence, it will serve as both an Event Queue and a status indicator.

AgenlGrouplmpl The AgentGroupImpl class derives from PersistentEventGroupImpl. Thus, it not only enables Agent collaboration, but also provides reliable group event handling.

As a result, Agent Groups may implement different levels of persistence: Group membership is always written to persistent storage, but quened events for m-transit agents will also be saved if the Agent Group's configuration allows it.

Occasionally, the Agent Group may generate events that it directly forwards to a member of the group (e.g., to "ping" it after it fails to arrive at a collaboration point) or others that it "multicasts" to its members (e.g., an Agent's failure to reply to a ping). Group members may also broadcast an event to the group (e.g., an Agent may inform the group it has encountered an exceptional condition).

AgenlEvenl The AgentEvent class is the superclass of all events generated by Agents. It includes the Agent's unique ID.

1 /* $Header /com/meitca/hsl zonesjagents/collaborate/AgentGroup java 5 10/01/96 3 40p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent Group distributed interface<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/collaborate/AgentGroup java $<BR> 13 *<BR> 14 * 5 10/01/93 3 40p Noemi<BR> 15 * Added some javadoc comments<BR> 16 *<BR> 17 * 4 9/10/96 5 07p Noemi<BR> 18 * Changed return value of collaborate method from a void to an Object<BR> 19 *<BR> 20 * 3 9/06/96 3 54p Noemi<BR> 21 * Added UpdateAgent method Changed argument to addAgent<BR> 22 *<BR> 23 * 2 8/30/96 4 24p Noemi<BR> 24 * Added addAgent, removeAgent, and getGroupSize methods<BR> 25 *<BR> 26 * 1 8/28/96 2:13p Noemi<BR> 27 * Basic AgentGroup functionality No support for remote groups or agent<BR> 28 * mobility yet<BR> 29 */<BR> 30<BR> 31 package com.meitca hsl zonesjagents collaborate;<BR> 32<BR> 33 import java.util NoSuchElementException;<BR> 34<BR> 35 import java.rmi.Remote;<BR> 36 import java rmi.RemoteException;<BR> 37<BR> 38<BR> 39 /**<BR> 40 * AgentGroup is an RMI distributed interface The actual<BR> 41 * implementation of agentGroup is handled by AgentGroup Impl<BR> 42 * This class provides RMI glue that enables Agents to invoke<BR> 43 * (remote) operations on an associate agent group<BR> 44 *<BR> 45 * Agents may belong to one or more agent coordination groups<BR> 46 * (AgentGroups), which act as focal points for distributed<BR> 47 * synchronous agent collaboration and asynchronous notification 48 * among members of the agent group<BR> 49 *<BR> 50 * @see Agent<BR> 51 * @see AgentGroupImpl<BR> 52 * @author Noemi Paciorek<BR> 53 */<BR> 54<BR> 55 public interface AgentGroup<BR> 56 extends Remote<BR> 57<BR> 58 // Instance methods<BR> 59 /**<BR> 60 * Collaboration interface<BR> 61 * @param result The result of the agent's computation<BR> 62 * @exception RemoteException If an error occurrs setting up network<BR> 63 * connections<BR> 64 * @exception AgentGroupException If the collaboration times out<BR> 65 * @return An Object that describes the result of collaboration<BR> 66 */<BR> 67 public Object collaborate(AgentResult result)<BR> 68 throws RemoteException AgentGroupException;<BR> 69<BR> 70 /**<BR> 71 * Adds an Agent to the group<BR> 72 * @param status The AgentStatus object that describes the Agent<BR> 73 * @exception RemoteException If an error occurrs setting up network<BR> 74 * connections<BR> 75 */<BR> 76 public void addAgent(AgentStatus status)<BR> 77 throws RemoteExceptior<BR> 78<BR> 79 /**<BR> 80 * Locates and removes the AgentStatus object containing the specified ID<BR> 81 * @param agentID An Agent's unique ID<BR> 82 * @exception RemoteException If an error occurrs setting up network<BR> 83 * connections<BR> 84 * @exception NoSuchElementException If the AgentStatus object does<BR> 85 * not exist<BR> 86 */<BR> 87 public void removeAgent(String agentID)<BR> 88 throws RemoteException, ArrayIndexOutOfBoundsException, NoSuchElementException,<BR> 89<BR> 90 /**<BR> 91 * Replaces the AgentStatus object for the specified ID.<BR> <P>92 * This method may be used to change an Agent's status, ID, or both.<BR> <P>93 * @param agentID An Agent's unique ID<BR> 94 * @param newStatus An AgentStatus object to replace the existing one.

95 * @exception RemoteException If an error occurrs setting up network<BR> 96 * connections<BR> 97 * @exception NoSuchElementException If the AgentStatus object does<BR> 98 * not exist<BR> 99 */<BR> 100 public void updateAgent(String agentID, AgentStatus status)<BR> 101 throws RemoteException, ArrayIndexOutOfBoundsException,NoSuchElementException;<BR > 102<BR> 103 /**<BR> 104 * Returns the number of Agents in the group<BR> 105 * @return The number of Agents in the group.<BR> <P>106 * @exception RemoteException If an error occurrs setting up network<BR> 107 * connections<BR> 108 */<BR> 109 public int getGroupSize()<BR> 110 throws RemoteException;<BR> 111<BR> 112 /*<BR> 113 * TURN ON LATER<BR> 114 *<BR> 115<BR> 116 public void agentException(String agentID, Exception type) throws RemoteException;<BR> 117<BR> 118 public void agentTermination(String agentID) throws RemoteException;<BR> 119<BR> 120 */<BR> 121<BR> 122 }<BR> 123 1 /* $Header: /com/meitca/hsl/zonesjagents/collaborate/AgentGroupException .java 2 10/01/96 3.41p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Agent Group exceptions<BR> 11 *<BR> 12 * $Log /com/meitca hsl/zonesjagents/collaborate/AgentGroupException java $<BR> 13 *<BR> 14 * 2 10/01/96 3 41p Noemi<BR> 15 * Added a protected default constructor and some javadoc comments<BR> 16 *<BR> 17 * 1 8/28/96 2 16p Noemi<BR> 18 * AgentGroup related exceptions<BR> 19 */<BR> 20<BR> 21 package com.meitca hsl zonesjagents collaborate,<BR> 22<BR> 23 import com.meitca hsl zonesjagents shared.Agent,<BR> 24<BR> 25 /**<BR> 26 * AgentGroupException defines exceptions that occur during<BR> 27 * AgentGroup operations<BR> 28 *<BR> 29 * @see Agent.<BR> <P>30 * @see AgentGroup<BR> 31 * @author Noemi Paciorek<BR> 32 */<BR> 33<BR> 34 public class AgentGroupException extends Exception {<BR> 35<BR> 36 //Constructors<BR> 37<BR> 38 /**<BR> 39 * Constructs an AgentGroupException<BR> 40 * @exception IllegalAccessException Whenever called.<BR> <P>41 */<BR> 42 protected AgentGroupException()<BR> 43 throws I legalAccessException {<BR> 44<BR> 45 System.out println("Default constructor called for AgentGroupException");<BR> 46 throw new I egalAccessException("AgentGroupException Default constructor");<BR> 47 } 48<BR> 49 /**<BR> 50 * Constructs an AgentGroupException<BR> 51 * @param type A String describing the exception<BR> 52 */<BR> 53 public AgentGr upException(String type) {<BR> 54 super (type)<BR> 55 }<BR> 56<BR> 57 } 1 /* $Header: /com/meitca/hsl/zonesjagents/collaborate/AgentGroupImpl java 7 10/0196 3 43p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 Thread.currentThread() stop();<BR> 8 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 9 *<BR> 10 * DESCRIPTION<BR> 11 * Agent Group distributed class<BR> 12 *<BR> 13 * $Log /com/meitca/hsl/zonesjagents/collaborate/AgentGroupImpl java $<BR> 14 *<BR> 15 * 7 10/01/96 3:43p Noemi<BR> 16 * Added javadoc comments<BR> 17 *<BR> 18 * 6 9/20/96 12:37p Noemi<BR> 19 * Added agentsWithStatus() method and some temporary retry logic to<BR> 20 * collaboarte()<BR> 21 *<BR> 22 * 5 9/10/96 5 05p Noemi<BR> 23 * Changed collaborate and analyzeResults methods to return an Object<BR> 24 *<BR> 25 * 4 9/06/96 3 53p Noemi<BR> 26 * Added removeAgent, updateAgent, and indexOfAgent methods Changed<BR> 27 * addAgent's argument to an AgentStatus object<BR> 28 *<BR> 29 * 3 9/04/96 3 14p Noemi<BR> 30 * Added getGroupName method<BR> 31 *<BR> 32 * 2 8/30/96 4 28p Noemi<BR> 33 * Turned on code in constructor and finalizer that registers and<BR> 34 * deregisters with the RMI name server<BR> 35 *<BR> 36 * 1 8/28/96 2 16p Noemi<BR> 37 * Basic synchronous agent collaboration functionality No support for<BR> 38 * remote groups, agent mobility, or asynchronous notifications<BR> 39 */<BR> 40<BR> 41 package com meitca hsl zonesjagents collaborate;<BR> 42<BR> 43 import java.util *<BR> 44 import java io *;<BR> 45<BR> 46 import java rmi server UnicastRemoteServer;<BR> 47 import java rmi RemoteException; 48 import java.rmi.Naming;<BR> 49 import java rmi.NotBoundException;<BR> 50<BR> 51 import java net InetAddress<BR> 52<BR> 53 /**<BR> 54 * AgentGroupImpl s an RMI distributed object This is a base class<BR> 55 * that implements the AgentGroup interfaces<BR> 56 *<BR> 57 * Agents may belong to one or more agent coordination groups<BR> 58 * (AgentGroups), which act as focal points for distributed<BR> 59 * synchronous agent collaboration and asynchronous notifications<BR> 60 * (e.g., exceptions) among members of the agent group<BR> 61 *<BR> 62 * @see Agent<BR> 63 * @see AgentGroup<BR> 64 * @author Noemi Packorek<BR> 65 */<BR> 66<BR> 67 abstract public class AgentGroupImpl<BR> 68 extends UnicastRemoteServer<BR> 69 implements AgentGroup {<BR> 70<BR> 71 // Constants<BR> 72 /**<BR> 73 * Default timeout for collaboration in ms<BR> 74 */<BR> 75 public static final long DEFAULT~TIMEOUT = 100000;<BR> 76 // public static final long DEFAULT~TIMEOUT = 5000;<BR> 77<BR> 78<BR> 79 // Class variables<BR> 80 protected static int groupID = 0,<BR> 81<BR> 82 // Instance variables<BR> 83 protected long timeout, // collaboration timeout in ms<BR> 84 protected String groupName; // name to register with RMI Name Server<BR> 85 protected Vector agentList; // Agent IDs of group members<BR> 86 protected Vector resultList; // results shared via collaborate<BR> 87 protected boolean collaborationInProgress;<BR> 88<BR> 89<BR> 90 //Constructors<BR> 91 /**<BR> 92 * Constructs an AgentGroupImpl object.<BR> <P>93 *<BR> 94 */ 95 public AgentGroupImpl()<BR> 96 throws RemoteException {<BR> 97 this(DEFAULT~TIMEOUT)<BR> 98 }<BR> 99<BR> 100 //*<BR> 101 * Constructs an AgentGroupsImpl object<BR> 102 * @param timeout The collaboration timeout in milliseconds<BR> 103 *<BR> 104 */<BR> 105<BR> 106 public AgentGroupImpl(long timeout)<BR> 107 throws RemoteException {<BR> 108<BR> 109 this timeout = (timeout > 0) ? timeout DEFAULT~TIMEOUT;<BR> 110 agentList = new Vector();<BR> 111 resultList = null;<BR> 112 collaborationInProgress = false;<BR> 113<BR> 114 /*<BR> 115 * Create a name to represent this instance of an agent group<BR> 116 * and register it with the RMI name service<BR> 117 */<BR> 118 groupName = "AgentGroup" + nextGroupID();<BR> 119 System out printIn("groupName = " + groupName);<BR> 120<BR> 121 try {<BR> 122 Naming rebind(groupName, this)<BR> 123 } catch (Exception e) {<BR> 124 System out printIn("AgentGroupImpl can't rebind " + e getMessage() );<BR> 125 e printStackTrace()<BR> 126 }<BR> 127 }<BR> 128<BR> 129<BR> 130 // Finalizer<BR> 131 protected void finalize()<BR> 132 throws Throwable (<BR> 133<BR> 134 System.out printIn("AgentGroupImpl Finalizer called");<BR> 135<BR> 136 // Remove this AgentGroup's Name from the RMI registry<BR> 137 try {<BR> 138 Naming unbind(groupName);<BR> 139 } catch (Exception e) {<BR> 140 System out printIn("AgentGroupImpl can't unbind " + e getMessage());<BR> 141 e.printStackTrace() 142 }<BR> 143<BR> 144 super finalize();<BR> 145 }<BR> 146<BR> 147<BR> 148 // Class methods<BR> 149 private final synchronized int nextGroupID() {<BR> 150 return ++groupID;<BR> 151 }<BR> 152<BR> 153<BR> 154 // Instance methods<BR> 155 /**<BR> 156 * Returns the Agent Groups's unique ID<BR> 157 * @return the Agent Group's unique ID<BR> 158 */<BR> 159 public final String getGroupName() {<BR> 160 return groupName;<BR> 161 }<BR> 162<BR> 163<BR> 164 /**<BR> 165 * Converts an Agent Group into its string representation<BR> 166 * @return A string representing the Agent Group<BR> 167 */<BR> 168 public String roString() {<BR> 169 return gro Name,<BR> 170 }<BR> 171<BR> 172<BR> 173 // Methods to manipulate agentList<BR> 174<BR> 175 /**<BR> 176 * Adds an Agent to the group<BR> 177 * @param status The AgentStatus object that describes the Agent<BR> 178 */<BR> 179 public synchronized void addAgent(AgentStatus status) {<BR> 180 agentList.addElement(status);<BR> 181 System.out println("Added Agent, ID = " + status.getAgentID() +<BR> 182 ", Status = " + status.getStatus() + " to group");<BR> 183 }<BR> 184<BR> 185 /**<BR> 186 * Locates and removes the AgentStatus object containing the specified ID.<BR> <P>187 * @param agentID An Agent's unique ID.<BR> <P>188 * @exception NoSuchElementException If the AgentStatus object does 189 * not exist<BR> 190 */<BR> 191 public synchronized void removeAgent(String agentID)<BR> 192 throws NoSuchElementException, ArrayIndexOutOfBoundsException {<BR> 193<BR> 194 int index = indexOfAgent(agent ID)<BR> 195 if (index == 1)<BR> 196 throw new NoSuchElementException("Can't find AgentID")<BR> 197 agentList removeElementAt(index);<BR> 198 System out println("Removed Agent, ID = " + agent ID + " from group");<BR> 199 }<BR> 200<BR> 201 /**<BR> 202 * Replaces the AgentStatus object for the specified ID<BR> 203 * This method may be used to change an Agent's status, ID, or both<BR> 204 * @param agentID An Agent's unique ID<BR> 205 * @param newStatus An AgentStatus object to replace the existing one<BR> 206 * @exception NoSuchElementException If the AgentStatus object does<BR> 207 * not exist<BR> 208 */<BR> 209 public synchronized void updateAgent(String agentID, AgentStatus newStatus)<BR> 210 throws NoSuchElementException, ArrayIndexOutOfBoundsException {<BR> 211<BR> 212 removeAgent(agentID)<BR> 213 addAgent(newStatus);<BR> 214 System.out.println("Updated Agent ID from " + agentID + " to Next ID = " +<BR> 215 newStatus getAgentID() + ", Status = " + newStatus getStatus());<BR> 216 }<BR> 217<BR> 218 /*<BR> 219 * Walks the agentList looking for an AgentStatus obiect with the<BR> 220 * specified ID<BR> 221 */<BR> 222 private int undexOfAgent(String agentID) {<BR> 223 int index, numAgents;<BR> 224 for (index = 0, numAgents = agentList size(); index < numAgents; index++) {<BR> 225 AgentStatus status = (AgentStatus)agentList elementAt(index);<BR> 226 if (agentID.compareTo(Status getAgentID()) == 0)<BR> 227 return index;<BR> 228 }<BR> 229 return -1;<BR> 230 }<BR> 231<BR> 232 /**<BR> 233 * Determines how many agents in the group have the specified status<BR> 234 * @param status The status value to search for<BR> 235 * @return The number of Agent's with the specified status 236 * @see AgentStatus<BR> 237 */<BR> 238 public int agentsWithStatus(int status) {<BR> 239 int agents = 0;<BR> 240 for (Enumeration e = agentList elements(); e hasMoreElements(); ) {<BR> 241 AgentStatus aStatus = (AgentStatus)e nextElement();<BR> 242 if (aStatus.getStatus() == status)<BR> 243 agents++;<BR> 244 }<BR> 245 return agents<BR> 246 }<BR> 247<BR> 248<BR> 249 /**<BR> 250 * Returns the number of Agents in the group<BR> 251 * @return The number of Agents in the group<BR> 252 */<BR> 253 public final int getGroupSize() {<BR> 254 return agentList size()<BR> 255 }<BR> 256<BR> 257<BR> 258 // Methods to mplement collaboration<BR> 259<BR> 260 /**<BR> 261 * Collaborate( is the public interface to collaboration It calls<BR> 262 * beginCollaboration() to synchornize the recording of agent results<BR> 263 * and to wait for all agents to arrive<BR> 264 *<BR> 265 * If all agents in the group have arrived at the collaboration<BR> 266 * point, each agent calls the application-specific analyzeResults()<BR> 267 * method to determine the agent's next course of action<BR> 268 *<BR> 269 * Otherwise, the agent that initiated the collaborate calls<BR> 270 * recoverCollaboration()<BR> 271 *<BR> 272 *<BR> 273 * @param result The result of the agent's computation<BR> 274 * @exception RemoteException If an error occurrs setting up network<BR> 275 * connections<BR> 276 * @exception AgentGroupEcxception If the collaboration times out.<BR> <P>277 * @return An Object that describes the result of collaboration<BR> 278 */<BR> 279 public Object collaborate(AgentResult result)<BR> 280 throws RemoteException, AgentGroupException {<BR> 281<BR> 282 System out println("collaborate RMI"); 283<BR> 284 boolean firstCollaborator = beginCollaboration(result);<BR> 285<BR> 286 /*<BR> 287 * If collaboration failed and this is the agent that initiated<BR> 288 * collaboration, it woke up because its timer expired It retries<BR> 289 * once before waking up the other agents<BR> 290<BR> 291 */<BR> 292 if (firstCollaborator && !collaborationSucceeded()) {<BR> 293 System out pr ntln("Collaboration Failed R trying ")<BR> 294 synchronized(thi ) {<BR> 295 try {<BR> 296 this wait(timeout);<BR> 297 } catch (InterruptedException e) { }<BR> 298 }<BR> 299 }<BR> 300<BR> 301 /*<BR> 302 * If al~ agents in the group have arrived at the collaboration<BR> 303 * point, each agent calls the application-specific analyzeResults<BR> 304 * method to determine the agent's next course of action<BR> 305 */<BR> 306 if (collaborationSucceeded()) {<BR> 307 System out.println("Ready to do collaboration");<BR> 308 Object collaboration = analyzeResults(resultList elements());<BR> 309<BR> 310 /*<BR> 311 * The agent that initiated collaboration cleans up<BR> 312 */<BR> 313 if (f~rstCollaborator)<BR> 314 endCollaboration());<BR> 315<BR> 316 return collaboration<BR> 317 } else {<BR> 318 /*<BR> 319 * If this is the agent that originated the collaboration,<BR> 320 * it woke up because the timer expired. It must wake up<BR> 321 * the other blocked agents (which are still sitting in<BR> 322 * beginCollaborate()) and then recover from the error<BR> 323 */<BR> 324 if (firstCollaborator) {<BR> 325 System.out println("Collaboration Failed while " +<BR> 326 agentsWithStatus(AgentStatus INTRANSIT) +<BR> 327 " agents were in transit");<BR> 328<BR> 329 synchronized(this) { 330 this notifyAll();<BR> 331 }<BR> 332 recoverCollaboration();<BR> 333 } else<BR> 334 System out println("Collaboration Failed");<BR> 335<BR> 336 throw new AgentGroupException("Collaboration timed out");<BR> 337 }<BR> 338<BR> 339 }<BR> 340<BR> 341<BR> 342 /**<BR> 343 * beginCollaboration() is called internally by collaborate() to<BR> 344 * synchronize each agent's recording of results and to wait for<BR> 345 * all agents to arrive at the collaboration point This method acts<BR> 346 * as a distributed rendezvous, of sorts. Each caller blocks until<BR> 347 * all agents in the group have "arrived" at the collaboration point<BR> 348 *<BR> 349 * This method returns a boolean that indicates if the agent initiated<BR> 350 * the collaboration<BR> 351 *<BR> 352 * @param result The result of the agent's computation<BR> 353 * @exception AgentGroupException If the group only has one member<BR> 354 * @return A boolean indicating if the collaboration was successful<BR> 355 *<BR> 356 */<BR> 357 protected synchronized boolean beginCollaboration(AgentResult result)<BR> 358 throws AgentGroupException {<BR> 359<BR> 360 boolean firstCollaborator = false;<BR> 361<BR> 362 System out println("Beginning collaboration")<BR> 363<BR> 364 of (!collaborationInProgress) {<BR> 365 /*<BR> 366 * If this agent is initiating the collaboration, allocate the<BR> 367 * resultList Vector and add result to it. Then wait for all<BR> 368 * agents to arrive at the collaboration point or for the<BR> 369 * collaboration timer to expire<BR> 370 */<BR> 371 if (agentList size() < 2) {<BR> 372 endCollaboration();<BR> 373 throw new AgentGroupException("AgentGroup too small");<BR> 374 }<BR> 375<BR> 376 collaborationInProgress = true; 377 firstCollaborator = true;<BR> 378 resultList = new Vector();<BR> 379 resultList.addElement(result);<BR> 380<BR> 381 try {<BR> 382 this wait(timeout);<BR> 383 } ca ch (InterruptedException e) { }<BR> 384<BR> 385 } else {<BR> 386<BR> 387 /*<BR> 388 * Add this agent's results to resultList. If this is the<BR> 389 * last agent to arrive, wake up the other agents Otherwise<BR> 390 * wait for the rest of the agents in the group to arrive<BR> 391 */<BR> 392 resultList.addElement(result);<BR> 393 if (collaborationSucceeded())<BR> 394 this notifyAll();<BR> 395 else {<BR> 396 try {<BR> 397 this.wait();<BR> 398 catch (InterruptedException e) { )<BR> 399 }<BR> 400 }<BR> 401<BR> 402 return f~rstCollaborator;<BR> 403 }<BR> 404<BR> 405<BR> 406 /**<BR> 407 * Cleans up after a successful collaboration<BR> 408 */<BR> 409 protected void endCollaboration() {<BR> 410 collaborationInProgress = false;<BR> 411 }<BR> 412<BR> 413<BR> 414 /**<BR> 415 * Cleans up after a failed collaboration<BR> 416 */<BR> 417 protected void recoverCollaboration() {<BR> 418 endCollaboration();<BR> 419<BR> 420 }<BR> 421<BR> 422<BR> 423 /** 424 * analyzeResults() is an abstract method that must be overridden by<BR> 425 * each application It provides the application-specific behavior<BR> 426 * required to implement collaboration This method is invoked on<BR> 427 * behalf of each agent in the group. It is passed the results<BR> 428 * computed by each agent and determines the course of action for the<BR> 429 * calling agent, if any, based on the computed results<BR> 430 *<BR> 431 * @param res~ s An Enumeration of the results computed by the agents<BR> 432 * @return Object An application-specific object or null<BR> 433 *<BR> 434 */<BR> 435 abstract protect d Objec analyzeResults(Enumeration results);<BR> 436<BR> 437 /*<BR> 438 * Private method to determine if all agents have reached the<BR> 439 * collaboration point This method is sychronized to prevent<BR> 440 * races with agents joining and leaving the group<BR> 441 */<BR> 442 private synchronized boolean collaborationSucceeded() {<BR> 443 return (resultList size() == agentList size());<BR> 444 }<BR> 445<BR> 446<BR> 447<BR> 448 /*<BR> 449 * TURN ON LATER<BR> 450 *<BR> 451<BR> 452 // Methods to handle exceptions and other notifications<BR> 453 public void agentException(String agentID, Exception type)<BR> 454 throws Rem teException {<BR> 455 }<BR> 456<BR> 457 public void agentTermination(string agentID)<BR> 458 throws RemoteException {<BR> 459 }<BR> 460<BR> 461 */<BR> 462<BR> 463 } 1 /* $Header /com/meitca/hsl/zonesjagents/collaborate/AgentResult java 4 10/01/96 3:43p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Inforamation Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRPTION<BR> 10 * This object heads the result of an agent's computations<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/collaborate/AgentResult java $<BR> 13 *<BR> 14 * 4 10/01/96 3 43p Noemi<BR> 15 * Added some javadoc comments<BR> 16 *<BR> 17 * 3 9/06/96 3 48 Noemi<BR> 18 * Added protected default constructor to ensure that the public<BR> 19 * constructors set up instance variables correctly<BR> 20 *<BR> 21 * 2 8/30/96 4 22p Noemi<BR> 22 * Changed private protected instance variables to protected<BR> 23 *<BR> 24 * 1 8/28/96 2 17p Noemi<BR> 25 * A generic class that represents the result of an agent computation<BR> 26 * (Used by collaboration code)<BR> 27 */<BR> 28<BR> 29 package com meitca hsl zonesjagents collaborate<BR> 30<BR> 31 /**<BR> 32 * AgentResult co ta ns an @ent ID and a result to be shared<BR> 33 * via collaboration<BR> 34 *<BR> 35 * @see CollaboratorAgent<BR> 36 * @see AgentGroupImpl<BR> 37 * @author Noemi Paciorek<BR> 38 */<BR> 39<BR> 40 public class AgentResult {<BR> 41<BR> 42 // Instance variables<BR> 43 protected String agentID // ID of agent that computed result<BR> 44 protected Object result; // actual result computed<BR> 45<BR> 46 // Constructors<BR> 47 /** 48 * Protected Default Constuctor for an AgentResult object<BR> 49 * @exception IllegalAccessException Whenever called<BR> 50 */<BR> 51 protected AgentResult()<BR> 52 throws IllegalAccessException {<BR> 53<BR> 54 System.out println("Default constructor called for AgentResult");<BR> 55 throw new IllegalAccessException("AgentResult default constructor");<BR> 56 }<BR> 57<BR> 58 /**<BR> 59 * Constructs an AgentResult object<BR> 60 * @param agentID The Agent's unique ID.<BR> <P>61 * @param result The result to be shared via collaboration<BR> 62 */<BR> 63 public AgentResult(String agentID, Object result) {<BR> 64 this.agentID = agentID,<BR> 65 this result = result<BR> 66 }<BR> 67<BR> 68<BR> 69 // Instance methods<BR> 70 /**<BR> 71 * Gets an Agent's unique ID from this AgentResult object<BR> 72 * @return An Agent's unique ID.<BR> <P>73 */<BR> 74 public final String getAgentID() {<BR> 75 return agentID;<BR> 76 }<BR> 77<BR> 78 /**<BR> 79 * Gets the result to be shared via collaboration<BR> 80 * from this AgentResult Object<BR> 81 * @return The result to be shared via collaboration<BR> 82 */<BR> 83 public Object getResult() {<BR> 84 return result<BR> 85 }<BR> 86<BR> 87 } 1 /* $Header: /com/meitca/hsl/zonesjagents/collaborate/AgentStatus java 2 10/01/96 3.44p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 This object holds an Agent's status (e g ACTIVE)<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/collaborate/AgentStatus java $<BR> 13 *<BR> 14 * 2 10/01/96 3 44p Noemi<BR> 15 * Added some javadoc comments<BR> 16 *<BR> 17 * 1 9/06/96 3 51p Noemi<BR> 18 * This class represents an agent's current status (e g , ACTIVE)<BR> 19 */<BR> 20<BR> 21 package com meitca hsl zonesjagents collaborate<BR> 22<BR> 23 /**<BR> 24 * AgentStatus contains an agent ID and a status value Each AgentGroup<BR> 25 * contains an AgentStatus object for each Agent in the group<BR> 26 *<BR> 27 * @see CollaboratorAgent<BR> 28 * @see AgentGroupImpl<BR> 29 * @author Noemi Paciorek<BR> 30 */<BR> 31<BR> 32 public class AgentStatus {<BR> 33<BR> 34 // Constants<BR> 35 private state final int FIRST~STATUS = 1;<BR> 36 /**<BR> 37 * Agent is active<BR> 38 */<BR> 39 public static final int.ACTIVE = 1;<BR> 40 /**<BR> 41 * Agent is intransit<BR> 42 */<BR> 43 public static final int INTRANSIT = 2;<BR> 44 /**<BR> 45 * Agent is in an unknown state<BR> 46 */<BR> 47 public static final int UNKNOWN = 3; 48 private static final int LAST~STATUS = UNKNOWN;<BR> 49<BR> 50 // Instance variables<BR> 51 protected String agent ID; // ID of agent<BR> 52 int status; // current status<BR> 53<BR> 54 //Constructs<BR> 55 /**<BR> 56 * Constructs an AgentStatus object<BR> 57 * @exception IllegalAccessException Whenever called<BR> 58 */<BR> 59 protected AgentStatus()<BR> 60 throws I egalAccessException {<BR> 61<BR> 62 System.cmt println("Defaul constuctor called for AgentStatus");<BR> 63 throw new IllegalAccessException("AgentStatus default constructor");<BR> 64 }<BR> 65<BR> 66<BR> 67 /**<BR> 68 * Constructs an AgentStatus object<BR> 69 * @param agentID The Agent's unique ID<BR> 70 */<BR> 71 public AgentStatus(String agentID) {<BR> 72 this(agentID, ACTIVE);<BR> 73 }<BR> 74<BR> 75<BR> 76 /**<BR> 77 * Constructs an AgentStatus object<BR> 78 * @param agentID The Agent's unique ID<BR> 79 * @param status The Agent's status<BR> 80 */<BR> 81 public AgentStatus(String agentID, int status) (<BR> 82 this agentID = agentID;<BR> 83 this status = ((status < FIRST~STATUS) || (status > LAST~STATUS)) ?<BR> 84 UNKNOWN status;<BR> 85 }<BR> 86<BR> 87<BR> 88 // Instance methods<BR> 89 /**<BR> 90 * Extracts an Agent's uniqe ID from an AgentStatus object<BR> 91 * @return An Agent's unique ID<BR> 92 */<BR> 93 public final String getAgentID() {<BR> 94 return agentID, 95 }<BR> 96<BR> 97 /**<BR> 98 * Extracts an Agent's current status from an AgentStatus object<BR> 99 * @return An Agent s current status<BR> 100 */<BR> 101 public final in getStatus() {<BR> 102 return status<BR> 103 }<BR> 104<BR> 105 } 1 /* $Header /com/meitca/hsl/zonesjagents/collaborate/CollaboratorAgent.j ava 5 10/01/96 3:45p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * InformationThechnology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Derived class for mobile Agent collaboration<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/collaborate/CollaboratorAgent java $<BR> 13 *<BR> 14 * 5 10/01/96 3 45p Noemi<BR> 15 * Added some javadoc comments<BR> 16 *<BR> 17 * 4 9/20/96 4 16p Noemi<BR> 18 * Changed finalizer to ensure that it performs cleanup no more than once<BR> 19 * ( A bug in the garbage collector may cause the finalizer to be called<BR> 20 * more than once!)<BR> 21 *<BR> 22 * 3 9/10/96 5 08p Noemi<BR> 23 * Renamed setIntransitStatus and setActiveStatus to prepareForTransport<BR> 24 * and completedTransport, respectively<BR> 25 *<BR> 26 * 2 9/06/96 3 57p Noemi<BR> 27 * Added the following methods addGroup removeGroup updateStatus,<BR> 28 * setIntransitStatus and se ActiveStatus<BR> 29 *<BR> 30 * 1 9/04/96 3 15p Noemi<BR> 31 * Subclass of Agent that implements a collaborating Agent<BR> 32 *<BR> 33 */<BR> 34 package com meitca hsl zonesjagents collaborate<BR> 35<BR> 36 import java util *;<BR> 37 import java net InetAddress;<BR> 38<BR> 39 import com meitca hsl zonesjagents shared Agent;<BR> 40<BR> 41 /**<BR> 42 * A subclass of Agent that enables collaboration among agents in a group<BR> 43 * Agents wishing to ollaborate must extend this class to do some useful work.<BR> <P>44 * They must also be ong to an agent coordination group (AgentGroup). Generally,<BR> 45 * an application first creates an AgentGroup Then it obtains a reference to<BR> 46 * the RMI intarface for the group by looking up the group in the local RMI name<BR> 47 * service Subsenquen ly, it creates new CollaboratorAgents and populates the 48 * group with them (by passing the constuctor a reference to the interface).<BR> <P>49 *<BR> 50 * @see Agent<BR> 51 * @see AgentGroup<BR> 52 * @author Noemi Paciorek<BR> 53 */<BR> 54 public abstract class CollaboratorAgent<BR> 55 extends Agent<BR> 56<BR> 57 // Instance variables<BR> 58 protected Vector grouplist: //AgentGroups this agent belongs to<BR> 59<BR> 60 // Constructors<BR> 61 /**<BR> 62 * Constructs a CollaboratorAgent<BR> 63 * @except.on IllegalAccessException Whenever called<BR> 64 */<BR> 65 protected CollaboratorAgent()<BR> 66 throws IllegalAccessException {<BR> 67<BR> 68 System out println("Default constructor called for CollaboratorAgent");<BR> 69 throw new IllegalAccessException("ColaboratorAgent Default constructor");<BR> 70 }<BR> 71<BR> 72 /**<BR> 73 * Constructs a CollaboratorAgent<BR> 74 * @param group The AgentGroup to which this Agent belongs<BR> 75 */<BR> 76 public Collab ratorAgent(AgentGroup group) {<BR> 77 /*<BR> 78 * Store a copy of the agentID in the AgentGroup and save a<BR> 79 * reference to the AgentGroup in groupList<BR> 80 /*<BR> 81 groupList = new Vector();<BR> 82 addGroup(group);<BR> 83 }<BR> 84<BR> 85<BR> 86 /**<BR> 87 * Constructs a CollaboratorAgent<BR> 88 * @param groups A list of AgentGroups to which this Agent belongs<BR> 89 */<BR> 90 public CollaboratorAgent(Vector groups) {<BR> 91 this(groups, null);<BR> 92 }<BR> 93<BR> 94 95 /**<BR> 96 * Constructs a CollaboratorAgent<BR> 97 * @param groups A list of AgentGroups to which this Agent belongs.<BR> <P>98 * @param oldID The unique ID of an agent to be replaced by this agent.<BR> <P>99 */<BR> 100 public CollaboratorAgent(Vector groups, String oldID) {<BR> 101 /*<BR> 102 * Save a copy of agentID in each of the associated AgentGroups and<BR> 103 * store a reference to each AgentGroup in groupList<BR> 104 */<BR> 105 goupList new Vector();<BR> 106 for (Enumeration e = groups elements(); e.hasMoreElements(); ) {<BR> 107 AgentGroup group = (AgentGroup)e nextElement();<BR> 108 groupList addElement(group);<BR> 109<BR> 110 try {<BR> 111 if (oldID == null)<BR> 112 group addAgent(new AgentStatus(agentID);<BR> 113 else<BR> 114 group updateAgent(oldID, new AgentStatus(agentID));<BR> 115 System out println("Group size = " + group getGroupSize());<BR> 116 } catch (Exception ex) {<BR> 117 System out println("Agent constructor can't add agent to group " +<BR> 118 ex getMessage());<BR> 119 System.out.println("AgentID = " + agentID + ", oldID = " + oldID);<BR> 120 ex printStackTrace();<BR> 121 }<BR> 122<BR> 123 }<BR> 124 }<BR> 125<BR> 126<BR> 127 // Finalizer<BR> 128 protected void finalize()<BR> 129 throws Therowable {<BR> 130<BR> 131 System.out println("CollaboratorAgent Finalizer called");<BR> 132<BR> 133 /*<BR> 134 * Remove agentID from all groups this agent belongs to<BR> 135 */<BR> 136 if (groupList != null) {<BR> 137 for (Enumeration e = groupList.elements(): e.hasMoreElements(); ) {<BR> 138 AgentGroup group = (AgentGroup)e.nextElement();<BR> 139 try {<BR> 140 group removeAgent(agentID);<BR> 141 } catch (Exception ex) { 142 System.out.println("CollaboratorAgent finalizer: can't remove agent from group " +<BR> 143 ex getMessage());<BR> 144 ex printStackTrace();<BR> 145 }<BR> 146 }<BR> 147 groupList = null // in case finalizer gets called twice (it has been!)<BR> 148 }<BR> 149 super finalize();<BR> 150 }<BR> 151<BR> 152 // Instance methods<BR> 153 /**<BR> 154 * Returns a list of groups the CollaboratorAgent belongs to<BR> 155 * @return The list of groups this CollaboratorAgent belongs to<BR> 156 */<BR> 157 public final synchronized Enumeration getGroups() {<BR> 158 return groupList elements();<BR> 159 }<BR> 160<BR> 161 /**<BR> 162 * Add a group to this agent's groupList and add the agent<BR> 163 * to the group's agent list<BR> 164 * @param group The group to be added<BR> 165 */<BR> 166 public synchronized void addGroup(AgentGroup group) {<BR> 167 groupList addElement(group)<BR> 168<BR> 169 try {<BR> 170 group addAgent(new AgentStatus(agentID))<BR> 171 System out println("Group size = " + group getGroupSize());<BR> 172 } catch (Exception ex) {<BR> 173 System.out println("Can't add agent to group " + ex getMessage());<BR> 174 ex printStackTrace()<BR> 175 }<BR> 176 }<BR> 177<BR> 178 /**<BR> 179 * Remove a group from this agent s groupList and remove the agent<BR> 180 * from the group's agent list<BR> 181 * @param group The group to be removed<BR> 182 */<BR> 183 public synchronized void removeGroup(AgentGroup group) {<BR> 184 groupList removeElement(group);<BR> 185<BR> 186 try {<BR> 187 group.removeAgent(agentID);<BR> 188 } catch (Exception ex) { 189 System.out.println("Can't remove agent from group: " + ex.getMessage());<BR> 190 ex printStackTrace();<BR> 191 }<BR> 192 }<BR> 193<BR> 194<BR> 195 /**<BR> 196 * Update an agent's status in all groups it belongs to<BR> 197 * @param status The new status<BR> 198 */<BR> 199 public synchronized void updateStatus(int status) {<BR> 200 if (groupList !=null)<BR> 201 for (Enumeration e = groupList.elements(); e.hasMoreElements(); ) {<BR> 202 AgentGroup group = (AgentGroup)e nextElement();<BR> 203 try {<BR> 204 group updateAgent(agentID, new AgentStatus(agentID, status));<BR> 205 } catch (Exception ex) {<BR> 206 System out println("CollaboratorAgent finalizer: can't remove agent from group: " +<BR> 207 ex getMessage());<BR> 208 ex printStackTrace();<BR> 209 }<BR> 210 }<BR> 211 }<BR> 212<BR> 213 /**<BR> 214 * Set an agen s status to INTRANSIT before transport<BR> 215 */<BR> 216 public void prepareForTransport() {<BR> 217 updateStatus(AgentStatus INTRANSIT);<BR> 218 }<BR> 219<BR> 220<BR> 221 /**<BR> 222 * Set an agent s status to ACTIVE after transport<BR> 223 */<BR> 224 public void completedTransport() {<BR> 225 updateStatus(AgentStatus.ACTIVE);<BR> 226 }<BR> 227<BR> 228 } 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventException java 1 10/14/96 6:55p Noemi $<BR> 2 *<BR> 3 * Copyrigt 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Event exceptions<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/event/EventException java $<BR> 13 *<BR> 14 * 1 10/14/96 6 55p Noemi<BR> 15 * Base class for exceptions generated during event processing<BR> 16 */<BR> 17 package com meitca hsl zonesjagents event;<BR> 18<BR> 19 /**<BR> 20 * Exceptions encountered by Events<BR> 21 *<BR> 22 * @see EventType<BR> 23 * @author Noemi Paciorek<BR> 24 */<BR> 25<BR> 26 public class EventException extends Exception {<BR> 27<BR> 28 // Constructors<BR> 29 /*<BR> 30 * Constructs an EventException<BR> 31 * @exception IllegalAccessException Whenever called<BR> 32 */<BR> 33 protected EventException()<BR> 34 throws IllegalAccessException {<BR> 35<BR> 36 System out println("Default constructor called for EventException");<BR> 37 throw new IllegalAccessException("EventException Default constructor");<BR> 38 }<BR> 39<BR> 40 /**<BR> 41 * Constructs an EventException<BR> 42 * @param type A String describing exception<BR> 43 */<BR> 44 public EventException(String type) {<BR> 45 super(type)<BR> 46 }<BR> 47 } 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventGroup java 1 10/14/96 6 59p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRITARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Event Group distributed interface<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/event/EventGroup java $<BR> 13 *<BR> 14 * 1 10/14/96 6 59p Noemi<BR> 15 * Event Group interface<BR> 16 *<BR> 17 */<BR> 18<BR> 19 package com meitca hsl zonesjagents event<BR> 20<BR> 21 import java util @ SuchElementException;<BR> 22<BR> 23 import java.rmi Remote;<BR> 24 import java rmi RemoteException<BR> 25<BR> 26 /**<BR> 27 * EventGroup is a d stributed RMI interface for event groups<BR> 28 *<BR> 29 * An EventGroup onsists f a group of object that wish to receive<BR> 30 * events generated by the other members of the group The EventGroup<BR> 31 * serves as a gateway between the objects in the group and forwards<BR> 32 * events posted to it to the members of the group<BR> 33 *<BR> 34 * The members of the group must all implement the EventPost interface<BR> 35 *<BR> 36 * @see EventGroupImpl<BR> 37 * @author Noemi Paciorek<BR> 38 */<BR> 39<BR> 40 public interface EventGroup<BR> 41 extends Remote {<BR> 42<BR> 43 /**<BR> 44 * Adds a member to the event group.<BR> <P>45 * @param object An Object that implements the EventPost inteface<BR> 46 * @exception RemoteExcept on If an error occurrs setting up network<BR> 47 * connections 48 * exception ClassCastException If object does not implement EventPost<BR> 49 */<BR> 50 public void addMember(Object object)<BR> 51 throws RemoteException, ClassCastException;<BR> 52<BR> 53 /**<BR> 54 * Remove a member from the group<BR> 55 * @param object The object to remove<BR> 56 * @exception RemoteException If an error occurrs setting up network<BR> 57 * connections<BR> 58 * @exception oSuchElementException If object is not a member of the group<BR> 59 */<BR> 60 public void removeMember(Ob ect object)<BR> 61 throws Rem teException, NoSuchElementException<BR> 62<BR> 63 } 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventGroupImpl.java 2 10/22/96 7:10p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Event Group distributed object<BR> 11 *<BR> 12 * $Log /com meitca/hsl/zonesjagents/event/EventGroupImpl java $<BR> 13 *<BR> 14 * 2 10/22/96 7 10p Noemi<BR> 15 * Changed the throws clause of the postEvent method<BR> 16 *<BR> 17 * 1 10/14/96 6 59p Noemi<BR> 18 * Event group implementation<BR> 19 *<BR> 20 */<BR> 21<BR> 22 package com meitca hsl zonesjagents event;<BR> 23<BR> 24<BR> 25 import java.util *<BR> 26 import java io *;<BR> 27<BR> 28 import java rmi server UnicastRemoteServer;<BR> 29 import java rmi RemoteException<BR> 30 import java rmi Naming;<BR> 31 import java rmi AlreadyBoundException<BR> 32<BR> 33 import com.meitca hsl util UniqueID,<BR> 34<BR> 35 /**<BR> 36 * EventGroupImpl is an RMI distributed object that implements<BR> 37 * Event Group and EventPost<BR> 38 *<BR> 39 * An EventGroup consists of a group of objects that wish to receive<BR> 40 * events generated by the other members of the group The EventGroup<BR> 41 * serves as a gateway between the objects in the group and forwards<BR> 42 * events posted to it to the members of the group.<BR> <P>43 *<BR> 44 * The members of the group must all implement the EventPost interface<BR> 45 *<BR> 46 * @see EventGroup<BR> 47 * @author Noemi Paciorek 48 */<BR> 49<BR> 50 public class EventGroupImpl<BR> 51 extends UnicastRemoteServer<BR> 52 implements EventGroup, EventPost {<BR> 53<BR> 54 // Instance variables<BR> 55<BR> 56 /** A list of the group's members */<BR> 57 protected Vector memberList<BR> 58<BR> 59 // Constructors<BR> 60 /**<BR> 61 * Constructs an EventGroupImpl object<BR> 62 * @exception RemoteException If an error occurrs setting up network<BR> 63 * connections<BR> 64 */<BR> 65 public EventGroupImpl()<BR> 66 throws RemoteException {<BR> 67 /*<BR> 68 * Create member list and event queue<BR> 69 */<BR> 70 memberList - new Vector )<BR> 71 }<BR> 72<BR> 73 // Instance methods<BR> 74<BR> 75 // EventGroup m hods<BR> 76 /**<BR> 77 * Add a member to the event group<BR> 78 * @param on ect An Object that implements the EventPost interface<BR> 79 * @exception ClassCastException If object does not implement EventPost<BR> 80 */<BR> 81 public synchronized void addMember(Object object)<BR> 82 throws ClassCastException {<BR> 83<BR> 84 try {<BR> 85 EventPost eventPost = (EventPost)object<BR> 86 } catch (ClassCastException e) {<BR> 87 System out println("addMember Object does not implement Event Post");<BR> 88 throw s<BR> 89 }<BR> 90 memberList addElement(object);<BR> 91 }<BR> 92<BR> 93<BR> 94 /** 95 * Remove a member from the group<BR> 96 * @param object The Object to remove<BR> 97 * @exception NoSuchElementException If object is not a member of the group.<BR> <P>98 */<BR> 99 public synchronized void removeMember(Object object)<BR> 100 throws NoSuchElementException {<BR> 101<BR> 102 if (!memberList re: veElement(object))<BR> 103 throw new NoSuchElementException("Object not member of group");<BR> 104 }<BR> 105<BR> 106<BR> 107 // EventPost methods<BR> 108 /**<BR> 109 * Forward an event to all members of the group<BR> 110 * @param event The event to post<BR> 111 * @exception EventException If an error occurs posting the event<BR> 112 */<BR> 113 public void postEvent(EventType event)<BR> 114 throws RemoteException, EventException, IOException {<BR> 115<BR> 116 for (Enumeratior e = memberList elements() e hasMoreElements() ) {<BR> 117 EventPost eventQueue = (EventPost)e nextElement();<BR> 118 eventQueue postEvent(event);<BR> 119 }<BR> 120 }<BR> 121<BR> 122 } 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventHandler java 1 10/14/96 6:56p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Event handler interface<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventHandler.java $<BR> 13 *<BR> 14 * 1 10/14/96 6:56p Noemi<BR> 15 * Event handler interface<BR> 16 */<BR> 17<BR> 18 package com.meitca hsl zonesjagents.event;<BR> 19<BR> 20 import java.rmi.Remote;<BR> 21 import java.rmi.RemoteException;<BR> 22<BR> 23 /**<BR> 24 * EventHandler is a distributed RMI interface for handling events.<BR> <P>25 *<BR> 26 * @author Noemi Paciorek<BR> 27 */<BR> 28<BR> 29 public interface EventHandler {<BR> 30<BR> 31 // Instance methods<BR> 32 /**<BR> 33 * Event handler interface.<BR> <P>34 * @param event Current event<BR> 35 * @exception RemoteException If an error occurrs setting up network<BR> 36 * connections<BR> 37 * @exception EventException If an error occurs handling the event.<BR> <P>38 */<BR> 39 public void handleEvent(EventType event)<BR> 40 throws RemoteException, EventException;<BR> 41 }<BR> 42 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventManager.java 2 10/22/96 7:12p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Event Manager Interface<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventManager.java $<BR> 13 *<BR> 14 * 2 10/22/96 7 12p Noemi<BR> 15 * Changed registerEvents and unregisterEvents to take an array of<BR> 16 * Strings, rather than an array of EventType. Also changed several of<BR> 17 * the throws clauses<BR> 18 *<BR> 19 * 1 10/14/96 6 58p Noemi<BR> 20 * Event Manager interface<BR> 21 */<BR> 22<BR> 23 package com.meitca hsl zonesjagents event;<BR> 24<BR> 25 import java.io.*;<BR> 26 import java rmi.Remote;<BR> 27 import java rmi.RemoteException,<BR> 28<BR> 29 /**<BR> 30 * EventManager is a distributed RMI interface for event management<BR> 31 *<BR> 32 * @see EventManagerImpl<BR> 33 * @author Noemi Paciorek<BR> 34 */<BR> 35<BR> 36 public interface EventManager<BR> 37 extends Remote {<BR> 38<BR> 39 // Instance methods.<BR> <P>40 // Methods used to register interest in specified events.<BR> <P>41<BR> 42 /**<BR> 43 * Register interest in receiving specified events<BR> 44 * @param events An array of the names of events that an object<BR> 45 * is interested in receiving.<BR> <P>46 * @param eventQueue The associated event queue's EventPost interface<BR> 47 * @exception RemoteException If an error occurrs setting up network 48 *connections.<BR> <P>49 */<BR> 50 public void registerEvents(String events[], EventPost eventQueue)<BR> 51 throws RemoteException, IOException;<BR> 52<BR> 53 /**<BR> 54 * Register interest in receiving all events posted to this EventManager<BR> 55 * @param eventQueue The associated event queue's EventPost interface.<BR> <P>56 * @exception RemoteException If an error occurrs setting up network<BR> 57 * connections<BR> 58 */<BR> 59 public void registerAll(EventPost eventQueue)<BR> 60 throws RemoteException, IOException;<BR> 61<BR> 62 // Methods to unregister events<BR> 63 /**<BR> 64 * Remove registration for specified events.<BR> <P>65 * @param events An array of the names of events that an object<BR> 66 * is no longer interested in receiving.<BR> <P>67 * @param eventQueue The associated event queue's EventPost interface.<BR> <P>68 * @exception RemoteException If an error occurrs setting up network<BR> 69 * connections<BR> 70 * @exception EventManagerException If the event queue was not registered<BR> 71 * for one or more of the specified exceptions<BR> 72 */<BR> 73 public void unregisterEvents(String events[], EventPost eventQueue)<BR> 74 throws RemoteException, IOException, EventManagerException;<BR> 75<BR> 76 /**<BR> 77 * Remove registration for all events.<BR> <P>78 * @param eventQueue The associated event queue's EventPost interface.<BR> <P>79 * @exception RemoteException If an error occurrs setting up network<BR> 80 * connections<BR> 81 */<BR> 82 public void unregisterAll(EventPost eventQueue)<BR> 83 throws RemoteException, IOException;<BR> 84<BR> 85 } 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventManagerException.jav a 1 10/14/96 6:57p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * EventManager exceptions<BR> 11 *<BR> 12 * $Log /com/meitca/hsl/zonesjagents/event/EventManagerException.jav a $<BR> 13 *<BR> 14 * 1 10/14/96 6 57p Noemi<BR> 15 * Exceptions generated by the Event Manager.<BR> <P>16 */<BR> 17 package com meitca hsl zonesjagents event;<BR> 18<BR> 19 /**<BR> 20 * Exceptions encountered by the EventManager<BR> 21 *<BR> 22 * @see EventMangerImpl<BR> 23 * @author Noemi Paciorek<BR> 24 */<BR> 25<BR> 26 public class EventManagerException extends EventException {<BR> 27<BR> 28 // Constructors<BR> 29 /**<BR> 30 * Constructs an EventManagerException<BR> 31 * @exception llegalAccessException Whenever called<BR> 32 */<BR> 33 protected EventManagerException()<BR> 34 throws IllegalAccessException {<BR> 35<BR> 36 System.out println("Default constructor called for EventManagerException");<BR> 37 throw new IllegalAccessException("EventManagerException Default constructor");<BR> 38 }<BR> 39<BR> 40 /**<BR> 41 * Constructs an EventManagerException.<BR> <P>42 * @param type A String describing the exception<BR> 43 */<BR> 44 public EventManagerException(String type) {<BR> 45 super(type);<BR> 46 }<BR> 47 } 48<BR> 49<BR> 50<BR> 51<BR> 52 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventManagerImpl.java 3 10/24/96 4:57p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America.<BR> <P>5 * All rights reserved.<BR> <P>6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Event Manager distributed object<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventManagerImpl java $<BR> 13 *<BR> 14 * 3 10/24/96 4 57p Noemi<BR> 15 * Added support for an Event Manager properties file and properties that<BR> 16 * specify if persistence is enabled and the name of the persistent<BR> 17 * storage file<BR> 18 *<BR> 19 * 2 10/22/96 7 28p Noemi<BR> 20 * Save full and specific event registrations to persistent storage<BR> 21 * Constructor reads persistent, data and reconstructs notifications<BR> 22 * EventManager removes event queues that it can t post events to<BR> 23 * Changed registerEvents and unregisterEvents to take an array of String<BR> 24 * Made constructor protected and added a main method.<BR> <P>25 * Perform cleanup when receiving conflicting registrations (full vs<BR> 26 * specific)<BR> 27 *<BR> 28 * 1 10/14/96 6 58p Noemi<BR> 29 * The Event Manager<BR> 30 */<BR> 31<BR> 32 package com.meitca hsl zonesjagents event;<BR> 33<BR> 34 import java util.*<BR> 35 import java io *;<BR> 36<BR> 37 import java.rmi server UnicastRemoteServer;<BR> 38 import java rmi.RemoteException<BR> 39 import java.rmi.Naming;<BR> 40 import java.rmi.NotBoundException;<BR> 41 import java.rmi.AlreadyBoundException;<BR> 42<BR> 43 import com.meitca.hsl zonesjagents shared *;<BR> 44<BR> 45 import com.meitca.hsl zonesjagents security.InsecurityManager;<BR> 46<BR> 47 48 /**<BR> 49 * EventManagerImpl is an Event Manager that implements the RMI<BR> 50 * EventManager and EventPost interfaces<BR> 51 *<BR> 52 * This class allows objects to register their interest in receiving<BR> 53 * specified event and to delete their registrations<BR> 54 *<BR> 55 * Objects post events by calling the EventManager's postEvent method<BR> 56 * (defined by the EventPost interface)<BR> 57 *<BR> 58 * The EventManager is a sentinel object (i e , there is only one<BR> 59 * per system.<BR> <P>60 *<BR> 61 * @see EventManager<BR> 62 * @see EventPost<BR> 63 * @see EventHandler<BR> 64 * @see EventManagerProxy<BR> 65 * @author Noemi Paciorek<BR> 66 */<BR> 67<BR> 68 public class EventManagerImpl<BR> 69 extends UnicastRemoteServer<BR> 70 implements EventManager, EventPost {<BR> 71<BR> 72 // Constants<BR> 73 private static final String EVENT~MANAGER~NAME = "EventManager";<BR> 74<BR> 75 private static final String PROPERTIES~DESCRIPTION = Properties File for EventManager"<BR> 76 private static final String ENABLE~PERSISTENCE = "EventManager.persistence.Enable";<BR> 77 private static final String PERSISTENCE~FILE = "EventManager.persistence.FileName";<BR> 78 // private static final String DEFAULT~PERSISTENCE~FILE = "C \\temp\\EventManager.store";<BR> 79 private static final String DEFAULT~PERSISTENCE~FILE = "EventManager store";<BR> 80<BR> 81<BR> 82 /* IDs for persistent objects */<BR> 83 private static final int EVENT~REGISTRATION~ID = 1;<BR> 84 private static final int FULL~REGISTRATION~ID = 2;<BR> 85<BR> 86 private static final int STORAGE~PADDING = 1024;<BR> 87<BR> 88<BR> 89 // Instance variables<BR> 90<BR> 91 /**<BR> 92 * Hash table that maps class names derived from EventType to<BR> 93 * registered EventPost stubs<BR> 94 */ 95 protected Hashtable eventRegistrations;<BR> 96<BR> 97 /** List of EventPost stubs registered to receive all notifications. */<BR> 98 protected Vector fullRegistrations;<BR> 99<BR> 100 /**<BR> 101 *Hash table that maps an EventPost stub to the list of events it<BR> 102 * is registered for (Actually, it maps the stub to the class name of<BR> 103 * the event)<BR> 104 */<BR> 105 protected Hashtable eventNotifications<BR> 106<BR> 107 /** A reference to this EventManager's persistent store handler. */<BR> 108 protected PersistentStoreHandler persistenceManager,<BR> 109<BR> 110 /** Name of the persistent storage file */<BR> 111 protected String persistentStoreFile;<BR> 112<BR> 113 /** The properties file */<BR> 114 protected JASProperties properties;<BR> 115<BR> 116 // Constructors<BR> 117 /**<BR> 118 * Constructs an EventManager EventManager Impl has no public<BR> 119 * constructors Applications wishing to utilize the Event Manager's<BR> 120 * services must access it via EventManagerProxy.<BR> <P>121 */<BR> 122 protected EventManagerimpl()<BR> 123 throws Exception {<BR> 124<BR> 125 /*<BR> 126 * Locate properties file<BR> 127 */<BR> 128 try<BR> 129 properties = new JASProperties(EVENT~MANAGER~NAME,<BR> 130 JASProperties SERVER, PROPERTIES~DESCRIPTION, false);<BR> 131 System out println("EventManagerImpl Located properties file");<BR> 132<BR> 133 } catch (Exception e) {<BR> 134 System out.println("EventManagerImpl: Couldn't access Properties file for Conduit Ser<BR> 135 System.out.println("\tContinuing with defaults.");<BR> 136 // Construct an empty Properties object.<BR> <P>137 properties = new JASProperties();<BR> 138 }<BR> 139<BR> 140 /*<BR> 141 * Recover event and full registrations from persistent storage, 142 * if required. Then reconstruct event notifications<BR> 143 */<BR> 144 recoverRegistrations();<BR> 145<BR> 146 /*<BR> 147 * Register this instance with the RMI registry<BR> 148 */<BR> 149 try {<BR> 150 Naming rebind(EVENT~MANAGER~NAME, this);<BR> 151 } catch (Exception e) {<BR> 152 System.out.println( EventManagerImpl can't bind " + EVENT~MANAGER~NAME + " " + e getMessage());<BR> 153 e.printStackTrace()<BR> 154 throw e;<BR> 155 }<BR> 156 }<BR> 157<BR> 158<BR> 159 // Finalizer<BR> 160 /**<BR> 161 * Removes the EventManager's entry from the RMI registry<BR> 162 */<BR> 163 protected void finalize()<BR> 164 throws Throwable {<BR> 165<BR> 166 System.out.println("EventManagerImpl Finalizer called");<BR> 167<BR> 168 // Remove this EventManager's Name from the RMI registry.<BR> <P>169 try {<BR> 170 Naming.unbind(EVENT~MANAGER~NAME);<BR> 171 } catch (Exception e) {<BR> 172 System.out println( EventManagerImpl can't unbind " + e getMessage());<BR> 173 e.printStackTrace()<BR> 174 }<BR> 175<BR> 176 // Delete reference to Persistent Store Manager<BR> 177 persistenceManager = null;<BR> 178<BR> 179 super finalize();<BR> 180 }<BR> 181<BR> 182<BR> 183<BR> 184 // Instance methods<BR> 185<BR> 186 // Methods to add event registrations<BR> 187 /**<BR> 188 * Register interest in receiving specified events 189 * To remove these registrations use<BR> 190 * unregisterEvents(EventType events[], EventPost eventQueue).<BR> <P>191 * @param events An array of the names of events that an object<BR> 192 * is interested in receiving<BR> 193 * @param eventQueue The associated event queue's EventPost interface<BR> 194 */<BR> 195 public synchronized void registerEvents(String events[], EventPost eventQueue)<BR> 196 throws IOException {<BR> 197<BR> 198 /*<BR> 199 * If the event queue has already registered to receive all<BR> 200 * notifications, ignore this request<BR> 201 */<BR> 202 if (fullRegistrations contains(eventQueue))<BR> 203 return;<BR> 204<BR> 205 /*<BR> 206 * Get the list of events the queue has registered<BR> 207 * for notification If the list does not exist, create it<BR> 208 */<BR> 209 Vector notifyList = (Vector)eventNotifications get(eventQueue);<BR> 210 if (notifyList == null) {<BR> 211 notifyList = new Vector();<BR> 212 eventNotifications put(eventQueue, notifyList);<BR> 213 }<BR> 214<BR> 215 for (int i = 0; i < events length; i++) {<BR> 216 String eventName = events[i];<BR> 217 System out println("registerEvents, event = " + eventName);<BR> 218<BR> 219 /*<BR> 220 * Add the event to the queue s list of registered events<BR> 221 */<BR> 222 if (!notifyList contains(eventName)) {<BR> 223 System.out println("registerEvents, adding event name to notify list");<BR> 224 notifyList addElement(eventName);<BR> 225 }<BR> 226<BR> 227 /*<BR> 228 * Look up the event name in the eventRegistrations hash table<BR> 229 * and add the queue to the list of registered Objects for the event.<BR> <P>230 */<BR> 231 Vector registryList = (Vector)eventRegistrations get(eventName);<BR> 232 if (registryList == null) {<BR> 233 registryList = new Vector();<BR> 234 eventRegistrations.put(eventName, registryList);<BR> 235 System out println("registerEvents, adding event queue to registry list"); 236 registryList.addElement(eventQueue);<BR> 237<BR> 238 } else if (!registryList.contains(eventQueue)) {<BR> 239 System.out.println("registerEvents, adding event queue to registry list");<BR> 240 registryList addElement(eventQueue);<BR> 241 }<BR> 242 }<BR> 243 /*<BR> 244 * Write the updated eventRegistrations table to<BR> 245 * persistent storage<BR> 246 */<BR> 247 updateEventRegistrations();<BR> 248 }<BR> 249<BR> 250<BR> 251 /**<BR> 252 * Register interest in receiving all events posted to this EventManager<BR> 253 * To remove these registrations use<BR> 254 * unregisterAll(EventPost eventQueue)<BR> 255 * @param eventQueue The associated event queue s EventPost interface<BR> 256 */<BR> 257 public synchronized void registerAll(EventPost eventQueue)<BR> 258 throws IOException {<BR> 259<BR> 260 System.out.println("registerAll");<BR> 261<BR> 262 /*<BR> 263 * If this event queue already registered to receive<BR> 264 * specific registrations, remove them.<BR> <P>265 */<BR> 266 if (Vector)eventNotifications get(eventQueue) != null)<BR> 267 unregisterAll(eventQueue);<BR> 268<BR> 269 /*<BR> 270 * If the event queue has already been registered for<BR> 271 * all notifications, ignore this request<BR> 272 * Otherwise add the queue the the list of full registrations<BR> 273 */<BR> 274 if (!fullRegistrations.contains(eventQueue)) {<BR> 275 System.out.println("registerAll, adding event queue to full registrations");<BR> 276 fullRegistrations addElement(eventQueue);<BR> 277 /*<BR> 278 * Write the updated fullRegistrations list to<BR> 279 * persistent storage.<BR> <P>280 */<BR> 281 updateFullRegistrations();<BR> 282 } 283 }<BR> 284<BR> 285<BR> 286 // Methods to remove registrations<BR> 287<BR> 288 /**<BR> 289 * Remove registration for specified events<BR> 290 * @param events An array of the names of events that an object<BR> 291 * is no longer interested in receiving<BR> 292 * @param eventQueue The associated event queue's EventPost interface.<BR> <P>293 * @exception EventManagerException If the event queue was not registered<BR> 294 * for one or more of the specified exceptions<BR> 295 */<BR> 296 public synchronized void unregisterEvents(String events[], EventPost eventQueue)<BR> 297 throws EventManagerException, IOException {<BR> 298<BR> 299 /*<BR> 300 * Get the list of events the queue has registered<BR> 301 * for notification<BR> 302 */<BR> 303 Vector notifyList = (Vector)eventNotifications get(eventQueue);<BR> 304 if (notifyList == null)<BR> 305 throw new EventManagerException("Bad event queue");<BR> 306<BR> 307 for (int i = 0; i < events length, i++) {<BR> 308 String eventName = events[i];<BR> 309 System out println("unregisterEvents, event = " + eventName);<BR> 310<BR> 311 /*<BR> 312 * Remove the event from the queue's list of registered events<BR> 313 */<BR> 314 System.out println("unregisterEvents, removing event name from notify list");<BR> 315 notifyList removeElement(eventName);<BR> 316<BR> 317 /*<BR> 318 * Look up the event name in the eventRegistrations hash table<BR> 319 * and remove the queue from the list of registered Objects for<BR> 320 * the event. If the list is empty, remove the event's hash<BR> 321 * table entry<BR> 322 */<BR> 323 Vector registryList = (Vector)eventRegistrations get(eventName);<BR> 324 if (registryList == null)<BR> 325 throw new EventManagerException("Bad event");<BR> 326<BR> 327 System.out.println("unregisterEvents, removing event queue from registry list.");<BR> 328 registryList removeElement(eventQueue);<BR> 329 330 if (registryList.isEmpty()) {<BR> 331 System.out.println("unregisterEvents, removing hash table entry for event " + eventName);<BR> 332 eventRegistrations remove(eventName);<BR> 333 }<BR> 334 }<BR> 335<BR> 336 /*<BR> 337 * Write the updated eventRegistrations table to<BR> 338 * persistent storage<BR> 339 */<BR> 340 updateEventRegistrations();<BR> 341<BR> 342 /*<BR> 343 * If the queue's list of registered events is empty, remove<BR> 344 * the queue's hash table entry.<BR> <P>345 */<BR> 346 if (notifyList isEmpty()) {<BR> 347 System out.println("unregisterEvents, removing event queue's hash table entry");<BR> 348 eventNotifications remove(eventQueue);<BR> 349 }<BR> 350 }<BR> 351<BR> 352<BR> 353 /**<BR> 354 * Remove registration for all events<BR> 355 * @param eventQueue The associated event queue's EventPost interface<BR> 356 * This method is often called by finalizers, so it ignores errors<BR> 357 */<BR> 358 public synchronized void unregisterAll(EventPost eventQueue)<BR> 359 throws IOException {<BR> 360<BR> 361 if (fullRegistrations contains(eventQueue)) {<BR> 362 /*<BR> 363 * If the event queue was registered to receive all registrations,<BR> 364 * remove it from the fullRegistrations hash table<BR> 365 */<BR> 366 System.out.println("unregisterAll, removing full registration");<BR> 367 fullRegistrations removeElement(eventQueue);<BR> 368<BR> 369 /*<BR> 370 * Write the updated fullRegistrations list to<BR> 371 * persistent storage<BR> 372 */<BR> 373 updateFullRegistrations();<BR> 374 } else {<BR> 375 /*<BR> 376 * Locate the event queue's list of registered events 377 */<BR> 378 Vector notifyList = (Vector)eventNotifications.get(eventQueue);<BR> 379 if (notifyList == null)<BR> 380 return;<BR> 381<BR> 382 System out println("unregisterAll, removing event registrations");<BR> 383<BR> 384 for (Enumeration e = notifyList.elements(); e hasMoreElements(); ) {<BR> 385 String eventName = (String)e.nextElement();<BR> 386 System out println("unregisterAll, event = " + eventName);<BR> 387<BR> 388 Vector registryList = (Vector)eventRegistrations.get(eventName);<BR> 389 if (registryList == null)<BR> 390 continue;<BR> 391 /*<BR> 392 For each event in the list, remove the queue from the<BR> 393 " event's list of registered Objects.<BR> <P>394 " If the list is empty, remove the event's hash table entry.<BR> <P>395 */<BR> 396 System.out.println("removing event queue from registry list");<BR> 397 registryList removeElement(eventQueue);<BR> 398 if (registryList.isEmpty()) {<BR> 399 System.out.println("unregisterAll, removing hash table entry for event " + eventName);<BR> 400 eventRegistrations.remove(eventName);<BR> 401 registryList = null;<BR> 402 }<BR> 403 }<BR> 404<BR> 405 /*<BR> 406 * Wr te the updated eventRegistrations table to<BR> 407 * persistent storage<BR> 408 */<BR> 409 updateEventRegistrations()<BR> 410<BR> 411 /*<BR> 412 * Remove the event queue's hash table entry<BR> 413 */<BR> 414 System out.println("unregisterAll, removing event queue's hash table entry");<BR> 415 eventNotifications remove(eventQueue);<BR> 416 }<BR> 417 }<BR> 418<BR> 419<BR> 420 // Methods to post events and send notifications<BR> 421<BR> 422 /**<BR> 423 * Notify objects that an event occurred (EventPost interface) 424 * @param event Event being posted.<BR> <P>425 * @exception EventException If an error occurs posting the event.<BR> <P>426 */<BR> 427 public synchronized void postEvent(EventType event)<BR> 428 throws RemoteException, EventException, IOException {<BR> 429<BR> 430 System out println("EventManager, posting event");<BR> 431 /*<BR> 432 * Handle specific registrations for this event Locate this event's<BR> 433 * entry in the eventRegistrations hash table and post the event to<BR> 434 * each of the event queues on its hash chain<BR> 435 */<BR> 436 String eventName = event getClass().getName();<BR> 437 System.out println("postEvent, event = " + eventName);<BR> 438<BR> 439 System out println("postEvent, checking specific registrations");<BR> 440<BR> 441 /*<BR> 442 * Post the event to the event queues registered to<BR> 443 * receive it<BR> 444 */<BR> 445 Vector badEventRegistrations = new Vector();<BR> 446<BR> 447 Vector registryList = (Vector)eventRegistrations get(eventName);<BR> 448 if (registryList != null) {<BR> 449 System out.println("registryList contains " + registryList.size() +<BR> 450 elements")<BR> 451<BR> 452 for (Enumeration e = registryList elements(); e.hasMoreElements(); ) {<BR> 453 . EventPost eventQueue = (EventPost)e nextElement();<BR> 454<BR> 455 System out println("Posting event");<BR> 456<BR> 457 try {<BR> 458 eventQueue postEvent(event);<BR> 459 } catch (Exception e2) {<BR> 460 System out.println("Event post failed");<BR> 461 badEventRegistrations addElement(eventQueue);<BR> 462 }<BR> 463 }<BR> 464 }<BR> 465<BR> 466 /*<BR> 467 * Post the event to all Objects that have requested notification<BR> 468 * of all events<BR> 469 */<BR> 470 System out println(@postEvent, checking full registrations"); 471 System.out.println("fullRegistrations contains " + fullRegistrations.size() +<BR> 472 " elements");<BR> 473<BR> 474 Vector badFullRegistrations = new Vector();<BR> 475 for (Enumeration e = fullRegistrations.elements(); e hasMoreElements(); ) {<BR> 476 EventPost eventQueue = (EventPost)e nextElement()<BR> 477<BR> 478 System out println("Posting event");<BR> 479 try {<BR> 480 eventQueue postEvent(event);<BR> 481 } catch (Exception e3) {<BR> 482 System.out.println("Event post failed");<BR> 483 badFullRegistrations.addElement(eventQueue);<BR> 484 }<BR> 485 }<BR> 486<BR> 487 /*<BR> 488 * If the EventManager was unable to contact any event queues,<BR> 489 * remove them from eventRegistrations and/or fullRegistrations<BR> 490 * and update the affected registrations in persistent storage<BR> 491 */<BR> 492 if (!badEventRegistrations isEmpty()) {<BR> 493 for (Enumeration e = badEventRegistrations.elements(); e hasMoreElements(); ) {<BR> 494 EventPost eventQueue = (EventPost)e.nextElement();<BR> 495 System.out.println("Removing bad event queue from registry list");<BR> 496 registryList removeElement(eventQueue);<BR> 497 }<BR> 498 updateEventRegistrations();<BR> 499 }<BR> 500 badEventRegistrations = null;<BR> 501<BR> 502 if (!badFullRegistrations isEmpty()) {<BR> 503 for Enumeration e = badFullRegistrations elements(); e.basMoreElements(); ) {<BR> 504 EventPost eventQueue = (EventPost)e nextElement(),<BR> 505 System out.println("Removing bad event queue from full list");<BR> 506 fullRegistrations removeElement(eventQueue);<BR> 507<BR> 508 updateFullRegistrations();<BR> 509 }<BR> 510 badFullRegistrations = null;<BR> 511<BR> 512 }<BR> 513<BR> 514<BR> 515 // Methods to handle persistence<BR> 516<BR> 517 /** 518 * Allocate a persistent store manager and restore<BR> 519 * eventRegistrations and fullRegistrations. (If they<BR> 520 * don't exist in the persistent store, instantiate<BR> 521 * new ones.) Then reconstruct eventNotifications from<BR> 522 * eventRegistrations<BR> 523 */<BR> 524 protected void recoverRegistrations() {<BR> 525<BR> 526 Boolean enabled = new Boolen(getProperty(ENABLE~PERSISTENCE, "false"));<BR> 527 if (!enabled booleanValue()) {<BR> 528 /*<BR> 529 * If persistence is disabled, perform initialization,<BR> 530 * but not recovery<BR> 531 */<BR> 532 System out println("recoverRegistrations. persistence disabled");<BR> 533 persistentStoreFile = "";<BR> 534 persistenceManager = null;<BR> 535 eventRegistrations = new Hashtable();<BR> 536 fullRegistrations = new Vector();<BR> 537 eventNotifications = new Hashtable();<BR> 538 return,<BR> 539 }<BR> 540<BR> 541 System out.println('Persistence enabled.");<BR> 542 persistentStoreFile = getProperty(PERSISTENCE~FILE, "");<BR> 543 System out println("EventManager persistence FileName property set to: " + persistentStoreFile)<BR> 544<BR> 545 /*<BR> 546 * If no file is specified, use the default<BR> 547 *<BR> 548 if (persistentStoreFile.length() == 0)<BR> 549 persistentStoreFile = AgentConstants.AGENT~DIR + DEFAULT~PERSISTENCE~FILE;<BR> 550 System.out println("Persistent Store File " + persistentStoreFile);<BR> 551<BR> 552 persistenceManager = new PersistentStoreHandler(persistentStoreFile);<BR> 553<BR> 554 /*<BR> 555 * Fetch registrations from the persistent store. If they don't exist,<BR> 556 * instantiate eventRegistrations and fullRegistrations<BR> 557 */<BR> 558 System out println("Fetching eventRegistrations")<BR> 559 if ((eventRegistrations =<BR> 560 (Hashtable)persistenceManager fetchObject(EVENT~REGISTRATION~ID)) == null)<BR> 561 eventRegistrations = new Hashtable();<BR> 562<BR> 563 System.out.println("Fetching fullRegistrations");<BR> 564 if ((fullRegistrations = 565 (Vector)persistenceMenager.fetchObject(FULL~REGISTRATION~ID) == null)<BR> 566 fullRegistrations = new Vector();<BR> 567<BR> 568 /*<BR> 569 * Reconstruct the event notifications using event registrations Then<BR> 570 * truncate the persistent store and write out the registrations<BR> 571 */<BR> 572 System.out println("Reconstructinp event notifications");<BR> 573 reconstructNotifications();<BR> 574<BR> 575 System.out.println("Saving registrations");<BR> 576 saveRegistrations();<BR> 577 }<BR> 578<BR> 579<BR> 580 /**<BR> 581 * Truncate persistent storage and write out event and full<BR> 582 * registrations<BR> 583 */<BR> 584 protected void saveRegistrations() {<BR> 585 if (persistenceManager == null)<BR> 586 return<BR> 587<BR> 588 persistenceManager truncateFileStore();<BR> 589 persistenceManager.insertObject(EVENT~REGISTRATION~ID,<BR > 590 eventRegistrations, STORAGE~PADDING);<BR> 591 persistenceManager insertObject(FULL~REGISTRATION~ID,<BR> 592 fullRegistrations, STORAGE~PADDING);<BR> 593 }<BR> 594<BR> 595<BR> 596 /**<BR> 597 * Update event registrations in persistent storage<BR> 598 */<BR> 599 protected void updateEventRegistrations() {<BR> 600 if (persistenceManager == null)<BR> 601 return;<BR> 602<BR> 603 System.out.println("Updating eventRegistrations");<BR> 604 persistenceManager.updateObject(EVENT~REGISTRATION~ID, eventRegistrations);<BR> 605 }<BR> 606<BR> 607<BR> 608 /**<BR> 609 * Update full registrations in persistent storage<BR> 610 */<BR> 611 protected void updateFullRegistrations() { 612 if (persistenceManager == null)<BR> 613 return;<BR> 614<BR> 615 System.out println("Updating fullRegistrations");<BR> 616 persistenceManager updateObject(FULL~REGISTRATION~ID, fullRegistrations);<BR> 617 }<BR> 618<BR> 619<BR> 620 /**<BR> 621 * Reconstruct the event notifications table from the<BR> 622 * event registrations table<BR> 623 */<BR> 624 protected void reconstructNotifications() {<BR> 625 eventNotifications = new Hashtable();<BR> 626<BR> 627 if (persistenceManager == null)<BR> 628 return;<BR> 629<BR> 630 /*<BR> 631 * Reconstruct the eventNotifications hash table by walking<BR> 632 * the EventRegistrations hash table and extracting registrations.<BR> <P>633 */<BR> 634 for (Enumeration registryKeys = eventRegistrations.keys();<BR> 635 registryKeys.hasMoreElements(): ) {<BR> 636<BR> 637 /<BR> 638 * For each key (event name) in the table, obtain the list of<BR> 639 * registered event queues<BR> 640 */<BR> 641 String.eventName = (String)registryKeys.nextElement();<BR> 642 System.out println ("reconstructNotifications, event = " + eventName);<BR> 643 Vector registryList = (Vector) eventRegistrations get (eventName);<BR> 644<BR> 645 /*<BR> 646 * If no objects have registered to receive this event,<BR> 647 * remove it from the eventRegistrations hash table<BR> 648 */<BR> 649 if ((registryList == null) || (registryList.isEmpty())) {<BR> 650 System.out.println("reconstructNotifications, removing hash table entry for event " + eventNa<BR> 651 eventRegistrations.remove(eventName);<BR> 652 continue;<BR> 653 }<BR> 654<BR> 655 /*<BR> 656 * Add the event name to the eventNotifications entry of<BR> 657 * each of the registered event queues, creating hash table<BR> 658 * entries, as necessary 659 */<BR> 660 for (Enumeration registryElements = registryList elements();<BR> 661 registryElements.hasMoreElements(); ) {<BR> 662<BR> 663 EventPost eventQueue = (EventPost)registryElements.nextElement();<BR> 664 Vector notifyList = (Vector)eventNotifications get(eventQueue);<BR> 665 if (notifyList == null) {<BR> 666 notifyList = newVector();<BR> 667 eventNotifications put (eventQueue, notifyList);<BR> 668 System out println ("reconstructNotifications, created eventNotifications hash table entry<BR> 669 }<BR> 670 notifyList addElement(eventName)<BR> 671 }<BR> 672 }<BR> 673 }<BR> 674<BR> 675 // Misc. methods<BR> 676 /** Returns the EventManager's name */<BR> 677 protected static String getEventManagerName() {<BR> 678 return EVENT~MANAGER~NAME;<BR> 679 }<BR> 680<BR> 681<BR> 682 /** Returns the value of a property */<BR> 683 protected String getProperty(String key, String def) {<BR> 684 return properties.getProperty(key, def);<BR> 685 }<BR> 686<BR> 687 // Main method<BR> 688 /**<BR> 689 * EventManagerImpl bootstrap This is the only way to start<BR> 690 * the EventManager since it has no public constructors<BR> 691 */<BR> 692 public static void main(String args[]) {<BR> 693 System setSecurityManager(new InsecurityManager());<BR> 694 try {<BR> 695 EventManagerImpl eventManager = new EventManagerImpl();<BR> 696 } catch (Exception e) {<BR> 697 System out println("An exception occurred setting up the EventManager: " +<BR> 698 e.getMessage());<BR> 699 e.printStackTrace();<BR> 700 }<BR> 701 }<BR> 702<BR> 703 }<BR> 704<BR> 705 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventManagerProxy.java 1 10/22/96 7:30p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DECRIPTION<BR> 10 * A client proxy for the EventManager<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventManagerProxy java $<BR> 13 *<BR> 14 * 1 10/22/96 7 30p Noemi<BR> 15 * EventManagerProxy is the public interface to the EventManager It<BR> 16 * shields users from the effects of EventManager crashes<BR> 17 */<BR> 18<BR> 19 package com.meitca hsl zonesjagents event;<BR> 20<BR> 21 import java.io *;<BR> 22<BR> 23 import java.rmi.RemoteException;<BR> 24 import java.rmi.Naming;<BR> 25 import java.rmi.Remote;<BR> 26<BR> 27<BR> 28 /**<BR> 29 * EventManagerProxy is the public interface to the EventManager As a<BR> 30 * proxy for the Event Manager, it maintains a reference to the actual<BR> 31 * Event Manager and shields users from the effects of Event Manager<BR> 32 * crashes. Whenever the proxy fails to communicate with the Event Manager<BR> 33 * it attempts to re-estabilish a connection to it<BR> 34 *<BR> 35 * @see EventManager<BR> 36 * @see EventManagerImpl<BR> 37 * @author Noemi Paciorek<BR> 38 */<BR> 39<BR> 40 public class EventManagerProxy {<BR> 41<BR> 42 // Constants<BR> 43 protected static final int DEFAULT~RETRIES = 2;<BR> 44 protected static final long DEFAULT~TIMEOUT = 10000;<BR> 45<BR> 46<BR> 47 // Instance variables 48 /** Stub for EventManagerImpl's EventManager interface. */<BR> 49 protected EventManager eventManager;<BR> 50<BR> 51 /** Stub for EventManagerImpl's EventPost interface */<BR> 52 protected EventPost eventPost;<BR> 53<BR> 54 /** The EventManagerImpl's name. */<BR> 55 protected String eventManagerName,<BR> 56<BR> 57 /**<BR> 58 * The number of times to retry when an invocation<BR> 59 * on the EventManager fails<BR> 60 */<BR> 61 int retries;<BR> 62<BR> 63 /** The timeout period in ms for requests to the EventManager */<BR> 64 long timeout<BR> 65<BR> 66<BR> 67 // Constructors<BR> 68 /**<BR> 69 * Constructs an EventManagerProxy<BR> 70 */<BR> 71 public EventManagerProxy()<BR> 72 throws Exception {<BR> 73<BR> 74 this(DEFAULT~RETRIES, DEFAULT~TIMEOUT);<BR> 75 }<BR> 76<BR> 77<BR> 78 /**<BR> 79 * Constructs an EventManagerProxy<BR> 80 * @param retries The number of times to retry if an operation fails<BR> 81 */<BR> 82 public EventManagerProxy(int retries)<BR> 83 throws Exception {<BR> 84<BR> 85 this(retries, DEFAULT~TIMEOUT);<BR> 86 }<BR> 87<BR> 88<BR> 89 /**<BR> 90 * Constructs an EventManagerProxy.<BR> <P>91 * @param timeout The time to wait in ms between retries<BR> 92 */<BR> 93 public EventManagerProxy(long timeout)<BR> 94 throws Exception { 95<BR> 96 this(DEFAULT~RETRIES timeout);<BR> 97 }<BR> 98<BR> 99<BR> 100 /**<BR> 101 * Constructs an EventManagerProxy.<BR> <P>102 * @param retries The number of times to retry if an operation fails<BR> 103 * @ timeout The time to wait in ms between retries<BR> 104 */<BR> 105 public EventManagerProxy(int retries, long timeout)<BR> 106 throws Exception {<BR> 107<BR> 108 this.retries = (retries >= 0) ? retries DEFAULT~RETRIES;<BR> 109 this timeout = (timeout > 0) ? timeout DEFAULT~TIMEOUT;<BR> 110<BR> 111 /*<BR> 112 * Lookup the EventManager<BR> 113 */<BR> 114 initialize();<BR> 115 }<BR> 116<BR> 117<BR> 118 // Instance methods<BR> 119 /*<BR> 120 * Lookup the Event Manager in the RMI registry and obtain a<BR> 121 * stub for its EventManager and EventPost interfaces<BR> 122 */<BR> 123 private void initialize()<BR> 124 throws Exception {<BR> 125<BR> 126 eventManagerName = EventManagerImpl getEvenManagerName();<BR> 127 try {<BR> 128 Remote stub = Naming lookup(eventManagerName)<BR> 129 eventManager = (EventManager)stub;<BR> 130 eventPost = (EventPost)stub;<BR> 131 } catch (Exception e) {<BR> 132 System out.println("initialize; error looking up EventManager: "<BR> 133 - e.getMessage());<BR> 134 e.printStackTrace();<BR> 135 throw e;<BR> 136 }<BR> 137 }<BR> 138<BR> 139<BR> 140 /*<BR> 141 * Block for the timeout interval. Then look up the 142 * EventManager.<BR> <P>143 */<BR> 144 private void waitAndInitialize()<BR> 145 throws Exception {<BR> 146<BR> 147 synchronized(this) {<BR> 148 try {<BR> 149 this.wait(timeout);<BR> 150 } catch (InterruptedException e) { }<BR> 151 }<BR> 152 initialize();<BR> 153 }<BR> 154<BR> 155 /*<BR> 156 * Convert the event class names to strings<BR> 157 */<BR> 158 private String[] eventNametoString(EventType[] events) {<BR> 159<BR> 160 int length = events length;<BR> 161 String eventNames[] = new String[length];<BR> 162 for (int i = 0; i < length; i++) {<BR> 163 eventNames[i] = events[i] getClass().getName();<BR> 164 System out println("eventNametoString, event = " + eventNames[i]);<BR> 165 }<BR> 166 return eventNames,<BR> 167 }<BR> 168<BR> 169<BR> 170<BR> 171 // Methods to handle registrations<BR> 172<BR> 173 /**<BR> 174 * Register interest in receiving specified events<BR> 175 * @param events An array of events an object is interesed in receiving<BR> 176 * @param eventQueue The associated event queue's EventPost interface<BR> 177 * @exception RemoteException If an error occurrs settings up network<BR> 178 * connections<BR> 179 * @exception IOException If the tranport layer generates one.<BR> <P>180 */<BR> 181 public voidregisterEvents(EventType events[]. EventPost eventQueue)<BR> 182 throws Exception {<BR> 183<BR> 184 /*<BR> 185 * Convert the event class names to strings<BR> 186 * Then invoke the EventManager's registerEvants<BR> 187 * method and retry the operation, if necessary<BR> 188 */ 189 String eventNames[] = eventNametoString(events);<BR> 190 for (int i = 0; i <= retries; i++) {<BR> 191 try {<BR> 192 eventManager registerEvents(eventNames, eventQueue);<BR> 193 return;<BR> 194 } catch (RemoteException e1) {<BR> 195 if (i == retries) {<BR> 196 System.cut.println("registerEvents Throwing RemoteException");<BR> 197 throw e1,<BR> 198 }<BR> 199 System.out.println("registerEvents Caught RemoteException");<BR> 200 } catch (IOException e2) {<BR> 201 if (i == retries) {<BR> 202 System.cut println("registerEvents Throwing IOException");<BR> 203 throw e2<BR> 204 }<BR> 205 System out println("registerEvents Caught IOException");<BR> 206 }<BR> 207 /*<BR> 208 * Block for the timeout interval Then lock up the<BR> 209 * EventManager, before retrying the operation<BR> 210 */<BR> 211 waitAndInitialize();<BR> 212 }<BR> 213 }<BR> 214<BR> 215<BR> 216 /**<BR> 217 * Register interest in receiving all events posted to this EventManager<BR> 218 * @param. eventQueue The associated event queue's EventPost interface<BR> 219 * @exception RemoteException If an error occurrs setting up network<BR> 220 * connections<BR> 221 * @exception IOException If the tranport layer generates one<BR> 222 */<BR> 223 public void registerAll(EventPost eventQueue)<BR> 224 throws Exception {<BR> 225<BR> 226 /*<BR> 227 * Invoke the EventManager's registerAll<BR> 228 * method and retry the operation, if necessary<BR> 229 */<BR> 230 for (int i = 0; i <= retries; i++) {<BR> 231 try {<BR> 232 eventManager registerAll(eventQueue);<BR> 233 return;<BR> 234 } catch (RemoteException e1) {<BR> 235 if (i == retries) { 236 System.out.println("registerAll: Throwing RemoteException");<BR> 237 throw e1<BR> 238 }<BR> 239 System.out.println("registerAll Caught RemoteException");<BR> 240 } catch (IOException e2) {<BR> 241 if (i == retries) {<BR> 242 System.out println("registerAll Throwing IOException");<BR> 243 throw e2;<BR> 244 }<BR> 245 System out println("registerAll Caught IOException");<BR> 246 }<BR> 247 /*<BR> 248 * Block for the timeout interval. Then look up the<BR> 249 * EventManager, before retrying the operation<BR> 250 */<BR> 251 waitAndInitialize();<BR> 252 }<BR> 253 }<BR> 254<BR> 255<BR> 256 // Methods to unregister events<BR> 257 /**<BR> 258 * Remove registration for specified events<BR> 259 * @param events An array of events an object is interested in receiving.<BR> <P>260 * @param eventQueue The associated event queue's EventPost interface<BR> 261 * @exception RemoteException If an error occurrs setting up network<BR> 262 * connections<BR> 263 * @exception EventManagerException If the event queue was not registered<BR> 264 * for one or more of the specified exceptions<BR> 265 * @exception IOException If the tranport layer generates one<BR> 266 */<BR> 267 public void unregisterEvents(EventType events[], EventPost eventQueue)<BR> 268 throws Exception {<BR> 269<BR> 270 /*<BR> 271 * Convert the event class names to strings<BR> 272 * Then invoke the EventManager's registerEvents<BR> 273 * method and retry the operation, if necessary.<BR> <P>274 */<BR> 275 String eventNames[] = eventNametoString(events);<BR> 276 for (int i = 0; i <= retries; i++) {<BR> 277 try {<BR> 278 eventManager unregisterEvents(eventNames, eventQueue);<BR> 279 return;<BR> 280 } catch (RemoteException e1) {<BR> 281 if (i == retries) {<BR> 282 System out println("unregisterEvents Throwing RemoteException"); 283 throw e1;<BR> 284 }<BR> 285 System.out.println("unregisterEvents: Caught RemoteException");<BR> 286 } catch (IOException e2) {<BR> 287 if (i == retries) {<BR> 288 System.out.println("unregisterEvents: Throwing IOException");<BR> 289 throw e2;<BR> 290 }<BR> 291 System.out.println("unregisterEvents: Caught IOException");<BR> 292 }<BR> 293 /*<BR> 294 * Block for the timeout interval. Then look up the<BR> 295 * EventManager, before retrying the operation.<BR> <P>296 */<BR> 297 waitAndInitialize();<BR> 298 }<BR> 299 }<BR> 300<BR> 301<BR> 302 /**<BR> 303 * Remove registration for all events<BR> 304 * @param eventQueue The associated event queue's EventPost interface<BR> 305 * This method is often called by finalizers, so it does not<BR> 306 * propagate any errors<BR> 307 */<BR> 308 public void unregisterAll (EventPost eventQueue) {<BR> 309 /*<BR> 310 * Invoke the EventManager's registerAll<BR> 311 * method and retry the operation, if necessary<BR> 312 */<BR> 313 for (int i = 0 i <= retries; i++) {<BR> 314 try;<BR> 315 eventManager unregisterAll(eventQueue);<BR> 316 return;<BR> 317 } catch (RemoteException e1) {<BR> 318 System.out.println("unregisterAll: Caught RemoteException");<BR> 319 } catch (IOException e2) {<BR> 320 System.out.println("unregisterAll: Caught IOException");<BR> 321 }<BR> 322 /*<BR> 323 * Block for the timeout interval. Then look up the<BR> 324 * EventManager, before retrying the operation<BR> 325 */<BR> 326 try {<BR> 327 waitAndInitialize();<BR> 328 } catch (Exception e3) {<BR> 329 System.out.println("waitAndInitialize failed"); 330 }<BR> 331 }<BR> 332 }<BR> 333<BR> 334<BR> 335 // Methods to post events<BR> 336<BR> 337 /**<BR> 338 * Event notification interface<BR> 339 * @param event The event to post<BR> 340 * @exception RemoteException If an error occurrs setting up network<BR> 341 * connections<BR> 342 * @exception EventException If an error occurs posting the event<BR> 343 * @exception IOException If the tranport layer generates one<BR> 344 */<BR> 345 public void postEvent(EventType event)<BR> 346 throws Exception {<BR> 347 /*<BR> 348 * Invoks the EventManager's eventPost<BR> 349 * method and retry the operation, if necessary<BR> 350 */<BR> 351 for (int i = 0; i <= retries; i++) {<BR> 352 try {<BR> 353 eventPost.postEvent(event);<BR> 354 return;<BR> 355 } catch (RemoteException e1) {<BR> 356 if (i == retries) {<BR> 357 System out println("postEvent Throwing remoteException");<BR> 358 throw e1<BR> 359 }<BR> 360 System out println("postEvent Caught RemoteException");<BR> 361 } catch (IOException e2) {<BR> 362 if (i == retries) {<BR> 363 System.out println("postEvent Throwing IOException");<BR> 364 throw e2;<BR> 365 }<BR> 366 System.out.println("postEvent: Caught IOException");<BR> 367 }<BR> 368 /*<BR> 369 * Block for the timeout interval. Then look up the<BR> 370 * EventManager, before retrying the operation<BR> 371 */<BR> 372 waitAndInitialize();<BR> 373 }<BR> 374 }<BR> 375 }<BR> 376 377 1 /* $Header: /com/meitca/hsl zonesjagents/event/EventPost java 2 10/22/96 7:10p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Interface for event notification<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventPost java $<BR> 13 *<BR> 14 * 2 10/22/96 7:10p Noemi<BR> 15 * Changed the throws clause of the postEvent method<BR> 16 *<BR> 17 * 1 10/14/96 6 5@p Noemi<BR> 18 * Interface used for posting events<BR> 19 */<BR> 20<BR> 21 package com.meitca hsl zonesjagents event;<BR> 22<BR> 23 import java.io *;<BR> 24<BR> 25 import java.rmi.Remote;<BR> 26 import java.rmi.RemoteException<BR> 27<BR> 28 /**<BR> 29 * EventPost is a distributed RMI interface for notification of events<BR> 30 *<BR> 31 * @author Noemi Paciorek<BR> 32 */<BR> 33<BR> 34 public interface EventPost<BR> 35 extends Remote<BR> 36<BR> 37 // Instance methods<BR> 38 /**<BR> 39 * Event notification interface.<BR> <P>40 * @param event The event to post<BR> 41 * @exception RemoteException If an error occurrs setting up network<BR> 42 * connections<BR> 43 * @exception EventException If an error occurs posting the event<BR> 44 */<BR> 45 public void postEvent (EventType event)<BR> 46 throws RemoteException, EventException, IOException;<BR> 47 48 } 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventQueueImpl java 1 10/14/96 6:58p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Event queue distr buted object<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventQueueImpl java $<BR> 13 *<BR> 14 * 1 10/14/96 6:58p Noemi<BR> 15 * Event queue implementation<BR> 16 */<BR> 17<BR> 18 package com.meitca.hsl zonesjagents.event;<BR> 19<BR> 20 import java util<BR> 21<BR> 22 import java rmi server UnicastRemoteServer;<BR> 23 import java rmi.RemoteException,<BR> 24 import java.rmi.Naming;<BR> 25 import java.rmi.NotBoundException,<BR> 26<BR> 27 /**<BR> 28 * EventQueueImpl is an event queue that implements the RMT<BR> 29 * EventPost interface<BR> 30 *<BR> 31 * Event notification is performed by appending an event to the queue.<BR> <P>32 * Each queue has an associated EventQueueThread started by the constructor<BR> 33 * The thread dequeues events and calls their handlers.<BR> <P>34 *<BR> 35 * @see EventQueueThread<BR> 36 * @see EventPost<BR> 37 * @author Noemi Paciorek<BR> 38 */<BR> 39<BR> 40 public class EventQueueImpl<BR> 41 extends UnicastRemoteServer<BR> 42 implements EventPost {<BR> 43<BR> 44 // Instance variables<BR> 45 /** The event queue */<BR> 46 protected Vector eventQueue<BR> 47 48 /** The thread that manages this queue */<BR> 49 protected EventQueueThread queueThread;<BR> 50<BR> 51 // Constructors<BR> 52 /**<BR> 53 * Protected Default Constructor for EventQueueImpl<BR> 54 * exception IllegalAccessException Whenever called<BR> 55 */<BR> 56 protected EventQueueImpl()<BR> 57 throws RemoteException, IllegalAccessException {<BR> 58<BR> 59 System.out pr@ntl("Default constructor called for EventQueueImpl");<BR> 60 throw new IllegalAccessException("EventQueueImpl default constructor");<BR> 61 }<BR> 62<BR> 63 /**<BR> 64 * Constructs an EventQueueImpl<BR> 65 * @param handler An EventHandler interface.<BR> <P>66 */<BR> 67 public EventQueueImpl(EventHandler handler)<BR> 68 throws RemoteException:<BR> 69 eventQueue = new Vector();<BR> 70 queueThread = new EventQueueThread(this, handler);<BR> 71 }<BR> 72<BR> 73 /**<BR> 74 * Constructs an EventQueueImpl<BR> 75 * @param handler An EventHandler interface.<BR> <P>76 * @param timeout The time in ms to wait between consecutive queue<BR> 77 * examinations<BR> 78 */<BR> 79 public EventQueueImpl(EvenHandler handler, long timeout)<BR> 80 throws RemoteException<BR> 81 eventQueue = new Vector();<BR> 82 queueThread = new EventQueueThread(this, handler, timeout);<BR> 83 }<BR> 84<BR> 85 // Instance methods<BR> 86 /**<BR> 87 * Posts an event by enqueueing it and waking up the<BR> 88 * queue's thread.<BR> <P>89 * @param event The event to post<BR> 90 */<BR> 91 public synchronized void postEvent(EventType event) {<BR> 92 System.out.println("EventQueueImpl, posting event");<BR> 93 enqueue(event);<BR> 94 this notifyAll() 95 }<BR> 96<BR> 97 /**<BR> 98 * Enqueues an event.<BR> <P>99 * @param event The event to queue<BR> 100 */<BR> 101 protected final synchronized void enqueue(EventType event) {<BR> 102 eventQueue addElement(event);<BR> 103 }<BR> 104<BR> 105 /**<BR> 106 * Dequeues an event<BR> 107 * @return The first event in the queue<BR> 108 */<BR> 109 protected final synchronized EventType dequeue()<BR> 110 throws ArrayIndexOutOfBoundsException {<BR> 111<BR> 112 if (!eventQueue.isEmpty()) {<BR> 113 EventType event = (EventType) (eventQueue firstElement()):<BR> 114 eventQueue.remoteElementAt(0);<BR> 115 return event;<BR> 116 }<BR> 117 return null<BR> 118 }<BR> 119 }<BR> 120<BR> 121<BR> 122<BR> 123<BR> 124<BR> 125<BR> 126<BR> 127 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventQueueThread.java 1 10/14/96 6:59p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Thread that manages an event queue<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/event/EventQueueThread.java $<BR> 13 *<BR> 14 * 1 10/14/96 6 59p Noemi<BR> 15 * Thread to manage the event queue<BR> 16 */<BR> 17<BR> 18 package com.meitca hs~ zonesjagents event;<BR> 19<BR> 20 /**<BR> 21 * EventQueueThread is a Thread that manages an event queue<BR> 22 * Event notification is implemented by appending a event to the queue<BR> 23 * and waking up its EventQueueThread to process the event by calling its<BR> 24 * event handler.<BR> <P>25 * The EventQueueThread is instantiated by the EventQueueImpl constructor<BR> 26 *<BR> 27 * @see EventQueueImpl<BR> 28 * @see EventPost<BR> 29 * @see EventHandler<BR> 30 * @author Noemi Paciorek<BR> 31 */<BR> 32 class EventQueueThread<BR> 33 extends Thread {<BR> 34<BR> 35 // Constants<BR> 36 //* The default timeout value in ms */<BR> 37 public static final long DEFAULT~TIMEOUT = 1000;<BR> 38<BR> 39 // Instance variables<BR> 40 /** This thread's event queue */<BR> 41 protected EventQueueImpl eventQueue;<BR> 42<BR> 43 /** The application's event handler */<BR> 44 protected EventHandler eventHandler;<BR> 45<BR> 46 /** The time is ms between consecutive examinations of the queue. */<BR> 47 protected long timeout; 48<BR> 49 // Constructors<BR> 50 /**<BR> 51 * Protected Default Constructor for an EventQueueThread<BR> 52 * @exception IllegalAccessException Whenever called.<BR> <P>53 */<BR> 54 protected EventQueueThread(<BR> 55 throws IllegalAccessException {<BR> 56<BR> 57 System.out.println("Default constructor called for EventQueueThread");<BR> 58 throw new IllegalAccessExcpetion("EventQueueThread default constructor");<BR> 59 }<BR> 60<BR> 61 /** Constructs an EventQueueThread<BR> 62 * @param queue The associated event queue.<BR> <P>63 * @param handler The associated event handler interface<BR> 64 */<BR> 65 public EventQueueThread(EventQueueImpl queue, EventHandler handler) {<BR> 66 this(queue, handler, DEFAULT~TIMEOUT);<BR> 67 }<BR> 68<BR> 69 /** Constructs an EventQueueThread<BR> 70 * @param queue The associated event queue<BR> 71 * @param handler The associated event handler interface.<BR> <P>72 * @param timeout The time in ms to wait between consecutive queue<BR> 73 * examinations<BR> 74 */<BR> 75 public EventQueueThread(EventQueueImpl queue, EventHandler handler, long timeout) {<BR> 76 eventQueue = queue<BR> 77 eventHandler = handler;<BR> 78 this timeout = timeout<BR> 79 this start@)<BR> 80 }<BR> 81<BR> 82 // Instance methods<BR> 83<BR> 84 /**<BR> 85 * The thread's run method<BR> 86 */<BR> 87 public void run() {<BR> 88 while (true {<BR> 89 try {<BR> 90 synchronized(eventQueue) {<BR> 91 eventQueue.wait(timeout);<BR> 92 }<BR> 93 } catch (InterruptedException e) { }<BR> 94 95 EventType event;<BR> 96 while ((event = eventQueue.dequeue()) != null) {<BR> 97 System out.println("EventQueueThread, handling event");<BR> 98 try {<BR> 99 eventHandler.handleEvent(event);<BR> 100 } catch (Exception ex) {<BR> 101 System.out println("EvenQueueThread can't handle event. " +<BR> 102 ex.getMessage());<BR> 103 ex.printStackTrace();<BR> 104<BR> 105 }<BR> 106 }<BR> 107 }<BR> 108 }<BR> 109<BR> 110<BR> 111<BR> 112<BR> 113<BR> 114<BR> 115<BR> 116 1 /* $Header: /com/meitca/hsl/zonesjagents/event/EventType java 1 10/14/96 6:55p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA.<BR> <P>8 *<BR> 9 * DESCRIPTION<BR> 10 * Base class for distributed events<BR> 11 *<BR> 12 * $Log. /com/meitca/hsl/zonesjagents/event/EventType java $<BR> 13 *<BR> 14 * 1 10/14/96 6:55p Noemi<BR> 15 * Base class for distributed events<BR> 16 */<BR> 17<BR> 18 package com.meitca hsl zonesjagents event;<BR> 19<BR> 20 import com.meitca.hsl util UniqueID;<BR> 21<BR> 22 /**<BR> 23 * Base class for distributed events EventType describes an event.<BR> <P>24 * It contains: a unique ID (generated by the EventManager) and a description<BR> 25 * (optionally passed to the constructors)<BR> 26 *<BR> 27 * Applications must derive and handle their own event types<BR> 28 *<BR> 29 * @author Noemi Paciorek<BR> 30 */<BR> 31<BR> 32 abstract public class EventType {<BR> 33<BR> 34 // Constants<BR> 35 private static final String UNKNOWN = "Unknown";<BR> 36 private static final String TYPE = "event";<BR> 37<BR> 38 // Instance variables<BR> 39 /* A unique ID representing the event */<BR> 40 protected String eventID;<BR> 41<BR> 42 /** A description of the event */<BR> 43 protected String description;<BR> 44<BR> 45<BR> 46 // Constructors<BR> 47 /** Constructors an EventType */ 48 public EventType () {<BR> 49 this(UNKNOWN);<BR> 50 }<BR> 51<BR> 52 /** Constructs an EventType<BR> 53 * @param description A String describing the event<BR> 54 */<BR> 55 public EventType(String description);<BR> 56 eventID = UniqueID.getNextID(TYPE, this);<BR> 57 System.out.println("eventID = " + eventID);<BR> 58 this description = description;<BR> 59 }<BR> 60<BR> 61<BR> 62 // Instance methods<BR> 63 /**<BR> 64 * String representation of event.<BR> <P>65 * @return A String representation of the event.<BR> <P>66 */<BR> 67 public final String toString() {<BR> 68 return (eventID + " " + description);<BR> 69 return (eventID + " " + description);<BR> 69 }<BR> 70<BR> 71 /**<BR> 72 * Retrieve an event's ID<BR> 73 * @return. The event's ID<BR> 74 */<BR> 75 public final String getEvenID() {<BR> 76 return eventID;<BR> 77 }<BR> 78<BR> 79 /**<BR> 80 * Retrieve an event's description<BR> 81 * @return A description of the event<BR> 82 */<BR> 83 public final String getEvenDescription() {<BR> 84 return description;<BR> 85 }<BR> 86<BR> 87 }<BR> 88<BR> 89<BR> 90<BR> 91<BR> 92<BR> 93<BR> 94 95<BR> 96<BR> 97<BR> 98 1 /* $Header: /com/meitca/hsl/zonesjagents/shared/PersistentStoreHandler.j ava 1 10/22/96 7:32p Noemi $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Systems Laboratory, Mitsubishi Electric<BR> 4 * Information Technology Center America.<BR> <P>5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * Persistent Store Manager wrapper that handles exceptions<BR> 11 *<BR> 12 * $Log: /com/meitca/hsl/zonesjagents/shared/PersistentStoreHandler java $<BR> 13 *<BR> 14 * 1 10/22/96 7:32p Noemi<BR> 15 * A generic wrapper for PersistentStoreManager that catches exceptions<BR> 16 * and retries operations, as necessary.<BR> <P>17 */<BR> 18<BR> 20 package com.meitca hsl zonesjagents shared;<BR> 21 import com.meitca.hsl.zonesjagents.persistence *;<BR> 22<BR> 23 /**<BR> 24 * A wrapper class for the persistent storage manager<BR> 25 * (persistence.PersistentStoreManager)that catches<BR> 26 * all its exceptions and performs the appropriate cleanup<BR> 27 * commat;see PersistentStoreManager<BR> 28 * @author Noemi Paciorek<BR> 29 */<BR> 30 public class PersistentStoreHandler {<BR> 31<BR> 32 // Instance variables<BR> 33 /** A reference to the persistent store manager. */<BR> 34 protected PersistentStoreManager persistenceManager.<BR> <P>35<BR> 36 // Constructors<BR> 37 /**<BR> 38 * Constructs a PersistentStoreHandler<BR> 39 * @param filename The name of the persistent storage file<BR> 40 */<BR> 41 public PersistentStoreHandler(String filename) {<BR> 42 try {<BR> 43 persistenceManager = new PersistentStoreManager(filename);<BR> 44 } catch (PersistentStoreException e) {<BR> 45 System.out.println("PersistentStoreHadler. can't create persistent store manager " + e getMessa<BR> 46 e.printStackTrace();<BR> 47 pers~stenceManager = null; 48 }<BR> 49 }<BR> 50<BR> 51 // Finalizer<BR> 52 /**<BR> 53 * Deletes reference to Per~stentStoreManager.<BR> <P>54 */<BR> 55 protected void finalize()<BR> 56 throws Throwable {<BR> 57<BR> 58 System.out println ("PersistentStoreHandler Finalizer called");<BR> 59<BR> 60 // Delete reference to Persistent Store Manager<BR> 61 persistenceManager = null;<BR> 62<BR> 63 super.final~ze ();<BR> 64 }<BR> 65<BR> 66<BR> 67<BR> 68 // Instance methods<BR> 69 /**<BR> 70 * Find an object in the persist store.<BR> <P>71 * @param object The Object to locate.<BR> <P>72 * @return The Object's persistent storage ID.<BR> <P>73 */<BR> 74 public int findObject(Object object) {<BR> 75 return pers~stenceManager findObject (object);<BR> 76 }<BR> 77<BR> 78 /**<BR> 79 * Insert an Object into persistent storage.<BR> <P>80 * If a storage manager exception occurs, attempt to<BR> 81 * truncate the persistent storage and disable persistence<BR> 82 * @param object The Object represented by id.<BR> <P>83 * @return The Object's persistent storage ID.<BR> <P>84 * A return value of PersistentStoreManager. INVALID~OID indicates<BR> 85 * an unsuccessful attempt to insert the object<BR> 86 */<BR> 87 public int insertObject(Object object) {<BR> 88 return insertObject(0, object, 0);<BR> 89 }<BR> 90<BR> 91<BR> 92 /**<BR> 93 * Insert an Object into persistent storage.<BR> <P>94 * If a storage manager exception occurs, attempt to 95 * truncate the persistent storage and disable persistence.<BR> <P>96 * @param Object The Object represented by id.<BR> <P>97 * @param space The additional space in bytes to be preallocated<BR> 98 * for this object<BR> 99 * @return The Object's persistent storage ID.<BR> <P>100 * A return value of PersistentStoreManager INVALID~OID indicates<BR> 101 * an unsuccessful attempt to insert the object<BR> 102 */<BR> 103 public int insertObject(Object object, int space) {<BR> 104 return insertObject (0, object, spoace);<BR> 105 }<BR> 106<BR> 107<BR> 108 /**<BR> 109 * Insert an Object into persistent storage<BR> 110 * If a storage manager exception occurs, attempt to<BR> 111 * truncate the persistent storage and disable persistence<BR> 112 * @param id The Object's persistent storage ID<BR> 113 * @param Object The Object represented by id<BR> 114 * @return The Object's persistent storage ID.<BR> <P>115 * A return value of PersistentStoreManager. INVALID~OID indicates<BR> 116 * an unsuccessful attempt to insert the object<BR> 117 */<BR> 118 public int insertObject (int id, Object object) {<BR> 119 return insertObject (id, object, 0);<BR> 120 }<BR> 121<BR> 122<BR> 123 /**<BR> 124 * Insert an Object into persistent storage.<BR> <P>125 * If a storage manager exception occurs, attempt to<BR> 126 * truncate the persistent storage and disable persistence<BR> 127 * @param id The Object's persistent storage ID.<BR> <P>128 * @param Object The Object represented by id.<BR> <P>129 * @param space The additional space in bytes to be preallocated<BR> 130 * for this object.<BR> <P>131 * A return value of PersistentStoreManager. INVALID~OID indicates<BR> 132 * an unsuccessful attempt to insert the object.<BR> <P>133 */<BR> 134 public int insertObject (int id, Object object, int space) {<BR> 135 if (persistenceManager == null)<BR> 136 return PersistentStoreManager.INVALID~OID;<BR> 137<BR> 138 try {<BR> 139 if (id == 0)<BR> 140 return persistenceManager.insertObject(object, space);<BR> 141 return persistenceManager.insertObject(id, object, space); 142 } catch (PersistentStoreDuplicateObjectException el) {<BR> 143 try {<BR> 144 id = persistenceManager.findObject(object);<BR> 145 if (id != PersistentStoreManager.INVALID~OID) {<BR> 146 persistenceManager updateObject(id, object);<BR> 147 return id;<BR> 148 }<BR> 149 } catch (PersistenceStoreException e2) {<BR> 150 Sytem.out.princln("insertObject: duplicate object found" + e2.getMessage());<BR> 151 e2.printStackTrace();<BR> 152 truncateFileStore();<BR> 153 persistenceManager = null;<BR> 154 }<BR> 155 } catch (PersistentStoreInvalidObjectException e3) {<BR> 156 Sytem.out.println("insertObject: invalid ID" + e3.getMessage());<BR> 157 e3.printStackTrace();<BR> 158 } catch (PersistentStoreException e4) {<BR> 159 Syytem.out.println('insertObject: can't insert object " + e4.getMessage());<BR> 160 e4.printStackTrace( :<BR> 161 trunacateFileStore()<BR> 162 persistentManager = null;<BR> 163 }<BR> 164 return PersistentStoreManager INVALID~OID;<BR> 165 }<BR> 166<BR> 167<BR> 168 /**<BR> 169 * Fetch an Object from persistent storage<BR> 170 * If a storage manager exception occurs, attempt to<BR> 171 * truncate the persistent storage and disable persistence<BR> 172 * @param id The Object's persistent storage ID.<BR> <P>173 * @return Object The Object represented by id, or null,<BR> 174 * if the Object was not found in persistent storage<BR> 175 */<BR> 176 public Object fetchObject (int id) {<BR> 177 of (persistenceManager == null)<BR> 178 return null;<BR> 179<BR> 180 try {<BR> 181 return persistanceManager.fetchObject(id);<BR> 182 } catch (PersistentStoreObjectNotFoundException e1) {<BR> 183 Sytem.out.println("fetchObject: Object not found in persistent store, ID = " + id);<BR> 184 } catch (PersistentStoreInvalidObjectException e2) {<BR> 185 System.out.princln("fetchObject invalid ID" + e2.getMessage());<BR> 186 e2.printStackTrace();<BR> 187 } catch (PersistentStoreException e3) {<BR> 188 System out.println("fetchObject: can't fetch object " + e3getMessage ()); 189 e3.printStackTrace();<BR> 190 truncateFileStore();<BR> 191 persistenceManager = null;<BR> 192 }<BR> 193 return null<BR> 194 }<BR> 195<BR> 196<BR> 197 /**<BR> 198 * Update an Object in persistent storage<BR> 199 * If a storage manager exception occurs, attempt to<BR> 200 * truncate the persistent storage and disable persistence<BR> 201 * @param id The Object's persistent storage ID.<BR> <P>202 * @param Object The updated Object represented by id.<BR> <P>203 * @return A boolean indicating if the update was successful<BR> 204 */<BR> 205 public boolean updateObject(int id, Object object) {<BR> 206 if (persistenceManager == null)<BR> 207 return false;<BR> 208<BR> 209 try {<BR> 210 persistenceManager.updateObject(id, object);<BR> 211 return true,<BR> 212 } catch (PersistentStoreObjectNotFoundException e1) {<BR> 213 Syytem.out.println ('updateObject: Object not found in persistent store, ID = " + id);<BR> 214 try {<BR> 215 persistenceManager insertObject (id, object);<BR> 216 return true;<BR> 217 } catch (PersistentStoreException e2) {<BR> 218 System out println ("updateObject can't insert object " + e2 getMessage ().);<BR> 219 e2.printStackTrace();<BR> 220 truncateFileStore();<BR> 221 pers-stenceManager = null;<BR> 222 }<BR> 223 } catch (PersistentStoreInvalidObjectException e3) {<BR> 224 System.out.println("updateObject. invalid ID" + e3 getMessage());<BR> 225 e3 printStackTrace ();<BR> 226 } catch (PersistentStoreException e4) {<BR> 227 System out.println("updateObject: can't update object " + e4.getMessage ());<BR> 228 e4.printStackTrace();<BR> 229 truncateFileStore();<BR> 230 persistenceManager = null;<BR> 231 }<BR> 232 return false;<BR> 233 }<BR> 234<BR> 235 283 try {<BR> 284 persistenceManager truncateFileStore ();<BR> 285 return true;<BR> 286 } catch(Exception e) {<BR> 287 System out println('truncateFileStore. can't truncate store " + e getMessage());<BR> 288 e.printStackTrace()<BR> 289 persistenceManager = null;<BR> 290 return false,<BR> 291 }<BR> 292 }<BR> 293<BR> 294 /**<BR> 295 * Return a reference to the persistent storage manager.<BR> <P>296 */<BR> 297 public PersistentStoreManager getPersistenceManager () {<BR> 298 return persistenceManager;<BR> 299 }<BR> 300 }<BR> 301<BR> 302<BR> 303<BR> 304 236 /**<BR> 237 * Delete an object from persistent storage.<BR> <P>238 * If a storage manager exception occurs, attempt to<BR> 239 * truncate the persistent storage and disable persistence<BR> 240 * @param id The Object's persistent storage ID.<BR> <P>241 * @return A boolean indicating if the deletion was successful.<BR> <P>242 */<BR> 243 public boolean deleteObject(int id) {<BR> 244 if (persistenceManager == null)<BR> 245 return false,<BR> 246<BR> 247 try {<BR> 248 persistenceManager deleteObject(id);<BR> 249 return true;<BR> 250 } catch (PersistentStoreObjectNotFoundEception e1) {<BR> 251 System.out println ("deleteObject Object not found in persistent store, ID = " + id);<BR> 252 } catch (PersistentStoreInvalidObjectException e2) {<BR> 253 System out.println ("deleteObject invalid ID" + e2 getMessage ());<BR> 254 e2.printStackTrace();<BR> 255 } catch (PersistentStoreException e3) {<BR> 256 System out.println ('deleteObject: can't delete object " + e3.getMessage ());<BR> 257 e3.printStackTrace ( ;<BR> 258 truncateFileStore ()<BR> 259 persistenceManager = null;<BR> 260 }<BR> 261 return false,<BR> 262 }<BR> 263<BR> 264<BR> 265 /**<BR> 266 * Disable storage of objects in persistent store This method<BR> 267 * also truncates the persistent storage files to 0 bytes<BR> 268 */<BR> 269 public void disablePersistence () {<BR> 270 truncateFileStore ();<BR> 271 persistenceManager = null<BR> 272 }<BR> 273<BR> 274<BR> 275 /**<BR> 276 * Truncate the persistent storage file to 0 bytes If a storage manager<BR> 277 * exception occurs, disable persistence<BR> 278 */<BR> 279 public boolean truncateFileStore () {<BR> 280 if (persistenceManager == null)<BR> 281 return false;<BR> 282 1 /* $Header: /com/meitca/hsl/util/UniqueID.java 1 10/15/96 7.20a Billp $<BR> 2 *<BR> 3 * Copyright 1996 Horizon Sytems Laboratory. Mitsubishi Electric<BR> 4 * Information Technology Carter America<BR> 5 * All rights reserved<BR> 6 *<BR> 7 * CONFIDENTIAL AND PROPRIETARY PROPERTY OF MITSUBISHI ELECTRIC ITA<BR> 8 *<BR> 9 * DESCRIPTION<BR> 10 * This class generates IDs that are unique across distributed systems<BR> 11 * $Log: /com/meitca/hsl/util/UniqueID java $<BR> 12 *<BR> 13 * 1 10/15/96 7.20a Billp<BR> 14 */<BR> 15<BR> 16 package com.meitca.hsl.util;<BR> 17<BR> 18 import java.util *;<BR> 19<BR> 20 import java net InetAddress;<BR> 21<BR> 22 /**<BR> 23 * This class generates Ids that are unique within a Java VM.<BR> <P>24 * It is used by classes that need to generate unique IDs<BR> 25 *<BR> 26 * @author Noemi Paciorek<BR> 27 */<BR> 28 public class UniqueID {<BR> 29<BR> 30 // Class variables<BR> 31 /** A counter used in generating IDs */<BR> 32 protected static long IDNum = 0<BR> 33<BR> 34 /** A unique ID representing the host */<BR> 35 protected static String host;<BR> 36<BR> 37 // Static initializer<BR> 38 static {<BR> 39 /*<BR> 40 * Try to obtain the host's name and IP address. If this fails,<BR> 41 * construct a pseudo-random name and hope for the best! (Of course,<BR> 42 * this should never happen.)<BR> 43 */<BR> 44 try {<BR> 45 host = InetAddress.getLocalHost().toString();<BR> 46 ) catch (Exception e) {<BR> 47 host = "~HOSTID~" + new Random() nextLong(); 48 }<BR> 49 }<BR> 50<BR> 51<BR> 52 // Constructors<BR> 53 // No accessible constructors<BR> 54 /**<BR> 55 * Protected Default Constructor for UniqueID.<BR> <P>56 * This class never needs to be instantiated since all its variables<BR> 57 * and methods are static<BR> 58 * @exception IllegalAccessException Whenever called<BR> 59 */<BR> 60 protected UniqueID()<BR> 61 throws IllegalAccessException {<BR> 62<BR> 63 System.out.println("Default constructor called for UniqueID");<BR> 64 throw new IllegalAccessException("UniqueID default constructor");<BR> 65 }<BR> 66<BR> 67<BR> 68 // Class methods<BR> 69 /**<BR> 70 * this method attempts to create an ID that is unique across<BR> 71 * Java VMs. The ID is created from: the hostname, an application type<BR> 72 * (e.g., agent), the current time in ms, and the virtual memory<BR> 73 * address of the object being created.<BR> <P>74 *<BR> 75 * @param type A String containing an application type, e.g., "agent"<BR> 76 * @param object The this" reference of the calling object<BR> 77 */<BR> 78 public static String getNextID(String type, Object object) {<BR> 79 return (host + "/" + type + nextIDNum () + "/" +<BR> 80 System currentTimeMillis () + Integer toHexString(object hashCode ()));<BR> 81 }<BR> 82<BR> 83<BR> 84 private static final synchronized long nextIDNum() {<BR> 85 return +IDNum;<BR> 86 }<BR> 87<BR> 88 }