All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bdware.doip.dbrepo.DBRepoHandler Maven / Gradle / Ivy

There is a newer version: 1.5.4
Show newest version
package org.bdware.doip.dbrepo;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mysql.cj.jdbc.result.ResultSetMetaData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.RocksDBUtil;
import org.bdware.doip.audit.client.AuditIrpClient;
import org.bdware.doip.codec.digitalObject.DigitalObject;
import org.bdware.doip.codec.digitalObject.DoType;
import org.bdware.doip.codec.digitalObject.Element;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.codec.doipMessage.DoipMessageFactory;
import org.bdware.doip.codec.doipMessage.DoipResponseCode;
import org.bdware.doip.endpoint.server.RepositoryHandler;
import org.bdware.irp.exception.IrpClientException;
import org.bdware.irp.stateinfo.StateInfoBase;

import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class DBRepoHandler implements RepositoryHandler {
    private static final Logger LOGGER = LogManager.getLogger(DBRepoHandler.class);
    AuditIrpClient irpClient;
    public String repoId;
    RocksDBUtil doTable = RocksDBUtil.loadDB("./doTable", false);

    public DBRepoHandler(AuditIrpClient irpClient, String repoId) {
        this.irpClient = irpClient;
        this.repoId = repoId;
    }


    private DoipMessage returnFailed(DoipMessage msg) {
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        DoipMessage ret = builder.createResponse(DoipResponseCode.Invalid, msg).create();
        ret.body.encodedData = "Failed!!!".getBytes(StandardCharsets.UTF_8);
        return ret;
    }

    @Override
    public DoipMessage handleHello(DoipMessage doipMessage) {
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        DoipMessage ret = builder.createResponse(DoipResponseCode.Invalid, doipMessage).create();
        ret.body.encodedData = "Hello".getBytes(StandardCharsets.UTF_8);
        return ret;
    }

    @Override
    public DoipMessage handleListOps(DoipMessage doipMessage) {
        return (doipMessage);
    }

    @Override
    public DoipMessage handleCreate(DoipMessage doipMessage) {
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        try {
            JsonObject attr = doipMessage.body.getDataAsDigitalObject().attributes;
            String url = attr.get("url").getAsString();
            if (!url.contains("//"))
                url = "jdbc:mysql://" + url;
            if (!url.startsWith("jdbc:mysql://")) {
                DoipMessage ret = builder.createResponse(DoipResponseCode.Invalid, doipMessage).create();
                ret.body.encodedData = "unsupported db type".getBytes(StandardCharsets.UTF_8);
                return ret;
            }
            String tableName = attr.get("tableName").getAsString();
            String userName = attr.get("userName").getAsString();
            String password = attr.get("password").getAsString();
            String doid = createSQL(url, tableName, userName, password);
            DoipMessage ret = builder.createResponse(DoipResponseCode.Success, doipMessage).create();
            ret.header.parameters.id = doid;
            return ret;
        } catch (Exception e) {
            e.printStackTrace();
            DoipMessage ret = builder.createResponse(DoipResponseCode.Invalid, doipMessage).create();
            ret.body.encodedData = e.getMessage().getBytes(StandardCharsets.UTF_8);
            return ret;
        }
    }

    Map connectionMap = new HashMap<>();

    public Connection getOrCreate(String doid) {
        if (connectionMap.containsKey(doid)) {
            Connection connection = connectionMap.get(doid);
            try {
                if (connection != null && connection.isValid(5)) {
                    return connection;
                } else return createConn(doid);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                return createConn(doid);
            }
        } else {
            return createConn(doid);
        }
    }

    Map urlToConnectionCache = new ConcurrentHashMap<>();

    private Connection createConn(String doid) {
        try {
            connectionMap.remove(doid);
            JsonObject jo = JsonParser.parseString(doTable.get(doid)).getAsJsonObject();
            Connection connection = getFromUrlCache(jo);
            // 打开链接
            connectionMap.put(doid, connection);
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private Connection getFromUrlCache(JsonObject jo) {
        try {
            String url = jo.get("url").getAsString();
            if (urlToConnectionCache.containsKey(url)) {
                Connection c = urlToConnectionCache.get(url);
                if (c.isValid(5)) {
                    return c;
                }
            }
            String tableName = jo.get("tableName").getAsString();
            String usrName = jo.get("usrName").getAsString();
            String password = jo.get("password").getAsString();
            Class.forName("com.mysql.cj.jdbc.Driver");
            Properties prop = new Properties();
            prop.put("user", usrName);
            prop.put("password", password);
            Connection connection = DriverManager.getConnection(url, prop);

            urlToConnectionCache.put(url, connection);

            return connection;
        } catch (Exception e) {
            return null;
        }
    }

    public String createSQL(String url, String tableName, String usrName, String password) {
        //检查前缀是不是repo自身id,后缀是要获取的对应do
        StateInfoBase base = new StateInfoBase();
        base.handleValues = new JsonObject();
        base.handleValues.addProperty("repoId", repoId);
        base.handleValues.addProperty("createTime", System.currentTimeMillis());
        base.handleValues.addProperty("tableName", tableName);
        JsonObject connInfo = new JsonObject();
        connInfo.addProperty("url", url);
        connInfo.addProperty("tableName", tableName);
        connInfo.addProperty("usrName", usrName);
        connInfo.addProperty("password", password);
        String ret = null;
        try {
            ret = irpClient.register(base);
            doTable.put(ret, connInfo.toString());
        } catch (IrpClientException e) {
            e.printStackTrace();
        }

        return ret;
    }


    @Override
    public DoipMessage handleUpdate(DoipMessage doipMessage) {
        return (doipMessage);
    }

    @Override
    public DoipMessage handleDelete(DoipMessage doipMessage) {
        return (doipMessage);
    }

    @Override
    public DoipMessage handleRetrieve(DoipMessage doipMessage) {
        Connection connection = getOrCreate(doipMessage.header.parameters.id);
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        if (connection == null) {
            builder.createResponse(DoipResponseCode.DoNotFound, doipMessage);
            return builder.create();
        }
        int offset = doipMessage.header.parameters.attributes.get("offset").getAsInt();
        int count = doipMessage.header.parameters.attributes.get("count").getAsInt();
        if (count > 1024) {
            builder.createResponse(DoipResponseCode.Declined, doipMessage);
            builder.setBody("count too large! count<=1024".getBytes(StandardCharsets.UTF_8));
            return builder.create();
        }
        JsonObject jo = JsonParser.parseString(doTable.get(doipMessage.header.parameters.id)).getAsJsonObject();
        try {
            String tableName = jo.get("tableName").getAsString();
            JsonArray result = new JsonArray();
            Statement stmt = connection.createStatement();
            String sql;
            // 数据库数据示例
            List dataList = new ArrayList<>();
            sql = "SELECT * FROM " + tableName + " LIMIT " + count + " OFFSET " + offset;
            // sql = "SELECT * FROM " + tablename;// + " LIMIT 10 OFFSET 0";
            ResultSet rs = stmt.executeQuery(sql);
            ResultSetMetaData rsmd = (ResultSetMetaData) rs.getMetaData();
            // {"data|3":["no":'@string',"subject":'@string',"core|60-100":1}],"status":"success"}
            int size = rsmd.getColumnCount();
            while (rs.next()) {
                JsonObject rowData = new JsonObject();
                for (int i = 0; i < size; i++) {
                    int type = rsmd.getColumnType(i + 1);
                    if (type == -6 || type == 5 || type == 4) {
                        rowData.addProperty(rsmd.getColumnName(i + 1), rs.getInt(i + 1));
                    } else if (type == -5) {
                        rowData.addProperty(rsmd.getColumnName(i + 1), rs.getLong(i + 1));
                    } else if (type == 6 || type == 7 || type == 8) {
                        rowData.addProperty(rsmd.getColumnName(i + 1), rs.getDouble(i + 1));
                    } else {
                        rowData.addProperty(rsmd.getColumnName(i + 1), rs.getString(i + 1));
                    }
                }
                result.add(rowData);
            }
            rs.close();
            stmt.close();
            builder.createResponse(DoipResponseCode.Success, doipMessage);
            DigitalObject digitalObject = new DigitalObject(doipMessage.header.parameters.id, DoType.DO);
            Element element = new Element(doipMessage.header.parameters.id, "json");
            element.setData(result.toString().getBytes(StandardCharsets.UTF_8));
            digitalObject.addElements(element);
            builder.setBody(digitalObject);
            return builder.create();
        } catch (Exception e) {
            e.printStackTrace();
            builder.createResponse(DoipResponseCode.Declined, doipMessage);
            builder.setBody(e.getMessage().getBytes(StandardCharsets.UTF_8));
            return builder.create();
        }
    }
}