|
1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 ## |
|
17 # @author Teemu Rytkonen |
|
18 |
|
19 import getpass |
|
20 import StringIO |
|
21 import os |
|
22 import re |
|
23 import copy |
|
24 import logging |
|
25 import httplib |
|
26 import urllib, urllib2 |
|
27 import simplejson |
|
28 import posixpath |
|
29 |
|
30 from cone.public import * |
|
31 from cone.carbon import persistentjson, model |
|
32 from cone.storage import authenticate |
|
33 |
|
34 class WebStorage(api.Storage): |
|
35 """ |
|
36 A general base class for all storage type classes |
|
37 @param path : the reference to the root of the storage. |
|
38 """ |
|
39 |
|
40 def __init__(self, path, mode="a", **kwargs): |
|
41 api.Storage.__init__(self,path) |
|
42 self.mode = mode |
|
43 self.extapi = CarbonExtapi(path, **kwargs) |
|
44 self.persistentmodule = persistentjson |
|
45 |
|
46 # resource cache is a intermediate solution to create a mapping between carbon objects and Configuration project |
|
47 self._resource_cache = None |
|
48 |
|
49 |
|
50 def _create_resource(self, path, object): |
|
51 """ |
|
52 Create a new resource (configuration|featurelist) to carbon storage. |
|
53 """ |
|
54 # Test the path, whether it is a featurelist or configuration |
|
55 try: |
|
56 object_type = object.meta.get('type') |
|
57 except (TypeError,AttributeError): |
|
58 logging.getLogger('cone').error('Cannot dump configuration %s to webstorage without a type.' % path) |
|
59 return False |
|
60 carbonpath = persistentjson.CarbonResourceMapper().map_confml_resource(object_type, path) |
|
61 if object_type == 'featurelist': |
|
62 # Create a featurelist |
|
63 success = self.extapi.create_featurelist(carbonpath, object) |
|
64 if success: |
|
65 self.resource_cache.add_resource_link(path, carbonpath) |
|
66 return success |
|
67 else: |
|
68 # Create a configuration |
|
69 success = self.extapi.create_configuration(carbonpath, object) |
|
70 if success: |
|
71 self.resource_cache.add_resource_link(path, carbonpath) |
|
72 return success |
|
73 |
|
74 @classmethod |
|
75 def supported_storage(cls,path): |
|
76 """ |
|
77 Class method for determing if the given clas supports a storage by given path. |
|
78 E.g. http://foo.com/ |
|
79 @param path: |
|
80 @return: Boolean value. True if the storage of the path is supported. False if not. |
|
81 """ |
|
82 if path.startswith('http://'): |
|
83 return True |
|
84 else: |
|
85 return False |
|
86 |
|
87 @property |
|
88 def resource_cache(self): |
|
89 """ |
|
90 Returns a resource cache dictionary of all the resources inside the Carbon storage. Works as an intermediate |
|
91 solution to link Configuration project concepts to Carbon storage |
|
92 |
|
93 """ |
|
94 if not self._resource_cache: |
|
95 self._resource_cache = ResourceCache() |
|
96 reslist = self.extapi.list_resources("/", True) |
|
97 # Append all resources to resource cache |
|
98 for res in reslist: |
|
99 self._resource_cache.add_resource(res) |
|
100 # if isinstance(res, model.ConfigurationResource): |
|
101 # self._resource_cache.add_configuration(res) |
|
102 # elif isinstance(res, model.FeatureListResource): |
|
103 # self._resource_cache.add_featurelist(res) |
|
104 return self._resource_cache |
|
105 |
|
106 def list_resources(self,path, recurse=False, empty_folders=False): |
|
107 """ |
|
108 find the resources under certain path/path |
|
109 @param path : reference to path where resources are searched |
|
110 @param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders. |
|
111 Default value is False. Set to True to enable recursion. |
|
112 @param empty_folders: parameters that defined whether empty folders are included. This parameter is ignored |
|
113 in WebStorage. |
|
114 """ |
|
115 return self.resource_cache.list_resources(path,recurse) |
|
116 |
|
117 |
|
118 def open_resource(self,path,mode="r"): |
|
119 path = utils.resourceref.remove_begin_slash(path) |
|
120 if self.resource_cache.get_resource_object(path): |
|
121 return self.resource_cache.get_resource_object(path) |
|
122 elif self.resource_cache.get_resource_link(path): |
|
123 path = self.resource_cache.get_resource_link(path) |
|
124 |
|
125 # path = path.replace(".confml", ".configuration") |
|
126 # path = utils.resourceref.join_refs([self.get_current_path(), path]) |
|
127 try: |
|
128 if self.get_mode(mode) == self.MODE_READ: |
|
129 strio = self.extapi._get_stringio_from_path(path) |
|
130 elif self.get_mode(mode) == self.MODE_APPEND: |
|
131 strio = self.extapi._get_stringio_from_path(path) |
|
132 strio.seek(0, os.SEEK_END) |
|
133 elif self.get_mode(mode) == self.MODE_WRITE: |
|
134 strio = StringIO.StringIO() |
|
135 else: |
|
136 raise StorageException("Unrecognized mode %s" % mode) |
|
137 res = WebResource(self,path,mode,strio) |
|
138 self.__opened__(res) |
|
139 return res |
|
140 except KeyError: |
|
141 raise exceptions.NotResource("The given resource is not found %s" % path) |
|
142 |
|
143 def is_resource(self,path): |
|
144 return self.resource_cache.is_resource(path) |
|
145 # path = path.replace(".confml", ".configuration") |
|
146 # path = utils.resourceref.join_refs([self.get_current_path(), path]) |
|
147 # try: |
|
148 # query = urllib.quote(self._get_action_url('is_resource', path)) |
|
149 # self.conn.request("GET", query) |
|
150 # resp = self.conn.getresponse() |
|
151 # reader = persistentjson.HasResourceReader() |
|
152 # return reader.loads(resp.read()) |
|
153 # except exceptions.NotFound: |
|
154 # return False |
|
155 |
|
156 def save_resource(self, res): |
|
157 """ |
|
158 Close resource is no-operation action with webstorage for now |
|
159 """ |
|
160 return |
|
161 |
|
162 def close_resource(self, path): |
|
163 """ |
|
164 Close resource is no-operation action with webstorage |
|
165 """ |
|
166 return |
|
167 |
|
168 def export_resources(self, paths, storage, empty_folders=False): |
|
169 for path in paths: |
|
170 if not self.is_resource(path): |
|
171 logging.getLogger('cone').warning("The given path is not a Resource in this storage %s! Ignoring from export!" % path) |
|
172 continue |
|
173 wres = storage.open_resource(path,'wb') |
|
174 res = self.open_resource(path,"rb") |
|
175 wres.write(res.read()) |
|
176 wres.close() |
|
177 res.close() |
|
178 |
|
179 def unload(self, path, object): |
|
180 """ |
|
181 Dump a given object to the storage (reference is fetched from the object) |
|
182 @param object: The object to dump to the storage, which is expected to be an instance |
|
183 of Base class. |
|
184 """ |
|
185 # Add the current path in front of the given path |
|
186 path = utils.resourceref.join_refs([self.get_current_path(), path]) |
|
187 print "unload %s" % path |
|
188 if not isinstance(object, api.Configuration): |
|
189 raise exceptions.StorageException("Cannot dump object type %s" % object.__class__) |
|
190 # Skip the unload storing to storage if the storage is opened in read mode |
|
191 if self.get_mode(self.mode) != api.Storage.MODE_READ: |
|
192 if self.resource_cache.get_resource_link(path): |
|
193 path = self.resource_cache.get_resource_link(path) |
|
194 else: |
|
195 """ otherwise create the new resource first before update""" |
|
196 if self._create_resource(path, object): |
|
197 path = self.resource_cache.get_resource_link(path) |
|
198 else: |
|
199 # Creation failed |
|
200 logging.getLogger('cone').error('Creation of %s resource failed' % path) |
|
201 return |
|
202 data = persistentjson.dumps(object) |
|
203 self.extapi.update_resource(path, data) |
|
204 else: |
|
205 raise exceptions.StorageException("Cannot dump object to readonly storage") |
|
206 return |
|
207 |
|
208 def load(self, path): |
|
209 """ |
|
210 Load resource from a path. |
|
211 """ |
|
212 # Check if the object is already cached or has a cached link to another resource to load |
|
213 path = utils.resourceref.remove_begin_slash(path) |
|
214 print "load %s" % path |
|
215 if self.resource_cache.get_resource_link(path): |
|
216 path = self.resource_cache.get_resource_link(path) |
|
217 elif self.resource_cache.get_mapped_resource(path): |
|
218 path = self.resource_cache.get_mapped_resource(path) |
|
219 elif not utils.resourceref.get_ext(path) == "confml": |
|
220 raise exceptions.StorageException("Cannot load reference type %s" % utils.resourceref.get_ext(path)) |
|
221 else: |
|
222 # Add the current path in front of the given path |
|
223 path = utils.resourceref.join_refs([self.get_current_path(), path]) |
|
224 if not self.is_resource(path): |
|
225 raise exceptions.NotResource("No such %s resource!" % path) |
|
226 |
|
227 res = self.open_resource(path,"r") |
|
228 # read the resource with persistentmodule |
|
229 try: |
|
230 obj = self.persistentmodule.loads(res.read()) |
|
231 #obj.set_path(path) |
|
232 res.close() |
|
233 return obj |
|
234 except exceptions.ParseError,e: |
|
235 logging.getLogger('cone').error("Resource %s parsing failed with exception: %s" % (path,e)) |
|
236 # returning an empty config in case of xml parsing failure. |
|
237 return api.Configuration(path) |
|
238 |
|
239 def close(self): |
|
240 """ No operation in web storage close """ |
|
241 pass |
|
242 |
|
243 |
|
244 class WebResource(api.Resource): |
|
245 def __init__(self,storage,path,mode,handle): |
|
246 api.Resource.__init__(self,storage,path,mode) |
|
247 self.handle = handle |
|
248 |
|
249 def read(self,bytes=0): |
|
250 if bytes == 0: |
|
251 return self.handle.read() |
|
252 else: |
|
253 return self.handle.read(bytes) |
|
254 |
|
255 def write(self,string): |
|
256 if self.get_mode() == api.Storage.MODE_READ: |
|
257 raise exceptions.StorageException("Writing attempted to %s in read-only mode." % self.path) |
|
258 else: |
|
259 self.handle.write(string) |
|
260 |
|
261 def truncate(self,size=0): |
|
262 raise exceptions.NotSupportedException() |
|
263 |
|
264 def flush(self): |
|
265 self.storage.flush_resource(self) |
|
266 |
|
267 def close(self): |
|
268 self.storage.close_resource(self) |
|
269 self.handle.close() |
|
270 |
|
271 def get_size(self): |
|
272 if self.get_mode() == api.Storage.MODE_WRITE: |
|
273 raise exceptions.StorageException("Reading resource size attempted to %s in write-only mode." % self.path) |
|
274 return len(self.handle.getvalue()) |
|
275 |
|
276 def getvalue(self): |
|
277 return self.handle.getvalue() |
|
278 |
|
279 |
|
280 class CarbonExtapi(object): |
|
281 ACTIONS = { 'open_resource' : 'get_resource', |
|
282 'list_resources' : 'list_resources', |
|
283 'is_resource' : 'has_resource', |
|
284 'put_resource' : 'put_resource', |
|
285 'update_resource' : 'update_resource' } |
|
286 |
|
287 """ |
|
288 A general container for Carbon extapi action |
|
289 """ |
|
290 def __init__(self, path, **kwargs): |
|
291 self.path = path |
|
292 self.server_path = '' |
|
293 self.service_path = '' |
|
294 if path.startswith('http://'): |
|
295 path = path.replace('http://','',1) |
|
296 pathelems = path.split('/',1) |
|
297 self.server_path = pathelems[0] |
|
298 if len(pathelems) > 1: |
|
299 self.service_path = pathelems[1] |
|
300 self._username = kwargs.get('username', None) |
|
301 self._password = kwargs.get('password', None) |
|
302 authhandler = authenticate.CarbonAuthHandler() |
|
303 authhandler.add_password(self.username, self.password) |
|
304 self.conn = urllib2.build_opener(urllib2.HTTPCookieProcessor, authhandler, urllib2.ProxyHandler({})) |
|
305 |
|
306 @property |
|
307 def username(self): |
|
308 if self._username == None: |
|
309 self._username = getpass.getuser() |
|
310 return self._username |
|
311 |
|
312 @property |
|
313 def password(self): |
|
314 if self._password == None: |
|
315 self._password = getpass.getpass() |
|
316 return self._password |
|
317 |
|
318 def checklogin(self): |
|
319 """ |
|
320 Checks that we are logged in by loading the main page. |
|
321 If we are not logged in it will redirect us to login page. |
|
322 """ |
|
323 loginurl = "http://%(host)s/" % dict(host=self.server_path) |
|
324 loginreq = urllib2.Request(loginurl) |
|
325 print 'Checking login by opening URL %s ...' % loginurl |
|
326 try: |
|
327 resp = self.conn.open(loginreq) |
|
328 except urllib2.URLError, e: |
|
329 print str(e) |
|
330 return False |
|
331 return True |
|
332 |
|
333 def _get_stringio_from_path(self,path): |
|
334 """ |
|
335 return a StringIO object containing the data under a given path. |
|
336 @return: StringIO buffer |
|
337 @raise exception.NotResource: if the resource under path is not found |
|
338 """ |
|
339 path = utils.resourceref.remove_begin_slash(path) |
|
340 action_url = self._get_action_url('open_resource', path) |
|
341 req = urllib2.Request(action_url) |
|
342 try: |
|
343 resp = self.conn.open(req) |
|
344 bytes = resp.read() |
|
345 strio = StringIO.StringIO(bytes) |
|
346 return strio |
|
347 except urllib2.HTTPError,e: |
|
348 raise exceptions.NotResource("The given path %s could not be retrived from this storage. Server returned status %s." % (path, e)) |
|
349 |
|
350 def _get_action_url(self, action, path, **kwargs): |
|
351 path = utils.resourceref.remove_begin_slash(path) |
|
352 return "%s/%s/%s" % (self.path,self.ACTIONS[action], urllib.quote(path)) |
|
353 |
|
354 def list_resources_for_type(self,path,type, recurse=False): |
|
355 """ |
|
356 find the resources under certain path/path |
|
357 @param path : reference to path where resources are searched |
|
358 @param type : resources for particular carbon specific type. |
|
359 @param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders. |
|
360 Default value is False. Set to True to enable recursion. |
|
361 """ |
|
362 try: |
|
363 path = utils.resourceref.join_refs([path,'.'+type]) |
|
364 path = utils.resourceref.remove_begin_slash(path) |
|
365 query = self._get_action_url('list_resources', path) |
|
366 req = urllib2.Request(query) |
|
367 resp = self.conn.open(req) |
|
368 if resp.code == httplib.OK: |
|
369 bytes = resp.read() |
|
370 reader = persistentjson.ResourceListReader() |
|
371 reslist = reader.loads(bytes) |
|
372 return reslist |
|
373 else: |
|
374 return [] |
|
375 except exceptions.NotFound: |
|
376 return [] |
|
377 |
|
378 def list_resources(self,path, recurse=False): |
|
379 """ |
|
380 find the resources under certain path/path |
|
381 @param path : reference to path where resources are searched |
|
382 @param recurse : defines whether to return resources directly under the path or does the listing recurse to subfolders. |
|
383 Default value is False. Set to True to enable recursion. |
|
384 """ |
|
385 try: |
|
386 path = utils.resourceref.remove_begin_slash(path) |
|
387 query = self._get_action_url('list_resources', path) |
|
388 req = urllib2.Request(query) |
|
389 resp = self.conn.open(req) |
|
390 if resp.code == httplib.OK: |
|
391 bytes = resp.read() |
|
392 reslist = simplejson.loads(bytes) |
|
393 return reslist.get('resources',[]) |
|
394 else: |
|
395 return [] |
|
396 except exceptions.NotFound: |
|
397 return [] |
|
398 |
|
399 |
|
400 def update_resource(self, path, data): |
|
401 """ |
|
402 Update a resource to carbon. The resource can be a CarbonConfiguration or FeatureList object. |
|
403 @param object: The object which is dumped to dict with persistentjson and then updated to server. |
|
404 """ |
|
405 try: |
|
406 path = utils.resourceref.remove_begin_slash(path) |
|
407 query = self._get_action_url('update_resource', path) |
|
408 jsondata = simplejson.dumps(data) |
|
409 encdata = urllib.urlencode({'data' : jsondata}) |
|
410 req = urllib2.Request(query, encdata) |
|
411 |
|
412 resp = self.conn.open(req) |
|
413 if resp.code == httplib.OK: |
|
414 bytes = resp.read() |
|
415 respdata = simplejson.loads(bytes) |
|
416 success = respdata.get('success') == True |
|
417 if success: |
|
418 logging.getLogger('cone').info('Carbon update succeeds to path %s.' % (respdata.get('path'))) |
|
419 else: |
|
420 logging.getLogger('cone').error('Carbon update %s failed %s' % (path,respdata.get('errors'))) |
|
421 return success |
|
422 else: |
|
423 logging.getLogger('cone').error('Carbon update %s failed %s: %s' % (path,resp.code, resp)) |
|
424 return False |
|
425 except urllib2.HTTPError,e: |
|
426 utils.log_exception(logging.getLogger('cone'), "HTTPError in %s, %s" % (query,e)) |
|
427 return False |
|
428 |
|
429 def create_feature(self,path, feature, parent=None): |
|
430 """ |
|
431 Create new Carbon feature based on Feature object. |
|
432 @param path: The path to the featurelist where the feature is created. |
|
433 @param feature: The feature object |
|
434 @param parent: A possible parent feature ref |
|
435 """ |
|
436 try: |
|
437 path = utils.resourceref.remove_begin_slash(path) |
|
438 query = self._get_action_url('put_resource', path) |
|
439 data = persistentjson.dumps(feature) |
|
440 if parent: |
|
441 data['parent'] = parent |
|
442 jsondata = simplejson.dumps(data) |
|
443 encdata = urllib.urlencode({'data' : jsondata}) |
|
444 req = urllib2.Request(query, encdata) |
|
445 |
|
446 resp = self.conn.open(req) |
|
447 if resp.code == httplib.OK: |
|
448 bytes = resp.read() |
|
449 respdata = simplejson.loads(bytes) |
|
450 success = respdata.get('success') == True |
|
451 if success: |
|
452 logging.getLogger('cone').info('New Carbon feature created to path %s.' % (respdata.get('path'))) |
|
453 else: |
|
454 logging.getLogger('cone').error('Feature %s creation failed %s' % (feature.fqr,respdata.get('errors'))) |
|
455 return success |
|
456 else: |
|
457 logging.getLogger('cone').error('Feature %s creation failed %s: %s' % (feature.fqr,resp.code, resp)) |
|
458 return False |
|
459 except urllib2.HTTPError,e: |
|
460 utils.log_exception(logging.getLogger('cone'), "HTTPError in %s, %s" % (query,e)) |
|
461 return False |
|
462 |
|
463 def create_featurelist(self, path, featurelist): |
|
464 """ |
|
465 Create new Carbon featurelist to carbon. |
|
466 @param featurelist: The FeatureList object which is created. |
|
467 @return: tuple (success, created_path) where success indicates the success of the operation |
|
468 and created_path is the newly created featurelist path on success. |
|
469 """ |
|
470 try: |
|
471 path = utils.resourceref.remove_begin_slash(path) |
|
472 query = self._get_action_url('put_resource', path) |
|
473 data = persistentjson.FeatureListCreateWriter().dumps(featurelist) |
|
474 jsondata = simplejson.dumps(data) |
|
475 encdata = urllib.urlencode({'data' : jsondata}) |
|
476 req = urllib2.Request(query, encdata) |
|
477 |
|
478 resp = self.conn.open(req) |
|
479 if resp.code == httplib.OK: |
|
480 bytes = resp.read() |
|
481 respdata = simplejson.loads(bytes) |
|
482 success = respdata.get('success') == True |
|
483 newpath = respdata.get('path') |
|
484 if success: |
|
485 logging.getLogger('cone').info('New Carbon featurelist created to path %s.' % (newpath)) |
|
486 else: |
|
487 logging.getLogger('cone').error('FeatureList %s creation failed %s' % (featurelist.path,respdata.get('errors'))) |
|
488 return (success, newpath) |
|
489 else: |
|
490 logging.getLogger('cone').error('FeatureList %s creation failed %s: %s' % (featurelist.path,resp.code, resp)) |
|
491 return (False,'') |
|
492 except urllib2.HTTPError,e: |
|
493 utils.log_exception(logging.getLogger('cone'), "HTTPError in %s, %s" % (query,e)) |
|
494 return (False,'') |
|
495 |
|
496 def create_configuration(self, path, configuration): |
|
497 """ |
|
498 Create new Carbon configuration to carbon. |
|
499 @param path: The path to the configuration |
|
500 @param configuration: The CarbonConfiguration object |
|
501 @return: tuple (success, created_path) where success indicates the success of the operation |
|
502 and created_path is the newly created configuration path on success. |
|
503 """ |
|
504 try: |
|
505 path = utils.resourceref.remove_begin_slash(path) |
|
506 query = self._get_action_url('put_resource', path) |
|
507 data = persistentjson.ConfigurationCreateWriter().dumps(configuration) |
|
508 jsondata = simplejson.dumps(data) |
|
509 encdata = urllib.urlencode({'data' : jsondata}) |
|
510 req = urllib2.Request(query, encdata) |
|
511 |
|
512 resp = self.conn.open(req) |
|
513 if resp.code == httplib.OK: |
|
514 bytes = resp.read() |
|
515 respdata = simplejson.loads(bytes) |
|
516 success = respdata.get('success') == True |
|
517 newpath = respdata.get('path') |
|
518 if success: |
|
519 logging.getLogger('cone').info('New Carbon configuration created to path %s.' % (newpath)) |
|
520 else: |
|
521 logging.getLogger('cone').error('CarbonConfiguration %s creation failed %s' % (configuration.path,respdata.get('errors'))) |
|
522 return (success, newpath) |
|
523 else: |
|
524 logging.getLogger('cone').error('CarbonConfiguration %s creation failed %s: %s' % (configuration.path,resp.code, resp)) |
|
525 return (False,'') |
|
526 except urllib2.HTTPError,e: |
|
527 utils.log_exception(logging.getLogger('cone'), "HTTPError in %s, %s" % (query,e)) |
|
528 return (False,'') |
|
529 |
|
530 class ResourceCache(object): |
|
531 """ |
|
532 Resource cache maintains a list of ConE resource names and their actual links to Carbon resources. |
|
533 """ |
|
534 def __init__(self): |
|
535 self._cache = {} |
|
536 |
|
537 def add_configuration(self, configuration): |
|
538 """ |
|
539 Add a list of Carbon configurations. |
|
540 """ |
|
541 |
|
542 # Create the configuration as a layer and configuration root |
|
543 self._cache[configuration.get_path()] = configuration.path |
|
544 rootconf_path = configuration.name+'.confml' |
|
545 rootconf = model.CarbonConfiguration(rootconf_path) |
|
546 rootconf.include_configuration(configuration.get_path()) |
|
547 self._cache[rootconf_path] = rootconf |
|
548 |
|
549 def add_featurelist(self, featurelist): |
|
550 """ |
|
551 Add a list of Carbon configurations. |
|
552 """ |
|
553 # Add the feature list under feature list folder |
|
554 self._cache["featurelists/"+featurelist.get_path()] = featurelist.get_carbon_path() |
|
555 pass |
|
556 |
|
557 def add_resource(self, resourcepath): |
|
558 """ |
|
559 Add a resource |
|
560 """ |
|
561 confmlpath = persistentjson.CarbonResourceMapper().map_carbon_resource(resourcepath) |
|
562 self._cache[confmlpath] = resourcepath |
|
563 |
|
564 def list_resources(self, path, recurse=False): |
|
565 """ |
|
566 List ConE resources under certain path |
|
567 """ |
|
568 resources = [] |
|
569 path = utils.resourceref.insert_begin_slash(path) |
|
570 for res in self._cache.keys(): |
|
571 (respath,resname) = posixpath.split(res) |
|
572 respath = utils.resourceref.insert_begin_slash(respath) |
|
573 if recurse: |
|
574 if posixpath.normpath(respath).startswith(posixpath.normpath(path)): |
|
575 resources.append(res) |
|
576 else: |
|
577 if posixpath.normpath(respath) == posixpath.normpath(path): |
|
578 resources.append(res) |
|
579 return resources |
|
580 |
|
581 def is_resource(self,path): |
|
582 return self._cache.has_key(path) |
|
583 |
|
584 def get_resource_link(self,path): |
|
585 """ |
|
586 Get a the actual Carbon resource link if it is found from cached storage. |
|
587 """ |
|
588 linkpath = self._cache.get(path, None) |
|
589 if isinstance(linkpath, str): |
|
590 return linkpath |
|
591 else: |
|
592 return None |
|
593 |
|
594 def get_mapped_resource(self, path): |
|
595 # Try to make a carbon like resource path for a confml resource |
|
596 if path.startswith('featurelists'): |
|
597 object_type = 'featurelist' |
|
598 elif path.endswith('/root.confml'): |
|
599 object_type = 'configurationlayer' |
|
600 else: |
|
601 object_type = 'configurationroot' |
|
602 carbonpath = persistentjson.CarbonResourceMapper().map_confml_resource(object_type, path) |
|
603 return carbonpath |
|
604 |
|
605 def add_resource_link(self,link, path): |
|
606 """ |
|
607 Add a actual Carbon resource link. The link is the key which returns path when asked from get_resource_link. |
|
608 @param link: is linking path to the actual carbon resource path |
|
609 @param path: is the actual carbon path |
|
610 """ |
|
611 self._cache[link] = path |
|
612 |
|
613 def get_resource_object(self,path): |
|
614 """ |
|
615 Get a the actual cached Carbon object if it is found. |
|
616 """ |
|
617 cachebj = self._cache.get(path, None) |
|
618 if isinstance(cachebj, model.CarbonConfiguration): |
|
619 return cachebj |
|
620 return None |
|
621 |