Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 9febd3f003653456ffe37792b7104677fe22ccbf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# *******************************************************************************
# * Copyright (c) 2011 Wind River Systems, Inc. and others.
# * All rights reserved. This program and the accompanying materials
# * are made available under the terms of the Eclipse Public License v1.0
# * which accompanies this distribution, and is available at
# * http://www.eclipse.org/legal/epl-v10.html
# *
# * Contributors:
# *     Wind River Systems - initial API and implementation
# *******************************************************************************

import threading, exceptions, collections
from tcf import protocol

_providers = []
_lock = threading.RLock()

class ServiceProvider(object):
    """
    Clients can implement this abstract class if they want to provide implementation of a local service or
    remote service proxy.
    """
    def getLocalService(self, channel):
        pass
    def getServiceProxy(self, channel, service_name):
        pass

def addServiceProvider(provider):
    with _lock:
        _providers.append(provider)

def removeServiceProvider(provider):
    with _lock:
        _providers.remove(provider)

def onChannelCreated(channel, services_by_name):
    with _lock:
        # TODO ZeroCopy support is incomplete
#        zero_copy = ZeroCopy()
#        services_by_name[zero_copy.getName()] = zero_copy
        for provider in _providers:
            try:
                arr = provider.getLocalService(channel)
                if not arr: continue
                for service in arr:
                    if services_by_name.has_key(service.getName()): continue
                    services_by_name[service.getName()] = service
            except exceptions.Exception as x:
                protocol.log("Error calling TCF service provider", x);

def onChannelOpened(channel, service_names, services_by_name):
    with _lock:
        for name in service_names:
            for provider in _providers:
                try:
                    service = provider.getServiceProxy(channel, name)
                    if not service: continue
                    services_by_name[name] = service
                    break
                except exceptions.Exception as x:
                    protocol.log("Error calling TCF service provider", x)
            if services_by_name.has_key(name): continue
            services_by_name[name] = GenericProxy(channel, name)

def getServiceManagerID():
    # In current implementation ServiceManager is a singleton,
    # so its ID is same as agent ID.
    return protocol.getAgentID()

class GenericCallback(object):
    def __init__(self, callback):
        self.callback = callback
    def __getattr__(self, attr):
        if attr.startswith("done"):
            return self.callback

class Service(object):
    def getName(self):
        raise exceptions.NotImplementedError("Abstract method")
    def __str__(self):
        return self.getName()
    def _makeCallback(self, done):
        if isinstance(done, collections.Callable):
            return GenericCallback(done)
        return done

class ZeroCopy(Service):
    def getName(self):
        return "ZeroCopy"

class GenericProxy(Service):
    """
     * Objects of GenericProxy class represent remote services, which don't
     * have a proxy class defined for them.
     * Clients still can use such services, but framework will not provide
     * service specific utility methods for message formatting and parsing.
    """
    def __init__(self, channel, name):
        self.__channel = channel
        self.name = name
    def getName(self):
        return self.name
    def getChannel(self):
        return self.__channel

class DefaultServiceProvider(ServiceProvider):
    package_base = "tcf.services.remote"
    def getLocalService(self, channel):
        # TODO DiagnosticsService
        #return [DiagnosticsService(channel)]
        return []
    def getServiceProxy(self, channel, service_name):
        service = None
        try:
            clsName = service_name + "Proxy"
            package = self.package_base + "." + clsName
            clsModule = __import__(package, fromlist=[clsName], globals=globals())
            cls = clsModule.__dict__.get(clsName)
            service = cls(channel)
            assert service_name == service.getName()
        except exceptions.ImportError:
            pass
        except exceptions.Exception as x:
            protocol.log("Cannot instantiate service proxy for "+service_name, x)
        return service

addServiceProvider(DefaultServiceProvider())

Back to the top