jp.realglobe.util.uploader.DirectoryUploader.java Source code

Java tutorial

Introduction

Here is the source code for jp.realglobe.util.uploader.DirectoryUploader.java

Source

/*----------------------------------------------------------------------
 * Copyright 2017 realglobe Inc.
 *
 * 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 jp.realglobe.util.uploader;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Logger;

import org.apache.commons.io.FilenameUtils;
import org.apache.http.HttpException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

/**
 * ??
 */
public class DirectoryUploader implements Runnable {

    private static final Logger LOG = Logger.getLogger(DirectoryUploader.class.getName());

    static final int BUFFER_SIZE = 4096;

    // ?
    private final Path watchDirectoryPath;
    // ?
    private final long delay;
    // ???????
    private final boolean latestOnly;
    // ??
    private final Set<String> targetExtensions;
    // ??
    private final long minSize;
    // ?
    private final long maxSize;
    // ???? ID
    private final String userId;
    // ? ID
    private final String id;
    // ???
    private final String name;
    // ?????? URL
    private final URI tokenUrl;
    // ???? URL
    private final URI uploadUrl;
    // ???
    private final Store store;
    // ?
    private final String token;

    /**
     * ??
     * @param watchDirectoryPath ??
     * @param delay ?????
     *            ??????????
     * @param latestOnly ????????
     * @param targetExtensions ??
     * @param minSize ???
     * @param maxSize ??
     * @param urlBase ?? URL
     * @param userId ???? ID
     * @param name ??
     * @param id ? ID
     * @param token ?
     * @throws URISyntaxException URL ?????
     * @throws MalformedURLException URL ????
     */
    public DirectoryUploader(final Path watchDirectoryPath, final long delay, final boolean latestOnly,
            final Collection<String> targetExtensions, final long minSize, final long maxSize, final String urlBase,
            final String userId, final String name, final String id, final String token)
            throws MalformedURLException, URISyntaxException {
        this.watchDirectoryPath = watchDirectoryPath;
        this.delay = delay;
        this.latestOnly = latestOnly;
        this.targetExtensions = (targetExtensions == null ? Collections.emptySet()
                : new HashSet<>(targetExtensions));
        this.minSize = minSize;
        this.maxSize = maxSize;
        this.userId = userId;
        this.id = id;
        this.name = name;
        this.tokenUrl = null;
        this.uploadUrl = (new URL(
                urlBase + Constants.URL_PATH_UPLOAD_PREFIX + "/" + this.id + Constants.URL_PATH_UPLOAD_SUFFIX))
                        .toURI();
        this.store = null;
        this.token = token;

        LOG.info("ID is " + this.id);
    }

    /**
     * ??
     * @param watchDirectoryPath ??
     * @param delay ?????
     *            ??????????
     * @param latestOnly ????????
     * @param targetExtensions ??
     * @param minSize ???
     * @param maxSize ??
     * @param urlBase ?? URL
     * @param userId ???? ID
     * @param name ??
     * @param store ???
     * @throws Exception ???
     */
    public DirectoryUploader(final Path watchDirectoryPath, final long delay, final boolean latestOnly,
            final Collection<String> targetExtensions, final long minSize, final long maxSize, final String urlBase,
            final String userId, final String name, final Store store) throws Exception {
        this.watchDirectoryPath = watchDirectoryPath;
        this.delay = delay;
        this.latestOnly = latestOnly;
        this.targetExtensions = (targetExtensions == null ? Collections.emptySet()
                : new HashSet<>(targetExtensions));
        this.minSize = minSize;
        this.maxSize = maxSize;
        this.userId = userId;
        this.id = getId(store);
        this.name = name;
        this.tokenUrl = (new URL(urlBase + Constants.URL_PATH_TOKEN)).toURI();
        this.uploadUrl = (new URL(
                urlBase + Constants.URL_PATH_UPLOAD_PREFIX + "/" + this.id + Constants.URL_PATH_UPLOAD_SUFFIX))
                        .toURI();
        this.store = store;
        this.token = null;

        LOG.info("ID is " + this.id);
    }

    String getId() {
        return this.id;
    }

    /**
     * ID ?
     * @param store ???
     * @return ID
     * @throws Exception ???
     */
    private static String getId(final Store store) throws Exception {
        final String loadedId = store.load(Constants.STORE_KEY_ID);
        if (loadedId != null) {
            return loadedId;
        }
        final String newId = UUID.randomUUID().toString();
        store.store(Constants.STORE_KEY_ID, newId);
        return newId;
    }

    @Override
    public void run() {
        final String token1;
        if (this.token != null) {
            token1 = this.token;
        } else {
            try {
                token1 = getToken();
            } catch (final InterruptedException e) {
                // 
                return;
            } catch (final Exception e) {
                throw new RuntimeException(e);
            }
        }

        LOG.info("Use token " + token1);

        (new DelayedWatcher(this.watchDirectoryPath, this.delay, this.latestOnly, path -> {
            if (!Files.isReadable(path)) {
                LOG.info("Cannot read " + path);
                return;
            }
            final File file = path.toFile();
            if (!this.targetExtensions.isEmpty()
                    && !this.targetExtensions.contains(FilenameUtils.getExtension(file.getName()))) {
                LOG.info("Skip non target file " + path);
                return;
            } else if (this.minSize > 0 && file.length() < this.minSize) {
                LOG.info("Skip too small file " + path);
                return;
            } else if (this.maxSize > 0 && file.length() > this.maxSize) {
                LOG.info("Skip too large file " + path);
                return;
            }
            upload(token1, path);
        })).run();
    }

    /**
     * ??
     * ????
     * @return ?
     * @throws Exception ???
     */
    private String getToken() throws Exception {
        final String localToken = this.store.load(Constants.STORE_KEY_TOKEN);
        if (localToken != null) {
            if (isValidToken(localToken)) {
                return localToken;
            }
            this.store.clear(Constants.STORE_KEY_TOKEN);
        }
        final String token1 = getRemoteToken();
        if (token1 == null) {
            throw new RuntimeException("Cannot get token");
        }
        this.store.store(Constants.STORE_KEY_TOKEN, token1);
        return token1;
    }

    /**
     * ???????
     * @param token ??
     * @return ? true
     */
    private boolean isValidToken(final String token1) {
        // TODO ???????
        LOG.info("Token check is not implemented");
        return true;
    }

    /**
     * ????
     * @return 
     * @throws IOException ?
     */
    private String getRemoteToken() throws IOException {
        try (CloseableHttpClient client = HttpClients.createDefault()) {

            final HttpPost post = new HttpPost(this.tokenUrl);
            post.setEntity(new StringEntity((new TokenRequestBody(this.userId, this.id, this.name)).toJson(),
                    ContentType.APPLICATION_JSON));

            try (CloseableHttpResponse response = client.execute(post)) {
                if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_CREATED) {
                    return TokenResponseBody.parse(Utils.readAll(response.getEntity().getContent())).getToken();
                }

                LOG.warning(response.toString());
                LOG.info("Retrying request is not implemented");
                return null;
            }
        }
    }

    /**
     * ?
     * @param token1 ?
     * @param path ??
     * @throws IOException ????????
     * @throws HttpException HTTP 
     */
    private void upload(final String token1, final Path path) throws HttpException, IOException {
        try (CloseableHttpClient client = HttpClients.createDefault()) {

            final HttpPost post = new HttpPost(this.uploadUrl);
            post.setEntity(MultipartEntityBuilder.create().addTextBody("info", "{}")
                    .addTextBody(Constants.UPLOAD_REQUEST_PART_TOKEN, token1)
                    .addBinaryBody(Constants.UPLOAD_REQUEST_PART_DATA, path.toFile()).build());

            LOG.info("Upload " + path);

            try (CloseableHttpResponse response = client.execute(post)) {
                if (response.getStatusLine().getStatusCode() == HttpURLConnection.HTTP_CREATED) {
                    return;
                }

                LOG.warning(response.toString());
            }
        }
    }

    /**
     * ???
     * @throws Exception ???
     */
    public void prepareToken() throws Exception {
        getToken();
    }

}