org.locomotive.server
Class ServiceRoutingTable

java.lang.Object
  |
  +--org.locomotive.server.ServiceRoutingTable
Direct Known Subclasses:
HandlerRoutingTable, ServletRoutingTable

public abstract class ServiceRoutingTable
extends java.lang.Object

An abstract way to route services to pattern Strings. This presently loads a file which maps a token or an extension to a class, as well as a path to a properties file. It will take care of loading and parsing the file, and loading the properties. Moreover, it'll even reload the file, or an individual service, for you. Here's the file format:

  <url_pattern>  <classname>  [<path to properties file>]
  // comments after the double slash
 
To get this to work for you, you'll have to override the following:


Inner Class Summary
 class ServiceRoutingTable.ServiceEntry
          This little class is the companion to the ServiceRoutingTable.
 
Field Summary
static int AVAILABLE
          If the instance member availability is set to AVAILABLE, that means that this ServiceEntry's service is available to serve requests.
static int PERMANENTLY_UNAVAILABLE
          If the instance member availability is set to PERMANENTLY_UNAVAILABLE, that means that this ServiceEntry's service is unavailable, and probably won't be available again until the system administrator(s) restart the Locomotive.
protected  Log server_log
           
protected  java.util.Hashtable service_configs
          The Hashtable that stores service-to-propsfile mappings
protected  java.util.Hashtable service_extensions_hash
          The Hashtable that stores extension-to-service mappings
protected  java.util.Hashtable service_tokens_hash
          The Hashtable that stores token-to-service mappings
static int SHUTDOWN
          If the instance member availability is set to SHUTDOWN, that means that the Object factory for this service has been shut down.
static int UNAVAILABLE_AND_WAITING
          If the instance member availability is set to UNAVAILABLE_AND_WAITING, that means that this ServiceEntry's service is currently unavailable, but may become available again after unavailable_seconds have elapsed.
 
Constructor Summary
ServiceRoutingTable(java.lang.String path, Log log, java.util.Vector classpath, boolean auto_reload)
          creates a new (but uninitialized) HanderRouting Table
 
Method Summary
 void addService(java.lang.String pattern, java.lang.String classname, java.lang.String config_path)
          Creates and adds a new service to the ServiceRoutingTable.
 boolean containsService(java.lang.String pattern)
          Returns true if there is a service associated with this pattern
protected abstract  ServiceRoutingTable.ServiceEntry createServiceEntry(java.lang.String pattern, java.lang.String classname, java.lang.String config_path)
          Override this to return the ServiceEntry class you need.
 java.util.Properties getProperties(java.lang.Class theclass)
          return the properties object for a given Class.
 ServiceRoutingTable.ServiceEntry getService(LocoConfig config, java.lang.String pattern)
          returns the Service Entry object appropriate for the given config and pattern string.
 void initialize()
          initializes or re-initializes this object's routing structures based on the defaults and the contents of the file at the location specified in 'path' in the Constructor.
protected  void log(int log_level, java.lang.String message)
          Log with the correct class name
 void markServiceForReloading(java.lang.String pattern)
          Marks a service for reloading, which means it will be reloaded on the next request for it, as opposed to right now, which is what the reloadService() method does.
protected abstract  void putInDefaults()
          Override this to put in service defaults.
 void reloadService(java.lang.String pattern)
          reloads a single service - that is, creates a new Service routing table entry, attempts to reload the properties, and if all goes well, replaces the old service with the new one.
abstract  void routeRequest(int request_id, java.net.Socket sock, java.io.InputStream is, java.io.OutputStream os, java.util.Hashtable cgi_envars, java.util.Hashtable form_hash, java.util.Hashtable steam_vars, java.lang.String[] url_tokens, java.lang.String request_uri, long bstamp_id, Response resp, java.sql.Connection conn, Session session, java.util.Hashtable attributes)
          This is the method which actually routes a request to a particular service.
 java.lang.Class routeToClass(LocoConfig config, java.lang.String pattern)
          returns the service class for the specified pattern NOTE: I think this is only used for Handlers! --JB
 java.lang.Object routeToService(LocoConfig config, java.lang.String request_uri, java.lang.String first_token)
          Finds and returns the service Object associated with the specified request uri.
 ServiceRoutingTable.ServiceEntry routeToServiceEntry(LocoConfig config, java.lang.String request_uri, java.lang.String first_token)
          Returns the ServiceEntry Object appropriate for the given config, URI, and first token.
 boolean shutdown()
          Attempts to shut down each of the services
protected  void throwException(java.lang.String message)
          throw an initializationException with the correct classname
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

AVAILABLE

public static final int AVAILABLE
If the instance member availability is set to AVAILABLE, that means that this ServiceEntry's service is available to serve requests.

UNAVAILABLE_AND_WAITING

public static final int UNAVAILABLE_AND_WAITING
If the instance member availability is set to UNAVAILABLE_AND_WAITING, that means that this ServiceEntry's service is currently unavailable, but may become available again after unavailable_seconds have elapsed.

PERMANENTLY_UNAVAILABLE

public static final int PERMANENTLY_UNAVAILABLE
If the instance member availability is set to PERMANENTLY_UNAVAILABLE, that means that this ServiceEntry's service is unavailable, and probably won't be available again until the system administrator(s) restart the Locomotive.

SHUTDOWN

public static final int SHUTDOWN
If the instance member availability is set to SHUTDOWN, that means that the Object factory for this service has been shut down.

server_log

protected Log server_log

service_tokens_hash

protected java.util.Hashtable service_tokens_hash
The Hashtable that stores token-to-service mappings

service_extensions_hash

protected java.util.Hashtable service_extensions_hash
The Hashtable that stores extension-to-service mappings

service_configs

protected java.util.Hashtable service_configs
The Hashtable that stores service-to-propsfile mappings
Constructor Detail

ServiceRoutingTable

public ServiceRoutingTable(java.lang.String path,
                           Log log,
                           java.util.Vector classpath,
                           boolean auto_reload)
creates a new (but uninitialized) HanderRouting Table
Parameters:
path - the path to the table file
log - a server log
classpath - a Vector of paths to search for service classes in
Method Detail

initialize

public void initialize()
                throws InitializationException
initializes or re-initializes this object's routing structures based on the defaults and the contents of the file at the location specified in 'path' in the Constructor. Returns true if successful.
Throws:
InitializationException - if the file could not be loaded correctly, or if any of the Services could not be loaded successfully.

shutdown

public boolean shutdown()
Attempts to shut down each of the services

createServiceEntry

protected abstract ServiceRoutingTable.ServiceEntry createServiceEntry(java.lang.String pattern,
                                                                       java.lang.String classname,
                                                                       java.lang.String config_path)
Override this to return the ServiceEntry class you need. It should just call the constructor for a subclass of serviceEntry, then return the newly contructed object. This should never be called in your code- call addService instead, which will call this, then register the newly created service.

addService

public void addService(java.lang.String pattern,
                       java.lang.String classname,
                       java.lang.String config_path)
                throws InitializationException
Creates and adds a new service to the ServiceRoutingTable. Note that this will call the createService() method to instantiate a new serviceEntry. Be sure to override it to create the service entry you need.
Parameters:
pattern - the pattern that the service is mapped to.
classname - the service class's name.
config_path - the path to the objects' properties file. Leave this null if the service doesn't have a properties file.
Throws:
InitializationException - if the ServiceEntry could not be loaded successfully.

containsService

public boolean containsService(java.lang.String pattern)
Returns true if there is a service associated with this pattern

routeRequest

public abstract void routeRequest(int request_id,
                                  java.net.Socket sock,
                                  java.io.InputStream is,
                                  java.io.OutputStream os,
                                  java.util.Hashtable cgi_envars,
                                  java.util.Hashtable form_hash,
                                  java.util.Hashtable steam_vars,
                                  java.lang.String[] url_tokens,
                                  java.lang.String request_uri,
                                  long bstamp_id,
                                  Response resp,
                                  java.sql.Connection conn,
                                  Session session,
                                  java.util.Hashtable attributes)
This is the method which actually routes a request to a particular service. This must be overridden to each different ServiceRoutingTable.
Parameters:
request_id - the unique id for this request
sock - the socket this request connected on
is - the inputstream from that socket
os - the outputstream from that socket
reply_protocol - the protocol type we received the request from
cgi_envars - the CGI variables passed in with the request
form_hash - the form data, if there was any
url_tokens - a tokenized form of the url
request_uri - the unparsed url tokens
bstamp_id - the browser stamp id that came in from the bstamp cookie for this request
conn - the Database connection for this request
session - the Session object for this request
user - the user for this request

routeToClass

public java.lang.Class routeToClass(LocoConfig config,
                                    java.lang.String pattern)
returns the service class for the specified pattern NOTE: I think this is only used for Handlers! --JB

routeToService

public java.lang.Object routeToService(LocoConfig config,
                                       java.lang.String request_uri,
                                       java.lang.String first_token)
Finds and returns the service Object associated with the specified request uri. This method first tries to match the first token to a token mapping (like "base"), and then tries to match the request uri to an extension mapping (like "*.jsp").

routeToServiceEntry

public ServiceRoutingTable.ServiceEntry routeToServiceEntry(LocoConfig config,
                                                            java.lang.String request_uri,
                                                            java.lang.String first_token)
Returns the ServiceEntry Object appropriate for the given config, URI, and first token. Returns null if a suitable service entry cannot be found.

Parameters:
config - the LocoConfig Object.
request_uri - the URI of the request.
first_token - the first token of the request.

getService

public ServiceRoutingTable.ServiceEntry getService(LocoConfig config,
                                                   java.lang.String pattern)
returns the Service Entry object appropriate for the given config and pattern string. Returns null if a suitable service cannot be found. Note that if a reload has been issued and certain classes could not be found the method may also return null (indicative of error)

That it is synchronized should mean that we don't have to worry about synchonizing the methods inside, like initialize. We may want to rethink this...


markServiceForReloading

public void markServiceForReloading(java.lang.String pattern)
Marks a service for reloading, which means it will be reloaded on the next request for it, as opposed to right now, which is what the reloadService() method does.

reloadService

public void reloadService(java.lang.String pattern)
                   throws InitializationException
reloads a single service - that is, creates a new Service routing table entry, attempts to reload the properties, and if all goes well, replaces the old service with the new one.

getProperties

public java.util.Properties getProperties(java.lang.Class theclass)
return the properties object for a given Class. This properties file will always have the path to the properties file as an attribute, called PROPERTIES_PATH.

putInDefaults

protected abstract void putInDefaults()
                               throws InitializationException
Override this to put in service defaults. This class assumes there should be a service installed for the 'unknown' token, and one installed for the 'default' token.

log

protected void log(int log_level,
                   java.lang.String message)
Log with the correct class name

throwException

protected void throwException(java.lang.String message)
                       throws InitializationException
throw an initializationException with the correct classname