class SimpleRequestProcessor(object): """Processes request payloads from a RequestFactory client. This implementation is stateless. A single instance may be reused and is thread-safe. """ # Allows the creation of properly-configured AutoBeans without having to # create an AutoBeanFactory with the desired annotations. CONFIGURATION = Configuration.Builder().setCategories(EntityProxyCategory, ValueProxyCategory, BaseProxyCategory).setNoWrap(EntityProxyId).build() def __init__(self, serviceLayer): self._service = serviceLayer self._exceptionHandler = DefaultExceptionHandler() def processPayload(self, payload): """Process a payload sent by a RequestFactory client. @param payload the payload sent by the client @return a payload to return to the client """ req = AutoBeanCodex.decode(FACTORY, RequestMessage, payload).as_() responseBean = FACTORY.response() # Create a new response envelope, since the state is unknown # Return a JSON-formatted payload try: self.process(req, responseBean.as_()) except ReportableException, e: responseBean = FACTORY.response() responseBean.as_().setGeneralFailure(self.createFailureMessage(e).as_()) return AutoBeanCodex.encode(responseBean).getPayload()
def createOobMessage(self, domainValues): """Encode a list of objects into a self-contained message that can be used for out-of-band communication. """ state = RequestState(self._service) encodedValues = list() for domainValue in domainValues: if domainValue is None: clientValue = None else: clientType = self._service.resolveClientType( domainValue.__class__, BaseProxy, True) clientValue = state.getResolver().resolveClientValue( domainValue, clientType, set()) encodedValues.append(EntityCodex.encode(state, clientValue)) map_ = IdToEntityMap() map_.update(state.beans) operations = list() self.createReturnOperations(operations, state, map_) invocation = FACTORY.invocation().as_() invocation.setParameters(encodedValues) bean = FACTORY.request() resp = bean.as_() resp.setInvocations(list(invocation)) resp.setOperations(operations) return AutoBeanCodex.encode(bean)
def decodeOobMessage(self, domainClass, payload): """Decode an out-of-band message.""" proxyType = self._service.resolveClientType(domainClass, BaseProxy, True) state = RequestState(self._service) message = AutoBeanCodex.decode(FACTORY, RequestMessage, payload).as_() self.processOperationMessages(state, message) decoded = self.decodeInvocationArguments(state, message.getInvocations()[0].getParameters(), [proxyType], [domainClass]) return decoded
def getBeanForPayload(self, id_, domainObject=None): """Get or create a BaseProxy AutoBean for the given id.""" if domainObject is None: idMessage = AutoBeanCodex.decode(MessageFactoryHolder.FACTORY, IdMessage, id_).as_() toReturn = self.getBeansForPayload([idMessage]).get(0) return toReturn else: toReturn = self.beans.get(id_) if toReturn is None: toReturn = self.createProxyBean(id_, domainObject) return toReturn
def processPayload(self, payload): """Process a payload sent by a RequestFactory client. @param payload the payload sent by the client @return a payload to return to the client """ req = AutoBeanCodex.decode(FACTORY, RequestMessage, payload).as_() responseBean = FACTORY.response() # Create a new response envelope, since the state is unknown # Return a JSON-formatted payload try: self.process(req, responseBean.as_()) except ReportableException, e: responseBean = FACTORY.response() responseBean.as_().setGeneralFailure(self.createFailureMessage(e).as_())
def getSerializedProxyId(self, stableId): """EntityCodex support. This method is identical to {@link IdFactory#getHistoryToken(SimpleProxyId)} except that it base64-encodes the server ids. <p> XXX: Merge this with AbstsractRequestContext's implementation """ bean = MessageFactoryHolder.FACTORY.id() ref = bean.as_() ref.setTypeToken(self._service.resolveTypeToken(stableId.getProxyClass())) if stableId.isSynthetic(): ref.setStrength(Strength.SYNTHETIC) ref.setSyntheticId(stableId.getSyntheticId()) elif stableId.isEphemeral(): ref.setStrength(Strength.EPHEMERAL) ref.setClientId(stableId.getClientId()) else: ref.setServerId(toBase64(stableId.getServerId())) return AutoBeanCodex.encode(bean)
def processInvocationMessages(self, state, req, results, successes, returnState): invocations = req.getInvocations() if invocations is None: # No method invocations which can happen via RequestContext.fire() return contextMethods = list() invocationResults = list() allPropertyRefs = dict() for invocation in invocations: # Find the Method try: operation = invocation.getOperation() contextMethod = self._service.resolveRequestContextMethod(operation) if contextMethod is None: raise UnexpectedException('Cannot resolve operation ' + invocation.getOperation(), None) contextMethods.append(contextMethod) domainMethod = self._service.resolveDomainMethod(operation) if domainMethod is None: raise UnexpectedException('Cannot resolve domain method ' + invocation.getOperation(), None) # Compute the arguments args = self.decodeInvocationArguments_(state, invocation, contextMethod) # Possibly use a ServiceLocator if self._service.requiresServiceLocator(contextMethod, domainMethod): requestContext = self._service.resolveRequestContext(operation) serviceInstance = self._service.createServiceInstance(requestContext) args.add(0, serviceInstance) # Invoke it domainReturnValue = self._service.invoke(domainMethod, list(args)) if invocation.getPropertyRefs() is not None: paths = allPropertyRefs[domainReturnValue] if paths is None: paths = set()#TreeSet() allPropertyRefs[domainReturnValue] = paths paths.update(invocation.getPropertyRefs()) ok = True except ReportableException, e: domainReturnValue = AutoBeanCodex.encode(self.createFailureMessage(e)) ok = False invocationResults.append(domainReturnValue) successes.append(ok)
def getSerializedProxyId(self, stableId): """EntityCodex support. This method is identical to {@link IdFactory#getHistoryToken(SimpleProxyId)} except that it base64-encodes the server ids. <p> XXX: Merge this with AbstsractRequestContext's implementation """ bean = MessageFactoryHolder.FACTORY.id() ref = bean.as_() ref.setTypeToken( self._service.resolveTypeToken(stableId.getProxyClass())) if stableId.isSynthetic(): ref.setStrength(Strength.SYNTHETIC) ref.setSyntheticId(stableId.getSyntheticId()) elif stableId.isEphemeral(): ref.setStrength(Strength.EPHEMERAL) ref.setClientId(stableId.getClientId()) else: ref.setServerId(toBase64(stableId.getServerId())) return AutoBeanCodex.encode(bean)