• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/opal/ZSI/build/lib/ZSI/generate/wsdl2dispatch.py

00001 #!/usr/bin/env python
00002 import inspect
00003 from cStringIO import StringIO
00004 import ZSI, string, sys, getopt, urlparse, types, warnings
00005 from ZSI.wstools import WSDLTools
00006 from ZSI.ServiceContainer import ServiceSOAPBinding, SimpleWSResource, WSAResource
00007 
00008 from ZSI.generate import WsdlGeneratorError, Wsdl2PythonError
00009 from utility import TextProtect, GetModuleBaseNameFromWSDL, \
00010     NCName_to_ClassName, GetPartsSubNames, TextProtectAttributeName
00011 from containers import BindingDescription
00012 from wsdl2python import MessageWriter, WriteServiceModule,\
00013     MessageTypecodeContainer, SchemaDescription
00014 
00015 # Split last token
00016 rsplit = lambda x,sep,: (x[:x.rfind(sep)], x[x.rfind(sep)+1:],)
00017 if sys.version_info[0:2] == (2, 4, 0, 'final', 0)[0:2]:
00018     rsplit = lambda x,sep,: x.rsplit(sep, 1)
00019 
00020 
00021 class SOAPService:
00022     def __init__(self, service):
00023         self.classdef = StringIO()
00024         self.initdef  = StringIO()
00025         self.location = ''
00026         self.methods  = []
00027 
00028     def newMethod(self):
00029         '''name -- operation name
00030         '''
00031         self.methods.append(StringIO())
00032         return self.methods[-1]
00033 
00034 
00035 class ServiceModuleWriter:
00036     '''Creates a skeleton for a SOAP service instance.
00037     '''
00038     indent = ' '*4
00039     server_module_suffix = '_server'
00040     func_aname = TextProtectAttributeName
00041     func_aname = staticmethod(func_aname)
00042     separate_messages = False 
00043 
00044     def __init__(self, base=ServiceSOAPBinding, prefix='soap', 
00045                  service_class=SOAPService):
00046         '''
00047         parameters:
00048             base -- either a class definition, or a str representing a qualified 
00049                 class name (eg. module.name.classname)
00050             prefix -- method prefix.
00051         '''
00052         if inspect.isclass(base):
00053             self.base_class_name = base.__name__
00054             self.base_module_name = inspect.getmodule(base).__name__
00055         else:
00056             self.base_module_name, self.base_class_name  = base.rsplit('.', 1)
00057 
00058         self.wsdl = None
00059         self.method_prefix = prefix
00060         self._service_class = SOAPService
00061 
00062         self.header  = None
00063         self.imports  = None
00064         self.messages = []
00065         self._services = None
00066         self.types_module_path = None
00067         self.types_module_name = None
00068         self.messages_module_name = None
00069 
00070     def reset(self):
00071         self.header  = StringIO()
00072         self.imports  = StringIO()
00073         self.message = []
00074         self._services = {}
00075 
00076     def getIndent(self, level=1):
00077         '''return indent.
00078         '''
00079         assert 0 < level < 10, 'bad indent level %d' %level
00080         return self.indent*level
00081 
00082     def getMethodName(self, method):
00083         '''return method name.
00084         '''
00085         return '%s_%s' %(self.method_prefix, TextProtect(method))
00086 
00087     def getClassName(self, name):
00088         '''return class name.
00089         '''
00090         return NCName_to_ClassName(name)
00091 
00092     def setTypesModuleName(self, name):
00093         self.types_module_name = name
00094 
00095     # Backwards compatibility
00096     setClientModuleName = setTypesModuleName
00097     
00098     def getTypesModuleName(self):
00099         '''return module name.
00100         '''
00101         assert self.wsdl is not None, 'initialize, call fromWSDL'
00102         if self.types_module_name is not None:
00103             return self.types_module_name
00104 
00105         wsm = WriteServiceModule(self.wsdl)
00106         return wsm.getTypesModuleName()
00107 
00108     def getServiceModuleName(self):
00109         '''return module name.
00110         '''
00111         name = GetModuleBaseNameFromWSDL(self.wsdl)
00112         if not name:
00113             raise WsdlGeneratorError, 'could not determine a service name'
00114         
00115         if self.server_module_suffix is None:
00116             return name
00117         return '%s%s' %(name, self.server_module_suffix)
00118 
00119     def getTypesModulePath(self):
00120         return self.types_module_path
00121     getClientModulePath = getTypesModulePath
00122     
00123     def setTypesModulePath(self, path):
00124         '''setup module path to where client module before calling fromWSDL.
00125         '''
00126         self.types_module_path = path
00127     setClientModulePath = setTypesModulePath
00128     
00129     def setUpClassDef(self, service):
00130         '''set class definition and class variables.
00131         service -- ServiceDescription instance
00132         '''
00133         assert isinstance(service, WSDLTools.Service) is True,\
00134             'expecting WSDLTools.Service instance.'
00135 
00136         s = self._services[service.name].classdef
00137 
00138         print >>s, 'class %s(%s):' %(self.getClassName(service.name), self.base_class_name)
00139 
00140         print >>s, '%ssoapAction = {}' % self.getIndent(level=1)
00141         print >>s, '%sroot = {}' % self.getIndent(level=1)
00142         
00143     def setUpImports(self):
00144         '''set import statements
00145         '''
00146         i = self.imports
00147         print >>i, 'from ZSI.schema import GED, GTD'
00148         print >>i, 'from ZSI.TCcompound import ComplexType, Struct'
00149 
00150         module = self.getTypesModuleName()
00151         package = self.getTypesModulePath()
00152         if package:
00153             module = '%s.%s' %(package, module)
00154             
00155         print >>i, 'from %s import *' %(module)
00156             
00157         print >>i, 'from %s import %s' %(self.base_module_name, self.base_class_name)
00158 
00159     def setUpInitDef(self, service):
00160         '''set __init__ function
00161         '''
00162         assert isinstance(service, WSDLTools.Service), \
00163             'expecting WSDLTools.Service instance.'
00164             
00165         sd = self._services[service.name]
00166         d = sd.initdef
00167  
00168         if sd.location is not None:
00169             scheme,netloc,path,params,query,fragment = urlparse.urlparse(sd.location)
00170             print >>d, '%sdef __init__(self, post=\'%s\', **kw):' %(self.getIndent(level=1), path)
00171         else:
00172             print >>d, '%sdef __init__(self, post, **kw):' %self.getIndent(level=1)
00173 
00174         # Require POST initialization value for test implementation
00175         if self.base_module_name == inspect.getmodule(ServiceSOAPBinding).__name__:
00176             print >>d, '%s%s.__init__(self, post)' %(self.getIndent(level=2), self.base_class_name)
00177             return 
00178 
00179         # No POST initialization value, obtained from HTTP Request in twisted or wsgi
00180         print >>d, '%s%s.__init__(self)' %(self.getIndent(level=2), self.base_class_name)
00181 
00182     def mangle(self, name):
00183         return TextProtect(name)
00184 
00185     def getAttributeName(self, name):
00186         return self.func_aname(name)
00187 
00188     def setUpMethods(self, port):
00189         '''set up all methods representing the port operations.
00190         Parameters:
00191             port -- Port that defines the operations.
00192         '''
00193         assert isinstance(port, WSDLTools.Port), \
00194             'expecting WSDLTools.Port not: ' %type(port)
00195 
00196         sd = self._services.get(port.getService().name)
00197         assert sd is not None, 'failed to initialize.'
00198 
00199         binding = port.getBinding()
00200         portType = port.getPortType()
00201         action_in = ''
00202         for bop in binding.operations:
00203             try:
00204                 op = portType.operations[bop.name]
00205             except KeyError, ex:
00206                 raise WsdlGeneratorError,\
00207                     'Port(%s) PortType(%s) missing operation(%s) defined in Binding(%s)' \
00208                     %(port.name,portType.name,bop.name,binding.name)
00209 
00210             for ext in bop.extensions:
00211                  if isinstance(ext, WSDLTools.SoapOperationBinding):
00212                      action_in = ext.soapAction
00213                      break
00214             else:
00215                 warnings.warn('Port(%s) operation(%s) defined in Binding(%s) missing soapAction' \
00216                     %(port.name,op.name,binding.name)
00217                 )
00218 
00219             msgin = op.getInputMessage()
00220             msgin_name = TextProtect(msgin.name)
00221             method_name = self.getMethodName(op.name)
00222 
00223             m = sd.newMethod()
00224             print >>m, '%sdef %s(self, ps, **kw):' %(self.getIndent(level=1), method_name)
00225             if msgin is not None:
00226                 print >>m, '%srequest = ps.Parse(%s.typecode)' %(self.getIndent(level=2), msgin_name)
00227             else:
00228                 print >>m, '%s# NO input' %self.getIndent(level=2)
00229 
00230             msgout = op.getOutputMessage()
00231             if msgout is not None:
00232                 msgout_name = TextProtect(msgout.name)
00233                 print >>m, '%sreturn request,%s()' %(self.getIndent(level=2), msgout_name)
00234             else:
00235                 print >>m, '%s# NO output' % self.getIndent(level=2)
00236                 print >>m, '%sreturn request,None' % self.getIndent(level=2)
00237 
00238             print >>m, ''
00239             print >>m, '%ssoapAction[\'%s\'] = \'%s\'' %(self.getIndent(level=1), action_in, method_name)
00240             print >>m, '%sroot[(%s.typecode.nspname,%s.typecode.pname)] = \'%s\'' \
00241                      %(self.getIndent(level=1), msgin_name, msgin_name, method_name)
00242 
00243         return
00244 
00245     def setUpHeader(self):
00246         print >>self.header, '#'*50
00247         print >>self.header, '# file: %s.py' %self.getServiceModuleName()
00248         print >>self.header, '#'
00249         print >>self.header, '# skeleton generated by "%s"' %self.__class__
00250         print >>self.header, '#      %s' %' '.join(sys.argv)
00251         print >>self.header, '#'
00252         print >>self.header, '#'*50
00253 
00254     def write(self, fd=sys.stdout):
00255         '''write out to file descriptor, 
00256         should not need to override.
00257         '''
00258         print >>fd, self.header.getvalue()
00259         print >>fd, self.imports.getvalue()
00260         
00261         print >>fd, '# Messages ',
00262         for m in self.messages:
00263             print >>fd, m
00264         
00265         print >>fd, ''
00266         print >>fd, ''
00267         print >>fd, '# Service Skeletons'
00268         for k,v in self._services.items():
00269             print >>fd, v.classdef.getvalue()
00270             print >>fd, v.initdef.getvalue()
00271             for s in v.methods:
00272                 print >>fd, s.getvalue()
00273 
00274     def fromWSDL(self, wsdl):
00275         '''setup the service description from WSDL,
00276         should not need to override.
00277         '''
00278         assert isinstance(wsdl, WSDLTools.WSDL), 'expecting WSDL instance'
00279 
00280         if len(wsdl.services) == 0:
00281             raise WsdlGeneratorError, 'No service defined'
00282             
00283         self.reset() 
00284         self.wsdl = wsdl
00285         self.setUpHeader()
00286         self.setUpImports()
00287                 
00288         for service in wsdl.services:
00289             sd = self._service_class(service.name)
00290             self._services[service.name] = sd
00291 
00292             for port in service.ports:
00293                 desc = BindingDescription(wsdl=wsdl)
00294                 try:
00295                     desc.setUp(port.getBinding())
00296                 except Wsdl2PythonError, ex:
00297                     continue
00298                 
00299                 for soc in desc.operations:
00300                     if not soc.hasInput(): continue
00301                     
00302                     self.messages.append(MessageWriter())
00303                     self.messages[-1].setUp(soc, port, input=True)
00304                     if soc.hasOutput():
00305                         self.messages.append(MessageWriter())
00306                         self.messages[-1].setUp(soc, port, input=False)
00307                 
00308                 for e in port.extensions:
00309                     if isinstance(e, WSDLTools.SoapAddressBinding):
00310                         sd.location = e.location
00311 
00312                 self.setUpMethods(port)
00313 
00314             self.setUpClassDef(service)
00315             self.setUpInitDef(service)
00316 
00317 
00318 class WSAServiceModuleWriter(ServiceModuleWriter):
00319     '''Creates a skeleton for a WS-Address service instance.
00320     '''
00321     def __init__(self, base=WSAResource, prefix='wsa', service_class=SOAPService, 
00322                  strict=True):
00323         '''
00324         Parameters:
00325             strict -- check that soapAction and input ws-action do not collide.
00326         '''
00327         ServiceModuleWriter.__init__(self, base, prefix, service_class)
00328         self.strict = strict
00329 
00330     def createMethodBody(msgInName, msgOutName, **kw):
00331         '''return a tuple of strings containing the body of a method.
00332         msgInName -- None or a str
00333         msgOutName --  None or a str
00334         '''
00335         body = []
00336         if msgInName is not None:
00337             body.append('request = ps.Parse(%s.typecode)' %msgInName)
00338             
00339         if msgOutName is not None:
00340             body.append('return request,%s()' %msgOutName)
00341         else: 
00342             body.append('return request,None')
00343             
00344         return tuple(body)
00345     createMethodBody = staticmethod(createMethodBody)
00346 
00347     def setUpClassDef(self, service):
00348         '''use soapAction dict for WS-Action input, setup wsAction
00349         dict for grabbing WS-Action output values.
00350         '''
00351         assert isinstance(service, WSDLTools.Service), \
00352             'expecting WSDLTools.Service instance'
00353 
00354         s = self._services[service.name].classdef
00355         print >>s, 'class %s(%s):' %(self.getClassName(service.name), self.base_class_name)
00356         print >>s, '%ssoapAction = {}' % self.getIndent(level=1)
00357         print >>s, '%swsAction = {}' % self.getIndent(level=1)
00358         print >>s, '%sroot = {}' % self.getIndent(level=1)
00359 
00360     def setUpMethods(self, port):
00361         '''set up all methods representing the port operations.
00362         Parameters:
00363             port -- Port that defines the operations.
00364         '''
00365         assert isinstance(port, WSDLTools.Port), \
00366             'expecting WSDLTools.Port not: ' %type(port)
00367 
00368         binding = port.getBinding()
00369         portType = port.getPortType()
00370         service = port.getService()
00371         s = self._services[service.name]
00372         for bop in binding.operations:
00373             try:
00374                 op = portType.operations[bop.name]
00375             except KeyError, ex:
00376                 raise WsdlGeneratorError,\
00377                     'Port(%s) PortType(%s) missing operation(%s) defined in Binding(%s)' \
00378                     %(port.name, portType.name, op.name, binding.name)
00379 
00380             soap_action = wsaction_in = wsaction_out = None
00381             if op.input is not None:
00382                 wsaction_in = op.getInputAction()
00383             if op.output is not None:
00384                 wsaction_out = op.getOutputAction()
00385 
00386             for ext in bop.extensions:
00387                 if isinstance(ext, WSDLTools.SoapOperationBinding) is False: continue
00388                 soap_action = ext.soapAction
00389                 if not soap_action: break
00390                 if wsaction_in is None: break
00391                 if wsaction_in == soap_action: break
00392                 if self.strict is False:
00393                     warnings.warn(\
00394                         'Port(%s) operation(%s) in Binding(%s) soapAction(%s) != WS-Action(%s)' \
00395                          %(port.name, op.name, binding.name, soap_action, wsaction_in),
00396                     )
00397                     break
00398                 raise WsdlGeneratorError,\
00399                     'Port(%s) operation(%s) in Binding(%s) soapAction(%s) MUST match WS-Action(%s)' \
00400                      %(port.name, op.name, binding.name, soap_action, wsaction_in)
00401 
00402             method_name = self.getMethodName(op.name)
00403 
00404             m = s.newMethod()
00405             print >>m, '%sdef %s(self, ps, address):' %(self.getIndent(level=1), method_name)
00406             
00407             msgin_name = msgout_name = None
00408             msgin,msgout = op.getInputMessage(),op.getOutputMessage()
00409             if msgin is not None: 
00410                 msgin_name = TextProtect(msgin.name)
00411             if msgout is not None: 
00412                 msgout_name = TextProtect(msgout.name)
00413         
00414             indent = self.getIndent(level=2)
00415             for l in self.createMethodBody(msgin_name, msgout_name):
00416                 print >>m, indent + l
00417 
00418             print >>m, ''
00419             print >>m, '%ssoapAction[\'%s\'] = \'%s\'' %(self.getIndent(level=1), wsaction_in, method_name)
00420             print >>m, '%swsAction[\'%s\'] = \'%s\'' %(self.getIndent(level=1), method_name, wsaction_out)
00421             print >>m, '%sroot[(%s.typecode.nspname,%s.typecode.pname)] = \'%s\'' \
00422                      %(self.getIndent(level=1), msgin_name, msgin_name, method_name)
00423  

Generated on Wed Oct 20 2010 11:12:16 for APBS by  doxygen 1.7.2