Example #1
0
        void checkSourceAssociations()
        {
            Hashtable <String, int> hashPassed = new Hashtable <String, int>();

            for (int nCurSrc = m_sources.size() - 1; nCurSrc > 0;)
            {
                SyncSource oCurSrc = (SyncSource)m_sources.elementAt(nCurSrc);
                if (oCurSrc.getAssociations().size() == 0 || hashPassed.containsKey(oCurSrc.getName()))
                {
                    nCurSrc--;
                }
                else
                {
                    int nSrc = nCurSrc;
                    for (int i = 0; i < (int)oCurSrc.getAssociations().size(); i++)
                    {
                        SyncSource.CAssociation oAssoc = (SyncSource.CAssociation)oCurSrc.getAssociations().elementAt(i);
                        int nAssocSrcIndex             = findSrcIndex(m_sources, oAssoc.m_strSrcName);
                        if (nAssocSrcIndex >= 0 && nAssocSrcIndex < nSrc)
                        {
                            m_sources.removeElementAt(nSrc);
                            m_sources.insertElementAt(oCurSrc, nAssocSrcIndex);

                            nSrc = nAssocSrcIndex;
                        }
                    }
                }

                hashPassed.put(oCurSrc.getName(), 1);
            }
        }
Example #2
0
        SyncNotification getSyncNotifyBySrc(SyncSource src)
        {
            SyncNotification pSN = null;

            if (getSync().isSearch())
            {
                pSN = m_pSearchNotification;
            }
            else
            {
                if (src != null)
                {
                    pSN = (SyncNotification)m_mapSyncNotifications.get(src.getID());
                }

                if (pSN == null)
                {
                    pSN = m_pAllNotification;
                }
            }

            if (pSN == null && !getSync().isNoThreadedMode())
            {
                return(null);
            }

            return(pSN != null ? pSN : m_emptyNotify);
        }
Example #3
0
            public boolean isEqual(SyncSource src)
            {
                if ( m_strName.length() > 0 )
                    return src.getName().equals(m_strName);

                return m_nID == src.getID();
            }
Example #4
0
        boolean syncOneSource(int i)
        {
            SyncSource src    = null;
            boolean    bError = false;

            try{
                src = (SyncSource)m_sources.elementAt(i);
                if (src.getSyncType().compareTo("bulk_sync_only") == 0)
                {
                    return(true);
                }

                if (isSessionExist() && getState() != esStop)
                {
                    src.sync();
                }

                //getNotify().onSyncSourceEnd(i, m_sources);
            }catch (Exception exc)
            {
                if (src.m_nErrCode == RhoAppAdapter.ERR_NONE)
                {
                    src.m_nErrCode = RhoAppAdapter.ERR_RUNTIME;
                }

                setState(esStop);
                throw exc;
            }finally{
                getNotify().onSyncSourceEnd(i, m_sources);
                bError = src.m_nErrCode != RhoAppAdapter.ERR_NONE;
            }

            return(!bError);
        }
Example #5
0
/*
 *          int getStartSource()
 *          {
 *              for( int i = 0; i < m_sources.size(); i++ )
 *              {
 *                  SyncSource src = (SyncSource)m_sources.elementAt(i);
 *                  if ( !src.isEmptyToken() )
 *                      return i;
 *              }
 *
 *              return -1;
 *          }
 */
        void syncOneSource(int i)
        {
            SyncSource src = null;

            //boolean bError = false;
            try{
                src = (SyncSource)m_sources.elementAt(i);
                if (src.getSyncType().compareTo("bulk_sync_only") == 0)
                {
                    return;
                }

                if (isSessionExist() && getState() != esStop)
                {
                    src.sync();
                }

                //getNotify().onSyncSourceEnd(i, m_sources);
            }catch (Exception exc)
            {
                if (src.m_nErrCode == RhoAppAdapter.ERR_NONE)
                {
                    src.m_nErrCode = RhoAppAdapter.ERR_RUNTIME;
                }

                //setState(esStop);
                //throw exc;
                LOG.ERROR("Sync of source '" + src.getName() + "' failed.", exc);
            }finally{
                getNotify().onSyncSourceEnd(i, m_sources);
                //bError = src.m_nErrCode != RhoAppAdapter.ERR_NONE;
            }

            //return !bError;
        }
Example #6
0
            public boolean isEqual(SyncSource src)
            {
                if (m_strName.length() > 0)
                {
                    return(src.getName().equals(m_strName));
                }

                return(m_nID == src.getID());
            }
Example #7
0
 void processAssociations(String strOldObject, String strNewObject)
 {
     for (int i = 0; i < m_arAssociations.size(); i++)
     {
         SyncSource pSrc = getSync().findSourceByName(((CAssociation)m_arAssociations.elementAt(i)).m_strSrcName);
         if (pSrc != null)
         {
             pSrc.updateAssociation(strOldObject, strNewObject, ((CAssociation)m_arAssociations.elementAt(i)).m_strAttrib);
         }
     }
 }
Example #8
0
        SyncSource findSource(SourceID oSrcID)
        {
            for (int i = 0; i < (int)m_sources.size(); i++)
            {
                SyncSource src = (SyncSource)m_sources.elementAt(i);
                if (oSrcID.isEqual(src))
                {
                    return(src);
                }
            }

            return(null);
        }
Example #9
0
        int getStartSource()
        {
            for (int i = 0; i < m_sources.size(); i++)
            {
                SyncSource src = (SyncSource)m_sources.elementAt(i);
                if (!src.isEmptyToken())
                {
                    return(i);
                }
            }

            return(-1);
        }
Example #10
0
        void prepareSync(int eState, SourceID oSrcID)
        {
            setState(eState);
            m_bIsSearch        = eState == esSearch;
            m_bStopByUser      = false;
            m_nErrCode         = RhoAppAdapter.ERR_NONE;
            m_strError         = "";
            m_strServerError   = "";
            m_bIsSchemaChanged = false;

            loadAllSources();

            m_strSession = loadSession();
            if (isSessionExist())
            {
                m_clientID = loadClientID();
                if (m_nErrCode == RhoAppAdapter.ERR_NONE)
                {
                    getNotify().cleanLastSyncObjectCount();
                    doBulkSync();

                    return;
                }
            }
            else
            {
                m_nErrCode = RhoAppAdapter.ERR_CLIENTISNOTLOGGEDIN;
            }

            SyncSource src = null;

            if (oSrcID != null)
            {
                src = findSource(oSrcID);
            }

            if (src != null)
            {
                src.m_nErrCode = m_nErrCode;
                src.m_strError = m_strError;
                getNotify().fireSyncNotification(src, true, src.m_nErrCode, "");
            }
            else
            {
                getNotify().fireAllSyncNotifications(true, m_nErrCode, m_strError, "");
            }

            stopSync();
        }
Example #11
0
        public void doSyncSource(SourceID oSrcID, String strQueryParams)
        {
            SyncSource src = null;

            try
            {
                prepareSync(esSyncSource, oSrcID);

                if (isContinueSync())
                {
                    src = findSource(oSrcID);
                    if (src != null)
                    {
                        LOG.INFO("Started synchronization of the data source: " + src.getName());

                        src.m_strQueryParams = strQueryParams;
                        src.sync();

                        getNotify().fireSyncNotification(src, true, src.m_nErrCode, src.m_nErrCode == RhoAppAdapter.ERR_NONE ? RhoAppAdapter.getMessageText("sync_completed") : "");
                    }
                    else
                    {
                        //                    LOG.ERROR( "Sync one source : Unknown Source " + oSrcID.toString() );

                        src = new SyncSource(this, getUserDB());
                        //src.m_strError = "Unknown sync source.";
                        src.m_nErrCode = RhoAppAdapter.ERR_RUNTIME;

                        throw new Exception("Sync one source : Unknown Source " + oSrcID.toString());
                    }
                }
            } catch (Exception exc) {
                LOG.ERROR("Sync source " + oSrcID.toString() + " failed.", exc);

                if (src != null && src.m_nErrCode == RhoAppAdapter.ERR_NONE)
                {
                    src.m_nErrCode = RhoAppAdapter.ERR_RUNTIME;
                }

                getNotify().fireSyncNotification(src, true, src.m_nErrCode, "");
            }

            getNotify().cleanCreateObjectErrors();
            if (getState() != esExit)
            {
                setState(esNone);
            }
        }
Example #12
0
        void clearNotification(SyncSource src)
        {
            LOG.INFO("Clear notification. Source : " + (src != null ? src.getName() : ""));

            lock (m_mxSyncNotifications)
            {
                if (getSync().isSearch())
                {
                    m_pSearchNotification = null;
                }
                else
                {
                    m_mapSyncNotifications.remove(src.getID());
                }
            }
        }
Example #13
0
        void processSingleObject()
        {
            if (m_strSingleObjectSrcName.length() == 0)
            {
                return;
            }

            SyncSource Src = getSync().findSourceByName(m_strSingleObjectSrcName);

            if (Src != null)
            {
                int nSrcID = Src.getID();
                addObjectNotify(nSrcID, m_strSingleObjectID);
            }

            m_strSingleObjectSrcName = "";
            m_strSingleObjectID      = "";
        }
Example #14
0
        public void applyChangedValues(DBAdapter db)
        {
            IDBResult resSrc = db.executeSQL("SELECT DISTINCT(source_id) FROM changed_values");

            for ( ; !resSrc.isEnd(); resSrc.next())
            {
                int       nSrcID = resSrc.getIntByIdx(0);
                IDBResult res    = db.executeSQL("SELECT source_id,sync_type,name, partition from sources WHERE source_id=?", nSrcID);
                if (res.isEnd())
                {
                    continue;
                }

                SyncSource src = new SyncSource(res.getIntByIdx(0), res.getStringByIdx(2), "none", db, this);

                src.applyChangedValues();
            }
        }
Example #15
0
        public void onSyncSourceEnd(int nSrc, Vector <SyncSource> sources)
        {
            SyncSource src = sources.elementAt(nSrc);

/*
 *          if ( getSync().getState() == SyncEngine.esStop && src.m_nErrCode != RhoAppAdapter.ERR_NONE )
 *          {
 *                  SyncNotification pSN = getSyncNotifyBySrc(src);
 *                  if ( pSN != null )
 *                          fireSyncNotification(src, true, src.m_nErrCode, "");
 *                  else
 *                          fireAllSyncNotifications(true, src.m_nErrCode, src.m_strError, "" );
 *          }
 *          else*/
            fireSyncNotification(src, true, src.m_nErrCode, "");

            cleanCreateObjectErrors();
        }
Example #16
0
        public void fireSyncNotification(SyncSource src, boolean bFinish, int nErrCode, String strMessage)
        {
            if (getSync().getState() == SyncEngine.esExit)
            {
                return;
            }

            if (strMessage.length() > 0 || nErrCode != RhoAppAdapter.ERR_NONE)
            {
                if (!getSync().isSearch())
                {
                    if (src != null && (strMessage == null || strMessage.length() == 0))
                    {
                        strMessage = RhoAppAdapter.getMessageText("sync_failed_for") + src.getName() + ".";
                    }

                    reportSyncStatus(strMessage, nErrCode, src != null?src.m_strError:"");
                }
            }

            doFireSyncNotification(src, bFinish, nErrCode, "", "", "");
        }
Example #17
0
	    SyncNotification getSyncNotifyBySrc(SyncSource src)
	    {
	        SyncNotification pSN = null;
		    if ( getSync().isSearch() )
			    pSN = m_pSearchNotification;
		    else
	        {
	            if ( src != null )
			        pSN = (SyncNotification)m_mapSyncNotifications.get( src.getID());

	            if ( pSN == null )
	                pSN = m_pAllNotification;
	        }

		    if ( pSN == null && !getSync().isNoThreadedMode() )
	            return null;

	        return pSN != null ? pSN : m_emptyNotify;
	    }
Example #18
0
	    public void fireSyncNotification( SyncSource src, boolean bFinish, int nErrCode, String strMessage )
	    {
		    if ( getSync().getState() == SyncEngine.esExit )
			    return;
		
		    if( strMessage.length() > 0 || nErrCode != RhoAppAdapter.ERR_NONE)
		    {
			    if ( !getSync().isSearch() )
			    {
				    if ( src != null && (strMessage==null || strMessage.length() == 0) )
					    strMessage = RhoAppAdapter.getMessageText("sync_failed_for") + src.getName() + ".";
				
				    reportSyncStatus(strMessage,nErrCode,src!= null?src.m_strError:"");
			    }
		    }
		
		    doFireSyncNotification(src, bFinish, nErrCode, "", "", "" );
	    }
Example #19
0
	    public void applyChangedValues(DBAdapter db)
	    {
	        IDBResult resSrc = db.executeSQL( "SELECT DISTINCT(source_id) FROM changed_values" );
	        for ( ; !resSrc.isEnd(); resSrc.next() )
	        {
	            int nSrcID = resSrc.getIntByIdx(0);
	            IDBResult res = db.executeSQL("SELECT source_id,sync_type,name, partition from sources WHERE source_id=?", nSrcID);
	            if ( res.isEnd() )
	                continue;

	            SyncSource src = new SyncSource( res.getIntByIdx(0), res.getStringByIdx(2), "none", db, this );

	            src.applyChangedValues();
	        }
	    }
Example #20
0
        public void doSyncSource(SourceID oSrcID)
        {
            SyncSource src = null;

	        try
	        {
	            prepareSync(esSyncSource, oSrcID);
	
	            if ( isContinueSync() )
	            {
	        	    src = findSource(oSrcID);
	                if ( src != null )
	                {
		                LOG.INFO("Started synchronization of the data source: " + src.getName() );
	
	                    src.sync();
	
				        getNotify().fireSyncNotification(src, true, src.m_nErrCode, src.m_nErrCode == RhoAppAdapter.ERR_NONE ? RhoAppAdapter.getMessageText("sync_completed") : "");
	                }else
	                {
    //                    LOG.ERROR( "Sync one source : Unknown Source " + oSrcID.toString() );
	            
		        	    src = new SyncSource(this, getUserDB());
			    	    //src.m_strError = "Unknown sync source.";
			    	    src.m_nErrCode = RhoAppAdapter.ERR_RUNTIME;
		        	
	    	    	    throw new Exception("Sync one source : Unknown Source " + oSrcID.toString() );
	                }
	            }
	
	        } catch(Exception exc) {
    		    LOG.ERROR("Sync source " + oSrcID.toString() + " failed.", exc);
	    	
	    	    if ( src != null && src.m_nErrCode == RhoAppAdapter.ERR_NONE )
	    		    src.m_nErrCode = RhoAppAdapter.ERR_RUNTIME;
	    	
	    	    getNotify().fireSyncNotification(src, true, src.m_nErrCode, "" ); 
	        }

            getNotify().cleanCreateObjectErrors();
            if ( getState() != esExit )
                setState(esNone);
        }
Example #21
0
        void doFireSyncNotification(SyncSource src, boolean bFinish, int nErrCode, String strError, String strParams, String strServerError)
        {
            if (getSync().isStoppedByUser())
            {
                return;
            }

            try{
                SyncNotification pSN = null;

                String  strBody          = "";
                boolean bRemoveAfterFire = bFinish;
                {
                    lock (m_mxSyncNotifications){
                        pSN = getSyncNotifyBySrc(src);
                        if (pSN == null)
                        {
                            return;
                        }

                        strBody = "";

                        if (src != null)
                        {
                            strBody += "total_count=" + src.getTotalCount();
                            strBody += "&processed_count=" + src.getCurPageCount();
                            strBody += "&processed_objects_count=" + getLastSyncObjectCount(src.getID());
                            strBody += "&cumulative_count=" + src.getServerObjectsCount();
                            strBody += "&source_id=" + src.getID();
                            strBody += "&source_name=" + src.getName();
                        }

                        if (strParams.length() > 0)
                        {
                            strBody += (strBody.length() > 0 ? "&" : "") + strParams;
                        }
                        else
                        {
                            strBody += (strBody.length() > 0 ? "&" : "") + "sync_type=incremental";
                        }

                        strBody += "&status=";
                        if (bFinish)
                        {
                            if (nErrCode == RhoAppAdapter.ERR_NONE)
                            {
                                if (getSync().isSchemaChanged())
                                {
                                    strBody += "schema_changed";
                                }
                                else
                                {
                                    strBody += (src == null && strParams.length() == 0) ? "complete" : "ok";
                                }
                            }
                            else
                            {
                                if (getSync().isStoppedByUser())
                                {
                                    nErrCode = RhoAppAdapter.ERR_CANCELBYUSER;
                                }

                                strBody += "error";
                                strBody += "&error_code=" + nErrCode;

                                if (strError != null && strError.length() > 0)
                                {
                                    strBody += "&error_message=" + URI.urlEncode(strError);
                                }
                                else if (src != null)
                                {
                                    strBody += "&error_message=" + URI.urlEncode(src.m_strError);
                                }

                                if (strServerError != null && strServerError.length() > 0)
                                {
                                    strBody += "&" + strServerError;
                                }
                                else if (src != null && src.m_strServerError != null && src.m_strServerError.length() > 0)
                                {
                                    strBody += "&" + src.m_strServerError;
                                }
                            }

                            if (src != null)
                            {
                                strBody += makeCreateObjectErrorBody(src.getID());
                            }
                        }
                        else
                        {
                            strBody += "in_progress";
                        }

                        strBody += "&rho_callback=1";
                        if (pSN.m_strParams != null && pSN.m_strParams.length() > 0)
                        {
                            if (!pSN.m_strParams.startsWith("&"))
                            {
                                strBody += "&";
                            }

                            strBody += pSN.m_strParams;
                        }

                        bRemoveAfterFire = bRemoveAfterFire && pSN.m_bRemoveAfterFire;
                    }
                }
                if (bRemoveAfterFire)
                {
                    clearNotification(src);
                }

                LOG.INFO("Fire notification. Source : " + (src != null ? (src).getName():"") + "; " + pSN.ToString());

                if (callNotify(pSN, strBody))
                {
                    clearNotification(src);
                }
            }catch (Exception exc)
            {
                LOG.ERROR("Fire notification failed.", exc);
            }
        }
Example #22
0
	    void doFireSyncNotification( SyncSource src, boolean bFinish, int nErrCode, String strError, String strParams, String strServerError )
	    {
		    if ( getSync().isStoppedByUser() )
			    return;
		
		    try{
			    SyncNotification pSN = null;		
			
		        String strBody = "";
		        boolean bRemoveAfterFire = bFinish;
		        {
		    	    lock(m_mxSyncNotifications){
		    		    pSN = getSyncNotifyBySrc(src);
			            if ( pSN == null )
			                return;
			
				        strBody = "";

		                if ( src != null )
		                {
				            strBody += "total_count=" + src.getTotalCount();
				            strBody += "&processed_count=" + src.getCurPageCount();
				            strBody += "&processed_objects_count=" + getLastSyncObjectCount(src.getID());
				            strBody += "&cumulative_count=" + src.getServerObjectsCount();			        
				            strBody += "&source_id=" + src.getID();
				            strBody += "&source_name=" + src.getName();
		                }
		            
		                if ( strParams.length() > 0 )
		            	    strBody += (strBody.length() > 0 ? "&" : "") + strParams;
		                else
		            	    strBody += (strBody.length() > 0 ? "&" : "") + "sync_type=incremental";
			        
			            strBody += "&status=";
			            if ( bFinish )
			            {
				            if ( nErrCode == RhoAppAdapter.ERR_NONE )
				            {
				        	    if ( getSync().isSchemaChanged() )
				        		    strBody += "schema_changed";
				        	    else				        	
				        		    strBody += (src == null && strParams.length() == 0) ? "complete" : "ok";
				            }
				            else
				            {
				        	    if ( getSync().isStoppedByUser() )
		                            nErrCode = RhoAppAdapter.ERR_CANCELBYUSER;
				        	
				        	    strBody += "error";				        	
						        strBody += "&error_code=" + nErrCode;

                                if (strError != null && strError.length() > 0)
                                {
                                    if (strError.length() > MAX_SERVER_ERROR_LEN)
                                        strError = strError.substring(0, MAX_SERVER_ERROR_LEN);
                                    strBody += "&error_message=" + URI.urlEncode(strError);
                                }
                                else if (src != null && src.m_strError != null)
                                {
                                    if (src.m_strError.length() > MAX_SERVER_ERROR_LEN)
                                        src.m_strError = src.m_strError.substring(0, MAX_SERVER_ERROR_LEN);
                                    strBody += "&error_message=" + URI.urlEncode(src.m_strError);
                                }

                                if (strServerError != null && strServerError.length() > 0)
                                {
                                    if (strServerError.length() > MAX_SERVER_ERROR_LEN)
                                        strServerError = strServerError.substring(0, MAX_SERVER_ERROR_LEN);
                                    strBody += "&" + strServerError;
                                }
                                else if (src != null && src.m_strServerError != null && src.m_strServerError.length() > 0)                              
                                {
                                    if ( src.m_strServerError.length() > MAX_SERVER_ERROR_LEN )
                                        src.m_strServerError = src.m_strServerError.substring(0, MAX_SERVER_ERROR_LEN);	
                                    strBody += "&" + src.m_strServerError;	                }						    
				                }
				        
		                    if ( src != null )
		                        strBody += makeCreateObjectErrorBody( src.getID());
			            }
			            else
			        	    strBody += "in_progress";
			        
			            strBody += "&rho_callback=1";
			            if ( pSN.m_strParams != null && pSN.m_strParams.length() > 0 )
			            {
			        	    if ( !pSN.m_strParams.startsWith("&") )
			        		    strBody += "&";
			        	
			        	    strBody += pSN.m_strParams;
			            }			        	
			        
			            bRemoveAfterFire = bRemoveAfterFire && pSN.m_bRemoveAfterFire;
		            }
		        }
		        if ( bRemoveAfterFire )
		    	    clearNotification(src);
		    
		        LOG.INFO("Fire notification. Source : " + (src != null ? (src).getName():"") + "; " + pSN.ToString());
		    
                if ( callNotify(pSN, strBody) )
                    clearNotification(src);
		    }catch(Exception exc)
		    {
			    LOG.ERROR("Fire notification failed.", exc);
		    }
	    }
Example #23
0
	    void clearNotification(SyncSource src)
	    {
		    LOG.INFO( "Clear notification. Source : " + (src != null ? src.getName() : "" ) );

	        lock(m_mxSyncNotifications)
	        {
	    	    if ( getSync().isSearch() )
	                m_pSearchNotification = null;
	            else
	                m_mapSyncNotifications.remove(src.getID());
	        }
	    }
Example #24
0
        public void doSearch(Vector <String> arSources, String strParams, String strAction, boolean bSearchSyncChanges, int nProgressStep)
        {
            try
            {
                prepareSync(esSearch, null);
                if (!isContinueSync())
                {
                    if (getState() != esExit)
                    {
                        setState(esNone);
                    }

                    return;
                }

                TimeInterval startTime = TimeInterval.getCurrentTime();

                if (bSearchSyncChanges)
                {
                    for (int i = 0; i < (int)arSources.size(); i++)
                    {
                        SyncSource pSrc = findSourceByName((String)arSources.elementAt(i));
                        if (pSrc != null)
                        {
                            pSrc.syncClientChanges();
                        }
                    }
                }

                while (isContinueSync())
                {
                    int    nSearchCount = 0;
                    String strUrl       = getProtocol().getServerQueryUrl(strAction);
                    String strQuery     = getProtocol().getServerQueryBody("", getClientID(), getSyncPageSize());

                    if (strParams.length() > 0)
                    {
                        strQuery += strParams;
                    }

                    String strTestResp = "";
                    for (int i = 0; i < (int)arSources.size(); i++)
                    {
                        SyncSource pSrc = findSourceByName((String)arSources.elementAt(i));
                        if (pSrc != null)
                        {
                            strQuery += "&sources[][name]=" + pSrc.getName();

                            if (!pSrc.isTokenFromDB() && pSrc.getToken() > 1)
                            {
                                strQuery += "&sources[][token]=" + pSrc.getToken();
                            }

                            strTestResp = getSourceOptions().getProperty(pSrc.getID(), "rho_server_response");
                        }
                    }

                    LOG.INFO("Call search on server. Url: " + (strUrl + strQuery));
                    NetResponse resp = getNet().pullData(strUrl + strQuery, this);

                    if (!resp.isOK())
                    {
                        stopSync();
                        m_nErrCode = RhoAppAdapter.getErrorFromResponse(resp);
                        m_strError = resp.getCharData();
                        continue;
                    }

                    String szData = null;
                    if (strTestResp != null && strTestResp.length() > 0)
                    {
                        szData = strTestResp;
                    }
                    else
                    {
                        szData = resp.getCharData();
                    }

                    JSONArrayIterator oJsonArr = new JSONArrayIterator(szData);

                    for ( ; !oJsonArr.isEnd() && isContinueSync(); oJsonArr.next())
                    {
                        JSONArrayIterator oSrcArr = oJsonArr.getCurArrayIter();        //new JSONArrayIterator(oJsonArr.getCurItem());
                        if (oSrcArr.isEnd())
                        {
                            break;
                        }

                        int nVersion = 0;
                        if (!oSrcArr.isEnd() && oSrcArr.getCurItem().hasName("version"))
                        {
                            nVersion = oSrcArr.getCurItem().getInt("version");
                            oSrcArr.next();
                        }

                        if (nVersion != getProtocol().getVersion())
                        {
                            LOG.ERROR("Sync server send search data with incompatible version. Client version: " + getProtocol().getVersion() +
                                      "; Server response version: " + nVersion);
                            stopSync();
                            m_nErrCode = RhoAppAdapter.ERR_SYNCVERSION;
                            continue;
                        }

                        if (!oSrcArr.isEnd() && oSrcArr.getCurItem().hasName("token"))
                        {
                            oSrcArr.next();
                        }

                        if (!oSrcArr.getCurItem().hasName("source"))
                        {
                            LOG.ERROR("Sync server send search data without source name.");
                            stopSync();
                            m_nErrCode = RhoAppAdapter.ERR_UNEXPECTEDSERVERRESPONSE;
                            m_strError = szData;
                            continue;
                        }

                        String     strSrcName = oSrcArr.getCurItem().getString("source");
                        SyncSource pSrc       = findSourceByName(strSrcName);
                        if (pSrc == null)
                        {
                            LOG.ERROR("Sync server send search data for unknown source name:" + strSrcName);
                            stopSync();
                            m_nErrCode = RhoAppAdapter.ERR_UNEXPECTEDSERVERRESPONSE;
                            m_strError = szData;
                            continue;
                        }

                        oSrcArr.reset(0);
                        pSrc.setProgressStep(nProgressStep);
                        pSrc.processServerResponse_ver3(oSrcArr);

                        nSearchCount += pSrc.getCurPageCount();

                        if (pSrc.getServerError().length() > 0)
                        {
                            if (m_strServerError.length() > 0)
                            {
                                m_strServerError += "&";
                            }

                            m_strServerError += pSrc.getServerError();
                            m_nErrCode        = pSrc.getErrorCode();
                        }
                    }

                    if (nSearchCount == 0)
                    {
                        for (int i = 0; i < (int)arSources.size(); i++)
                        {
                            SyncSource pSrc = findSourceByName((String)arSources.elementAt(i));
                            if (pSrc != null)
                            {
                                pSrc.processToken(0);
                            }
                        }
                        break;
                    }
                }

                getNotify().fireAllSyncNotifications(true, m_nErrCode, m_strError, m_strServerError);

                //update db info
                TimeInterval endTime = TimeInterval.getCurrentTime();
                //unsigned long timeUpdated = CLocalTime().toULong();
                for (int i = 0; i < (int)arSources.size(); i++)
                {
                    SyncSource oSrc = findSourceByName((String)arSources.elementAt(i));
                    if (oSrc == null)
                    {
                        continue;
                    }
                    oSrc.getDB().executeSQL("UPDATE sources set last_updated=?,last_inserted_size=?,last_deleted_size=?, " +
                                            "last_sync_duration=?,last_sync_success=?, backend_refresh_time=? WHERE source_id=?",
                                            endTime.toULong() / 1000, oSrc.getInsertedCount(), oSrc.getDeletedCount(),
                                            endTime.minus(startTime).toULong(), oSrc.getGetAtLeastOnePage()?1:0,
                                            oSrc.getRefreshTime(), oSrc.getID());
                }
                //

                getNotify().cleanCreateObjectErrors();
                if (getState() != esExit)
                {
                    setState(esNone);
                }
            } catch (Exception exc) {
                LOG.ERROR("Search failed.", exc);

                getNotify().fireAllSyncNotifications(true, RhoAppAdapter.ERR_RUNTIME, "", "");
            }
        }