nya.miku.wishmaster.http.ExtendedMultipartBuilder.java Source code

Java tutorial

Introduction

Here is the source code for nya.miku.wishmaster.http.ExtendedMultipartBuilder.java

Source

/*
 * Overchan Android (Meta Imageboard Client)
 * Copyright (C) 2014-2015  miku-nyan <https://github.com/miku-nyan>
 *     
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package nya.miku.wishmaster.http;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Random;

import nya.miku.wishmaster.api.interfaces.CancellableTask;
import nya.miku.wishmaster.api.interfaces.ProgressListener;
import nya.miku.wishmaster.common.IOUtils;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;

/**
 *   Multipart HttpEntity.
 * ? ?  ?? ,   .
 * - ?? boundary ( , ? ? ?, ? ??? ?  ).
 * @author miku-nyan
 *
 */

/* Google  ? ??  ?  org.apache.http  "deprecated"  API 22 (Android 5.1)
 * ? ?  ??? ? ?? apache-hc httpclient 4.3.5.1-android
 * ?: https://issues.apache.org/jira/browse/HTTPCLIENT-1632 */
@SuppressWarnings("deprecation")

public class ExtendedMultipartBuilder {
    private static final int RANDOMHASH_TAIL_SIZE = 6;

    private static Random random = new Random();

    private static Random getRandom() {
        if (random == null)
            random = new Random();
        return random;
    }

    private final MultipartEntityBuilder builder;
    private ProgressListener listener = null;
    private CancellableTask task = null;

    public ExtendedMultipartBuilder() {
        builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
                .setBoundary(generateBoundary());
    }

    public static ExtendedMultipartBuilder create() {
        return new ExtendedMultipartBuilder();
    }

    public ExtendedMultipartBuilder setCharset(Charset charset) {
        builder.setCharset(charset);
        return this;
    }

    public ExtendedMultipartBuilder addPart(String key, ContentBody body) {
        builder.addPart(key, body);
        return this;
    }

    /**
     *  ?   UTF-8
     * @param key ? ()
     * @param value ?
     * @return ? 
     */
    public ExtendedMultipartBuilder addString(String key, String value) {
        return addPart(key, new StringBody(value, ContentType.create("text/plain", "UTF-8")));
    }

    private ExtendedMultipartBuilder addFile(String key, File value, final int randomTail) {
        return addPart(key, new FileBody(value) {
            @Override
            public long getContentLength() {
                return super.getContentLength() + randomTail;
            }

            @Override
            public void writeTo(OutputStream out) throws IOException {
                super.writeTo(out);
                if (randomTail > 0) {
                    byte[] buf = new byte[randomTail];
                    getRandom().nextBytes(buf);
                    out.write(buf);
                }
            }
        });
    }

    /**
     *  
     * @param key ? ()
     * @param file ? 
     * @param uniqueHash ? true,     ?  ,  ?  ?
     * @return ? 
     */
    public ExtendedMultipartBuilder addFile(String key, File file, boolean uniqueHash) {
        return addFile(key, file, uniqueHash ? RANDOMHASH_TAIL_SIZE : 0);
    }

    /**
     *  
     * @param key ? ()
     * @param file ? 
     * @return ? 
     */
    public ExtendedMultipartBuilder addFile(String key, File file) {
        return addFile(key, file, false);
    }

    /**
     * ? ? ??  ? 
     * @param listener ? ?? ??
     * @param task ,    
     * @return ? 
     */
    public ExtendedMultipartBuilder setDelegates(ProgressListener listener, CancellableTask task) {
        this.listener = listener;
        this.task = task;
        return this;
    }

    public HttpEntity build() {
        return new HttpEntityWrapper(builder.build(), listener, task);
    }

    protected String generateBoundary() {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 27; ++i)
            stringBuilder.append("-");
        int length = 26 + getRandom().nextInt(4);
        for (int i = 0; i < length; ++i)
            stringBuilder.append(Integer.toString(getRandom().nextInt(10)));
        return stringBuilder.toString();
    }

    private static class HttpEntityWrapper implements HttpEntity {

        private final HttpEntity entity;
        private final ProgressListener listener;
        private final CancellableTask task;

        private HttpEntityWrapper(HttpEntity entity, ProgressListener listener, CancellableTask task) {
            this.entity = entity;
            this.listener = listener;
            this.task = task;
        }

        @Override
        public void consumeContent() throws IOException {
            entity.consumeContent();
        }

        @Override
        public InputStream getContent() throws IOException, IllegalStateException {
            return entity.getContent();
        }

        @Override
        public Header getContentEncoding() {
            return entity.getContentEncoding();
        }

        @Override
        public long getContentLength() {
            return entity.getContentLength();
        }

        @Override
        public Header getContentType() {
            return entity.getContentType();
        }

        @Override
        public boolean isChunked() {
            return entity.isChunked();
        }

        @Override
        public boolean isRepeatable() {
            return entity.isRepeatable();
        }

        @Override
        public boolean isStreaming() {
            return entity.isStreaming();
        }

        @Override
        public void writeTo(OutputStream outstream) throws IOException {
            if (listener != null)
                listener.setMaxValue(this.getContentLength());
            entity.writeTo(IOUtils.modifyOutputStream(outstream, listener, task));
            if (listener != null)
                listener.setIndeterminate();
        }

    }

}