// TODO: Implement /* private SIF_Request createSIF_Request( ElementDef objectType, String refId, Zone zone ) { SIF_Request request = new SIF_Request(); request.getHeader().setSIF_MsgId( MSG_GUID ); request.getHeader().setSIF_SourceId( "foo" ); request.setSIF_MaxBufferSize("32768"); request.setSIF_Version( ADK.getSIFVersion().toString() ); Query query = new Query(objectType); query.addCondition(SifDtd.SIF_REPORTOBJECT_REFID, Condition.EQ, refId); SIF_Query q = SIFPrimitives.createSIF_Query(query, zone); SIF_QueryObject sqo = new SIF_QueryObject(); sqo.setObjectName( objectType.name() ); q.setSIF_QueryObject(sqo); request.setSIF_Query(q); return request; } */ private SIF_Response createSIF_Response(IElementDef objType, bool storeInRequestCache, ISerializable stateObject) { SIF_Request req = createSIF_Request(objType); if (storeInRequestCache) { Query q = new Query(objType); q.UserData = stateObject; RequestCache.GetInstance(fAgent).StoreRequestInfo(req, q, fZone); } SIF_Response resp = new SIF_Response(); resp.SIF_RequestMsgId = req.Header.SIF_MsgId; SIF_ObjectData sod = new SIF_ObjectData(); resp.SIF_ObjectData = sod; Object responseObject = null; try { responseObject = ClassFactory.CreateInstance(objType.FQClassName, false); } catch (Exception cfe) { throw new AdkException("Unable to create instance of " + objType.Name, fZone, cfe); } sod.AddChild((SifElement)responseObject); return resp; }
private void assertRequestCacheCleared(SIF_Response r) { // Now the RequestCache should no longer contain the specified object IRequestInfo inf = RequestCache.GetInstance(fAgent).LookupRequestInfo(r.SIF_RequestMsgId, fZone); Assert.IsNull(inf, "RequestInfo should be removed from the cache"); }
/// <summary> Find the QueryResults object for a zone by searching up the message /// dispatching chain until a Zone, Topic, or Agent is found with a registered /// QueryResults implementation. /// /// </summary> /// <param name="rsp">The SIF_Response message (if a SIF_Response was received). /// Either rsp or req must be specified, but not both. /// </param> /// <param name="req">The SIF_Request message (if a SIF_Request is being sent). /// Either rsp or req must be specified, but not both. /// </param> /// <param name="query">Only applicable when <i>req</i> is non-null: The Query /// associated with the SIF_Request /// </param> /// <param name="zone">The Zone to begin the search at /// </param> internal IQueryResults getQueryResultsTarget(SIF_Response rsp, SIF_Request req, IElementDef objType, Query query, IZone zone) { // // - First check TrackQueryResults for a matching pending request // - Next check the Topic, the Zone, and finally the Agent. The // message is dispatched to the first one that results a // QueryResults object // IQueryResults target = null; SifContext context = null; if (req != null) { // First check TrackQueryResults string reqId = req.MsgId; // TODO: Implement SMB later // TrackQueryResults tracker = (TrackQueryResults) TrackQueryResultsImpl.sRequestQueries[query]; // if (tracker != null) // { // TrackQueryResultsImpl.sRequestQueries.Remove( query ); // target = tracker; // } // else // { SIF_Query q = req.SIF_Query; if (q == null) { throw new SifException (SifErrorCategoryCode.Xml, SifErrorCodes.XML_MISSING_MANDATORY_ELEMENT_6, "SIF_Request message missing mandatory element", "SIF_Query is required", fZone); } SIF_QueryObject qo = q.SIF_QueryObject; if (qo == null) { throw new SifException (SifErrorCategoryCode.Xml, SifErrorCodes.XML_MISSING_MANDATORY_ELEMENT_6, "SIF_Request message missing mandatory element", "SIF_QueryObject is required", fZone); } objType = Adk.Dtd.LookupElementDef(qo.ObjectName); if (objType == null) { throw new SifException (SifErrorCategoryCode.RequestResponse, SifErrorCodes.REQRSP_INVALID_OBJ_3, "Agent does not support this object type", qo.ObjectName, fZone); } // Check to see if the Context is supported // TODO: Determine if a SIFException should be thrown at this point? try { context = req.SifContexts[0]; } catch (AdkNotSupportedException contextNotSupported) { throw new SifException( SifErrorCategoryCode.Generic, SifErrorCodes.GENERIC_CONTEXT_NOT_SUPPORTED_4, contextNotSupported.Message, fZone); } } else if (rsp != null) { // TODO Implement SMB // // First check TrackQueryResults object to see if it is expecting // // to be called for this SIF_Response // string reqId = rsp.SIF_RequestMsgId; // // TrackQueryResults tracker = (TrackQueryResults) TrackQueryResultsImpl.sRequestMsgIds[reqId]; // if (tracker != null) // { // // Dispatch to the TrackQueryResults object // target = tracker; // } // Check to see if the Context is supported // TODO: Determine if a SIFException should be thrown at this point? try { context = rsp.SifContexts[0]; } catch (AdkNotSupportedException contextNotSupported) { throw new SifException( SifErrorCategoryCode.Generic, SifErrorCodes.GENERIC_CONTEXT_NOT_SUPPORTED_4, contextNotSupported.Message, fZone); } } else { throw new ArgumentException ( "A SIF_Request or SIF_Response object must be passed to getQueryResultsTarget"); } if (target == null) { TopicImpl topic = (TopicImpl)fZone.Agent.TopicFactory.LookupInstance(objType, context); if (topic != null) { target = topic.fQueryResults; } if (target == null) { // Next try the Zone... target = fZone.GetQueryResults(context, objType); } if (target == null) { // Finally, try the Agent... target = fZone.Agent.GetQueryResults(context, objType); } } return target; }
/// <summary> Dispatch a SIF_Response. /// /// SIF_Response messages are dispatched as follows: /// /// <ul> /// <li> /// If a TrackQueryResults object issued the original SIF_Request /// during this agent session (i.e. the agent process has not /// terminated since the SIF_Request was issued), the response is /// dispatched to that TrackQueryResults object via its QueryResults /// interface. /// </li> /// <li> /// If a Topic exists for the data type associated with the /// SIF_Response, it is dispatched to the QueryResults object /// registered with that Topic. /// </li> /// <li> /// If no Topic exists for the data type associated with the /// SIF_Response, it is dispatched to the QueryResults object /// registered with the Zone from which the SIF_Response was /// received. /// </li> /// </ul> /// /// <b>SIF_ZoneStatus</b> is handled specially. When Zone.awaitingZoneStatus /// returns true, the agent is blocking on a call to Zone.getZoneStatus(). /// In this case, the SIF_ZoneStatus object is routed directly to the Zone /// object instead of being dispatched via the usual QueryResults mechanism. /// /// </summary> private void dispatchResponse(SIF_Response rsp) { // block thread until Zone.Query() has completed in case it is in the // midst of a SIF_Request. This is done to ensure that we don't receive // the SIF_Response from the zone before the ADK and agent have finished // with the SIF_Request in Zone.Query() fZone.WaitForRequestsToComplete(); bool retry = false; IRequestInfo reqInfo = null; AdkException cacheErr = null; try { try { reqInfo = fRequestCache.LookupRequestInfo(rsp.SIF_RequestMsgId, fZone); } catch (AdkException adke) { cacheErr = adke; } #if PROFILED if( objType != null ) { ProfilerUtils.profileStart( com.OpenADK.sifprofiler.api.OIDs.ADK_SIFRESPONSE_REQUESTOR_MESSAGING.ToString(), Adk.Dtd.LookupElementDef(objType), rsp.MsgId ); } #endif SIF_Error error = null; SIF_ObjectData od = rsp.SIF_ObjectData; if (od == null) { throw new SifException ( SifErrorCategoryCode.Xml, SifErrorCodes.XML_MISSING_MANDATORY_ELEMENT_6, "SIF_Response missing mandatory element", "SIF_ObjectData is a required element of SIF_Response", fZone); } IList<SifElement> sel = od.GetChildList(); if (sel.Count < 1) { error = rsp.SIF_Error; // // If the SIF_Response has no SIF_ObjectData elements but does // have a SIF_Error child, the associated object type can // only be gotten from the RequestCache, but that had // failed so try and call the UndeliverableMessageHandler. // if (cacheErr != null || reqInfo == null) { bool handled = false; IUndeliverableMessageHandler errHandler = fZone.ErrorHandler; if (errHandler != null) { SifMessageInfo msginfo = new SifMessageInfo(rsp, fZone); msginfo.SIFRequestInfo = reqInfo; handled = errHandler.OnDispatchError(rsp, fZone, msginfo); // Notify MessagingListeners... NotifyMessagingListeners_OnMessageProcessed (SifMessageType.SIF_Response, msginfo); } if (!handled) { fZone.Log.Warn ( "Received a SIF_Response message with MsgId " + rsp.MsgId + " (for SIF_Request with MsgId " + rsp.SIF_RequestMsgId + ") " + " containing an empty result set or a SIF_Error, but failed to obtain the SIF Data Object" + " type from the RequestCache" + (cacheErr != null ? (" due to an error: " + cacheErr.Message) : "")); } return; } } string objectType = reqInfo != null ? reqInfo.ObjectType : null; if (objectType == null && sel.Count > 0) { objectType = sel[0].ElementDef.Tag(rsp.SifVersion); } if (objectType != null && (string.Compare(objectType, "SIF_ZoneStatus", true) == 0)) { // SIF_ZoneStatus is a special case if (fZone.AwaitingZoneStatus()) { fZone.SetZoneStatus((SIF_ZoneStatus)sel[0]); return; } } if (reqInfo == null) { reqInfo = new UnknownRequestInfo(rsp.SIF_RequestMsgId, objectType); } // Decide where to send this response IQueryResults target = getQueryResultsTarget (rsp, null, Adk.Dtd.LookupElementDef(objectType), null, fZone); if (target == null) { bool handled = false; IUndeliverableMessageHandler errHandler = fZone.ErrorHandler; if (errHandler != null) { SifMessageInfo msginfo = new SifMessageInfo(rsp, fZone); if (reqInfo != null) { msginfo.SIFRequestInfo = reqInfo; } handled = errHandler.OnDispatchError(rsp, fZone, msginfo); // Notify MessagingListeners... NotifyMessagingListeners_OnMessageProcessed (SifMessageType.SIF_Response, msginfo); } if (!handled) { fZone.Log.Warn ("Received a SIF_Response message with MsgId " + rsp.MsgId + " (for SIF_Request with MsgId " + rsp.SIF_RequestMsgId + "), but no QueryResults object is registered to handle it or the request was issued by a TrackQueryResults that has timed out"); } return; } // // Dispatch the message... // IElementDef sifRequestObjectDef = Adk.Dtd.LookupElementDef(objectType); DataObjectInputStreamImpl dataStr = DataObjectInputStreamImpl.newInstance(); dataStr.fObjType = sifRequestObjectDef; if (error == null) { // Convert to a SifDataObject array SifDataObject[] data = new SifDataObject[sel.Count]; for (int i = 0; i < sel.Count; i++) { data[i] = (SifDataObject)sel[i]; } // Let the QueryResults object process the message dataStr.Data = data; } SifMessageInfo msgInf = new SifMessageInfo(rsp, fZone); msgInf.SIFRequestInfo = reqInfo; msgInf.SIFRequestObjectType = sifRequestObjectDef; target.OnQueryResults(dataStr, error, fZone, msgInf); // Notify MessagingListeners... NotifyMessagingListeners_OnMessageProcessed(SifMessageType.SIF_Response, msgInf); } catch (AdkException adkEx) { retry = adkEx.Retry; throw; } catch (Exception thr) { throw new SifException ( SifErrorCategoryCode.Generic, SifErrorCodes.GENERIC_GENERIC_ERROR_1, "Error processing SIF_Response", "Exception in QueryResults message handler: " + thr.ToString(), fZone); } finally { // If the reqInfo variable came from the cache, and retry is set to false, // remove it from the cache if this is the last packet if (!(reqInfo is UnknownRequestInfo) && !retry) { String morePackets = rsp.SIF_MorePackets; if (!(morePackets != null && morePackets.ToLower().Equals("yes"))) { // remove from the cache fRequestCache.GetRequestInfo(rsp.SIF_RequestMsgId, fZone); } } #if PROFILED if( BuildOptions.PROFILED ) { if( reqInfo != null ) { ProfilerUtils.profileStop(); } #endif } }
/// <summary> Calculate the size of a SIF_Response minus the SIF_ObjectData content.</summary> protected virtual long CalcEnvelopeSize( ZoneImpl zone ) { long size = 400; try { SIF_Response rsp = new SIF_Response(); rsp.SIF_MorePackets = "Yes"; rsp.SIF_RequestMsgId = fReqId; rsp.SIF_PacketNumber = 100000000; SIF_ObjectData data = new SIF_ObjectData(); data.TextValue = " "; rsp.SIF_ObjectData = data; SIF_Header hdr = rsp.Header; hdr.SIF_Timestamp = DateTime.Now; hdr.SIF_MsgId = "012345678901234567890123456789012"; hdr.SIF_SourceId = zone.Agent.Id; hdr.SIF_Security = zone.Dispatcher.secureChannel(); hdr.SIF_DestinationId = fDestId; using ( MemoryStream buffer = new MemoryStream() ) { SifWriter writer = new SifWriter( buffer ); writer.Write( rsp ); writer.Flush(); size = buffer.Length + 10; writer.Close(); buffer.Close(); } } catch( Exception ex ) { zone.Log.Warn( "Error calculating packet size: " + ex, ex ); } return size; }