Package com.groupon.odo.proxylib

Source Code of com.groupon.odo.proxylib.ClientService

/*
Copyright 2014 Groupon, 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 com.groupon.odo.proxylib;

import com.groupon.odo.proxylib.models.Client;
import com.groupon.odo.proxylib.models.Profile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class ClientService {

    private static final Logger logger = LoggerFactory.getLogger(ClientService.class);
    private static SQLService sqlService = null;
    private static ClientService serviceInstance = null;

    public ClientService() {

    }

    public static ClientService getInstance() {
        if (serviceInstance == null) {
            serviceInstance = new ClientService();
            try {
                sqlService = SQLService.getInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return serviceInstance;
    }

    /**
     * Return all Clients for a profile
     *
     * @param profileId
     * @return
     * @throws Exception
     */
    public List<Client> findAllClients(int profileId) throws Exception {
        ArrayList<Client> clients = new ArrayList<Client>();

        PreparedStatement query = null;
        ResultSet results = null;

        try (Connection sqlConnection = sqlService.getConnection()) {
            query = sqlConnection.prepareStatement(
                    "SELECT * FROM " + Constants.DB_TABLE_CLIENT +
                            " WHERE " + Constants.GENERIC_PROFILE_ID + " = ?"
            );
            query.setInt(1, profileId);
            results = query.executeQuery();
            while (results.next()) {
                clients.add(this.getClientFromResultSet(results));
            }
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (results != null) results.close();
            } catch (Exception e) {
            }
            try {
                if (query != null) query.close();
            } catch (Exception e) {
            }
        }
        return clients;
    }

    /**
     * Returns a client object for a clientId
     *
     * @param clientId
     * @return
     * @throws Exception
     */
    public Client getClient(int clientId) throws Exception {
        Client client = null;

        PreparedStatement statement = null;
        ResultSet results = null;
        try (Connection sqlConnection = sqlService.getConnection()) {
            String queryString = "SELECT * FROM " + Constants.DB_TABLE_CLIENT +
                    " WHERE " + Constants.GENERIC_ID + " = ?";

            statement = sqlConnection.prepareStatement(queryString);
            statement.setInt(1, clientId);

            results = statement.executeQuery();
            if (results.next()) {
                client = this.getClientFromResultSet(results);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (results != null) results.close();
            } catch (Exception e) {
            }
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        return client;
    }

    /**
     * Returns a Client object for a clientUUID and profileId
     *
     * @param clientUUID
     * @param profileId  - can be null, safer if it is not null
     * @return client object
     * @throws Exception
     */
    public Client findClient(String clientUUID, Integer profileId) throws Exception {
        Client client = null;

        // first see if the clientUUID is actually a uuid.. it might be a friendlyName and need conversion
        if (clientUUID.compareTo(Constants.PROFILE_CLIENT_DEFAULT_ID) != 0 &&
                !clientUUID.matches("[\\w]{8}-[\\w]{4}-[\\w]{4}-[\\w]{4}-[\\w]{12}")) {
            Client tmpClient = this.findClientFromFriendlyName(profileId, clientUUID);

            // if we can't find a client then fall back to the default ID
            if (tmpClient == null) {
                clientUUID = Constants.PROFILE_CLIENT_DEFAULT_ID;
            } else {
                return tmpClient;
            }
        }

        PreparedStatement statement = null;
        ResultSet results = null;
        try (Connection sqlConnection = sqlService.getConnection()) {
            String queryString = "SELECT * FROM " + Constants.DB_TABLE_CLIENT +
                    " WHERE " + Constants.CLIENT_CLIENT_UUID + " = ?";

            if (profileId != null) {
                queryString += " AND " + Constants.GENERIC_PROFILE_ID + "=?";
            }

            statement = sqlConnection.prepareStatement(queryString);
            statement.setString(1, clientUUID);

            if (profileId != null)
                statement.setInt(2, profileId);

            results = statement.executeQuery();
            if (results.next()) {
                client = this.getClientFromResultSet(results);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (results != null) results.close();
            } catch (Exception e) {
            }
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        return client;
    }

    /**
     * Returns a client model from a ResultSet
     *
     * @param result
     * @return
     * @throws Exception
     */
    private Client getClientFromResultSet(ResultSet result) throws Exception {
        Client client = new Client();
        client.setId(result.getInt(Constants.GENERIC_ID));
        client.setUUID(result.getString(Constants.CLIENT_CLIENT_UUID));
        client.setFriendlyName(result.getString(Constants.CLIENT_FRIENDLY_NAME));
        client.setProfile(ProfileService.getInstance().findProfile(result.getInt(Constants.GENERIC_PROFILE_ID)));
        client.setIsActive(result.getBoolean(Constants.CLIENT_IS_ACTIVE));
        client.setActiveServerGroup(result.getInt(Constants.CLIENT_ACTIVESERVERGROUP));
        return client;
    }

    private String getUniqueClientUUID() {
        String curClientUUID = UUID.randomUUID().toString();
        PreparedStatement statement = null;
        ResultSet results = null;

        try (Connection sqlConnection = sqlService.getConnection()) {
            while (true) {
                statement = sqlConnection.prepareStatement("SELECT * FROM " + Constants.DB_TABLE_CLIENT +
                        " WHERE " + Constants.GENERIC_CLIENT_UUID + " = ?");
                statement.setString(1, curClientUUID);
                results = statement.executeQuery();
                if (results.next()) {
                    curClientUUID = UUID.randomUUID().toString();
                } else {
                    break;
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (results != null) results.close();
            } catch (Exception e) {
            }
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }
        logger.info("ClientUUID of new client = {}", curClientUUID);
        return curClientUUID;
    }

    /**
     * Create a new client for profile
     * There is a limit of Constants.CLIENT_CLIENTS_PER_PROFILE_LIMIT
     * If this limit is reached an exception is thrown back to the caller
     *
     * @param profileId
     * @return
     * @throws Exception
     */
    public Client add(int profileId) throws Exception {
        Client client = null;
        ArrayList<Integer> pathsToCopy = new ArrayList<Integer>();
        String clientUUID = getUniqueClientUUID();

        // get profile for profileId
        Profile profile = ProfileService.getInstance().findProfile(profileId);
        PreparedStatement statement = null;
        ResultSet rs = null;

        try (Connection sqlConnection = sqlService.getConnection()) {
           
            // get the current count of clients
            statement = sqlConnection.prepareStatement("SELECT COUNT(" + Constants.GENERIC_ID + ") FROM " +
                                  Constants.DB_TABLE_CLIENT + " WHERE " + Constants.GENERIC_PROFILE_ID + "=?");
            statement.setInt(1, profileId);
            int clientCount = -1;
            rs = statement.executeQuery();
            if (rs.next()) {
              clientCount = rs.getInt(1);
            }
            statement.close();
            rs.close();

            // check count
            if (clientCount == -1) {
              throw new Exception("Error querying clients for profileId=" + profileId);
            }
            if (clientCount >= Constants.CLIENT_CLIENTS_PER_PROFILE_LIMIT) {
              throw new Exception("Profile(" + profileId + ") already contains 50 clients.  Please remove clients before adding new ones.");
            }
           
            statement = sqlConnection.prepareStatement(
                    "INSERT INTO " + Constants.DB_TABLE_CLIENT +
                            " (" + Constants.CLIENT_CLIENT_UUID + ", " +
                            Constants.CLIENT_IS_ACTIVE + ", " +
                            Constants.CLIENT_PROFILE_ID + ")" +
                            " VALUES (?, ?, ?)", Statement.RETURN_GENERATED_KEYS
            );
            statement.setString(1, clientUUID);
            statement.setBoolean(2, false);
            statement.setInt(3, profile.getId());
            statement.executeUpdate();
            rs = statement.getGeneratedKeys();
            int clientId = -1;
            if (rs.next()) {
                clientId = rs.getInt(1);
            } else {
                // something went wrong
                throw new Exception("Could not add client");
            }
            rs.close();
            statement.close();

            // adding entries into request response table for this new client for every path
            // basically a copy of what happens when a path gets created
            statement = sqlConnection.prepareStatement(
                    "SELECT * FROM " + Constants.DB_TABLE_REQUEST_RESPONSE +
                            " WHERE " + Constants.GENERIC_PROFILE_ID + " = ?" +
                            " AND " + Constants.GENERIC_CLIENT_UUID + " = ?"
            );
            statement.setInt(1, profile.getId());
            statement.setString(2, Constants.PROFILE_CLIENT_DEFAULT_ID);
            rs = statement.executeQuery();
            while (rs.next()) {
                // collect up the pathIds we need to copy
                pathsToCopy.add(rs.getInt(Constants.REQUEST_RESPONSE_PATH_ID));
            }
            client = new Client();
            client.setIsActive(false);
            client.setUUID(clientUUID);
            client.setId(clientId);
            client.setProfile(profile);
        } catch (SQLException e) {
            throw e;
        } finally {
            try {
                if (rs != null) rs.close();
            } catch (Exception e) {
            }
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        // add all of the request response items
        for (Integer pathId : pathsToCopy) {
            PathOverrideService.getInstance().addPathToRequestResponseTable(profile.getId(), client.getUUID(), pathId);
        }

        return client;
    }

    /**
     * Set a friendly name for a client
     *
     * @param profileId
     * @param clientUUID
     * @param friendlyName
     * @return
     * @throws Exception
     */
    public Client setFriendlyName(int profileId, String clientUUID, String friendlyName) throws Exception {
        // first see if this friendlyName is already in use
        Client client = this.findClientFromFriendlyName(profileId, friendlyName);
        if (client != null) {
            throw new Exception("Friendly name already in use");
        }

        PreparedStatement statement = null;
        int rowsAffected = 0;

        try (Connection sqlConnection = sqlService.getConnection()) {
            statement = sqlConnection.prepareStatement(
                    "UPDATE " + Constants.DB_TABLE_CLIENT +
                            " SET " + Constants.CLIENT_FRIENDLY_NAME + " = ?" +
                            " WHERE " + Constants.CLIENT_CLIENT_UUID + " = ?" +
                            " AND " + Constants.GENERIC_PROFILE_ID + " = ?"
            );
            statement.setString(1, friendlyName);
            statement.setString(2, clientUUID);
            statement.setInt(3, profileId);

            rowsAffected = statement.executeUpdate();
        } catch (Exception e) {

        } finally {
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        if (rowsAffected == 0) {
            return null;
        }
        return this.findClient(clientUUID, profileId);
    }

    /**
     * Get the client for a profileId/friendlyName
     *
     * @param profileId
     * @param friendlyName
     * @return Client or null
     * @throws Exception
     */
    public Client findClientFromFriendlyName(int profileId, String friendlyName) throws Exception {
        Client client = null;

        // Don't even try if the friendlyName is null/empty
        if (friendlyName == null || friendlyName.compareTo("") == 0) {
            return client;
        }

        PreparedStatement statement = null;
        ResultSet results = null;

        try (Connection sqlConnection = sqlService.getConnection()) {
            String queryString = "SELECT * FROM " + Constants.DB_TABLE_CLIENT +
                    " WHERE " + Constants.CLIENT_FRIENDLY_NAME + " = ?" +
                    " AND " + Constants.GENERIC_PROFILE_ID + " = ?";
            statement = sqlConnection.prepareStatement(queryString);
            statement.setString(1, friendlyName);
            statement.setInt(2, profileId);

            results = statement.executeQuery();
            if (results.next()) {
                client = this.getClientFromResultSet(results);
            }
        } catch (SQLException e) {
            throw e;
        } finally {
            try {
                if (results != null) results.close();
            } catch (Exception e) {
            }
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        return client;
    }

    /**
     * Removes a client from the database
     * Also clears all additional override information for the clientId
     *
     * @param profileId
     * @param clientUUID
     * @throws Exception
     */
    public void remove(int profileId, String clientUUID) throws Exception {
        PreparedStatement statement = null;
        ResultSet results = null;
        try (Connection sqlConnection = sqlService.getConnection()) {
            // first try selecting the row we want to deal with
            statement = sqlConnection.prepareStatement(
                    "SELECT * FROM " + Constants.DB_TABLE_CLIENT +
                            " WHERE " + Constants.GENERIC_CLIENT_UUID + " = ?" +
                            " AND " + Constants.CLIENT_PROFILE_ID + "= ?"
            );
            statement.setString(1, clientUUID);
            statement.setInt(2, profileId);
            results = statement.executeQuery();
            if (!results.next()) {
                throw new Exception("Could not find specified clientUUID: " + clientUUID);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (results != null) results.close();
            } catch (Exception e) {
            }
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        // delete from the client table
        String queryString = "DELETE FROM " + Constants.DB_TABLE_CLIENT +
                " WHERE " + Constants.CLIENT_CLIENT_UUID + " = ? " +
                " AND " + Constants.CLIENT_PROFILE_ID + " = ?";

        try (Connection sqlConnection = sqlService.getConnection()) {
            statement = sqlConnection.prepareStatement(queryString);
            statement.setString(1, clientUUID);
            statement.setInt(2, profileId);

            logger.info("Query: {}", statement.toString());
            statement.executeUpdate();
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }


        // delete from other tables as appropriate
        // need to delete from enabled_overrides and request_response
        try (Connection sqlConnection = sqlService.getConnection()) {
            statement = sqlConnection.prepareStatement(
                    "DELETE FROM " + Constants.DB_TABLE_REQUEST_RESPONSE +
                            " WHERE " + Constants.CLIENT_CLIENT_UUID + " = ? " +
                            " AND " + Constants.CLIENT_PROFILE_ID + " = ?"
            );
            statement.setString(1, clientUUID);
            statement.setInt(2, profileId);
            statement.executeUpdate();
        } catch (Exception e) {
            // ok to swallow this.. just means there wasn't any
        }

        try (Connection sqlConnection = sqlService.getConnection()) {
            statement = sqlConnection.prepareStatement(
                    "DELETE FROM " + Constants.DB_TABLE_ENABLED_OVERRIDE +
                            " WHERE " + Constants.CLIENT_CLIENT_UUID + " = ? " +
                            " AND " + Constants.CLIENT_PROFILE_ID + " = ?"
            );
            statement.setString(1, clientUUID);
            statement.setInt(2, profileId);
            statement.executeUpdate();
        } catch (Exception e) {
            // ok to swallow this.. just means there wasn't any
        } finally {
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }
    }

    /**
     * disables the current active id, enables the new one selected
     *
     * @param profileId
     * @param clientUUID
     * @param active
     * @throws Exception
     */
    public void updateActive(int profileId, String clientUUID, Boolean active) throws Exception {
        PreparedStatement statement = null;
        try (Connection sqlConnection = sqlService.getConnection()) {
            statement = sqlConnection.prepareStatement(
                    "UPDATE " + Constants.DB_TABLE_CLIENT +
                            " SET " + Constants.CLIENT_IS_ACTIVE + "= ?" +
                            " WHERE " + Constants.GENERIC_CLIENT_UUID + "= ? " +
                            " AND " + Constants.GENERIC_PROFILE_ID + "= ?"
            );
            statement.setBoolean(1, active);
            statement.setString(2, clientUUID);
            statement.setInt(3, profileId);
            statement.executeUpdate();
        } catch (Exception e) {
            // ok to swallow this.. just means there wasn't any
        } finally {
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }
    }

    /**
     * Resets all override settings for the clientUUID and disables it
     *
     * @param profileId
     * @param clientUUID
     * @throws Exception
     */
    public void reset(int profileId, String clientUUID) throws Exception {
        PreparedStatement statement = null;

        // TODO: need a better way to do this than brute force.. but the iterative approach is too slow
        try (Connection sqlConnection = sqlService.getConnection()) {

            // first remove all enabled overrides with this client uuid
            String queryString = "DELETE FROM " + Constants.DB_TABLE_ENABLED_OVERRIDE +
                    " WHERE " + Constants.GENERIC_CLIENT_UUID + "= ? " +
                    " AND " + Constants.GENERIC_PROFILE_ID + " = ?";
            statement = sqlConnection.prepareStatement(queryString);
            statement.setString(1, clientUUID);
            statement.setInt(2, profileId);
            statement.executeUpdate();
            statement.close();

            // clean up request response table for this uuid
            queryString = "UPDATE " + Constants.DB_TABLE_REQUEST_RESPONSE +
                    " SET " + Constants.REQUEST_RESPONSE_CUSTOM_REQUEST + "=?, "
                    + Constants.REQUEST_RESPONSE_CUSTOM_RESPONSE + "=?, "
                    + Constants.REQUEST_RESPONSE_REPEAT_NUMBER + "=-1, "
                    + Constants.REQUEST_RESPONSE_REQUEST_ENABLED + "=0, "
                    + Constants.REQUEST_RESPONSE_RESPONSE_ENABLED + "=0 "
                    + "WHERE " + Constants.GENERIC_CLIENT_UUID + "=? " +
                    " AND " + Constants.GENERIC_PROFILE_ID + "=?";
            statement = sqlConnection.prepareStatement(queryString);
            statement.setString(1, "");
            statement.setString(2, "");
            statement.setString(3, clientUUID);
            statement.setInt(4, profileId);
            statement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (statement != null) statement.close();
            } catch (Exception e) {
            }
        }

        this.updateActive(profileId, clientUUID, false);
    }

    public String getClientUUIDfromId(int id) {
        return (String) sqlService.getFromTable(Constants.CLIENT_CLIENT_UUID, Constants.GENERIC_ID, id, Constants.DB_TABLE_CLIENT);
    }

    public int getIdFromClientUUID(String uuid) {
        return (Integer) sqlService.getFromTable(Constants.GENERIC_ID, Constants.CLIENT_CLIENT_UUID, uuid, Constants.DB_TABLE_CLIENT);
    }

    //gets the profile_name associated with a specific id
    public String getProfileIdFromClientId(int id) {
        return (String) sqlService.getFromTable(Constants.CLIENT_PROFILE_ID, Constants.GENERIC_ID, id, Constants.DB_TABLE_CLIENT);
    }

}
TOP

Related Classes of com.groupon.odo.proxylib.ClientService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.