Index: trunk/ippToPsps/jython/ipptopsps.py
===================================================================
--- trunk/ippToPsps/jython/ipptopsps.py	(revision 33350)
+++ trunk/ippToPsps/jython/ipptopsps.py	(revision 33350)
@@ -0,0 +1,152 @@
+#!/usr/bin/env jython
+
+import signal
+import sys
+import os
+import time
+import logging
+import socket
+
+from config import Config
+from pslogger import PSLogger
+from ipptopspsdb import IppToPspsDb
+from dxlayer import DXLayer
+from datastore import Datastore
+from dvo import Dvo
+from odm import Odm
+
+
+'''
+Abstract base class for all ippToPsps programs
+handle command-line args, setting up of Config and logger objects, clean exiting etc 
+'''
+class IppToPsps(object):
+
+    '''
+    Constructor
+    '''
+    def __init__(self, argv):
+
+        # are the arsg ok? all programs require a config name
+        if len(sys.argv) < 2: 
+            self.printUsage()
+            self.exitProgram("Wrong args")
+            
+        # some class constants
+        self.PROGNAME = sys.argv[0]
+        self.CONFIGNAME = sys.argv[1]
+        self.HOST = socket.gethostname()
+        self.PID = os.getpid()
+        self.PAUSEPERIOD = 60
+        self.HOURS = None
+        self.MINUTES = None
+        self.SECONDS = None
+
+        # set up config object
+        self.config = Config(self.PROGNAME, self.CONFIGNAME)
+        self.logger = self.config.getLogger(self.HOST, self.PID, 1, 1)
+
+        # create connection to databases database
+        self.ippToPspsDb = IppToPspsDb(self.logger, self.config)
+
+        self.checkClientStatus()
+
+        # catch Ctrl-C signal
+        signal.signal(signal.SIGINT, self.signal_handler)
+
+        # title for log
+        self.logger.infoSeparator()
+        self.logger.infoTitle("ippToPsps '" + self.PROGNAME + "' started")
+
+    '''
+    Parses a poll-time argument string and stored as class variables
+    '''
+    def parsePollTimeArg(self, hours):
+
+        try:
+            self.HOURS = float(hours)
+            self.MINUTES = self.HOURS * 60.0
+            self.SECONDS = self.MINUTES * 60.0
+        except:
+            pass
+
+
+    '''
+    Waits for user defined poll time
+    '''
+    def waitForPollTime(self):
+
+        # if not POLL time set, then return False
+        if not self.SECONDS: return False
+
+        if self.HOURS < 1.0:
+            str = "%.1f minutes" % self.MINUTES
+        else:
+            str = "%.1f hours" % self.HOURS
+
+        self.logger.infoPair("Waiting for", str)
+        time.sleep(self.SECONDS)
+
+        return True
+
+    '''
+    Prints usage to stdout
+    '''
+    def printUsage(self):
+        # using sys.stdout to avoid newline in case sub-classes need to add further args
+        sys.stdout.write("** Usage: " + sys.argv[0] + " <configPath>")
+
+
+    '''
+    Refreshes the config then recreates objects with new settings
+    '''
+    def refreshConfig(self):
+        return self.ippToPspsDb.readConfig(self.HOST, self.PID)
+
+    '''
+    All implementing subclasses (programs) should call this method once in a while to see if it should be paused or killed, otherwise this updates the clients table with current time and reloads the config data
+    '''
+    def checkClientStatus(self):
+
+        self.ippToPspsDb.updateClient(self.PROGNAME, self.HOST, self.PID, self.config.name)
+
+        if self.ippToPspsDb.isKilled(self.HOST, self.PID): 
+            self.exitProgram("killed via Db")
+       
+        # this loop pauses the process if we have no config or we have set it to pause
+        while not self.refreshConfig() or self.ippToPspsDb.isPaused(self.HOST, self.PID):
+
+            self.ippToPspsDb.updateClient(self.PROGNAME, self.HOST, self.PID,  self.config.name)
+            if self.ippToPspsDb.isKilled(self.HOST, self.PID): self.exitProgram("killed while paused")
+            self.logger.infoPair("Paused. Will check again in", "%d secs" % self.PAUSEPERIOD)
+            time.sleep(self.PAUSEPERIOD)
+
+
+    '''
+    Handler for Ctrl-C signal
+    '''
+    def signal_handler(self, signal, frame):
+
+       self.exitProgram("Ctrl-C")
+
+
+    '''
+    Exits the program cleanly, removes info from ipptopsps database
+    '''
+    def exitProgram(self, exitReason):
+
+        # write message to log or stdout if no logger set up
+        try:
+            self.logger.infoPair("Program exited", exitReason)
+        except: 
+            print "** program exited: " + exitReason
+
+        # remove from database if possible
+        try:
+            self.ippToPspsDb.removeClient(self.HOST, self.PID)
+        except:
+            pass
+
+        sys.exit(0)
+   
+
