amber.server.application
Class ApplicationHandler

java.lang.Object
  |
  +--java.lang.Thread
        |
        +--amber.server.application.ApplicationHandler
All Implemented Interfaces:
ApplicationInterface, java.lang.Runnable, java.io.Serializable
Direct Known Subclasses:
LicenseViolatedApplicationHandler

public abstract class ApplicationHandler
extends java.lang.Thread
implements java.io.Serializable, ApplicationInterface

This class handles the requirements for the manipulation of the pages. This is the overall intelligence for this particular page.

Version:
1.0.0
Author:
Dr. David J. Knowles
See Also:
ApplicationHandler, Serialized Form

Field Summary
protected  java.net.Socket connection
          Handle to the socket connection to the remote browser.
protected  EventThread eventHandler
          The thread handling reception of event packets from the remote components.
protected  java.io.InputStream input
          Handle to the socket connection input stream.
protected  Log loggingFile
          Logging file, set by the server.
protected  java.io.OutputStream output
          Handle to the socket connection output stream.
protected  HandlePacketThread packetHandler
          The thread handling transmission of packets from the remote component to the corresponding server component.
protected  int pageId
          Numeric identifier for this specific instance of Page.
protected  int pageSubId
          2nd Numeric identifier for this specific instance of Page.
protected  CoreInterface parentServer
          The original server which started this ApplicationHandler.
protected  java.util.Vector receivedPackets
          Vector which holds pending incoming packets.
protected  ReceiveThread receiver
          The thread handling reception of packets from the remote components.
protected  SendThread sender
          The thread handling transmission of packets to the remote components.
protected  java.lang.String sessionInfo
          String which is defined by the server.
protected  Mutex waitForClientShutDown
          Lock when waiting for the client shutdown response packet.
protected  Mutex waitForPacket
          Lock when waiting for incoming packets.
 
Fields inherited from class java.lang.Thread
MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY
 
Constructor Summary
ApplicationHandler()
          Default constructor.
ApplicationHandler(int pageIdentifier, int pageSubIdentifier)
          Initialising constructor.
ApplicationHandler(int pageIdentifier, int pageSubIdentifier, java.net.Socket newConnection)
          The initialising constructor.
ApplicationHandler(int pageIdentifier, int pageSubIdentifier, java.net.Socket newConnection, java.util.Vector components)
          The initialising constructor.
ApplicationHandler(int pageIdentifier, int pageSubIdentifier, java.util.Vector components)
          The initialising constructor.
 
Method Summary
protected  void activateChildren(boolean state)
          Activates/deactivates all the clildren of this application.
 void add(ComponentHandler newComponent, java.lang.Object constraints)
          This function adds a specified component to this application.
 void addComponent(ComponentHandler newComponent)
          Deprecated. This function is now replaced by add for consistency with standard Java.
 PanelComponentInfo addComponent(ComponentHandler newComponent, int eventMask, int x, int y, int width, int height)
          Deprecated. This function is now replaced by add for consistency with standard Java.
 void addInPostPacketListener(PacketListener l)
           
 void addInPrePacketListener(PacketListener l)
           
 void addOutPostPacketListener(PacketListener l)
           
 void addOutPrePacketListener(PacketListener l)
           
 void addReceivedPacket(Packet packet)
          Called by the ReceiveThread when a packet has been received.
protected  void computeMaximumDimensions()
          This function works out the maximum size of the application required to hold all the current controls.
protected abstract  void defineComponents()
          Component Set up function.
 void directPacket(Packet packet)
          Called by the ReceiveThread when a packet has been received.
protected  void encodeComponentState(AmberOutputStream dataEncoder)
          This function encodes the basic state of the components understood by the application.
protected  boolean fireInPostPacketPerformed(Packet p)
           
protected  boolean fireInPrePacketPerformed(Packet p)
           
protected  boolean fireOutPostPacketPerformed(Packet p)
           
protected  boolean fireOutPrePacketPerformed(Packet p)
           
 void forwardEventPacket(Packet packet)
          Called by the EventThread when a packet has been received.
 java.awt.Dimension getClientScreenSize()
          This function returns the physical screen dimensions of the client screen.
 java.util.Vector getComponents()
          Returns the component vector.
 java.net.Socket getConnection()
          Returns the socket connection associated with this application.
 Log getLog()
          Returns the Log object.
 ApplicationInterface getModalObject()
          Returns the current object which is receiving all input packets.
 int getPageId()
          Gets the unique ID for this instance of the page.
 int getPageSubId()
          Gets the unique ID for this instance of the page.
 CoreInterface getParentServer()
          Returns the original server which started this ApplicationHandler.
 PropertiesHandler getRemoteProperties()
          This function returns the remote properties of the client.
 java.lang.String getSessionId()
          Returns the unique identifier which is used to specify which session this application is associated with.
 int getValidId()
          This function allocates a valid unused ID from a pool of ID's held within the Application.
protected  boolean isAlreadyCreated(ComponentHandler component, java.util.Vector groups)
          This function checks to see if the component has already been created.
 boolean isConnected()
          This function returns the state of the application handler.
 boolean isMyPageId(int id)
          Checks that the unique ID passed to this page is handled by this ApplicationHandler.
 boolean isMyPageId(int id, int subId)
          Checks that the unique IDs passed to this page is handled by this ApplicationHandler.
 void logComponentStructure()
          This function dumps all the components that this page recognises.
protected  void processApplicationPacket(Packet packet)
           
 void remove(ComponentHandler component)
          This function removes the specified component to this application.
 void removeInPostPacketListener(PacketListener l)
          This function removes an input post packet listener.
 void removeInPrePacketListener(PacketListener l)
          This function removes an input pre packet listener.
 void removeOutPostPacketListener(PacketListener l)
          This function removes an output post packet listener.
 void removeOutPrePacketListener(PacketListener l)
          This function removes an output pre packet listener.
 void restart(java.net.Socket newConnection)
          This function restarts the functioning of the ApplicationInterface.
 void run()
          Main run function.
 void sendPacket(Packet packet)
          Writes a packet to the output stream.
 void sendReconnectionState()
          This function sends the session reconnection message which tells the client the reconnection was successful.
 void sendSessionInitialisationState()
          This function sends the session initialisation which is stored in the master applet system.
 void setClientScreenSize(java.awt.Dimension screenSize)
          This function sets the physical screen dimensions of the client screen.
 void setComponents(java.util.Vector newComponents)
          Overrides the component vector.
 void setConnectedState(boolean state)
          This function will force the application to go active/inactive.
 void setInitialValidId(int baseId)
          This function sets the allocator ID so that the ID's will offset from a different value.
 void setLog(Log logFile)
          Sets the Log for this ApplicationHandler.
 void setModalObject(ApplicationInterface object)
          Sets the current object which is to receive all input packets.
 void setPageId(int newPageId)
          Sets the unique ID for this instance of the page.
 void setPageSubId(int newPageId)
          Sets the unique ID for this instance of the page.
 void setParentServer(CoreInterface server)
          Sets the original server which started this ApplicationHandler.
 void setRemoteProperties(PropertiesHandler properties)
          This function sets the remote properties of the client.
 void setSize(int width, int height)
          This sets the physical size of the required area to hold the entire application in the HTML page.
 void setUpComponent(ComponentHandler newComponent)
          Deprecated. This function is now replaced by add for consistency with standard Java.
 PanelComponentInfo setUpComponent(ComponentHandler newComponent, int eventMask, int x, int y, int width, int height)
          Deprecated. This function is now replaced by add for consistency with standard Java.
 void shutDown()
          This function attempts to shut down the page handler gracefully.
 void shutDownClient()
          This function will force the client to shut down.
 void shutDownClient(java.lang.String message)
          This function will force the client to shut down.
protected  boolean specialPacket(Packet packet)
          This function checks the packet.
 void start()
          This function initiates the functioning of the ApplicationHandler.
 void start(java.net.Socket newConnection)
          This function initiates the functioning of the ApplicationHandler.
protected  void terminateThreads(boolean destroyThreads)
          Terminates the messaging threads.
 
Methods inherited from class java.lang.Thread
activeCount, checkAccess, countStackFrames, currentThread, destroy, dumpStack, enumerate, getContextClassLoader, getName, getPriority, getThreadGroup, interrupt, interrupted, isAlive, isDaemon, isInterrupted, join, join, join, resume, setContextClassLoader, setDaemon, setName, setPriority, sleep, sleep, stop, stop, suspend, toString, yield
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

pageId

protected int pageId
Numeric identifier for this specific instance of Page.

pageSubId

protected int pageSubId
2nd Numeric identifier for this specific instance of Page.

connection

protected java.net.Socket connection
Handle to the socket connection to the remote browser.

input

protected java.io.InputStream input
Handle to the socket connection input stream.

output

protected java.io.OutputStream output
Handle to the socket connection output stream.

receiver

protected ReceiveThread receiver
The thread handling reception of packets from the remote components.

sender

protected SendThread sender
The thread handling transmission of packets to the remote components.

eventHandler

protected EventThread eventHandler
The thread handling reception of event packets from the remote components.

packetHandler

protected HandlePacketThread packetHandler
The thread handling transmission of packets from the remote component to the corresponding server component.

receivedPackets

protected java.util.Vector receivedPackets
Vector which holds pending incoming packets.

waitForPacket

protected Mutex waitForPacket
Lock when waiting for incoming packets.

waitForClientShutDown

protected Mutex waitForClientShutDown
Lock when waiting for the client shutdown response packet.

loggingFile

protected Log loggingFile
Logging file, set by the server.

sessionInfo

protected java.lang.String sessionInfo
String which is defined by the server. This is used to identify the current session uniquely.

parentServer

protected CoreInterface parentServer
The original server which started this ApplicationHandler.
Constructor Detail

ApplicationHandler

public ApplicationHandler()
                   throws java.io.IOException
Default constructor.

ApplicationHandler

public ApplicationHandler(int pageIdentifier,
                          int pageSubIdentifier)
                   throws java.io.IOException
Initialising constructor.
Parameters:
pageIdentifier - An int uniquely identifying this instance of page.
pageSubIdentifier - An int used for extra information.

ApplicationHandler

public ApplicationHandler(int pageIdentifier,
                          int pageSubIdentifier,
                          java.util.Vector components)
                   throws java.io.IOException
The initialising constructor.
Parameters:
pageIdentifier - An int uniquely identifying this instance of page.
pageSubIdentifier - An int used for extra information.
components - A Vector containing all the active components in use.

ApplicationHandler

public ApplicationHandler(int pageIdentifier,
                          int pageSubIdentifier,
                          java.net.Socket newConnection)
                   throws java.io.IOException
The initialising constructor.
Parameters:
pageIdentifier - An int uniquely identifying this instance of page.
pageSubIdentifier - An int used for extra information.
newConnection - The Socket which is connected to the page in operation.

ApplicationHandler

public ApplicationHandler(int pageIdentifier,
                          int pageSubIdentifier,
                          java.net.Socket newConnection,
                          java.util.Vector components)
                   throws java.io.IOException
The initialising constructor.
Parameters:
pageIdentifier - An int uniquely identifying this instance of page.
pageSubIdentifier - An int used for extra information.
newConnection - The Socket which is connected to the page in operation.
components - A Vector containing all the active components in use.
Method Detail

forwardEventPacket

public void forwardEventPacket(Packet packet)
                        throws ApplicationHandlerException
Called by the EventThread when a packet has been received. This function examines the packet and passes it to the appropriate handler.
Specified by:
forwardEventPacket in interface ApplicationInterface
Parameters:
packet - Packet to forward to the specified component.

directPacket

public void directPacket(Packet packet)
                  throws ApplicationHandlerException
Called by the ReceiveThread when a packet has been received. This function examines the packet and passes it to the appropriate handler.
Specified by:
directPacket in interface ApplicationInterface
Parameters:
packet - Packet to forward to the specified component.

specialPacket

protected boolean specialPacket(Packet packet)
This function checks the packet. If it is destined for the application rather than any component the function returns true.
Parameters:
packet - Packet sent to the application.
Returns:
boolean true if the packet is for the application rather than a component.

processApplicationPacket

protected void processApplicationPacket(Packet packet)

sendPacket

public void sendPacket(Packet packet)
                throws ApplicationHandlerException
Writes a packet to the output stream.
Specified by:
sendPacket in interface ApplicationInterface
Parameters:
packet - Packet which will be written to the remote browser.
Throws:
amber.server.applicationException - containing error information

add

public void add(ComponentHandler newComponent,
                java.lang.Object constraints)
This function adds a specified component to this application.
Parameters:
newComponent - ComponentHandler for the created component.
constraints - Object containing the constraints defining where the component will be placed in the application screen.

remove

public void remove(ComponentHandler component)
This function removes the specified component to this application.
Parameters:
component - ComponentHandler of the component to remove.

addComponent

public void addComponent(ComponentHandler newComponent)
Deprecated. This function is now replaced by add for consistency with standard Java.

Adds a new component to the component vector.
Parameters:
newComponent - ComponentHandler for the new component.

addComponent

public PanelComponentInfo addComponent(ComponentHandler newComponent,
                                       int eventMask,
                                       int x,
                                       int y,
                                       int width,
                                       int height)
Deprecated. This function is now replaced by add for consistency with standard Java.

This function takes the parameters and creates a PanelComponentInfo containing the information on the component. This function is used by the ApplicationHandler to keep information on the approximate appearance of the application in the HTML page. This allows connecting applications to mimic the look of the page if a browser was to connect.
Parameters:
newComponent - ComponentHandler for the created component.
eventMask - int containing the event mask.
x - int x coordinate of top left point of component in page.
y - int y coordinate of top left point of component in page.
width - int width of component in panel.
height - int height of component in panel.
Returns:
PanelComponentInfo containing creation characteristics for the control.

setUpComponent

public void setUpComponent(ComponentHandler newComponent)
Deprecated. This function is now replaced by add for consistency with standard Java.

Adds a new component to the component vector. In this class this function is an alias for addComponent.
Parameters:
newComponent - ComponentHandler for the new component.

setUpComponent

public PanelComponentInfo setUpComponent(ComponentHandler newComponent,
                                         int eventMask,
                                         int x,
                                         int y,
                                         int width,
                                         int height)
Deprecated. This function is now replaced by add for consistency with standard Java.

This function takes the parameters and creates a PanelComponentInfo containing the information on the component. This function is used by the ApplicationHandler to keep information on the approximate appearance of the application in the HTML page. This allows connecting applications to mimic the look of the page if a browser was to connect. In this class this function is an alias for addComponent.
Parameters:
newComponent - ComponentHandler for the created component.
eventMask - int containing the event mask.
x - int x coordinate of top left point of component in page.
y - int y coordinate of top left point of component in page.
width - int width of component in panel.
height - int height of component in panel.
Returns:
PanelComponentInfo containing creation characteristics for the control.

setComponents

public void setComponents(java.util.Vector newComponents)
Overrides the component vector.
Parameters:
newComponents - Vector which contains the new components.

getComponents

public java.util.Vector getComponents()
Returns the component vector.
Returns:
Vector which contains the components.

getConnection

public java.net.Socket getConnection()
Returns the socket connection associated with this application.
Returns:
Socket which is the connection to the remote client.

isConnected

public boolean isConnected()
This function returns the state of the application handler. If the application is connected and can message to the server then this function returns true.
Specified by:
isConnected in interface ApplicationInterface
Returns:
boolean connection state.

start

public void start(java.net.Socket newConnection)
           throws java.lang.IllegalThreadStateException
This function initiates the functioning of the ApplicationHandler. This function is required as the page handler will not immediately start operation until it is handed the socket by the main handling system.
Specified by:
start in interface ApplicationInterface
Parameters:
newConnection - The Socket which is connected to the page in operation. If null uses the connection already set.
Throws:
java.lang.IllegalThreadStateException - containing any problems.

restart

public void restart(java.net.Socket newConnection)
             throws java.lang.IllegalThreadStateException
This function restarts the functioning of the ApplicationInterface. This function is called when an application has lost the connection which is then reestablished.
Specified by:
restart in interface ApplicationInterface
Parameters:
newConnection - The Socket which is connected to the page in operation. If null uses the connection already set.
Throws:
java.lang.IllegalThreadStateException - containing any problems.

start

public void start()
           throws java.lang.IllegalThreadStateException
This function initiates the functioning of the ApplicationHandler. This function is required as the page handler will not immediately start operation until it is handed the socket by the main handling system.
Overrides:
start in class java.lang.Thread
Throws:
java.lang.IllegalThreadStateException - containing any problems.

sendSessionInitialisationState

public void sendSessionInitialisationState()
This function sends the session initialisation which is stored in the master applet system. It is this information which is used in fail-over situations. The information is also used in the client application situation to create the proper BaseComponents.

sendReconnectionState

public void sendReconnectionState()
This function sends the session reconnection message which tells the client the reconnection was successful.

computeMaximumDimensions

protected void computeMaximumDimensions()
This function works out the maximum size of the application required to hold all the current controls. This function then updates the size of the application.

encodeComponentState

protected void encodeComponentState(AmberOutputStream dataEncoder)
                             throws java.io.IOException
This function encodes the basic state of the components understood by the application. This would normally correspond to those controls which reside in the HTML code.
Parameters:
dataEncoder - AmberOutputStream to encode with this information.
Throws:
java.io.IOException - if the encoding fails.

isAlreadyCreated

protected boolean isAlreadyCreated(ComponentHandler component,
                                   java.util.Vector groups)
This function checks to see if the component has already been created. This is mainly the case for PanelTemplateGroups where many panels share one drawing panel.
Parameters:
component - ComponentHandler to check.
groups - Vector containing current PanelTemplateGroups
Returns:
boolean true if the drawing surface for the component has already been created.

run

public void run()
Main run function. This function is responsible for receiving and directing packets from the remote client.
Overrides:
run in class java.lang.Thread

addReceivedPacket

public void addReceivedPacket(Packet packet)
Called by the ReceiveThread when a packet has been received. This function adds the packet to the Vector of pending packets. The run method of the ApplicationHandler class will dispatch the packet in the run method.
Specified by:
addReceivedPacket in interface ApplicationInterface
Parameters:
packet - Packet to forward to the specified component.

setPageId

public void setPageId(int newPageId)
Sets the unique ID for this instance of the page.
Parameters:
newPageId - int containing the new page identifier.

setClientScreenSize

public void setClientScreenSize(java.awt.Dimension screenSize)
This function sets the physical screen dimensions of the client screen.
Parameters:
screenSize - Dimension containing the client screen dimensions.

getClientScreenSize

public java.awt.Dimension getClientScreenSize()
This function returns the physical screen dimensions of the client screen.
Returns:
Dimension containing the client screen dimensions.

setRemoteProperties

public void setRemoteProperties(PropertiesHandler properties)
This function sets the remote properties of the client.
Parameters:
properties - PropertiesHandler with the remote properties.

getRemoteProperties

public PropertiesHandler getRemoteProperties()
This function returns the remote properties of the client.
Returns:
PropertiesHandler with the remote properties.

getPageId

public int getPageId()
Gets the unique ID for this instance of the page.
Returns:
int containing the new page identifier.

setPageSubId

public void setPageSubId(int newPageId)
Sets the unique ID for this instance of the page.
Parameters:
newPageId - int containing the new page identifier.

getPageSubId

public int getPageSubId()
Gets the unique ID for this instance of the page.
Returns:
int containing the new page identifier.

isMyPageId

public boolean isMyPageId(int id)
Checks that the unique ID passed to this page is handled by this ApplicationHandler.
Parameters:
id - int page handler ID.
Returns:
boolean if this is the correct ApplicationHandler.

isMyPageId

public boolean isMyPageId(int id,
                          int subId)
Checks that the unique IDs passed to this page is handled by this ApplicationHandler.
Parameters:
id - int page handler ID.
subId - int page handler Sub ID.
Returns:
boolean if this is the correct ApplicationHandler.

getValidId

public int getValidId()
               throws ApplicationHandlerException
This function allocates a valid unused ID from a pool of ID's held within the Application. This function is typically called from a component when it is created. The ID's start unaltered at a base of 200.
Specified by:
getValidId in interface ApplicationInterface
Returns:
int containing the valid ID.
Throws:
ApplicationHandlerException - should the component ID overflow the maximum allowed.

setInitialValidId

public void setInitialValidId(int baseId)
This function sets the allocator ID so that the ID's will offset from a different value. This function should be used with care as it may cause an overlap between component ID's.
Parameters:
baseId - int containing the first valid ID to allocate on next request.

getParentServer

public CoreInterface getParentServer()
Returns the original server which started this ApplicationHandler.
Specified by:
getParentServer in interface ApplicationInterface
Returns:
CoreInterface which is the parent server.

setParentServer

public void setParentServer(CoreInterface server)
Sets the original server which started this ApplicationHandler.
Specified by:
setParentServer in interface ApplicationInterface
Parameters:
server - CoreInterface which is the parent server.

getLog

public Log getLog()
Returns the Log object.
Specified by:
getLog in interface ApplicationInterface
Returns:
Log which is the Logging object.

setLog

public void setLog(Log logFile)
Sets the Log for this ApplicationHandler.
Specified by:
setLog in interface ApplicationInterface
Parameters:
logFile - Log object for logging.

logComponentStructure

public void logComponentStructure()
This function dumps all the components that this page recognises. This is very important in marrying the remote objects to their respective ComponentHandlers. This is written to the internal Log object.

setConnectedState

public void setConnectedState(boolean state)
This function will force the application to go active/inactive. An inactive application is assumed to be not connected to the remote client. Should a reconnection occur the application is re-activated.
Specified by:
setConnectedState in interface ApplicationInterface

getSessionId

public java.lang.String getSessionId()
Returns the unique identifier which is used to specify which session this application is associated with.
Returns:
String with the session ID.

activateChildren

protected void activateChildren(boolean state)
Activates/deactivates all the clildren of this application.
Parameters:
state - boolean state to set. true is activate children.

terminateThreads

protected void terminateThreads(boolean destroyThreads)
Terminates the messaging threads.
Parameters:
destroyThreads - boolean flag when true the threads are also destroyed.

shutDown

public void shutDown()
This function attempts to shut down the page handler gracefully. If the program is already shut down it does nothing.
Specified by:
shutDown in interface ApplicationInterface

setSize

public void setSize(int width,
                    int height)
This sets the physical size of the required area to hold the entire application in the HTML page.
Parameters:
width - int width of the application.
height - int height of the application.

getModalObject

public ApplicationInterface getModalObject()
Returns the current object which is receiving all input packets.
Specified by:
getModalObject in interface ApplicationInterface
Returns:
ApplicationInterface which is the modal object.

setModalObject

public void setModalObject(ApplicationInterface object)
Sets the current object which is to receive all input packets.
Specified by:
setModalObject in interface ApplicationInterface
Parameters:
object - ApplicationInterface which is the modal object.

shutDownClient

public void shutDownClient()
                    throws ApplicationHandlerException
This function will force the client to shut down. The function waits for the client to respond that it has shut down before returning.
Specified by:
shutDownClient in interface ApplicationInterface
Throws:
ApplicationHandlerException - should there be a messaging error.

shutDownClient

public void shutDownClient(java.lang.String message)
                    throws ApplicationHandlerException
This function will force the client to shut down. The function waits for the client to respond that it has shut down before returning.
Specified by:
shutDownClient in interface ApplicationInterface
Parameters:
message - String optional message which the client will display in a message box when the client is closed. A null value sends no message and silently shuts down the client.
Throws:
ApplicationHandlerException - should there be a messaging error.

removeInPrePacketListener

public void removeInPrePacketListener(PacketListener l)
This function removes an input pre packet listener.

addInPrePacketListener

public void addInPrePacketListener(PacketListener l)

fireInPrePacketPerformed

protected boolean fireInPrePacketPerformed(Packet p)

removeOutPrePacketListener

public void removeOutPrePacketListener(PacketListener l)
This function removes an output pre packet listener.

addOutPrePacketListener

public void addOutPrePacketListener(PacketListener l)

fireOutPrePacketPerformed

protected boolean fireOutPrePacketPerformed(Packet p)

removeInPostPacketListener

public void removeInPostPacketListener(PacketListener l)
This function removes an input post packet listener.

addInPostPacketListener

public void addInPostPacketListener(PacketListener l)

fireInPostPacketPerformed

protected boolean fireInPostPacketPerformed(Packet p)

removeOutPostPacketListener

public void removeOutPostPacketListener(PacketListener l)
This function removes an output post packet listener.

addOutPostPacketListener

public void addOutPostPacketListener(PacketListener l)

fireOutPostPacketPerformed

protected boolean fireOutPostPacketPerformed(Packet p)

defineComponents

protected abstract void defineComponents()
Component Set up function. This function creates all the standard components and attaches them to the correct vector.


Copyright © 2002 Clearfield Research Ltd. All Rights Reserved.