hd3gtv.embddb.network.DataBlock.java Source code

Java tutorial

Introduction

Here is the source code for hd3gtv.embddb.network.DataBlock.java

Source

/*
 * This file is part of MyDMAM.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * 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 Lesser General Public License for more details.
 * 
 * Copyright (C) hdsdi3g for hd3g.tv 21 nov. 2016
 * 
*/
package hd3gtv.embddb.network;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import hd3gtv.tools.Hexview;

public final class DataBlock {

    private static final Logger log = Logger.getLogger(DataBlock.class);

    private ArrayList<RequestEntry> entries;
    private String request_name;

    /**
     * Create mode
     */
    public DataBlock(String request_name) {
        entries = new ArrayList<>();
        this.request_name = request_name;
        if (request_name == null) {
            throw new NullPointerException("\"request_name\" can't to be null");
        }
    }

    /**
     * Import mode
     */
    DataBlock(Protocol protocol, byte[] request_raw_datas) throws IOException {
        if (log.isTraceEnabled()) {
            log.trace("Get raw datas" + Hexview.LINESEPARATOR + Hexview.tracelog(request_raw_datas));
        }

        ByteArrayInputStream inputstream_client_request = new ByteArrayInputStream(request_raw_datas);

        DataInputStream dis = new DataInputStream(inputstream_client_request);

        byte[] app_socket_header_tag = new byte[Protocol.APP_SOCKET_HEADER_TAG.length];
        dis.readFully(app_socket_header_tag, 0, Protocol.APP_SOCKET_HEADER_TAG.length);

        if (Arrays.equals(Protocol.APP_SOCKET_HEADER_TAG, app_socket_header_tag) == false) {
            throw new IOException("Protocol error with app_socket_header_tag");
        }

        int version = dis.readInt();
        if (version != Protocol.VERSION) {
            throw new IOException(
                    "Protocol error with version, this = " + Protocol.VERSION + " and dest = " + version);
        }

        byte tag = dis.readByte();
        if (tag != 0) {
            throw new IOException("Protocol error, can't found request_name raw datas");
        }

        int size = dis.readInt();
        if (size < 1) {
            throw new IOException(
                    "Protocol error, can't found request_name raw datas size is too short (" + size + ")");
        }

        byte[] request_name_raw = new byte[size];
        dis.read(request_name_raw);
        request_name = new String(request_name_raw, Protocol.UTF8);

        tag = dis.readByte();
        if (tag != 1) {
            throw new IOException("Protocol error, can't found zip raw datas");
        }

        entries = new ArrayList<>(1);

        ZipInputStream request_zip = new ZipInputStream(dis);

        ZipEntry entry;
        while ((entry = request_zip.getNextEntry()) != null) {
            entries.add(new RequestEntry(entry, request_zip));
        }
        request_zip.close();
    }

    public void checkIfNotEmpty() {
        if (entries.isEmpty()) {
            throw new IndexOutOfBoundsException("No data entries in block");
        }
    }

    byte[] getBytes(Protocol protocol) throws IOException {
        checkIfNotEmpty();

        ByteArrayOutputStream byte_array_out_stream = new ByteArrayOutputStream(Protocol.BUFFER_SIZE);

        DataOutputStream dos = new DataOutputStream(byte_array_out_stream);
        dos.write(Protocol.APP_SOCKET_HEADER_TAG);
        dos.writeInt(Protocol.VERSION);

        /**
         * Start header name
         */
        dos.writeByte(0);
        byte[] request_name_data = request_name.getBytes(Protocol.UTF8);
        dos.writeInt(request_name_data.length);
        dos.write(request_name_data);

        /**
         * Start datas payload
         */
        dos.writeByte(1);

        /**
         * Get datas from zip
         */
        ZipOutputStream zos = new ZipOutputStream(dos);
        zos.setLevel(3);
        entries.forEach(entry -> {
            try {
                entry.toZip(zos);
            } catch (IOException e) {
                log.error("Can't add to zip", e);
            }
        });
        zos.flush();
        zos.finish();
        zos.close();

        dos.flush();
        dos.close();

        byte[] result = byte_array_out_stream.toByteArray();

        if (log.isTraceEnabled()) {
            log.trace("Make raw datas for " + request_name + Hexview.LINESEPARATOR + Hexview.tracelog(result));
        }

        return result;
    }

    public synchronized DataBlock createEntry(String name, byte[] datas) {
        entries.add(new RequestEntry(name, datas, System.currentTimeMillis()));
        return this;
    }

    public synchronized DataBlock createEntry(String name, String datas) {
        entries.add(new RequestEntry(name, datas.getBytes(Protocol.UTF8), System.currentTimeMillis()));

        if (log.isTraceEnabled()) {
            log.trace("Add string datas to block " + name + " \"" + datas + "\"");
        }
        return this;
    }

    public String getRequestName() {
        return request_name;
    }

    public Stream<RequestEntry> getEntries() {
        return entries.stream();
    }

    public int getSize() {
        return entries.size();
    }

    public RequestEntry getByName(String name) throws IOException {
        Optional<RequestEntry> o_entry = entries.stream().filter(entry -> {
            return entry.getName().equalsIgnoreCase(name);
        }).findFirst();

        if (o_entry.isPresent()) {
            return o_entry.get();
        }
        throw new IOException("Can't found " + name + " in entries names from " + request_name + " request");
    }

    public boolean hasName(String name) {
        return entries.stream().anyMatch(entry -> {
            return entry.getName().equalsIgnoreCase(name);
        });
    }

    public String toString() {
        AtomicInteger all_size = new AtomicInteger(0);
        entries.forEach(block -> {
            all_size.addAndGet(block.getLen());
        });

        if (entries.size() == 1) {
            return request_name + " (" + all_size.get() + " bytes in 1 item)";
        } else {
            return request_name + " (" + all_size.get() + " bytes in " + entries.size() + " items)";
        }
    }

    public class RequestEntry {

        private String name;
        private byte[] datas;
        private long date;
        private int len;

        private RequestEntry(String name, byte[] datas, long date) {
            this.name = name;
            if (name == null) {
                throw new NullPointerException("\"name\" can't to be null");
            }
            this.datas = datas;
            if (datas == null) {
                throw new NullPointerException("\"datas\" can't to be null");
            }
            this.date = date;
            len = datas.length;
        }

        private RequestEntry(ZipEntry entry, ZipInputStream zipdatas) throws IOException {
            ByteArrayOutputStream bias = new ByteArrayOutputStream(Protocol.BUFFER_SIZE);
            IOUtils.copy(zipdatas, bias);

            datas = bias.toByteArray();
            len = datas.length;
            date = entry.getTime();
            name = entry.getName();

            if (log.isTraceEnabled()) {
                log.trace("Get datas from zip: \"" + name + "\"" + Hexview.LINESEPARATOR
                        + Hexview.tracelog(datas, 0, len));
            }
        }

        public byte[] getDatas() {
            return datas;
        }

        public long getDate() {
            return date;
        }

        public int getLen() {
            return len;
        }

        public String getName() {
            return name;
        }

        public String getDatasAsString() {
            return new String(datas, 0, len, Protocol.UTF8);
        }

        private void toZip(ZipOutputStream zipdatas) throws IOException {
            if (log.isTraceEnabled()) {
                log.trace("Add entry to Zip: \"" + name + "\"" + Hexview.LINESEPARATOR
                        + Hexview.tracelog(datas, 0, len));
            }

            ZipEntry entry = new ZipEntry(name);
            entry.setTime(date);
            // entry.setSize(len);
            zipdatas.putNextEntry(entry);
            zipdatas.write(datas, 0, len);
            zipdatas.flush();
            zipdatas.closeEntry();
        }

    }

}