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

📄 syncmanager.java

📁 SyncML的java实现类库 funambol公司发布的
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            if(statusList.size() > 0 || mappings.size() > 0) {
                
                String mapMsg = prepareMappingMessage();
                
                Log.info("Sending Mappings\n");
                Log.debug(mapMsg);
                
                response = postRequest(mapMsg);
                mapMsg = null;
                
                Log.info("response received");
                Log.debug(response);
                
                //source.dataReceived(
                //    transportAgent.getResponseDate(), response.length());
                
                // Check server response (can throws exception to the caller)
                checkStatus(new ChunkedString(response), SyncML.TAG_SYNCHDR );
                response = null;
                
                Log.info("Mapping session succesfully completed");
                
            } else {
                Log.info("No mapping message to send");
                
            }
            
            
            // Set the last anchor to the next timestamp for the source
            source.setLastAnchor(source.getNextAnchor());
            // Tell the source that the sync is finished
            source.endSync();
            
        } finally {
            // Release resources
            this.mappings = null;
            this.statusList = null;
            
            this.source = null;
            this.sessionID = null;
            this.serverUrl = null;
            
        }
        
    }
    
    /**
     * 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;
    }
    
    //---------------------------------------------------------- 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,
                                    "User not authorized: " + config.userName
                                    + " for source: " + source.getSourceUri());
                        case SyncMLStatus.NOT_FOUND:                    // 404
                            throw new SyncException(
                                    SyncException.ACCESS_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());
                        default:
                            // Unhandled status code
                            //source.setLastAnchor(0l);
                            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
     * serverAlerts
     * <p>If this is the first sync for the source, the status code might change
     * according to the value of the PARAM_FIRST_TIME_SYNC_MODE configuration
     * property
     * <p>If firstTimeSyncMode is not set, the alert is left unchanged. If it is
     * set to a value, the specified value is used instead
     *
     * @param msg The message to be checked
     *
     * @throws SyncException In case of errors
     **/
    private void checkServerAlerts(ChunkedString msg) throws SyncException {
        ChunkedString target = null;
        ChunkedString code = null;
        Vector alertTags = null;
        
        serverAlerts = new Hashtable();
        
        try {
            alertTags = XmlUtil.getTagValues(
                    XmlUtil.getTagValues(
                    XmlUtil.getTagValues(
                    msg,
                    SyncML.TAG_SYNCML),
                    SyncML.TAG_SYNCBODY),
                    SyncML.TAG_ALERT);
            
            for (int i=0, l = alertTags.size(); i < l; i++) {
                ChunkedString alert = (ChunkedString)alertTags.elementAt(i);
                code = XmlUtil.getTagValue(alert, SyncML.TAG_DATA);
                Vector items = XmlUtil.getTagValues(alert, SyncML.TAG_ITEM);
                
                for (int j=0, m = items.size(); j < m; j++) {
                    ChunkedString targetTag = (ChunkedString)items.elementAt(j);
                    target = XmlUtil.getTagValue(targetTag, SyncML.TAG_TARGET);
                    
                    target = XmlUtil.getTagValue(target, SyncML.TAG_LOC_URI);
                    Log.info("The server alert code for "+target+" is "+code);
                    serverAlerts.put(target.toString(), code.toString());
                }
            }
        } catch (XmlException xe) {
            Log.error("checkServerAlerts: error parsing server alert " + msg);
            xe.printStackTrace();
            throw new SyncException(
                    SyncException.SERVER_ERROR,
                    "Invalid alert from server.");
        }
    }
    
    /**
     * Prepare a SyncML Message header.
     *
     * @param sessionid the session id to use.
     * @param msgid the message id to use.
     * @param src the source uri
     * @param tgt the target uri
     * @param tags other SyncML tags to insert in the header.
     *             (e.g. &lt;Cred&gt; or &lt;Meta&gt;).
     */
    private String prepareSyncHeader(String sessionid,
            String msgid,
            String src,
            String tgt,
            String tags) {
        
        StringBuffer ret = new StringBuffer();
        
        ret.append("<SyncHdr>\n")
        .append("<VerDTD>1.2</VerDTD>\n")
        .append("<VerProto>SyncML/1.2</VerProto>\n")
        .append("<SessionID>").append(sessionid).append("</SessionID>\n")
        .append("<MsgID>").append(msgid).append("</MsgID>\n")
        .append("<Target><LocURI>").append(tgt).append("</LocURI></Target>\n")
        .append("<Source><LocURI>").append(src).append("</LocURI></Source>\n");
        
        if(tags != null) {
            ret.append(tags);
        }
        
        ret.append("</SyncHdr>\n");
        
        return ret.toString();
    }
    
    /**
     * Prepares inizialization SyncML message
     */
    private String prepareInizializationMessage(int syncMode)
    throws SyncException {
        
        
        String b64login = new String(Base64.encode(login.getBytes()));
        
        StringBuffer ret = new StringBuffer("<SyncML>\n");
        
        // Add <Cred> and <Meta> to the syncHdr
        StringBuffer tags = new StringBuffer("<Cred>\n");
        tags.append("<Meta>")
        .append("<Type xmlns=\"syncml:metinf\">syncml:auth-basic</Type>\n")
        .append("<Format xmlns=\"syncml:metinf\">b64</Format>\n")
        .append("</Meta>\n")
        .append("<Data>").append(b64login).append("</Data>")
        .append("</Cred>\n");
        // Meta for the maxmsgsize
        tags.append("<Meta><MaxMsgSize>")
        .append(maxMsgSize)
        .append("</MaxMsgSize></Meta>\n");
        
        // Add SyncHdr
        ret.append( prepareSyncHeader(sessionID, resetMsgID(),
                deviceId, serverUrl,
                tags.toString()) );
        // Add SyncBody
        ret.append("<SyncBody>\n")
        .append(createAlerts(source, syncMode));
        
        // Add DevInf
        if (sendDevInf) {
            ret.append(createPut(config.deviceConfig));
        }
        
        ret.append("<Final/>")
        .append("</SyncBody>\n");
        
        ret.append("</SyncML>\n");
        
        tags = null;
        
        return ret.toString();
    }
    
    
    /**
     * Process the &lt;Format&gt; tag and return the requested modification
     * in a String array.
     */
    private String[] processFormat(ChunkedString xml) {
        String[] ret = null;
        
        try {
            if (XmlUtil.getTag(xml, "Format") != -1) {
                ChunkedString format = XmlUtil.getTagValue(xml, "Format");

⌨️ 快捷键说明

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