org.sfs.nodes.compute.account.GetAccount.java Source code

Java tutorial

Introduction

Here is the source code for org.sfs.nodes.compute.account.GetAccount.java

Source

/*
 * Copyright 2016 The Simple File Server Authors
 *
 * 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 org.sfs.nodes.compute.account;

import com.google.common.net.MediaType;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.logging.Logger;
import org.sfs.SfsRequest;
import org.sfs.auth.Authenticate;
import org.sfs.elasticsearch.account.ListContainers;
import org.sfs.elasticsearch.account.LoadAccount;
import org.sfs.io.AsyncIO;
import org.sfs.io.BufferOutputStream;
import org.sfs.metadata.Metadata;
import org.sfs.rx.ConnectionCloseTerminus;
import org.sfs.validate.ValidateAccountPath;
import org.sfs.validate.ValidateActionAuthenticated;
import org.sfs.validate.ValidatePersistentAccountExists;
import org.sfs.vo.Account;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.SortedSet;

import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Ordering.from;
import static com.google.common.net.HttpHeaders.ACCEPT;
import static com.google.common.net.HttpHeaders.CONTENT_LENGTH;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static com.google.common.net.MediaType.APPLICATION_XML_UTF_8;
import static com.google.common.net.MediaType.JSON_UTF_8;
import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8;
import static com.google.common.net.MediaType.parse;
import static io.vertx.core.buffer.Buffer.buffer;
import static io.vertx.core.logging.LoggerFactory.getLogger;
import static java.lang.String.format;
import static java.lang.String.valueOf;
import static java.math.BigDecimal.ROUND_HALF_UP;
import static java.net.HttpURLConnection.HTTP_OK;
import static javax.xml.stream.XMLOutputFactory.newFactory;
import static org.sfs.rx.Defer.aVoid;
import static org.sfs.util.NullSafeAscii.equalsIgnoreCase;
import static org.sfs.util.SfsHttpHeaders.X_ACCOUNT_BYTES_USED;
import static org.sfs.util.SfsHttpHeaders.X_ACCOUNT_CONTAINER_COUNT;
import static org.sfs.util.SfsHttpHeaders.X_ACCOUNT_OBJECT_COUNT;
import static org.sfs.util.SfsHttpHeaders.X_ADD_ACCOUNT_META_PREFIX;
import static org.sfs.util.SfsHttpQueryParams.FORMAT;
import static org.sfs.vo.ContainerList.SparseContainer;
import static org.sfs.vo.ObjectPath.fromPaths;
import static org.sfs.vo.ObjectPath.fromSfsRequest;

public class GetAccount implements Handler<SfsRequest> {

    private static final Logger LOGGER = getLogger(GetAccount.class);

    @Override
    public void handle(final SfsRequest httpServerRequest) {

        aVoid().flatMap(new Authenticate(httpServerRequest))
                .flatMap(new ValidateActionAuthenticated(httpServerRequest))
                .map(aVoid -> fromSfsRequest(httpServerRequest)).map(new ValidateAccountPath())
                .map(objectPath -> objectPath.accountPath().get())
                .flatMap(new LoadAccount(httpServerRequest.vertxContext()))
                .map(new ValidatePersistentAccountExists()).flatMap(new ListContainers(httpServerRequest))
                .flatMap(containerList -> {
                    HttpServerResponse httpServerResponse = httpServerRequest.response();
                    MultiMap headerParams = httpServerRequest.headers();
                    MultiMap queryParams = httpServerRequest.params();
                    String format = queryParams.get(FORMAT);

                    String accept = headerParams.get(ACCEPT);

                    Account account = containerList.getAccount();

                    Metadata metadata = account.getMetadata();

                    for (String key : metadata.keySet()) {
                        SortedSet<String> values = metadata.get(key);
                        if (values != null && !values.isEmpty()) {
                            httpServerResponse.putHeader(format("%s%s", X_ADD_ACCOUNT_META_PREFIX, key), values);
                        }
                    }

                    httpServerResponse.putHeader(X_ACCOUNT_OBJECT_COUNT, valueOf(containerList.getObjectCount()));
                    httpServerResponse.putHeader(X_ACCOUNT_CONTAINER_COUNT,
                            valueOf(containerList.getContainerCount()));
                    httpServerResponse.putHeader(X_ACCOUNT_BYTES_USED,
                            BigDecimal.valueOf(containerList.getBytesUsed()).setScale(0, ROUND_HALF_UP).toString());

                    MediaType parsedAccept = null;
                    if (!isNullOrEmpty(accept)) {
                        parsedAccept = parse(accept);
                    }

                    if (equalsIgnoreCase("xml", format)) {
                        parsedAccept = APPLICATION_XML_UTF_8;
                    } else if (equalsIgnoreCase("json", format)) {
                        parsedAccept = JSON_UTF_8;
                    }

                    httpServerResponse.setStatusCode(HTTP_OK);

                    if (parsedAccept != null && JSON_UTF_8.is(parsedAccept)) {
                        String charset = UTF_8.toString();

                        JsonArray array = new JsonArray();

                        for (SparseContainer container : ordered(containerList.getContainers())) {

                            array.add(new JsonObject().put("name", container.getContainerName())
                                    .put("count", container.getObjectCount())
                                    .put("bytes", BigDecimal.valueOf(container.getByteCount())
                                            .setScale(0, ROUND_HALF_UP).longValue()));

                        }

                        Buffer buffer = buffer(array.encode(), charset);
                        httpServerResponse = httpServerResponse.putHeader(CONTENT_TYPE, JSON_UTF_8.toString());
                        httpServerResponse = httpServerResponse.putHeader(CONTENT_LENGTH, valueOf(buffer.length()));
                        return AsyncIO.append(buffer, httpServerResponse);

                    } else if (parsedAccept != null && APPLICATION_XML_UTF_8.is(parsedAccept)) {

                        BufferOutputStream bufferOutputStream = new BufferOutputStream();
                        String charset = UTF_8.toString();
                        XMLStreamWriter writer = null;
                        try {
                            writer = newFactory().createXMLStreamWriter(bufferOutputStream, charset);

                            writer.writeStartDocument(charset, "1.0");

                            writer.writeStartElement("account");

                            writer.writeAttribute("name", fromPaths(account.getId()).accountName().get());

                            for (SparseContainer container : ordered(containerList.getContainers())) {

                                writer.writeStartElement("container");

                                writer.writeStartElement("name");
                                writer.writeCharacters(container.getContainerName());
                                writer.writeEndElement();

                                writer.writeStartElement("count");
                                writer.writeCharacters(valueOf(container.getObjectCount()));
                                writer.writeEndElement();

                                writer.writeStartElement("bytes");
                                writer.writeCharacters(BigDecimal.valueOf(container.getByteCount())
                                        .setScale(0, ROUND_HALF_UP).toString());
                                writer.writeEndElement();

                                writer.writeEndElement();
                            }

                            writer.writeEndElement();

                            writer.writeEndDocument();

                        } catch (XMLStreamException e) {
                            throw new RuntimeException(e);
                        } finally {
                            try {
                                if (writer != null) {
                                    writer.close();
                                }
                            } catch (XMLStreamException e) {
                                LOGGER.warn(e.getLocalizedMessage(), e);
                            }
                        }

                        Buffer buffer = bufferOutputStream.toBuffer();
                        httpServerResponse = httpServerResponse.putHeader(CONTENT_TYPE,
                                APPLICATION_XML_UTF_8.toString());
                        httpServerResponse = httpServerResponse.putHeader(CONTENT_LENGTH, valueOf(buffer.length()));
                        return AsyncIO.append(buffer, httpServerResponse);

                    } else {
                        String charset = UTF_8.toString();
                        Buffer buffer = buffer();
                        for (SparseContainer container : ordered(containerList.getContainers())) {
                            buffer.appendString(container.getContainerName(), charset);
                            buffer.appendString("\n", charset);
                        }
                        httpServerResponse = httpServerResponse.putHeader(CONTENT_TYPE,
                                PLAIN_TEXT_UTF_8.toString());
                        httpServerResponse = httpServerResponse.putHeader(CONTENT_LENGTH, valueOf(buffer.length()));
                        return AsyncIO.append(buffer, httpServerResponse);
                    }
                }).single().subscribe(new ConnectionCloseTerminus<Void>(httpServerRequest) {

                    @Override
                    public void onNext(Void aVoid) {

                    }

                });

    }

    protected Iterable<SparseContainer> ordered(Iterable<SparseContainer> iterable) {
        return from(new Comparator<SparseContainer>() {
            @Override
            public int compare(SparseContainer o1, SparseContainer o2) {
                return o1.getContainerName().compareTo(o2.getContainerName());
            }
        }).sortedCopy(iterable);
    }
}