⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syncmanager.java

📁 j2me java syncml moblie
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            } catch (XmlException xe) {
                Log.error("Error parsing RespURI from server " + xe.toString());
                throw new SyncException(
                        SyncException.SERVER_ERROR,
                        "Cannot find the Response URI in server response.");
            }

            chunkedResp = null;

            response = null;


            // ================================================================
            // Sync phase
            // ================================================================
                    
            // init mapping table
            this.mappings = new Hashtable();
            // init status commands list
            this.statusList = new Vector();

            // Notifies that the synchronization is going to begin

            boolean ok = listener.startSyncing(alertCode);

            if (!ok) {
                //User Aborts the slow sync request
                Log.info("[SyncManager] Sync process aborted by the user");
                return;
            }


            source.beginSync(alertCode);
            listener.syncStarted(alertCode);

            boolean done = false;

            // the implementation of the client/server multi-messaging
            // through a do while loop: while </final> tag is reached.
            do {
                listener.startSending(source.getClientAddNumber(),
                        source.getClientReplaceNumber(),
                        source.getClientDeleteNumber());
                String modificationsMsg = prepareModificationMessage();
                Log.info("Sending modification");
                Log.debug(modificationsMsg);

                response = postRequest(modificationsMsg);
                
                modificationsMsg = null;

                Log.info("response received");
                Log.debug(response);
                listener.endSending();

                //listener.dataReceived(transportAgent.getResponseDate(),
                //                      response.length());

                // The startReceiving(n) is notified from within the
                // processModifications because here we do not know the number
                // of messages to be received
                processModifications(new ChunkedString(response));

                done = ((response.indexOf("<Final/>") >= 0) ||
                        (response.indexOf("</Final>") >= 0));

                response = null;

                listener.endReceiving();
                

            } while (!done);

            Log.info("Modification session succesfully completed");
            listener.endSyncing();

            // ================================================================
            // Mapping phase
            // ================================================================

            listener.startMapping();
            
            // Send the map message only if a mapping or a status has to be sent
            if (statusList.size() > 0 || mappings.size() > 0) {
                String mapMsg = prepareMappingMessage();
                
                Log.info("Sending Mappings\n");
                Log.debug(mapMsg);

                try {
                    response = postRequest(mapMsg);
                } catch (ReadResponseException rre) {
                    source.setLastAnchor(source.getNextAnchor());
                    //save last anchors if the mapping message has been sent but
                    //the response has not been received due to network problems
                    Log.info("[SyncManager] Last sync message sent - Error reading the response " + rre);
                }
                
                mapMsg = null;

                if (response!=null) {
                    Log.info("response received");
                    Log.debug(response);

                    //listener.dataReceived(
                    //      transportAgent.getResponseDate(), response.length());

                    // Check server response (can throws exception to the caller)
                    checkStatus(new ChunkedString(response), SyncML.TAG_SYNCHDR);

                    response = null;
                } else {
                    Log.info("Response not received");
                    Log.info("Skipping check for status");
                    
                }

                Log.info("Mapping session succesfully completed");

            } else {
                Log.info("No mapping message to send");

            }
            
            // TODO: following code must be run only for succesfull path or error reading inputstream
            //       the other cases must skip the following code
            Log.debug("Notifying listener end mapping");
            listener.endMapping();

            Log.debug("Changing anchors");
            // Set the last anchor to the next timestamp for the source
            source.setLastAnchor(source.getNextAnchor());
            
            Log.debug("source endSsync method call");
            // Tell the source that the sync is finished
            source.endSync();

        } catch (CompressedSyncException compressedSyncException) {
            Log.error("[SyncManager] CompressedSyncException: " + compressedSyncException);
            //releaseResources();
            throw compressedSyncException;
        } finally {
            // Notifies the listener that the session is over
            Log.debug("Ending session");
            listener.endSession(source.getStatus());
            releaseResources();
        }

    }

    private void releaseResources() {
        // Release resources
        this.mappings = null;
        this.statusList = null;

        this.source = null;
        this.sessionID = null;
        this.serverUrl = null;

        this.busy = false;
    }

    /**
     * To be invoked by every change of the device configuration and if the
     * serverUrl is a new one (i.e., not already on the list
     * <code>lastServerUrl</code>
     */
    public void setFlagSendDevInf() {
        sendDevInf = true;
    }

    public boolean isBusy() {
        return busy;
    }

    //---------------------------------------------------------- Private methods
    /**
     * Checks if the current server URL is the same as by the last connection.
     * If not, the current server URL is persisted in a record store on the
     * device
     *
     * @param url
     *            The server URL coming from the SyncConfig
     * @return true if the client wasn't ever connected to the corresponding
     *         server, false elsewhere
     */
    private boolean isNewServerUrl(String url) {

        //retrieve last server URL from the configuration
        lastServerUrl = config.lastServerUrl;

        if (StringUtil.equalsIgnoreCase(lastServerUrl, url)) {
            // the server url is the same as by the last connection, the client
            // may not send the device capabilities
            return false;
        } else {
            // the server url is new, the value has to be stored (this is let to
            // the SyncmlMPIConfig, while the SyncConfig isn't currently stored)
            return true;//the url is different, client can send the device info
        }
    }

    /**
     * Posts the given message to the url specified by <code>serverUrl</code>.
     *
     * @param request the request msg
     * @return the response of the server as a string
     *
     * @throws SyncException in case of network errors (thrown by sendMessage)
     */
    private String postRequest(String request) throws SyncException {
        transportAgent.setRequestURL(serverUrl);
        return transportAgent.sendMessage(request);
    }

    /**
     * TODO: check CHAL element in the 401 status returned.
     */
    private boolean checkMD5(String msg) {
        return false;
    }

    /**
     * Checks if the given response message is authenticated by the server
     *
     * @param msg the message to be checked
     * @param statusOf the command of which we want to check the status
     *
     * @throws SyncException in case of other errors
     */
    private void checkStatus(ChunkedString msg, String statusOf)
            throws SyncException {

        Vector statusTags = null;
        try {
            statusTags = XmlUtil.getTagValues(
                    XmlUtil.getTagValues(
                    XmlUtil.getTagValues(msg, SyncML.TAG_SYNCML),
                    SyncML.TAG_SYNCBODY),
                    SyncML.TAG_STATUS);
        } catch (XmlException xe) {
            xe.printStackTrace();
            Log.error("checkStatus: error parsing server status " + msg);
            return;
        }


        for (int i = 0,  l = statusTags.size(); i < l; i++) {
            ChunkedString tag = (ChunkedString) statusTags.elementAt(i);
            // Parse the status
            SyncMLStatus status = SyncMLStatus.parse(tag);

            if (status != null) {
                // Consider only that status for the requested command
                if (statusOf.equals(status.getCmd())) {
                    switch (status.getStatus()) {

                        case SyncMLStatus.SUCCESS:                      // 200
                            return;
                        case SyncMLStatus.REFRESH_REQUIRED:             // 508
                            Log.info("Refresh required by server.");
                            return;
                        case SyncMLStatus.AUTHENTICATION_ACCEPTED:      // 212
                            Log.info("Authentication accepted by the server.");
                            return;
                        case SyncMLStatus.INVALID_CREDENTIALS:          // 401
                            // TODO: handle MD5 authentication.
                            if (checkMD5(msg.toString())) {
                                Log.error("MD5 authentication not supported");
                                throw new SyncException(
                                        SyncException.AUTH_ERROR,
                                        "MD5 authentication not supported");
                            } else {
                                Log.error("Invalid credentials: " + config.userName);

                                throw new SyncException(
                                        SyncException.AUTH_ERROR,
                                        "Authentication failed for: " + source.getSourceUri());
                            }
                        case SyncMLStatus.FORBIDDEN:                    // 403
                            throw new SyncException(
                                    //SyncException.AUTH_ERROR,
                                    SyncException.FORBIDDEN_ERROR,
                                    "User not authorized: " + config.userName + " for source: " + source.getSourceUri());
                        case SyncMLStatus.NOT_FOUND:                    // 404
                            Log.error(this, "Source URI not found on server: " + source.getSourceUri());
                            throw new SyncException(
                                    //SyncException.ACCESS_ERROR,
                                    SyncException.NOT_FOUND_URI_ERROR,
                                    "Source URI not found on server: " + source.getSourceUri());
                        case SyncMLStatus.SERVER_BUSY:                  // 503
                            throw new SyncException(
                                    SyncException.SERVER_BUSY,
                                    "Server busy, another sync in progress for " + source.getSourceUri());
                        case SyncMLStatus.PROCESSING_ERROR:             // 506
                            throw new SyncException(
                                    SyncException.BACKEND_ERROR,
                                    "Error processing source: " + source.getSourceUri() + status.getStatusDataMessage());
                        case SyncMLStatus.BACKEND_AUTH_ERROR:             // 506
                            throw new SyncException(
                                    SyncException.BACKEND_AUTH_ERROR,
                                    "Error processing source: " + source.getSourceUri() + status.getStatusDataMessage());
                        default:
                            // Unhandled status code
                            Log.debug("[SyncManger] Unhandled Status Code, throwing exception");
                            throw new SyncException(
                                    SyncException.SERVER_ERROR,
                                    "Error from server: " + status.getStatus());
                    }
                }
            }

        }

        // Should neven happen
        Log.error("checkStatus: can't find Status in " + statusOf + " in server response");
        throw new SyncException(
                SyncException.SERVER_ERROR,
                "Status Tag for " + statusOf + " not found in server response");
    }

    /**
     * <p>Checks response status for the synchronized databases and saves their

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -