1910 lines
60 KiB
Python
1910 lines
60 KiB
Python
# -*- coding: iso-8859-15 -*-
|
|
|
|
|
|
# Glasnost
|
|
# By: Odile Bénassy <obenassy@entrouvert.com>
|
|
# Romain Chantereau <rchantereau@entrouvert.com>
|
|
# Nicolas Clapiès <nclapies@easter-eggs.org>
|
|
# Pierre-Antoine Dejace <padejace@entrouvert.be>
|
|
# Thierry Dulieu <tdulieu@easter-eggs.com>
|
|
# Florent Monnier <monnier@codelutin.com>
|
|
# Cédric Musso <cmusso@easter-eggs.org>
|
|
# Frédéric Péters <fpeters@entrouvert.be>
|
|
# Benjamin Poussin <poussin@codelutin.com>
|
|
# Emmanuel Raviart <eraviart@entrouvert.com>
|
|
# Sébastien Régnier <regnier@codelutin.com>
|
|
# Emmanuel Saracco <esaracco@easter-eggs.com>
|
|
#
|
|
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
|
|
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
|
|
# Emmanuel Saracco & Théridion
|
|
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
|
|
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
|
|
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
|
|
# Régnier, Emmanuel Saracco, Théridion & Vecam
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
__doc__ = """Glasnost Objects Proxy"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import copy
|
|
|
|
import glasnost.common.context as context
|
|
import glasnost.common.faults as faults
|
|
from glasnost.common.ObjectsCommon import ObjectsCommonMixin
|
|
import glasnost.common.system as system
|
|
import glasnost.common.tools_new as commonTools
|
|
|
|
from DispatcherProxy import MultiCall, callServer, getApplicationToken
|
|
import kinds # Do not remove!
|
|
import things
|
|
from tools import *
|
|
|
|
register = things.register
|
|
|
|
|
|
class ObjectProxyMixin(things.ThingMixin):
|
|
"""Abstract class designed to be inherited."""
|
|
|
|
def getProxy(self):
|
|
"""Return the object proxy class instance."""
|
|
|
|
return getProxyForServerRole(self.serverRole)
|
|
|
|
|
|
class AdminWithoutWritersMixin(ObjectProxyMixin):
|
|
def newDefaultObject(self):
|
|
proxy = self.getProxy()
|
|
return commonTools.newThing(
|
|
'object', '%s.%s' % (proxy.serverRole, proxy.objectClassName))
|
|
|
|
|
|
class AdminMixin(AdminWithoutWritersMixin):
|
|
pass
|
|
|
|
|
|
class Proxy(things.BaseThing):
|
|
|
|
"""Proxy base superclass.
|
|
|
|
This call is designed to be inherited with other specific class in order to
|
|
produce a fully fonctionnal Glasnost proxy class.
|
|
|
|
Attribute:
|
|
==========
|
|
|
|
*serverRole*:
|
|
The class server role string.
|
|
|
|
thingCategory*:
|
|
The thing category string (here 'proxy').
|
|
|
|
"""
|
|
|
|
serverRole = None
|
|
thingCategory = 'proxy'
|
|
|
|
def canGetAdmin(self, serverId = None):
|
|
"""Test if the proxy is able to get the admin instance.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Return:
|
|
=======
|
|
|
|
1 or true:
|
|
The proxy is able to get the server admin instance.
|
|
|
|
0 or false:
|
|
The proxy is not able to get the server admin instance (incredible,
|
|
isn't it ?).
|
|
|
|
Exceptions
|
|
==========
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'canGetAdmin',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
def canViewAll(self, serverId = None):
|
|
return 0
|
|
|
|
def getHandledRoles(self):
|
|
"""Return the proxy handled roles.
|
|
|
|
This method seems not to be used.
|
|
|
|
Return None.
|
|
|
|
"""
|
|
|
|
return None
|
|
|
|
def getServerId(self, serverId = None):
|
|
"""Get the dispatcher ID string.
|
|
|
|
This method returns the ID string to use for XML RPC.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*serverId*:
|
|
The server ID string.
|
|
|
|
Return the callable dispatcher ID.
|
|
|
|
Exception:
|
|
==========
|
|
|
|
*AssertionError*:
|
|
The given server ID doesn't begin by 'glasnost://'.
|
|
|
|
*Standard Exception*:
|
|
The server ID folowing the protocol specifier is not valid.
|
|
|
|
*Exception*('Missing context'):
|
|
The context does not contain information about the dispatcher Id.
|
|
|
|
|
|
**TODO**:
|
|
=========
|
|
|
|
*FIXME*:
|
|
ServerId is a misnamer. It should be replaced by dispatcherId.
|
|
|
|
"""
|
|
|
|
if serverId is not None:
|
|
return commonTools.makeApplicationId(serverId, self.serverRole)
|
|
dispatcherId = context.getVar('dispatcherId')
|
|
if dispatcherId is None:
|
|
dispatcherId = context.getVar('defaultDispatcherId')
|
|
if dispatcherId is None:
|
|
raise Exception('Missing dispatcherId in context')
|
|
return commonTools.makeApplicationId(dispatcherId, self.serverRole)
|
|
|
|
|
|
class AdministrableProxyMixin:
|
|
|
|
"""Abstract class designed to be inherited with a specialized class.
|
|
|
|
The product of a multiple inheritance is a fonctionnal administrable proxy.
|
|
All attributes can or must be overriden or extended, in fact, this class
|
|
define their default values.
|
|
|
|
"""
|
|
|
|
def canModifyAdmin(self, serverId = None):
|
|
"""Tests if the user can modify the proxy admin instance.
|
|
|
|
Only an admin can modify the proxy admin class.
|
|
|
|
Keyword Arguments:
|
|
==================
|
|
|
|
*serverId*:
|
|
The server Id string.
|
|
|
|
Return values:
|
|
==============
|
|
|
|
*0*:
|
|
If the admin set doesn't contain the user.
|
|
|
|
*1*:
|
|
If the admin set contains the user.
|
|
There is no admin set defined.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*KeyError*:
|
|
The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
Warning:
|
|
========
|
|
|
|
An user token must be present in the context.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'canModifyAdmin',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
def getAdmin(self, serverId = None):
|
|
"""Get the server Admin class instance.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*serverId*:
|
|
The server ID string to send the XML RPC.
|
|
|
|
Return the Admin class instance.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*Exception*:
|
|
|
|
+ Unknown category.
|
|
|
|
+ Unknown class name.
|
|
|
|
*All exception of the wanted admin class constructor.*
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
"""
|
|
|
|
cache = context.getVar('cache')
|
|
cacheKey = 'admin_%s' % self.serverRole
|
|
if cache is not None and cache.has_key(cacheKey):
|
|
adminImport = copy.deepcopy(cache[cacheKey])
|
|
return commonTools.importThing(adminImport)
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
adminImport = callServer(
|
|
serverId,
|
|
'getAdmin',
|
|
[serverId, getApplicationToken(), userToken])
|
|
if cache is not None:
|
|
cache[cacheKey] = copy.deepcopy(adminImport)
|
|
return commonTools.importThing(adminImport)
|
|
|
|
def getAdminSlotValueHolder(self, slotPath, serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
valueHolderImport = callServer(
|
|
serverId,
|
|
'getAdminSlotValueHolder',
|
|
[serverId, getApplicationToken(), userToken, slotPath])
|
|
return commonTools.importThing(valueHolderImport)
|
|
|
|
def getAdminStringFromDigest(self, path, digest, serverId = None):
|
|
serverId = self.getServerId(serverId = serverId)
|
|
userToken = context.getVar('userToken', default = '')
|
|
return iso8859_15(callServer(
|
|
serverId,
|
|
'getAdminStringFromDigest',
|
|
[serverId, getApplicationToken(),
|
|
userToken, utf8(path), digest]))
|
|
|
|
def hasAdminSlot(self, slotPath, serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'hasAdminSlot',
|
|
[serverId, getApplicationToken(), userToken, slotPath])
|
|
|
|
def isAdmin(self, serverId = None):
|
|
"""Indicate whether the caller is an administrator of this server."""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'isAdmin',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
def modifyAdmin(self, admin, serverId = None):
|
|
"""Modify the admin virtual server object.
|
|
|
|
Keyword argument:
|
|
==================
|
|
|
|
*serverId*:
|
|
The server ID string to send the XML RPC.
|
|
|
|
|
|
Returns:
|
|
========
|
|
|
|
The admin object new version.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.\**:
|
|
An XML-RPC fault.
|
|
|
|
*UnknownException*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
adminExport = admin.exportToXmlRpc()
|
|
admin.version = callServer(
|
|
serverId,
|
|
'modifyAdmin',
|
|
[serverId, getApplicationToken(), userToken, adminExport])
|
|
return None
|
|
|
|
def newAdmin(self, keywords = None):
|
|
"""Instanciate a new Admin class.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*keywords*:
|
|
May be used in subclasses to create different objects on the basis
|
|
of some keyword.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*Exception*:
|
|
|
|
+ Unknown category.
|
|
|
|
+ Unknown class name.
|
|
|
|
*All exception of the wanted admin class constructor.*
|
|
|
|
"""
|
|
|
|
return commonTools.newThing(
|
|
'object', '%s.%s' % (self.serverRole, self.adminClassName))
|
|
|
|
def setAdminSlotValueHolder(self, slotPath, valueHolder, serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
valueHolderExport = valueHolder.exportToXmlRpc()
|
|
callServer(
|
|
serverId,
|
|
'setAdminSlotValueHolder',
|
|
[serverId, getApplicationToken(), userToken, slotPath,
|
|
valueHolderExport])
|
|
|
|
|
|
class ObjectsProxy(ObjectsCommonMixin, AdministrableProxyMixin, Proxy):
|
|
|
|
"""Proxy of the Objects server.
|
|
|
|
This class is used to communicate with the Object server.
|
|
|
|
"""
|
|
|
|
def addObject(self, object, serverId = None):
|
|
"""Add an object to the server.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectImport*:
|
|
The object instance to add.
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Returns:
|
|
========
|
|
|
|
The new object ID.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*UnknowException*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
objectExport = object.exportToXmlRpc()
|
|
objectId = callServer(
|
|
serverId,
|
|
'addObject',
|
|
[serverId, getApplicationToken(), userToken, objectExport])
|
|
return objectId
|
|
|
|
def canAddObject(self, serverId = None):
|
|
"""Test if adding an object is allowed.
|
|
|
|
To add an object to the server, the user must be an admin, or in the
|
|
writers' set.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The user can add an object to the server.
|
|
|
|
*0 or false*:
|
|
The user cannot add an object to the server.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*UnknowException*:
|
|
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'canAddObject',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
def canCloneObject(self, objectId):
|
|
"""Test if the user can duplicate an existing object.
|
|
|
|
To be able to clone an object, the user must have a valid userToken,
|
|
must be able to retrieve the object and be able to add an object to the
|
|
server.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*objectId*:
|
|
The object ID string to clone.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The user can duplicate the object.
|
|
|
|
*0 or false*:
|
|
The user cannot duplicate the object.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*UnknowException*:
|
|
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
*AssertionError*:
|
|
The object ID string is not a glasnost service ('glasnost://').
|
|
|
|
*IndexError*:
|
|
The given object ID is incomplete.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = commonTools.extractServerId(objectId)
|
|
return userToken and self.canGetObject(objectId) \
|
|
and self.canAddObject(serverId = serverId)
|
|
|
|
def canDeleteObject(self, objectId):
|
|
"""Test if deleting a specified object is allowed.
|
|
|
|
To delete an object on the server, the user must be an admin, or in the
|
|
writers' set and the object must exist.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The object ID string to delete.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The user can delete the object.
|
|
|
|
*0 or false*:
|
|
The user cannot delete the object.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*UnknowException*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
*AssertionError*:
|
|
The object ID string is not a glasnost service ('glasnost://').
|
|
|
|
*IndexError*:
|
|
The given object ID is incomplete.
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'canDeleteObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def canGetObject(self, objectId):
|
|
"""Test if the user can retrieve a specified object.
|
|
|
|
To get an object on the server, the user must be an admin, or in the
|
|
object or admin server class instance readers' set or the client
|
|
application can get it, and the object must exist.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The object ID string to retrieve.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The user can get the object.
|
|
|
|
*0 or false*:
|
|
The user cannot get the object.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*AssertionError*:
|
|
The server ID cannot be defined. (is None)
|
|
|
|
*AttributeError*:
|
|
The call procedure doesn't exist.
|
|
|
|
*ProtocolError*:
|
|
A protocol error in the underlying transport layer (such as a 404
|
|
'not found' error if the server named by the URI does not exist).
|
|
|
|
*Fault.\**:
|
|
A Fault object encapsulates the content of an XML-RPC fault tag.
|
|
|
|
*Exception*:
|
|
All kind of exceptions raised by the called Remote Procedure.
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
*AssertionError*:
|
|
The object ID string is not a glasnost service ('glasnost://').
|
|
|
|
*IndexError*:
|
|
The given object ID is incomplete.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'canGetObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def canGetObjects(self, serverId = None):
|
|
"""Test if the user can retrieve the server objects.
|
|
|
|
To be able to see the objects stored in the server the use must be an
|
|
admin, or the admin server class instance doesn't use readers set, or
|
|
the user is in the admin class instance readers set.
|
|
|
|
If an user cannot get the server objects, he could be able to retrieve
|
|
a specified object.
|
|
|
|
The admin readers set is used to limit the allowed users to list the
|
|
objects on the server.
|
|
|
|
Keyword argument:
|
|
==================
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The user can get the objects.
|
|
|
|
*0 or false*:
|
|
The user cannot get the objects.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*UnknowException*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*faults.UnknownApplicationToken*:
|
|
The given application token is not in the dispatcher virtual server
|
|
ids dictionnary.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'canGetObjects',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
def canModifyObject(self, objectId):
|
|
"""Test if the user can modify a specified object.
|
|
|
|
The user must be admin, or in the object writers set in order to be
|
|
able to modify the object.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The object ID string designing the object to modify.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The user can modify the object.
|
|
|
|
*0 or false*:
|
|
The user cannot modify the object.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*UnknowException*:
|
|
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
*AssertionError*:
|
|
The object ID string is not a glasnost service ('glasnost://').
|
|
|
|
*IndexError*:
|
|
The given object ID is incomplete.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
cache = context.getVar('temporaryCache')
|
|
cacheKey = 'canModifyObject-%s-%s' % (objectId, userToken)
|
|
if cache is not None:
|
|
try:
|
|
return cache[cacheKey]
|
|
except KeyError:
|
|
pass
|
|
result = callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'canModifyObject',
|
|
[commonTools.extractServerId(objectId),
|
|
getApplicationToken(), userToken, objectId])
|
|
if cache is not None:
|
|
cache[cacheKey] = result
|
|
return result
|
|
|
|
|
|
def canUseObject(self, objectId):
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'canUseObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def deleteObject(self, objectId):
|
|
"""Test if the user can delete a specified object.
|
|
|
|
The user must be admin, or in the object writers set in order to be
|
|
able to modify the object.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The object ID string designing the object to modify.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*UnknowException*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
*AssertionError*:
|
|
The object ID string is not a glasnost service ('glasnost://').
|
|
|
|
*IndexError*:
|
|
The given object ID is incomplete.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'deleteObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def getIdsAllowedToDeleteObject(self, objectId):
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getIdsAllowedToDeleteObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def getIdsAllowedToModifyObject(self, objectId):
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getIdsAllowedToModifyObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def getLastObjectIds(self, objectsCount, possibleReadersSet,
|
|
possibleWritersSet, serverId = None):
|
|
"""Retrieve the last accessed objects ids.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectCount*:
|
|
The maximum number of object ids to retrieve.
|
|
|
|
*possibleReaderSet*:
|
|
Useless.
|
|
|
|
*possibleWriterSet*:
|
|
Useless.
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Returns:
|
|
========
|
|
|
|
*Object ID sequence*:
|
|
The sequence of the last accessed object ids.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*standard Exception*:
|
|
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
if not possibleReadersSet:
|
|
possibleReadersSet = [system.generalPublicId]
|
|
if not possibleWritersSet:
|
|
possibleWritersSet = [system.generalPublicId]
|
|
return callServer(
|
|
serverId,
|
|
'getLastObjectIds',
|
|
[serverId, getApplicationToken(), userToken, objectsCount,
|
|
possibleReadersSet, possibleWritersSet])
|
|
|
|
def getLastObjects(
|
|
self, objectsCount, possibleReadersSet, possibleWritersSet,
|
|
requiredSlotNames = None, serverId = None):
|
|
"""Retrieve the last accessed objects.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectCount*:
|
|
The maximum number of object ids to retrieve.
|
|
|
|
*possibleReaderSet*:
|
|
Useless.
|
|
|
|
*possibleWriterSet*:
|
|
Useless.
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Returns:
|
|
========
|
|
|
|
*Objects sequence*:
|
|
The sequence of the last accessed objects.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*standard Exception*:
|
|
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
objectIds = self.getLastObjectIds(
|
|
objectsCount, possibleReadersSet, possibleWritersSet,
|
|
serverId = serverId)
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
self.getPartialObject(objectId, requiredSlotNames,
|
|
multiCall = multiCall)
|
|
return [lazyObject() for lazyObject in multiCall.call()]
|
|
|
|
def getObject(self, objectId, multiCall = None):
|
|
"""Retrieve a specified object instance.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The ID of the object instance to retrieve.
|
|
|
|
*multiCall*:
|
|
If (1 or true), this call is stacked in order to perform a
|
|
multicall.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*Object instance*:
|
|
The wanted object instance.
|
|
|
|
*None*:
|
|
The call is designed for multi call, so the object instance will be
|
|
retrieved by the multi call returns sequence.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.MissingItem*:
|
|
The object ID string does not correspond to a existing object
|
|
instance.
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not allowed to read the object isntance.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*faults.UnknownApplicationToken*:
|
|
The given application token is not in the dispatcher virtual server
|
|
ids dictionnary.
|
|
|
|
*AssertionError*:
|
|
The object ID string is not a glasnost service ('glasnost://').
|
|
|
|
*IndexError*:
|
|
The given object ID is incomplete.
|
|
|
|
"""
|
|
|
|
cache = context.getVar('cache')
|
|
if cache is not None and cache.has_key(objectId):
|
|
result = copy.deepcopy(cache[objectId])
|
|
if multiCall:
|
|
multiCall.addEarlyResult(result)
|
|
return None
|
|
return result
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId],
|
|
resultHandler = self.getObject_handleResult,
|
|
multiCall = multiCall)
|
|
|
|
def getObject_handleResult(self, lazyObject):
|
|
"""Return an object instance from a XML RPC object dictionnary.
|
|
|
|
Keyword argument:
|
|
================
|
|
|
|
*lazyObject*:
|
|
The result representation instance.
|
|
|
|
Return the object instance defined in the lazyObject.
|
|
|
|
"""
|
|
|
|
objectImport = lazyObject()
|
|
object = commonTools.importThing(objectImport)
|
|
cache = context.getVar('cache')
|
|
if cache is not None and object.canCache():
|
|
cache[object.id] = copy.deepcopy(object)
|
|
return object
|
|
|
|
def getObjectIds(self, serverId = None):
|
|
"""Retrieve the ids of all server objects.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*Object ID sequence*:
|
|
The sequence of the server objects ids.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*KeyError*:
|
|
The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
|
|
cache = context.getVar('temporaryCache')
|
|
cacheKey = 'getObjectIds_%s' % serverId
|
|
if cache is not None and cache.has_key(cacheKey):
|
|
return cache[cacheKey]
|
|
|
|
result = callServer(
|
|
serverId,
|
|
'getObjectIds',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
if cache is not None:
|
|
cache[cacheKey] = result
|
|
return result
|
|
|
|
|
|
def getObjectIdsWithCriteria(self, criteria, sort = '', serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'getObjectIdsWithCriteria',
|
|
[serverId, getApplicationToken(), userToken, criteria, sort])
|
|
|
|
def getObjectLabelAndLanguage(self, objectId, multiCall = None):
|
|
"""Retrieve the object label and language in sequence.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*objectId*:
|
|
The ID of the object.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*KeyError*:
|
|
The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
if not objectId:
|
|
if multiCall is None:
|
|
return '', None
|
|
else:
|
|
return multiCall.addEarlyResult(('', None))
|
|
|
|
cache = context.getVar('cache')
|
|
if cache is not None and cache.has_key(objectId):
|
|
object = cache[objectId]
|
|
result = (object.getLabel(), object.getLabelLanguage())
|
|
if multiCall is None:
|
|
return result
|
|
else:
|
|
return multiCall.addEarlyResult(result)
|
|
|
|
def handleResult(lazyLabelAndLanguage):
|
|
label, language = lazyLabelAndLanguage()
|
|
if not language:
|
|
language = None
|
|
return iso8859_15(label), language
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getObjectLabelAndLanguage',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId],
|
|
resultHandler = handleResult,
|
|
multiCall = multiCall)
|
|
|
|
def getObjectLabelsTranslated(
|
|
self, objectIds, destinationLanguages, serverId = None):
|
|
"""Get the objects labels in the specified languages.
|
|
|
|
Keyword Arguments:
|
|
==================
|
|
|
|
*objectIds*:
|
|
The sequence of IDs of the objects of the wanted labels.
|
|
|
|
*destinationLanguages*:
|
|
The sequence of the wanted language strings.
|
|
|
|
Return the labels dictionnary (the key is the object ID).
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*KeyError*:
|
|
The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
cache = context.getVar('temporaryCache')
|
|
if cache is not None:
|
|
cacheKey = 'getObjectLabelsTranslated-%r-%r' % (
|
|
objectIds, destinationLanguages)
|
|
try:
|
|
return cache[cacheKey]
|
|
except KeyError:
|
|
pass
|
|
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
try:
|
|
self.getObjectLabelAndLanguage(objectId, multiCall = multiCall)
|
|
except faults.UnknownDispatcherInId:
|
|
objectIds.remove(objectId)
|
|
lazyLabelsAndLanguages = multiCall.call()
|
|
labelsAndLanguages = {}
|
|
for i in range(len(objectIds)):
|
|
try:
|
|
labelsAndLanguages[objectIds[i]] = lazyLabelsAndLanguages[i]()
|
|
except faults.MissingItem:
|
|
pass
|
|
translationsProxy = getProxyForServerRole('translations')
|
|
labels = {}
|
|
if translationsProxy:
|
|
multiCall = MultiCall()
|
|
for objectId, labelAndLanguage in labelsAndLanguages.items():
|
|
label, language = labelAndLanguage
|
|
try:
|
|
translationsProxy.getTranslation(
|
|
label, objectId, 'self.getLabel()', language,
|
|
destinationLanguages, multiCall = multiCall)
|
|
except faults.UnknownDispatcherInId:
|
|
labels[objectId] = objectId
|
|
del labelsAndLanguages[objectId]
|
|
lazyTranslations = multiCall.call()
|
|
objectIds = labelsAndLanguages.keys()
|
|
for i in range(len(objectIds)):
|
|
labels[objectIds[i]] = lazyTranslations[i]()
|
|
else:
|
|
for objectId, labelAndLanguage in labelsAndLanguages.items():
|
|
labels[objectId] = labelAndLanguage[0]
|
|
defaultDispatcherId = context.getVar('defaultDispatcherId')
|
|
dispatcherId = context.getVar('dispatcherId')
|
|
if not commonTools.extractDispatcherId(objectId) in [
|
|
defaultDispatcherId, dispatcherId, 'glasnost://help',
|
|
'glasnost://system']:
|
|
for id, label in labels.items():
|
|
label += _(' (at <%s>)') \
|
|
% extractApplicationHostNameAndPort(objectId)
|
|
labels[id] = label
|
|
|
|
if cache is not None:
|
|
cache[cacheKey] = labels
|
|
return labels
|
|
|
|
def getObjectLabelTranslated(self, objectId, destinationLanguages):
|
|
"""Get the object label in the specified languages.
|
|
|
|
Keyword Arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The sequence of IDs of the objects of the wanted labels.
|
|
|
|
*destinationLanguages*:
|
|
The sequence of the wanted language strings.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*The translated label*
|
|
|
|
*An empty tring*:
|
|
The object Id is None.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*KeyError*:
|
|
The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
if not objectId:
|
|
return ''
|
|
label, language = self.getObjectLabelAndLanguage(objectId)
|
|
if destinationLanguages[0] == context.getVar('readLanguages')[0] and \
|
|
language == 'en' and hasattr(_, 'im_self') and \
|
|
hasattr(_.im_self, '_catalog') and \
|
|
_.im_self._catalog.has_key(label):
|
|
return _(label)
|
|
translationsProxy = getProxyForServerRole('translations')
|
|
if translationsProxy:
|
|
labelTranslated = translationsProxy.getTranslation(
|
|
label, objectId, 'self.getLabel()', language,
|
|
destinationLanguages )
|
|
else:
|
|
labelTranslated = label
|
|
defaultDispatcherId = context.getVar('defaultDispatcherId')
|
|
dispatcherId = context.getVar('dispatcherId')
|
|
if not commonTools.extractDispatcherId(objectId) in [
|
|
defaultDispatcherId, dispatcherId, 'glasnost://help',
|
|
'glasnost://system']:
|
|
labelTranslated += _(' (at <%s>)') \
|
|
% extractApplicationHostNameAndPort(objectId)
|
|
return labelTranslated
|
|
|
|
def getObjects(self, requiredSlotNames = None, serverId = None):
|
|
"""Get the server objects instances.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*requiredSlotNames*:
|
|
The wanted slots names sequence.
|
|
|
|
*serverId*:
|
|
The server ID string (default = None).
|
|
|
|
Return the objects dictionnary (key is the object ID).
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user is not in the admin set.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*standard Exception*:
|
|
- The thing category 'object' doesn't exists. (very grave !)
|
|
- The adminImport __thingName__ key is not a valid Thing name.
|
|
|
|
*KeyError*:
|
|
The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
objectIds = self.getObjectIds(serverId = serverId)
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
self.getPartialObject(
|
|
objectId, requiredSlotNames, multiCall = multiCall)
|
|
lazyObjects = multiCall.call()
|
|
objects = {}
|
|
for i in range(len(objectIds)):
|
|
objects[objectIds[i]] = lazyObjects[i]()
|
|
return objects
|
|
|
|
def getObjectsCount(self, serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'getObjectsCount',
|
|
[serverId, getApplicationToken(), userToken])
|
|
|
|
def getObjectsFromIds(self, objectIds,
|
|
requiredSlotNames = None, serverId = None):
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
if requiredSlotNames:
|
|
self.getPartialObject(objectId,
|
|
requiredSlotNames, multiCall = multiCall)
|
|
else:
|
|
self.getObject(objectId, multiCall = multiCall)
|
|
lazyObjects = multiCall.call()
|
|
objects = {}
|
|
for i in range(len(objectIds)):
|
|
objects[objectIds[i]] = lazyObjects[i]()
|
|
return objects
|
|
|
|
def getObjectsWithCriteria(self, criteria, sort = '',
|
|
requiredSlotNames = None, serverId = None):
|
|
objectIds = self.getObjectIdsWithCriteria(
|
|
criteria, sort, serverId = serverId)
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
self.getPartialObject(
|
|
objectId, requiredSlotNames, multiCall = multiCall)
|
|
lazyObjects = multiCall.call()
|
|
objects = {}
|
|
for i in range(len(objectIds)):
|
|
objects[objectIds[i]] = lazyObjects[i]()
|
|
return objects
|
|
|
|
|
|
def getObjectSlotValueHolder(self, objectId, slotPath):
|
|
userToken = context.getVar('userToken', default = '')
|
|
valueHolderImport = callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getObjectSlotValueHolder',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId, slotPath])
|
|
return commonTools.importThing(valueHolderImport)
|
|
|
|
def getObjectStringFromDigest(self, objectId, path, digest):
|
|
userToken = context.getVar('userToken', default = '')
|
|
return iso8859_15(callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getObjectStringFromDigest',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId, utf8(path), digest]))
|
|
|
|
def getObjectWithVersion(self, objectId, versionNumber):
|
|
userToken = context.getVar('userToken', default = '')
|
|
objectImport = callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getObjectWithVersion',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId, versionNumber])
|
|
return commonTools.importThing(objectImport)
|
|
|
|
def getPartialObject(self, objectId, requiredSlotNames, multiCall = None):
|
|
"""Retrieve partial object instance from the server.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectId*:
|
|
The ID of the wanted object partial informations.
|
|
|
|
*requiredSlotNames*:
|
|
The wanted slot names sequence.
|
|
|
|
*multiCall*:
|
|
If true (or 1), the call is stacked in order to perform a multi
|
|
calls.
|
|
|
|
|
|
Return the wanted partial object instance.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*UnknowError*:
|
|
- A required slot name is a private slot name.
|
|
|
|
- A element of the required slots names sequence is not a string.
|
|
|
|
"""
|
|
|
|
if not requiredSlotNames:
|
|
return self.getObject(objectId, multiCall = multiCall)
|
|
cacheKey = requiredSlotNames[:]
|
|
cacheKey.sort()
|
|
cacheKey = '%s_%s' % (objectId, str(cacheKey))
|
|
def handleResult(lazyObject, self = self, cacheKey = cacheKey):
|
|
objectImport = lazyObject()
|
|
object = commonTools.importThing(objectImport)
|
|
cache = context.getVar('cache')
|
|
if cache is not None and object.canCache():
|
|
cache[cacheKey] = copy.deepcopy(object)
|
|
return object
|
|
cache = context.getVar('cache')
|
|
if cache is not None and cache.has_key(objectId):
|
|
result = copy.deepcopy(cache[objectId])
|
|
if multiCall:
|
|
multiCall.addEarlyResult(result)
|
|
return None
|
|
else:
|
|
return result
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getPartialObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId, requiredSlotNames],
|
|
resultHandler = handleResult,
|
|
multiCall = multiCall)
|
|
|
|
def getRevisionsInfos(self, objectId):
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'getRevisionsInfos',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def hasObject(self, objectId):
|
|
"""Test if the server contains an object.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*objectId*:
|
|
The object Id to look up.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*1 or true*:
|
|
The server owns the object with the ID *objectId*.
|
|
|
|
*0 of false*:
|
|
The server does not own the object with the ID *objectId*.
|
|
|
|
Exception:
|
|
==========
|
|
|
|
*UnknowException*:
|
|
The virtual server ID does not correspond to a instanciated virtual
|
|
server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'hasObject',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId])
|
|
|
|
def hasObjectSlot(self, objectId, slotPath):
|
|
userToken = context.getVar('userToken', default = '')
|
|
return callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'hasObjectSlot',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId, slotPath])
|
|
|
|
def isObjectId(self, id):
|
|
"""Test if the given string is a valid object ID.
|
|
|
|
A valid object ID begin with the server ID string, followed by sub id
|
|
(separated by slashes).
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*id*:
|
|
The id string to test.
|
|
|
|
Return 1 or true if the given string is a valid object ID.
|
|
"""
|
|
return id.startswith(self.getServerId() + '/')
|
|
|
|
def modifyObject(self, object):
|
|
"""Modify an object on the server.
|
|
|
|
The client object is also modified to be in sync with the server object
|
|
(same object version).
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*object*:
|
|
The modified object instance.
|
|
|
|
Returns:
|
|
========
|
|
|
|
**None**
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.MissingItem*:
|
|
The specified object does not exist.
|
|
|
|
*faults.UserAccessDenied*:
|
|
The client is not allowed to modify the object.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
objectExport = object.exportToXmlRpc()
|
|
object.version = callServer(
|
|
commonTools.extractServerId(object.id),
|
|
'modifyObject',
|
|
[commonTools.extractServerId(object.id), getApplicationToken(),
|
|
userToken, objectExport])
|
|
return None
|
|
|
|
def modifyPartialObject(self, object, givenSlotNames):
|
|
"""Partialy modify a object.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*object*:
|
|
The modified object.
|
|
|
|
*givenSlotNames*:
|
|
The sequence of the slot names to modify. If empty, the object is
|
|
completly modified.
|
|
|
|
Returns:
|
|
========
|
|
|
|
**None**
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.MissingId*:
|
|
The modified object instance has no id attribute.
|
|
|
|
*faults.MissingItem*:
|
|
The specified object does not exist.
|
|
|
|
*faults.UserAccessDenied*:
|
|
The client is not allowed to modify the object.
|
|
|
|
*faults.ReadOnlyObject*:
|
|
The object cannot be modified.
|
|
|
|
"""
|
|
|
|
if not givenSlotNames:
|
|
return self.modifyObject(object)
|
|
givenSlotNames = givenSlotNames[:]
|
|
for slotName in ['id', 'version']:
|
|
if not slotName in givenSlotNames and object.hasSlotName(slotName):
|
|
slot = object.getSlot(slotName)
|
|
if slot.getKind().isImportable():
|
|
assert hasattr(object, slotName) \
|
|
and getattr(object, slotName) is not None
|
|
givenSlotNames.append(slotName)
|
|
userToken = context.getVar('userToken', default = '')
|
|
objectExport = object.exportToXmlRpc(
|
|
requiredSlotNames = givenSlotNames)
|
|
object.version = callServer(
|
|
commonTools.extractServerId(object.id),
|
|
'modifyPartialObject',
|
|
[commonTools.extractServerId(object.id), getApplicationToken(),
|
|
userToken, objectExport, givenSlotNames])
|
|
return None
|
|
|
|
def newObject(self, keywords = None):
|
|
"""Instanciate a new object.
|
|
|
|
The class of the new object instance is stored in the *objectClassName*
|
|
attribute.
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*keywords*:
|
|
May be used in subclasses to create different objects on the basis
|
|
of some keyword.
|
|
|
|
Return the new object instance.
|
|
|
|
"""
|
|
|
|
return commonTools.newThing(
|
|
'object', '%s.%s' % (self.serverRole, self.objectClassName))
|
|
|
|
def searchObjects(self, serverId = None, objectIds = [],
|
|
sortRule = '', **searchKeywords):
|
|
objectIds = self.searchObjectIds(serverId, objectIds = objectIds,
|
|
sortRule = sortRule, **searchKeywords)
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
self.getObject(objectId, multiCall = multiCall)
|
|
lazyObjects = multiCall.call()
|
|
objects = {}
|
|
for i in range(len(objectIds)):
|
|
objects[objectIds[i]] = lazyObjects[i]()
|
|
return objects
|
|
|
|
def searchObjectIds(self, serverId = None, multiCall = None,
|
|
objectIds = [], sortRule = '', **searchKeywords):
|
|
"""Find object Ids.
|
|
|
|
Search keywords syntax:
|
|
=======================
|
|
|
|
+ 'attribute_name_EQ = value' means attribute=value
|
|
|
|
+ 'attribute_name_LT = value' means attribute < value
|
|
|
|
+ 'attribute_name_GT = value' means attribute > value
|
|
|
|
+ 'attribute_name_LE = value' means attribute <= value
|
|
|
|
+ 'attribute_name_GE = value' means attribute >= value
|
|
|
|
+ 'attribute_name_IN = value' means value contains attribute
|
|
|
|
+ 'attribute_name_CT = value' means value in attribute
|
|
|
|
+ 'searchTerms = value' is for plain text blank-separated search terms
|
|
|
|
Keyword argument:
|
|
=================
|
|
|
|
*searchDict*:
|
|
The search string following the search keywords syntax.
|
|
|
|
Returns:
|
|
========
|
|
|
|
*Object ID sequence*:
|
|
The sequence of the corresponding objects ids.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user cannont get the objects list.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*UnknowException*:
|
|
- Invalid syntax in the *searchDict* string.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
searchDict = {}
|
|
for sk in searchKeywords.keys():
|
|
searchDict[sk] = searchKeywords[sk]
|
|
if not objectIds and not searchDict:
|
|
return self.getObjectIds()
|
|
return callServer(
|
|
serverId,
|
|
'searchObjectIds',
|
|
[serverId, getApplicationToken(), userToken,
|
|
objectIds, sortRule, searchDict],
|
|
multiCall = multiCall)
|
|
|
|
def searchPartialObjects(self, serverId = None, requiredSlotNames = [],
|
|
objectIds = [], sortRule = '', **searchKeywords):
|
|
objectIds = self.searchObjectIds(serverId, objectIds = objectIds,
|
|
sortRule = sortRule, **searchKeywords)
|
|
multiCall = MultiCall()
|
|
for objectId in objectIds:
|
|
self.getPartialObject(objectId, requiredSlotNames,
|
|
multiCall = multiCall)
|
|
lazyObjects = multiCall.call()
|
|
objects = {}
|
|
for i in range(len(objectIds)):
|
|
objects[objectIds[i]] = lazyObjects[i]()
|
|
return objects
|
|
|
|
def setObjectSlotValueHolder(self, objectId, slotPath, valueHolder):
|
|
userToken = context.getVar('userToken', default = '')
|
|
valueHolderExport = valueHolder.exportToXmlRpc()
|
|
callServer(
|
|
commonTools.extractServerId(objectId),
|
|
'setObjectSlotValueHolder',
|
|
[commonTools.extractServerId(objectId), getApplicationToken(),
|
|
userToken, objectId, slotPath, valueHolderExport])
|
|
|
|
def sortObjectIds(self, objectIds, serverId = None, sortRule = None,
|
|
forceIds = 0):
|
|
"""Sort object Ids by specified attribute.
|
|
|
|
The object id are sorted by *sortRule* string.
|
|
This string is an attribute name.
|
|
Supported names are:
|
|
+ 'modificationTime': Descendent sort by modification time.
|
|
|
|
+ 'id': Ascendent sort by Id.
|
|
|
|
+ 'date': Descendent sort by the date attribute.
|
|
|
|
+ '': Ascendent sort by label.
|
|
|
|
Keyword arguments:
|
|
==================
|
|
|
|
*objectIds*:
|
|
The object ids sequence to sort.
|
|
|
|
*sortRule*:
|
|
The specified sort attribute.
|
|
|
|
Return:
|
|
=======
|
|
|
|
The sorted sequence of object ids.
|
|
|
|
Exceptions:
|
|
===========
|
|
|
|
*faults.UserAccessDenied*:
|
|
The user cannont get the objects list.
|
|
|
|
*faults.MissingItem*:
|
|
The object does not exist.
|
|
|
|
*UnknowException*:
|
|
- Error in comparaisons.
|
|
|
|
- The virtual server ID does not correspond to a instanciated
|
|
virtual server.
|
|
|
|
"""
|
|
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
if not objectIds and not forceIds:
|
|
return []
|
|
if sortRule is None:
|
|
sortRule = ""
|
|
return callServer(
|
|
serverId,
|
|
'sortObjectIds',
|
|
[serverId, getApplicationToken(), userToken,
|
|
objectIds, sortRule])
|
|
|
|
def subscribe(self, method, when, callbackName, serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'subscribe',
|
|
[serverId, getApplicationToken(), userToken, method, when,
|
|
callbackName])
|
|
|
|
def unsubscribe(self, method = '_ALL_', when= 'any ', callbackName = 'any',
|
|
serverId = None):
|
|
userToken = context.getVar('userToken', default = '')
|
|
serverId = self.getServerId(serverId = serverId)
|
|
return callServer(
|
|
serverId,
|
|
'unsubscribe',
|
|
[serverId, getApplicationToken(), userToken, method, when,
|
|
callbackName])
|
|
|