ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

dcs-sdk-java-master/app/src/main/java/com/baidu/duer/dcs/framework/dispatcher/MultipartParser.java

Committer:
TMBOY
Date:
2017-07-18
Revision:
45:2aa9f933c8d2

File content as of revision 45:2aa9f933c8d2:

/*
 * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.baidu.duer.dcs.framework.dispatcher;

import com.baidu.duer.dcs.framework.message.DcsResponseBody;
import com.baidu.duer.dcs.http.HttpConfig;

import org.apache.commons.fileupload.MultipartStream;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

import okhttp3.Response;

/**
 * 把从服务器返回multipart中json对象和二进制解析成directive对象
 * <p>
 * Created by wuruisheng on 2017/5/12.
 */
public class MultipartParser extends Parser {
    private static final int BUFFER_SIZE = 512;
    private final IMultipartParserListener multipartParserListener;

    public MultipartParser(IMultipartParserListener listener) {
        this.multipartParserListener = listener;
    }

    public void parseResponse(Response response) throws IOException {
        String boundary = getBoundary(response);
        if (boundary != null) {
            parseStream(response.body().byteStream(), boundary);
        }
    }

    private void parseStream(InputStream inputStream, String boundary) throws IOException {
        MultipartStream multipartStream = new MultipartStream(inputStream, boundary.getBytes(), BUFFER_SIZE, null);
        parseMultipartStream(multipartStream);
    }

    private void parseMultipartStream(MultipartStream multipartStream) throws IOException {
        try {
            Boolean hasNextPart = multipartStream.skipPreamble();
            while (hasNextPart) {
                handlePart(multipartStream);
                hasNextPart = multipartStream.readBoundary();
            }
        } catch (DcsJsonProcessingException exception) {
            if (multipartParserListener != null) {
                multipartParserListener.onParseFailed(exception.getUnparsedCotent());
            }
        } catch (MultipartStream.MalformedStreamException exception) {
            // 用于处理 empty part
        }
    }

    private void handlePart(MultipartStream multipartStream) throws IOException {
        Map<String, String> headers = getPartHeaders(multipartStream);
        if (headers != null) {
            byte[] partBytes = getPartBytes(multipartStream);
            Boolean isJsonData = isPartJSON(headers);
            if (isJsonData) {
                handleJsonData(partBytes);
            } else {
                handleAudio(headers, partBytes);
            }
        }
    }

    private void handleJsonData(byte[] partBytes) throws IOException {
        final DcsResponseBody responseBody = parse(partBytes, DcsResponseBody.class);
        if (multipartParserListener != null) {
            multipartParserListener.onResponseBody(responseBody);
        }
    }

    private void handleAudio(Map<String, String> headers, byte[] partBytes) {
        String contentId = getMultipartContentId(headers);
        final AudioData audioData = new AudioData(contentId, partBytes);
        if (multipartParserListener != null) {
            multipartParserListener.onAudioData(audioData);
        }
    }

    private byte[] getPartBytes(MultipartStream multipartStream) throws IOException {
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        multipartStream.readBodyData(data);
        return data.toByteArray();
    }

    private Map<String, String> getPartHeaders(MultipartStream multipartStream) throws IOException {
        String headers = multipartStream.readHeaders();
        BufferedReader reader = new BufferedReader(new StringReader(headers));
        Map<String, String> headerMap = new HashMap<>();
        try {
            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
                line = line.trim();
                if (!StringUtils.isBlank(line) && line.contains(":")) {
                    int colon = line.indexOf(":");
                    String headerName = line.substring(0, colon).trim();
                    String headerValue = line.substring(colon + 1).trim();
                    headerMap.put(headerName.toLowerCase(), headerValue);
                }
            }
        } catch (Exception e) {
            throw e;
        }

        return headerMap;
    }

    private String getMultipartHeaderValue(Map<String, String> headers, String searchHeader) {
        return headers.get(searchHeader.toLowerCase());
    }

    private String getMultipartContentId(Map<String, String> headers) {
        String contentId = getMultipartHeaderValue(headers, HttpConfig.HttpHeaders.CONTENT_ID);
        contentId = contentId.substring(1, contentId.length() - 1);
        return contentId;
    }

    private boolean isPartJSON(Map<String, String> headers) {
        String contentType = getMultipartHeaderValue(headers, HttpConfig.HttpHeaders.CONTENT_TYPE);
        return StringUtils.contains(contentType, HttpConfig.ContentTypes.JSON);
    }

    private static String getBoundary(Response response) {
        String headerValue = response.header(HttpConfig.HttpHeaders.CONTENT_TYPE);
        String boundary = getHeaderParameter(headerValue, HttpConfig.Parameters.BOUNDARY);
        return boundary;
    }

    private static String getHeaderParameter(final String headerValue, final String key) {
        if ((headerValue == null) || (key == null)) {
            return null;
        }

        String[] parts = headerValue.split(";");
        for (String part : parts) {
            part = part.trim();
            if (part.startsWith(key)) {
                return part.substring(key.length() + 1).replaceAll("(^\")|(\"$)", "").trim();
            }
        }

        return null;
    }

    public interface IMultipartParserListener {
        void onResponseBody(DcsResponseBody responseBody);

        void onAudioData(AudioData audioData);

        void onParseFailed(String unParseMessage);
    }
}