Index: fedd/fedd_allocate_project.py
===================================================================
--- fedd/fedd_allocate_project.py	(revision f8582c9a024862e2f99c61a303029f0c7929d8b3)
+++ fedd/fedd_allocate_project.py	(revision cfabc4029587360a09aa12f17fb3b457c2e3f18c)
@@ -74,13 +74,13 @@
 	# Internal services are SOAP only
 	self.soap_services = {\
-		"AllocateProject": make_soap_handler(\
+		"AllocateProject": soap_handler(\
 		AllocateProjectRequestMessage.typecode,\
 		self.dynamic_project, AllocateProjectResponseMessage,\
 		"AllocateProjectResponseBody"), 
-		"StaticProject": make_soap_handler(\
+		"StaticProject": soap_handler(\
 		StaticProjectRequestMessage.typecode,\
 		self.static_project, StaticProjectResponseMessage,\
 		"StaticProjectResponseBody"),\
-		"ReleaseProject": make_soap_handler(\
+		"ReleaseProject": soap_handler(\
 		ReleaseProjectRequestMessage.typecode,\
 		self.release_project, ReleaseProjectResponseMessage,\
@@ -345,74 +345,53 @@
 	return { 'project': req['ReleaseProjectRequestBody']['project']}
 
-def make_proxy(method, req_name, req_alloc, resp_name):
-    """
-    Construct the proxy calling function from the given parameters.
-    """
-
-    # Define the proxy, NB, the parameters to make_proxy are visible to the
-    # definition of proxy.
-    def proxy(self, req, fedid=None):
-	"""
-	Send req on to a remote project instantiator.
-
-	Req is just the message to be sent.  This function re-wraps it.
-	It also rethrows any faults.
-	"""
-
-	# No retry loop here.  Proxy servers must correctly authenticate
-	# themselves without help
-	try:
-	    ctx = fedd_ssl_context(self.cert_file, self.trusted_certs,
-		    password=self.cert_pwd)
-	except SSL.SSLError:
-	    raise service_error(service_error.server_config, 
-		    "Server certificates misconfigured")
-
-	loc = feddInternalServiceLocator();
-	port = loc.getfeddInternalPortType(self.url,
-		transport=M2Crypto.httpslib.HTTPSConnection, 
-		transdict={ 'ssl_context' : ctx })
-
-	if req.has_key(req_name):
-	    req = req[req_name]
-	else:
-	    raise service_error(service_error.req, "Bad formated request");
-
-	# Reconstruct the full request message
-	msg = req_alloc()
-	set_elem = getattr(msg, "set_element_%s" % req_name)
-	set_elem(pack_soap(msg, req_name, req))
-	try:
-	    mattr = getattr(port, method)
-	    resp = mattr(msg)
-	except ZSI.ParseException, e:
-	    raise service_error(service_error.proxy,
-		    "Bad format message (XMLRPC??): %s" % str(e))
-	except ZSI.FaultException, e:
-	    resp = e.fault.detail[0]
-
-	r = unpack_soap(resp)
-
-	if r.has_key(resp_name):
-	    return r[resp_name]
-	else:
-	    raise service_error(service_error.proxy, "Bad proxy response")
-    # NB: end of proxy function definition	
-    return proxy
-
 class fedd_allocate_project_remote:
     """
     Allocate projects on a remote machine using the internal SOAP interface
     """
-    dynamic_project = make_proxy("AllocateProject",
-	    "AllocateProjectRequestBody", AllocateProjectRequestMessage,
-	    "AllocateProjectResponseBody")
-    static_project = make_proxy("StaticProject",
-	    "StaticProjectRequestBody", StaticProjectRequestMessage,
-	    "StaticProjectResponseBody")
-    release_project = make_proxy("ReleaseProject",
-	    "ReleaseProjectRequestBody", ReleaseProjectRequestMessage,
-	    "ReleaseProjectResponseBody")
-
+    class proxy(service_caller):
+	"""
+	This class is a proxy functor (callable) that has the same signature as
+	a function called by soap_handler or xmlrpc_handler, but that used the
+	service_caller class to call the function remotely.
+	"""
+
+	def __init__(self, url, cert_file, cert_pwd, trusted_certs, 
+		method, req_name, req_alloc, resp_name):
+	    service_caller.__init__(self, method, 'getfeddInternalPortType',
+		    feddInternalServiceLocator, req_alloc, req_name)
+	    self.url = url
+	    self.cert_file = cert_file
+	    self.cert_pwd = cert_pwd
+	    self.trusted_certs = trusted_certs
+	    self.resp_name = resp_name
+	    # Calling the proxy object directly invokes the proxy_call method,
+	    # not the service_call method.
+	    self.__call__ = self.proxy_call
+	    
+
+	# Define the proxy, NB, the parameters to make_proxy are visible to the
+	# definition of proxy.
+	def proxy_call(self, req, fedid=None):
+	    """
+	    Send req on to a remote project instantiator.
+
+	    Req is just the message to be sent.  This function re-wraps it.
+	    It also rethrows any faults.
+	    """
+
+	    if req.has_key(self.request_body_name):
+		req = req[self.request_body_name]
+	    else:
+		raise service_error(service_error.req, "Bad formated request");
+
+	    r = self.call_service(self.url, req, self.cert_file, self.cert_pwd,
+		    self.trusted_certs)
+	    if r.has_key(self.resp_name):
+		return r[self.resp_name]
+	    else:
+		raise service_error(service_error.protocol, 
+			"Bad proxy response")
+
+    # back to defining the fedd_allocate_project_remote class
     def __init__(self, config):
 	"""
@@ -457,2 +436,16 @@
 	self.log = logging.getLogger("fedd.allocate.remote")
 	set_log_level(config, "access", self.log)
+	# The specializations of the proxy functions
+	self.dynamic_project = self.proxy(self.url, self.cert_file, 
+		self.cert_pwd, self.trusted_certs, "AllocateProject",
+		"AllocateProjectRequestBody", AllocateProjectRequestMessage,
+		"AllocateProjectResponseBody")
+	self.static_project = self.proxy(self.url, self.cert_file, 
+		self.cert_pwd, self.trusted_certs, "StaticProject",
+		"StaticProjectRequestBody", StaticProjectRequestMessage,
+		"StaticProjectResponseBody")
+	self.release_project = self.proxy(self.url, self.cert_file,
+		self.cert_pwd, self.trusted_certs, "ReleaseProject",
+		"ReleaseProjectRequestBody", ReleaseProjectRequestMessage,
+		"ReleaseProjectResponseBody")
+
