public Element sendRequestWithNotification(Element request) throws ServiceException { Server server = Provisioning.getInstance() .get(Key.ServerBy.name, OfflineConstants.SYNC_SERVER_PREFIX + getAccountId()); if (server != null) { // when we first add an account, server is still null List<Session> soapSessions = getListeners(Session.Type.SOAP); Session session = null; if (soapSessions.size() == 1) { session = soapSessions.get(0); } else if (soapSessions.size() > 1) { // this occurs if user refreshes web browser (or opens ZD in two different browsers); older // session does not time out so there are now two listening // only the most recent is 'active' for (Session ses : soapSessions) { if (session == null || ses.accessedAfter(session.getLastAccessTime())) { session = ses; } } } if (session != null) { ZAuthToken zat = getAuthToken(); if (zat != null) { AuthToken at = AuthProvider.getAuthToken(OfflineProvisioning.getOfflineInstance().getLocalAccount()); at.setProxyAuthToken(zat.getValue()); ProxyTarget proxy = new ProxyTarget(server, at, getSoapUri()); // zscProxy needs to be for the 'ffffff-' account, but with target of *this* mailbox's // acct // currently UI receives SoapJS in its responses, we ask for that protocol so // notifications are handled correctly ZimbraSoapContext zscIn = new ZimbraSoapContext( at, at.getAccountId(), SoapProtocol.Soap12, SoapProtocol.SoapJS); ZimbraSoapContext zscProxy = new ZimbraSoapContext(zscIn, getAccountId(), session); proxy.setTimeouts(OfflineLC.zdesktop_request_timeout.intValue()); return DocumentHandler.proxyWithNotification(request, proxy, zscProxy, session); } } } return sendRequest(request); }
/** * Always does a request -- caller is responsible for checking to see if this is necessary or not */ private boolean bufferNextHits() throws ServiceException { if (atEndOfList || searchParams.getHopCount() > ZimbraSoapContext.MAX_HOP_COUNT) { return false; } bufferStartOffset = iterOffset; int chunkSizeToUse; if (singleShotRemoteRequest) { chunkSizeToUse = searchParams.getLimit(); } else { chunkSizeToUse = searchParams.getLimit() * 2; if (chunkSizeToUse < MIN_BUFFER_CHUNK_SIZE) { chunkSizeToUse = MIN_BUFFER_CHUNK_SIZE; } if (chunkSizeToUse > 500) { chunkSizeToUse = 500; } } bufferEndOffset = bufferStartOffset + chunkSizeToUse; hitBuffer = new ArrayList<ProxiedHit>(chunkSizeToUse); Element searchElt = Element.create(responseProto, MailConstants.SEARCH_REQUEST); searchParams.setOffset(bufferStartOffset); searchParams.setLimit(chunkSizeToUse); searchParams.encodeParams(searchElt); if (singleShotRemoteRequest && (searchParams.getCursor() != null)) { Element cursorElt = searchElt.addElement(MailConstants.E_CURSOR); cursorElt.addAttribute(MailConstants.A_ID, searchParams.getCursor().getItemId().getId()); if (searchParams.getCursor().getSortValue() != null) { cursorElt.addAttribute(MailConstants.A_SORTVAL, searchParams.getCursor().getSortValue()); } if (searchParams.getCursor().getEndSortValue() != null) { cursorElt.addAttribute( MailConstants.A_ENDSORTVAL, searchParams.getCursor().getEndSortValue()); } } // call the remote server now! Server targetServer = Provisioning.getInstance().get(Key.ServerBy.name, server); String baseurl = null; try { baseurl = URLUtil.getSoapURL(targetServer, false); } catch (ServiceException e) { } if (baseurl == null) { baseurl = URLUtil.getAdminURL(targetServer, AdminConstants.ADMIN_SERVICE_URI, true); } ProxyTarget proxy = new ProxyTarget(targetServer, authToken, baseurl + MailConstants.SEARCH_REQUEST.getName()); if (mTimeout != -1) { proxy.setTimeouts(mTimeout); } ZimbraSoapContext zscInbound = searchParams.getRequestContext(); ZimbraSoapContext zscProxy; if (zscInbound != null) { zscProxy = new ZimbraSoapContext(zscInbound, targetAcctId); } else { zscProxy = new ZimbraSoapContext( authToken, targetAcctId, responseProto, responseProto, searchParams.getHopCount() + 1); } long start = System.currentTimeMillis(); Element searchResp = null; try { searchResp = DocumentHandler.proxyWithNotification(searchElt, proxy, zscProxy, zscInbound); } catch (SoapFaultException sfe) { ZimbraLog.index.warn( "Unable to (" + sfe + ") fetch search results from remote server " + proxy); atEndOfList = true; bufferEndOffset = iterOffset; return false; } catch (ServiceException e) { if (ServiceException.PROXY_ERROR.equals(e.getCode())) { ZimbraLog.index.warn( "Unable to (" + e + ") fetch search results from remote server " + proxy); atEndOfList = true; bufferEndOffset = iterOffset; return false; } throw e; } finally { long elapsed = System.currentTimeMillis() - start; ZimbraLog.index.debug( "Remote query took " + elapsed + "ms; URL=" + proxy.toString() + "; QUERY=" + searchElt.toString()); } int hitOffset; if (singleShotRemoteRequest) { hitOffset = (int) searchResp.getAttributeLong(MailConstants.A_QUERY_OFFSET, bufferStartOffset); } else { hitOffset = (int) searchResp.getAttributeLong(MailConstants.A_QUERY_OFFSET); } boolean hasMore = searchResp.getAttributeBool(MailConstants.A_QUERY_MORE); assert (bufferStartOffset == hitOffset); SortBy sb = getSortBy(); // put these hits into our buffer! int bufferIdx = 0; int stop = bufferEndOffset - bufferStartOffset; for (Iterator<Element> iter = searchResp.elementIterator(); iter.hasNext() && bufferIdx < stop; ) { Element el = iter.next(); if (el.getName().equalsIgnoreCase(MailConstants.E_INFO)) { for (Element info : el.listElements()) { queryInfo.add(new ProxiedQueryInfo(info)); } } else { if (sb != null && ((SortBy.NAME_LOCALIZED_ASC.equals(sb)) || (SortBy.NAME_LOCALIZED_DESC.equals(sb)))) { hitBuffer.add( bufferIdx++, new ProxiedContactHit(this, el, el.getAttribute(MailConstants.A_FILE_AS_STR))); } else { hitBuffer.add( bufferIdx++, new ProxiedHit(this, el, el.getAttribute(MailConstants.A_SORT_FIELD))); } } } // are we at the end of the line here? if (bufferIdx < stop || !hasMore) { // update the buffer-end-pointer bufferEndOffset = bufferStartOffset + bufferIdx; if (hasMore) { assert (!hasMore); // if bufferIdx < stop then !hasMore should be set...server bug! } atEndOfList = true; } else { assert (bufferEndOffset == bufferStartOffset + bufferIdx); } if (singleShotRemoteRequest) { atEndOfList = true; } assert (bufferStartOffset <= iterOffset); // OK, we were successful if we managed to buffer the current hit return (bufferEndOffset > iterOffset); }