source: trunk/ToolboxSearchTool.py @ 66

Revision 66, 6.3 KB checked in by tarmo, 14 years ago (diff)

Changed the svn:eol-style property to "native", since
people aren't using unix line feeds uniformally.

  • Property svn:eol-style set to native
Line 
1from OFS.SimpleItem import SimpleItem
2from OFS.SimpleItem import Item
3from OFS.PropertyManager import PropertyManager
4from Products.CMFCore.utils import UniqueObject
5from Globals import InitializeClass
6from AccessControl import ClassSecurityInfo
7from Products.CMFCore.utils import getToolByName
8from ZODB.PersistentMapping import PersistentMapping
9import xmlrpclib
10from Acquisition import aq_base
11from config import MANAGE_PORTAL
12
13class ToolboxSearchTool(PropertyManager, SimpleItem, UniqueObject):
14    """ toolbox search. Performs standard plone search and xml-rpc search to query distant toolboxes """
15
16    id = 'toolbox_search'
17    meta_type = 'ToolboxSearch'
18    security = ClassSecurityInfo()
19    plone_tool = 1
20    __allow_access_to_unprotected_subobjects__ = 1
21
22    def manage_afterAdd(self, item, container):
23        self._setProperty('enable_remotesearch', True, 'boolean')
24        self.remote_toolboxes = {}
25
26    def toolbox_search(self, REQUEST, **kw):
27    """ toolbox search method. performs local and remote searches """
28        class myremotebrain:
29            """ my brain """
30            __allow_access_to_unprotected_subobjects__=1
31            def __init__(self, ob, data):
32                self.__ob = ob
33                self.data = data
34               
35            def __get__(self, key):
36                try:
37                    return self.data[key]
38                except:
39                    print "ERROR: ", key
40
41            def __getattr__(self, key, default=''):
42                if self.data.has_key(key):
43                    return self.data[key]
44                return getattr(self.__ob, key)
45
46        results = []
47        local = self.local_search(REQUEST, **kw)
48        remote = []
49        if self.getEnableRemoteSearch():
50            remote = self.remote_search(REQUEST, **kw)
51        for x in local:
52            results.append(x)
53        for y in remote:
54            rbrain = myremotebrain(aq_base(self).__of__(self),y)
55            results.append(rbrain)
56    return results
57
58    security.declarePrivate('local_search')
59    def local_search(self, REQUEST, **kw):
60        """ do a local search """
61    portal_catalog = getToolByName( self, 'portal_catalog' )
62    results = portal_catalog.searchResults(REQUEST, **kw)
63        return results
64
65    security.declarePrivate('remote_search')
66    def remote_search(self, REQUEST, **kw):
67        """ do remote search.
68            connects to distant toolbox via xml-rpc and invokes incoming_query method.
69        """
70        # get remote toolbox address from somewhere
71        tb_locations = self.get_urls_of_remote_toolboxes()
72        result = []
73        if tb_locations is None:
74            return result
75        for tb in tb_locations:
76            ping = self.ping(tb)
77            if not ping:
78                print "Toolbox @ %s is alive!" % tb
79                # connect now!
80                r = xmlrpclib.Server(tb+'/'+self.getId(), allow_none=1)
81                query_str = REQUEST.get('QUERY_STRING')
82                query = {}
83                q_tmp = query_str.split('&')
84                params = []
85                for pair in q_tmp:
86                    key_tmp, value = pair.split('=')
87                    key = key_tmp.split('%')[0]
88                    if key not in params:
89                        params.append(key)
90                for p in params:
91                    query[p] = REQUEST.get(p)
92                #XXX: this is evil. need to find out if unix timestamps are ok here.
93                query['created'] = str(query['created'])
94                result += r.incoming_search(query)
95                #XXX: when passing **kw
96                #XXX: TypeError: __call__() got an unexpected keyword argument 'use_types_blacklist'
97            else:
98                print "Toolbox @ %s is dead!" % tb
99        return result
100
101    security.declarePublic('incoming_search')
102    def incoming_search(self, query):
103        """ search request coming from remote toolbox uses this method """
104        from DateTime import DateTime
105        #XXX: this is evil. need to find out if unix timestamps are ok here.
106        # mybrains object doesn't want to travel over xml-rpc...
107        query['created'] = eval(query['created'])
108        query_results = self.local_search(query)
109        results = []
110        for x in query_results:
111            # XXX: should use schema values here?
112            results.append({'Title':x.Title,
113                    'Description':x.Description,
114                    'pretty_title_or_id':x.pretty_title_or_id(),
115                    'Creator':x.Creator,
116                    'ModificationDate':x.ModificationDate,
117                    'getURL':x.getURL(),
118                    'portal_type':x.portal_type,
119                    'review_state':x.review_state,
120                    'data_record_normalized_score_':x.data_record_normalized_score_,
121                    })
122        return results
123
124    def get_urls_of_remote_toolboxes(self):
125        """ get remote toolbox locations. ie. ('http://localhost:9090/SecondToolBox',) """
126        result = []
127        for x in self.remote_toolboxes.values():
128            result.append(x['URL'])
129        return result
130
131    def get_remote_toolboxes(self):
132        return self.remote_toolboxes
133
134    def ping(self, address):
135        """ ping remote toolbox, see if it's alive """
136        address = address +'/'+ self.getId()
137        r = xmlrpclib.Server(address)
138        remote = r.pong('ping')
139        if remote != 'pong':
140            return 1
141        return 0
142
143    def pong(self, ping):
144        """ respond to ping """
145        if ping != 'ping':
146            return 1
147        return "pong"
148
149    security.declareProtected(MANAGE_PORTAL, 'manage_changeLocations')
150    def setNewLocation(self, location):
151        """ set remote search location and protocol """
152        import time
153        timestamp = time.time()
154        while self.remote_toolboxes.has_key(str(int(timestamp))):
155            timestamp = time.time()
156        timestamp = str(int(timestamp))
157        self.remote_toolboxes[timestamp] = {'URL': location, 'protocol': 'xmlrpc'}
158        self._p_changed = True
159        return 0
160
161    def delete_remote_toolbox(self, id):
162        """ delete remote toolbox address from our list """
163        del self.remote_toolboxes[id]
164        self._p_changed = True
165
166    def getEnableRemoteSearch(self):
167        return self.enable_remotesearch
168   
169    def setEnableRemoteSearch(self, enable):
170        self.enable_remotesearch = enable
171
172InitializeClass(ToolboxSearchTool)
Note: See TracBrowser for help on using the repository browser.