# should take the runtime parameters out of the body.
            # Sanity checking and filling in of defaults for the runtime parameers
            if service_def.get('allow_params_in_body')  and  input:
                base_params = input
                if base_params:
                    input = None

                # Load the values from the body into the runtime_param_dict, but
                # only those which are not defined there yet. This allows the
                # command line args to overwrite what's specified in the body.
                for name, value in base_params.items():
                    if name not in runtime_param_dict:
                        runtime_param_dict[name] = value

            paramSanityCheck(runtime_param_dict, runtime_param_def, "runtime parameter")
            fillDefaults(runtime_param_def, runtime_param_dict)
            convertTypes(runtime_param_def, runtime_param_dict)

        if not proxy_dispatch_func:
            service_method     = getattr(component, service_name)
            is_proxy_component = False
        else:
            # Maybe this is a proxy object for a dynamic component (e.g. JavaScript)?
            # In that case, we need to use the generic dispatcher method.
            service_method     = proxy_dispatch_func
            is_proxy_component = True
        
        # Get the parameters from the resource definition time
        params = complete_resource_def['private']['params']

        if runtime_param_dict:
def _accessComponentService(component, services, complete_resource_def, resource_name, service_name,
                            positional_params, runtime_param_dict, input, request=None, method=None, direct_call=False):
    """
    Passes control to a service method exposed by a component.
    
    @param component:             An instance of the component.
    @type component:              BaseComponent (object of child class)
    
    @param services:              Dictionary of services definitions for this component. Can be had
                                  by calling _getServices() on the component. But we would need the
                                  resource's base URI to get those URIs exported properly. Since
                                  we already did this call in process() from where we called this
                                  method, we just pass the services dictionary in, rather than
                                  calling _getServices() again.
    @param services:              dict
    
    @param complete_resource_def: The entire resource definition as it was retrieved from storage.
    @type complete_resource_def:  dict
    
    @param resource_name:         Name of the resource. This may contain '/' if positional parameters
                                  are defined in the URL.
    @type resource_name:          string
    
    @param service_name:          The name of the requested service
    @type service_name:           string
    
    @param positional_params:     List of positional parameters.
    @type positional_params:      list

    @param runtime_param_dict:    Dictionary of URL command line arguments.
    @type runtime_param_dict:     dict
    
    @param input:                 Any potential input (came in the request body)
    @type input:                  string

    @param request:               HTTP request structure.
    @type request:                RestxHttpRequest
    
    @param method:                Http method of the request.
    @type method:                 HttpMethod
    
    @param direct_call:           Set this if the function is called directly from another component
                                  or piece of code that's not part of RESTx. In that case, it wraps
                                  the actual exception in a 'normal' exception and passes it up.
                                  That allows the framework code to react differently to exceptions
                                  in here than direct-call code.
    @type direct_call:            boolean
    
    @return                       HTTP result structure
    @rtype                        Result
    
    """
    try:
        service_def = services.get(service_name)
        if not service_def:
            raise RestxException("Service '%s' is not available in this resource." % service_name)

        #
        # Some runtime parameters may have been provided as arguments on
        # the URL command line. They need to be processed and added to
        # the parameters if necessary.
        #
        # Parameters may either appear as named arguments after the URL,
        # like this:  http://resource/somename?name1=val1&name2=val2
        #
        # If positional parameters are defined for the service then they
        # may be extracted from the URL. For example, if the positional
        # parameters are defined as [ "name1", "name2" ] then the URL can
        # be this: http://resource/somename/val1/val2/
        # With that URL and using the order that's defined in the
        # positional parameter definition, the values are assigned
        # like this: name1=val1, name2=val2
        #
        # Parameters specified in the first form (named arguments after '?')
        # override the same parameters specified in the URL itself.
        #
        # Why did we not check for those parameters earlier when the
        # runtime_param_dict parameter was created before this function
        # was called? Because we may have been called out of the accessResource()
        # method, which could possibly use a complete 
        #
        if positional_params:
            try:
                pos_param_def = complete_resource_def['public']['services'][service_name]['positional_params']
            except Exception, e:
                pos_param_def = None
            if pos_param_def:
                # Iterating over all the positional parameters that are provided in the URI
                # There might be some empty ones (when the URL has two // in a row or ends
                # in a /). In that case, we skip that parameter.
                pos_def_index = 0
                for value in positional_params:
                    if value:
                        pname = pos_param_def[pos_def_index]
                        pos_def_index += 1
                        # Put the new value in the runtime_parameter_dict, but only if it
                        # doesn't exist there already (parameters specified after a '?'
                        # are in there and they take precedence).
                        if pname not in runtime_param_dict:
                            runtime_param_dict[pname] = value
                    if pos_def_index == len(pos_param_def):
                        # No more positional parameters defined? We will ignore whatever
                        # else is in the URL
                        break
            
        runtime_param_def  = service_def.get('params')
        if runtime_param_def:
            # If the 'allow_params_in_body' flag is set for a service then we
            # allow runtime parameters to be passed in the request body PUT or POST.
            # So, if the URL command line parameters are not specified then we
            # should take the runtime parameters out of the body.
            # Sanity checking and filling in of defaults for the runtime parameters
            if service_def.get('allow_params_in_body')  and  input:
                # Take the base definition of the parameters from the request body
                try:
                    base_params = json.loads(input.strip())
                    input       = None  # The input is now 'used up'
                except ValueError, e:
                    # Probably couldn't parse JSON properly.
                    base_param = {}
                # Load the values from the body into the runtime_param_dict, but
                # only those which are not defined there yet. This allows the
                # command line args to overwrite what's specified in the body.
                for name, value in base_params.items():
                    if name not in runtime_param_dict:
                        runtime_param_dict[name] = value

            paramSanityCheck(runtime_param_dict, runtime_param_def, "runtime parameter")
            fillDefaults(runtime_param_def, runtime_param_dict)
            convertTypes(runtime_param_def, runtime_param_dict)
Exemple #3
0
def _accessComponentService(component,
                            services,
                            complete_resource_def,
                            resource_name,
                            service_name,
                            positional_params,
                            runtime_param_dict,
                            input,
                            request=None,
                            method=None,
                            direct_call=False):
    """
    Passes control to a service method exposed by a component.
    
    @param component:             An instance of the component.
    @type component:              BaseComponent (object of child class)
    
    @param services:              Dictionary of services definitions for this component. Can be had
                                  by calling _getServices() on the component. But we would need the
                                  resource's base URI to get those URIs exported properly. Since
                                  we already did this call in process() from where we called this
                                  method, we just pass the services dictionary in, rather than
                                  calling _getServices() again.
    @param services:              dict
    
    @param complete_resource_def: The entire resource definition as it was retrieved from storage.
    @type complete_resource_def:  dict
    
    @param resource_name:         Name of the resource. This may contain '/' if positional parameters
                                  are defined in the URL.
    @type resource_name:          string
    
    @param service_name:          The name of the requested service
    @type service_name:           string
    
    @param positional_params:     List of positional parameters.
    @type positional_params:      list

    @param runtime_param_dict:    Dictionary of URL command line arguments.
    @type runtime_param_dict:     dict
    
    @param input:                 Any potential input (came in the request body)
    @type input:                  string

    @param request:               HTTP request structure.
    @type request:                RestxHttpRequest
    
    @param method:                Http method of the request.
    @type method:                 HttpMethod
    
    @param direct_call:           Set this if the function is called directly from another component
                                  or piece of code that's not part of RESTx. In that case, it wraps
                                  the actual exception in a 'normal' exception and passes it up.
                                  That allows the framework code to react differently to exceptions
                                  in here than direct-call code.
    @type direct_call:            boolean
    
    @return                       HTTP result structure
    @rtype                        Result
    
    """
    try:
        service_def = services.get(service_name)
        if not service_def:
            raise RestxException(
                "Service '%s' is not available in this resource." %
                service_name)

        #
        # Some runtime parameters may have been provided as arguments on
        # the URL command line. They need to be processed and added to
        # the parameters if necessary.
        #
        # Parameters may either appear as named arguments after the URL,
        # like this:  http://resource/somename?name1=val1&name2=val2
        #
        # If positional parameters are defined for the service then they
        # may be extracted from the URL. For example, if the positional
        # parameters are defined as [ "name1", "name2" ] then the URL can
        # be this: http://resource/somename/val1/val2/
        # With that URL and using the order that's defined in the
        # positional parameter definition, the values are assigned
        # like this: name1=val1, name2=val2
        #
        # Parameters specified in the first form (named arguments after '?')
        # override the same parameters specified in the URL itself.
        #
        # Why did we not check for those parameters earlier when the
        # runtime_param_dict parameter was created before this function
        # was called? Because we may have been called out of the accessResource()
        # method, which could possibly use a complete
        #
        if positional_params:
            try:
                pos_param_def = complete_resource_def['public']['services'][
                    service_name]['positional_params']
            except Exception, e:
                pos_param_def = None
            if pos_param_def:
                # Iterating over all the positional parameters that are provided in the URI
                # There might be some empty ones (when the URL has two // in a row or ends
                # in a /). In that case, we skip that parameter.
                pos_def_index = 0
                for value in positional_params:
                    if value:
                        pname = pos_param_def[pos_def_index]
                        pos_def_index += 1
                        # Put the new value in the runtime_parameter_dict, but only if it
                        # doesn't exist there already (parameters specified after a '?'
                        # are in there and they take precedence).
                        if pname not in runtime_param_dict:
                            runtime_param_dict[pname] = value
                    if pos_def_index == len(pos_param_def):
                        # No more positional parameters defined? We will ignore whatever
                        # else is in the URL
                        break

        runtime_param_def = service_def.get('params')
        if runtime_param_def:
            # If the 'allow_params_in_body' flag is set for a service then we
            # allow runtime parameters to be passed in the request body PUT or POST.
            # So, if the URL command line parameters are not specified then we
            # should take the runtime parameters out of the body.
            # Sanity checking and filling in of defaults for the runtime parameters
            if service_def.get('allow_params_in_body') and input:
                # Take the base definition of the parameters from the request body
                try:
                    base_params = json.loads(input.strip())
                    input = None  # The input is now 'used up'
                except ValueError, e:
                    # Probably couldn't parse JSON properly.
                    base_param = {}
                # Load the values from the body into the runtime_param_dict, but
                # only those which are not defined there yet. This allows the
                # command line args to overwrite what's specified in the body.
                for name, value in base_params.items():
                    if name not in runtime_param_dict:
                        runtime_param_dict[name] = value

            paramSanityCheck(runtime_param_dict, runtime_param_def,
                             "runtime parameter")
            fillDefaults(runtime_param_def, runtime_param_dict)
            convertTypes(runtime_param_def, runtime_param_dict)