Release Notes for JSDT 1.5
[Last updated 14th May 1999].
Contents
Changes in JSDT 1.5
Changes in JSDT 1.4
Changes in JSDT 1.3
Changes in JSDT 1.2
Changes in JSDT 1.1
Changes from JSDA
Migrating from JSDT 1.4 to JSDT 1.5
Getting JSDT to Work Through Firewalls
JDK 1.2 Policy Files for the examples
How to get the HotJava Browser
How to get the LRMP Distribution
How to make jsdt.jar smaller
JSDT Interest Mailing List
Trouble Shooting
More Information on JSDT
Changes in JSDT 1.5
These are the changes between JSDT 1.4 and JSDT 1.5.
New Features and Improvements.
API Changes.
Bugs Fixed.
Changes to the User Guide.
Changes to the Examples.
New exceptions.
- TimedOutException, which will get thrown if no reply was
received for this operation in the given timeout period. This
affects nearly all the methods in the JSDT API.
- InvalidClientException, which gets thrown if the Client handle
provided is invalid (ie. returns a null from its getName() method).
This exception is now thrown by most JSDT API methods.
New classes.
- URLString, which encapsulates the creation and parsing of JSDT
Session and Client URL Strings. It contains the following methods:
public
URLString(String url);
public static URLString
createSessionURL(String hostName, int port,
String connectionType, String sessionName);
public static URLString
createClientURL(String hostName, int port,
String connectionType, String clientName);
public String
getHostAddress();
public String
getHostName();
public String
getProtocol();
public int
getPort();
public String
getConnectionType();
public String
getObjectType();
public String
getObjectName();
public boolean
isValid();
public String
toString();
Classes with new methods.
- RegistryFactory.java
public static void
startRegistry(String registryType, int port)
throws RegistryExistsException, NoRegistryException;
public static void
stopRegistry(String registryType)
throws NoRegistryException;
public static void
stopRegistry(String registryType, int port)
throws NoRegistryException;
public static boolean
registryExists(String registryType, int port)
throws NoRegistryException;
- ClientFactory.java
// signatures changes to use URLString.
public static void
createClient(URLString urlString, Client client,
ClientListener listener);
public static boolean
clientExists(URLString urlString);
- SessionFactory.java
// signature changes to use URLString.
public static Session
createSession(URLString urlString);
public static Session
createSession(Client client, URLString urlString, boolean autoJoin);
public static Session
createSession(URLString urlString, SessionManager sessionManager);
public static boolean
sessionExists(URLString urlString);
public static boolean
sessionManaged(URLString urlString);
// determine if a Session is managed.
public static boolean
sessionManaged(String url);
- Naming.java
// signature changes to use URLStrings
public static void
bind(URLString urlString, Object object);
public static void
rebind(URLString urlString, Object object);
public static void
unbind(URLString urlString);
public static Object
lookup(URLString urlString);
// lists all the url strings of the known bound JSDT objects on
// the given host.
public static String[]
list(String host, String connectionType);
- Manageable.java
// event masking on the managers.
public void
enableManagerEvents(JSDTManager manager, int eventMask);
public void
disableManagerEvents(JSDTManager manager, int eventMask);
- Session.java
// changes to the way ByteArrays are created. They are now initially
// created with a zero filled byte array of length one. Then use the
// setValue() method calls to set the actual value.
public ByteArray
createByteArray(Client client, String byteArrayName, boolean autoJoin);
public ByteArray
createByteArray(Client client, String byteArrayName,
ByteArrayManager byteArrayManager);
// determine if a ByteArray, Channel or Token is managed.
public boolean
byteArrayManaged(String byteArrayName);
public boolean
channelManaged(String channelName);
public boolean
tokenManaged(String tokenName);
// close a Session (and possibly it's network connection).
public void
close(boolean closeConnection);
- ByteArray.java
// methods to make it easier to get/set objects in a ByteArray.
public void
setValue(Client client, String string);
public void
setValue(Client client, Object object);
public byte[]
getValueAsBytes();
public Object
getValueAsObject();
public byte[]
getValueAsString();
- Data.java
public
Data(Object object);
public Object
getDataAsObject();
public String
getDataAsString();
public byte[]
getDataAsBytes();
Classes with deprecated methods.
- ClientFactory.java
public static void
createClient(String url, Client client, ClientListener listener);
public static boolean
clientExists(String url);
- SessionFactory.java
public static Session
createSession(String url);
public static Session
createSession(Client client, String url, boolean autoJoin);
public static Session
createSession(String url, SessionManager sessionManager);
public static boolean
sessionExists(String url);
- Naming.java
public static void
bind(String name, Object object);
public static void
rebind(String name, Object object);
public static void
unbind(String name, Object object);
public static Object
lookup(String name);
- Session.java
public ByteArray
createByteArray(Client client, String byteArrayName,
byte[] value, boolean autoJoin);
public ByteArray
createByteArray(Client client, String byteArrayName, byte[] value,
ByteArrayManager byteArrayManager);
public ByteArray
createByteArray(Client client, String byteArrayName, byte[] value,
int offset, int length, boolean autoJoin);
public ByteArray
createByteArray(Client client, String byteArrayName,
byte[] value, int offset, int length,
ByteArrayManager byteArrayManager);
public void
close();
- ByteArray.java
public byte[]
getValue();
- Data.java
public byte[]
getData();
- For the socket and lrmp implementations, if you tried to send Data over a
Channel without first joining it, you got a NullPointerException.
- For the socket and lrmp implementations, if you tried to receive data
sent over a Channel without first joining it, a NullPointerException
was thrown.
- There was a hang if try to list something on a session after destroying
it rather than throwing an exception. Create a session, then a channel,
then destroy the session, close the session then attempt to do
channel.listClientNames() at which point it hangs.
- Rather than loop continuously in RegistryFactory.startRegistry() waiting
for the Registry to start, a check has been added, that causes a
NoRegistryException to be thrown after a certain amount of time, if the
Registry hasn't successfully started. This uses the
JSDTObject.registryTime variable (which is user settable), to determine
the amount of time (in seconds), before a NoRegistryException is thrown.
- For the socket implementation, calling
RegistryFactory.registryExists(type) with the Registry already running,
generated:
Registry: constructor: java.net.BindException: Address already in use
java.net.BindException: Address already in use
- For the rmi implementation, when a Client leaves a Session, the Clients
hashtables for all the ByteArrays, Channels and Tokens on the proxy-side
now also have this Client removed.
- For the rmi implementation, if a client leaves a token, we now check to
see if this client had grabbed it, and release it if it had.
- If an attempt is made to create a Manageable object with a manager
attached, then the following two exception conditions can now occur:
- It throws ManagerExistsException if this Manageable object was
previously created with a manager attached.
- It throws PermissionDeniedException if this Manageable object was
previously created without a manager attached. You should not be
able to add a manager afterwards.
- Changes to the way that the Token.give() operation works:
- The giving Client must be either exclusively grabbing the Token or the
only Client non-exclusively inhibiting this Token for the give operation
to be permissible.
- While the Token is in the GIVING state, if the receiving Client
grabs it, this automatically causes the giving Client to be
released from the Token, and a TokenEvent.RELEASED event sent to
all Token listeners.
- A TokenEvent GIVEN event will now be sent to *all* token listeners.
[For consistency, doing a Token.request() operation will now cause
a TokenEvent REQUESTED event to be sent to *all* token listeners,
rather than just those current possessing the Token.]
- A new ClientEvent TOKEN_GIVEN event type has been added:
/** The Client Token given event type. */
public static final int TOKEN_GIVEN = 0x00000100;
- A new ClientListener tokenGiven() method has been added:
public void
tokenGiven(ClientEvent event);
- If the Client who has been given the Token was created using the
ClientFactory class, then it will have a ClientListener associated
with it. That ClientListener's tokenGiven() method will be called
as a result of the Token.give() operation.
- The Naming.unbind() proxy method now removes the unbound Session/Client
from the appropriate hash table, if the unbind() operation was successful.
- The JSDT Registry for the socket and the LRMP implementations failed to
recognise that the following hostnames given in JSDT URLs, all refer to
the same machine:
jsdt://stard:5555/socket/Session/chatSession
jsdt://stard.Eng:5555/socket/Session/chatSession
jsdt://stard.Eng.Sun.COM:5555/socket/Session/chatSession
If two applications are started on the server machine, and they use JSDT
URLs which contain different hostnames which both refer to that same
machine, then the second one will fail
- There were problems having two sessions with the same name on the same
host, but using different port numbers. Ie:
jsdt://stard:6666/socket/Session/session1
jsdt://stard:7777/socket/Session/session1
- The JavaDoc documentation for the Manageable.destroy() method erronously
described invited clients. Cut & paste error
- When a Client did an operation that required authentication, it's
authenticate() method was called. If that method did something like pop
up a dialog box asking the user for a password, then this would block
another Client from doing a similar thing until the first Client had
entered a password and dismissed that popup.
- If the Client associated with a Channel.receive() leaves the Channel,
than Data will no longer be accumulated for that Client.
- The following methods now return an array of zero elements if there are
no objects of the appropriate type present:
Session.getByteArraysJoined()
Session.getChannelsJoined()
Session.getTokensJoined()
Session.listByteArrayNames()
Session.listChannelNames()
Session.listTokenNames()
Channel.listConsumerNames()
Token.listHolderNames()
- If there are two JSDT applications with a ByteArray reference, running
on the same machine, but in different VMs, and if the ByteArray value
is changed by each one close enough together, the first value no
longer gets trashed by the second, before the application has a chance
to read that value within its ByteArray event listener.
- The following Token methods always get a status integer value returned
from the server to the proxy, irrespective of whether the return value
in zero or not:
give() grab() request() release() test()
This was a problem with the socket, lrmp and http implementations.
- Added a JSDTSecurity class to the impl package which enables calls to
various methods that the Netscape browser security manager found
restrictive.
- Changed the way that Channel.receive() works for all implementations.
It no longer uses a name of "__receive__" + client.getName(). It now
just uses the normal client.getName().
- The RMI implementation of Channel.sendToClient() was incorrect. It should
have been using an _RMIClient to try to get the consumer out of the
clientConsumers hash table, not the receiverName String.
- Adjusted the Data(String string) constructor to get the bytes in that
string using getBytes("UTF8") rather than just getBytes().
- Various proxy-side threads needed to be set to daemon threads when they
were created, in order to get them to terminate properly when the last
user thread terminates.
- There were several places where an InterruptedException needed to be
caught, and just ignored, rather than terminating the current thread.
- If the Registry is started by the startRegistry method, then it runs in
its own thread. This is not a deamon thread, so it should either be
stopped with the stopRegistry method, or it will be terminated when the
application that started it, exits. This change was to fix problems with
the Registry not starting correctly on the SGI platform, and with the
Registry process persisting under WinNT.
- Doing a Session.destroy() was not completely removing all internal
variables associated with that Session in the proxy, such that recreating
that Session generated a NoSuchSessionException.
- Restarting a server-side JSDT application was not allowing proxy-side
JSDT applets and applications to be reconnected correctly.
- Added a check for a hostname name of "127.0.0.1" in the JSDT URL Strings,
and if found, resolved it to the real local host name before it gets
bound in the Registry.
- If a JSDT application has two or more Sessions created on the same
"host:port", then doing a Session.close() on one of them, would not close
the connection until you'd done a Session.close() on the others as well.
- On win32 machines, depending on how name lookup was configured on that
machine, it was possible for the JSDT Registry to hang when trying to
resolve the host's InetAddress. The code has been adjusted to pass the
IP address of the sending machine across in the message to the Registry.
The Registry then uses this, rather than try to determine it for itself.
- If you attempt to call Channel.dataAvailable() using a client that has
not joined the Channel, a NullPointerException is thrown.
- If you haven't joined a ByteArray, and you try to set its value, then a
NoSuchClientException exception is now thrown."
- Added in an Implementations chapter which given details specific to each
implementation, and lists the implementation specific variables in the
com.sun.media.jsdt.impl.JSDTObject class that are settable by an
application. These are:
/** Use for debugging purposes. Set to true to print a message when
* an unexpected exception occurs.
*/
public static boolean showMessage = false;
/** Use for debugging purposes. Set to true to print a stack trace when
* an unexpected exception occurs.
*/
public static boolean showStack = false;
/** The time to wait (in milliseconds) for Token give() operations. */
public static int giveTime = 15000;
/** The number of milliseconds to wait for a reply from the server. */
public static long timeoutPeriod = 15000;
/** The number of milliseconds to wait before pinging the server to see
* if there are any asynchronous messages buffered there which need to
* be retrieved. Used by the HTTP implementation.
*/
public static long pingPeriod = 500;
/** The number of seconds to attempt to try to start the Registry. */
public static int registryTime = 60;
/** The maximum size of the message queue. */
public static int maxQueueSize = 15;
/** The maximum thread pool size. */
public static int maxThreadPoolSize = 5;
/** The time-to-live for LRMP packets. */
public static int TTL = 15;
/** The factory class for creating sockets for the "socket" implementation
* of JSDT.
*
* For TCP sockets, this should be set to:
* "com.sun.media.jsdt.socket.TCPSocketFactory"
*
* For SSL sockets, this should be set to:
* "com.sun.media.jsdt.socket.SSLSocketFactory"
*/
public static String socketFactoryClass =
"com.sun.media.jsdt.socket.TCPSocketFactory";
/** The cipher String to use with SSL sockets. */
public static String SSLCipher = "SSL_DH_anon_WITH_RC4_128_MD5";
/** The port number the Registry should run on. */
public static int registryPort = 4561;
/** The multicast Registry address to use with the LRMP implementation. */
public static String registryAddress = "224.1.2.3";
/** The port number to use, to contact the HTTP proxy server. */
public static int httpTunnelPort = 80;
- Included the HTTP implementation.
- The wording of Registry usage on page 13 was confusing. It's been
reworded.
- Added in an example of setting a managers event mask.
- Section 2.12.15 of the JSDT User Guide should have used SessionEvent.JOIN
and SessionEvent.LEFT not Session.JOIN and Session.LEAVE.
- Added a small paragraph to section 2.2 (URL String) in the User Guide to
indicate that you can use IP addresses instead of names for the
portion of a JSDT URL.
- Added a ClientFactory section to the "Getting Started" chapter, with
cross references to the "inviting/expelling a Client" and "Giving a
Token" sections.
- Added a sentence near the beginning of the Listeners chapter to mention
that a ChannelListener is also informed when a ChannelConsumer is added
or removed from a Channel.
- Added a sentence near the beginning of the Listeners chapter to mention
that a ClientListener is also informed when a Client is given a Token.
- Adjusted the section that described how the Token.give() operation works.
- Needed to add a "created = true;" line to the small code sample in the
SessionFactory section of the "Getting Started" chapter, that deals with
Session creation.
- Added in a small paragraph to the ClientFactory section of the "Getting
Started" chapter, to describe how to delete Clients registered in the
Registry.
- Added to the LRMP section in the Implementation chapter, a new
sub-section which describes how to trouble-shoot the various likely
problems (taken from faq.html).
Changes to the Examples.
- Have added a Ppong example into the distribution, based on the classic
Atari Pong game.
- Added screen shots of the fives examples to the example.html page.
- All.
- Updated to use the URLString class.
- Whiteboard
- Can now type in text with a "," character in them.
- Now correctly handles shift (ie. uppercase) characters when typing
in text.
- Can no longer backspace text beyond the beginning of the string.
Changes in JSDT 1.4
These are the major changes between JSDT 1.3 and JSDT 1.4.
- Added Manageable.getSession()
- Added a Client parameter to the ByteArray.setValue() methods.
- Added a new PortInUseException(). This can be thrown by:
- SessionFactory.createSession()
- ClientFactory.createClient()
- Naming.bind()
- Naming.rebind()
- Internationalized all the text strings.
- Added a check for a hostname name of "localhost" in the JSDT URL Strings,
and if found, resolved it to the real local host name before it gets bound
in the Registry.
- Adjusted the JSDT User Guide to reflect these API changes.
- Expelling a Client from a Channel was not sending out the
ChannelEvent.LEFT and ChannelEvent.CONSUMER_REMOVED events.
- Trying to release() a Token you hadn't grabbed or inhibited caused a
NullPointerException.
- For the socket or LRMP implementations, if an exception is thrown
inside any of the JSDT user callbacks, it is now caught, and an error
message is printed out. These user callbacks are:
- ByteArrayManager.byteArrayRequest()
- ChannelConsumer.dataReceived()
- ChannelManager.channelRequest()
- Client.authenticate()
- Client.getName()
- SessionManager.sessionRequest()
- TokenManager.tokenRequest()
- All methods in event.ByteArrayListener
- All methods in event.ChannelListener
- All methods in event.ClientListener
- All methods in event.SessionListener
- All methods in event.TokenListener
- It was possible for the Session.close() operation to hang waiting for
a reply that was lost.
- Token.give() would fail with PermissionDeniedException due to incorrect
security checking.
- Using the LRMP implementation sometimes gave a ClassCastException when
creating a managed Session.
- Killing a Client that was grabbing a Token, was not causing the Token's
status to be reset correctly.
- Due to a thread timing issue, it was possible to hang JSDT on a Windows
platform doing two Session.createChannel() calls in a row to a managed
Session, when everything was running in the same VM.
- Doing a Token.test() on a token that no longer existed resulted in a
hang.
Changes in JSDT 1.3
These are the major changes between JSDT 1.2 and JSDT 1.3.
- Added Channel.listConsumerNames()
- Added Token.listHolderNames()
- Channel.receive() and Channel.dataAvailable() now take a Client parameter
- New ClientFactory class
- Authentication is now done with Java objects rather than String values
- SessionListener and SessionAdaptor did not have a sessionDestroyed()
method
- Added an alternate SessionFactory.createSession() method
- Added Manageable.isManaged()
- Added Channel.receive(Client client, long timeout)
- Significant speedups to the socket implementation
- Various JSDT User Guide updates
- Error messages are now written to System.err
- Added extra checks on certain operations to prevent Client spoofing.
- With the socket implementation if you tried to set two or more consumers
from a single channel proxy, it would not work correctly
- If a client left a channel and it was consuming that channel, then no
CONSUMER_REMOVED channel event was ever sent
- The socket implementation (hopefully) no longer hangs under very heavy
loads
- If a Client subclasses ClientAdaptor, it no longer gets a
java.lang.ClassCastException when an attempt is made to send it a
ClientEvent.
- With the socket implementation it was possible for multiple
TCPSocketServer objects to be instantiated, each waiting for messages
on the same port.
- Incorrectly specifying the JSDT Session URL could cause a
NullPointerException
- If Data is sent on a Channel that is no longer valid (the Client has left
the Session), there is no longer a NullPointerException. It now correctly
throws a NoSuchClientException
- Inhibiting a token was not correctly sending a tokenGrabbed() event to
token listeners
Changes in JSDT 1.2
These are the major changes between JSDT 1.1 and JSDT 1.2.
- Release includes a JSDT User Guide.
- JSDT API JavaDoc now generated using the new JDK1.2beta3 version of
javadoc, which results in much nicer output.
- ChannelListeners can now be notified when ChannelConsumers are added or
removed from a Channel.
- Added a new ConnectionException that gets thrown when some kind of
network error has occured when two components within a JSDT
collaboration have failed to communicate with each other. This affects
most methods in the JSDT API.
- Channel.sendToClient() now also throws NoSuchConsumerException.
- SessionFactory.sessionExists() now also throws NoSuchHostException.
- By default, no error messages will be output. Added debugging flags
for displaying these error messages and stack traces. See the FAQ
for details of how to turn these on.
- With the LRMP implementation; if the proxy-side and server-side
connections are in the same VM, then JSDT uses direct method calls
(rather than an LRMP session), to talk between the two, yielding a
vast speedup.
- Added a new getSession() method to the AuthenticationInfo class which
will return the name of the Session associated with this authentication
operation.
- Added more documentation of getting LRMP.
- Added better documentation to describe what the AuthenticationInfo
class getName() method will return.
- Fixed NullPointerException with SessionFactory.sessionExists() if this
method was called before a SessionFactory.createSession() call had been
made.
- Much better cleanup when a JSDT application terminates.
- The Data.getChannel() method now returns the Channel value.
- The AuthenticationInfo.getType() method now returns the correct value.
- Removing a listener didn't work correctly if there was already more than
one listener associated with that JSDT object.
- All the threads that JSDT creates are now explicitly named to aid in
debugging.
- Fixed up all the deprecated methods.
Changes in JSDT 1.1
These are the major changes between JSDT 1.0 and JSDT 1.1.
- Release includes an LRMP (light-weight reliable multicast protocol)
implementation of JSDT.
- Release includes an RMI (remote method invocation) implementation of JSDT.
- Naming.list() no longer throws NoSuchHostException.
- Naming.list() no longer throws a NullPointerException if there are no
Sessions or Clients registered with the JSDT Registry.
- Added a DESTROY_SESSION action to AuthenticationInfo.java.
- Added a Session.close() method to allow a client to terminate their
session connection.
- Implemented Session.destroy().
- With the socket implementation; if the proxy-side and server-side
connections are in the same VM, then JSDT uses direct method calls
(rather than a socket), to talk between the two, yielding a vast speedup.
- The Token grab() method also needed to throw PermissionDeniedException.
- The Manageable interface needed to extend Serializable.
- Added a RegistryFactory class to start/check the Registry, independent of
implementation type.
- Added a new RegistryExistsException exception class.
- Added a SessionFactory.sessionExists(String url) method.
- Fixed NullPointerException problem if a Client used Channel.sendToClient() to send Data to a Client that did not have a Consumer for that Channel.
- Tested JSDT against JDK 1.2(beta3).
Changes from JSDA
JSDA was the predecessor to JSDT. These are the major differences between
the last released version of JSDA and JSDT 1.0
- Package name is now
com.sun.media.jsdt
- Session and Client URLS now start with
jsdt:
rather than
coll:
- Rather than having a single Exception class, there is now a separate
class for each type of JSDT Exception that can be thrown
- ByteArrays, Channels, Sessions and Tokens are now defined in interface
files rather than classes, to separate the definition from the
implementation
- The shared primitives (Boolean, Integer, Long, Float, Double, String)
have been removed
- Observers are now Listeners
- Uses a JDK 1.1 event model. Events are in a separate
com.sun.media.jsdt.event
package. Event Listeners and
Adaptors are provided for ByteArray, Channel, Client, Session and
Token events
- ByteArrays are now extended from the Manageable class, and are peer
objects to Channels and Tokens
- Users should implement Client and ClientListener if they want to receive
ClientEvents for notification of invitation to and expulsion from
ByteArrays, Channels, Sessions and Tokens
- When you create an unmanaged ByteArray, Channel or Token you have the
option to automatically join it
- New methods in the Session class allow you to determine if a ByteArray,
Channel or Token exists, and which ByteArrays, Channels and Tokens you
have already joined
- The various
uniformSend
methods have been removed from the
Channel class. The state of the reliable
and
ordered
flags when the Channel is created indicate whether
Data sent over the Channel with be uniformly sent
- Rather than having
destroyChannel
and
destroyToken
methods on the Session class, there is now a
destroy
method on the Manageable class that works for
ByteArrays, Channels, Sessions and Tokens
Migrating from JSDT 1.4 to JSDT 1.5
JSDT 1.5 has introduced several new methods, and deprecated several others.
This section is provided to help you adjust your code to use these new methods.
The URLString class.
New Exceptions.
Creation of ByteArrays.
Getting and Setting Values in Data and ByteArray Objects.
New Functionality.
Configurable Options.
Note that you should just be able to run your JSDT 1.4 applications and
applets against JSDT 1.5, but when you go to recompile, you will notice
that some of the methods you are using have been deprecated. Over time,
you should adjust your code to use the non-deprecated methods. The
deprecated methods will probably be removed from a future JSDT release.
These API changes are not gratuitous. They've been done to:
- try to provide a more consistent API.
- make it even simpler to use.
- to abstract out things which might change dramatically under the covers
This new class has been provided to encapsulate the way a JSDT URL String
is created.
The JSDT 1.4 approach was something like:
String url = "jsdt://stard.eng.sun.com:7777/socket/Session/chatSession";
Session session = SessionFactory.createSession(client, url, true);
The simplest JSDT 1.5 approach would be:
String url = "jsdt://stard.eng.sun.com:7777/socket/Session/chatSession";
Session session = SessionFactory.createSession(client, new URLString(url), true);
Typically the URL String is made up of several parts. A static method on
the URLString class is providing to make construction of one of these
URLStrings easier.
The JSDT 1.4 approach was something like:
String url = "jsdt://" + host + ":" + port + "/" + type + "/Session/" + name;
Session session = SessionFactory.createSession(client, url, true);
Now with JSDT 1.5, you would do:
URLString urlString = URLString.createSession(host, port, type, name);
Methods in SessionFactory, ClientFactory and the Naming classes have been
provided to use URLString.
Two new exceptions have been introduced:
- TimedOutException:thrown if no reply was received for this operation in
the given timeout period.
- InvalidClientException: thrown if the Client handle provided is invalid
(ie. returns a null from its getName() method).
These new exceptions are thrown by most methods in the JSDT API.
If you typically have something like:
try {
... JSDT method call ...
} catch (JSDTException e) {
... handle exception ...
}
then you should not have to make any changes to your code. If on the other
hand, you individually catch each exception that a method can throw, then
you will have to add in catch clauses for these new exceptions.
The exceptions are there to help you, so there might be some specific action
you now would like to do if these new exceptions are thrown.
The way ByteArrays are created has been changed in JSDT 1.5 to be consistent
with the way Channels and Tokens are created. It's now a two step process;
you create the bytearray, then set the value.
In JSDT 1.4, you would have had something like:
try {
byteArray = session.createByteArray(client, name, value, true);
} catch (JSDTException e) {
... handle exception ...
}
In JSDT 1.5, this is now:
try {
byteArray = session.createByteArray(client, name, true);
byteArray.setValue(value);
} catch (JSDTException e) {
... handle exception ...
}
If there was no ByteArray with this name already created, then it is initially
created with a zero-filled byte array of length 1. If the ByteArray did exist,
the proxy is returned the current value (as with JSDT 1.4), which can be then
be retrieved with one of the new ByteArray getValueXXX() methods.
Methods have been added to the Data and ByteArray classes, to make it easier
to handle Strings and Java objects.
In JSDT 1.4, for converting a Java object into serialized form, and storing
as a byte array within a Data object, you would have done:
Object object = ... some Java object ...;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
Data data = new Data(bos.toByteArray());
} catch (Exception e) {
... handle exception ...
}
In JSDT 1.5, to achieve the same result, you would do:
Object object = ... some Java object ...;
try {
Data data = new Data(object);
} catch (Exception e) {
... handle exception ...
}
After being sent over a Channel, with JSDT 1.4, you could unmarshall the
byte array stored in the Data object, back into a Java object with:
try {
Data data;
ByteArrayInputStream bais = new ByteArrayInputStream(data.getData());
ObjectInputStream ois = new ObjectInputStream(bais);
Object object = ois.readObject();
ois.close();
bais.close();
} catch (Exception e) {
... handle exception ...
}
The equivalent JSDT 1.5 code is now:
try {
Data data;
Object object = data.getDataAsObject();
} catch (Exception e) {
... handle exception ...
}
A similar approach can now be used for setting and getting Java objects
to/from ByteArrays too.
These are the completely new methods that have been introduced in JSDT 1.5.
- Being able to detect if an object is managed, without first having
created it and joined it.
For Sessions, the new method is in the SessionFactory class:
public static boolean
sessionManaged(URLString urlString);
For ByteArrays, Channels and Tokens, the methods are in Session:
public boolean
byteArrayManaged(String byteArrayName);
public boolean
channelManaged(String channelName);
public boolean
tokenManaged(String tokenName);
Note that you will have to have a handle to the Session to use these
three methods.
- Listing all the URL strings of the known bound JSDT objects on the given
host.
In JSDT 1.4, doing a Naming.list() only returned URL Strings for hosts
where you had bound or looked up a Session or Client. This new method:
public static String[]
list(String host, String connectionType);
allows you to force a list from a host you haven't contacted. For example:
try {
String names[] = Naming.list("myhost.com", "socket");
} catch (JSDTException e) {
... handle exception ...
}
- Setting event masks for managers. For example, my session manager might
not be interested in controlling the creation of bytearrays or tokens.
I would like to specify a mask with the session manager to change the
event mask so that the manager never receives authentication requests
for these two actions.
There are two new methods in the Manageable.java class to provide this
functionality:
public void
enableManagerEvents(JSDTManager manager, int eventMask);
public void
disableManagerEvents(JSDTManager manager, int eventMask);
Only the creator of the managed object can call these two methods.
By default, a manager will provide authentication for all actions
associated with a Manageable object that need authenticating.
To adjust the Session manager event mask to ignore authentication
for bytearray and token creation would be something like:
try {
session.disableManagerEvents(manager,
SessionEvent.BYTEARRAY_CREATED | SessionEvent.TOKEN_CREATED);
} catch (JSDTException e) {
... handle exception ...
}
The following variables are available to allow you to adjust the way each
implementation operates. These variables are described more fully in the new
Implementations chapter in the User Guide, including details of exactly
which implementation each variable is applicable to. They should be set
right at the beginning of your JSDT application.
/** Use for debugging purposes. Set to true to print a message when
* an unexpected exception occurs.
*/
public static boolean showMessage = false;
/** Use for debugging purposes. Set to true to print a stack trace when
* an unexpected exception occurs.
*/
public static boolean showStack = false;
/** The time to wait (in milliseconds) for Token give() operations. */
public static int giveTime = 15000;
/** The number of milliseconds to wait for a reply from the server. */
public static long timeoutPeriod = 15000;
/** The number of milliseconds to wait before pinging the server to see
* if there are any asynchronous messages buffered there which need to
* be retrieved. Used by the HTTP implementation.
*/
public static long pingPeriod = 500;
/** The number of seconds to attempt to try to start the Registry. */
public static int registryTime = 60;
/** The maximum size of the message queue. */
public static int maxQueueSize = 15;
/** The maximum thread pool size. */
public static int maxThreadPoolSize = 5;
/** The time-to-live for LRMP packets. */
public static int TTL = 15;
/** The factory class for creating sockets for the "socket" implementation
* of JSDT.
*
* For TCP sockets, this should be set to:
* "com.sun.media.jsdt.socket.TCPSocketFactory"
*
* For SSL sockets, this should be set to:
* "com.sun.media.jsdt.socket.SSLSocketFactory"
*/
public static String socketFactoryClass =
"com.sun.media.jsdt.socket.TCPSocketFactory";
/** The cipher String to use with SSL sockets. */
public static String SSLCipher = "SSL_DH_anon_WITH_RC4_128_MD5";
/** The port number the Registry should run on. */
public static int registryPort = 4561;
/** The multicast Registry address to use with the LRMP implementation. */
public static String registryAddress = "224.1.2.3";
/** The port number to use, to contact the HTTP proxy server. */
public static int httpTunnelPort = 80;
Getting JSDT to Work Through Firewalls
Many intranets have firewalls which do not allow a direct connection to the
Internet. If the JSDT HTTP implementation cannot establish a direct TCP
socket connection, it provides two forms of HTTP-tunneling, tried in order:
- http-to-port
- http-to-cgi.
In http-to-port tunneling, we attempt an HTTP POST request to a http: URL
directed at the exact hostname and port number of the target server. The
HTTP request contains a single JSDT request. If the HTTP proxy accepts this
URL, it will forward the POST request to the listening JSDT server, which
will recognise the request and unwrap it. The result of the call is wrapped
in an HTTP reply, which is returned through the same proxy.
Often, HTTP proxies will refuse to proxy requests to unusual port numbers.
In this case, we will fall back to http-to-cgi tunneling. The JSDT request
is encapsulated in a HTTP POST request as before, but the request URL is of
the form http://hostname:80/cgi-bin/java-jsdt.cgi?port=n (where hostname
and n are the hostname and port number of the intended server). There must
be an HTTP server listening on port 80 on the server host, which will run
the java-jsdt.cgi script (supplied with the JSDT distribution), which will
in turn forward the request to a JSDT server listening on port n. JSDT can
unwrap a HTTP-tunneled request without help from a http server, CGI script,
or any other external entity. So, if the client's HTTP proxy can connect
directly to the server's port, then you don't need a java-jsdt.cgi script
at all.
Note that you can set an alternate HTTP proxy port using the
com.sun.media.jsdt.impl.JSDTObject.httpTunnelPort variable (see Section 8.6.2,
of the JSDT User Guide for more information.
If you are running a web server that is capable of running Java servlets, then
you can alias the "/cgi-bin/java-jsdt.cgi" script to a Java servlet class
called com.sun.media.jsdt.http.ServletHandler which is also included with the
JSDT distribution. This is much faster that a CGI script.
Note that the http-to-cgi method opens a dramatic security hole on the server
side, since without modification it will redirect any incoming request to any
port.
The following two files from your JSDT distribution need to be put in the
web servers cgi-bin directory:
- .../bin/java-jsdt.cgi
- .../lib/jsdt.jar
Make sure the java-jsdt.cgi script has execute permission by the web server.
These instructions are written under the assumption that you will be using
JavaWebServer1.1.
To run the ServletHandler perform the following steps:
- Install the servlet class files:
- Copy the jsdt.jar file from your JSDT distribution to the
servlets directory of your webserver
(for example /usr/local/JavaWebServer1.1/servlets).
- Ensure that the webserver can read the jsdt.jar file, so that
the webserver has permission to load the classes from this URL).
- Configure the servlet using the webserver's administration utility:
- Gain administrator access to a webserver that supports servlets.
This servlet prints error messages to stderr. It is quite
helpful for debugging purposes to run your webserver in a
console that you can view so that you can read the text of error
messages when errors occur.
- Create/register the servlet handler using your webserver's
Administration utility through the "Add a new servlet" form
located at:
web-service -> servlets -> servlets:add
Servlet Name: JSDTServletHandler
Servlet Class: com.sun.media.jsdt.http.ServletHandler
- Ensure that the web service under which you are installing the
servlet handler is running on port 80.
- Associate the servlet alias, "/cgi-bin/java-jsdt.cgi", with the
servlet created in step 3 using:
web-service -> setup -> Servlet Aliases -> Add
Alias: /cgi-bin/java-jsdt.cgi
Servlet Invoked: JSDTServletHandler
- Load the servlet through the Administrator utility using:
web-service -> servlets ->
servlets: -> load
JDK 1.2 Policy Files for the examples
JDK 1.2 contains substantial security features and enhancements. They include
security policy files. The minimal policy files to run the examples included
with the JSDT distribution are included here.
For a good tutorial on creating policy files, see:
http://java.sun.com/docs/books/tutorial/security1.2/tour1/index.html
This is the policy file for the Chat example when run as an applet.
grant {
permission java.lang.RuntimePermission "modifyThread";
permission java.lang.RuntimePermission "modifyThreadGroup";
permission java.net.SocketPermission "*:1024-", "connect,accept";
};
This is the policy file for the WhiteBoard and Stock examples when run as
applets.
grant {
permission java.lang.RuntimePermission "modifyThreadGroup";
permission java.lang.RuntimePermission "modifyThread";
permission java.net.SocketPermission "*:1024-", "connect,accept";
permission java.io.FilePermission "<>", "read";
};
This is the policy file for the Sound example when run as an applet.
grant {
permission java.lang.RuntimePermission "modifyThreadGroup";
permission java.lang.RuntimePermission "modifyThread";
permission java.net.SocketPermission "*:1024-", "connect,accept";
permission java.io.FilePermission "<>", "read";
permission java.lang.RuntimePermission "accessClassInPackage.sun.audio";
};
This is the policy file for the Ppong example when run as an applet.
grant {
permission java.lang.RuntimePermission "modifyThreadGroup";
permission java.lang.RuntimePermission "modifyThread";
permission java.net.SocketPermission "*:1024-", "connect,accept";
permission java.lang.RuntimePermission "accessClassInPackage.sun.audio";
};
How to get the HotJava Browser
The top-level runme
file launches HotJava to browse the
JSDT setup html page. If you haven't already got HotJava, then you
can download it from here.
How to get the LRMP Distribution
If you are going to use the LRMP implementation of JSDT, then you will need
to get a copy of the Inria LRMP distribution, which can be downloaded from
here.
How to make jsdt.jar smaller
With this release, the jsdt.jar
file contains four
implementations (socket, LRMP, RMI and HTTP). This has increased the size of
the file quite dramatically. If you know you are only going to be using
one implementation, then you might wish to unpack this file, remove the
implementations you don't want, and jar
it up again.
If you don't want the socket implementation, remove the
com.sun.media.jsdt.socket
directory.
If you don't want the LRMP implementation, remove the
com.sun.media.jsdt.lrmp
directory.
If you don't want the RMI implementation, remove the
com.sun.media.jsdt.rmi
directory.
If you don't want the HTTP implementation, remove the
com.sun.media.jsdt.http
directory.
JSDT Interest Mailing List
There is a mailing list for people interested in the JSDT. It is:
jsdt-interest@Sun.COM
In order to subscribe to the jsdt-interest list now, you should send
mail to
javamedia-request@Sun.COM
with the message body (not the subject) containing:
subscribe jsdt-interest
To unsubscribe, the body needs to read:
unsubscribe jsdt-interest
Note this is javamedia-request@sun.com *NOT* jsdt-request@sun.com.
This is in line with the other javamedia aliases.
The JSDT alias is now being managed by majordomo. For those of you not
familiar with majordomo, here are a few notes:
The common commands you can give in the body of the email to
javamedia-request@sun.com are:
lists (gives you a list of aliases maintained by majordomo)
info (returns information about the alias)
subscribe
unsubscribe
help (help on the commands available)
New versions of the JSDT are announced on the mailing list, plus active
discussion on problems with and ideas for enhancements to the JSDT.
The JSDT mailing list archives (in hypermail format) are available
here.
Trouble Shooting
No DOS Environment Space Under Windows 95
Under Windows 95, you might need to increase the environment space to enable
the example Run commands to work. There is an easy way to increase your DOS
environment space for ALL DOS programs. Add or modify this line to your
config.sys
file (typically on c:\
):
shell=c:\windows\command.com c:\windows /p /e:4096
Problems Running The LRMP Implementation
Running the LRMP implementation of JSDT requires that you have installed
LRMP on your machine and have the LRMP lib/webcanal.jar
file
added to your CLASS_PATH. See an earlier entry in these Release Notes on how
to get the LRMP distribution.
More Information on JSDT
There is a home page for JSDT at:
http://www.sun.com/software/jsdt.
A FAQ (Frequently Asked Questions) document can be found here.